1
1
mirror of https://github.com/go-gitea/gitea synced 2024-06-01 08:55:47 +00:00
gitea/vendor/github.com/fxamacker/cbor/v2/stream.go
Lunny Xiao 35c3553870
Support webauthn (#17957)
Migrate from U2F to Webauthn

Co-authored-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-01-14 16:03:31 +01:00

197 lines
5.4 KiB
Go
Vendored

// 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
}