gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

value_encoder.go (6439B)


      1 package exifcommon
      2 
      3 import (
      4 	"bytes"
      5 	"math"
      6 	"reflect"
      7 	"time"
      8 
      9 	"encoding/binary"
     10 
     11 	"github.com/dsoprea/go-logging"
     12 )
     13 
     14 var (
     15 	typeEncodeLogger = log.NewLogger("exif.type_encode")
     16 )
     17 
     18 // EncodedData encapsulates the compound output of an encoding operation.
     19 type EncodedData struct {
     20 	Type    TagTypePrimitive
     21 	Encoded []byte
     22 
     23 	// TODO(dustin): Is this really necessary? We might have this just to correlate to the incoming stream format (raw bytes and a unit-count both for incoming and outgoing).
     24 	UnitCount uint32
     25 }
     26 
     27 // ValueEncoder knows how to encode values of every type to bytes.
     28 type ValueEncoder struct {
     29 	byteOrder binary.ByteOrder
     30 }
     31 
     32 // NewValueEncoder returns a new ValueEncoder.
     33 func NewValueEncoder(byteOrder binary.ByteOrder) *ValueEncoder {
     34 	return &ValueEncoder{
     35 		byteOrder: byteOrder,
     36 	}
     37 }
     38 
     39 func (ve *ValueEncoder) encodeBytes(value []uint8) (ed EncodedData, err error) {
     40 	ed.Type = TypeByte
     41 	ed.Encoded = []byte(value)
     42 	ed.UnitCount = uint32(len(value))
     43 
     44 	return ed, nil
     45 }
     46 
     47 func (ve *ValueEncoder) encodeAscii(value string) (ed EncodedData, err error) {
     48 	ed.Type = TypeAscii
     49 
     50 	ed.Encoded = []byte(value)
     51 	ed.Encoded = append(ed.Encoded, 0)
     52 
     53 	ed.UnitCount = uint32(len(ed.Encoded))
     54 
     55 	return ed, nil
     56 }
     57 
     58 // encodeAsciiNoNul returns a string encoded as a byte-string without a trailing
     59 // NUL byte.
     60 //
     61 // Note that:
     62 //
     63 // 1. This type can not be automatically encoded using `Encode()`. The default
     64 //    mode is to encode *with* a trailing NUL byte using `encodeAscii`. Only
     65 //    certain undefined-type tags using an unterminated ASCII string and these
     66 //    are exceptional in nature.
     67 //
     68 // 2. The presence of this method allows us to completely test the complimentary
     69 //    no-nul parser.
     70 //
     71 func (ve *ValueEncoder) encodeAsciiNoNul(value string) (ed EncodedData, err error) {
     72 	ed.Type = TypeAsciiNoNul
     73 	ed.Encoded = []byte(value)
     74 	ed.UnitCount = uint32(len(ed.Encoded))
     75 
     76 	return ed, nil
     77 }
     78 
     79 func (ve *ValueEncoder) encodeShorts(value []uint16) (ed EncodedData, err error) {
     80 	defer func() {
     81 		if state := recover(); state != nil {
     82 			err = log.Wrap(state.(error))
     83 		}
     84 	}()
     85 
     86 	ed.UnitCount = uint32(len(value))
     87 	ed.Encoded = make([]byte, ed.UnitCount*2)
     88 
     89 	for i := uint32(0); i < ed.UnitCount; i++ {
     90 		ve.byteOrder.PutUint16(ed.Encoded[i*2:(i+1)*2], value[i])
     91 	}
     92 
     93 	ed.Type = TypeShort
     94 
     95 	return ed, nil
     96 }
     97 
     98 func (ve *ValueEncoder) encodeLongs(value []uint32) (ed EncodedData, err error) {
     99 	defer func() {
    100 		if state := recover(); state != nil {
    101 			err = log.Wrap(state.(error))
    102 		}
    103 	}()
    104 
    105 	ed.UnitCount = uint32(len(value))
    106 	ed.Encoded = make([]byte, ed.UnitCount*4)
    107 
    108 	for i := uint32(0); i < ed.UnitCount; i++ {
    109 		ve.byteOrder.PutUint32(ed.Encoded[i*4:(i+1)*4], value[i])
    110 	}
    111 
    112 	ed.Type = TypeLong
    113 
    114 	return ed, nil
    115 }
    116 
    117 func (ve *ValueEncoder) encodeFloats(value []float32) (ed EncodedData, err error) {
    118 	defer func() {
    119 		if state := recover(); state != nil {
    120 			err = log.Wrap(state.(error))
    121 		}
    122 	}()
    123 
    124 	ed.UnitCount = uint32(len(value))
    125 	ed.Encoded = make([]byte, ed.UnitCount*4)
    126 
    127 	for i := uint32(0); i < ed.UnitCount; i++ {
    128 		ve.byteOrder.PutUint32(ed.Encoded[i*4:(i+1)*4], math.Float32bits(value[i]))
    129 	}
    130 
    131 	ed.Type = TypeFloat
    132 
    133 	return ed, nil
    134 }
    135 
    136 func (ve *ValueEncoder) encodeDoubles(value []float64) (ed EncodedData, err error) {
    137 	defer func() {
    138 		if state := recover(); state != nil {
    139 			err = log.Wrap(state.(error))
    140 		}
    141 	}()
    142 
    143 	ed.UnitCount = uint32(len(value))
    144 	ed.Encoded = make([]byte, ed.UnitCount*8)
    145 
    146 	for i := uint32(0); i < ed.UnitCount; i++ {
    147 		ve.byteOrder.PutUint64(ed.Encoded[i*8:(i+1)*8], math.Float64bits(value[i]))
    148 	}
    149 
    150 	ed.Type = TypeDouble
    151 
    152 	return ed, nil
    153 }
    154 
    155 func (ve *ValueEncoder) encodeRationals(value []Rational) (ed EncodedData, err error) {
    156 	defer func() {
    157 		if state := recover(); state != nil {
    158 			err = log.Wrap(state.(error))
    159 		}
    160 	}()
    161 
    162 	ed.UnitCount = uint32(len(value))
    163 	ed.Encoded = make([]byte, ed.UnitCount*8)
    164 
    165 	for i := uint32(0); i < ed.UnitCount; i++ {
    166 		ve.byteOrder.PutUint32(ed.Encoded[i*8+0:i*8+4], value[i].Numerator)
    167 		ve.byteOrder.PutUint32(ed.Encoded[i*8+4:i*8+8], value[i].Denominator)
    168 	}
    169 
    170 	ed.Type = TypeRational
    171 
    172 	return ed, nil
    173 }
    174 
    175 func (ve *ValueEncoder) encodeSignedLongs(value []int32) (ed EncodedData, err error) {
    176 	defer func() {
    177 		if state := recover(); state != nil {
    178 			err = log.Wrap(state.(error))
    179 		}
    180 	}()
    181 
    182 	ed.UnitCount = uint32(len(value))
    183 
    184 	b := bytes.NewBuffer(make([]byte, 0, 8*ed.UnitCount))
    185 
    186 	for i := uint32(0); i < ed.UnitCount; i++ {
    187 		err := binary.Write(b, ve.byteOrder, value[i])
    188 		log.PanicIf(err)
    189 	}
    190 
    191 	ed.Type = TypeSignedLong
    192 	ed.Encoded = b.Bytes()
    193 
    194 	return ed, nil
    195 }
    196 
    197 func (ve *ValueEncoder) encodeSignedRationals(value []SignedRational) (ed EncodedData, err error) {
    198 	defer func() {
    199 		if state := recover(); state != nil {
    200 			err = log.Wrap(state.(error))
    201 		}
    202 	}()
    203 
    204 	ed.UnitCount = uint32(len(value))
    205 
    206 	b := bytes.NewBuffer(make([]byte, 0, 8*ed.UnitCount))
    207 
    208 	for i := uint32(0); i < ed.UnitCount; i++ {
    209 		err := binary.Write(b, ve.byteOrder, value[i].Numerator)
    210 		log.PanicIf(err)
    211 
    212 		err = binary.Write(b, ve.byteOrder, value[i].Denominator)
    213 		log.PanicIf(err)
    214 	}
    215 
    216 	ed.Type = TypeSignedRational
    217 	ed.Encoded = b.Bytes()
    218 
    219 	return ed, nil
    220 }
    221 
    222 // Encode returns bytes for the given value, infering type from the actual
    223 // value. This does not support `TypeAsciiNoNull` (all strings are encoded as
    224 // `TypeAscii`).
    225 func (ve *ValueEncoder) Encode(value interface{}) (ed EncodedData, err error) {
    226 	defer func() {
    227 		if state := recover(); state != nil {
    228 			err = log.Wrap(state.(error))
    229 		}
    230 	}()
    231 
    232 	switch t := value.(type) {
    233 	case []byte:
    234 		ed, err = ve.encodeBytes(t)
    235 		log.PanicIf(err)
    236 	case string:
    237 		ed, err = ve.encodeAscii(t)
    238 		log.PanicIf(err)
    239 	case []uint16:
    240 		ed, err = ve.encodeShorts(t)
    241 		log.PanicIf(err)
    242 	case []uint32:
    243 		ed, err = ve.encodeLongs(t)
    244 		log.PanicIf(err)
    245 	case []float32:
    246 		ed, err = ve.encodeFloats(t)
    247 		log.PanicIf(err)
    248 	case []float64:
    249 		ed, err = ve.encodeDoubles(t)
    250 		log.PanicIf(err)
    251 	case []Rational:
    252 		ed, err = ve.encodeRationals(t)
    253 		log.PanicIf(err)
    254 	case []int32:
    255 		ed, err = ve.encodeSignedLongs(t)
    256 		log.PanicIf(err)
    257 	case []SignedRational:
    258 		ed, err = ve.encodeSignedRationals(t)
    259 		log.PanicIf(err)
    260 	case time.Time:
    261 		// For convenience, if the user doesn't want to deal with translation
    262 		// semantics with timestamps.
    263 
    264 		s := ExifFullTimestampString(t)
    265 
    266 		ed, err = ve.encodeAscii(s)
    267 		log.PanicIf(err)
    268 	default:
    269 		log.Panicf("value not encodable: [%s] [%v]", reflect.TypeOf(value), value)
    270 	}
    271 
    272 	return ed, nil
    273 }