Skip to content

Instantly share code, notes, and snippets.

@liuzhida33
Created September 8, 2022 08:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liuzhida33/bc59a8c5d1e4918e8bcfc6575d26377d to your computer and use it in GitHub Desktop.
Save liuzhida33/bc59a8c5d1e4918e8bcfc6575d26377d to your computer and use it in GitHub Desktop.
Codable 添加默认值
protocol CodableDefaultSource {
associatedtype Value: Codable
static var defaultValue: Value { get }
}
enum CodableDefault {}
extension CodableDefault {
@propertyWrapper
struct Wrapper<Source: CodableDefaultSource> {
typealias Value = Source.Value
var wrappedValue = Source.defaultValue
}
}
extension CodableDefault.Wrapper: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
wrappedValue = try container.decode(Value.self)
}
}
extension CodableDefault.Wrapper: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(wrappedValue)
}
}
extension KeyedDecodingContainer {
func decode<T>(_ type: CodableDefault.Wrapper<T>.Type,
forKey key: Key) throws -> CodableDefault.Wrapper<T> {
try decodeIfPresent(type, forKey: key) ?? .init()
}
}
extension KeyedEncodingContainer {
mutating func encode<T>(_ value: CodableDefault.Wrapper<T>, forKey key: Key) throws {
try encode(value.wrappedValue, forKey: key)
}
}
extension CodableDefault {
typealias Source = CodableDefaultSource
typealias List = Codable & ExpressibleByArrayLiteral
typealias Map = Codable & ExpressibleByDictionaryLiteral
enum Sources {
enum True: Source {
static var defaultValue: Bool { true }
}
enum False: Source {
static var defaultValue: Bool { false }
}
enum EmptyString: Source {
static var defaultValue: String { "" }
}
enum EmptyList<T: List>: Source {
static var defaultValue: T { [] }
}
enum EmptyMap<T: Map>: Source {
static var defaultValue: T { [:] }
}
enum Zero: Source {
static var defaultValue: Int { 0 }
}
enum One: Source {
static var defaultValue: Int { 1 }
}
}
}
extension CodableDefault {
typealias True = Wrapper<Sources.True>
typealias False = Wrapper<Sources.False>
typealias EmptyString = Wrapper<Sources.EmptyString>
typealias EmptyList<T: List> = Wrapper<Sources.EmptyList<T>>
typealias EmptyMap<T: Map> = Wrapper<Sources.EmptyMap<T>>
typealias Zero = Wrapper<Sources.Zero>
typealias One = Wrapper<Sources.One>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment