mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-15 21:10:59 +00:00
97 lines
2.8 KiB
Swift
97 lines
2.8 KiB
Swift
// Copyright © 2020 Metabolist. All rights reserved.
|
|
|
|
import Foundation
|
|
|
|
// Thank you https://www.swiftbysundell.com/tips/default-decoding-values/
|
|
|
|
protocol DecodableDefaultSource {
|
|
associatedtype Value: Decodable
|
|
static var defaultValue: Value { get }
|
|
}
|
|
|
|
enum DecodableDefault {}
|
|
|
|
// swiftlint:disable nesting
|
|
extension DecodableDefault {
|
|
@propertyWrapper
|
|
struct Wrapper<Source: DecodableDefaultSource> {
|
|
typealias Value = Source.Value
|
|
var wrappedValue = Source.defaultValue
|
|
}
|
|
}
|
|
|
|
extension DecodableDefault {
|
|
typealias Source = DecodableDefaultSource
|
|
typealias List = Decodable & ExpressibleByArrayLiteral
|
|
typealias Map = Decodable & 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 StatusVisibilityPublic: Source {
|
|
static var defaultValue: Status.Visibility { .public }
|
|
}
|
|
|
|
enum ExpandMediaDefault: Source {
|
|
static var defaultValue: MastodonPreferences.ExpandMedia { .default }
|
|
}
|
|
}
|
|
}
|
|
// swiftlint:enable nesting
|
|
|
|
extension DecodableDefault {
|
|
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 StatusVisibilityPublic = Wrapper<Sources.StatusVisibilityPublic>
|
|
typealias ExpandMediaDefault = Wrapper<Sources.ExpandMediaDefault>
|
|
}
|
|
|
|
extension DecodableDefault.Wrapper: Decodable {
|
|
init(from decoder: Decoder) throws {
|
|
let container = try decoder.singleValueContainer()
|
|
wrappedValue = try container.decode(Value.self)
|
|
}
|
|
}
|
|
|
|
extension DecodableDefault.Wrapper: Equatable where Value: Equatable {}
|
|
extension DecodableDefault.Wrapper: Hashable where Value: Hashable {}
|
|
|
|
extension DecodableDefault.Wrapper: Encodable where Value: Encodable {
|
|
func encode(to encoder: Encoder) throws {
|
|
var container = encoder.singleValueContainer()
|
|
try container.encode(wrappedValue)
|
|
}
|
|
}
|
|
|
|
extension KeyedDecodingContainer {
|
|
func decode<T>(_ type: DecodableDefault.Wrapper<T>.Type,
|
|
forKey key: Key) throws -> DecodableDefault.Wrapper<T> {
|
|
try decodeIfPresent(type, forKey: key) ?? .init()
|
|
}
|
|
}
|