gtsocial-umbx

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

intern.go (5029B)


      1 package msgpack
      2 
      3 import (
      4 	"fmt"
      5 	"math"
      6 	"reflect"
      7 
      8 	"github.com/vmihailenco/msgpack/v5/msgpcode"
      9 )
     10 
     11 const (
     12 	minInternedStringLen = 3
     13 	maxDictLen           = math.MaxUint16
     14 )
     15 
     16 var internedStringExtID = int8(math.MinInt8)
     17 
     18 func init() {
     19 	extTypes[internedStringExtID] = &extInfo{
     20 		Type:    stringType,
     21 		Decoder: decodeInternedStringExt,
     22 	}
     23 }
     24 
     25 func decodeInternedStringExt(d *Decoder, v reflect.Value, extLen int) error {
     26 	idx, err := d.decodeInternedStringIndex(extLen)
     27 	if err != nil {
     28 		return err
     29 	}
     30 
     31 	s, err := d.internedStringAtIndex(idx)
     32 	if err != nil {
     33 		return err
     34 	}
     35 
     36 	v.SetString(s)
     37 	return nil
     38 }
     39 
     40 //------------------------------------------------------------------------------
     41 
     42 func encodeInternedInterfaceValue(e *Encoder, v reflect.Value) error {
     43 	if v.IsNil() {
     44 		return e.EncodeNil()
     45 	}
     46 
     47 	v = v.Elem()
     48 	if v.Kind() == reflect.String {
     49 		return e.encodeInternedString(v.String(), true)
     50 	}
     51 	return e.EncodeValue(v)
     52 }
     53 
     54 func encodeInternedStringValue(e *Encoder, v reflect.Value) error {
     55 	return e.encodeInternedString(v.String(), true)
     56 }
     57 
     58 func (e *Encoder) encodeInternedString(s string, intern bool) error {
     59 	// Interned string takes at least 3 bytes. Plain string 1 byte + string len.
     60 	if len(s) >= minInternedStringLen {
     61 		if idx, ok := e.dict[s]; ok {
     62 			return e.encodeInternedStringIndex(idx)
     63 		}
     64 
     65 		if intern && len(e.dict) < maxDictLen {
     66 			if e.dict == nil {
     67 				e.dict = make(map[string]int)
     68 			}
     69 			idx := len(e.dict)
     70 			e.dict[s] = idx
     71 		}
     72 	}
     73 
     74 	return e.encodeNormalString(s)
     75 }
     76 
     77 func (e *Encoder) encodeInternedStringIndex(idx int) error {
     78 	if idx <= math.MaxUint8 {
     79 		if err := e.writeCode(msgpcode.FixExt1); err != nil {
     80 			return err
     81 		}
     82 		return e.write1(byte(internedStringExtID), uint8(idx))
     83 	}
     84 
     85 	if idx <= math.MaxUint16 {
     86 		if err := e.writeCode(msgpcode.FixExt2); err != nil {
     87 			return err
     88 		}
     89 		return e.write2(byte(internedStringExtID), uint16(idx))
     90 	}
     91 
     92 	if uint64(idx) <= math.MaxUint32 {
     93 		if err := e.writeCode(msgpcode.FixExt4); err != nil {
     94 			return err
     95 		}
     96 		return e.write4(byte(internedStringExtID), uint32(idx))
     97 	}
     98 
     99 	return fmt.Errorf("msgpack: interned string index=%d is too large", idx)
    100 }
    101 
    102 //------------------------------------------------------------------------------
    103 
    104 func decodeInternedInterfaceValue(d *Decoder, v reflect.Value) error {
    105 	s, err := d.decodeInternedString(true)
    106 	if err == nil {
    107 		v.Set(reflect.ValueOf(s))
    108 		return nil
    109 	}
    110 	if err != nil {
    111 		if _, ok := err.(unexpectedCodeError); !ok {
    112 			return err
    113 		}
    114 	}
    115 
    116 	if err := d.s.UnreadByte(); err != nil {
    117 		return err
    118 	}
    119 	return decodeInterfaceValue(d, v)
    120 }
    121 
    122 func decodeInternedStringValue(d *Decoder, v reflect.Value) error {
    123 	s, err := d.decodeInternedString(true)
    124 	if err != nil {
    125 		return err
    126 	}
    127 
    128 	v.SetString(s)
    129 	return nil
    130 }
    131 
    132 func (d *Decoder) decodeInternedString(intern bool) (string, error) {
    133 	c, err := d.readCode()
    134 	if err != nil {
    135 		return "", err
    136 	}
    137 
    138 	if msgpcode.IsFixedString(c) {
    139 		n := int(c & msgpcode.FixedStrMask)
    140 		return d.decodeInternedStringWithLen(n, intern)
    141 	}
    142 
    143 	switch c {
    144 	case msgpcode.Nil:
    145 		return "", nil
    146 	case msgpcode.FixExt1, msgpcode.FixExt2, msgpcode.FixExt4:
    147 		typeID, extLen, err := d.extHeader(c)
    148 		if err != nil {
    149 			return "", err
    150 		}
    151 		if typeID != internedStringExtID {
    152 			err := fmt.Errorf("msgpack: got ext type=%d, wanted %d",
    153 				typeID, internedStringExtID)
    154 			return "", err
    155 		}
    156 
    157 		idx, err := d.decodeInternedStringIndex(extLen)
    158 		if err != nil {
    159 			return "", err
    160 		}
    161 
    162 		return d.internedStringAtIndex(idx)
    163 	case msgpcode.Str8, msgpcode.Bin8:
    164 		n, err := d.uint8()
    165 		if err != nil {
    166 			return "", err
    167 		}
    168 		return d.decodeInternedStringWithLen(int(n), intern)
    169 	case msgpcode.Str16, msgpcode.Bin16:
    170 		n, err := d.uint16()
    171 		if err != nil {
    172 			return "", err
    173 		}
    174 		return d.decodeInternedStringWithLen(int(n), intern)
    175 	case msgpcode.Str32, msgpcode.Bin32:
    176 		n, err := d.uint32()
    177 		if err != nil {
    178 			return "", err
    179 		}
    180 		return d.decodeInternedStringWithLen(int(n), intern)
    181 	}
    182 
    183 	return "", unexpectedCodeError{
    184 		code: c,
    185 		hint: "interned string",
    186 	}
    187 }
    188 
    189 func (d *Decoder) decodeInternedStringIndex(extLen int) (int, error) {
    190 	switch extLen {
    191 	case 1:
    192 		n, err := d.uint8()
    193 		if err != nil {
    194 			return 0, err
    195 		}
    196 		return int(n), nil
    197 	case 2:
    198 		n, err := d.uint16()
    199 		if err != nil {
    200 			return 0, err
    201 		}
    202 		return int(n), nil
    203 	case 4:
    204 		n, err := d.uint32()
    205 		if err != nil {
    206 			return 0, err
    207 		}
    208 		return int(n), nil
    209 	}
    210 
    211 	err := fmt.Errorf("msgpack: unsupported ext len=%d decoding interned string", extLen)
    212 	return 0, err
    213 }
    214 
    215 func (d *Decoder) internedStringAtIndex(idx int) (string, error) {
    216 	if idx >= len(d.dict) {
    217 		err := fmt.Errorf("msgpack: interned string at index=%d does not exist", idx)
    218 		return "", err
    219 	}
    220 	return d.dict[idx], nil
    221 }
    222 
    223 func (d *Decoder) decodeInternedStringWithLen(n int, intern bool) (string, error) {
    224 	if n <= 0 {
    225 		return "", nil
    226 	}
    227 
    228 	s, err := d.stringWithLen(n)
    229 	if err != nil {
    230 		return "", err
    231 	}
    232 
    233 	if intern && len(s) >= minInternedStringLen && len(d.dict) < maxDictLen {
    234 		d.dict = append(d.dict, s)
    235 	}
    236 
    237 	return s, nil
    238 }