BSON.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2020 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. import Realm
  19. /// Protocol representing a BSON value.
  20. /// - SeeAlso: bsonspec.org
  21. public protocol BSON: Equatable {
  22. }
  23. extension NSNull: BSON {
  24. }
  25. extension Int: BSON {
  26. }
  27. extension Int32: BSON {
  28. }
  29. extension Int64: BSON {
  30. }
  31. extension Bool: BSON {
  32. }
  33. extension Double: BSON {
  34. }
  35. extension String: BSON {
  36. }
  37. extension Data: BSON {
  38. }
  39. extension Date: BSON {
  40. }
  41. extension Decimal128: BSON {
  42. }
  43. extension ObjectId: BSON {
  44. }
  45. /// A Dictionary object representing a `BSON` document.
  46. public typealias Document = Dictionary<String, AnyBSON?>
  47. extension Dictionary: BSON where Key == String, Value == AnyBSON? {
  48. }
  49. extension Array: BSON where Element == AnyBSON? {
  50. }
  51. extension NSRegularExpression: BSON {
  52. }
  53. /// MaxKey will always be the greatest value when comparing to other BSON types
  54. public typealias MaxKey = RLMMaxKey
  55. extension MaxKey: BSON {
  56. }
  57. /// MinKey will always be the smallest value when comparing to other BSON types
  58. public typealias MinKey = RLMMinKey
  59. extension MinKey: BSON {
  60. }
  61. /// Enum representing a BSON value.
  62. /// - SeeAlso: bsonspec.org
  63. @frozen public enum AnyBSON: BSON {
  64. /// A BSON double.
  65. case double(Double)
  66. /// A BSON string.
  67. /// - SeeAlso: https://docs.mongodb.com/manual/reference/bson-types/#string
  68. case string(String)
  69. /// A BSON document.
  70. indirect case document(Document)
  71. /// A BSON array.
  72. indirect case array([AnyBSON?])
  73. /// A BSON binary.
  74. case binary(Data)
  75. /// A BSON ObjectId.
  76. /// - SeeAlso: https://docs.mongodb.com/manual/reference/bson-types/#objectid
  77. case objectId(ObjectId)
  78. /// A BSON boolean.
  79. case bool(Bool)
  80. /// A BSON UTC datetime.
  81. /// - SeeAlso: https://docs.mongodb.com/manual/reference/bson-types/#date
  82. case datetime(Date)
  83. /// A BSON regular expression.
  84. case regex(NSRegularExpression)
  85. /// A BSON int32.
  86. case int32(Int32)
  87. /// A BSON timestamp.
  88. /// - SeeAlso: https://docs.mongodb.com/manual/reference/bson-types/#timestamps
  89. case timestamp(Date)
  90. /// A BSON int64.
  91. case int64(Int64)
  92. /// A BSON Decimal128.
  93. /// - SeeAlso: https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.rst
  94. case decimal128(Decimal128)
  95. /// A BSON minKey.
  96. case minKey
  97. /// A BSON maxKey.
  98. case maxKey
  99. /// A BSON null type.
  100. case null
  101. /// Initialize a `BSON` from an integer. On 64-bit systems, this will result in an `.int64`. On 32-bit systems,
  102. /// this will result in an `.int32`.
  103. public init(_ int: Int) {
  104. if MemoryLayout<Int>.size == 4 {
  105. self = .int32(Int32(int))
  106. } else {
  107. self = .int64(Int64(int))
  108. }
  109. }
  110. /// Initialize a `BSON` from a type `T`. If this is not a valid `BSON` type,
  111. /// if will be considered `BSON` null type and will return `nil`.
  112. public init<T: BSON>(_ bson: T) {
  113. switch bson {
  114. case let val as Int:
  115. self = .int64(Int64(val))
  116. case let val as Int32:
  117. self = .int32(val)
  118. case let val as Int64:
  119. self = .int64(val)
  120. case let val as Double:
  121. self = .double(val)
  122. case let val as String:
  123. self = .string(val)
  124. case let val as Data:
  125. self = .binary(val)
  126. case let val as Date:
  127. self = .datetime(val)
  128. case let val as Decimal128:
  129. self = .decimal128(val)
  130. case let val as ObjectId:
  131. self = .objectId(val)
  132. case let val as Document:
  133. self = .document(val)
  134. case let val as Array<AnyBSON?>:
  135. self = .array(val)
  136. case let val as Bool:
  137. self = .bool(val)
  138. case is MaxKey:
  139. self = .maxKey
  140. case is MinKey:
  141. self = .minKey
  142. case let val as NSRegularExpression:
  143. self = .regex(val)
  144. default:
  145. self = .null
  146. }
  147. }
  148. /// If this `BSON` is an `.int32`, return it as an `Int32`. Otherwise, return nil.
  149. public var int32Value: Int32? {
  150. guard case let .int32(i) = self else {
  151. return nil
  152. }
  153. return i
  154. }
  155. /// If this `BSON` is a `.regex`, return it as a `RegularExpression`. Otherwise, return nil.
  156. public var regexValue: NSRegularExpression? {
  157. guard case let .regex(r) = self else {
  158. return nil
  159. }
  160. return r
  161. }
  162. /// If this `BSON` is an `.int64`, return it as an `Int64`. Otherwise, return nil.
  163. public var int64Value: Int64? {
  164. guard case let .int64(i) = self else {
  165. return nil
  166. }
  167. return i
  168. }
  169. /// If this `BSON` is an `.objectId`, return it as an `ObjectId`. Otherwise, return nil.
  170. public var objectIdValue: ObjectId? {
  171. guard case let .objectId(o) = self else {
  172. return nil
  173. }
  174. return o
  175. }
  176. /// If this `BSON` is a `.date`, return it as a `Date`. Otherwise, return nil.
  177. public var dateValue: Date? {
  178. guard case let .datetime(d) = self else {
  179. return nil
  180. }
  181. return d
  182. }
  183. /// If this `BSON` is an `.array`, return it as an `[BSON]`. Otherwise, return nil.
  184. public var arrayValue: [AnyBSON?]? {
  185. guard case let .array(a) = self else {
  186. return nil
  187. }
  188. return a
  189. }
  190. /// If this `BSON` is a `.string`, return it as a `String`. Otherwise, return nil.
  191. public var stringValue: String? {
  192. guard case let .string(s) = self else {
  193. return nil
  194. }
  195. return s
  196. }
  197. /// If this `BSON` is a `.document`, return it as a `Document`. Otherwise, return nil.
  198. public var documentValue: Document? {
  199. guard case let .document(d) = self else {
  200. return nil
  201. }
  202. return d
  203. }
  204. /// If this `BSON` is a `.bool`, return it as an `Bool`. Otherwise, return nil.
  205. public var boolValue: Bool? {
  206. guard case let .bool(b) = self else {
  207. return nil
  208. }
  209. return b
  210. }
  211. /// If this `BSON` is a `.binary`, return it as a `Binary`. Otherwise, return nil.
  212. public var binaryValue: Data? {
  213. guard case let .binary(b) = self else {
  214. return nil
  215. }
  216. return b
  217. }
  218. /// If this `BSON` is a `.double`, return it as a `Double`. Otherwise, return nil.
  219. public var doubleValue: Double? {
  220. guard case let .double(d) = self else {
  221. return nil
  222. }
  223. return d
  224. }
  225. /// If this `BSON` is a `.decimal128`, return it as a `Decimal128`. Otherwise, return nil.
  226. public var decimal128Value: Decimal128? {
  227. guard case let .decimal128(d) = self else {
  228. return nil
  229. }
  230. return d
  231. }
  232. /// If this `BSON` is a `.timestamp`, return it as a `Timestamp`. Otherwise, return nil.
  233. public var timestampValue: Date? {
  234. guard case let .timestamp(t) = self else {
  235. return nil
  236. }
  237. return t
  238. }
  239. /// If this `BSON` is a `.null` return true. Otherwise, false.
  240. public var isNull: Bool {
  241. return self == .null
  242. }
  243. /// Return this BSON as an `Int` if possible.
  244. /// This will coerce non-integer numeric cases (e.g. `.double`) into an `Int` if such coercion would be lossless.
  245. public func asInt() -> Int? {
  246. switch self {
  247. case let .int32(value):
  248. return Int(value)
  249. case let .int64(value):
  250. return Int(exactly: value)
  251. case let .double(value):
  252. return Int(exactly: value)
  253. default:
  254. return nil
  255. }
  256. }
  257. /// Return this BSON as an `Int32` if possible.
  258. /// This will coerce numeric cases (e.g. `.double`) into an `Int32` if such coercion would be lossless.
  259. public func asInt32() -> Int32? {
  260. switch self {
  261. case let .int32(value):
  262. return value
  263. case let .int64(value):
  264. return Int32(exactly: value)
  265. case let .double(value):
  266. return Int32(exactly: value)
  267. default:
  268. return nil
  269. }
  270. }
  271. /// Return this BSON as an `Int64` if possible.
  272. /// This will coerce numeric cases (e.g. `.double`) into an `Int64` if such coercion would be lossless.
  273. public func asInt64() -> Int64? {
  274. switch self {
  275. case let .int32(value):
  276. return Int64(value)
  277. case let .int64(value):
  278. return value
  279. case let .double(value):
  280. return Int64(exactly: value)
  281. default:
  282. return nil
  283. }
  284. }
  285. /// Return this BSON as a `Double` if possible.
  286. /// This will coerce numeric cases (e.g. `.decimal128`) into a `Double` if such coercion would be lossless.
  287. public func asDouble() -> Double? {
  288. switch self {
  289. case let .double(d):
  290. return d
  291. default:
  292. guard let intValue = self.asInt() else {
  293. return nil
  294. }
  295. return Double(intValue)
  296. }
  297. }
  298. /// Return this BSON as a `Decimal128` if possible.
  299. /// This will coerce numeric cases (e.g. `.double`) into a `Decimal128` if such coercion would be lossless.
  300. public func asDecimal128() -> Decimal128? {
  301. switch self {
  302. case let .decimal128(d):
  303. return d
  304. case let .int64(i):
  305. return try? Decimal128(string: String(i))
  306. case let .int32(i):
  307. return try? Decimal128(string: String(i))
  308. case let .double(d):
  309. return try? Decimal128(string: String(d))
  310. default:
  311. return nil
  312. }
  313. }
  314. /// Return this BSON as a `T` if possible, otherwise nil.
  315. public func value<T: BSON>() -> T? {
  316. switch self {
  317. case .int32(let val):
  318. if T.self == Int.self && MemoryLayout<Int>.size == 4 {
  319. return Int(val) as? T
  320. }
  321. return val as? T
  322. case .int64(let val):
  323. if T.self == Int.self && MemoryLayout<Int>.size != 4 {
  324. return Int(val) as? T
  325. }
  326. return val as? T
  327. case .bool(let val):
  328. return val as? T
  329. case .double(let val):
  330. return val as? T
  331. case .string(let val):
  332. return val as? T
  333. case .binary(let val):
  334. return val as? T
  335. case .datetime(let val):
  336. return val as? T
  337. case .decimal128(let val):
  338. return val as? T
  339. case .objectId(let val):
  340. return val as? T
  341. case .document(let val):
  342. return val as? T
  343. case .array(let val):
  344. return val as? T
  345. case .maxKey:
  346. return MaxKey() as? T
  347. case .minKey:
  348. return MinKey() as? T
  349. case .regex(let val):
  350. return val as? T
  351. default:
  352. return nil
  353. }
  354. }
  355. }
  356. extension AnyBSON: ExpressibleByStringLiteral {
  357. public init(stringLiteral value: String) {
  358. self = .string(value)
  359. }
  360. }
  361. extension AnyBSON: ExpressibleByBooleanLiteral {
  362. public init(booleanLiteral value: Bool) {
  363. self = .bool(value)
  364. }
  365. }
  366. extension AnyBSON: ExpressibleByFloatLiteral {
  367. public init(floatLiteral value: Double) {
  368. self = .double(value)
  369. }
  370. }
  371. extension AnyBSON: ExpressibleByIntegerLiteral {
  372. /// Initialize a `BSON` from an integer. On 64-bit systems, this will result in an `.int64`. On 32-bit systems,
  373. /// this will result in an `.int32`.
  374. public init(integerLiteral value: Int) {
  375. self.init(value)
  376. }
  377. }
  378. extension AnyBSON: ExpressibleByDictionaryLiteral {
  379. public init(dictionaryLiteral elements: (String, AnyBSON?)...) {
  380. self = .document(Document(uniqueKeysWithValues: elements))
  381. }
  382. }
  383. extension AnyBSON: ExpressibleByArrayLiteral {
  384. public init(arrayLiteral elements: AnyBSON?...) {
  385. self = .array(elements)
  386. }
  387. }
  388. extension AnyBSON: Equatable {}
  389. extension AnyBSON: Hashable {}