Large structs and stack overflow

We have now added a CoW struct that we can use to wrap heavy structs and give them copy on write behaviour.

@dynamicMemberLookup
struct CoW<T> {
    init(_ value: T) {
        _storage = Storage(value)
    }
    public subscript<V>(dynamicMember keyPath: WritableKeyPath<T, V>) -> V {
        get { value[keyPath: keyPath] }
        set { value[keyPath: keyPath] = newValue }
    }
    var value: T {
        get {
            return _storage.value
        }
        set {
            if isKnownUniquelyReferenced(&_storage) {
                _storage.value = value
            } else {
                _storage = Storage(newValue)
            }
        }
    }
    
    private var _storage: Storage<T>
    private class Storage<T> {
        var value: T
        init(_ value: T) {
            self.value = value
        }
    }
}
extension CoW: Equatable where T: Equatable {
    static func == (lhs: CoW<T>, rhs: CoW<T>) -> Bool {
        return lhs.value == rhs.value
    }
}

Not sure if the @dynamicMemberLookup should be used or not, but I think it will let us skip the value-part when accessing properties on the storage.

Now we can easily wrap state objects when needed:

var articleListState:CoW<ArticleListState> = CoW(ArticleListState.initialState())
2 Likes