marshal.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  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 bson
  7. import (
  8. "bytes"
  9. "encoding/json"
  10. "go.mongodb.org/mongo-driver/bson/bsoncodec"
  11. "go.mongodb.org/mongo-driver/bson/bsonrw"
  12. "go.mongodb.org/mongo-driver/bson/bsontype"
  13. )
  14. const defaultDstCap = 256
  15. var bvwPool = bsonrw.NewBSONValueWriterPool()
  16. var extjPool = bsonrw.NewExtJSONValueWriterPool()
  17. // Marshaler is the interface implemented by types that can marshal themselves
  18. // into a valid BSON document.
  19. //
  20. // Implementations of Marshaler must return a full BSON document. To create
  21. // custom BSON marshaling behavior for individual values in a BSON document,
  22. // implement the ValueMarshaler interface instead.
  23. type Marshaler interface {
  24. MarshalBSON() ([]byte, error)
  25. }
  26. // ValueMarshaler is the interface implemented by types that can marshal
  27. // themselves into a valid BSON value. The format of the returned bytes must
  28. // match the returned type.
  29. //
  30. // Implementations of ValueMarshaler must return an individual BSON value. To
  31. // create custom BSON marshaling behavior for an entire BSON document, implement
  32. // the Marshaler interface instead.
  33. type ValueMarshaler interface {
  34. MarshalBSONValue() (bsontype.Type, []byte, error)
  35. }
  36. // Marshal returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed into a
  37. // document, MarshalValue should be used instead.
  38. //
  39. // Marshal will use the default registry created by NewRegistry to recursively
  40. // marshal val into a []byte. Marshal will inspect struct tags and alter the
  41. // marshaling process accordingly.
  42. func Marshal(val interface{}) ([]byte, error) {
  43. return MarshalWithRegistry(DefaultRegistry, val)
  44. }
  45. // MarshalAppend will encode val as a BSON document and append the bytes to dst. If dst is not large enough to hold the
  46. // bytes, it will be grown. If val is not a type that can be transformed into a document, MarshalValueAppend should be
  47. // used instead.
  48. //
  49. // Deprecated: Use [NewEncoder] and pass the dst byte slice (wrapped by a bytes.Buffer) into
  50. // [bsonrw.NewBSONValueWriter]:
  51. //
  52. // buf := bytes.NewBuffer(dst)
  53. // vw, err := bsonrw.NewBSONValueWriter(buf)
  54. // if err != nil {
  55. // panic(err)
  56. // }
  57. // enc, err := bson.NewEncoder(vw)
  58. // if err != nil {
  59. // panic(err)
  60. // }
  61. //
  62. // See [Encoder] for more examples.
  63. func MarshalAppend(dst []byte, val interface{}) ([]byte, error) {
  64. return MarshalAppendWithRegistry(DefaultRegistry, dst, val)
  65. }
  66. // MarshalWithRegistry returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed
  67. // into a document, MarshalValueWithRegistry should be used instead.
  68. //
  69. // Deprecated: Use [NewEncoder] and specify the Registry by calling [Encoder.SetRegistry] instead:
  70. //
  71. // buf := new(bytes.Buffer)
  72. // vw, err := bsonrw.NewBSONValueWriter(buf)
  73. // if err != nil {
  74. // panic(err)
  75. // }
  76. // enc, err := bson.NewEncoder(vw)
  77. // if err != nil {
  78. // panic(err)
  79. // }
  80. // enc.SetRegistry(reg)
  81. //
  82. // See [Encoder] for more examples.
  83. func MarshalWithRegistry(r *bsoncodec.Registry, val interface{}) ([]byte, error) {
  84. dst := make([]byte, 0)
  85. return MarshalAppendWithRegistry(r, dst, val)
  86. }
  87. // MarshalWithContext returns the BSON encoding of val as a BSON document using EncodeContext ec. If val is not a type
  88. // that can be transformed into a document, MarshalValueWithContext should be used instead.
  89. //
  90. // Deprecated: Use [NewEncoder] and use the Encoder configuration methods to set the desired marshal
  91. // behavior instead:
  92. //
  93. // buf := bytes.NewBuffer(dst)
  94. // vw, err := bsonrw.NewBSONValueWriter(buf)
  95. // if err != nil {
  96. // panic(err)
  97. // }
  98. // enc, err := bson.NewEncoder(vw)
  99. // if err != nil {
  100. // panic(err)
  101. // }
  102. // enc.IntMinSize()
  103. //
  104. // See [Encoder] for more examples.
  105. func MarshalWithContext(ec bsoncodec.EncodeContext, val interface{}) ([]byte, error) {
  106. dst := make([]byte, 0)
  107. return MarshalAppendWithContext(ec, dst, val)
  108. }
  109. // MarshalAppendWithRegistry will encode val as a BSON document using Registry r and append the bytes to dst. If dst is
  110. // not large enough to hold the bytes, it will be grown. If val is not a type that can be transformed into a document,
  111. // MarshalValueAppendWithRegistry should be used instead.
  112. //
  113. // Deprecated: Use [NewEncoder], and pass the dst byte slice (wrapped by a bytes.Buffer) into
  114. // [bsonrw.NewBSONValueWriter], and specify the Registry by calling [Encoder.SetRegistry] instead:
  115. //
  116. // buf := bytes.NewBuffer(dst)
  117. // vw, err := bsonrw.NewBSONValueWriter(buf)
  118. // if err != nil {
  119. // panic(err)
  120. // }
  121. // enc, err := bson.NewEncoder(vw)
  122. // if err != nil {
  123. // panic(err)
  124. // }
  125. // enc.SetRegistry(reg)
  126. //
  127. // See [Encoder] for more examples.
  128. func MarshalAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) ([]byte, error) {
  129. return MarshalAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val)
  130. }
  131. // MarshalAppendWithContext will encode val as a BSON document using Registry r and EncodeContext ec and append the
  132. // bytes to dst. If dst is not large enough to hold the bytes, it will be grown. If val is not a type that can be
  133. // transformed into a document, MarshalValueAppendWithContext should be used instead.
  134. //
  135. // Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into
  136. // [bsonrw.NewBSONValueWriter], and use the Encoder configuration methods to set the desired marshal
  137. // behavior instead:
  138. //
  139. // buf := bytes.NewBuffer(dst)
  140. // vw, err := bsonrw.NewBSONValueWriter(buf)
  141. // if err != nil {
  142. // panic(err)
  143. // }
  144. // enc, err := bson.NewEncoder(vw)
  145. // if err != nil {
  146. // panic(err)
  147. // }
  148. // enc.IntMinSize()
  149. //
  150. // See [Encoder] for more examples.
  151. func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) ([]byte, error) {
  152. sw := new(bsonrw.SliceWriter)
  153. *sw = dst
  154. vw := bvwPool.Get(sw)
  155. defer bvwPool.Put(vw)
  156. enc := encPool.Get().(*Encoder)
  157. defer encPool.Put(enc)
  158. err := enc.Reset(vw)
  159. if err != nil {
  160. return nil, err
  161. }
  162. err = enc.SetContext(ec)
  163. if err != nil {
  164. return nil, err
  165. }
  166. err = enc.Encode(val)
  167. if err != nil {
  168. return nil, err
  169. }
  170. return *sw, nil
  171. }
  172. // MarshalValue returns the BSON encoding of val.
  173. //
  174. // MarshalValue will use bson.DefaultRegistry to transform val into a BSON value. If val is a struct, this function will
  175. // inspect struct tags and alter the marshalling process accordingly.
  176. func MarshalValue(val interface{}) (bsontype.Type, []byte, error) {
  177. return MarshalValueWithRegistry(DefaultRegistry, val)
  178. }
  179. // MarshalValueAppend will append the BSON encoding of val to dst. If dst is not large enough to hold the BSON encoding
  180. // of val, dst will be grown.
  181. //
  182. // Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go
  183. // Driver 2.0.
  184. func MarshalValueAppend(dst []byte, val interface{}) (bsontype.Type, []byte, error) {
  185. return MarshalValueAppendWithRegistry(DefaultRegistry, dst, val)
  186. }
  187. // MarshalValueWithRegistry returns the BSON encoding of val using Registry r.
  188. //
  189. // Deprecated: Using a custom registry to marshal individual BSON values will not be supported in Go
  190. // Driver 2.0.
  191. func MarshalValueWithRegistry(r *bsoncodec.Registry, val interface{}) (bsontype.Type, []byte, error) {
  192. dst := make([]byte, 0)
  193. return MarshalValueAppendWithRegistry(r, dst, val)
  194. }
  195. // MarshalValueWithContext returns the BSON encoding of val using EncodeContext ec.
  196. //
  197. // Deprecated: Using a custom EncodeContext to marshal individual BSON elements will not be
  198. // supported in Go Driver 2.0.
  199. func MarshalValueWithContext(ec bsoncodec.EncodeContext, val interface{}) (bsontype.Type, []byte, error) {
  200. dst := make([]byte, 0)
  201. return MarshalValueAppendWithContext(ec, dst, val)
  202. }
  203. // MarshalValueAppendWithRegistry will append the BSON encoding of val to dst using Registry r. If dst is not large
  204. // enough to hold the BSON encoding of val, dst will be grown.
  205. //
  206. // Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go
  207. // Driver 2.0.
  208. func MarshalValueAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) (bsontype.Type, []byte, error) {
  209. return MarshalValueAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val)
  210. }
  211. // MarshalValueAppendWithContext will append the BSON encoding of val to dst using EncodeContext ec. If dst is not large
  212. // enough to hold the BSON encoding of val, dst will be grown.
  213. //
  214. // Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go
  215. // Driver 2.0.
  216. func MarshalValueAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) (bsontype.Type, []byte, error) {
  217. // get a ValueWriter configured to write to dst
  218. sw := new(bsonrw.SliceWriter)
  219. *sw = dst
  220. vwFlusher := bvwPool.GetAtModeElement(sw)
  221. // get an Encoder and encode the value
  222. enc := encPool.Get().(*Encoder)
  223. defer encPool.Put(enc)
  224. if err := enc.Reset(vwFlusher); err != nil {
  225. return 0, nil, err
  226. }
  227. if err := enc.SetContext(ec); err != nil {
  228. return 0, nil, err
  229. }
  230. if err := enc.Encode(val); err != nil {
  231. return 0, nil, err
  232. }
  233. // flush the bytes written because we cannot guarantee that a full document has been written
  234. // after the flush, *sw will be in the format
  235. // [value type, 0 (null byte to indicate end of empty element name), value bytes..]
  236. if err := vwFlusher.Flush(); err != nil {
  237. return 0, nil, err
  238. }
  239. buffer := *sw
  240. return bsontype.Type(buffer[0]), buffer[2:], nil
  241. }
  242. // MarshalExtJSON returns the extended JSON encoding of val.
  243. func MarshalExtJSON(val interface{}, canonical, escapeHTML bool) ([]byte, error) {
  244. return MarshalExtJSONWithRegistry(DefaultRegistry, val, canonical, escapeHTML)
  245. }
  246. // MarshalExtJSONAppend will append the extended JSON encoding of val to dst.
  247. // If dst is not large enough to hold the extended JSON encoding of val, dst
  248. // will be grown.
  249. //
  250. // Deprecated: Use [NewEncoder] and pass the dst byte slice (wrapped by a bytes.Buffer) into
  251. // [bsonrw.NewExtJSONValueWriter] instead:
  252. //
  253. // buf := bytes.NewBuffer(dst)
  254. // vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false)
  255. // if err != nil {
  256. // panic(err)
  257. // }
  258. // enc, err := bson.NewEncoder(vw)
  259. // if err != nil {
  260. // panic(err)
  261. // }
  262. //
  263. // See [Encoder] for more examples.
  264. func MarshalExtJSONAppend(dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
  265. return MarshalExtJSONAppendWithRegistry(DefaultRegistry, dst, val, canonical, escapeHTML)
  266. }
  267. // MarshalExtJSONWithRegistry returns the extended JSON encoding of val using Registry r.
  268. //
  269. // Deprecated: Use [NewEncoder] and specify the Registry by calling [Encoder.SetRegistry] instead:
  270. //
  271. // buf := new(bytes.Buffer)
  272. // vw, err := bsonrw.NewBSONValueWriter(buf)
  273. // if err != nil {
  274. // panic(err)
  275. // }
  276. // enc, err := bson.NewEncoder(vw)
  277. // if err != nil {
  278. // panic(err)
  279. // }
  280. // enc.SetRegistry(reg)
  281. //
  282. // See [Encoder] for more examples.
  283. func MarshalExtJSONWithRegistry(r *bsoncodec.Registry, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
  284. dst := make([]byte, 0, defaultDstCap)
  285. return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML)
  286. }
  287. // MarshalExtJSONWithContext returns the extended JSON encoding of val using Registry r.
  288. //
  289. // Deprecated: Use [NewEncoder] and use the Encoder configuration methods to set the desired marshal
  290. // behavior instead:
  291. //
  292. // buf := new(bytes.Buffer)
  293. // vw, err := bsonrw.NewBSONValueWriter(buf)
  294. // if err != nil {
  295. // panic(err)
  296. // }
  297. // enc, err := bson.NewEncoder(vw)
  298. // if err != nil {
  299. // panic(err)
  300. // }
  301. // enc.IntMinSize()
  302. //
  303. // See [Encoder] for more examples.
  304. func MarshalExtJSONWithContext(ec bsoncodec.EncodeContext, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
  305. dst := make([]byte, 0, defaultDstCap)
  306. return MarshalExtJSONAppendWithContext(ec, dst, val, canonical, escapeHTML)
  307. }
  308. // MarshalExtJSONAppendWithRegistry will append the extended JSON encoding of
  309. // val to dst using Registry r. If dst is not large enough to hold the BSON
  310. // encoding of val, dst will be grown.
  311. //
  312. // Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into
  313. // [bsonrw.NewExtJSONValueWriter], and specify the Registry by calling [Encoder.SetRegistry]
  314. // instead:
  315. //
  316. // buf := bytes.NewBuffer(dst)
  317. // vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false)
  318. // if err != nil {
  319. // panic(err)
  320. // }
  321. // enc, err := bson.NewEncoder(vw)
  322. // if err != nil {
  323. // panic(err)
  324. // }
  325. //
  326. // See [Encoder] for more examples.
  327. func MarshalExtJSONAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
  328. return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML)
  329. }
  330. // MarshalExtJSONAppendWithContext will append the extended JSON encoding of
  331. // val to dst using Registry r. If dst is not large enough to hold the BSON
  332. // encoding of val, dst will be grown.
  333. //
  334. // Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into
  335. // [bsonrw.NewExtJSONValueWriter], and use the Encoder configuration methods to set the desired marshal
  336. // behavior instead:
  337. //
  338. // buf := bytes.NewBuffer(dst)
  339. // vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false)
  340. // if err != nil {
  341. // panic(err)
  342. // }
  343. // enc, err := bson.NewEncoder(vw)
  344. // if err != nil {
  345. // panic(err)
  346. // }
  347. // enc.IntMinSize()
  348. //
  349. // See [Encoder] for more examples.
  350. func MarshalExtJSONAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
  351. sw := new(bsonrw.SliceWriter)
  352. *sw = dst
  353. ejvw := extjPool.Get(sw, canonical, escapeHTML)
  354. defer extjPool.Put(ejvw)
  355. enc := encPool.Get().(*Encoder)
  356. defer encPool.Put(enc)
  357. err := enc.Reset(ejvw)
  358. if err != nil {
  359. return nil, err
  360. }
  361. err = enc.SetContext(ec)
  362. if err != nil {
  363. return nil, err
  364. }
  365. err = enc.Encode(val)
  366. if err != nil {
  367. return nil, err
  368. }
  369. return *sw, nil
  370. }
  371. // IndentExtJSON will prefix and indent the provided extended JSON src and append it to dst.
  372. func IndentExtJSON(dst *bytes.Buffer, src []byte, prefix, indent string) error {
  373. return json.Indent(dst, src, prefix, indent)
  374. }
  375. // MarshalExtJSONIndent returns the extended JSON encoding of val with each line with prefixed
  376. // and indented.
  377. func MarshalExtJSONIndent(val interface{}, canonical, escapeHTML bool, prefix, indent string) ([]byte, error) {
  378. marshaled, err := MarshalExtJSON(val, canonical, escapeHTML)
  379. if err != nil {
  380. return nil, err
  381. }
  382. var buf bytes.Buffer
  383. err = IndentExtJSON(&buf, marshaled, prefix, indent)
  384. if err != nil {
  385. return nil, err
  386. }
  387. return buf.Bytes(), nil
  388. }