Skip to content

Commit

Permalink
Make encoding work again
Browse files Browse the repository at this point in the history
  • Loading branch information
ptoffy committed Nov 6, 2024
1 parent d6c26c3 commit d9a056e
Show file tree
Hide file tree
Showing 13 changed files with 541 additions and 487 deletions.
54 changes: 27 additions & 27 deletions Sources/MultipartKit/FormDataEncoder/FormDataEncoder.Encoder.swift
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
// extension FormDataEncoder {
// struct Encoder {
// let codingPath: [any CodingKey]
// let storage = Storage()
// let userInfo: [CodingUserInfoKey: Any]
// }
// }
extension FormDataEncoder {
struct Encoder {
let codingPath: [any CodingKey]
let storage = Storage()
let userInfo: [CodingUserInfoKey: Any]
}
}

// extension FormDataEncoder.Encoder: Encoder {
// func container<Key: CodingKey>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> {
// let container = FormDataEncoder.KeyedContainer<Key>(encoder: self)
// storage.dataContainer = container.dataContainer
// return .init(container)
// }
extension FormDataEncoder.Encoder: Encoder {
func container<Key: CodingKey>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> {
let container = FormDataEncoder.KeyedContainer<Key>(encoder: self)
storage.dataContainer = container.dataContainer
return .init(container)
}

// func unkeyedContainer() -> any UnkeyedEncodingContainer {
// let container = FormDataEncoder.UnkeyedContainer(encoder: self)
// storage.dataContainer = container.dataContainer
// return container
// }
func unkeyedContainer() -> any UnkeyedEncodingContainer {
let container = FormDataEncoder.UnkeyedContainer(encoder: self)
storage.dataContainer = container.dataContainer
return container
}

// func singleValueContainer() -> any SingleValueEncodingContainer {
// self
// }
// }
func singleValueContainer() -> any SingleValueEncodingContainer {
self
}
}

// extension FormDataEncoder.Encoder {
// func nested(at key: any CodingKey) -> FormDataEncoder.Encoder {
// .init(codingPath: codingPath + [key], userInfo: userInfo)
// }
// }
extension FormDataEncoder.Encoder {
func nested(at key: any CodingKey) -> FormDataEncoder.Encoder {
.init(codingPath: codingPath + [key], userInfo: userInfo)
}
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
// extension FormDataEncoder {
// struct KeyedContainer<Key: CodingKey> {
// let dataContainer = KeyedDataContainer()
// let encoder: Encoder
// }
// }

// extension FormDataEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
// var codingPath: [any CodingKey] {
// encoder.codingPath
// }

// func encodeNil(forKey _: Key) throws {
// // skip
// }

// func encode<T: Encodable>(_ value: T, forKey key: Key) throws {
// try encoderForKey(key).encode(value)
// }

// func nestedContainer<NestedKey: CodingKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
// encoderForKey(key).container(keyedBy: keyType)
// }

// func nestedUnkeyedContainer(forKey key: Key) -> any UnkeyedEncodingContainer {
// encoderForKey(key).unkeyedContainer()
// }

// func superEncoder() -> any Encoder {
// encoderForKey(BasicCodingKey.super)
// }

// func superEncoder(forKey key: Key) -> any Encoder {
// encoderForKey(key)
// }

// func encoderForKey(_ key: any CodingKey) -> FormDataEncoder.Encoder {
// let encoder = self.encoder.nested(at: key)
// dataContainer.value[key.stringValue] = encoder.storage
// return encoder
// }
// }
extension FormDataEncoder {
struct KeyedContainer<Key: CodingKey> {
let dataContainer = KeyedDataContainer()
let encoder: Encoder
}
}

extension FormDataEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
var codingPath: [any CodingKey] {
encoder.codingPath
}

func encodeNil(forKey _: Key) throws {
// skip
}

func encode<T: Encodable>(_ value: T, forKey key: Key) throws {
try encoderForKey(key).encode(value)
}

func nestedContainer<NestedKey: CodingKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
encoderForKey(key).container(keyedBy: keyType)
}

func nestedUnkeyedContainer(forKey key: Key) -> any UnkeyedEncodingContainer {
encoderForKey(key).unkeyedContainer()
}

