func (d Document) DebugString() string {
	if len(d) < 5 {
		return "<malformed>"
	}
	var buf bytes.Buffer
	buf.WriteString("Document")
	length, rem, _ := ReadLength(d)  
	buf.WriteByte('(')
	buf.WriteString(strconv.Itoa(int(length)))
	length -= 4
	buf.WriteString("){")
	var elem Element
	var ok bool
	for length > 1 {
		elem, rem, ok = ReadElement(rem)
		length -= int32(len(elem))
		if !ok {
			buf.WriteString(fmt.Sprintf("<malformed (%d)>", length))
			break
		}
		fmt.Fprintf(&buf, "%s ", elem.DebugString())
	}
	buf.WriteByte('}')
	return buf.String()
}
DebugString outputs a human readable version of Document. It will attempt to stringify the
valid components of the document even if the entire document is not valid.
package bsoncore
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"strconv"
	"github.com/go-stack/stack"
	"go.mongodb.org/mongo-driver/bson/bsontype"
)
type ValidationError string
func (ve ValidationError) Error() string { return string(ve) }
func NewDocumentLengthError(length, rem int) error {
	return lengthError("document", length, rem)
}
func lengthError(bufferType string, length, rem int) error {
	return ValidationError(fmt.Sprintf("%v length exceeds available bytes. length=%d remainingBytes=%d",
		bufferType, length, rem))
}
type InsufficientBytesError struct {
	Source    []byte
	Remaining []byte
	Stack     stack.CallStack
}
func NewInsufficientBytesError(src, rem []byte) InsufficientBytesError {
	return InsufficientBytesError{Source: src, Remaining: rem, Stack: stack.Trace().TrimRuntime()}
}
func (ibe InsufficientBytesError) Error() string {
	return "too few bytes to read next component"
}
func (ibe InsufficientBytesError) ErrorStack() string {
	s := bytes.NewBufferString("too few bytes to read next component: [")
	for i, call := range ibe.Stack {
		if i != 0 {
			s.WriteString(", ")
		}
		callFormat := "%k.%n %v"
		s.WriteString(fmt.Sprintf(callFormat, call, call, call))
	}
	s.WriteRune(']')
	return s.String()
}
func (ibe InsufficientBytesError) Equal(err2 error) bool {
	switch err2.(type) {
	case InsufficientBytesError:
		return true
	default:
		return false
	}
}
type InvalidDepthTraversalError struct {
	Key  string
	Type bsontype.Type
}
func (idte InvalidDepthTraversalError) Error() string {
	return fmt.Sprintf(
		"attempt to traverse into %s, but it's type is %s, not %s nor %s",
		idte.Key, idte.Type, bsontype.EmbeddedDocument, bsontype.Array,
	)
}
const ErrMissingNull ValidationError = "document or array end is missing null byte"
const ErrInvalidLength ValidationError = "document or array length is invalid"
var ErrNilReader = errors.New("nil reader")
var ErrEmptyKey = errors.New("empty key provided")
var ErrElementNotFound = errors.New("element not found")
var ErrOutOfBounds = errors.New("out of bounds")
type Document []byte
func NewDocumentFromReader(r io.Reader) (Document, error) {
	return newBufferFromReader(r)
}
func newBufferFromReader(r io.Reader) ([]byte, error) {
	if r == nil {
		return nil, ErrNilReader
	}
	var lengthBytes [4]byte
	_, err := io.ReadFull(r, lengthBytes[:])
	if err != nil {
		return nil, err
	}
	length, _, _ := readi32(lengthBytes[:])  
	if length < 0 {
		return nil, ErrInvalidLength
	}
	buffer := make([]byte, length)
	copy(buffer, lengthBytes[:])
	_, err = io.ReadFull(r, buffer[4:])
	if err != nil {
		return nil, err
	}
	if buffer[length-1] != 0x00 {
		return nil, ErrMissingNull
	}
	return buffer, nil
}
func (d Document) Lookup(key ...string) Value {
	val, _ := d.LookupErr(key...)
	return val
}
func (d Document) LookupErr(key ...string) (Value, error) {
	if len(key) < 1 {
		return Value{}, ErrEmptyKey
	}
	length, rem, ok := ReadLength(d)
	if !ok {
		return Value{}, NewInsufficientBytesError(d, rem)
	}
	length -= 4
	var elem Element
	for length > 1 {
		elem, rem, ok = ReadElement(rem)
		length -= int32(len(elem))
		if !ok {
			return Value{}, NewInsufficientBytesError(d, rem)
		}
		if string(elem.KeyBytes()) != key[0] {
			continue
		}
		if len(key) > 1 {
			tt := bsontype.Type(elem[0])
			switch tt {
			case bsontype.EmbeddedDocument:
				val, err := elem.Value().Document().LookupErr(key[1:]...)
				if err != nil {
					return Value{}, err
				}
				return val, nil
			case bsontype.Array:
				val, err := elem.Value().Array().LookupErr(key[1:]...)
				if err != nil {
					return Value{}, err
				}
				return val, nil
			default:
				return Value{}, InvalidDepthTraversalError{Key: elem.Key(), Type: tt}
			}
		}
		return elem.ValueErr()
	}
	return Value{}, ErrElementNotFound
}
func (d Document) Index(index uint) Element {
	elem, err := d.IndexErr(index)
	if err != nil {
		panic(err)
	}
	return elem
}
func (d Document) IndexErr(index uint) (Element, error) {
	return indexErr(d, index)
}
func indexErr(b []byte, index uint) (Element, error) {
	length, rem, ok := ReadLength(b)
	if !ok {
		return nil, NewInsufficientBytesError(b, rem)
	}
	length -= 4
	var current uint
	var elem Element
	for length > 1 {
		elem, rem, ok = ReadElement(rem)
		length -= int32(len(elem))
		if !ok {
			return nil, NewInsufficientBytesError(b, rem)
		}
		if current != index {
			current++
			continue
		}
		return elem, nil
	}
	return nil, ErrOutOfBounds
}