22// CodableProxy.swift
33// OpenSwiftUICore
44//
5- // Audited for 6.0.87
6- // Status: WIP
5+ // Audited for 6.5.4
6+ // Status: Complete
7+ // ID: A66FCB65C49D586C0CA23AF611BF2C2B (SwiftUICore?)
8+
9+ package import Foundation
10+
11+ // MARK: - CodableByProxy
712
813package protocol CodableByProxy {
914 associatedtype CodingProxy : Codable
15+
1016 var codingProxy : CodingProxy { get }
1117
1218 static func unwrap( codingProxy: CodingProxy ) -> Self
1319}
1420
21+ // MARK: - CodableProxy
22+
1523package protocol CodableProxy : Codable {
1624 associatedtype Base
25+
1726 var base : Base { get }
1827}
1928
@@ -22,3 +31,276 @@ extension CodableByProxy where Self == CodingProxy.Base, CodingProxy: CodablePro
2231 codingProxy. base
2332 }
2433}
34+
35+ // MARK: - ProxyCodable
36+
37+ @propertyWrapper
38+ package struct ProxyCodable < Value> : Codable where Value: CodableByProxy {
39+ package var wrappedValue : Value
40+
41+ package var projectedValue : ProxyCodable < Value > { self }
42+
43+ package init ( _ value: Value ) {
44+ self . wrappedValue = value
45+ }
46+
47+ package init ( wrappedValue: Value ) {
48+ self . wrappedValue = wrappedValue
49+ }
50+
51+ package func encode( to encoder: any Encoder ) throws {
52+ var container = encoder. singleValueContainer ( )
53+ try container. encode ( wrappedValue. codingProxy)
54+ }
55+
56+ package init ( from decoder: any Decoder ) throws {
57+ var container = try decoder. singleValueContainer ( )
58+ let proxy = try container. decode ( Value . CodingProxy. self)
59+ wrappedValue = Value . unwrap ( codingProxy: proxy)
60+ }
61+ }
62+
63+ extension ProxyCodable : Equatable where Value: Equatable {
64+ package static func == ( lhs: ProxyCodable < Value > , rhs: ProxyCodable < Value > ) -> Bool {
65+ lhs. wrappedValue == rhs. wrappedValue
66+ }
67+ }
68+
69+ extension ProxyCodable : Hashable where Value: Hashable {
70+ package func hash( into hasher: inout Hasher ) {
71+ hasher. combine ( wrappedValue)
72+ }
73+ }
74+
75+ // MARK: - Optional + CodableByProxy
76+
77+ extension Optional : CodableByProxy where Wrapped: CodableByProxy {
78+ package var codingProxy : CodableOptional < Wrapped > {
79+ CodableOptional ( self )
80+ }
81+ }
82+
83+ // MARK: - RawRepresentable + CodableByProxy
84+
85+ extension RawRepresentable where RawValue: Codable {
86+ package var codingProxy : RawRepresentableProxy < Self > {
87+ RawRepresentableProxy ( self )
88+ }
89+ }
90+
91+ // MARK: - Error
92+
93+ private enum Error : Swift . Error {
94+ case unarchivingError
95+ }
96+
97+ // MARK: - RawRepresentableProxy
98+
99+ package struct RawRepresentableProxy < Value> : CodableProxy where Value: RawRepresentable , Value. RawValue: Codable {
100+ package var base : Value
101+
102+ package init ( _ base: Value ) {
103+ self . base = base
104+ }
105+
106+ package init ( from decoder: any Decoder ) throws {
107+ let container = try decoder. singleValueContainer ( )
108+ let rawValue = try container. decode ( Value . RawValue. self)
109+ guard let value = Value ( rawValue: rawValue) else {
110+ throw Error . unarchivingError
111+ }
112+ base = value
113+ }
114+
115+ package func encode( to encoder: any Encoder ) throws {
116+ var container = encoder. singleValueContainer ( )
117+ try container. encode ( base. rawValue)
118+ }
119+ }
120+
121+ // MARK: - NSAttributedString.Key + CodableByProxy
122+
123+ extension NSAttributedString . Key : CodableByProxy {
124+ package typealias CodingProxy = RawRepresentableProxy < NSAttributedString . Key >
125+ }
126+
127+ // MARK: - Array + CodableByProxy
128+
129+ extension Array : CodableByProxy where Element: CodableByProxy {
130+ package var codingProxy : [ Element . CodingProxy ] {
131+ map ( \. codingProxy)
132+ }
133+
134+ package static func unwrap( codingProxy: [ Element . CodingProxy ] ) -> [ Element ] {
135+ codingProxy. map { Element . unwrap ( codingProxy: $0) }
136+ }
137+ }
138+
139+ // MARK: - JSONCodable
140+
141+ package struct JSONCodable < Value> : Codable {
142+ package var base : Value
143+
144+ package init ( _ base: Value ) {
145+ self . base = base
146+ }
147+
148+ package func encode( to encoder: any Encoder ) throws {
149+ let data = try JSONSerialization . data ( withJSONObject: base)
150+ let string = String ( data: data, encoding: . utf8) !
151+ var container = encoder. singleValueContainer ( )
152+ try container. encode ( string)
153+ }
154+
155+ private enum Error : Swift . Error {
156+ case invalidType( objectDescription: String , dataDescription: String )
157+ }
158+
159+ package init ( from decoder: any Decoder ) throws {
160+ let container = try decoder. singleValueContainer ( )
161+ let string = try container. decode ( String . self)
162+ let data = string. data ( using: . utf8) !
163+ let object = try JSONSerialization . jsonObject ( with: data)
164+ guard let base = object as? Value else {
165+ throw Error . invalidType (
166+ objectDescription: String ( describing: type ( of: object) ) ,
167+ dataDescription: string
168+ )
169+ }
170+ self . base = base
171+ }
172+ }
173+
174+ // MARK: - CodableRawRepresentable
175+
176+ @propertyWrapper
177+ package struct CodableRawRepresentable < Value> : Codable where Value: RawRepresentable , Value. RawValue: Codable {
178+ package var wrappedValue : Value
179+
180+ package init ( _ value: Value ) {
181+ self . wrappedValue = value
182+ }
183+
184+ package init ( wrappedValue: Value ) {
185+ self . wrappedValue = wrappedValue
186+ }
187+
188+ package init ( from decoder: any Decoder ) throws {
189+ let container = try decoder. singleValueContainer ( )
190+ let rawValue = try container. decode ( Value . RawValue. self)
191+ guard let value = Value ( rawValue: rawValue) else {
192+ throw Error . unarchivingError
193+ }
194+ wrappedValue = value
195+ }
196+
197+ package func encode( to encoder: any Encoder ) throws {
198+ var container = encoder. singleValueContainer ( )
199+ try container. encode ( wrappedValue. rawValue)
200+ }
201+ }
202+
203+ extension CodableRawRepresentable : Equatable where Value: Equatable {
204+ package static func == ( lhs: CodableRawRepresentable < Value > , rhs: CodableRawRepresentable < Value > ) -> Bool {
205+ lhs. wrappedValue == rhs. wrappedValue
206+ }
207+ }
208+
209+ extension CodableRawRepresentable : Hashable where Value: Hashable {
210+ package func hash( into hasher: inout Hasher ) {
211+ hasher. combine ( wrappedValue)
212+ }
213+ }
214+
215+ // MARK: - CodableOptional
216+
217+ package struct CodableOptional < Wrapped> : CodableProxy where Wrapped: CodableByProxy {
218+ package var base : Wrapped ?
219+
220+ package init ( _ base: Wrapped ? ) {
221+ self . base = base
222+ }
223+
224+ private enum CodingKeys : CodingKey {
225+ case value
226+ }
227+
228+ package func encode( to encoder: any Encoder ) throws {
229+ var container = encoder. container ( keyedBy: CodingKeys . self)
230+ if let base {
231+ try container. encode ( base. codingProxy, forKey: . value)
232+ }
233+ }
234+
235+ package init ( from decoder: any Decoder ) throws {
236+ let container = try decoder. container ( keyedBy: CodingKeys . self)
237+ let proxy = try container. decodeIfPresent ( Wrapped . CodingProxy. self, forKey: . value)
238+ base = proxy. map { Wrapped . unwrap ( codingProxy: $0) }
239+ }
240+ }
241+
242+ // MARK: - CodableNSAttributes
243+
244+ @propertyWrapper
245+ package struct CodableNSAttributes : CodableByProtobuf , Hashable {
246+
247+ package typealias Value = [ NSAttributedString . Key : Any ]
248+
249+ package var wrappedValue : Value
250+
251+ package var projectedValue : CodableNSAttributes { self }
252+
253+ package init ( _ value: Value ) {
254+ self . wrappedValue = value
255+ }
256+
257+ package init ( wrappedValue: Value ) {
258+ self . wrappedValue = wrappedValue
259+ }
260+
261+ package func encode( to encoder: inout ProtobufEncoder ) throws {
262+ let string = NSAttributedString ( string: " " , attributes: wrappedValue)
263+ try CodableAttributedString ( string) . encode ( to: & encoder)
264+ }
265+
266+ package init ( from decoder: inout ProtobufDecoder ) throws {
267+ let string = try CodableAttributedString ( from: & decoder) . base
268+ guard string. length >= 0 else {
269+ throw DecodingError . dataCorrupted ( . init( codingPath: [ ] , debugDescription: " CodableNSAttribute found empty string " ) )
270+ }
271+ wrappedValue = string. attributes ( at: 0 , effectiveRange: nil )
272+ }
273+
274+ package static func == ( lhs: CodableNSAttributes , rhs: CodableNSAttributes ) -> Bool {
275+ func areEqual< T> ( _ a: T , _ b: Any ) -> Bool where T: Equatable {
276+ guard let b = b as? T else {
277+ return false
278+ }
279+ return a == b
280+ }
281+ guard lhs. wrappedValue. count == rhs. wrappedValue. count else {
282+ return false
283+ }
284+ for (key, leftValue) in lhs. wrappedValue {
285+ guard let rightValue = rhs. wrappedValue [ key] else {
286+ return false
287+ }
288+ guard let leftValue = leftValue as? any Equatable else {
289+ return false
290+ }
291+ guard areEqual ( leftValue, rightValue) else {
292+ return false
293+ }
294+ }
295+ return true
296+ }
297+
298+ package func hash( into hasher: inout Hasher ) {
299+ for (key, value) in wrappedValue {
300+ hasher. combine ( key)
301+ if let value = value as? any Hashable {
302+ hasher. combine ( value)
303+ }
304+ }
305+ }
306+ }
0 commit comments