Skip to content

Commit

Permalink
Move EC2 array coder from Soto (#536)
Browse files Browse the repository at this point in the history
* Move EC2ArrayCoder from Soto

* Comments
  • Loading branch information
adam-fowler authored Jan 10, 2023
1 parent 02d3054 commit cf1c872
Showing 1 changed file with 69 additions and 0 deletions.
69 changes: 69 additions & 0 deletions Sources/SotoCore/Encoder/CodableProperties/EC2ArrayCoder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2023 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

/// Coder for encoding/decoding Arrays for EC2 service. This is extended to support encoding and
/// decoding based on whether `Element` is `Encodable` or `Decodable`.
///
/// EC2 requires a special case array encoder as it flattens arrays on encode, while still expecting
/// them to have array elements on decode.
public struct EC2ArrayCoder<Properties: ArrayCoderProperties, Element: _SotoSendable>: CustomCoder {
public typealias CodableValue = [Element]
}

/// Standard EC2 Array Coder with element name "member"
public typealias EC2StandardArrayCoder<Element> = EC2ArrayCoder<StandardArrayCoderProperties, Element>

/// CodingKey used by Encoder property wrappers
private struct _EncodingWrapperKey: CodingKey {
public var stringValue: String
public var intValue: Int?

public init?(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}

public init?(intValue: Int) {
self.stringValue = "\(intValue)"
self.intValue = intValue
}

public init(stringValue: String, intValue: Int?) {
self.stringValue = stringValue
self.intValue = intValue
}
}

/// extend to support decoding
extension EC2ArrayCoder: CustomDecoder where Element: Decodable {
public static func decode(from decoder: Decoder) throws -> CodableValue {
let topLevelContainer = try decoder.container(keyedBy: _EncodingWrapperKey.self)
var values: [Element] = []
let memberKey = _EncodingWrapperKey(stringValue: Properties.member, intValue: nil)
guard topLevelContainer.contains(memberKey) else { return values }

var container = try topLevelContainer.nestedUnkeyedContainer(forKey: memberKey)
while !container.isAtEnd {
values.append(try container.decode(Element.self))
}
return values
}
}

/// extend to support encoding (flatten the array)
extension EC2ArrayCoder: CustomEncoder where Element: Encodable {
public static func encode(value: CodableValue, to encoder: Encoder) throws {
try value.encode(to: encoder)
}
}

0 comments on commit cf1c872

Please sign in to comment.