1use std::convert::Infallible;
2
3use o3::buffer::ByteSink;
4
5pub trait Write: ByteSink {
6 fn put(&mut self, src: &[u8]) -> Result<(), Self::Error> {
7 self.write_slice(src)
8 }
9
10 fn put_str(&mut self, value: &[u8]) -> Result<(), Self::Error> {
11 self.put(b"\"")?;
12 let mut start = 0usize;
13 let mut idx = 0usize;
14 while idx < value.len() {
15 if let Some(token) = Encode::esc_token(value[idx]) {
16 if start != idx {
17 self.put(&value[start..idx])?;
18 }
19 self.put(token.as_bytes())?;
20 idx += 1;
21 start = idx;
22 continue;
23 }
24 idx += 1;
25 }
26 if start != value.len() {
27 self.put(&value[start..])?;
28 }
29 self.put(b"\"")
30 }
31
32 fn put_str_plain(&mut self, value: &[u8]) -> Result<(), Self::Error> {
33 self.write_slices([b"\"".as_slice(), value, b"\"".as_slice()])
34 }
35
36 fn put_u64(&mut self, value: u64) -> Result<(), Self::Error> {
37 if value == 0 {
38 return self.put(b"0");
39 }
40 let mut digits = [0u8; 20];
41 let mut idx = digits.len();
42 let mut value = value;
43 while value != 0 {
44 idx -= 1;
45 digits[idx] = b'0' + (value % 10) as u8;
46 value /= 10;
47 }
48 self.put(&digits[idx..])
49 }
50
51 fn put_i64(&mut self, value: i64) -> Result<(), Self::Error> {
52 if value < 0 {
53 self.put(b"-")?;
54 }
55 self.put_u64(value.unsigned_abs())
56 }
57
58 fn put_f64(&mut self, value: f64) -> Result<(), Self::Error> {
59 if value.is_finite() {
60 self.put(ryu::Buffer::new().format_finite(value).as_bytes())
61 } else {
62 self.put(b"null")
63 }
64 }
65}
66
67impl<W: ByteSink + ?Sized> Write for W {}
68
69pub struct Writer<'a> {
70 inner: &'a mut Vec<u8>,
71 start: usize,
72}
73
74impl<'a> Writer<'a> {
75 pub fn new(buf: &'a mut Vec<u8>, estimate: usize) -> Self {
76 let start = buf.len();
77 buf.reserve(estimate);
78 Self { inner: buf, start }
79 }
80
81 pub fn finish(self) -> usize {
82 self.inner.len() - self.start
83 }
84}
85
86impl ByteSink for Writer<'_> {
87 type Error = Infallible;
88
89 fn write_slices<const N: usize>(&mut self, slices: [&[u8]; N]) -> Result<(), Self::Error> {
90 self.inner.write_slices(slices)
91 }
92}
93
94pub struct Encode;
95
96impl Encode {
97 pub fn u64_len(mut value: u64) -> usize {
98 if value == 0 {
99 return 1;
100 }
101 let mut digits = 0usize;
102 while value != 0 {
103 digits += 1;
104 value /= 10;
105 }
106 digits
107 }
108
109 pub fn i64_len(value: i64) -> usize {
110 Self::u64_len(value.unsigned_abs()) + usize::from(value < 0)
111 }
112
113 pub fn f64_len(value: f64) -> usize {
114 if value.is_finite() {
115 ryu::Buffer::new().format_finite(value).len()
116 } else {
117 4
118 }
119 }
120
121 pub fn str_len(value: &[u8]) -> usize {
122 2 + Self::esc_len(value)
123 }
124
125 fn esc_len(value: &[u8]) -> usize {
126 let mut len = 0usize;
127 let mut idx = 0usize;
128 while idx < value.len() {
129 len += Self::esc_size(value[idx]);
130 idx += 1;
131 }
132 len
133 }
134
135 fn esc_size(byte: u8) -> usize {
136 match Self::esc_token(byte) {
137 Some(token) => token.len(),
138 None => 1,
139 }
140 }
141
142 fn esc_token(byte: u8) -> Option<&'static str> {
143 match byte {
144 b'"' => Some("\\\""),
145 b'\\' => Some("\\\\"),
146 b'\n' => Some("\\n"),
147 b'\r' => Some("\\r"),
148 b'\t' => Some("\\t"),
149 0x00 => Some("\\u0000"),
150 0x01 => Some("\\u0001"),
151 0x02 => Some("\\u0002"),
152 0x03 => Some("\\u0003"),
153 0x04 => Some("\\u0004"),
154 0x05 => Some("\\u0005"),
155 0x06 => Some("\\u0006"),
156 0x07 => Some("\\u0007"),
157 0x08 => Some("\\b"),
158 0x0b => Some("\\u000b"),
159 0x0c => Some("\\f"),
160 0x0e => Some("\\u000e"),
161 0x0f => Some("\\u000f"),
162 0x10 => Some("\\u0010"),
163 0x11 => Some("\\u0011"),
164 0x12 => Some("\\u0012"),
165 0x13 => Some("\\u0013"),
166 0x14 => Some("\\u0014"),
167 0x15 => Some("\\u0015"),
168 0x16 => Some("\\u0016"),
169 0x17 => Some("\\u0017"),
170 0x18 => Some("\\u0018"),
171 0x19 => Some("\\u0019"),
172 0x1a => Some("\\u001a"),
173 0x1b => Some("\\u001b"),
174 0x1c => Some("\\u001c"),
175 0x1d => Some("\\u001d"),
176 0x1e => Some("\\u001e"),
177 0x1f => Some("\\u001f"),
178 _ => None,
179 }
180 }
181}