git.gammaspectra.live/P2Pool/go-json@v0.99.0/internal/decoder/uint.go (about)

     1  package decoder
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"unsafe"
     7  
     8  	"git.gammaspectra.live/P2Pool/go-json/internal/errors"
     9  	"git.gammaspectra.live/P2Pool/go-json/internal/runtime"
    10  )
    11  
    12  type uintDecoder struct {
    13  	typ        *runtime.Type
    14  	kind       reflect.Kind
    15  	op         func(unsafe.Pointer, uint64)
    16  	structName string
    17  	fieldName  string
    18  }
    19  
    20  func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder {
    21  	return &uintDecoder{
    22  		typ:        typ,
    23  		kind:       typ.Kind(),
    24  		op:         op,
    25  		structName: structName,
    26  		fieldName:  fieldName,
    27  	}
    28  }
    29  
    30  func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
    31  	return &errors.UnmarshalTypeError{
    32  		Value:  fmt.Sprintf("number %s", string(buf)),
    33  		Type:   runtime.RType2Type(d.typ),
    34  		Offset: offset,
    35  	}
    36  }
    37  
    38  var (
    39  	pow10u64 = [...]uint64{
    40  		1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
    41  		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
    42  	}
    43  	pow10u64Len = len(pow10u64)
    44  )
    45  
    46  func (d *uintDecoder) parseUint(b []byte) (uint64, error) {
    47  	maxDigit := len(b)
    48  	if maxDigit > pow10u64Len {
    49  		return 0, fmt.Errorf("invalid length of number")
    50  	}
    51  	sum := uint64(0)
    52  	for i := 0; i < maxDigit; i++ {
    53  		c := uint64(b[i]) - 48
    54  		digitValue := pow10u64[maxDigit-i-1]
    55  		sum += c * digitValue
    56  	}
    57  	return sum, nil
    58  }
    59  
    60  func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
    61  	for {
    62  		switch s.char() {
    63  		case ' ', '\n', '\t', '\r':
    64  			s.cursor++
    65  			continue
    66  		case '0':
    67  			s.cursor++
    68  			return numZeroBuf, nil
    69  		case '1', '2', '3', '4', '5', '6', '7', '8', '9':
    70  			start := s.cursor
    71  			for {
    72  				s.cursor++
    73  				if numTable[s.char()] {
    74  					continue
    75  				} else if s.char() == nul {
    76  					if s.read() {
    77  						s.cursor-- // for retry current character
    78  						continue
    79  					}
    80  				}
    81  				break
    82  			}
    83  			num := s.buf[start:s.cursor]
    84  			return num, nil
    85  		case 'n':
    86  			if err := nullBytes(s); err != nil {
    87  				return nil, err
    88  			}
    89  			return nil, nil
    90  		case nul:
    91  			if s.read() {
    92  				continue
    93  			}
    94  		default:
    95  			return nil, d.typeError([]byte{s.char()}, s.totalOffset())
    96  		}
    97  		break
    98  	}
    99  	return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset())
   100  }
   101  
   102  func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
   103  	for {
   104  		switch buf[cursor] {
   105  		case ' ', '\n', '\t', '\r':
   106  			cursor++
   107  			continue
   108  		case '0':
   109  			cursor++
   110  			return numZeroBuf, cursor, nil
   111  		case '1', '2', '3', '4', '5', '6', '7', '8', '9':
   112  			start := cursor
   113  			cursor++
   114  			for numTable[buf[cursor]] {
   115  				cursor++
   116  			}
   117  			num := buf[start:cursor]
   118  			return num, cursor, nil
   119  		case 'n':
   120  			if err := validateNull(buf, cursor); err != nil {
   121  				return nil, 0, err
   122  			}
   123  			cursor += 4
   124  			return nil, cursor, nil
   125  		default:
   126  			return nil, 0, d.typeError([]byte{buf[cursor]}, cursor)
   127  		}
   128  	}
   129  }
   130  
   131  func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
   132  	bytes, err := d.decodeStreamByte(s)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	if bytes == nil {
   137  		return nil
   138  	}
   139  	u64, err := d.parseUint(bytes)
   140  	if err != nil {
   141  		return d.typeError(bytes, s.totalOffset())
   142  	}
   143  	switch d.kind {
   144  	case reflect.Uint8:
   145  		if (1 << 8) <= u64 {
   146  			return d.typeError(bytes, s.totalOffset())
   147  		}
   148  	case reflect.Uint16:
   149  		if (1 << 16) <= u64 {
   150  			return d.typeError(bytes, s.totalOffset())
   151  		}
   152  	case reflect.Uint32:
   153  		if (1 << 32) <= u64 {
   154  			return d.typeError(bytes, s.totalOffset())
   155  		}
   156  	}
   157  	d.op(p, u64)
   158  	return nil
   159  }
   160  
   161  func (d *uintDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
   162  	bytes, c, err := d.decodeByte(ctx.Buf, cursor)
   163  	if err != nil {
   164  		return 0, err
   165  	}
   166  	if bytes == nil {
   167  		return c, nil
   168  	}
   169  	cursor = c
   170  	u64, err := d.parseUint(bytes)
   171  	if err != nil {
   172  		return 0, d.typeError(bytes, cursor)
   173  	}
   174  	switch d.kind {
   175  	case reflect.Uint8:
   176  		if (1 << 8) <= u64 {
   177  			return 0, d.typeError(bytes, cursor)
   178  		}
   179  	case reflect.Uint16:
   180  		if (1 << 16) <= u64 {
   181  			return 0, d.typeError(bytes, cursor)
   182  		}
   183  	case reflect.Uint32:
   184  		if (1 << 32) <= u64 {
   185  			return 0, d.typeError(bytes, cursor)
   186  		}
   187  	}
   188  	d.op(p, u64)
   189  	return cursor, nil
   190  }
   191  
   192  func (d *uintDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
   193  	return nil, 0, fmt.Errorf("json: uint decoder does not support decode path")
   194  }