| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- // Copyright (c) Faye Amacker. All rights reserved.
- // Licensed under the MIT License. See LICENSE in the project root for license information.
- package cbor
- import (
- "bytes"
- "errors"
- "io"
- "reflect"
- )
- // Decoder reads and decodes CBOR values from io.Reader.
- type Decoder struct {
- r io.Reader
- d decoder
- buf []byte
- off int // next read offset in buf
- bytesRead int
- }
- // NewDecoder returns a new decoder that reads and decodes from r using
- // the default decoding options.
- func NewDecoder(r io.Reader) *Decoder {
- return defaultDecMode.NewDecoder(r)
- }
- // Decode reads CBOR value and decodes it into the value pointed to by v.
- func (dec *Decoder) Decode(v any) error {
- _, err := dec.readNext()
- if err != nil {
- // Return validation error or read error.
- return err
- }
- dec.d.reset(dec.buf[dec.off:])
- err = dec.d.value(v)
- // Increment dec.off even if decoding err is not nil because
- // dec.d.off points to the next CBOR data item if current
- // CBOR data item is valid but failed to be decoded into v.
- // This allows next CBOR data item to be decoded in next
- // call to this function.
- dec.off += dec.d.off
- dec.bytesRead += dec.d.off
- return err
- }
- // Skip skips to the next CBOR data item (if there is any),
- // otherwise it returns error such as io.EOF, io.UnexpectedEOF, etc.
- func (dec *Decoder) Skip() error {
- n, err := dec.readNext()
- if err != nil {
- // Return validation error or read error.
- return err
- }
- dec.off += n
- dec.bytesRead += n
- return nil
- }
- // NumBytesRead returns the number of bytes read.
- func (dec *Decoder) NumBytesRead() int {
- return dec.bytesRead
- }
- // Buffered returns a reader for data remaining in Decoder's buffer.
- // Returned reader is valid until the next call to Decode or Skip.
- func (dec *Decoder) Buffered() io.Reader {
- return bytes.NewReader(dec.buf[dec.off:])
- }
- // readNext() reads next CBOR data item from Reader to buffer.
- // It returns the size of next CBOR data item.
- // It also returns validation error or read error if any.
- func (dec *Decoder) readNext() (int, error) {
- var readErr error
- var validErr error
- for {
- // Process any unread data in dec.buf.
- if dec.off < len(dec.buf) {
- dec.d.reset(dec.buf[dec.off:])
- off := dec.off // Save offset before data validation
- validErr = dec.d.wellformed(true, false)
- dec.off = off // Restore offset
- if validErr == nil {
- return dec.d.off, nil
- }
- if validErr != io.ErrUnexpectedEOF {
- return 0, validErr
- }
- // Process last read error on io.ErrUnexpectedEOF.
- if readErr != nil {
- if readErr == io.EOF {
- // current CBOR data item is incomplete.
- return 0, io.ErrUnexpectedEOF
- }
- return 0, readErr
- }
- }
- // More data is needed and there was no read error.
- var n int
- for n == 0 {
- n, readErr = dec.read()
- if n == 0 && readErr != nil {
- // No more data can be read and read error is encountered.
- // At this point, validErr is either nil or io.ErrUnexpectedEOF.
- if readErr == io.EOF {
- if validErr == io.ErrUnexpectedEOF {
- // current CBOR data item is incomplete.
- return 0, io.ErrUnexpectedEOF
- }
- }
- return 0, readErr
- }
- }
- // At this point, dec.buf contains new data from last read (n > 0).
- }
- }
- // read() reads data from Reader to buffer.
- // It returns number of bytes read and any read error encountered.
- // Postconditions:
- // - dec.buf contains previously unread data and new data.
- // - dec.off is 0.
- func (dec *Decoder) read() (int, error) {
- // Grow buf if needed.
- const minRead = 512
- if cap(dec.buf)-len(dec.buf)+dec.off < minRead {
- oldUnreadBuf := dec.buf[dec.off:]
- dec.buf = make([]byte, len(dec.buf)-dec.off, 2*cap(dec.buf)+minRead)
- dec.overwriteBuf(oldUnreadBuf)
- }
- // Copy unread data over read data and reset off to 0.
- if dec.off > 0 {
- dec.overwriteBuf(dec.buf[dec.off:])
- }
- // Read from reader and reslice buf.
- n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
- dec.buf = dec.buf[0 : len(dec.buf)+n]
- return n, err
- }
- func (dec *Decoder) overwriteBuf(newBuf []byte) {
- n := copy(dec.buf, newBuf)
- dec.buf = dec.buf[:n]
- dec.off = 0
- }
- // Encoder writes CBOR values to io.Writer.
- type Encoder struct {
- w io.Writer
- em *encMode
- indefTypes []cborType
- }
- // NewEncoder returns a new encoder that writes to w using the default encoding options.
- func NewEncoder(w io.Writer) *Encoder {
- return defaultEncMode.NewEncoder(w)
- }
- // Encode writes the CBOR encoding of v.
- func (enc *Encoder) Encode(v any) error {
- if len(enc.indefTypes) > 0 && v != nil {
- indefType := enc.indefTypes[len(enc.indefTypes)-1]
- if indefType == cborTypeTextString {
- k := reflect.TypeOf(v).Kind()
- if k != reflect.String {
- return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length text string")
- }
- } else if indefType == cborTypeByteString {
- t := reflect.TypeOf(v)
- k := t.Kind()
- if (k != reflect.Array && k != reflect.Slice) || t.Elem().Kind() != reflect.Uint8 {
- return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length byte string")
- }
- }
- }
- buf := getEncodeBuffer()
- err := encode(buf, enc.em, reflect.ValueOf(v))
- if err == nil {
- _, err = enc.w.Write(buf.Bytes())
- }
- putEncodeBuffer(buf)
- return err
- }
- // StartIndefiniteByteString starts byte string encoding of indefinite length.
- // Subsequent calls of (*Encoder).Encode() encodes definite length byte strings
- // ("chunks") as one contiguous string until EndIndefinite is called.
- func (enc *Encoder) StartIndefiniteByteString() error {
- return enc.startIndefinite(cborTypeByteString)
- }
- // StartIndefiniteTextString starts text string encoding of indefinite length.
- // Subsequent calls of (*Encoder).Encode() encodes definite length text strings
- // ("chunks") as one contiguous string until EndIndefinite is called.
- func (enc *Encoder) StartIndefiniteTextString() error {
- return enc.startIndefinite(cborTypeTextString)
- }
- // StartIndefiniteArray starts array encoding of indefinite length.
- // Subsequent calls of (*Encoder).Encode() encodes elements of the array
- // until EndIndefinite is called.
- func (enc *Encoder) StartIndefiniteArray() error {
- return enc.startIndefinite(cborTypeArray)
- }
- // StartIndefiniteMap starts array encoding of indefinite length.
- // Subsequent calls of (*Encoder).Encode() encodes elements of the map
- // until EndIndefinite is called.
- func (enc *Encoder) StartIndefiniteMap() error {
- return enc.startIndefinite(cborTypeMap)
- }
- // EndIndefinite closes last opened indefinite length value.
- func (enc *Encoder) EndIndefinite() error {
- if len(enc.indefTypes) == 0 {
- return errors.New("cbor: cannot encode \"break\" code outside indefinite length values")
- }
- _, err := enc.w.Write([]byte{cborBreakFlag})
- if err == nil {
- enc.indefTypes = enc.indefTypes[:len(enc.indefTypes)-1]
- }
- return err
- }
- var cborIndefHeader = map[cborType][]byte{
- cborTypeByteString: {cborByteStringWithIndefiniteLengthHead},
- cborTypeTextString: {cborTextStringWithIndefiniteLengthHead},
- cborTypeArray: {cborArrayWithIndefiniteLengthHead},
- cborTypeMap: {cborMapWithIndefiniteLengthHead},
- }
- func (enc *Encoder) startIndefinite(typ cborType) error {
- if enc.em.indefLength == IndefLengthForbidden {
- return &IndefiniteLengthError{typ}
- }
- _, err := enc.w.Write(cborIndefHeader[typ])
- if err == nil {
- enc.indefTypes = append(enc.indefTypes, typ)
- }
- return err
- }
- // RawMessage is a raw encoded CBOR value.
- type RawMessage []byte
- // MarshalCBOR returns m or CBOR nil if m is nil.
- func (m RawMessage) MarshalCBOR() ([]byte, error) {
- if len(m) == 0 {
- return cborNil, nil
- }
- return m, nil
- }
- // UnmarshalCBOR creates a copy of data and saves to *m.
- func (m *RawMessage) UnmarshalCBOR(data []byte) error {
- if m == nil {
- return errors.New("cbor.RawMessage: UnmarshalCBOR on nil pointer")
- }
- *m = append((*m)[0:0], data...)
- return nil
- }
|