0001 // 0002 // DecimalNumber.swift 0003 // PMJSON 0004 // 0005 // Created by Kevin Ballard on 2/8/16. 0006 // Copyright © 2016 Postmates. 0007 // 0008 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 0009 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 0010 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 0011 // option. This file may not be copied, modified, or distributed 0012 // except according to those terms. 0013 // 0014 0015 #if os(iOS) || os(OSX) || os(tvOS) || os(watchOS) 0016 0017 import Foundation 0018 0019 // MARK: Basic accessors 0020 0021 public extension JSON { 0022 /// Returns the receiver as an `NSDecimalNumber` if possible. 0023 /// - Returns: An `NSDecimalNumber` if the receiver is `.Int64` or `.Double`, or is a `.String` 0024 /// that contains a valid decimal number representation, otherwise `nil`. 0025 /// - Note: Whitespace is not allowed in the string representation. 0026 var asDecimalNumber: NSDecimalNumber? { 0027 switch self { 0028 case .Int64(let i): return NSDecimalNumber(longLong: i) 0029 case .Double(let d): return NSDecimalNumber(double: d) 0030 case .String(let s) where !s.isEmpty: 0031 // NSDecimalNumber(string:) doesn't tell us if the number was valid. 0032 // We could check for NaN, but that still doesn't tell us if there's anything left in the string. 0033 // I'm pretty sure it uses NSScanner.scanDecimal() internally, so we'll just use that instead. 0034 let scanner = NSScanner(string: s) 0035 scanner.charactersToBeSkipped = nil 0036 var decimal = NSDecimal() 0037 if scanner.scanDecimal(&decimal) && scanner.atEnd { 0038 return NSDecimalNumber(decimal: decimal) 0039 } 0040 return nil 0041 default: return nil 0042 } 0043 } 0044 0045 /// Returns the receiver as an `NSDecimalNumber` if it is `.Int64` or `.Double`. 0046 /// - Returns: An `NSDecimalNumber`. 0047 /// - Throws: `JSONError` if the receiver is not an `.Int64` or a `.Double`. 0048 func getDecimalNumber
DecimalNumber.swift:75 guard let value = asDecimalNumber else {DecimalNumber.swift:88 if let value = asDecimalNumber { return value }() throws -> NSDecimalNumber { 0049 switch self { 0050 case .Int64(let i): return NSDecimalNumber(longLong: i) 0051 case .Double(let d): return NSDecimalNumber(double: d) 0052 default: throw JSONError.MissingOrInvalidType(path: nil, expected: .Required(.Number), actual: .forValue(self)) 0053 } 0054 } 0055 0056 /// Returns the receiver as an `NSDecimalNumber` if it is `.Int64` or `.Double`. 0057 /// - Returns: An `NSDecimalNumber`, or `nil` if the receivre is `null`. 0058 /// - Throws: `JSONError` if the receiver is not an `.Int64` or a `.Double`. 0059 func getDecimalNumberOrNil
DecimalNumber.swift:105 return try scoped(key) { try value.getDecimalNumber() }DecimalNumber.swift:154 return try scoped(index) { try value.getDecimalNumber() }DecimalNumber.swift:201 return try scoped(key) { try value.getDecimalNumber() }() throws -> NSDecimalNumber? { 0060 switch self { 0061 case .Int64(let i): return NSDecimalNumber(longLong: i) 0062 case .Double(let d): return NSDecimalNumber(double: d) 0063 case .Null: return nil 0064 default: throw JSONError.MissingOrInvalidType(path: nil, expected: .Required(.Number), actual: .forValue(self)) 0065 } 0066 } 0067 0068 /// Returns the receiver as an `NSDecimalNumber` if possible. 0069 /// - Returns: An `NSDecimalNumber` if the receiver is `.Int64` or `.Double`, or is a `.String` 0070 /// that contains a valid decimal number representation. 0071 /// - Throws: `JSONError` if the receiver is the wrong type, or is a `.String` that does not contain 0072 /// a valid decimal number representation. 0073 /// - Note: Whitespace is not allowed in the string representation. 0074 func toDecimalNumber
DecimalNumber.swift:116 return try scoped(key) { try value.getDecimalNumberOrNil() }DecimalNumber.swift:164 return try scoped(index) { try value.getDecimalNumberOrNil() }DecimalNumber.swift:211 return try scoped(key) { try value.getDecimalNumberOrNil() }() throws -> NSDecimalNumber { 0075 guard let value = asDecimalNumber else { 0076 throw JSONError.MissingOrInvalidType(path: nil, expected: .Required(.Number), actual: .forValue(self)) 0077 } 0078 return value 0079 } 0080 0081 /// Returns the receiver as an `NSDecimalNumber` if possible. 0082 /// - Returns: An `NSDecimalNumber` if the receiver is `.Int64` or `.Double`, or is a `.String` 0083 /// that contains a valid decimal number representation, or `nil` if the receiver is `null`. 0084 /// - Throws: `JSONError` if the receiver is the wrong type, or is a `.String` that does not contain 0085 /// a valid decimal number representation. 0086 /// - Note: Whitespace is not allowed in the string representation. 0087 func toDecimalNumberOrNil
DecimalNumber.swift:128 return try scoped(key) { try value.toDecimalNumber() }DecimalNumber.swift:176 return try scoped(index) { try value.toDecimalNumber() }DecimalNumber.swift:222 return try scoped(key) { try value.toDecimalNumber() }() throws -> NSDecimalNumber? { 0088 if let value = asDecimalNumber { return value } 0089 else if isNull { return nil } 0090 else { throw JSONError.MissingOrInvalidType(path: nil, expected: .Optional(.Number), actual: .forValue(self)) } 0091 } 0092 } 0093 0094 // MARK: - Keyed accessors 0095 0096 public extension JSON { 0097 /// Subscripts the receiver with `key` and returns the result as an `NSDecimalNumber`. 0098 /// - Parameter key: The key that's used to subscript the receiver. 0099 /// - Returns: An `NSDecimalNumber`. 0100 /// - Throws: `JSONError` if the key doesn't exist or the value is the wrong type, or if 0101 /// the receiver is not an object. 0102 func getDecimalNumber(key: Swift.String) throws -> NSDecimalNumber { 0103 let dict = try getObject() 0104 let value = try getRequired(dict, key: key, type: .Number) 0105 return try scoped(key) { try value.getDecimalNumber() } 0106 } 0107 0108 /// Subscripts the receiver with `key` and returns the result as an `NSDecimalNumber`. 0109 /// - Parameter key: The key that's used to subscript the receiver. 0110 /// - Returns: An `NSDecimalNumber`, or `nil` if the key doesn't exist or the value is `null`. 0111 /// - Throws: `JSONError` if the value is the wrong type, or if the receiver is 0112 /// not an object. 0113 func getDecimalNumberOrNil(key: Swift.String) throws -> NSDecimalNumber? { 0114 let dict = try getObject() 0115 guard let value = dict[key] else { return nil } 0116 return try scoped(key) { try value.getDecimalNumberOrNil() } 0117 } 0118 0119 /// Subscripts the receiver with `key` and returns the result as an `NSDecimalNumber`. 0120 /// - Parameter key: The key that's used to subscript the receiver. 0121 /// - Returns: An `NSDecimalNumber`. 0122 /// - Throws: `JSONError` if the key doesn't exist or the value is `null`, a boolean, an object, 0123 /// an array, or a string that cannot be coerced to a decimal number, or if the 0124 /// receiver is not an object. 0125 func toDecimalNumber(key: Swift.String) throws -> NSDecimalNumber { 0126 let dict = try getObject() 0127 let value = try getRequired(dict, key: key, type: .Number) 0128 return try scoped(key) { try value.toDecimalNumber() } 0129 } 0130 0131 /// Subscripts the receiver with `key` and returns the result as an `NSDecimalNumber`. 0132 /// - Parameter key: The key that's used to subscript the receiver. 0133 /// - Returns: An `NSDecimalNumber`, or `nil` if the key doesn't exist or the value is `null`. 0134 /// - Throws: `JSONError` if the value is a boolean, an object, an array, or a string that 0135 /// cannot be coerced to a decimal number, or if the receiver is not an object. 0136 func toDecimalNumberOrNil(key: Swift.String) throws -> NSDecimalNumber? { 0137 let dict = try getObject() 0138 guard let value = dict[key] else { return nil } 0139 return try scoped(key) { try value.toDecimalNumberOrNil() } 0140 } 0141 } 0142 0143 // MARK: - Indexed accessors 0144 0145 public extension JSON { 0146 /// Subscripts the receiver with `index` and returns the result as an `NSDecimalNumber`. 0147 /// - Parameter index: The index that's used to subscript the receiver. 0148 /// - Returns: An `NSDecimalNumber`. 0149 /// - Throws: `JSONError` if the index is out of bounds or the value is the wrong type, or if 0150 /// the receiver is not an array. 0151 func getDecimalNumber(index: Int) throws -> NSDecimalNumber { 0152 let array = try getArray() 0153 let value = try getRequired(array, index: index, type: .Number) 0154 return try scoped(index) { try value.getDecimalNumber() } 0155 } 0156 0157 /// Subscripts the receiver with `index` and returns the result as an `NSDecimalNumber`. 0158 /// - Parameter index: The index that's used to subscript the receiver. 0159 /// - Returns: An `NSDecimalNumber`, or `nil` if the index is out of bounds or the value is `null`. 0160 /// - Throws: `JSONError` if the value is the wrong type, or if the receiver is not an array. 0161 func getDecimalNumberOrNil(index: Int) throws -> NSDecimalNumber? { 0162 let array = try getArray() 0163 guard let value = array[safe: index] else { return nil } 0164 return try scoped(index) { try value.getDecimalNumberOrNil() } 0165 } 0166 0167 /// Subscripts the receiver with `index` and returns the result as an `NSDecimalNumber`. 0168 /// - Parameter index: The index that's used to subscript the receiver. 0169 /// - Returns: An `NSDecimalNumber`. 0170 /// - Throws: `JSONError` if the index is out of bounds or the value is `null`, a boolean, 0171 /// an object, an array, or a string that cannot be coerced to a decimal number, or 0172 /// if the receiver is not an array. 0173 func toDecimalNumber(index: Int) throws -> NSDecimalNumber { 0174 let array = try getArray() 0175 let value = try getRequired(array, index: index, type: .Number) 0176 return try scoped(index) { try value.toDecimalNumber() } 0177 } 0178 0179 /// Subscripts the receiver with `index` and returns the result as an `NSDecimalNumber`. 0180 /// - Parameter index: The index that's used to subscript the receiver. 0181 /// - Returns: An `NSDecimalNumber`, or `nil` if the index is out of bounds or the value is `null`. 0182 /// - Throws: `JSONError` if the value is a boolean, an object, an array, or a string that 0183 /// cannot be coerced to a decimal number, or if the receiver is not an array. 0184 func toDecimalNumberOrNil(index: Int) throws -> NSDecimalNumber? { 0185 let array = try getArray() 0186 guard let value = array[safe: index] else { return nil } 0187 return try scoped(index) { try value.toDecimalNumberOrNil() } 0188 } 0189 } 0190 0191 // MARK: - 0192 0193 public extension JSONObject { 0194 /// Subscripts the receiver with `key` and returns the result as an `NSDecimalNumber`. 0195 /// - Parameter key: The key that's used to subscript the receiver. 0196 /// - Returns: An `NSDecimalNumber`. 0197 /// - Throws: `JSONError` if the key doesn't exist or the value is the wrong type, or if 0198 /// the receiver is not an object. 0199 func getDecimalNumber(key: Swift.String) throws -> NSDecimalNumber { 0200 let value = try getRequired(self, key: key, type: .Number) 0201 return try scoped(key) { try value.getDecimalNumber() } 0202 } 0203 0204 /// Subscripts the receiver with `key` and returns the result as an `NSDecimalNumber`. 0205 /// - Parameter key: The key that's used to subscript the receiver. 0206 /// - Returns: An `NSDecimalNumber`, or `nil` if the key doesn't exist or the value is `null`. 0207 /// - Throws: `JSONError` if the value is the wrong type, or if the receiver is 0208 /// not an object. 0209 func getDecimalNumberOrNil(key: Swift.String) throws -> NSDecimalNumber? { 0210 guard let value = self[key] else { return nil } 0211 return try scoped(key) { try value.getDecimalNumberOrNil() } 0212 } 0213 0214 /// Subscripts the receiver with `key` and returns the result as an `NSDecimalNumber`. 0215 /// - Parameter key: The key that's used to subscript the receiver. 0216 /// - Returns: An `NSDecimalNumber`. 0217 /// - Throws: `JSONError` if the key doesn't exist or the value is `null`, a boolean, an object, 0218 /// an array, or a string that cannot be coerced to a decimal number, or if the 0219 /// receiver is not an object. 0220 func toDecimalNumber(key: Swift.String) throws -> NSDecimalNumber { 0221 let value = try getRequired(self, key: key, type: .Number) 0222 return try scoped(key) { try value.toDecimalNumber() } 0223 } 0224 0225 /// Subscripts the receiver with `key` and returns the result as an `NSDecimalNumber`. 0226 /// - Parameter key: The key that's used to subscript the receiver. 0227 /// - Returns: An `NSDecimalNumber`, or `nil` if the key doesn't exist or the value is `null`. 0228 /// - Throws: `JSONError` if the value is a boolean, an object, an array, or a string that 0229 /// cannot be coerced to a decimal number, or if the receiver is not an object. 0230 func toDecimalNumberOrNil(key: Swift.String) throws -> NSDecimalNumber? { 0231 guard let value = self[key] else { return nil } 0232 return try scoped(key) { try value.toDecimalNumberOrNil() } 0233 } 0234 } 0235 0236 #endif // os(iOS) || os(OSX) || os(tvOS) || os(watchOS) 0237
DecimalNumber.swift:139 return try scoped(key) { try value.toDecimalNumberOrNil() }DecimalNumber.swift:187 return try scoped(index) { try value.toDecimalNumberOrNil() }DecimalNumber.swift:232 return try scoped(key) { try value.toDecimalNumberOrNil() }