github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/json/badjson/typed.go (about)

     1  package badjson
     2  
     3  import (
     4  	"bytes"
     5  	"strings"
     6  
     7  	E "github.com/sagernet/sing/common/exceptions"
     8  	"github.com/sagernet/sing/common/json"
     9  	"github.com/sagernet/sing/common/x/linkedhashmap"
    10  )
    11  
    12  type TypedMap[K comparable, V any] struct {
    13  	linkedhashmap.Map[K, V]
    14  }
    15  
    16  func (m TypedMap[K, V]) MarshalJSON() ([]byte, error) {
    17  	buffer := new(bytes.Buffer)
    18  	buffer.WriteString("{")
    19  	items := m.Entries()
    20  	iLen := len(items)
    21  	for i, entry := range items {
    22  		keyContent, err := json.Marshal(entry.Key)
    23  		if err != nil {
    24  			return nil, err
    25  		}
    26  		buffer.WriteString(strings.TrimSpace(string(keyContent)))
    27  		buffer.WriteString(": ")
    28  		valueContent, err := json.Marshal(entry.Value)
    29  		if err != nil {
    30  			return nil, err
    31  		}
    32  		buffer.WriteString(strings.TrimSpace(string(valueContent)))
    33  		if i < iLen-1 {
    34  			buffer.WriteString(", ")
    35  		}
    36  	}
    37  	buffer.WriteString("}")
    38  	return buffer.Bytes(), nil
    39  }
    40  
    41  func (m *TypedMap[K, V]) UnmarshalJSON(content []byte) error {
    42  	decoder := json.NewDecoder(bytes.NewReader(content))
    43  	m.Clear()
    44  	objectStart, err := decoder.Token()
    45  	if err != nil {
    46  		return err
    47  	} else if objectStart != json.Delim('{') {
    48  		return E.New("expected json object start, but starts with ", objectStart)
    49  	}
    50  	err = m.decodeJSON(decoder)
    51  	if err != nil {
    52  		return E.Cause(err, "decode json object content")
    53  	}
    54  	objectEnd, err := decoder.Token()
    55  	if err != nil {
    56  		return err
    57  	} else if objectEnd != json.Delim('}') {
    58  		return E.New("expected json object end, but ends with ", objectEnd)
    59  	}
    60  	return nil
    61  }
    62  
    63  func (m *TypedMap[K, V]) decodeJSON(decoder *json.Decoder) error {
    64  	for decoder.More() {
    65  		keyToken, err := decoder.Token()
    66  		if err != nil {
    67  			return err
    68  		}
    69  		keyContent, err := json.Marshal(keyToken)
    70  		if err != nil {
    71  			return err
    72  		}
    73  		var entryKey K
    74  		err = json.Unmarshal(keyContent, &entryKey)
    75  		if err != nil {
    76  			return err
    77  		}
    78  		var entryValue V
    79  		err = decoder.Decode(&entryValue)
    80  		if err != nil {
    81  			return err
    82  		}
    83  		m.Put(entryKey, entryValue)
    84  	}
    85  	return nil
    86  }