-
-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathConstructibleFromJSValue.swift
131 lines (120 loc) · 4.75 KB
/
ConstructibleFromJSValue.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/// Types conforming to this protocol can be constructed from `JSValue`.
public protocol ConstructibleFromJSValue {
/// Construct an instance of `Self`, if possible, from the given `JSValue`.
/// Return `nil` if the value is not compatible with the conforming Swift type.
///
/// - Parameter value: The `JSValue` to decode
/// - Returns: An instance of `Self`, if one was successfully constructed from the value.
static func construct(from value: JSValue) -> Self?
}
extension Bool: ConstructibleFromJSValue {
public static func construct(from value: JSValue) -> Bool? {
value.boolean
}
}
extension String: ConstructibleFromJSValue {
public static func construct(from value: JSValue) -> String? {
value.string
}
}
extension JSString: ConstructibleFromJSValue {
public static func construct(from value: JSValue) -> JSString? {
value.jsString
}
}
extension BinaryFloatingPoint where Self: ConstructibleFromJSValue {
public static func construct(from value: JSValue) -> Self? {
value.number.map(Self.init)
}
}
extension Double: ConstructibleFromJSValue {}
extension Float: ConstructibleFromJSValue {}
extension SignedInteger where Self: ConstructibleFromJSValue {
/// Construct an instance of `SignedInteger` from the given `JSBigIntExtended`.
///
/// If the value is too large to fit in the `Self` type, `nil` is returned.
///
/// - Parameter bigInt: The `JSBigIntExtended` to decode
public init?(exactly bigInt: some JSBigIntExtended) {
self.init(exactly: bigInt.int64Value)
}
/// Construct an instance of `SignedInteger` from the given `JSBigIntExtended`.
///
/// Crash if the value is too large to fit in the `Self` type.
///
/// - Parameter bigInt: The `JSBigIntExtended` to decode
public init(_ bigInt: some JSBigIntExtended) {
self.init(bigInt.int64Value)
}
/// Construct an instance of `SignedInteger` from the given `JSValue`.
///
/// Returns `nil` if one of the following conditions is met:
/// - The value is not a number or a bigint.
/// - The value is a number that does not fit or cannot be represented
/// in the `Self` type (e.g. NaN, Infinity).
/// - The value is a bigint that does not fit in the `Self` type.
///
/// If the value is a number, it is rounded towards zero before conversion.
///
/// - Parameter value: The `JSValue` to decode
public static func construct(from value: JSValue) -> Self? {
if let number = value.number {
return Self(exactly: number.rounded(.towardZero))
}
#if !hasFeature(Embedded)
if let bigInt = value.bigInt as? JSBigIntExtended {
return Self(exactly: bigInt)
}
#endif
return nil
}
}
extension Int: ConstructibleFromJSValue {}
extension Int8: ConstructibleFromJSValue {}
extension Int16: ConstructibleFromJSValue {}
extension Int32: ConstructibleFromJSValue {}
extension Int64: ConstructibleFromJSValue {}
extension UnsignedInteger where Self: ConstructibleFromJSValue {
/// Construct an instance of `UnsignedInteger` from the given `JSBigIntExtended`.
///
/// Returns `nil` if the value is negative or too large to fit in the `Self` type.
///
/// - Parameter bigInt: The `JSBigIntExtended` to decode
public init?(exactly bigInt: some JSBigIntExtended) {
self.init(exactly: bigInt.uInt64Value)
}
/// Construct an instance of `UnsignedInteger` from the given `JSBigIntExtended`.
///
/// Crash if the value is negative or too large to fit in the `Self` type.
///
/// - Parameter bigInt: The `JSBigIntExtended` to decode
public init(_ bigInt: some JSBigIntExtended) {
self.init(bigInt.uInt64Value)
}
/// Construct an instance of `UnsignedInteger` from the given `JSValue`.
///
/// Returns `nil` if one of the following conditions is met:
/// - The value is not a number or a bigint.
/// - The value is a number that does not fit or cannot be represented
/// in the `Self` type (e.g. NaN, Infinity).
/// - The value is a bigint that does not fit in the `Self` type.
/// - The value is negative.
///
/// - Parameter value: The `JSValue` to decode
public static func construct(from value: JSValue) -> Self? {
if let number = value.number {
return Self(exactly: number.rounded(.towardZero))
}
#if !hasFeature(Embedded)
if let bigInt = value.bigInt as? JSBigIntExtended {
return Self(exactly: bigInt)
}
#endif
return nil
}
}
extension UInt: ConstructibleFromJSValue {}
extension UInt8: ConstructibleFromJSValue {}
extension UInt16: ConstructibleFromJSValue {}
extension UInt32: ConstructibleFromJSValue {}
extension UInt64: ConstructibleFromJSValue {}