1 // In this file, JSON refers to WTF-JSON.
3 // BUG(mt): Itemstrings use variant of JSON called WTF-JSON
4 // where \u00XX escapes in string literals act like Go's \xXX escapes.
5 // This should not be fixed because it would break existing items.
28 // String returns the Stack's itemstring.
30 // BUG(mt): The term itemstring is somewhat misleading, because
31 // an itemstring represents a stack of items, not a single item.
32 func (s Stack) String() string {
40 } else if s.Wear > 0 {
42 } else if s.Count > 1 {
46 return strings.Join([]string{
50 optJSONStr(string(s.ItemMeta)),
54 func optJSONStr(s string) string {
56 if r <= ' ' || r == '"' || r >= utf8.RuneSelf {
63 func jsonStr(s string) string {
75 b := new(strings.Builder)
78 for i := 0; i < len(s); i++ {
81 fmt.Fprintf(b, "\\%c", esc[c])
82 case ' ' <= c && c <= '~':
85 fmt.Fprintf(b, "\\u%04x", c)
93 // Scan scans an itemstring, implementing the fmt.Scanner interface.
94 func (stk *Stack) Scan(state fmt.ScanState, verb rune) (err error) {
103 nm, err := scanOptJSONStr(state)
110 if _, err := fmt.Fscan(state, &stk.Count, &stk.Wear); err != nil {
114 s, err := scanOptJSONStr(state)
118 stk.ItemMeta = ItemMeta(s)
123 func scanOptJSONStr(state fmt.ScanState) (string, error) {
126 r, _, err := state.ReadRune()
133 return scanJSONStr(state)
136 token, err := state.Token(false, func(r rune) bool {
137 return r != ' ' && r != '\n'
139 return string(token), err
142 func scanJSONStr(state fmt.ScanState) (s string, rerr error) {
143 r, _, err := state.ReadRune()
148 return "", fmt.Errorf("unexpected rune: %q", r)
153 rerr = io.ErrUnexpectedEOF
157 b := new(strings.Builder)
159 r, _, err := state.ReadRune()
161 return b.String(), err
166 return b.String(), nil
168 r, _, err := state.ReadRune()
170 return b.String(), err
189 r, _, err := state.ReadRune()
191 return b.String(), err
195 n, err := strconv.ParseUint(string(hex[:]), 16, 8)
197 return b.String(), err
201 return b.String(), fmt.Errorf("invalid escape: \\%c", r)