Skip to main content

fory_core/
buffer.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::error::Error;
19use crate::types::bfloat16::bfloat16;
20use crate::types::float16::float16;
21use crate::util::buffer_rw_string::read_latin1_simd;
22use byteorder::{ByteOrder, LittleEndian};
23use std::cmp::max;
24
25/// Threshold for using SIMD optimizations in string operations.
26/// For buffers smaller than this, direct copy is faster than SIMD setup overhead.
27const SIMD_THRESHOLD: usize = 128;
28
29pub struct Writer<'a> {
30    pub(crate) bf: &'a mut Vec<u8>,
31}
32impl<'a> Writer<'a> {
33    // ============ Utility methods ============
34
35    #[inline(always)]
36    pub fn from_buffer(bf: &'a mut Vec<u8>) -> Writer<'a> {
37        Writer { bf }
38    }
39
40    #[inline(always)]
41    pub fn dump(&self) -> Vec<u8> {
42        self.bf.clone()
43    }
44
45    #[inline(always)]
46    pub fn reset(&mut self) {
47        self.bf.clear();
48    }
49
50    #[inline(always)]
51    pub fn len(&self) -> usize {
52        self.bf.len()
53    }
54
55    #[inline(always)]
56    pub fn is_empty(&self) -> bool {
57        self.bf.is_empty()
58    }
59
60    #[inline(always)]
61    pub fn reserve(&mut self, additional: usize) {
62        if self.bf.capacity() - self.len() < additional {
63            self.bf.reserve(max(additional * 2, self.bf.capacity()));
64        }
65    }
66
67    #[inline(always)]
68    pub fn skip(&mut self, len: usize) {
69        self.bf.resize(self.bf.len() + len, 0);
70    }
71
72    #[inline(always)]
73    pub fn set_bytes(&mut self, offset: usize, data: &[u8]) {
74        self.bf
75            .get_mut(offset..offset + data.len())
76            .unwrap()
77            .copy_from_slice(data);
78    }
79
80    #[inline(always)]
81    pub fn write_bytes(&mut self, v: &[u8]) -> usize {
82        self.bf.extend_from_slice(v);
83        v.len()
84    }
85
86    #[inline(always)]
87    pub(crate) unsafe fn write_bytes_from_ptr(&mut self, ptr: *const u8, len: usize) {
88        let offset = self.bf.len();
89        self.bf.reserve(len);
90        std::ptr::copy_nonoverlapping(ptr, self.bf.as_mut_ptr().add(offset), len);
91        self.bf.set_len(offset + len);
92    }
93
94    // ============ BOOL (TypeId = 1) ============
95
96    #[inline(always)]
97    pub fn write_bool(&mut self, value: bool) {
98        self.bf.push(if value { 1 } else { 0 });
99    }
100
101    // ============ INT8 (TypeId = 2) ============
102
103    #[inline(always)]
104    pub fn write_i8(&mut self, value: i8) {
105        self.bf.push(value as u8);
106    }
107
108    // ============ INT16 (TypeId = 3) ============
109
110    #[inline(always)]
111    pub fn write_i16(&mut self, value: i16) {
112        self.write_u16(value as u16);
113    }
114
115    // ============ INT32 (TypeId = 4) ============
116
117    #[inline(always)]
118    pub fn write_i32(&mut self, value: i32) {
119        self.write_u32(value as u32);
120    }
121
122    // ============ VARINT32 (TypeId = 5) ============
123
124    #[inline(always)]
125    pub fn write_var_i32(&mut self, value: i32) {
126        let zigzag = ((value as u32) << 1) ^ ((value >> 31) as u32);
127        self._write_var_u32(zigzag)
128    }
129
130    // ============ INT64 (TypeId = 6) ============
131
132    #[inline(always)]
133    pub fn write_i64(&mut self, value: i64) {
134        self.write_u64(value as u64);
135    }
136
137    // ============ VARINT64 (TypeId = 7) ============
138
139    #[inline(always)]
140    pub fn write_var_i64(&mut self, value: i64) {
141        let zigzag = ((value as u64) << 1) ^ ((value >> 63) as u64);
142        self._write_var_u64(zigzag);
143    }
144
145    // ============ TAGGED_INT64 (TypeId = 8) ============
146
147    /// Write signed long using fory Tagged(Small long as int) encoding.
148    /// If value is in [0xc0000000, 0x3fffffff] (i.e., [-1073741824, 1073741823]),
149    /// encode as 4 bytes: `((value as i32) << 1)`.
150    /// Otherwise write as 9 bytes: `0b1 | little-endian 8 bytes i64`.
151    #[inline(always)]
152    pub fn write_tagged_i64(&mut self, value: i64) {
153        const HALF_MIN_INT_VALUE: i64 = i32::MIN as i64 / 2; // -1073741824
154        const HALF_MAX_INT_VALUE: i64 = i32::MAX as i64 / 2; // 1073741823
155        if (HALF_MIN_INT_VALUE..=HALF_MAX_INT_VALUE).contains(&value) {
156            // Fits in 31 bits (with sign), encode as 4 bytes with bit 0 = 0
157            let v = (value as i32) << 1;
158            self.write_i32(v);
159        } else {
160            // Write flag byte (0b1) followed by 8-byte i64
161            self.bf.push(0b1);
162            self.write_i64(value);
163        }
164    }
165
166    // ============ UINT8 (TypeId = 9) ============
167
168    #[inline(always)]
169    pub fn write_u8(&mut self, value: u8) {
170        self.bf.push(value);
171    }
172
173    // ============ UINT16 (TypeId = 10) ============
174
175    #[inline(always)]
176    pub fn write_u16(&mut self, value: u16) {
177        #[cfg(target_endian = "little")]
178        {
179            let bytes = unsafe { &*(&value as *const u16 as *const [u8; 2]) };
180            self.bf.extend_from_slice(bytes);
181        }
182        #[cfg(target_endian = "big")]
183        {
184            self.bf.extend_from_slice(&value.to_le_bytes());
185        }
186    }
187
188    // ============ UINT32 (TypeId = 11) ============
189
190    #[inline(always)]
191    pub fn write_u32(&mut self, value: u32) {
192        #[cfg(target_endian = "little")]
193        {
194            let bytes = unsafe { &*(&value as *const u32 as *const [u8; 4]) };
195            self.bf.extend_from_slice(bytes);
196        }
197        #[cfg(target_endian = "big")]
198        {
199            self.bf.extend_from_slice(&value.to_le_bytes());
200        }
201    }
202
203    #[inline(always)]
204    fn write_u24(&mut self, value: u32) {
205        let bytes = value.to_le_bytes();
206        self.bf.extend_from_slice(&bytes[..3]);
207    }
208
209    #[inline(always)]
210    fn write_u40(&mut self, value: u64) {
211        let bytes = value.to_le_bytes();
212        self.bf.extend_from_slice(&bytes[..5]);
213    }
214
215    // ============ VAR_UINT32 (TypeId = 12) ============
216
217    #[inline(always)]
218    pub fn write_var_u32(&mut self, value: u32) {
219        self._write_var_u32(value)
220    }
221
222    #[inline(always)]
223    fn _write_var_u32(&mut self, value: u32) {
224        if value < 0x80 {
225            self.bf.push(value as u8);
226        } else if value < 0x4000 {
227            // 2 bytes
228            let u1 = ((value as u8) & 0x7F) | 0x80;
229            let u2 = (value >> 7) as u8;
230            self.write_u16(((u2 as u16) << 8) | u1 as u16);
231        } else if value < 0x200000 {
232            // 3 bytes
233            let u1 = ((value as u8) & 0x7F) | 0x80;
234            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
235            let u3 = (value >> 14) as u8;
236            self.write_u24(((u3 as u32) << 16) | ((u2 as u32) << 8) | u1 as u32);
237        } else if value < 0x10000000 {
238            // 4 bytes
239            let u1 = ((value as u8) & 0x7F) | 0x80;
240            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
241            let u3 = (((value >> 14) as u8) & 0x7F) | 0x80;
242            let u4 = (value >> 21) as u8;
243            self.write_u32(
244                ((u4 as u32) << 24) | ((u3 as u32) << 16) | ((u2 as u32) << 8) | u1 as u32,
245            );
246        } else {
247            // 5 bytes
248            let u1 = ((value as u8) & 0x7F) | 0x80;
249            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
250            let u3 = (((value >> 14) as u8) & 0x7F) | 0x80;
251            let u4 = (((value >> 21) as u8) & 0x7F) | 0x80;
252            let u5 = (value >> 28) as u8;
253            self.write_u40(
254                ((u5 as u64) << 32)
255                    | ((u4 as u64) << 24)
256                    | ((u3 as u64) << 16)
257                    | ((u2 as u64) << 8)
258                    | u1 as u64,
259            );
260        }
261    }
262
263    // ============ UINT64 (TypeId = 13) ============
264
265    #[inline(always)]
266    pub fn write_u64(&mut self, value: u64) {
267        #[cfg(target_endian = "little")]
268        {
269            let bytes = unsafe { &*(&value as *const u64 as *const [u8; 8]) };
270            self.bf.extend_from_slice(bytes);
271        }
272        #[cfg(target_endian = "big")]
273        {
274            self.bf.extend_from_slice(&value.to_le_bytes());
275        }
276    }
277
278    // ============ VAR_UINT64 (TypeId = 14) ============
279
280    #[inline(always)]
281    pub fn write_var_u64(&mut self, value: u64) {
282        self._write_var_u64(value);
283    }
284
285    #[inline(always)]
286    fn _write_var_u64(&mut self, value: u64) {
287        if value < 0x80 {
288            self.bf.push(value as u8);
289        } else if value < 0x4000 {
290            let u1 = ((value as u8) & 0x7F) | 0x80;
291            let u2 = (value >> 7) as u8;
292            self.write_u16(((u2 as u16) << 8) | u1 as u16);
293        } else if value < 0x200000 {
294            let u1 = ((value as u8) & 0x7F) | 0x80;
295            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
296            let u3 = (value >> 14) as u8;
297            self.write_u24(((u3 as u32) << 16) | ((u2 as u32) << 8) | u1 as u32);
298        } else if value < 0x10000000 {
299            let u1 = ((value as u8) & 0x7F) | 0x80;
300            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
301            let u3 = (((value >> 14) as u8) & 0x7F) | 0x80;
302            let u4 = (value >> 21) as u8;
303            self.write_u32(
304                ((u4 as u32) << 24) | ((u3 as u32) << 16) | ((u2 as u32) << 8) | u1 as u32,
305            );
306        } else if value < 0x800000000 {
307            let u1 = ((value as u8) & 0x7F) | 0x80;
308            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
309            let u3 = (((value >> 14) as u8) & 0x7F) | 0x80;
310            let u4 = (((value >> 21) as u8) & 0x7F) | 0x80;
311            let u5 = (value >> 28) as u8;
312            self.write_u40(
313                ((u5 as u64) << 32)
314                    | ((u4 as u64) << 24)
315                    | ((u3 as u64) << 16)
316                    | ((u2 as u64) << 8)
317                    | u1 as u64,
318            );
319        } else if value < 0x40000000000 {
320            let u1 = ((value as u8) & 0x7F) | 0x80;
321            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
322            let u3 = (((value >> 14) as u8) & 0x7F) | 0x80;
323            let u4 = (((value >> 21) as u8) & 0x7F) | 0x80;
324            let u5 = (((value >> 28) as u8) & 0x7F) | 0x80;
325            let u6 = (value >> 35) as u8;
326            self.write_u32(
327                ((u4 as u32) << 24) | ((u3 as u32) << 16) | ((u2 as u32) << 8) | u1 as u32,
328            );
329            self.write_u16(((u6 as u16) << 8) | u5 as u16);
330        } else if value < 0x2000000000000 {
331            let u1 = ((value as u8) & 0x7F) | 0x80;
332            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
333            let u3 = (((value >> 14) as u8) & 0x7F) | 0x80;
334            let u4 = (((value >> 21) as u8) & 0x7F) | 0x80;
335            let u5 = (((value >> 28) as u8) & 0x7F) | 0x80;
336            let u6 = (((value >> 35) as u8) & 0x7F) | 0x80;
337            let u7 = (value >> 42) as u8;
338            self.write_u32(
339                ((u4 as u32) << 24) | ((u3 as u32) << 16) | ((u2 as u32) << 8) | u1 as u32,
340            );
341            self.write_u16(((u6 as u16) << 8) | u5 as u16);
342            self.bf.push(u7);
343        } else if value < 0x100000000000000 {
344            let u1 = ((value as u8) & 0x7F) | 0x80;
345            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
346            let u3 = (((value >> 14) as u8) & 0x7F) | 0x80;
347            let u4 = (((value >> 21) as u8) & 0x7F) | 0x80;
348            let u5 = (((value >> 28) as u8) & 0x7F) | 0x80;
349            let u6 = (((value >> 35) as u8) & 0x7F) | 0x80;
350            let u7 = (((value >> 42) as u8) & 0x7F) | 0x80;
351            let u8 = (value >> 49) as u8;
352            self.write_u64(
353                (u8 as u64) << 56
354                    | (u7 as u64) << 48
355                    | (u6 as u64) << 40
356                    | (u5 as u64) << 32
357                    | (u4 as u64) << 24
358                    | (u3 as u64) << 16
359                    | (u2 as u64) << 8
360                    | (u1 as u64),
361            );
362        } else {
363            let u1 = ((value as u8) & 0x7F) | 0x80;
364            let u2 = (((value >> 7) as u8) & 0x7F) | 0x80;
365            let u3 = (((value >> 14) as u8) & 0x7F) | 0x80;
366            let u4 = (((value >> 21) as u8) & 0x7F) | 0x80;
367            let u5 = (((value >> 28) as u8) & 0x7F) | 0x80;
368            let u6 = (((value >> 35) as u8) & 0x7F) | 0x80;
369            let u7 = (((value >> 42) as u8) & 0x7F) | 0x80;
370            let u8 = (((value >> 49) as u8) & 0x7F) | 0x80;
371            let u9 = (value >> 56) as u8;
372            self.write_u64(
373                (u8 as u64) << 56
374                    | (u7 as u64) << 48
375                    | (u6 as u64) << 40
376                    | (u5 as u64) << 32
377                    | (u4 as u64) << 24
378                    | (u3 as u64) << 16
379                    | (u2 as u64) << 8
380                    | (u1 as u64),
381            );
382            self.bf.push(u9);
383        }
384    }
385
386    // ============ TAGGED_UINT64 (TypeId = 15) ============
387
388    /// Write unsigned long using fory Tagged(Small long as int) encoding.
389    /// If value is in [0, 0x7fffffff], encode as 4 bytes: `((value as u32) << 1)`.
390    /// Otherwise write as 9 bytes: `0b1 | little-endian 8 bytes u64`.
391    #[inline(always)]
392    pub fn write_tagged_u64(&mut self, value: u64) {
393        if value <= i32::MAX as u64 {
394            // Fits in 31 bits, encode as 4 bytes with bit 0 = 0
395            let v = (value as u32) << 1;
396            self.write_u32(v);
397        } else {
398            // Write flag byte (0b1) followed by 8-byte u64
399            self.bf.push(0b1);
400            self.write_u64(value);
401        }
402    }
403
404    // ============ FLOAT32 (TypeId = 17) ============
405
406    #[inline(always)]
407    pub fn write_f32(&mut self, value: f32) {
408        #[cfg(target_endian = "little")]
409        {
410            let bytes = unsafe { &*(&value as *const f32 as *const [u8; 4]) };
411            self.bf.extend_from_slice(bytes);
412        }
413        #[cfg(target_endian = "big")]
414        {
415            self.bf.extend_from_slice(&value.to_bits().to_le_bytes());
416        }
417    }
418
419    // ============ FLOAT16 (TypeId = 16) ============
420    #[inline(always)]
421    pub fn write_f16(&mut self, value: float16) {
422        self.write_u16(value.to_bits());
423    }
424
425    // ============ BFLOAT16 (TypeId = 18) ============
426    #[inline(always)]
427    pub fn write_bf16(&mut self, value: bfloat16) {
428        self.write_u16(value.to_bits());
429    }
430
431    // ============ FLOAT64 (TypeId = 18) ============
432
433    #[inline(always)]
434    pub fn write_f64(&mut self, value: f64) {
435        #[cfg(target_endian = "little")]
436        {
437            let bytes = unsafe { &*(&value as *const f64 as *const [u8; 8]) };
438            self.bf.extend_from_slice(bytes);
439        }
440        #[cfg(target_endian = "big")]
441        {
442            self.bf.extend_from_slice(&value.to_bits().to_le_bytes());
443        }
444    }
445
446    // ============ STRING (TypeId = 19) ============
447
448    #[inline(always)]
449    pub fn write_utf8_string(&mut self, s: &str) {
450        let bytes = s.as_bytes();
451        let len = bytes.len();
452        self.bf.reserve(len);
453        self.bf.extend_from_slice(bytes);
454    }
455
456    // ============ Rust-specific types (i128, u128, isize, usize) ============
457
458    #[inline(always)]
459    pub fn write_i128(&mut self, value: i128) {
460        self.write_u128(value as u128);
461    }
462
463    #[inline(always)]
464    pub fn write_u128(&mut self, value: u128) {
465        #[cfg(target_endian = "little")]
466        {
467            let bytes = unsafe { &*(&value as *const u128 as *const [u8; 16]) };
468            self.bf.extend_from_slice(bytes);
469        }
470        #[cfg(target_endian = "big")]
471        {
472            self.bf.extend_from_slice(&value.to_le_bytes());
473        }
474    }
475
476    #[inline(always)]
477    pub fn write_isize(&mut self, value: isize) {
478        const SIZE: usize = std::mem::size_of::<isize>();
479        match SIZE {
480            2 => self.write_i16(value as i16),
481            4 => self.write_var_i32(value as i32),
482            8 => self.write_var_i64(value as i64),
483            _ => unreachable!("unsupported isize size"),
484        }
485    }
486
487    #[inline(always)]
488    pub fn write_usize(&mut self, value: usize) {
489        const SIZE: usize = std::mem::size_of::<usize>();
490        match SIZE {
491            2 => self.write_u16(value as u16),
492            4 => self.write_var_u32(value as u32),
493            8 => self.write_var_u64(value as u64),
494            _ => unreachable!("unsupported usize size"),
495        }
496    }
497
498    // ============ Other helper methods ============
499
500    #[inline(always)]
501    pub fn write_var_u36_small(&mut self, value: u64) {
502        assert!(
503            value < (1u64 << 36),
504            "value too large for 36-bit variable-length integer"
505        );
506        if value < 0x80 {
507            self.bf.push(value as u8);
508        } else if value < 0x4000 {
509            let b0 = ((value & 0x7F) as u8) | 0x80;
510            let b1 = (value >> 7) as u8;
511            let combined = ((b1 as u16) << 8) | (b0 as u16);
512            self.write_u16(combined);
513        } else if value < 0x200000 {
514            let b0 = (value & 0x7F) | 0x80;
515            let b1 = ((value >> 7) & 0x7F) | 0x80;
516            let b2 = value >> 14;
517            let combined = b0 | (b1 << 8) | (b2 << 16);
518            self.write_u32(combined as u32);
519        } else if value < 0x10000000 {
520            let b0 = (value & 0x7F) | 0x80;
521            let b1 = ((value >> 7) & 0x7F) | 0x80;
522            let b2 = ((value >> 14) & 0x7F) | 0x80;
523            let b3 = value >> 21;
524            let combined = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
525            self.write_u32(combined as u32);
526        } else {
527            let b0 = (value & 0x7F) | 0x80;
528            let b1 = ((value >> 7) & 0x7F) | 0x80;
529            let b2 = ((value >> 14) & 0x7F) | 0x80;
530            let b3 = ((value >> 21) & 0x7F) | 0x80;
531            let b4 = value >> 28;
532            let combined = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24) | (b4 << 32);
533            self.write_u64(combined);
534        }
535    }
536}
537
538#[derive(Default)]
539#[allow(clippy::needless_lifetimes)]
540pub struct Reader<'a> {
541    pub(crate) bf: &'a [u8],
542    pub(crate) cursor: usize,
543}
544
545#[allow(clippy::needless_lifetimes)]
546impl<'a> Reader<'a> {
547    // ============ Utility methods ============
548
549    #[inline(always)]
550    pub fn new(bf: &[u8]) -> Reader<'_> {
551        Reader { bf, cursor: 0 }
552    }
553
554    #[inline(always)]
555    pub(crate) fn move_next(&mut self, additional: usize) {
556        self.cursor += additional;
557    }
558
559    #[inline(always)]
560    pub(crate) fn move_back(&mut self, additional: usize) {
561        self.cursor -= additional;
562    }
563
564    #[inline(always)]
565    pub fn sub_slice(&self, start: usize, end: usize) -> Result<&[u8], Error> {
566        // Allow start == bf.len() when end == bf.len() to support empty slices at buffer end
567        if start > self.bf.len() || end > self.bf.len() || end < start {
568            Err(Error::buffer_out_of_bound(
569                start,
570                self.bf.len(),
571                self.bf.len(),
572            ))
573        } else {
574            Ok(&self.bf[start..end])
575        }
576    }
577
578    #[inline(always)]
579    pub fn slice_after_cursor(&self) -> &[u8] {
580        &self.bf[self.cursor..]
581    }
582
583    #[inline(always)]
584    pub fn get_cursor(&self) -> usize {
585        self.cursor
586    }
587
588    #[inline(always)]
589    fn value_at(&self, index: usize) -> Result<u8, Error> {
590        match self.bf.get(index) {
591            None => Err(Error::buffer_out_of_bound(
592                index,
593                self.bf.len(),
594                self.bf.len(),
595            )),
596            Some(v) => Ok(*v),
597        }
598    }
599
600    #[inline(always)]
601    pub(crate) fn check_bound(&self, n: usize) -> Result<(), Error> {
602        let end = self
603            .cursor
604            .checked_add(n)
605            .ok_or_else(|| Error::buffer_out_of_bound(self.cursor, n, self.bf.len()))?;
606        if end > self.bf.len() {
607            Err(Error::buffer_out_of_bound(self.cursor, n, self.bf.len()))
608        } else {
609            Ok(())
610        }
611    }
612
613    #[inline(always)]
614    fn read_u8_uncheck(&mut self) -> u8 {
615        let result = unsafe { self.bf.get_unchecked(self.cursor) };
616        self.move_next(1);
617        *result
618    }
619
620    #[inline(always)]
621    pub fn skip(&mut self, len: usize) -> Result<(), Error> {
622        self.check_bound(len)?;
623        self.move_next(len);
624        Ok(())
625    }
626
627    #[inline(always)]
628    pub fn read_bytes(&mut self, len: usize) -> Result<&[u8], Error> {
629        self.check_bound(len)?;
630        let result = &self.bf[self.cursor..self.cursor + len];
631        self.move_next(len);
632        Ok(result)
633    }
634
635    #[inline(always)]
636    pub fn reset_cursor_to_here(&self) -> impl FnOnce(&mut Self) {
637        let raw_cursor = self.cursor;
638        move |this: &mut Self| {
639            this.cursor = raw_cursor;
640        }
641    }
642
643    pub fn set_cursor(&mut self, cursor: usize) {
644        self.cursor = cursor;
645    }
646
647    // ============ BOOL (TypeId = 1) ============
648
649    #[inline(always)]
650    pub fn read_bool(&mut self) -> Result<bool, Error> {
651        Ok(self.read_u8()? != 0)
652    }
653
654    // ============ INT8 (TypeId = 2) ============
655
656    #[inline(always)]
657    pub fn read_i8(&mut self) -> Result<i8, Error> {
658        Ok(self.read_u8()? as i8)
659    }
660
661    // ============ INT16 (TypeId = 3) ============
662
663    #[inline(always)]
664    pub fn read_i16(&mut self) -> Result<i16, Error> {
665        Ok(self.read_u16()? as i16)
666    }
667
668    // ============ INT32 (TypeId = 4) ============
669
670    #[inline(always)]
671    pub fn read_i32(&mut self) -> Result<i32, Error> {
672        Ok(self.read_u32()? as i32)
673    }
674
675    // ============ VARINT32 (TypeId = 5) ============
676
677    #[inline(always)]
678    pub fn read_var_i32(&mut self) -> Result<i32, Error> {
679        let encoded = self.read_var_u32()?;
680        Ok(((encoded >> 1) as i32) ^ -((encoded & 1) as i32))
681    }
682
683    // ============ INT64 (TypeId = 6) ============
684
685    #[inline(always)]
686    pub fn read_i64(&mut self) -> Result<i64, Error> {
687        Ok(self.read_u64()? as i64)
688    }
689
690    // ============ VARINT64 (TypeId = 7) ============
691
692    #[inline(always)]
693    pub fn read_var_i64(&mut self) -> Result<i64, Error> {
694        let encoded = self.read_var_u64()?;
695        Ok(((encoded >> 1) as i64) ^ -((encoded & 1) as i64))
696    }
697
698    // ============ TAGGED_INT64 (TypeId = 8) ============
699
700    /// Read signed fory Tagged(Small long as int) encoded i64.
701    /// If bit 0 of the first 4 bytes is 0, return the value >> 1 (arithmetic shift).
702    /// Otherwise, skip the flag byte and read 8 bytes as i64.
703    #[inline(always)]
704    pub fn read_tagged_i64(&mut self) -> Result<i64, Error> {
705        self.check_bound(4)?;
706        let i = LittleEndian::read_i32(&self.bf[self.cursor..]);
707        if (i & 0b1) != 0b1 {
708            // Bit 0 is 0, small value encoded in 4 bytes
709            self.cursor += 4;
710            Ok((i >> 1) as i64) // arithmetic right shift preserves sign
711        } else {
712            // Bit 0 is 1, big value: skip flag byte and read 8 bytes
713            self.check_bound(9)?;
714            self.cursor += 1;
715            let value = LittleEndian::read_i64(&self.bf[self.cursor..]);
716            self.cursor += 8;
717            Ok(value)
718        }
719    }
720
721    // ============ UINT8 (TypeId = 9) ============
722
723    #[inline(always)]
724    pub fn peek_u8(&mut self) -> Result<u8, Error> {
725        let result = self.value_at(self.cursor)?;
726        Ok(result)
727    }
728
729    #[inline(always)]
730    pub fn read_u8(&mut self) -> Result<u8, Error> {
731        let result = self.value_at(self.cursor)?;
732        self.move_next(1);
733        Ok(result)
734    }
735
736    // ============ UINT16 (TypeId = 10) ============
737
738    #[inline(always)]
739    pub fn read_u16(&mut self) -> Result<u16, Error> {
740        self.check_bound(2)?;
741        let result = LittleEndian::read_u16(&self.bf[self.cursor..self.cursor + 2]);
742        self.cursor += 2;
743        Ok(result)
744    }
745
746    // ============ UINT32 (TypeId = 11) ============
747
748    #[inline(always)]
749    pub fn read_u32(&mut self) -> Result<u32, Error> {
750        self.check_bound(4)?;
751        let result = LittleEndian::read_u32(&self.bf[self.cursor..self.cursor + 4]);
752        self.cursor += 4;
753        Ok(result)
754    }
755
756    // ============ VAR_UINT32 (TypeId = 12) ============
757
758    #[inline(always)]
759    pub fn read_var_u32(&mut self) -> Result<u32, Error> {
760        let b0 = self.value_at(self.cursor)? as u32;
761        if b0 < 0x80 {
762            self.move_next(1);
763            return Ok(b0);
764        }
765
766        let b1 = self.value_at(self.cursor + 1)? as u32;
767        let mut encoded = (b0 & 0x7F) | ((b1 & 0x7F) << 7);
768        if b1 < 0x80 {
769            self.move_next(2);
770            return Ok(encoded);
771        }
772
773        let b2 = self.value_at(self.cursor + 2)? as u32;
774        encoded |= (b2 & 0x7F) << 14;
775        if b2 < 0x80 {
776            self.move_next(3);
777            return Ok(encoded);
778        }
779
780        let b3 = self.value_at(self.cursor + 3)? as u32;
781        encoded |= (b3 & 0x7F) << 21;
782        if b3 < 0x80 {
783            self.move_next(4);
784            return Ok(encoded);
785        }
786
787        let b4 = self.value_at(self.cursor + 4)? as u32;
788        encoded |= b4 << 28;
789        self.move_next(5);
790        Ok(encoded)
791    }
792
793    // ============ UINT64 (TypeId = 13) ============
794
795    #[inline(always)]
796    pub fn read_u64(&mut self) -> Result<u64, Error> {
797        self.check_bound(8)?;
798        let result = LittleEndian::read_u64(&self.bf[self.cursor..self.cursor + 8]);
799        self.cursor += 8;
800        Ok(result)
801    }
802
803    // ============ VAR_UINT64 (TypeId = 14) ============
804
805    #[inline(always)]
806    pub fn read_var_u64(&mut self) -> Result<u64, Error> {
807        let b0 = self.value_at(self.cursor)? as u64;
808        if b0 < 0x80 {
809            self.move_next(1);
810            return Ok(b0);
811        }
812
813        let b1 = self.value_at(self.cursor + 1)? as u64;
814        let mut result = (b0 & 0x7F) | ((b1 & 0x7F) << 7);
815        if b1 < 0x80 {
816            self.move_next(2);
817            return Ok(result);
818        }
819
820        let b2 = self.value_at(self.cursor + 2)? as u64;
821        result |= (b2 & 0x7F) << 14;
822        if b2 < 0x80 {
823            self.move_next(3);
824            return Ok(result);
825        }
826
827        let b3 = self.value_at(self.cursor + 3)? as u64;
828        result |= (b3 & 0x7F) << 21;
829        if b3 < 0x80 {
830            self.move_next(4);
831            return Ok(result);
832        }
833
834        let b4 = self.value_at(self.cursor + 4)? as u64;
835        result |= (b4 & 0x7F) << 28;
836        if b4 < 0x80 {
837            self.move_next(5);
838            return Ok(result);
839        }
840
841        let b5 = self.value_at(self.cursor + 5)? as u64;
842        result |= (b5 & 0x7F) << 35;
843        if b5 < 0x80 {
844            self.move_next(6);
845            return Ok(result);
846        }
847
848        let b6 = self.value_at(self.cursor + 6)? as u64;
849        result |= (b6 & 0x7F) << 42;
850        if b6 < 0x80 {
851            self.move_next(7);
852            return Ok(result);
853        }
854
855        let b7 = self.value_at(self.cursor + 7)? as u64;
856        result |= (b7 & 0x7F) << 49;
857        if b7 < 0x80 {
858            self.move_next(8);
859            return Ok(result);
860        }
861
862        let b8 = self.value_at(self.cursor + 8)? as u64;
863        result |= (b8 & 0xFF) << 56;
864        self.move_next(9);
865        Ok(result)
866    }
867
868    // ============ TAGGED_UINT64 (TypeId = 15) ============
869
870    /// Read unsigned fory Tagged(Small long as int) encoded u64.
871    /// If bit 0 of the first 4 bytes is 0, return the value >> 1.
872    /// Otherwise, skip the flag byte and read 8 bytes as u64.
873    #[inline(always)]
874    pub fn read_tagged_u64(&mut self) -> Result<u64, Error> {
875        self.check_bound(4)?;
876        let i = LittleEndian::read_u32(&self.bf[self.cursor..]);
877        if (i & 0b1) != 0b1 {
878            // Bit 0 is 0, small value encoded in 4 bytes
879            self.cursor += 4;
880            Ok((i >> 1) as u64)
881        } else {
882            // Bit 0 is 1, big value: skip flag byte and read 8 bytes
883            self.check_bound(9)?;
884            self.cursor += 1;
885            let value = LittleEndian::read_u64(&self.bf[self.cursor..]);
886            self.cursor += 8;
887            Ok(value)
888        }
889    }
890
891    // ============ FLOAT32 (TypeId = 17) ============
892
893    #[inline(always)]
894    pub fn read_f32(&mut self) -> Result<f32, Error> {
895        self.check_bound(4)?;
896        let result = LittleEndian::read_f32(&self.bf[self.cursor..self.cursor + 4]);
897        self.cursor += 4;
898        Ok(result)
899    }
900
901    // ============ FLOAT64 (TypeId = 18) ============
902    #[inline(always)]
903    pub fn read_f16(&mut self) -> Result<float16, Error> {
904        self.check_bound(2)?;
905        let bits = LittleEndian::read_u16(&self.bf[self.cursor..self.cursor + 2]);
906        self.cursor += 2;
907        Ok(float16::from_bits(bits))
908    }
909
910    #[inline(always)]
911    pub fn read_bf16(&mut self) -> Result<bfloat16, Error> {
912        self.check_bound(2)?;
913        let bits = LittleEndian::read_u16(&self.bf[self.cursor..self.cursor + 2]);
914        self.cursor += 2;
915        Ok(bfloat16::from_bits(bits))
916    }
917
918    pub fn read_f64(&mut self) -> Result<f64, Error> {
919        self.check_bound(8)?;
920        let result = LittleEndian::read_f64(&self.bf[self.cursor..self.cursor + 8]);
921        self.cursor += 8;
922        Ok(result)
923    }
924
925    // ============ STRING (TypeId = 19) ============
926
927    #[inline(always)]
928    pub fn read_latin1_string(&mut self, len: usize) -> Result<String, Error> {
929        self.check_bound(len)?;
930        if len < SIMD_THRESHOLD {
931            // Fast path for small buffers
932            unsafe {
933                let src = self.sub_slice(self.cursor, self.cursor + len)?;
934
935                // Check if all bytes are ASCII (< 0x80)
936                let is_ascii = src.iter().all(|&b| b < 0x80);
937
938                if is_ascii {
939                    // ASCII fast path: Latin1 == UTF-8, direct copy
940                    let mut vec = Vec::with_capacity(len);
941                    let dst = vec.as_mut_ptr();
942                    std::ptr::copy_nonoverlapping(src.as_ptr(), dst, len);
943                    vec.set_len(len);
944                    self.move_next(len);
945                    Ok(String::from_utf8_unchecked(vec))
946                } else {
947                    // Contains Latin1 bytes (0x80-0xFF): must convert to UTF-8
948                    let mut out: Vec<u8> = Vec::with_capacity(len * 2);
949                    let out_ptr = out.as_mut_ptr();
950                    let mut out_len = 0;
951
952                    for &b in src {
953                        if b < 0x80 {
954                            *out_ptr.add(out_len) = b;
955                            out_len += 1;
956                        } else {
957                            // Latin1 -> UTF-8 encoding
958                            *out_ptr.add(out_len) = 0xC0 | (b >> 6);
959                            *out_ptr.add(out_len + 1) = 0x80 | (b & 0x3F);
960                            out_len += 2;
961                        }
962                    }
963
964                    out.set_len(out_len);
965                    self.move_next(len);
966                    Ok(String::from_utf8_unchecked(out))
967                }
968            }
969        } else {
970            // Use SIMD for larger strings where the overhead is amortized
971            read_latin1_simd(self, len)
972        }
973    }
974
975    #[inline(always)]
976    pub fn read_utf8_string(&mut self, len: usize) -> Result<String, Error> {
977        self.check_bound(len)?;
978        let src = &self.bf[self.cursor..self.cursor + len];
979        // Rust is the only runtime that checks UTF-8 string payloads by default; other runtimes
980        // preserve their platform replacement behavior for invalid byte sequences.
981        let string =
982            std::str::from_utf8(src).map_err(|_| Error::encoding_error("invalid UTF-8 string"))?;
983        let string = string.to_owned();
984        self.move_next(len);
985        Ok(string)
986    }
987
988    #[inline(always)]
989    pub fn read_utf8_string_unchecked(&mut self, len: usize) -> Result<String, Error> {
990        self.check_bound(len)?;
991        // don't use simd for memory copy, copy_non_overlapping is faster
992        unsafe {
993            let mut vec = Vec::with_capacity(len);
994            let src = self.bf.as_ptr().add(self.cursor);
995            let dst = vec.as_mut_ptr();
996            // Use fastest possible copy - copy_nonoverlapping compiles to memcpy
997            std::ptr::copy_nonoverlapping(src, dst, len);
998            vec.set_len(len);
999            self.move_next(len);
1000            Ok(String::from_utf8_unchecked(vec))
1001        }
1002    }
1003
1004    #[inline(always)]
1005    pub fn read_utf16_string(&mut self, len: usize) -> Result<String, Error> {
1006        self.check_bound(len)?;
1007        let slice = self.sub_slice(self.cursor, self.cursor + len)?;
1008        let units: Vec<u16> = slice
1009            .chunks_exact(2)
1010            .map(|c| u16::from_le_bytes([c[0], c[1]]))
1011            .collect();
1012        self.move_next(len);
1013        Ok(String::from_utf16_lossy(&units))
1014    }
1015
1016    // ============ Rust-specific types (i128, u128, isize, usize) ============
1017
1018    #[inline(always)]
1019    pub fn read_i128(&mut self) -> Result<i128, Error> {
1020        Ok(self.read_u128()? as i128)
1021    }
1022
1023    #[inline(always)]
1024    pub fn read_u128(&mut self) -> Result<u128, Error> {
1025        self.check_bound(16)?;
1026        let result = LittleEndian::read_u128(&self.bf[self.cursor..self.cursor + 16]);
1027        self.cursor += 16;
1028        Ok(result)
1029    }
1030
1031    #[inline(always)]
1032    pub fn read_isize(&mut self) -> Result<isize, Error> {
1033        const SIZE: usize = std::mem::size_of::<isize>();
1034        match SIZE {
1035            2 => Ok(self.read_i16()? as isize),
1036            4 => Ok(self.read_var_i32()? as isize),
1037            8 => Ok(self.read_var_i64()? as isize),
1038            _ => unreachable!("unsupported isize size"),
1039        }
1040    }
1041
1042    #[inline(always)]
1043    pub fn read_usize(&mut self) -> Result<usize, Error> {
1044        const SIZE: usize = std::mem::size_of::<usize>();
1045        match SIZE {
1046            2 => Ok(self.read_u16()? as usize),
1047            4 => Ok(self.read_var_u32()? as usize),
1048            8 => Ok(self.read_var_u64()? as usize),
1049            _ => unreachable!("unsupported usize size"),
1050        }
1051    }
1052
1053    // ============ Other helper methods ============
1054
1055    #[inline(always)]
1056    pub fn read_var_u36_small(&mut self) -> Result<u64, Error> {
1057        // Keep this API panic-free even if cursor is externally set past buffer end.
1058        self.check_bound(0)?;
1059        let start = self.cursor;
1060        let slice = self.slice_after_cursor();
1061
1062        if slice.len() >= 8 {
1063            // here already check bound
1064            let bulk = self.read_u64()?;
1065            let mut result = bulk & 0x7F;
1066            let mut read_idx = start;
1067
1068            if (bulk & 0x80) != 0 {
1069                read_idx += 1;
1070                result |= (bulk >> 1) & 0x3F80;
1071                if (bulk & 0x8000) != 0 {
1072                    read_idx += 1;
1073                    result |= (bulk >> 2) & 0x1FC000;
1074                    if (bulk & 0x800000) != 0 {
1075                        read_idx += 1;
1076                        result |= (bulk >> 3) & 0xFE00000;
1077                        if (bulk & 0x80000000) != 0 {
1078                            read_idx += 1;
1079                            result |= (bulk >> 4) & 0xFF0000000;
1080                        }
1081                    }
1082                }
1083            }
1084            self.cursor = read_idx + 1;
1085            return Ok(result);
1086        }
1087
1088        let mut result = 0u64;
1089        let mut shift = 0;
1090        while self.cursor < self.bf.len() {
1091            let b = self.read_u8_uncheck();
1092            result |= ((b & 0x7F) as u64) << shift;
1093            if (b & 0x80) == 0 {
1094                break;
1095            }
1096            shift += 7;
1097            if shift >= 36 {
1098                return Err(Error::encode_error("var_u36_small overflow"));
1099            }
1100        }
1101        Ok(result)
1102    }
1103}
1104
1105#[allow(clippy::needless_lifetimes)]
1106unsafe impl<'a> Send for Reader<'a> {}
1107#[allow(clippy::needless_lifetimes)]
1108unsafe impl<'a> Sync for Reader<'a> {}
1109
1110#[cfg(test)]
1111mod tests {
1112    use super::{Reader, Writer};
1113
1114    #[test]
1115    fn varuint_boundary_roundtrip() {
1116        let cases = [
1117            (0x3fff_u32, 2),
1118            (0x4000, 3),
1119            (0x1f_ffff, 3),
1120            (0x20_0000, 4),
1121            (0x0fff_ffff, 4),
1122            (0x1000_0000, 5),
1123            (u32::MAX, 5),
1124        ];
1125        for (value, expected_len) in cases {
1126            let mut buffer = Vec::new();
1127            let mut writer = Writer::from_buffer(&mut buffer);
1128            writer.write_var_u32(value);
1129            assert_eq!(writer.len(), expected_len);
1130            let bytes = writer.dump();
1131            assert_eq!(Reader::new(&bytes).read_var_u32().unwrap(), value);
1132            let mut padded = bytes;
1133            padded.extend_from_slice(&[0; 8]);
1134            let mut reader = Reader::new(&padded);
1135            assert_eq!(reader.read_var_u32().unwrap(), value);
1136            assert_eq!(reader.get_cursor(), expected_len);
1137
1138            let mut buffer = Vec::new();
1139            let mut writer = Writer::from_buffer(&mut buffer);
1140            writer.write_var_u64(u64::from(value));
1141            assert_eq!(writer.len(), expected_len);
1142            let bytes = writer.dump();
1143            assert_eq!(
1144                Reader::new(&bytes).read_var_u64().unwrap(),
1145                u64::from(value)
1146            );
1147        }
1148    }
1149}