// Copyright (c) Faye Amacker. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. package cbor import ( "errors" "io" "reflect" ) // Decoder reads and decodes CBOR values from an input stream. type Decoder struct { r io.Reader buf []byte d decodeState off int // start of unread data in buf bytesRead int } // NewDecoder returns a new decoder that reads from r using the default decoding options. func NewDecoder(r io.Reader) *Decoder { return defaultDecMode.NewDecoder(r) } // Decode reads the next CBOR-encoded value from its input and stores it in // the value pointed to by v. func (dec *Decoder) Decode(v interface{}) error { if len(dec.buf) == dec.off { if n, err := dec.read(); n == 0 { return err } } dec.d.reset(dec.buf[dec.off:]) err := dec.d.value(v) dec.off += dec.d.off dec.bytesRead += dec.d.off if err != nil { if err != io.ErrUnexpectedEOF { return err } // Need to read more data. if n, e := dec.read(); n == 0 { return e } return dec.Decode(v) } return nil } // NumBytesRead returns the number of bytes read. func (dec *Decoder) NumBytesRead() int { return dec.bytesRead } func (dec *Decoder) read() (int, error) { // Copy unread data over read data and reset off to 0. if dec.off > 0 { n := copy(dec.buf, dec.buf[dec.off:]) dec.buf = dec.buf[:n] dec.off = 0 } // Grow buf if needed. const minRead = 512 if cap(dec.buf)-len(dec.buf) < minRead { newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead) copy(newBuf, dec.buf) dec.buf = newBuf } // 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 } // Encoder writes CBOR values to an output stream. type Encoder struct { w io.Writer em *encMode e *encodeState 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 to the stream. func (enc *Encoder) Encode(v interface{}) 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") } } } err := encode(enc.e, enc.em, reflect.ValueOf(v)) if err == nil { _, err = enc.e.WriteTo(enc.w) } enc.e.Reset() return err } // StartIndefiniteByteString starts byte string encoding of indefinite length. // Subsequent calls of (*Encoder).Encode() encodes definite length byte strings // ("chunks") as one continguous 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 continguous 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{0xff}) if err == nil { enc.indefTypes = enc.indefTypes[:len(enc.indefTypes)-1] } return err } var cborIndefHeader = map[cborType][]byte{ cborTypeByteString: {0x5f}, cborTypeTextString: {0x7f}, cborTypeArray: {0x9f}, cborTypeMap: {0xbf}, } 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. It implements Marshaler and // Unmarshaler interfaces and can be used to delay CBOR decoding or // precompute a CBOR encoding. type RawMessage []byte // MarshalCBOR returns m as the CBOR encoding of m. func (m RawMessage) MarshalCBOR() ([]byte, error) { if len(m) == 0 { return cborNil, nil } return m, nil } // UnmarshalCBOR sets *m to a copy of data. 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 }