Skip to content

Commit

Permalink
Doc Comments
Browse files Browse the repository at this point in the history
  • Loading branch information
swhitty committed Jul 24, 2023
1 parent c871e3a commit 08a6ad5
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
19 changes: 17 additions & 2 deletions Sources/KeyValueDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,36 @@
import Foundation
import CoreFoundation

/// Top level encoder that converts `[String: Any]`, `[Any]` or `Any` into `Codable` types.
public final class KeyValueDecoder {

/// Contextual user-provided information for use during encoding.
public var userInfo: [CodingUserInfoKey: Any]

/// The strategy to use for decoding `nil`. Defaults to `Optional<Any>.none` which can be decoded to any optional type.
public var nilDecodingStrategy: NilDecodingStrategy = .default

/// Initializes `self` with default strategies.
public init () {
self.userInfo = [:]
}

public func decode<T: Decodable>(_ type: T.Type, from value: Any) throws -> T {
///
/// Decodes any loosely typed key value into a `Decodable` type.
/// - Parameters:
/// - type: The `Decodable` type to decode.
/// - value: The value to decode. May be `[Any]`, `[String: Any]` or any supported primitive `Bool`,
/// `String`, `Int`, `UInt`, `URL`, `Data` or `Decimal`.
/// - Returns: The decoded instance of `type`.
///
/// - Throws: `DecodingError` if a value cannot be decoded. The context will contain a keyPath of the failed property.
public func decode<T: Decodable>(_ type: T.Type = T.self, from value: Any) throws -> T {
let container = SingleContainer(value: value, codingPath: [], userInfo: userInfo, nilDecodingStrategy: nilDecodingStrategy)
return try container.decode(type)
}

public typealias NilDecodingStrategy = KeyValueEncoder.NilEncodingStrategy
/// Strategy used to decode nil values.
public typealias NilDecodingStrategy = NilCodingStrategy
}

extension KeyValueDecoder {
Expand Down
41 changes: 31 additions & 10 deletions Sources/KeyValueEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,48 @@

import Foundation

/// Top level encoder that converts `Codable` instances into loosely typed `[String: Any]`, `[Any]` or `Any`.
public final class KeyValueEncoder {

/// Contextual user-provided information for use during encoding.
public var userInfo: [CodingUserInfoKey: Any]

/// The strategy to use for encoding `nil`. Defaults to `Optional<Any>.none` which can be cast to any optional type.
public var nilEncodingStrategy: NilEncodingStrategy = .default

/// Initializes `self` with default strategies.
public init () {
self.userInfo = [:]
}

/// Encodes a value into a loosely typed key value type. May be a container `[Any]`, `[String: Any]`
/// or any supported plist primitive `Bool`, `String`, `Int`, `UInt`, `URL`, `Data` or `Decimal`.
/// - Parameter value: The `Encodable` value to encode.
/// - Returns: The encoded value.
public func encode<T>(_ value: T) throws -> Any? where T: Encodable {
try encodeValue(value).getValue(strategy: nilEncodingStrategy)
}

func encodeValue<T>(_ value: T) throws -> EncodedValue where T: Encodable {
try Encoder(userInfo: userInfo, nilEncodingStrategy: nilEncodingStrategy).encodeToValue(value)
}
/// Strategy used to encode nil values.
public typealias NilEncodingStrategy = NilCodingStrategy
}

public enum NilEncodingStrategy {
case removed
case placeholder(Any, isNull: (Any) -> Bool)
/// Strategy used to encode and decode nil values.
public enum NilCodingStrategy {
/// `nil` values are removed
case removed

public static let `default` = NilEncodingStrategy.placeholder(Optional<Any>.none as Any, isNull: isOptionalNone)
public static let stringNull = NilEncodingStrategy.placeholder("$null", isNull: { ($0 as? String == "$null") })
public static let nsNull = NilEncodingStrategy.placeholder(NSNull(), isNull: { $0 is NSNull })
}
/// `nil` values are substituted with a placeholder value
case placeholder(Any, isNull: (Any) -> Bool)

/// `nil` values are substituted with `Optional<Any>.none`. Can be cast to any optional type.
public static let `default` = NilCodingStrategy.placeholder(Optional<Any>.none as Any, isNull: isOptionalNone)

/// `nil` values are substituted with `"$null"` placeholder string. Compatible with `PropertyListEncoder`.
public static let stringNull = NilCodingStrategy.placeholder("$null", isNull: { ($0 as? String == "$null") })

/// `nil` values are substituted with `"NSNull()"`. Compatible with `JSONSerialization`.
public static let nsNull = NilCodingStrategy.placeholder(NSNull(), isNull: { $0 is NSNull })
}

extension KeyValueEncoder {
Expand All @@ -82,6 +99,10 @@ extension KeyValueEncoder {
}
}
}

func encodeValue<T: Encodable>(_ value: T) throws -> EncodedValue{
try Encoder(userInfo: userInfo, nilEncodingStrategy: nilEncodingStrategy).encodeToValue(value)
}
}

extension KeyValueEncoder.NilEncodingStrategy {
Expand Down

0 comments on commit 08a6ad5

Please sign in to comment.