File tree Expand file tree Collapse file tree 4 files changed +94
-0
lines changed Expand file tree Collapse file tree 4 files changed +94
-0
lines changed Original file line number Diff line number Diff line change @@ -42,6 +42,21 @@ public enum BSONError {
42
42
}
43
43
}
44
44
45
+ extension DecodingError {
46
+ /// Standardize the errors emitted by BSONValue initializers.
47
+ internal static func _extendedJSONError(
48
+ keyPath: [ String ] ,
49
+ debugDescription: String
50
+ ) -> DecodingError {
51
+ let debugStart = keyPath. joined ( separator: " . " ) +
52
+ ( keyPath == [ ] ? " " : " : " )
53
+ return . dataCorrupted( DecodingError . Context (
54
+ codingPath: [ ] ,
55
+ debugDescription: debugStart + debugDescription
56
+ ) )
57
+ }
58
+ }
59
+
45
60
/// Standardize the errors emitted from the BSON Iterator.
46
61
/// The BSON iterator is used for validation so this should help debug the underlying incorrect binary.
47
62
internal func BSONIterationError(
Original file line number Diff line number Diff line change @@ -14,6 +14,11 @@ internal protocol BSONValue: Codable {
14
14
15
15
/// Writes this value's BSON byte representation to the provided ByteBuffer.
16
16
func write( to buffer: inout ByteBuffer )
17
+
18
+ /// Initializes a corresponding `BSON` from the provided extendedJSON.
19
+ /// Currently commented out to avoid "not implemented" errors while implementing the
20
+ /// initializer one by one on each BSONValue.
21
+ // internal init(fromExtJSON json: JSON) throws
17
22
}
18
23
19
24
/// Convenience extension to get static bsonType from an instance
Original file line number Diff line number Diff line change 1
1
import NIO
2
2
3
3
extension Int32 : BSONValue {
4
+ /*
5
+ * Initializes an `Int32` from ExtendedJSON.
6
+ *
7
+ * Parameters:
8
+ * - `json`: a `JSON` representing the canonical or relaxed form of ExtendedJSON for an `Int32`.
9
+ * - `keyPath`: an array of `String`s containing the enclosing JSON keys of the current json being passed in.
10
+ * This is used for error messages.
11
+ *
12
+ * Returns:
13
+ * - `nil` if the provided value is not an `Int32`.
14
+ *
15
+ * Throws:
16
+ * - `DecodingError` if `json` is a partial match or is malformed.
17
+ */
18
+ internal init ? ( fromExtJSON json: JSON , keyPath: [ String ] ) throws {
19
+ switch json {
20
+ case let . number( n) :
21
+ // relaxed extended JSON
22
+ guard let int = Int32 ( exactly: n) else {
23
+ return nil
24
+ }
25
+ self = int
26
+ case let . object( obj) :
27
+ // canonical extended JSON
28
+ guard let value = obj [ " $numberInt " ] else {
29
+ return nil
30
+ }
31
+ guard obj. count == 1 else {
32
+ throw DecodingError . _extendedJSONError (
33
+ keyPath: keyPath,
34
+ debugDescription: " Expected only \" $numberInt \" key, found too many keys: \( obj. keys) "
35
+ )
36
+ }
37
+ guard let str = value. stringValue, let int = Int32 ( str) else {
38
+ throw DecodingError . _extendedJSONError (
39
+ keyPath: keyPath,
40
+ debugDescription: " Could not parse `Int32` from \" \( value) \" , " +
41
+ " input must be a 32-bit signed integer as a string. "
42
+ )
43
+ }
44
+ self = int
45
+ default :
46
+ return nil
47
+ }
48
+ }
49
+
4
50
internal static var bsonType : BSONType { . int32 }
5
51
6
52
internal var bson : BSON { . int32( self ) }
Original file line number Diff line number Diff line change
1
+ @testable import BSON
2
+ import Foundation
3
+ import Nimble
4
+ import NIO
5
+ import XCTest
6
+
7
+ open class ExtendedJSONConversionTestCase : BSONTestCase {
8
+ func testInt32( ) throws {
9
+ // Success cases
10
+ expect ( try Int32 ( fromExtJSON: 5 , keyPath: [ ] ) ) . to ( equal ( 5 ) )
11
+ expect ( try Int32 ( fromExtJSON: [ " $numberInt " : " 5 " ] , keyPath: [ ] ) ) . to ( equal ( 5 ) )
12
+
13
+ // Nil cases
14
+ expect ( try Int32 ( fromExtJSON: JSON . number ( Double ( Int32 . max) + 1 ) , keyPath: [ ] ) ) . to ( beNil ( ) )
15
+ expect ( try Int32 ( fromExtJSON: JSON . bool ( true ) , keyPath: [ ] ) ) . to ( beNil ( ) )
16
+ expect ( try Int32 ( fromExtJSON: [ " bad " : " 5 " ] , keyPath: [ ] ) ) . to ( beNil ( ) )
17
+
18
+ // Error cases
19
+ expect ( try Int32 ( fromExtJSON: [ " $numberInt " : 5 ] , keyPath: [ ] ) )
20
+ . to ( throwError ( errorType: DecodingError . self) )
21
+ expect ( try Int32 ( fromExtJSON: [ " $numberInt " : " 5 " , " extra " : true ] , keyPath: [ ] ) )
22
+ . to ( throwError ( errorType: DecodingError . self) )
23
+ expect ( try Int32 ( fromExtJSON: [ " $numberInt " : . string( " \( Double ( Int32 . max) + 1 ) " ) ] , keyPath: [ " key " , " path " ] ) )
24
+ . to ( throwError ( errorType: DecodingError . self) )
25
+ }
26
+
27
+ // TODO: Add equivalent tests for each type that conforms to `BSONValue`
28
+ }
You can’t perform that action at this time.
0 commit comments