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 }