Skip to content

Instantly share code, notes, and snippets.

@atierian
Last active April 11, 2021 16:20
Show Gist options
  • Select an option

  • Save atierian/1cb38e56c68edabe07c9f019a4e06eb9 to your computer and use it in GitHub Desktop.

Select an option

Save atierian/1cb38e56c68edabe07c9f019a4e06eb9 to your computer and use it in GitHub Desktop.
Struct with copy on write semantics
struct Person {
fileprivate final class Storage {
var name: String
var age: UInt8
init(name: String, age: UInt8) {
self.name = name
self.age = age
}
}
private var storage: Storage
init(name: String, age: UInt8) {
storage = .init(name: name, age: age)
}
}
extension Person.Storage {
func copy() -> Person.Storage {
.init(name: name, age: age)
}
}
extension Person {
private var storageForWriting: Person.Storage {
mutating get {
if !isKnownUniquelyReferenced(&storage) {
storage = storage.copy()
}
return storage
}
}
var name: String {
get { storage.name }
set { storageForWriting.name = newValue }
}
var age: UInt8 {
get { storage.age }
set { storageForWriting.age = newValue }
}
}
// Protocol
protocol Storageable: AnyObject {
func copy() -> Self
}
protocol CopyOnWriteable {
associatedtype Storage: Storageable
var storage: Storage { get set }
var storageForWriting: Storage { mutating get }
}
extension CopyOnWriteable {
var storageForWriting: Storage {
mutating get {
if !isKnownUniquelyReferenced(&storage) {
storage = storage.copy()
}
return storage
}
}
}
struct Car: CopyOnWriteable {
typealias Storage = CarStorage
final class CarStorage: Storageable {
var year: UInt
var color: String
func copy() -> Self {
.init(year: year, color: color)
}
init(year: UInt, color: String) {
self.year = year
self.color = color
}
}
var storage: CarStorage
init(year: UInt, color: String) {
storage = .init(year: year, color: color)
}
var year: UInt {
get { storage.year }
set { storageForWriting.year = newValue }
}
var color: String {
get { storage.color }
set { storageForWriting.color = newValue }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment