unmarshal.go raw

   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  
   7  package bson
   8  
   9  import (
  10  	"bytes"
  11  
  12  	"go.mongodb.org/mongo-driver/bson/bsoncodec"
  13  	"go.mongodb.org/mongo-driver/bson/bsonrw"
  14  	"go.mongodb.org/mongo-driver/bson/bsontype"
  15  )
  16  
  17  // Unmarshaler is the interface implemented by types that can unmarshal a BSON
  18  // document representation of themselves. The input can be assumed to be a valid
  19  // encoding of a BSON document. UnmarshalBSON must copy the JSON data if it
  20  // wishes to retain the data after returning.
  21  //
  22  // Unmarshaler is only used to unmarshal full BSON documents. To create custom
  23  // BSON unmarshaling behavior for individual values in a BSON document,
  24  // implement the ValueUnmarshaler interface instead.
  25  type Unmarshaler interface {
  26  	UnmarshalBSON([]byte) error
  27  }
  28  
  29  // ValueUnmarshaler is the interface implemented by types that can unmarshal a
  30  // BSON value representation of themselves. The input can be assumed to be a
  31  // valid encoding of a BSON value. UnmarshalBSONValue must copy the BSON value
  32  // bytes if it wishes to retain the data after returning.
  33  //
  34  // ValueUnmarshaler is only used to unmarshal individual values in a BSON
  35  // document. To create custom BSON unmarshaling behavior for an entire BSON
  36  // document, implement the Unmarshaler interface instead.
  37  type ValueUnmarshaler interface {
  38  	UnmarshalBSONValue(bsontype.Type, []byte) error
  39  }
  40  
  41  // Unmarshal parses the BSON-encoded data and stores the result in the value
  42  // pointed to by val. If val is nil or not a pointer, Unmarshal returns
  43  // InvalidUnmarshalError.
  44  func Unmarshal(data []byte, val interface{}) error {
  45  	return UnmarshalWithRegistry(DefaultRegistry, data, val)
  46  }
  47  
  48  // UnmarshalWithRegistry parses the BSON-encoded data using Registry r and
  49  // stores the result in the value pointed to by val. If val is nil or not
  50  // a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError.
  51  //
  52  // Deprecated: Use [NewDecoder] and specify the Registry by calling [Decoder.SetRegistry] instead:
  53  //
  54  //	dec, err := bson.NewDecoder(bsonrw.NewBSONDocumentReader(data))
  55  //	if err != nil {
  56  //		panic(err)
  57  //	}
  58  //	dec.SetRegistry(reg)
  59  //
  60  // See [Decoder] for more examples.
  61  func UnmarshalWithRegistry(r *bsoncodec.Registry, data []byte, val interface{}) error {
  62  	vr := bsonrw.NewBSONDocumentReader(data)
  63  	return unmarshalFromReader(bsoncodec.DecodeContext{Registry: r}, vr, val)
  64  }
  65  
  66  // UnmarshalWithContext parses the BSON-encoded data using DecodeContext dc and
  67  // stores the result in the value pointed to by val. If val is nil or not
  68  // a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError.
  69  //
  70  // Deprecated: Use [NewDecoder] and use the Decoder configuration methods to set the desired unmarshal
  71  // behavior instead:
  72  //
  73  //	dec, err := bson.NewDecoder(bsonrw.NewBSONDocumentReader(data))
  74  //	if err != nil {
  75  //		panic(err)
  76  //	}
  77  //	dec.DefaultDocumentM()
  78  //
  79  // See [Decoder] for more examples.
  80  func UnmarshalWithContext(dc bsoncodec.DecodeContext, data []byte, val interface{}) error {
  81  	vr := bsonrw.NewBSONDocumentReader(data)
  82  	return unmarshalFromReader(dc, vr, val)
  83  }
  84  
  85  // UnmarshalValue parses the BSON value of type t with bson.DefaultRegistry and
  86  // stores the result in the value pointed to by val. If val is nil or not a pointer,
  87  // UnmarshalValue returns an error.
  88  func UnmarshalValue(t bsontype.Type, data []byte, val interface{}) error {
  89  	return UnmarshalValueWithRegistry(DefaultRegistry, t, data, val)
  90  }
  91  
  92  // UnmarshalValueWithRegistry parses the BSON value of type t with registry r and
  93  // stores the result in the value pointed to by val. If val is nil or not a pointer,
  94  // UnmarshalValue returns an error.
  95  //
  96  // Deprecated: Using a custom registry to unmarshal individual BSON values will not be supported in
  97  // Go Driver 2.0.
  98  func UnmarshalValueWithRegistry(r *bsoncodec.Registry, t bsontype.Type, data []byte, val interface{}) error {
  99  	vr := bsonrw.NewBSONValueReader(t, data)
 100  	return unmarshalFromReader(bsoncodec.DecodeContext{Registry: r}, vr, val)
 101  }
 102  
 103  // UnmarshalExtJSON parses the extended JSON-encoded data and stores the result
 104  // in the value pointed to by val. If val is nil or not a pointer, Unmarshal
 105  // returns InvalidUnmarshalError.
 106  func UnmarshalExtJSON(data []byte, canonical bool, val interface{}) error {
 107  	return UnmarshalExtJSONWithRegistry(DefaultRegistry, data, canonical, val)
 108  }
 109  
 110  // UnmarshalExtJSONWithRegistry parses the extended JSON-encoded data using
 111  // Registry r and stores the result in the value pointed to by val. If val is
 112  // nil or not a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError.
 113  //
 114  // Deprecated: Use [NewDecoder] and specify the Registry by calling [Decoder.SetRegistry] instead:
 115  //
 116  //	vr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), true)
 117  //	if err != nil {
 118  //		panic(err)
 119  //	}
 120  //	dec, err := bson.NewDecoder(vr)
 121  //	if err != nil {
 122  //		panic(err)
 123  //	}
 124  //	dec.SetRegistry(reg)
 125  //
 126  // See [Decoder] for more examples.
 127  func UnmarshalExtJSONWithRegistry(r *bsoncodec.Registry, data []byte, canonical bool, val interface{}) error {
 128  	ejvr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), canonical)
 129  	if err != nil {
 130  		return err
 131  	}
 132  
 133  	return unmarshalFromReader(bsoncodec.DecodeContext{Registry: r}, ejvr, val)
 134  }
 135  
 136  // UnmarshalExtJSONWithContext parses the extended JSON-encoded data using
 137  // DecodeContext dc and stores the result in the value pointed to by val. If val is
 138  // nil or not a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError.
 139  //
 140  // Deprecated: Use [NewDecoder] and use the Decoder configuration methods to set the desired unmarshal
 141  // behavior instead:
 142  //
 143  //	vr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), true)
 144  //	if err != nil {
 145  //		panic(err)
 146  //	}
 147  //	dec, err := bson.NewDecoder(vr)
 148  //	if err != nil {
 149  //		panic(err)
 150  //	}
 151  //	dec.DefaultDocumentM()
 152  //
 153  // See [Decoder] for more examples.
 154  func UnmarshalExtJSONWithContext(dc bsoncodec.DecodeContext, data []byte, canonical bool, val interface{}) error {
 155  	ejvr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), canonical)
 156  	if err != nil {
 157  		return err
 158  	}
 159  
 160  	return unmarshalFromReader(dc, ejvr, val)
 161  }
 162  
 163  func unmarshalFromReader(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val interface{}) error {
 164  	dec := decPool.Get().(*Decoder)
 165  	defer decPool.Put(dec)
 166  
 167  	err := dec.Reset(vr)
 168  	if err != nil {
 169  		return err
 170  	}
 171  	err = dec.SetContext(dc)
 172  	if err != nil {
 173  		return err
 174  	}
 175  
 176  	return dec.Decode(val)
 177  }
 178