summaryrefslogtreecommitdiff
path: root/compat/json/compat.go
blob: 78a9d5ff3ce37ea2a56cbb97fde53a3eafc3caab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright (C) 2022  Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later

package json

import (
	"bufio"
	"bytes"
	"encoding/json"
	"io"

	"git.lukeshu.com/go/lowmemjson"
)

type (
	Number     = json.Number
	Marshaler  = json.Marshaler
	RawMessage = json.RawMessage

	// low-level decode errors
	SyntaxError         = lowmemjson.SyntaxError
	UnmarshalFieldError = json.UnmarshalFieldError
	UnmarshalTypeError  = json.UnmarshalTypeError // lowmemjson.DecodeTypeError

	// high-level decode errors
	InvalidUnmarshalError = json.InvalidUnmarshalError // lowmemjson.DecodeArgumentError

	// marshal errors
	InvalidUTF8Error      = json.InvalidUTF8Error
	MarshalerError        = json.MarshalerError
	UnsupportedTypeError  = json.UnsupportedTypeError
	UnsupportedValueError = json.UnsupportedValueError
)

/////////////////////////////////////////////////////////////////////

func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
	var buf bytes.Buffer
	formatter := &lowmemjson.ReEncoder{
		Out:    &buf,
		Indent: indent,
		Prefix: prefix,
	}
	err := lowmemjson.Encode(formatter, v)
	return buf.Bytes(), err
}

func Marshal(v any) ([]byte, error) {
	var buf bytes.Buffer
	formatter := &lowmemjson.ReEncoder{
		Out:     &buf,
		Compact: true,
	}
	err := lowmemjson.Encode(formatter, v)
	return buf.Bytes(), err
}

func HTMLEscape(dst *bytes.Buffer, src []byte) {
	formatter := &lowmemjson.ReEncoder{
		Out: dst,
	}
	_, _ = formatter.Write(src)
}

func Compact(dst *bytes.Buffer, src []byte) error {
	formatter := &lowmemjson.ReEncoder{
		Out:     dst,
		Compact: true,
	}
	_, err := formatter.Write(src)
	return err
}

func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
	formatter := &lowmemjson.ReEncoder{
		Out:    dst,
		Indent: indent,
		Prefix: prefix,
	}
	_, err := formatter.Write(src)
	return err
}

func Valid(data []byte) bool {
	formatter := &lowmemjson.ReEncoder{
		Out:     io.Discard,
		Compact: true,
	}
	_, err := formatter.Write(data)
	return err == nil
}

func Unmarshal(data []byte, ptr any) error {
	return lowmemjson.Decode(bytes.NewReader(data), ptr)
}

/////////////////////////////////////////////////////////////////////

type Decoder struct {
	*lowmemjson.Decoder
	buf *bufio.Reader
}

func NewDecoder(r io.Reader) *Decoder {
	br, ok := r.(*bufio.Reader)
	if !ok {
		br = bufio.NewReader(r)
	}
	return &Decoder{
		Decoder: lowmemjson.NewDecoder(br),
		buf:     br,
	}
}

func (dec *Decoder) Buffered() io.Reader {
	dat, _ := dec.buf.Peek(dec.buf.Buffered())
	return bytes.NewReader(dat)
}

//func (dec *Decoder) Token() (Token, error)