Skip to content

Instantly share code, notes, and snippets.

@ktoso
Forked from airspeedswift/cowed.swift
Created October 17, 2019 23:12
Show Gist options
  • Save ktoso/b2c3370059e2a40c000e921508a21570 to your computer and use it in GitHub Desktop.
Save ktoso/b2c3370059e2a40c000e921508a21570 to your computer and use it in GitHub Desktop.
COWed
/// Conform references types for use in the COW wrapper to this protocol
protocol Cowable: class {
/// Make a new unique instance of `copied`
static func makeUnique(_ copied: Self) -> Self
}
/// A wrapper that turns a Cowable reference type into a value-semantic
/// type with access to all of its properties
@dynamicMemberLookup
struct COW<Cowed: Cowable> {
private var _cowed: Cowed
init(_ cowing: Cowed) {
_cowed = cowing
}
public subscript<T>(dynamicMember keyPath: KeyPath<Cowed,T>) -> T {
get { _cowed[keyPath: keyPath] }
}
public subscript<T>(dynamicMember keyPath: WritableKeyPath<Cowed,T>) -> T {
get { _cowed[keyPath: keyPath] }
set {
if !isKnownUniquelyReferenced(&_cowed) { _cowed = .makeUnique(_cowed) }
_cowed[keyPath: keyPath] = newValue
}
}
}
extension COW: CustomStringConvertible where Cowed: CustomStringConvertible {
var description: String { _cowed.description }
}
extension Texture: CustomStringConvertible {
var description: String { "Texture(isSparkly: \(isSparkly)" }
}
final class Texture {
init(isSparkly: Bool) { self.isSparkly = isSparkly }
var isSparkly: Bool
}
extension Texture: Cowable {
static func makeUnique(_ copied: Texture) -> Texture {
Texture(isSparkly: copied.isSparkly)
}
}
struct Material {
public var roughness: Float
public var texture: COW<Texture> = COW(Texture(isSparkly: false))
}
var m1 = Material(roughness: 0.5)
var m2 = m1
m1.texture.isSparkly = true
print(m1)
print(m2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment