Skip to content

Instantly share code, notes, and snippets.

@onevcat
Created February 7, 2022 00:21
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 onevcat/6082ff5ab8c58536aef16d5d8baeb9cc to your computer and use it in GitHub Desktop.
Save onevcat/6082ff5ab8c58536aef16d5d8baeb9cc to your computer and use it in GitHub Desktop.
CoW wrapper
// https://github.com/pointfreeco/swift-composable-architecture/discussions/488#discussioncomment-591715
@propertyWrapper
public struct CoW<T> {
private final class Ref {
var val: T
init(_ v: T) { val = v }
}
private var ref: Ref
public init(wrappedValue: T) { ref = Ref(wrappedValue) }
public var wrappedValue: T {
get { ref.val }
set {
if !isKnownUniquelyReferenced(&ref) {
ref = Ref(newValue)
return
}
ref.val = newValue
}
}
}
//Restore automatic protocol conformance:
extension CoW: Equatable where T: Equatable {
public static func == (lhs: CoW<T>, rhs: CoW<T>) -> Bool {
lhs.wrappedValue == rhs.wrappedValue
}
}
extension CoW: Hashable where T: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(wrappedValue)
}
}
extension CoW: Decodable where T: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let value = try container.decode(T.self)
self = CoW(wrappedValue: value)
}
}
extension CoW: Encodable where T: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(wrappedValue)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment