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.

bsoncore.go 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  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 bsoncore contains functions that can be used to encode and decode BSON
  7. // elements and values to or from a slice of bytes. These functions are aimed at
  8. // allowing low level manipulation of BSON and can be used to build a higher
  9. // level BSON library.
  10. //
  11. // The Read* functions within this package return the values of the element and
  12. // a boolean indicating if the values are valid. A boolean was used instead of
  13. // an error because any error that would be returned would be the same: not
  14. // enough bytes. This library attempts to do no validation, it will only return
  15. // false if there are not enough bytes for an item to be read. For example, the
  16. // ReadDocument function checks the length, if that length is larger than the
  17. // number of bytes availble, it will return false, if there are enough bytes, it
  18. // will return those bytes and true. It is the consumers responsibility to
  19. // validate those bytes.
  20. //
  21. // The Append* functions within this package will append the type value to the
  22. // given dst slice. If the slice has enough capacity, it will not grow the
  23. // slice. The Append*Element functions within this package operate in the same
  24. // way, but additionally append the BSON type and the key before the value.
  25. package bsoncore // import "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
  26. import (
  27. "bytes"
  28. "fmt"
  29. "math"
  30. "strconv"
  31. "time"
  32. "go.mongodb.org/mongo-driver/bson/bsontype"
  33. "go.mongodb.org/mongo-driver/bson/primitive"
  34. )
  35. // EmptyDocumentLength is the length of a document that has been started/ended but has no elements.
  36. const EmptyDocumentLength = 5
  37. // AppendType will append t to dst and return the extended buffer.
  38. func AppendType(dst []byte, t bsontype.Type) []byte { return append(dst, byte(t)) }
  39. // AppendKey will append key to dst and return the extended buffer.
  40. func AppendKey(dst []byte, key string) []byte { return append(dst, key+string(0x00)...) }
  41. // AppendHeader will append Type t and key to dst and return the extended
  42. // buffer.
  43. func AppendHeader(dst []byte, t bsontype.Type, key string) []byte {
  44. dst = AppendType(dst, t)
  45. dst = append(dst, key...)
  46. return append(dst, 0x00)
  47. // return append(AppendType(dst, t), key+string(0x00)...)
  48. }
  49. // TODO(skriptble): All of the Read* functions should return src resliced to start just after what
  50. // was read.
  51. // ReadType will return the first byte of the provided []byte as a type. If
  52. // there is no availble byte, false is returned.
  53. func ReadType(src []byte) (bsontype.Type, []byte, bool) {
  54. if len(src) < 1 {
  55. return 0, src, false
  56. }
  57. return bsontype.Type(src[0]), src[1:], true
  58. }
  59. // ReadKey will read a key from src. The 0x00 byte will not be present
  60. // in the returned string. If there are not enough bytes available, false is
  61. // returned.
  62. func ReadKey(src []byte) (string, []byte, bool) { return readcstring(src) }
  63. // ReadKeyBytes will read a key from src as bytes. The 0x00 byte will
  64. // not be present in the returned string. If there are not enough bytes
  65. // available, false is returned.
  66. func ReadKeyBytes(src []byte) ([]byte, []byte, bool) { return readcstringbytes(src) }
  67. // ReadHeader will read a type byte and a key from src. If both of these
  68. // values cannot be read, false is returned.
  69. func ReadHeader(src []byte) (t bsontype.Type, key string, rem []byte, ok bool) {
  70. t, rem, ok = ReadType(src)
  71. if !ok {
  72. return 0, "", src, false
  73. }
  74. key, rem, ok = ReadKey(rem)
  75. if !ok {
  76. return 0, "", src, false
  77. }
  78. return t, key, rem, true
  79. }
  80. // ReadHeaderBytes will read a type and a key from src and the remainder of the bytes
  81. // are returned as rem. If either the type or key cannot be red, ok will be false.
  82. func ReadHeaderBytes(src []byte) (header []byte, rem []byte, ok bool) {
  83. if len(src) < 1 {
  84. return nil, src, false
  85. }
  86. idx := bytes.IndexByte(src[1:], 0x00)
  87. if idx == -1 {
  88. return nil, src, false
  89. }
  90. return src[:idx], src[idx+1:], true
  91. }
  92. // ReadElement reads the next full element from src. It returns the element, the remaining bytes in
  93. // the slice, and a boolean indicating if the read was successful.
  94. func ReadElement(src []byte) (Element, []byte, bool) {
  95. if len(src) < 1 {
  96. return nil, src, false
  97. }
  98. t := bsontype.Type(src[0])
  99. idx := bytes.IndexByte(src[1:], 0x00)
  100. if idx == -1 {
  101. return nil, src, false
  102. }
  103. length, ok := valueLength(src[idx+2:], t) // We add 2 here because we called IndexByte with src[1:]
  104. if !ok {
  105. return nil, src, false
  106. }
  107. elemLength := 1 + idx + 1 + int(length)
  108. if elemLength > len(src) {
  109. return nil, src, false
  110. }
  111. return src[:elemLength], src[elemLength:], true
  112. }
  113. // AppendValueElement appends value to dst as an element using key as the element's key.
  114. func AppendValueElement(dst []byte, key string, value Value) []byte {
  115. dst = AppendHeader(dst, value.Type, key)
  116. dst = append(dst, value.Data...)
  117. return dst
  118. }
  119. // ReadValue reads the next value as the provided types and returns a Value, the remaining bytes,
  120. // and a boolean indicating if the read was successful.
  121. func ReadValue(src []byte, t bsontype.Type) (Value, []byte, bool) {
  122. data, rem, ok := readValue(src, t)
  123. if !ok {
  124. return Value{}, src, false
  125. }
  126. return Value{Type: t, Data: data}, rem, true
  127. }
  128. // AppendDouble will append f to dst and return the extended buffer.
  129. func AppendDouble(dst []byte, f float64) []byte {
  130. return appendu64(dst, math.Float64bits(f))
  131. }
  132. // AppendDoubleElement will append a BSON double element using key and f to dst
  133. // and return the extended buffer.
  134. func AppendDoubleElement(dst []byte, key string, f float64) []byte {
  135. return AppendDouble(AppendHeader(dst, bsontype.Double, key), f)
  136. }
  137. // ReadDouble will read a float64 from src. If there are not enough bytes it
  138. // will return false.
  139. func ReadDouble(src []byte) (float64, []byte, bool) {
  140. bits, src, ok := readu64(src)
  141. if !ok {
  142. return 0, src, false
  143. }
  144. return math.Float64frombits(bits), src, true
  145. }
  146. // AppendString will append s to dst and return the extended buffer.
  147. func AppendString(dst []byte, s string) []byte {
  148. return appendstring(dst, s)
  149. }
  150. // AppendStringElement will append a BSON string element using key and val to dst
  151. // and return the extended buffer.
  152. func AppendStringElement(dst []byte, key, val string) []byte {
  153. return AppendString(AppendHeader(dst, bsontype.String, key), val)
  154. }
  155. // ReadString will read a string from src. If there are not enough bytes it
  156. // will return false.
  157. func ReadString(src []byte) (string, []byte, bool) {
  158. return readstring(src)
  159. }
  160. // AppendDocumentStart reserves a document's length and returns the index where the length begins.
  161. // This index can later be used to write the length of the document.
  162. //
  163. // TODO(skriptble): We really need AppendDocumentStart and AppendDocumentEnd.
  164. // AppendDocumentStart would handle calling ReserveLength and providing the index of the start of
  165. // the document. AppendDocumentEnd would handle taking that start index, adding the null byte,
  166. // calculating the length, and filling in the length at the start of the document.
  167. func AppendDocumentStart(dst []byte) (index int32, b []byte) { return ReserveLength(dst) }
  168. // AppendDocumentStartInline functions the same as AppendDocumentStart but takes a pointer to the
  169. // index int32 which allows this function to be used inline.
  170. func AppendDocumentStartInline(dst []byte, index *int32) []byte {
  171. idx, doc := AppendDocumentStart(dst)
  172. *index = idx
  173. return doc
  174. }
  175. // AppendDocumentElementStart writes a document element header and then reserves the length bytes.
  176. func AppendDocumentElementStart(dst []byte, key string) (index int32, b []byte) {
  177. return AppendDocumentStart(AppendHeader(dst, bsontype.EmbeddedDocument, key))
  178. }
  179. // AppendDocumentEnd writes the null byte for a document and updates the length of the document.
  180. // The index should be the beginning of the document's length bytes.
  181. func AppendDocumentEnd(dst []byte, index int32) ([]byte, error) {
  182. if int(index) > len(dst)-4 {
  183. return dst, fmt.Errorf("not enough bytes available after index to write length")
  184. }
  185. dst = append(dst, 0x00)
  186. dst = UpdateLength(dst, index, int32(len(dst[index:])))
  187. return dst, nil
  188. }
  189. // AppendDocument will append doc to dst and return the extended buffer.
  190. func AppendDocument(dst []byte, doc []byte) []byte { return append(dst, doc...) }
  191. // AppendDocumentElement will append a BSON embeded document element using key
  192. // and doc to dst and return the extended buffer.
  193. func AppendDocumentElement(dst []byte, key string, doc []byte) []byte {
  194. return AppendDocument(AppendHeader(dst, bsontype.EmbeddedDocument, key), doc)
  195. }
  196. // BuildDocument will create a document with the given slice of elements and will append
  197. // it to dst and return the extended buffer.
  198. func BuildDocument(dst []byte, elems ...[]byte) []byte {
  199. idx, dst := ReserveLength(dst)
  200. for _, elem := range elems {
  201. dst = append(dst, elem...)
  202. }
  203. dst = append(dst, 0x00)
  204. dst = UpdateLength(dst, idx, int32(len(dst[idx:])))
  205. return dst
  206. }
  207. // BuildDocumentValue creates an Embedded Document value from the given elements.
  208. func BuildDocumentValue(elems ...[]byte) Value {
  209. return Value{Type: bsontype.EmbeddedDocument, Data: BuildDocument(nil, elems...)}
  210. }
  211. // BuildDocumentElement will append a BSON embedded document elemnt using key and the provided
  212. // elements and return the extended buffer.
  213. func BuildDocumentElement(dst []byte, key string, elems ...[]byte) []byte {
  214. return BuildDocument(AppendHeader(dst, bsontype.EmbeddedDocument, key), elems...)
  215. }
  216. // BuildDocumentFromElements is an alaias for the BuildDocument function.
  217. var BuildDocumentFromElements = BuildDocument
  218. // ReadDocument will read a document from src. If there are not enough bytes it
  219. // will return false.
  220. func ReadDocument(src []byte) (doc Document, rem []byte, ok bool) { return readLengthBytes(src) }
  221. // AppendArrayStart appends the length bytes to an array and then returns the index of the start
  222. // of those length bytes.
  223. func AppendArrayStart(dst []byte) (index int32, b []byte) { return ReserveLength(dst) }
  224. // AppendArrayElementStart appends an array element header and then the length bytes for an array,
  225. // returning the index where the length starts.
  226. func AppendArrayElementStart(dst []byte, key string) (index int32, b []byte) {
  227. return AppendArrayStart(AppendHeader(dst, bsontype.Array, key))
  228. }
  229. // AppendArrayEnd appends the null byte to an array and calculates the length, inserting that
  230. // calculated length starting at index.
  231. func AppendArrayEnd(dst []byte, index int32) ([]byte, error) { return AppendDocumentEnd(dst, index) }
  232. // AppendArray will append arr to dst and return the extended buffer.
  233. func AppendArray(dst []byte, arr []byte) []byte { return append(dst, arr...) }
  234. // AppendArrayElement will append a BSON array element using key and arr to dst
  235. // and return the extended buffer.
  236. func AppendArrayElement(dst []byte, key string, arr []byte) []byte {
  237. return AppendArray(AppendHeader(dst, bsontype.Array, key), arr)
  238. }
  239. // BuildArray will append a BSON array to dst built from values.
  240. func BuildArray(dst []byte, values ...Value) []byte {
  241. idx, dst := ReserveLength(dst)
  242. for pos, val := range values {
  243. dst = AppendValueElement(dst, strconv.Itoa(pos), val)
  244. }
  245. dst = append(dst, 0x00)
  246. dst = UpdateLength(dst, idx, int32(len(dst[idx:])))
  247. return dst
  248. }
  249. // BuildArrayElement will create an array element using the provided values.
  250. func BuildArrayElement(dst []byte, key string, values ...Value) []byte {
  251. return BuildArray(AppendHeader(dst, bsontype.Array, key), values...)
  252. }
  253. // ReadArray will read an array from src. If there are not enough bytes it
  254. // will return false.
  255. func ReadArray(src []byte) (arr Document, rem []byte, ok bool) { return readLengthBytes(src) }
  256. // AppendBinary will append subtype and b to dst and return the extended buffer.
  257. func AppendBinary(dst []byte, subtype byte, b []byte) []byte {
  258. if subtype == 0x02 {
  259. return appendBinarySubtype2(dst, subtype, b)
  260. }
  261. dst = append(appendLength(dst, int32(len(b))), subtype)
  262. return append(dst, b...)
  263. }
  264. // AppendBinaryElement will append a BSON binary element using key, subtype, and
  265. // b to dst and return the extended buffer.
  266. func AppendBinaryElement(dst []byte, key string, subtype byte, b []byte) []byte {
  267. return AppendBinary(AppendHeader(dst, bsontype.Binary, key), subtype, b)
  268. }
  269. // ReadBinary will read a subtype and bin from src. If there are not enough bytes it
  270. // will return false.
  271. func ReadBinary(src []byte) (subtype byte, bin []byte, rem []byte, ok bool) {
  272. length, rem, ok := ReadLength(src)
  273. if !ok {
  274. return 0x00, nil, src, false
  275. }
  276. if len(rem) < 1 { // subtype
  277. return 0x00, nil, src, false
  278. }
  279. subtype, rem = rem[0], rem[1:]
  280. if len(rem) < int(length) {
  281. return 0x00, nil, src, false
  282. }
  283. if subtype == 0x02 {
  284. length, rem, ok = ReadLength(rem)
  285. if !ok || len(rem) < int(length) {
  286. return 0x00, nil, src, false
  287. }
  288. }
  289. return subtype, rem[:length], rem[length:], true
  290. }
  291. // AppendUndefinedElement will append a BSON undefined element using key to dst
  292. // and return the extended buffer.
  293. func AppendUndefinedElement(dst []byte, key string) []byte {
  294. return AppendHeader(dst, bsontype.Undefined, key)
  295. }
  296. // AppendObjectID will append oid to dst and return the extended buffer.
  297. func AppendObjectID(dst []byte, oid primitive.ObjectID) []byte { return append(dst, oid[:]...) }
  298. // AppendObjectIDElement will append a BSON ObjectID element using key and oid to dst
  299. // and return the extended buffer.
  300. func AppendObjectIDElement(dst []byte, key string, oid primitive.ObjectID) []byte {
  301. return AppendObjectID(AppendHeader(dst, bsontype.ObjectID, key), oid)
  302. }
  303. // ReadObjectID will read an ObjectID from src. If there are not enough bytes it
  304. // will return false.
  305. func ReadObjectID(src []byte) (primitive.ObjectID, []byte, bool) {
  306. if len(src) < 12 {
  307. return primitive.ObjectID{}, src, false
  308. }
  309. var oid primitive.ObjectID
  310. copy(oid[:], src[0:12])
  311. return oid, src[12:], true
  312. }
  313. // AppendBoolean will append b to dst and return the extended buffer.
  314. func AppendBoolean(dst []byte, b bool) []byte {
  315. if b {
  316. return append(dst, 0x01)
  317. }
  318. return append(dst, 0x00)
  319. }
  320. // AppendBooleanElement will append a BSON boolean element using key and b to dst
  321. // and return the extended buffer.
  322. func AppendBooleanElement(dst []byte, key string, b bool) []byte {
  323. return AppendBoolean(AppendHeader(dst, bsontype.Boolean, key), b)
  324. }
  325. // ReadBoolean will read a bool from src. If there are not enough bytes it
  326. // will return false.
  327. func ReadBoolean(src []byte) (bool, []byte, bool) {
  328. if len(src) < 1 {
  329. return false, src, false
  330. }
  331. return src[0] == 0x01, src[1:], true
  332. }
  333. // AppendDateTime will append dt to dst and return the extended buffer.
  334. func AppendDateTime(dst []byte, dt int64) []byte { return appendi64(dst, dt) }
  335. // AppendDateTimeElement will append a BSON datetime element using key and dt to dst
  336. // and return the extended buffer.
  337. func AppendDateTimeElement(dst []byte, key string, dt int64) []byte {
  338. return AppendDateTime(AppendHeader(dst, bsontype.DateTime, key), dt)
  339. }
  340. // ReadDateTime will read an int64 datetime from src. If there are not enough bytes it
  341. // will return false.
  342. func ReadDateTime(src []byte) (int64, []byte, bool) { return readi64(src) }
  343. // AppendTime will append time as a BSON DateTime to dst and return the extended buffer.
  344. func AppendTime(dst []byte, t time.Time) []byte {
  345. return AppendDateTime(dst, t.Unix()*1000+int64(t.Nanosecond()/1e6))
  346. }
  347. // AppendTimeElement will append a BSON datetime element using key and dt to dst
  348. // and return the extended buffer.
  349. func AppendTimeElement(dst []byte, key string, t time.Time) []byte {
  350. return AppendTime(AppendHeader(dst, bsontype.DateTime, key), t)
  351. }
  352. // ReadTime will read an time.Time datetime from src. If there are not enough bytes it
  353. // will return false.
  354. func ReadTime(src []byte) (time.Time, []byte, bool) {
  355. dt, rem, ok := readi64(src)
  356. return time.Unix(dt/1e3, dt%1e3*1e6), rem, ok
  357. }
  358. // AppendNullElement will append a BSON null element using key to dst
  359. // and return the extended buffer.
  360. func AppendNullElement(dst []byte, key string) []byte { return AppendHeader(dst, bsontype.Null, key) }
  361. // AppendRegex will append pattern and options to dst and return the extended buffer.
  362. func AppendRegex(dst []byte, pattern, options string) []byte {
  363. return append(dst, pattern+string(0x00)+options+string(0x00)...)
  364. }
  365. // AppendRegexElement will append a BSON regex element using key, pattern, and
  366. // options to dst and return the extended buffer.
  367. func AppendRegexElement(dst []byte, key, pattern, options string) []byte {
  368. return AppendRegex(AppendHeader(dst, bsontype.Regex, key), pattern, options)
  369. }
  370. // ReadRegex will read a pattern and options from src. If there are not enough bytes it
  371. // will return false.
  372. func ReadRegex(src []byte) (pattern, options string, rem []byte, ok bool) {
  373. pattern, rem, ok = readcstring(src)
  374. if !ok {
  375. return "", "", src, false
  376. }
  377. options, rem, ok = readcstring(rem)
  378. if !ok {
  379. return "", "", src, false
  380. }
  381. return pattern, options, rem, true
  382. }
  383. // AppendDBPointer will append ns and oid to dst and return the extended buffer.
  384. func AppendDBPointer(dst []byte, ns string, oid primitive.ObjectID) []byte {
  385. return append(appendstring(dst, ns), oid[:]...)
  386. }
  387. // AppendDBPointerElement will append a BSON DBPointer element using key, ns,
  388. // and oid to dst and return the extended buffer.
  389. func AppendDBPointerElement(dst []byte, key, ns string, oid primitive.ObjectID) []byte {
  390. return AppendDBPointer(AppendHeader(dst, bsontype.DBPointer, key), ns, oid)
  391. }
  392. // ReadDBPointer will read a ns and oid from src. If there are not enough bytes it
  393. // will return false.
  394. func ReadDBPointer(src []byte) (ns string, oid primitive.ObjectID, rem []byte, ok bool) {
  395. ns, rem, ok = readstring(src)
  396. if !ok {
  397. return "", primitive.ObjectID{}, src, false
  398. }
  399. oid, rem, ok = ReadObjectID(rem)
  400. if !ok {
  401. return "", primitive.ObjectID{}, src, false
  402. }
  403. return ns, oid, rem, true
  404. }
  405. // AppendJavaScript will append js to dst and return the extended buffer.
  406. func AppendJavaScript(dst []byte, js string) []byte { return appendstring(dst, js) }
  407. // AppendJavaScriptElement will append a BSON JavaScript element using key and
  408. // js to dst and return the extended buffer.
  409. func AppendJavaScriptElement(dst []byte, key, js string) []byte {
  410. return AppendJavaScript(AppendHeader(dst, bsontype.JavaScript, key), js)
  411. }
  412. // ReadJavaScript will read a js string from src. If there are not enough bytes it
  413. // will return false.
  414. func ReadJavaScript(src []byte) (js string, rem []byte, ok bool) { return readstring(src) }
  415. // AppendSymbol will append symbol to dst and return the extended buffer.
  416. func AppendSymbol(dst []byte, symbol string) []byte { return appendstring(dst, symbol) }
  417. // AppendSymbolElement will append a BSON symbol element using key and symbol to dst
  418. // and return the extended buffer.
  419. func AppendSymbolElement(dst []byte, key, symbol string) []byte {
  420. return AppendSymbol(AppendHeader(dst, bsontype.Symbol, key), symbol)
  421. }
  422. // ReadSymbol will read a symbol string from src. If there are not enough bytes it
  423. // will return false.
  424. func ReadSymbol(src []byte) (symbol string, rem []byte, ok bool) { return readstring(src) }
  425. // AppendCodeWithScope will append code and scope to dst and return the extended buffer.
  426. func AppendCodeWithScope(dst []byte, code string, scope []byte) []byte {
  427. length := int32(4 + 4 + len(code) + 1 + len(scope)) // length of cws, length of code, code, 0x00, scope
  428. dst = appendLength(dst, length)
  429. return append(appendstring(dst, code), scope...)
  430. }
  431. // AppendCodeWithScopeElement will append a BSON code with scope element using
  432. // key, code, and scope to dst
  433. // and return the extended buffer.
  434. func AppendCodeWithScopeElement(dst []byte, key, code string, scope []byte) []byte {
  435. return AppendCodeWithScope(AppendHeader(dst, bsontype.CodeWithScope, key), code, scope)
  436. }
  437. // ReadCodeWithScope will read code and scope from src. If there are not enough bytes it
  438. // will return false.
  439. func ReadCodeWithScope(src []byte) (code string, scope []byte, rem []byte, ok bool) {
  440. length, rem, ok := ReadLength(src)
  441. if !ok || len(src) < int(length) {
  442. return "", nil, src, false
  443. }
  444. code, rem, ok = readstring(rem)
  445. if !ok {
  446. return "", nil, src, false
  447. }
  448. scope, rem, ok = ReadDocument(rem)
  449. if !ok {
  450. return "", nil, src, false
  451. }
  452. return code, scope, rem, true
  453. }
  454. // AppendInt32 will append i32 to dst and return the extended buffer.
  455. func AppendInt32(dst []byte, i32 int32) []byte { return appendi32(dst, i32) }
  456. // AppendInt32Element will append a BSON int32 element using key and i32 to dst
  457. // and return the extended buffer.
  458. func AppendInt32Element(dst []byte, key string, i32 int32) []byte {
  459. return AppendInt32(AppendHeader(dst, bsontype.Int32, key), i32)
  460. }
  461. // ReadInt32 will read an int32 from src. If there are not enough bytes it
  462. // will return false.
  463. func ReadInt32(src []byte) (int32, []byte, bool) { return readi32(src) }
  464. // AppendTimestamp will append t and i to dst and return the extended buffer.
  465. func AppendTimestamp(dst []byte, t, i uint32) []byte {
  466. return appendu32(appendu32(dst, i), t) // i is the lower 4 bytes, t is the higher 4 bytes
  467. }
  468. // AppendTimestampElement will append a BSON timestamp element using key, t, and
  469. // i to dst and return the extended buffer.
  470. func AppendTimestampElement(dst []byte, key string, t, i uint32) []byte {
  471. return AppendTimestamp(AppendHeader(dst, bsontype.Timestamp, key), t, i)
  472. }
  473. // ReadTimestamp will read t and i from src. If there are not enough bytes it
  474. // will return false.
  475. func ReadTimestamp(src []byte) (t, i uint32, rem []byte, ok bool) {
  476. i, rem, ok = readu32(src)
  477. if !ok {
  478. return 0, 0, src, false
  479. }
  480. t, rem, ok = readu32(rem)
  481. if !ok {
  482. return 0, 0, src, false
  483. }
  484. return t, i, rem, true
  485. }
  486. // AppendInt64 will append i64 to dst and return the extended buffer.
  487. func AppendInt64(dst []byte, i64 int64) []byte { return appendi64(dst, i64) }
  488. // AppendInt64Element will append a BSON int64 element using key and i64 to dst
  489. // and return the extended buffer.
  490. func AppendInt64Element(dst []byte, key string, i64 int64) []byte {
  491. return AppendInt64(AppendHeader(dst, bsontype.Int64, key), i64)
  492. }
  493. // ReadInt64 will read an int64 from src. If there are not enough bytes it
  494. // will return false.
  495. func ReadInt64(src []byte) (int64, []byte, bool) { return readi64(src) }
  496. // AppendDecimal128 will append d128 to dst and return the extended buffer.
  497. func AppendDecimal128(dst []byte, d128 primitive.Decimal128) []byte {
  498. high, low := d128.GetBytes()
  499. return appendu64(appendu64(dst, low), high)
  500. }
  501. // AppendDecimal128Element will append a BSON primitive.28 element using key and
  502. // d128 to dst and return the extended buffer.
  503. func AppendDecimal128Element(dst []byte, key string, d128 primitive.Decimal128) []byte {
  504. return AppendDecimal128(AppendHeader(dst, bsontype.Decimal128, key), d128)
  505. }
  506. // ReadDecimal128 will read a primitive.Decimal128 from src. If there are not enough bytes it
  507. // will return false.
  508. func ReadDecimal128(src []byte) (primitive.Decimal128, []byte, bool) {
  509. l, rem, ok := readu64(src)
  510. if !ok {
  511. return primitive.Decimal128{}, src, false
  512. }
  513. h, rem, ok := readu64(rem)
  514. if !ok {
  515. return primitive.Decimal128{}, src, false
  516. }
  517. return primitive.NewDecimal128(h, l), rem, true
  518. }
  519. // AppendMaxKeyElement will append a BSON max key element using key to dst
  520. // and return the extended buffer.
  521. func AppendMaxKeyElement(dst []byte, key string) []byte {
  522. return AppendHeader(dst, bsontype.MaxKey, key)
  523. }
  524. // AppendMinKeyElement will append a BSON min key element using key to dst
  525. // and return the extended buffer.
  526. func AppendMinKeyElement(dst []byte, key string) []byte {
  527. return AppendHeader(dst, bsontype.MinKey, key)
  528. }
  529. // EqualValue will return true if the two values are equal.
  530. func EqualValue(t1, t2 bsontype.Type, v1, v2 []byte) bool {
  531. if t1 != t2 {
  532. return false
  533. }
  534. v1, _, ok := readValue(v1, t1)
  535. if !ok {
  536. return false
  537. }
  538. v2, _, ok = readValue(v2, t2)
  539. if !ok {
  540. return false
  541. }
  542. return bytes.Equal(v1, v2)
  543. }
  544. // valueLength will determine the length of the next value contained in src as if it
  545. // is type t. The returned bool will be false if there are not enough bytes in src for
  546. // a value of type t.
  547. func valueLength(src []byte, t bsontype.Type) (int32, bool) {
  548. var length int32
  549. ok := true
  550. switch t {
  551. case bsontype.Array, bsontype.EmbeddedDocument, bsontype.CodeWithScope:
  552. length, _, ok = ReadLength(src)
  553. case bsontype.Binary:
  554. length, _, ok = ReadLength(src)
  555. length += 4 + 1 // binary length + subtype byte
  556. case bsontype.Boolean:
  557. length = 1
  558. case bsontype.DBPointer:
  559. length, _, ok = ReadLength(src)
  560. length += 4 + 12 // string length + ObjectID length
  561. case bsontype.DateTime, bsontype.Double, bsontype.Int64, bsontype.Timestamp:
  562. length = 8
  563. case bsontype.Decimal128:
  564. length = 16
  565. case bsontype.Int32:
  566. length = 4
  567. case bsontype.JavaScript, bsontype.String, bsontype.Symbol:
  568. length, _, ok = ReadLength(src)
  569. length += 4
  570. case bsontype.MaxKey, bsontype.MinKey, bsontype.Null, bsontype.Undefined:
  571. length = 0
  572. case bsontype.ObjectID:
  573. length = 12
  574. case bsontype.Regex:
  575. regex := bytes.IndexByte(src, 0x00)
  576. if regex < 0 {
  577. ok = false
  578. break
  579. }
  580. pattern := bytes.IndexByte(src[regex+1:], 0x00)
  581. if pattern < 0 {
  582. ok = false
  583. break
  584. }
  585. length = int32(int64(regex) + 1 + int64(pattern) + 1)
  586. default:
  587. ok = false
  588. }
  589. return length, ok
  590. }
  591. func readValue(src []byte, t bsontype.Type) ([]byte, []byte, bool) {
  592. length, ok := valueLength(src, t)
  593. if !ok || int(length) > len(src) {
  594. return nil, src, false
  595. }
  596. return src[:length], src[length:], true
  597. }
  598. // ReserveLength reserves the space required for length and returns the index where to write the length
  599. // and the []byte with reserved space.
  600. func ReserveLength(dst []byte) (int32, []byte) {
  601. index := len(dst)
  602. return int32(index), append(dst, 0x00, 0x00, 0x00, 0x00)
  603. }
  604. // UpdateLength updates the length at index with length and returns the []byte.
  605. func UpdateLength(dst []byte, index, length int32) []byte {
  606. dst[index] = byte(length)
  607. dst[index+1] = byte(length >> 8)
  608. dst[index+2] = byte(length >> 16)
  609. dst[index+3] = byte(length >> 24)
  610. return dst
  611. }
  612. func appendLength(dst []byte, l int32) []byte { return appendi32(dst, l) }
  613. func appendi32(dst []byte, i32 int32) []byte {
  614. return append(dst, byte(i32), byte(i32>>8), byte(i32>>16), byte(i32>>24))
  615. }
  616. // ReadLength reads an int32 length from src and returns the length and the remaining bytes. If
  617. // there aren't enough bytes to read a valid length, src is returned unomdified and the returned
  618. // bool will be false.
  619. func ReadLength(src []byte) (int32, []byte, bool) { return readi32(src) }
  620. func readi32(src []byte) (int32, []byte, bool) {
  621. if len(src) < 4 {
  622. return 0, src, false
  623. }
  624. return (int32(src[0]) | int32(src[1])<<8 | int32(src[2])<<16 | int32(src[3])<<24), src[4:], true
  625. }
  626. func appendi64(dst []byte, i64 int64) []byte {
  627. return append(dst,
  628. byte(i64), byte(i64>>8), byte(i64>>16), byte(i64>>24),
  629. byte(i64>>32), byte(i64>>40), byte(i64>>48), byte(i64>>56),
  630. )
  631. }
  632. func readi64(src []byte) (int64, []byte, bool) {
  633. if len(src) < 8 {
  634. return 0, src, false
  635. }
  636. i64 := (int64(src[0]) | int64(src[1])<<8 | int64(src[2])<<16 | int64(src[3])<<24 |
  637. int64(src[4])<<32 | int64(src[5])<<40 | int64(src[6])<<48 | int64(src[7])<<56)
  638. return i64, src[8:], true
  639. }
  640. func appendu32(dst []byte, u32 uint32) []byte {
  641. return append(dst, byte(u32), byte(u32>>8), byte(u32>>16), byte(u32>>24))
  642. }
  643. func readu32(src []byte) (uint32, []byte, bool) {
  644. if len(src) < 4 {
  645. return 0, src, false
  646. }
  647. return (uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24), src[4:], true
  648. }
  649. func appendu64(dst []byte, u64 uint64) []byte {
  650. return append(dst,
  651. byte(u64), byte(u64>>8), byte(u64>>16), byte(u64>>24),
  652. byte(u64>>32), byte(u64>>40), byte(u64>>48), byte(u64>>56),
  653. )
  654. }
  655. func readu64(src []byte) (uint64, []byte, bool) {
  656. if len(src) < 8 {
  657. return 0, src, false
  658. }
  659. u64 := (uint64(src[0]) | uint64(src[1])<<8 | uint64(src[2])<<16 | uint64(src[3])<<24 |
  660. uint64(src[4])<<32 | uint64(src[5])<<40 | uint64(src[6])<<48 | uint64(src[7])<<56)
  661. return u64, src[8:], true
  662. }
  663. // keep in sync with readcstringbytes
  664. func readcstring(src []byte) (string, []byte, bool) {
  665. idx := bytes.IndexByte(src, 0x00)
  666. if idx < 0 {
  667. return "", src, false
  668. }
  669. return string(src[:idx]), src[idx+1:], true
  670. }
  671. // keep in sync with readcstring
  672. func readcstringbytes(src []byte) ([]byte, []byte, bool) {
  673. idx := bytes.IndexByte(src, 0x00)
  674. if idx < 0 {
  675. return nil, src, false
  676. }
  677. return src[:idx], src[idx+1:], true
  678. }
  679. func appendstring(dst []byte, s string) []byte {
  680. l := int32(len(s) + 1)
  681. dst = appendLength(dst, l)
  682. dst = append(dst, s...)
  683. return append(dst, 0x00)
  684. }
  685. func readstring(src []byte) (string, []byte, bool) {
  686. l, rem, ok := ReadLength(src)
  687. if !ok {
  688. return "", src, false
  689. }
  690. if len(src[4:]) < int(l) {
  691. return "", src, false
  692. }
  693. return string(rem[:l-1]), rem[l:], true
  694. }
  695. // readLengthBytes attempts to read a length and that number of bytes. This
  696. // function requires that the length include the four bytes for itself.
  697. func readLengthBytes(src []byte) ([]byte, []byte, bool) {
  698. l, _, ok := ReadLength(src)
  699. if !ok {
  700. return nil, src, false
  701. }
  702. if len(src) < int(l) {
  703. return nil, src, false
  704. }
  705. return src[:l], src[l:], true
  706. }
  707. func appendBinarySubtype2(dst []byte, subtype byte, b []byte) []byte {
  708. dst = appendLength(dst, int32(len(b)+4)) // The bytes we'll encode need to be 4 larger for the length bytes
  709. dst = append(dst, subtype)
  710. dst = appendLength(dst, int32(len(b)))
  711. return append(dst, b...)
  712. }