func superEncoder() -> any Encoder {
encoderForKey(BasicCodingKey.super)
}

func superEncoder(forKey key: Key) -> any Encoder {
encoderForKey(key)
}

func encoderForKey(_ key: any CodingKey) -> FormDataEncoder.Encoder {
let encoder = self.encoder.nested(at: key)
dataContainer.value[key.stringValue] = encoder.storage
return encoder
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// extension FormDataEncoder.Encoder: SingleValueEncodingContainer {
// func encodeNil() throws {
// // skip
// }
extension FormDataEncoder.Encoder: SingleValueEncodingContainer {
func encodeNil() throws {
// skip
}

// func encode<T: Encodable>(_ value: T) throws {
// if let convertible = value as? any MultipartPartConvertible,
// let part = convertible.multipart
// {
// storage.dataContainer = SingleValueDataContainer(part: part)
// } else {
// try value.encode(to: self)
// }
// }
// }
func encode<T: Encodable>(_ value: T) throws {
if let convertible = value as? any MultipartPartConvertible<[UInt8]>,
let part = convertible.multipart
{
storage.dataContainer = SingleValueDataContainer(part: part)
} else {
try value.encode(to: self)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
// extension FormDataEncoder {
// struct UnkeyedContainer {
// let dataContainer = UnkeyedDataContainer()
// let encoder: FormDataEncoder.Encoder
// }
// }

// extension FormDataEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
// var codingPath: [any CodingKey] {
// encoder.codingPath
// }

// var count: Int {
// dataContainer.value.count
// }

// func encodeNil() throws {
// // skip
// }

// func encode<T: Encodable>(_ value: T) throws {
// try nextEncoder().encode(value)
// }

// func nestedContainer<NestedKey: CodingKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
// nextEncoder().container(keyedBy: keyType)
// }

// func nestedUnkeyedContainer() -> any UnkeyedEncodingContainer {
// nextEncoder().unkeyedContainer()
// }

// func superEncoder() -> any Encoder {
// nextEncoder()
// }

// func nextEncoder() -> FormDataEncoder.Encoder {
// let encoder = self.encoder.nested(at: BasicCodingKey.index(count))
// dataContainer.value.append(encoder.storage)
// return encoder
// }
// }
extension FormDataEncoder {
struct UnkeyedContainer {
let dataContainer = UnkeyedDataContainer()
let encoder: FormDataEncoder.Encoder
}
}

extension FormDataEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
var codingPath: [any CodingKey] {
encoder.codingPath
}

var count: Int {
dataContainer.value.count
}

func encodeNil() throws {
// skip
}

func encode<T: Encodable>(_ value: T) throws {
try nextEncoder().encode(value)
}

func nestedContainer<NestedKey: CodingKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
nextEncoder().container(keyedBy: keyType)
}

func nestedUnkeyedContainer() -> any UnkeyedEncodingContainer {
nextEncoder().unkeyedContainer()
}

func superEncoder() -> any Encoder {
nextEncoder()
}

func nextEncoder() -> FormDataEncoder.Encoder {
let encoder = self.encoder.nested(at: BasicCodingKey.index(count))
dataContainer.value.append(encoder.storage)
return encoder
}
}
88 changes: 43 additions & 45 deletions Sources/MultipartKit/FormDataEncoder/FormDataEncoder.swift
Original file line number Diff line number Diff line change
@@ -1,50 +1,48 @@
// import NIOCore
/// Encodes `Encodable` items to `multipart/form-data` encoded `Data`.
///
/// See [RFC#2388](https://tools.ietf.org/html/rfc2388) for more information about `multipart/form-data` encoding.
///
/// Seealso `MultipartParser` for more information about the `multipart` encoding.
public struct FormDataEncoder: Sendable {

// /// Encodes `Encodable` items to `multipart/form-data` encoded `Data`.
// ///
// /// See [RFC#2388](https://tools.ietf.org/html/rfc2388) for more information about `multipart/form-data` encoding.
// ///
// /// Seealso `MultipartParser` for more information about the `multipart` encoding.
// public struct FormDataEncoder: Sendable {
/// Any contextual information set by the user for encoding.
public var userInfo: [CodingUserInfoKey: any Sendable] = [:]

// /// Any contextual information set by the user for encoding.
// public var userInfo: [CodingUserInfoKey: any Sendable] = [:]
/// Creates a new `FormDataEncoder`.
public init() {}

// /// Creates a new `FormDataEncoder`.
// public init() {}
/// Encodes an `Encodable` item to `String` using the supplied boundary.
///
/// let a = Foo(string: "a", int: 42, double: 3.14, array: [1, 2, 3])
/// let data = try FormDataEncoder().encode(a, boundary: "123")
///
/// - parameters:
/// - encodable: Generic `Encodable` item.
/// - boundary: Multipart boundary to use for encoding. This must not appear anywhere in the encoded data.
/// - throws: Any errors encoding the model with `Codable` or serializing the data.
/// - returns: `multipart/form-data`-encoded `String`.
public func encode<E: Encodable>(_ encodable: E, boundary: String) throws -> String {
try MultipartSerializer(boundary: boundary).serialize(parts: parts(from: encodable))
}

// /// Encodes an `Encodable` item to `String` using the supplied boundary.
// ///
// /// let a = Foo(string: "a", int: 42, double: 3.14, array: [1, 2, 3])
// /// let data = try FormDataEncoder().encode(a, boundary: "123")
// ///
// /// - parameters:
// /// - encodable: Generic `Encodable` item.
// /// - boundary: Multipart boundary to use for encoding. This must not appear anywhere in the encoded data.
// /// - throws: Any errors encoding the model with `Codable` or serializing the data.
// /// - returns: `multipart/form-data`-encoded `String`.
// public func encode<E: Encodable>(_ encodable: E, boundary: String) throws -> String {
// try MultipartSerializer().serialize(parts: parts(from: encodable), boundary: boundary)
// }
/// Encodes an `Encodable` item into a `ByteBuffer` using the supplied boundary.
///
/// let a = Foo(string: "a", int: 42, double: 3.14, array: [1, 2, 3])
/// var buffer = ByteBuffer()
/// let data = try FormDataEncoder().encode(a, boundary: "123", into: &buffer)
///
/// - parameters:
/// - encodable: Generic `Encodable` item.
/// - boundary: Multipart boundary to use for encoding. This must not appear anywhere in the encoded data.
/// - buffer: Buffer to write to.
/// - throws: Any errors encoding the model with `Codable` or serializing the data.
public func encode<E: Encodable>(_ encodable: E, boundary: String, into buffer: inout [UInt8]) throws {
try MultipartSerializer(boundary: boundary).serialize(parts: parts(from: encodable), into: &buffer)
}

// /// Encodes an `Encodable` item into a `ByteBuffer` using the supplied boundary.
// ///
// /// let a = Foo(string: "a", int: 42, double: 3.14, array: [1, 2, 3])
// /// var buffer = ByteBuffer()
// /// let data = try FormDataEncoder().encode(a, boundary: "123", into: &buffer)
// ///
// /// - parameters:
// /// - encodable: Generic `Encodable` item.
// /// - boundary: Multipart boundary to use for encoding. This must not appear anywhere in the encoded data.
// /// - buffer: Buffer to write to.
// /// - throws: Any errors encoding the model with `Codable` or serializing the data.
// public func encode<E: Encodable>(_ encodable: E, boundary: String, into buffer: inout ByteBuffer) throws {
// try MultipartSerializer().serialize(parts: parts(from: encodable), boundary: boundary, into: &buffer)
// }

// private func parts<E: Encodable>(from encodable: E) throws -> [MultipartPart] {
// let encoder = Encoder(codingPath: [], userInfo: userInfo)
// try encodable.encode(to: encoder)
// return encoder.storage.data?.namedParts() ?? []
// }
// }
private func parts<E: Encodable>(from encodable: E) throws -> [MultipartPart<[UInt8]>] {
let encoder = Encoder(codingPath: [], userInfo: userInfo)
try encodable.encode(to: encoder)
return encoder.storage.data?.namedParts() ?? []
}
}
Loading

0 comments on commit d9a056e

Please sign in to comment.