@@ -9,6 +9,7 @@ import OrderedCollections
9
9
10
10
// MARK: - Configuration files with dynamic lookup
11
11
12
+ @dynamicMemberLookup
12
13
public struct Config : Hashable , Sendable ,
13
14
ExpressibleByStringLiteral ,
14
15
ExpressibleByIntegerLiteral ,
@@ -36,23 +37,57 @@ public struct Config: Hashable, Sendable,
36
37
37
38
public static func == ( lhs: Data , rhs: Data ) -> Bool {
38
39
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
+ }
47
58
case ( . dictionary( let lhs) , . dictionary( let rhs) ) :
48
- return lhs == rhs // TODO: ensure equatable
59
+ return lhs == rhs
49
60
case ( . array( let lhs) , . array( let rhs) ) :
50
- return lhs == rhs // TODO: ensure equatable
61
+ return lhs == rhs
51
62
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
+ }
53
86
default :
54
87
return false
55
88
}
89
+
90
+ return false
56
91
}
57
92
58
93
public var description : String {
@@ -75,6 +110,52 @@ public struct Config: Hashable, Sendable,
75
110
return " ( \( val. 0 ) , \( val. 1 ) ) "
76
111
}
77
112
}
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
+ }
78
159
}
79
160
80
161
init ( ) {
@@ -218,12 +299,9 @@ public struct Config: Hashable, Sendable,
218
299
}
219
300
220
301
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 ( )
225
303
}
226
-
304
+
227
305
public func string( or: String ) -> String {
228
306
if let val: String = self . string ( ) {
229
307
return val
@@ -264,25 +342,9 @@ public struct Config: Hashable, Sendable,
264
342
}
265
343
266
344
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 ( )
284
346
}
285
-
347
+
286
348
public func boolean( or: Bool ) -> Bool {
287
349
if let val = self . boolean ( ) {
288
350
return val
@@ -301,13 +363,10 @@ public struct Config: Hashable, Sendable,
301
363
}
302
364
303
365
public func integer( ) -> Int ? {
304
- if case . integer( let val) = self . value {
305
- return val
306
- }
307
- return nil
366
+ return self . value. integer ( )
308
367
}
309
-
310
- public func integer( or: Int ) -> Int ? {
368
+
369
+ public func integer( or: Int ) -> Int {
311
370
if let val = self . integer ( ) {
312
371
return val
313
372
}
@@ -317,25 +376,19 @@ public struct Config: Hashable, Sendable,
317
376
// MARK: getters/operators - floating
318
377
319
378
public func get( ) -> Float ? {
320
- return self . floating ( )
379
+ return self . value . floating ( )
321
380
}
322
381
323
382
public func get( or: Float ) -> Float ? {
324
383
return self . floating ( or: or)
325
384
}
326
385
327
386
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 ( )
335
388
}
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 ( ) {
339
392
return val
340
393
}
341
394
return or
@@ -346,7 +399,7 @@ public struct Config: Hashable, Sendable,
346
399
public func get( ) -> [ BinaryDistinctString : Int ] ? {
347
400
if let dict = self . dictionary ( ) {
348
401
return dict. reduce ( into: [ : ] ) { result, element in
349
- if let val = element. value. integer ( ) {
402
+ if let val = element. value. value . integer ( ) {
350
403
result [ element. key] = val
351
404
}
352
405
}
@@ -407,7 +460,7 @@ public struct Config: Hashable, Sendable,
407
460
public func get( ) -> [ String ] ? {
408
461
if let arr = self . array ( ) {
409
462
return arr. reduce ( into: [ ] ) { result, element in
410
- if let val: String = element. string ( ) {
463
+ if let val: String = element. value . string ( ) {
411
464
result. append ( val)
412
465
}
413
466
}
@@ -511,6 +564,17 @@ public struct Config: Hashable, Sendable,
511
564
return Config ( )
512
565
}
513
566
}
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
+ }
514
578
515
579
func uncamelCase( _ string: BinaryDistinctString ) -> BinaryDistinctString {
516
580
let scalars = string. string. unicodeScalars
@@ -684,13 +748,7 @@ extension Config: Codable {
684
748
685
749
extension Config : Equatable {
686
750
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
694
752
}
695
753
}
696
754
0 commit comments