44// Copyright © 2023 MFB Technologies, Inc. All rights reserved.
55
66import Dependencies
7+ import Foundation
78
89/// A key/value pair argument that provides a given value for a option or variable.
910///
@@ -112,7 +113,7 @@ extension Option where Value: CustomStringConvertible {
112113 public init ( key: some CustomStringConvertible , value: Value ) {
113114 keyOverride = key. description
114115 wrappedValue = value
115- unwrap = { [ $0 . description ] }
116+ unwrap = Self . unwrap ( _ : )
116117 }
117118
118119 /// Initializes a new option when used as a `@propertyWrapper`
@@ -123,7 +124,72 @@ extension Option where Value: CustomStringConvertible {
123124 public init ( wrappedValue: Value , _ key: String ? = nil ) {
124125 keyOverride = key
125126 self . wrappedValue = wrappedValue
126- unwrap = { [ $0. description] }
127+ unwrap = Self . unwrap ( _: )
128+ }
129+
130+ @Sendable
131+ public static func unwrap( _ value: Value ) -> [ String ] {
132+ [ value. description]
133+ }
134+ }
135+
136+ extension Option where Value: RawRepresentable , Value. RawValue: CustomStringConvertible {
137+ /// Initializes a new option when not used as a `@propertyWrapper`
138+ ///
139+ /// - Parameters
140+ /// - key: Explicit key value
141+ /// - wrappedValue: The underlying value
142+ public init ( key: some CustomStringConvertible , value: Value ) {
143+ keyOverride = key. description
144+ wrappedValue = value
145+ unwrap = Self . unwrap ( _: )
146+ }
147+
148+ /// Initializes a new option when used as a `@propertyWrapper`
149+ ///
150+ /// - Parameters
151+ /// - wrappedValue: The underlying value
152+ /// - _ key: Optional explicit key value
153+ public init ( wrappedValue: Value , _ key: String ? = nil ) {
154+ keyOverride = key
155+ self . wrappedValue = wrappedValue
156+ unwrap = Self . unwrap ( _: )
157+ }
158+
159+ @Sendable
160+ public static func unwrap( _ value: Value ) -> [ String ] {
161+ [ value. rawValue. description]
162+ }
163+ }
164+
165+ extension Option where Value: CustomStringConvertible , Value: RawRepresentable ,
166+ Value. RawValue: CustomStringConvertible
167+ {
168+ /// Initializes a new option when not used as a `@propertyWrapper`
169+ ///
170+ /// - Parameters
171+ /// - key: Explicit key value
172+ /// - wrappedValue: The underlying value
173+ public init ( key: some CustomStringConvertible , value: Value ) {
174+ keyOverride = key. description
175+ wrappedValue = value
176+ unwrap = Self . unwrap ( _: )
177+ }
178+
179+ /// Initializes a new option when used as a `@propertyWrapper`
180+ ///
181+ /// - Parameters
182+ /// - wrappedValue: The underlying value
183+ /// - _ key: Optional explicit key value
184+ public init ( wrappedValue: Value , _ key: String ? = nil ) {
185+ keyOverride = key
186+ self . wrappedValue = wrappedValue
187+ unwrap = Self . unwrap ( _: )
188+ }
189+
190+ @Sendable
191+ public static func unwrap( _ value: Value ) -> [ String ] {
192+ [ value. rawValue. description]
127193 }
128194}
129195
@@ -140,7 +206,7 @@ extension Option {
140206 {
141207 keyOverride = key. description
142208 wrappedValue = value
143- unwrap = { [ $0 ? . description ] . compactMap { $0 } }
209+ unwrap = Self . unwrap ( _ : )
144210 }
145211
146212 /// Initializes a new option when used as a `@propertyWrapper`
@@ -153,7 +219,14 @@ extension Option {
153219 {
154220 keyOverride = key
155221 self . wrappedValue = wrappedValue
156- unwrap = { [ $0? . description] . compactMap { $0 } }
222+ unwrap = Self . unwrap ( _: )
223+ }
224+
225+ @Sendable
226+ public static func unwrap< Wrapped> ( _ value: Wrapped ? ) -> [ String ] where Wrapped: CustomStringConvertible ,
227+ Value == Wrapped ?
228+ {
229+ [ value? . description] . compactMap { $0 }
157230 }
158231}
159232
@@ -170,7 +243,7 @@ extension Option {
170243 {
171244 keyOverride = key. description
172245 wrappedValue = values
173- unwrap = { $0 . map ( \ E . description ) }
246+ unwrap = Self . unwrap ( _ : )
174247 }
175248
176249 /// Initializes a new option when used as a `@propertyWrapper`
@@ -183,7 +256,14 @@ extension Option {
183256 {
184257 keyOverride = key
185258 self . wrappedValue = wrappedValue
186- unwrap = { $0. map ( \E . description) }
259+ unwrap = Self . unwrap ( _: )
260+ }
261+
262+ @Sendable
263+ public static func unwrap< E> ( _ value: Value ) -> [ String ] where Value: Sequence , Value. Element == E ,
264+ E: CustomStringConvertible
265+ {
266+ value. map ( \E . description)
187267 }
188268}
189269
@@ -227,10 +307,43 @@ extension Option: ExpressibleByStringInterpolation where Value: StringProtocol {
227307 }
228308}
229309
230- extension Option : Decodable where Value: Decodable & CustomStringConvertible {
310+ extension Option : DecodableWithConfiguration where Value: Decodable {
311+ public init ( from decoder: Decoder , configuration: @escaping @Sendable ( Value ) -> [ String ] ) throws {
312+ let container = try decoder. singleValueContainer ( )
313+ try self . init ( wrappedValue: container. decode ( Value . self) , nil , configuration)
314+ }
315+ }
316+
317+ extension Option : Decodable where Value: Decodable {
231318 public init ( from decoder: Decoder ) throws {
232319 let container = try decoder. singleValueContainer ( )
233- try self . init ( wrappedValue: container. decode ( Value . self) )
320+ guard let configurationCodingUserInfoKey = Self . configurationCodingUserInfoKey ( for: Value . Type. self) else {
321+ throw DecodingError . dataCorrupted ( DecodingError . Context (
322+ codingPath: decoder. codingPath,
323+ debugDescription: " No CodingUserInfoKey found for accessing the DecodingConfiguration. " ,
324+ underlyingError: nil
325+ ) )
326+ }
327+ guard let _configuration = decoder. userInfo [ configurationCodingUserInfoKey] else {
328+ throw DecodingError . dataCorrupted ( DecodingError . Context (
329+ codingPath: decoder. codingPath,
330+ debugDescription: " No DecodingConfiguration found for key: \( configurationCodingUserInfoKey. rawValue) " ,
331+ underlyingError: nil
332+ ) )
333+ }
334+ guard let configuration = _configuration as? Self . DecodingConfiguration else {
335+ let desc = " Invalid DecodingConfiguration found for key: \( configurationCodingUserInfoKey. rawValue) "
336+ throw DecodingError . dataCorrupted ( DecodingError . Context (
337+ codingPath: decoder. codingPath,
338+ debugDescription: desc,
339+ underlyingError: nil
340+ ) )
341+ }
342+ try self . init ( wrappedValue: container. decode ( Value . self) , nil , configuration)
343+ }
344+
345+ public static func configurationCodingUserInfoKey( for _: ( some Any ) . Type) -> CodingUserInfoKey ? {
346+ CodingUserInfoKey ( rawValue: ObjectIdentifier ( Self . self) . debugDescription)
234347 }
235348}
236349
0 commit comments