@@ -9,6 +9,7 @@ import OrderedCollections
99
1010// MARK: - Configuration files with dynamic lookup
1111
12+ @dynamicMemberLookup
1213public struct Config : Hashable , Sendable ,
1314 ExpressibleByStringLiteral ,
1415 ExpressibleByIntegerLiteral ,
@@ -36,23 +37,57 @@ public struct Config: Hashable, Sendable,
3637
3738 public static func == ( lhs: Data , rhs: Data ) -> Bool {
3839 switch ( lhs, rhs) {
39- case ( . string( let lhs) , . string( let rhs) ) :
40- return lhs == rhs
41- case ( . integer( let lhs) , . integer( let rhs) ) :
42- return lhs == rhs
43- case ( . boolean( let lhs) , . boolean( let rhs) ) :
44- return lhs == rhs
45- case ( . floating( let lhs) , . floating( let rhs) ) :
46- return lhs == rhs
40+ case ( . null, . null) :
41+ return true
42+ case ( . string( let lhs) , _) :
43+ if let rhs = rhs. string ( ) {
44+ return lhs == BinaryDistinctString ( rhs)
45+ }
46+ case ( . integer( let lhs) , _) :
47+ if let rhs = rhs. integer ( ) {
48+ return lhs == rhs
49+ }
50+ case ( . boolean( let lhs) , _) :
51+ if let rhs = rhs. boolean ( ) {
52+ return lhs == rhs
53+ }
54+ case ( . floating( let lhs) , _) :
55+ if let rhs = rhs. floating ( ) {
56+ return lhs == rhs
57+ }
4758 case ( . dictionary( let lhs) , . dictionary( let rhs) ) :
48- return lhs == rhs // TODO: ensure equatable
59+ return lhs == rhs
4960 case ( . array( let lhs) , . array( let rhs) ) :
50- return lhs == rhs // TODO: ensure equatable
61+ return lhs == rhs
5162 case ( . token( let lhs) , . token( let rhs) ) :
52- return lhs == rhs // TODO: ensure equatable
63+ return lhs == rhs
64+ default :
65+ return false
66+ }
67+
68+ // right hand side might be a super set of left hand side
69+ switch rhs {
70+ case . string( let rhs) :
71+ if let lhs = lhs. string ( ) {
72+ return BinaryDistinctString ( lhs) == rhs
73+ }
74+ case . integer( let rhs) :
75+ if let lhs = lhs. integer ( ) {
76+ return lhs == rhs
77+ }
78+ case . boolean( let rhs) :
79+ if let lhs = lhs. boolean ( ) {
80+ return lhs == rhs
81+ }
82+ case . floating( let rhs) :
83+ if let lhs = lhs. floating ( ) {
84+ return lhs == rhs
85+ }
5386 default :
5487 return false
5588 }
89+
90+ return false
5691 }
5792
5893 public var description : String {
@@ -75,6 +110,52 @@ public struct Config: Hashable, Sendable,
75110 return " ( \( val. 0 ) , \( val. 1 ) ) "
76111 }
77112 }
113+
114+
115+ public func string( ) -> String ? {
116+ if case . string( let val) = self {
117+ return val. string
118+ }
119+ return nil
120+ }
121+
122+
123+ public func boolean( ) -> Bool ? {
124+ if case . boolean( let val) = self {
125+ return val
126+ }
127+ if case . integer( let val) = self {
128+ return val == 1
129+ }
130+ if case . string( let val) = self {
131+ switch val. string. lowercased ( ) {
132+ case " true " , " t " , " 1 " :
133+ return true
134+ case " false " , " f " , " 0 " :
135+ return false
136+ default :
137+ return nil
138+ }
139+ }
140+ return nil
141+ }
142+
143+ public func integer( ) -> Int ? {
144+ if case . integer( let val) = self {
145+ return val
146+ }
147+ return nil
148+ }
149+
150+ public func floating( ) -> Float ? {
151+ if case . floating( let val) = self {
152+ return val
153+ }
154+ if case . integer( let val) = self {
155+ return Float ( val)
156+ }
157+ return nil
158+ }
78159 }
79160
80161 init ( ) {
@@ -218,12 +299,9 @@ public struct Config: Hashable, Sendable,
218299 }
219300
220301 public func string( ) -> String ? {
221- if case . string( let val) = self . value {
222- return val. string
223- }
224- return nil
302+ return self . value. string ( )
225303 }
226-
304+
227305 public func string( or: String ) -> String {
228306 if let val: String = self . string ( ) {
229307 return val
@@ -264,25 +342,9 @@ public struct Config: Hashable, Sendable,
264342 }
265343
266344 public func boolean( ) -> Bool ? {
267- if case . boolean( let val) = self . value {
268- return val
269- }
270- if case . integer( let val) = self . value {
271- return val == 1
272- }
273- if case . string( let val) = self . value {
274- switch val. string. lowercased ( ) {
275- case " true " , " t " , " 1 " :
276- return true
277- case " false " , " f " , " 0 " :
278- return false
279- default :
280- return nil
281- }
282- }
283- return nil
345+ return self . value. boolean ( )
284346 }
285-
347+
286348 public func boolean( or: Bool ) -> Bool {
287349 if let val = self . boolean ( ) {
288350 return val
@@ -301,13 +363,10 @@ public struct Config: Hashable, Sendable,
301363 }
302364
303365 public func integer( ) -> Int ? {
304- if case . integer( let val) = self . value {
305- return val
306- }
307- return nil
366+ return self . value. integer ( )
308367 }
309-
310- public func integer( or: Int ) -> Int ? {
368+
369+ public func integer( or: Int ) -> Int {
311370 if let val = self . integer ( ) {
312371 return val
313372 }
@@ -317,25 +376,19 @@ public struct Config: Hashable, Sendable,
317376 // MARK: getters/operators - floating
318377
319378 public func get( ) -> Float ? {
320- return self . floating ( )
379+ return self . value . floating ( )
321380 }
322381
323382 public func get( or: Float ) -> Float ? {
324383 return self . floating ( or: or)
325384 }
326385
327386 public func floating( ) -> Float ? {
328- if case . floating( let val) = self . value {
329- return val
330- }
331- if case . integer( let val) = self . value {
332- return Float ( val)
333- }
334- return nil
387+ return self . value. floating ( )
335388 }
336-
337- public func floating( or: Float ) -> Float ? {
338- if let val = self . floating ( ) {
389+
390+ public func floating( or: Float ) -> Float {
391+ if let val = self . value . floating ( ) {
339392 return val
340393 }
341394 return or
@@ -346,7 +399,7 @@ public struct Config: Hashable, Sendable,
346399 public func get( ) -> [ BinaryDistinctString : Int ] ? {
347400 if let dict = self . dictionary ( ) {
348401 return dict. reduce ( into: [ : ] ) { result, element in
349- if let val = element. value. integer ( ) {
402+ if let val = element. value. value . integer ( ) {
350403 result [ element. key] = val
351404 }
352405 }
@@ -407,7 +460,7 @@ public struct Config: Hashable, Sendable,
407460 public func get( ) -> [ String ] ? {
408461 if let arr = self . array ( ) {
409462 return arr. reduce ( into: [ ] ) { result, element in
410- if let val: String = element. string ( ) {
463+ if let val: String = element. value . string ( ) {
411464 result. append ( val)
412465 }
413466 }
@@ -511,6 +564,17 @@ public struct Config: Hashable, Sendable,
511564 return Config ( )
512565 }
513566 }
567+
568+
569+ public subscript( dynamicMember member: String ) -> Config ? {
570+ get {
571+ if let dict = self . dictionary ( ) {
572+ return dict [ BinaryDistinctString ( member) ] ?? dict [ self . uncamelCase ( BinaryDistinctString ( member) ) ] ?? Config ( )
573+ }
574+
575+ return nil // backward compatibility
576+ }
577+ }
514578
515579 func uncamelCase( _ string: BinaryDistinctString ) -> BinaryDistinctString {
516580 let scalars = string. string. unicodeScalars
@@ -684,13 +748,7 @@ extension Config: Codable {
684748
685749extension Config : Equatable {
686750 public static func == ( lhs: Config , rhs: Config ) -> Bool {
687- let encoder = JSONEncoder ( )
688- encoder. outputFormatting = [ . prettyPrinted, . sortedKeys]
689-
690- guard let lhsData = try ? encoder. encode ( lhs) ,
691- let rhsData = try ? encoder. encode ( rhs)
692- else { return false }
693- return lhsData == rhsData
751+ return lhs. value == rhs. value
694752 }
695753}
696754
0 commit comments