1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
package cose
import (
"errors"
"fmt"
)
// intOrStr is a value that can be either an int or a tstr when serialized to
// CBOR.
type intOrStr struct {
intVal int64
strVal string
isString bool
}
func newIntOrStr(v interface{}) *intOrStr {
var ios intOrStr
if err := ios.Set(v); err != nil {
return nil
}
return &ios
}
func (ios intOrStr) Int() int64 {
return ios.intVal
}
func (ios intOrStr) String() string {
if ios.IsString() {
return ios.strVal
}
return fmt.Sprint(ios.intVal)
}
func (ios intOrStr) IsInt() bool {
return !ios.isString
}
func (ios intOrStr) IsString() bool {
return ios.isString
}
func (ios intOrStr) Value() interface{} {
if ios.IsInt() {
return ios.intVal
}
return ios.strVal
}
func (ios *intOrStr) Set(v interface{}) error {
switch t := v.(type) {
case int64:
ios.intVal = t
ios.strVal = ""
ios.isString = false
case int:
ios.intVal = int64(t)
ios.strVal = ""
ios.isString = false
case string:
ios.strVal = t
ios.intVal = 0
ios.isString = true
default:
return fmt.Errorf("must be int or string, found %T", t)
}
return nil
}
// MarshalCBOR returns the encoded CBOR representation of the intOrString, as
// either int or tstr, depending on the value. If no value has been set,
// intOrStr is encoded as a zero-length tstr.
func (ios intOrStr) MarshalCBOR() ([]byte, error) {
if ios.IsInt() {
return encMode.Marshal(ios.intVal)
}
return encMode.Marshal(ios.strVal)
}
// UnmarshalCBOR unmarshals the provided CBOR encoded data (must be an int,
// uint, or tstr).
func (ios *intOrStr) UnmarshalCBOR(data []byte) error {
if len(data) == 0 {
return errors.New("zero length buffer")
}
var val interface{}
if err := decMode.Unmarshal(data, &val); err != nil {
return err
}
return ios.Set(val)
}
|