Skip to content

Instantly share code, notes, and snippets.

@IanKeen
Last active July 4, 2024 14:55
Show Gist options
  • Save IanKeen/e5db10e66d617e5fe89135a9f125cc39 to your computer and use it in GitHub Desktop.
Save IanKeen/e5db10e66d617e5fe89135a9f125cc39 to your computer and use it in GitHub Desktop.
PropertyWrapper: Decode default values. when they are `null`
import Foundation
public protocol DefaultValue {
associatedtype Value: Codable
static var value: Value { get }
}
@propertyWrapper
public struct Default<Default: DefaultValue>: Codable {
public var wrappedValue: Default.Value
public init(wrappedValue: Default.Value) {
self.wrappedValue = wrappedValue
}
public init(value: Default.Value?) {
self.wrappedValue = value ?? Default.value
}
public func encode(to encoder: Encoder) throws {
try wrappedValue.encode(to: encoder)
}
}
extension Default: Equatable where Default.Value: Equatable {
public static func ==(lhs: Self, rhs: Self) -> Bool {
return lhs.wrappedValue == rhs.wrappedValue
}
}
extension KeyedDecodingContainer {
public func decode<T: DefaultValue>(_ type: Default<T>.Type, forKey key: KeyedDecodingContainer.Key) throws -> Default<T> {
return Default<T>(value: try decodeIfPresent(T.Value.self, forKey: key))
}
}
public struct True: DefaultValue {
public static let value = true
}
public struct False: DefaultValue {
public static let value = false
}
public struct Empty<T: Emptyable & Codable>: DefaultValue {
public static var value: T { .init() }
}
public protocol Emptyable {
init()
var isEmpty: Bool { get }
}
extension String: Emptyable { }
extension Array: Emptyable { }
@IanKeen
Copy link
Author

IanKeen commented Apr 23, 2020

Usage:

struct User: Codable {
   var name: String
   @Default<False> var isAdmin: Bool
   @Default<Empty> var pets: [Pet]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment