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  }