github.com/abemedia/appcast@v0.4.0/integrations/apt/deb/decode.go (about) 1 package deb 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding" 7 "encoding/hex" 8 "errors" 9 "fmt" 10 "io" 11 "reflect" 12 "strconv" 13 "sync" 14 "time" 15 ) 16 17 var decoders sync.Map //nolint:gochecknoglobals 18 19 type decoder func(*bufio.Reader, reflect.Value) error 20 21 func Unmarshal(b []byte, v any) error { 22 return NewDecoder(bytes.NewReader(b)).Decode(v) 23 } 24 25 type Decoder struct{ r *bufio.Reader } 26 27 func NewDecoder(r io.Reader) *Decoder { 28 return &Decoder{bufio.NewReader(r)} 29 } 30 31 func (d *Decoder) Decode(v any) error { 32 if v == nil { 33 return errors.New("unsupported type: nil") 34 } 35 36 val := reflect.ValueOf(v) 37 typ := val.Type() 38 39 if typ.Kind() != reflect.Pointer { 40 return errors.New("must use pointer") 41 } 42 43 if dec, ok := decoders.Load(typ); ok { 44 err := dec.(decoder)(d.r, val) //nolint:forcetypeassert 45 if err == io.EOF { 46 return errors.New("unexpected end of input") 47 } 48 return err 49 } 50 51 dec, err := newDecoder(typ) 52 if err != nil { 53 return err 54 } 55 decoders.Store(typ, dec) 56 return dec(d.r, val) 57 } 58 59 //nolint:gochecknoglobals 60 var unmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() 61 62 func newDecoder(typ reflect.Type) (decoder, error) { 63 switch { 64 case typ == dateType: 65 return newDateDecoder(typ) 66 case typ.Implements(unmarshalerType), reflect.PointerTo(typ).Implements(unmarshalerType): 67 return newUnmarshalerDecoder(typ) 68 } 69 70 switch typ.Kind() { 71 case reflect.Ptr: 72 return newPtrDecoder(typ) 73 case reflect.Slice: 74 return newSliceDecoder(typ) 75 case reflect.Struct: 76 return newStructDecoder(typ) 77 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 78 return newIntDecoder(typ) 79 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 80 return newUintDecoder(typ) 81 case reflect.Float32, reflect.Float64: 82 return newFloatDecoder(typ) 83 case reflect.String: 84 return newStringDecoder(typ) 85 case reflect.Array: 86 if typ.Elem().Kind() == reflect.Uint8 { 87 return newByteArrayDecoder(typ) 88 } 89 } 90 91 return nil, fmt.Errorf("unsupported type: %s", typ) 92 } 93 94 func newUnmarshalerDecoder(typ reflect.Type) (decoder, error) { 95 mustAddr := reflect.PointerTo(typ).Implements(unmarshalerType) 96 isPtr := typ.Kind() == reflect.Pointer 97 if isPtr { 98 typ = typ.Elem() 99 } 100 101 return func(r *bufio.Reader, v reflect.Value) error { 102 b, err := readlines(r) 103 if err != nil || len(b) == 0 { 104 return err 105 } 106 if isPtr && v.IsNil() { 107 v.Set(reflect.New(typ)) 108 } 109 if mustAddr { 110 v = v.Addr() 111 } 112 return v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b) //nolint:forcetypeassert 113 }, nil 114 } 115 116 func newPtrDecoder(typ reflect.Type) (decoder, error) { 117 typ = typ.Elem() 118 dec, err := newDecoder(typ) 119 if err != nil { 120 return nil, err 121 } 122 return func(r *bufio.Reader, v reflect.Value) error { 123 if v.IsNil() { 124 v.Set(reflect.New(typ)) 125 } 126 return dec(r, v.Elem()) 127 }, nil 128 } 129 130 func newSliceDecoder(typ reflect.Type) (decoder, error) { 131 typ = typ.Elem() 132 dec, err := newDecoder(typ) 133 if err != nil { 134 return nil, err 135 } 136 137 return func(r *bufio.Reader, v reflect.Value) error { 138 v.SetLen(0) 139 140 for { 141 for { 142 b, err := r.ReadByte() 143 if err == io.EOF { 144 return nil 145 } 146 if err != nil { 147 return err 148 } 149 if b != '\n' && b != '\r' { 150 _ = r.UnreadByte() 151 break 152 } 153 } 154 elem := reflect.New(typ).Elem() 155 if err := dec(r, elem); err != nil { 156 return err 157 } 158 v.Set(reflect.Append(v, elem)) 159 } 160 }, nil 161 } 162 163 func newStructDecoder(typ reflect.Type) (decoder, error) { 164 decoders := map[string]decoder{} 165 166 for i := 0; i < typ.NumField(); i++ { 167 i := i 168 field := typ.Field(i) 169 170 name := getFieldName(field) 171 if name == "" { 172 continue 173 } 174 175 dec, err := newDecoder(field.Type) 176 if err != nil { 177 return nil, err 178 } 179 180 decoders[name] = func(r *bufio.Reader, v reflect.Value) error { 181 return dec(r, v.Field(i)) 182 } 183 } 184 185 return func(r *bufio.Reader, v reflect.Value) error { 186 for { 187 c, err := r.Peek(1) 188 if err != nil && err != io.EOF { 189 return err 190 } 191 if err == io.EOF || c[0] == '\n' || c[0] == '\r' { 192 return nil 193 } 194 b, err := r.ReadSlice(':') 195 if err != nil { 196 return err 197 } 198 if i := bytes.IndexByte(b, '\n'); i != -1 { 199 return fmt.Errorf("invalid line: %q", b[:i]) 200 } 201 if dec := decoders[btoa(trim(b)[:len(b)-1])]; dec != nil { 202 if err := dec(r, v); err != nil { 203 return err 204 } 205 } else { 206 _, _ = readlines(r) // Discard value for unknown key. 207 } 208 } 209 }, nil 210 } 211 212 func newDateDecoder(reflect.Type) (decoder, error) { 213 return func(r *bufio.Reader, v reflect.Value) error { 214 b, err := readline(r) 215 if err != nil || len(b) == 0 { 216 return err 217 } 218 t, err := time.Parse(time.RFC1123, btoa(b)) 219 if err != nil { 220 return err 221 } 222 if !t.IsZero() { 223 v.Set(reflect.ValueOf(t)) 224 } 225 return nil 226 }, nil 227 } 228 229 func newIntDecoder(typ reflect.Type) (decoder, error) { 230 bits := typ.Bits() 231 return func(r *bufio.Reader, v reflect.Value) error { 232 b, err := readline(r) 233 if err != nil || len(b) == 0 { 234 return err 235 } 236 i, err := strconv.ParseInt(btoa(b), 10, bits) 237 if err != nil { 238 return err 239 } 240 v.SetInt(i) 241 return nil 242 }, nil 243 } 244 245 func newUintDecoder(typ reflect.Type) (decoder, error) { 246 bits := typ.Bits() 247 return func(r *bufio.Reader, v reflect.Value) error { 248 b, err := readline(r) 249 if err != nil || len(b) == 0 { 250 return err 251 } 252 i, err := strconv.ParseUint(btoa(b), 10, bits) 253 if err != nil { 254 return err 255 } 256 v.SetUint(i) 257 return nil 258 }, nil 259 } 260 261 func newFloatDecoder(typ reflect.Type) (decoder, error) { 262 bits := typ.Bits() 263 return func(r *bufio.Reader, v reflect.Value) error { 264 b, err := readline(r) 265 if err != nil || len(b) == 0 { 266 return err 267 } 268 i, err := strconv.ParseFloat(btoa(b), bits) 269 if err != nil { 270 return err 271 } 272 v.SetFloat(i) 273 return nil 274 }, nil 275 } 276 277 func newStringDecoder(reflect.Type) (decoder, error) { 278 return func(r *bufio.Reader, v reflect.Value) error { 279 b, err := readlines(r) 280 if err != nil { 281 return err 282 } 283 v.SetString(btoa(b)) 284 return nil 285 }, nil 286 } 287 288 func newByteArrayDecoder(typ reflect.Type) (decoder, error) { 289 size := typ.Len() 290 return func(r *bufio.Reader, v reflect.Value) error { 291 b, err := readline(r) 292 if err != nil || len(b) == 0 { 293 return err 294 } 295 if hex.DecodedLen(len(b)) > size { 296 return errors.New("hex data would overflow byte array") 297 } 298 out := make([]byte, size) 299 if _, err = hex.Decode(out, b); err != nil { 300 return err 301 } 302 for i, x := range out { 303 v.Index(i).SetUint(uint64(x)) 304 } 305 return nil 306 }, nil 307 } 308 309 func readline(r *bufio.Reader) ([]byte, error) { 310 b, err := r.ReadSlice('\n') 311 if err != nil { 312 return nil, err 313 } 314 return trim(b), nil 315 } 316 317 func readlines(r *bufio.Reader) ([]byte, error) { 318 b, err := readline(r) 319 if err != nil { 320 return nil, err 321 } 322 323 for { 324 p, err := r.Peek(1) 325 if err != nil && err != io.EOF { 326 return nil, err 327 } 328 if err == io.EOF || p[0] != ' ' && p[0] != '\t' { 329 break 330 } 331 l, err := readline(r) 332 if err != nil { 333 return nil, err 334 } 335 b = append(b, '\n') 336 if len(l) != 1 || l[0] != '.' { 337 b = append(b, l...) 338 } 339 } 340 341 return b, nil 342 }