metatext-app-ios-iphone-ipad/Mastodon/Sources/Mastodon/Property Wrappers/DecodableDefault.swift

100 lines
3.0 KiB
Swift
Raw Normal View History

2020-08-24 01:39:52 +02:00
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
// Thank you https://www.swiftbysundell.com/tips/default-decoding-values/
2020-08-31 01:33:11 +02:00
public protocol DecodableDefaultSource {
2020-08-24 01:39:52 +02:00
associatedtype Value: Decodable
static var defaultValue: Value { get }
}
2020-08-31 01:33:11 +02:00
public enum DecodableDefault {}
2020-08-24 01:39:52 +02:00
// swiftlint:disable nesting
extension DecodableDefault {
@propertyWrapper
2020-08-31 01:33:11 +02:00
public struct Wrapper<Source: DecodableDefaultSource> {
public typealias Value = Source.Value
public var wrappedValue = Source.defaultValue
public init() {}
2020-08-24 01:39:52 +02:00
}
}
2020-08-31 01:33:11 +02:00
public extension DecodableDefault {
2020-08-24 01:39:52 +02:00
typealias Source = DecodableDefaultSource
typealias List = Decodable & ExpressibleByArrayLiteral
typealias Map = Decodable & ExpressibleByDictionaryLiteral
enum Sources {
2020-08-31 01:33:11 +02:00
public enum True: Source {
public static var defaultValue: Bool { true }
2020-08-24 01:39:52 +02:00
}
2020-08-31 01:33:11 +02:00
public enum False: Source {
public static var defaultValue: Bool { false }
2020-08-24 01:39:52 +02:00
}
2020-08-31 01:33:11 +02:00
public enum EmptyString: Source {
public static var defaultValue: String { "" }
2020-08-24 01:39:52 +02:00
}
2020-08-31 01:33:11 +02:00
public enum EmptyList<T: List>: Source {
public static var defaultValue: T { [] }
2020-08-24 01:39:52 +02:00
}
2020-08-31 01:33:11 +02:00
public enum EmptyMap<T: Map>: Source {
public static var defaultValue: T { [:] }
2020-08-24 01:39:52 +02:00
}
2020-08-31 01:33:11 +02:00
public enum Zero: Source {
public static var defaultValue: Int { 0 }
2020-08-24 01:39:52 +02:00
}
2020-08-31 01:33:11 +02:00
public enum StatusVisibilityPublic: Source {
public static var defaultValue: Status.Visibility { .public }
2020-08-24 01:39:52 +02:00
}
2020-08-31 01:33:11 +02:00
public enum ExpandMediaDefault: Source {
public static var defaultValue: MastodonPreferences.ExpandMedia { .default }
2020-08-24 01:39:52 +02:00
}
}
}
// swiftlint:enable nesting
2020-08-31 01:33:11 +02:00
public extension DecodableDefault {
2020-08-24 01:39:52 +02:00
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 {
2020-08-31 01:33:11 +02:00
public init(from decoder: Decoder) throws {
2020-08-24 01:39:52 +02:00
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 {
2020-08-31 01:33:11 +02:00
public func encode(to encoder: Encoder) throws {
2020-08-24 01:39:52 +02:00
var container = encoder.singleValueContainer()
try container.encode(wrappedValue)
}
}
2020-08-31 01:33:11 +02:00
public extension KeyedDecodingContainer {
2020-08-24 01:39:52 +02:00
func decode<T>(_ type: DecodableDefault.Wrapper<T>.Type,
forKey key: Key) throws -> DecodableDefault.Wrapper<T> {
try decodeIfPresent(type, forKey: key) ?? .init()
}
}