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