copier.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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. "fmt"
  9. "io"
  10. "go.mongodb.org/mongo-driver/bson/bsontype"
  11. "go.mongodb.org/mongo-driver/bson/primitive"
  12. "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
  13. )
  14. // Copier is a type that allows copying between ValueReaders, ValueWriters, and
  15. // []byte values.
  16. //
  17. // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
  18. // supported in Go Driver 2.0.
  19. type Copier struct{}
  20. // NewCopier creates a new copier with the given registry. If a nil registry is provided
  21. // a default registry is used.
  22. //
  23. // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
  24. // supported in Go Driver 2.0.
  25. func NewCopier() Copier {
  26. return Copier{}
  27. }
  28. // CopyDocument handles copying a document from src to dst.
  29. //
  30. // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
  31. // supported in Go Driver 2.0.
  32. func CopyDocument(dst ValueWriter, src ValueReader) error {
  33. return Copier{}.CopyDocument(dst, src)
  34. }
  35. // CopyDocument handles copying one document from the src to the dst.
  36. //
  37. // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
  38. // supported in Go Driver 2.0.
  39. func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error {
  40. dr, err := src.ReadDocument()
  41. if err != nil {
  42. return err
  43. }
  44. dw, err := dst.WriteDocument()
  45. if err != nil {
  46. return err
  47. }
  48. return c.copyDocumentCore(dw, dr)
  49. }
  50. // CopyArrayFromBytes copies the values from a BSON array represented as a
  51. // []byte to a ValueWriter.
  52. //
  53. // Deprecated: Copying BSON arrays using the ValueWriter and ValueReader interfaces will not be
  54. // supported in Go Driver 2.0.
  55. func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error {
  56. aw, err := dst.WriteArray()
  57. if err != nil {
  58. return err
  59. }
  60. err = c.CopyBytesToArrayWriter(aw, src)
  61. if err != nil {
  62. return err
  63. }
  64. return aw.WriteArrayEnd()
  65. }
  66. // CopyDocumentFromBytes copies the values from a BSON document represented as a
  67. // []byte to a ValueWriter.
  68. //
  69. // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
  70. // supported in Go Driver 2.0.
  71. func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error {
  72. dw, err := dst.WriteDocument()
  73. if err != nil {
  74. return err
  75. }
  76. err = c.CopyBytesToDocumentWriter(dw, src)
  77. if err != nil {
  78. return err
  79. }
  80. return dw.WriteDocumentEnd()
  81. }
  82. type writeElementFn func(key string) (ValueWriter, error)
  83. // CopyBytesToArrayWriter copies the values from a BSON Array represented as a []byte to an
  84. // ArrayWriter.
  85. //
  86. // Deprecated: Copying BSON arrays using the ArrayWriter interface will not be supported in Go
  87. // Driver 2.0.
  88. func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error {
  89. wef := func(_ string) (ValueWriter, error) {
  90. return dst.WriteArrayElement()
  91. }
  92. return c.copyBytesToValueWriter(src, wef)
  93. }
  94. // CopyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a
  95. // DocumentWriter.
  96. //
  97. // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
  98. // supported in Go Driver 2.0.
  99. func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error {
  100. wef := func(key string) (ValueWriter, error) {
  101. return dst.WriteDocumentElement(key)
  102. }
  103. return c.copyBytesToValueWriter(src, wef)
  104. }
  105. func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error {
  106. // TODO(skriptble): Create errors types here. Anything thats a tag should be a property.
  107. length, rem, ok := bsoncore.ReadLength(src)
  108. if !ok {
  109. return fmt.Errorf("couldn't read length from src, not enough bytes. length=%d", len(src))
  110. }
  111. if len(src) < int(length) {
  112. return fmt.Errorf("length read exceeds number of bytes available. length=%d bytes=%d", len(src), length)
  113. }
  114. rem = rem[:length-4]
  115. var t bsontype.Type
  116. var key string
  117. var val bsoncore.Value
  118. for {
  119. t, rem, ok = bsoncore.ReadType(rem)
  120. if !ok {
  121. return io.EOF
  122. }
  123. if t == bsontype.Type(0) {
  124. if len(rem) != 0 {
  125. return fmt.Errorf("document end byte found before end of document. remaining bytes=%v", rem)
  126. }
  127. break
  128. }
  129. key, rem, ok = bsoncore.ReadKey(rem)
  130. if !ok {
  131. return fmt.Errorf("invalid key found. remaining bytes=%v", rem)
  132. }
  133. // write as either array element or document element using writeElementFn
  134. vw, err := wef(key)
  135. if err != nil {
  136. return err
  137. }
  138. val, rem, ok = bsoncore.ReadValue(rem, t)
  139. if !ok {
  140. return fmt.Errorf("not enough bytes available to read type. bytes=%d type=%s", len(rem), t)
  141. }
  142. err = c.CopyValueFromBytes(vw, t, val.Data)
  143. if err != nil {
  144. return err
  145. }
  146. }
  147. return nil
  148. }
  149. // CopyDocumentToBytes copies an entire document from the ValueReader and
  150. // returns it as bytes.
  151. //
  152. // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
  153. // supported in Go Driver 2.0.
  154. func (c Copier) CopyDocumentToBytes(src ValueReader) ([]byte, error) {
  155. return c.AppendDocumentBytes(nil, src)
  156. }
  157. // AppendDocumentBytes functions the same as CopyDocumentToBytes, but will
  158. // append the result to dst.
  159. //
  160. // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
  161. // supported in Go Driver 2.0.
  162. func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) {
  163. if br, ok := src.(BytesReader); ok {
  164. _, dst, err := br.ReadValueBytes(dst)
  165. return dst, err
  166. }
  167. vw := vwPool.Get().(*valueWriter)
  168. defer vwPool.Put(vw)
  169. vw.reset(dst)
  170. err := c.CopyDocument(vw, src)
  171. dst = vw.buf
  172. return dst, err
  173. }
  174. // AppendArrayBytes copies an array from the ValueReader to dst.
  175. //
  176. // Deprecated: Copying BSON arrays using the ValueWriter and ValueReader interfaces will not be
  177. // supported in Go Driver 2.0.
  178. func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) {
  179. if br, ok := src.(BytesReader); ok {
  180. _, dst, err := br.ReadValueBytes(dst)
  181. return dst, err
  182. }
  183. vw := vwPool.Get().(*valueWriter)
  184. defer vwPool.Put(vw)
  185. vw.reset(dst)
  186. err := c.copyArray(vw, src)
  187. dst = vw.buf
  188. return dst, err
  189. }
  190. // CopyValueFromBytes will write the value represtend by t and src to dst.
  191. //
  192. // Deprecated: Use [go.mongodb.org/mongo-driver/bson.UnmarshalValue] instead.
  193. func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) error {
  194. if wvb, ok := dst.(BytesWriter); ok {
  195. return wvb.WriteValueBytes(t, src)
  196. }
  197. vr := vrPool.Get().(*valueReader)
  198. defer vrPool.Put(vr)
  199. vr.reset(src)
  200. vr.pushElement(t)
  201. return c.CopyValue(dst, vr)
  202. }
  203. // CopyValueToBytes copies a value from src and returns it as a bsontype.Type and a
  204. // []byte.
  205. //
  206. // Deprecated: Use [go.mongodb.org/mongo-driver/bson.MarshalValue] instead.
  207. func (c Copier) CopyValueToBytes(src ValueReader) (bsontype.Type, []byte, error) {
  208. return c.AppendValueBytes(nil, src)
  209. }
  210. // AppendValueBytes functions the same as CopyValueToBytes, but will append the
  211. // result to dst.
  212. //
  213. // Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go
  214. // Driver 2.0.
  215. func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, []byte, error) {
  216. if br, ok := src.(BytesReader); ok {
  217. return br.ReadValueBytes(dst)
  218. }
  219. vw := vwPool.Get().(*valueWriter)
  220. defer vwPool.Put(vw)
  221. start := len(dst)
  222. vw.reset(dst)
  223. vw.push(mElement)
  224. err := c.CopyValue(vw, src)
  225. if err != nil {
  226. return 0, dst, err
  227. }
  228. return bsontype.Type(vw.buf[start]), vw.buf[start+2:], nil
  229. }
  230. // CopyValue will copy a single value from src to dst.
  231. //
  232. // Deprecated: Copying BSON values using the ValueWriter and ValueReader interfaces will not be
  233. // supported in Go Driver 2.0.
  234. func (c Copier) CopyValue(dst ValueWriter, src ValueReader) error {
  235. var err error
  236. switch src.Type() {
  237. case bsontype.Double:
  238. var f64 float64
  239. f64, err = src.ReadDouble()
  240. if err != nil {
  241. break
  242. }
  243. err = dst.WriteDouble(f64)
  244. case bsontype.String:
  245. var str string
  246. str, err = src.ReadString()
  247. if err != nil {
  248. return err
  249. }
  250. err = dst.WriteString(str)
  251. case bsontype.EmbeddedDocument:
  252. err = c.CopyDocument(dst, src)
  253. case bsontype.Array:
  254. err = c.copyArray(dst, src)
  255. case bsontype.Binary:
  256. var data []byte
  257. var subtype byte
  258. data, subtype, err = src.ReadBinary()
  259. if err != nil {
  260. break
  261. }
  262. err = dst.WriteBinaryWithSubtype(data, subtype)
  263. case bsontype.Undefined:
  264. err = src.ReadUndefined()
  265. if err != nil {
  266. break
  267. }
  268. err = dst.WriteUndefined()
  269. case bsontype.ObjectID:
  270. var oid primitive.ObjectID
  271. oid, err = src.ReadObjectID()
  272. if err != nil {
  273. break
  274. }
  275. err = dst.WriteObjectID(oid)
  276. case bsontype.Boolean:
  277. var b bool
  278. b, err = src.ReadBoolean()
  279. if err != nil {
  280. break
  281. }
  282. err = dst.WriteBoolean(b)
  283. case bsontype.DateTime:
  284. var dt int64
  285. dt, err = src.ReadDateTime()
  286. if err != nil {
  287. break
  288. }
  289. err = dst.WriteDateTime(dt)
  290. case bsontype.Null:
  291. err = src.ReadNull()
  292. if err != nil {
  293. break
  294. }
  295. err = dst.WriteNull()
  296. case bsontype.Regex:
  297. var pattern, options string
  298. pattern, options, err = src.ReadRegex()
  299. if err != nil {
  300. break
  301. }
  302. err = dst.WriteRegex(pattern, options)
  303. case bsontype.DBPointer:
  304. var ns string
  305. var pointer primitive.ObjectID
  306. ns, pointer, err = src.ReadDBPointer()
  307. if err != nil {
  308. break
  309. }
  310. err = dst.WriteDBPointer(ns, pointer)
  311. case bsontype.JavaScript:
  312. var js string
  313. js, err = src.ReadJavascript()
  314. if err != nil {
  315. break
  316. }
  317. err = dst.WriteJavascript(js)
  318. case bsontype.Symbol:
  319. var symbol string
  320. symbol, err = src.ReadSymbol()
  321. if err != nil {
  322. break
  323. }
  324. err = dst.WriteSymbol(symbol)
  325. case bsontype.CodeWithScope:
  326. var code string
  327. var srcScope DocumentReader
  328. code, srcScope, err = src.ReadCodeWithScope()
  329. if err != nil {
  330. break
  331. }
  332. var dstScope DocumentWriter
  333. dstScope, err = dst.WriteCodeWithScope(code)
  334. if err != nil {
  335. break
  336. }
  337. err = c.copyDocumentCore(dstScope, srcScope)
  338. case bsontype.Int32:
  339. var i32 int32
  340. i32, err = src.ReadInt32()
  341. if err != nil {
  342. break
  343. }
  344. err = dst.WriteInt32(i32)
  345. case bsontype.Timestamp:
  346. var t, i uint32
  347. t, i, err = src.ReadTimestamp()
  348. if err != nil {
  349. break
  350. }
  351. err = dst.WriteTimestamp(t, i)
  352. case bsontype.Int64:
  353. var i64 int64
  354. i64, err = src.ReadInt64()
  355. if err != nil {
  356. break
  357. }
  358. err = dst.WriteInt64(i64)
  359. case bsontype.Decimal128:
  360. var d128 primitive.Decimal128
  361. d128, err = src.ReadDecimal128()
  362. if err != nil {
  363. break
  364. }
  365. err = dst.WriteDecimal128(d128)
  366. case bsontype.MinKey:
  367. err = src.ReadMinKey()
  368. if err != nil {
  369. break
  370. }
  371. err = dst.WriteMinKey()
  372. case bsontype.MaxKey:
  373. err = src.ReadMaxKey()
  374. if err != nil {
  375. break
  376. }
  377. err = dst.WriteMaxKey()
  378. default:
  379. err = fmt.Errorf("Cannot copy unknown BSON type %s", src.Type())
  380. }
  381. return err
  382. }
  383. func (c Copier) copyArray(dst ValueWriter, src ValueReader) error {
  384. ar, err := src.ReadArray()
  385. if err != nil {
  386. return err
  387. }
  388. aw, err := dst.WriteArray()
  389. if err != nil {
  390. return err
  391. }
  392. for {
  393. vr, err := ar.ReadValue()
  394. if err == ErrEOA {
  395. break
  396. }
  397. if err != nil {
  398. return err
  399. }
  400. vw, err := aw.WriteArrayElement()
  401. if err != nil {
  402. return err
  403. }
  404. err = c.CopyValue(vw, vr)
  405. if err != nil {
  406. return err
  407. }
  408. }
  409. return aw.WriteArrayEnd()
  410. }
  411. func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error {
  412. for {
  413. key, vr, err := dr.ReadElement()
  414. if err == ErrEOD {
  415. break
  416. }
  417. if err != nil {
  418. return err
  419. }
  420. vw, err := dw.WriteDocumentElement(key)
  421. if err != nil {
  422. return err
  423. }
  424. err = c.CopyValue(vw, vr)
  425. if err != nil {
  426. return err
  427. }
  428. }
  429. return dw.WriteDocumentEnd()
  430. }