本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

482 lines
12KB

  1. // Copyright (C) MongoDB, Inc. 2017-present.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"); you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  6. package bsonrw
  7. import (
  8. "encoding/base64"
  9. "errors"
  10. "fmt"
  11. "math"
  12. "strconv"
  13. "time"
  14. "go.mongodb.org/mongo-driver/bson/bsontype"
  15. "go.mongodb.org/mongo-driver/bson/primitive"
  16. )
  17. func wrapperKeyBSONType(key string) bsontype.Type {
  18. switch string(key) {
  19. case "$numberInt":
  20. return bsontype.Int32
  21. case "$numberLong":
  22. return bsontype.Int64
  23. case "$oid":
  24. return bsontype.ObjectID
  25. case "$symbol":
  26. return bsontype.Symbol
  27. case "$numberDouble":
  28. return bsontype.Double
  29. case "$numberDecimal":
  30. return bsontype.Decimal128
  31. case "$binary":
  32. return bsontype.Binary
  33. case "$code":
  34. return bsontype.JavaScript
  35. case "$scope":
  36. return bsontype.CodeWithScope
  37. case "$timestamp":
  38. return bsontype.Timestamp
  39. case "$regularExpression":
  40. return bsontype.Regex
  41. case "$dbPointer":
  42. return bsontype.DBPointer
  43. case "$date":
  44. return bsontype.DateTime
  45. case "$ref":
  46. fallthrough
  47. case "$id":
  48. fallthrough
  49. case "$db":
  50. return bsontype.EmbeddedDocument // dbrefs aren't bson types
  51. case "$minKey":
  52. return bsontype.MinKey
  53. case "$maxKey":
  54. return bsontype.MaxKey
  55. case "$undefined":
  56. return bsontype.Undefined
  57. }
  58. return bsontype.EmbeddedDocument
  59. }
  60. func (ejv *extJSONValue) parseBinary() (b []byte, subType byte, err error) {
  61. if ejv.t != bsontype.EmbeddedDocument {
  62. return nil, 0, fmt.Errorf("$binary value should be object, but instead is %s", ejv.t)
  63. }
  64. binObj := ejv.v.(*extJSONObject)
  65. bFound := false
  66. stFound := false
  67. for i, key := range binObj.keys {
  68. val := binObj.values[i]
  69. switch key {
  70. case "base64":
  71. if bFound {
  72. return nil, 0, errors.New("duplicate base64 key in $binary")
  73. }
  74. if val.t != bsontype.String {
  75. return nil, 0, fmt.Errorf("$binary base64 value should be string, but instead is %s", val.t)
  76. }
  77. base64Bytes, err := base64.StdEncoding.DecodeString(val.v.(string))
  78. if err != nil {
  79. return nil, 0, fmt.Errorf("invalid $binary base64 string: %s", val.v.(string))
  80. }
  81. b = base64Bytes
  82. bFound = true
  83. case "subType":
  84. if stFound {
  85. return nil, 0, errors.New("duplicate subType key in $binary")
  86. }
  87. if val.t != bsontype.String {
  88. return nil, 0, fmt.Errorf("$binary subType value should be string, but instead is %s", val.t)
  89. }
  90. i, err := strconv.ParseInt(val.v.(string), 16, 64)
  91. if err != nil {
  92. return nil, 0, fmt.Errorf("invalid $binary subType string: %s", val.v.(string))
  93. }
  94. subType = byte(i)
  95. stFound = true
  96. default:
  97. return nil, 0, fmt.Errorf("invalid key in $binary object: %s", key)
  98. }
  99. }
  100. if !bFound {
  101. return nil, 0, errors.New("missing base64 field in $binary object")
  102. }
  103. if !stFound {
  104. return nil, 0, errors.New("missing subType field in $binary object")
  105. }
  106. return b, subType, nil
  107. }
  108. func (ejv *extJSONValue) parseDBPointer() (ns string, oid primitive.ObjectID, err error) {
  109. if ejv.t != bsontype.EmbeddedDocument {
  110. return "", primitive.NilObjectID, fmt.Errorf("$dbPointer value should be object, but instead is %s", ejv.t)
  111. }
  112. dbpObj := ejv.v.(*extJSONObject)
  113. oidFound := false
  114. nsFound := false
  115. for i, key := range dbpObj.keys {
  116. val := dbpObj.values[i]
  117. switch key {
  118. case "$ref":
  119. if nsFound {
  120. return "", primitive.NilObjectID, errors.New("duplicate $ref key in $dbPointer")
  121. }
  122. if val.t != bsontype.String {
  123. return "", primitive.NilObjectID, fmt.Errorf("$dbPointer $ref value should be string, but instead is %s", val.t)
  124. }
  125. ns = val.v.(string)
  126. nsFound = true
  127. case "$id":
  128. if oidFound {
  129. return "", primitive.NilObjectID, errors.New("duplicate $id key in $dbPointer")
  130. }
  131. if val.t != bsontype.String {
  132. return "", primitive.NilObjectID, fmt.Errorf("$dbPointer $id value should be string, but instead is %s", val.t)
  133. }
  134. oid, err = primitive.ObjectIDFromHex(val.v.(string))
  135. if err != nil {
  136. return "", primitive.NilObjectID, err
  137. }
  138. oidFound = true
  139. default:
  140. return "", primitive.NilObjectID, fmt.Errorf("invalid key in $dbPointer object: %s", key)
  141. }
  142. }
  143. if !nsFound {
  144. return "", oid, errors.New("missing $ref field in $dbPointer object")
  145. }
  146. if !oidFound {
  147. return "", oid, errors.New("missing $id field in $dbPointer object")
  148. }
  149. return ns, oid, nil
  150. }
  151. const rfc3339Milli = "2006-01-02T15:04:05.999Z07:00"
  152. func (ejv *extJSONValue) parseDateTime() (int64, error) {
  153. switch ejv.t {
  154. case bsontype.Int32:
  155. return int64(ejv.v.(int32)), nil
  156. case bsontype.Int64:
  157. return ejv.v.(int64), nil
  158. case bsontype.String:
  159. return parseDatetimeString(ejv.v.(string))
  160. case bsontype.EmbeddedDocument:
  161. return parseDatetimeObject(ejv.v.(*extJSONObject))
  162. default:
  163. return 0, fmt.Errorf("$date value should be string or object, but instead is %s", ejv.t)
  164. }
  165. }
  166. func parseDatetimeString(data string) (int64, error) {
  167. t, err := time.Parse(rfc3339Milli, data)
  168. if err != nil {
  169. return 0, fmt.Errorf("invalid $date value string: %s", data)
  170. }
  171. return t.Unix()*1e3 + int64(t.Nanosecond())/1e6, nil
  172. }
  173. func parseDatetimeObject(data *extJSONObject) (d int64, err error) {
  174. dFound := false
  175. for i, key := range data.keys {
  176. val := data.values[i]
  177. switch key {
  178. case "$numberLong":
  179. if dFound {
  180. return 0, errors.New("duplicate $numberLong key in $date")
  181. }
  182. if val.t != bsontype.String {
  183. return 0, fmt.Errorf("$date $numberLong field should be string, but instead is %s", val.t)
  184. }
  185. d, err = val.parseInt64()
  186. if err != nil {
  187. return 0, err
  188. }
  189. dFound = true
  190. default:
  191. return 0, fmt.Errorf("invalid key in $date object: %s", key)
  192. }
  193. }
  194. if !dFound {
  195. return 0, errors.New("missing $numberLong field in $date object")
  196. }
  197. return d, nil
  198. }
  199. func (ejv *extJSONValue) parseDecimal128() (primitive.Decimal128, error) {
  200. if ejv.t != bsontype.String {
  201. return primitive.Decimal128{}, fmt.Errorf("$numberDecimal value should be string, but instead is %s", ejv.t)
  202. }
  203. d, err := primitive.ParseDecimal128(ejv.v.(string))
  204. if err != nil {
  205. return primitive.Decimal128{}, fmt.Errorf("$invalid $numberDecimal string: %s", ejv.v.(string))
  206. }
  207. return d, nil
  208. }
  209. func (ejv *extJSONValue) parseDouble() (float64, error) {
  210. if ejv.t == bsontype.Double {
  211. return ejv.v.(float64), nil
  212. }
  213. if ejv.t != bsontype.String {
  214. return 0, fmt.Errorf("$numberDouble value should be string, but instead is %s", ejv.t)
  215. }
  216. switch string(ejv.v.(string)) {
  217. case "Infinity":
  218. return math.Inf(1), nil
  219. case "-Infinity":
  220. return math.Inf(-1), nil
  221. case "NaN":
  222. return math.NaN(), nil
  223. }
  224. f, err := strconv.ParseFloat(ejv.v.(string), 64)
  225. if err != nil {
  226. return 0, err
  227. }
  228. return f, nil
  229. }
  230. func (ejv *extJSONValue) parseInt32() (int32, error) {
  231. if ejv.t == bsontype.Int32 {
  232. return ejv.v.(int32), nil
  233. }
  234. if ejv.t != bsontype.String {
  235. return 0, fmt.Errorf("$numberInt value should be string, but instead is %s", ejv.t)
  236. }
  237. i, err := strconv.ParseInt(ejv.v.(string), 10, 64)
  238. if err != nil {
  239. return 0, err
  240. }
  241. if i < math.MinInt32 || i > math.MaxInt32 {
  242. return 0, fmt.Errorf("$numberInt value should be int32 but instead is int64: %d", i)
  243. }
  244. return int32(i), nil
  245. }
  246. func (ejv *extJSONValue) parseInt64() (int64, error) {
  247. if ejv.t == bsontype.Int64 {
  248. return ejv.v.(int64), nil
  249. }
  250. if ejv.t != bsontype.String {
  251. return 0, fmt.Errorf("$numberLong value should be string, but instead is %s", ejv.t)
  252. }
  253. i, err := strconv.ParseInt(ejv.v.(string), 10, 64)
  254. if err != nil {
  255. return 0, err
  256. }
  257. return i, nil
  258. }
  259. func (ejv *extJSONValue) parseJavascript() (code string, err error) {
  260. if ejv.t != bsontype.String {
  261. return "", fmt.Errorf("$code value should be string, but instead is %s", ejv.t)
  262. }
  263. return ejv.v.(string), nil
  264. }
  265. func (ejv *extJSONValue) parseMinMaxKey(minmax string) error {
  266. if ejv.t != bsontype.Int32 {
  267. return fmt.Errorf("$%sKey value should be int32, but instead is %s", minmax, ejv.t)
  268. }
  269. if ejv.v.(int32) != 1 {
  270. return fmt.Errorf("$%sKey value must be 1, but instead is %d", minmax, ejv.v.(int32))
  271. }
  272. return nil
  273. }
  274. func (ejv *extJSONValue) parseObjectID() (primitive.ObjectID, error) {
  275. if ejv.t != bsontype.String {
  276. return primitive.NilObjectID, fmt.Errorf("$oid value should be string, but instead is %s", ejv.t)
  277. }
  278. return primitive.ObjectIDFromHex(ejv.v.(string))
  279. }
  280. func (ejv *extJSONValue) parseRegex() (pattern, options string, err error) {
  281. if ejv.t != bsontype.EmbeddedDocument {
  282. return "", "", fmt.Errorf("$regularExpression value should be object, but instead is %s", ejv.t)
  283. }
  284. regexObj := ejv.v.(*extJSONObject)
  285. patFound := false
  286. optFound := false
  287. for i, key := range regexObj.keys {
  288. val := regexObj.values[i]
  289. switch string(key) {
  290. case "pattern":
  291. if patFound {
  292. return "", "", errors.New("duplicate pattern key in $regularExpression")
  293. }
  294. if val.t != bsontype.String {
  295. return "", "", fmt.Errorf("$regularExpression pattern value should be string, but instead is %s", val.t)
  296. }
  297. pattern = val.v.(string)
  298. patFound = true
  299. case "options":
  300. if optFound {
  301. return "", "", errors.New("duplicate options key in $regularExpression")
  302. }
  303. if val.t != bsontype.String {
  304. return "", "", fmt.Errorf("$regularExpression options value should be string, but instead is %s", val.t)
  305. }
  306. options = val.v.(string)
  307. optFound = true
  308. default:
  309. return "", "", fmt.Errorf("invalid key in $regularExpression object: %s", key)
  310. }
  311. }
  312. if !patFound {
  313. return "", "", errors.New("missing pattern field in $regularExpression object")
  314. }
  315. if !optFound {
  316. return "", "", errors.New("missing options field in $regularExpression object")
  317. }
  318. return pattern, options, nil
  319. }
  320. func (ejv *extJSONValue) parseSymbol() (string, error) {
  321. if ejv.t != bsontype.String {
  322. return "", fmt.Errorf("$symbol value should be string, but instead is %s", ejv.t)
  323. }
  324. return ejv.v.(string), nil
  325. }
  326. func (ejv *extJSONValue) parseTimestamp() (t, i uint32, err error) {
  327. if ejv.t != bsontype.EmbeddedDocument {
  328. return 0, 0, fmt.Errorf("$timestamp value should be object, but instead is %s", ejv.t)
  329. }
  330. handleKey := func(key string, val *extJSONValue, flag bool) (uint32, error) {
  331. if flag {
  332. return 0, fmt.Errorf("duplicate %s key in $timestamp", key)
  333. }
  334. switch val.t {
  335. case bsontype.Int32:
  336. if val.v.(int32) < 0 {
  337. return 0, fmt.Errorf("$timestamp %s number should be uint32: %s", key, string(val.v.(int32)))
  338. }
  339. return uint32(val.v.(int32)), nil
  340. case bsontype.Int64:
  341. if val.v.(int64) < 0 || uint32(val.v.(int64)) > math.MaxUint32 {
  342. return 0, fmt.Errorf("$timestamp %s number should be uint32: %s", key, string(val.v.(int32)))
  343. }
  344. return uint32(val.v.(int64)), nil
  345. default:
  346. return 0, fmt.Errorf("$timestamp %s value should be uint32, but instead is %s", key, val.t)
  347. }
  348. }
  349. tsObj := ejv.v.(*extJSONObject)
  350. tFound := false
  351. iFound := false
  352. for j, key := range tsObj.keys {
  353. val := tsObj.values[j]
  354. switch key {
  355. case "t":
  356. if t, err = handleKey(key, val, tFound); err != nil {
  357. return 0, 0, err
  358. }
  359. tFound = true
  360. case "i":
  361. if i, err = handleKey(key, val, iFound); err != nil {
  362. return 0, 0, err
  363. }
  364. iFound = true
  365. default:
  366. return 0, 0, fmt.Errorf("invalid key in $timestamp object: %s", key)
  367. }
  368. }
  369. if !tFound {
  370. return 0, 0, errors.New("missing t field in $timestamp object")
  371. }
  372. if !iFound {
  373. return 0, 0, errors.New("missing i field in $timestamp object")
  374. }
  375. return t, i, nil
  376. }
  377. func (ejv *extJSONValue) parseUndefined() error {
  378. if ejv.t != bsontype.Boolean {
  379. return fmt.Errorf("undefined value should be boolean, but instead is %s", ejv.t)
  380. }
  381. if !ejv.v.(bool) {
  382. return fmt.Errorf("$undefined balue boolean should be true, but instead is %v", ejv.v.(bool))
  383. }
  384. return nil
  385. }
上海开阖软件有限公司 沪ICP备12045867号-1