...

Source file src/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go

Documentation: go.mongodb.org/mongo-driver/x/bsonx/bsoncore

     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 bsoncore
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  
    13  	"go.mongodb.org/mongo-driver/bson/bsontype"
    14  )
    15  
    16  // MalformedElementError represents a class of errors that RawElement methods return.
    17  type MalformedElementError string
    18  
    19  func (mee MalformedElementError) Error() string { return string(mee) }
    20  
    21  // ErrElementMissingKey is returned when a RawElement is missing a key.
    22  const ErrElementMissingKey MalformedElementError = "element is missing key"
    23  
    24  // ErrElementMissingType is returned when a RawElement is missing a type.
    25  const ErrElementMissingType MalformedElementError = "element is missing type"
    26  
    27  // Element is a raw bytes representation of a BSON element.
    28  type Element []byte
    29  
    30  // Key returns the key for this element. If the element is not valid, this method returns an empty
    31  // string. If knowing if the element is valid is important, use KeyErr.
    32  func (e Element) Key() string {
    33  	key, _ := e.KeyErr()
    34  	return key
    35  }
    36  
    37  // KeyBytes returns the key for this element as a []byte. If the element is not valid, this method
    38  // returns an empty string. If knowing if the element is valid is important, use KeyErr. This method
    39  // will not include the null byte at the end of the key in the slice of bytes.
    40  func (e Element) KeyBytes() []byte {
    41  	key, _ := e.KeyBytesErr()
    42  	return key
    43  }
    44  
    45  // KeyErr returns the key for this element, returning an error if the element is not valid.
    46  func (e Element) KeyErr() (string, error) {
    47  	key, err := e.KeyBytesErr()
    48  	return string(key), err
    49  }
    50  
    51  // KeyBytesErr returns the key for this element as a []byte, returning an error if the element is
    52  // not valid.
    53  func (e Element) KeyBytesErr() ([]byte, error) {
    54  	if len(e) <= 0 {
    55  		return nil, ErrElementMissingType
    56  	}
    57  	idx := bytes.IndexByte(e[1:], 0x00)
    58  	if idx == -1 {
    59  		return nil, ErrElementMissingKey
    60  	}
    61  	return e[1 : idx+1], nil
    62  }
    63  
    64  // Validate ensures the element is a valid BSON element.
    65  func (e Element) Validate() error {
    66  	if len(e) < 1 {
    67  		return ErrElementMissingType
    68  	}
    69  	idx := bytes.IndexByte(e[1:], 0x00)
    70  	if idx == -1 {
    71  		return ErrElementMissingKey
    72  	}
    73  	return Value{Type: bsontype.Type(e[0]), Data: e[idx+2:]}.Validate()
    74  }
    75  
    76  // CompareKey will compare this element's key to key. This method makes it easy to compare keys
    77  // without needing to allocate a string. The key may be null terminated. If a valid key cannot be
    78  // read this method will return false.
    79  func (e Element) CompareKey(key []byte) bool {
    80  	if len(e) < 2 {
    81  		return false
    82  	}
    83  	idx := bytes.IndexByte(e[1:], 0x00)
    84  	if idx == -1 {
    85  		return false
    86  	}
    87  	if index := bytes.IndexByte(key, 0x00); index > -1 {
    88  		key = key[:index]
    89  	}
    90  	return bytes.Equal(e[1:idx+1], key)
    91  }
    92  
    93  // Value returns the value of this element. If the element is not valid, this method returns an
    94  // empty Value. If knowing if the element is valid is important, use ValueErr.
    95  func (e Element) Value() Value {
    96  	val, _ := e.ValueErr()
    97  	return val
    98  }
    99  
   100  // ValueErr returns the value for this element, returning an error if the element is not valid.
   101  func (e Element) ValueErr() (Value, error) {
   102  	if len(e) <= 0 {
   103  		return Value{}, ErrElementMissingType
   104  	}
   105  	idx := bytes.IndexByte(e[1:], 0x00)
   106  	if idx == -1 {
   107  		return Value{}, ErrElementMissingKey
   108  	}
   109  
   110  	val, rem, exists := ReadValue(e[idx+2:], bsontype.Type(e[0]))
   111  	if !exists {
   112  		return Value{}, NewInsufficientBytesError(e, rem)
   113  	}
   114  	return val, nil
   115  }
   116  
   117  // String implements the fmt.String interface. The output will be in extended JSON format.
   118  func (e Element) String() string {
   119  	if len(e) <= 0 {
   120  		return ""
   121  	}
   122  	t := bsontype.Type(e[0])
   123  	idx := bytes.IndexByte(e[1:], 0x00)
   124  	if idx == -1 {
   125  		return ""
   126  	}
   127  	key, valBytes := []byte(e[1:idx+1]), []byte(e[idx+2:])
   128  	val, _, valid := ReadValue(valBytes, t)
   129  	if !valid {
   130  		return ""
   131  	}
   132  	return "\"" + string(key) + "\": " + val.String()
   133  }
   134  
   135  // DebugString outputs a human readable version of RawElement. It will attempt to stringify the
   136  // valid components of the element even if the entire element is not valid.
   137  func (e Element) DebugString() string {
   138  	if len(e) <= 0 {
   139  		return "<malformed>"
   140  	}
   141  	t := bsontype.Type(e[0])
   142  	idx := bytes.IndexByte(e[1:], 0x00)
   143  	if idx == -1 {
   144  		return fmt.Sprintf(`bson.Element{[%s]<malformed>}`, t)
   145  	}
   146  	key, valBytes := []byte(e[1:idx+1]), []byte(e[idx+2:])
   147  	val, _, valid := ReadValue(valBytes, t)
   148  	if !valid {
   149  		return fmt.Sprintf(`bson.Element{[%s]"%s": <malformed>}`, t, key)
   150  	}
   151  	return fmt.Sprintf(`bson.Element{[%s]"%s": %v}`, t, key, val)
   152  }
   153  

View as plain text