diff --git a/{{cookiecutter.app_name}}/Common/Sources/Common/Heap.swift b/{{cookiecutter.app_name}}/Common/Sources/Common/Heap.swift new file mode 100644 index 0000000..8c3b70e --- /dev/null +++ b/{{cookiecutter.app_name}}/Common/Sources/Common/Heap.swift @@ -0,0 +1,60 @@ +// +// Heap.swift +// Common +// +// Created by {{ cookiecutter.creator }} on {% now 'utc', '%d/%m/%Y' %}. +// Copyright © {% now 'utc', '%Y' %} {{cookiecutter.company_name}}. All rights reserved. +// + +private final class Reference: Equatable { + var value: T + init(_ value: T) { + self.value = value + } + static func == (lhs: Reference, rhs: Reference) -> Bool { + lhs.value == rhs.value + } +} + +@propertyWrapper public struct Heap: Equatable { + private var reference: Reference + + public init(_ value: T) { + reference = .init(value) + } + + public var wrappedValue: T { + get { reference.value } + set { + if !isKnownUniquelyReferenced(&reference) { + reference = .init(newValue) + return + } + reference.value = newValue + } + } + public var projectedValue: Heap { + self + } +} + +extension Heap: Hashable where T: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(wrappedValue) + } +} + +extension Heap: Decodable where T: Decodable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let value = try container.decode(T.self) + self = Heap(value) + } +} + +extension Heap: Encodable where T: Encodable { + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(wrappedValue) + } +}