Skip to main content

bsv_primitives/util/
mod.rs

1//! Utility types for binary serialization.
2//!
3//! Provides VarInt encoding/decoding, `BsvReader` and `BsvWriter` structs
4//! for reading/writing Bitcoin protocol binary data, and byte manipulation
5//! helpers used in transaction serialization.
6//! Ported from the Go BSV SDK (`util` package).
7
8use crate::PrimitivesError;
9
10// ---------------------------------------------------------------------------
11// VarInt
12// ---------------------------------------------------------------------------
13
14/// A Bitcoin protocol variable-length integer.
15///
16/// VarInt is used in transaction data to indicate the number of upcoming fields
17/// or the length of an upcoming field. The encoding uses 1, 3, 5, or 9 bytes
18/// depending on the magnitude of the value.
19///
20/// See <http://learnmeabitcoin.com/glossary/varint>
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct VarInt(pub u64);
23
24impl VarInt {
25    /// Decode a VarInt from a byte slice.
26    ///
27    /// Returns the decoded value and the number of bytes consumed.
28    ///
29    /// # Arguments
30    /// * `data` - Byte slice starting with a VarInt encoding.
31    ///
32    /// # Returns
33    /// `Ok((VarInt, bytes_consumed))` or `Err` if the slice is too short.
34    ///
35    /// # Panics
36    /// None — all bounds are checked.
37    pub fn from_bytes(data: &[u8]) -> Result<(Self, usize), PrimitivesError> {
38        if data.is_empty() {
39            return Err(PrimitivesError::UnexpectedEof);
40        }
41        match data[0] {
42            0xff => {
43                if data.len() < 9 {
44                    return Err(PrimitivesError::UnexpectedEof);
45                }
46                let val = u64::from_le_bytes([
47                    data[1], data[2], data[3], data[4],
48                    data[5], data[6], data[7], data[8],
49                ]);
50                Ok((VarInt(val), 9))
51            }
52            0xfe => {
53                if data.len() < 5 {
54                    return Err(PrimitivesError::UnexpectedEof);
55                }
56                let val = u32::from_le_bytes([data[1], data[2], data[3], data[4]]) as u64;
57                Ok((VarInt(val), 5))
58            }
59            0xfd => {
60                if data.len() < 3 {
61                    return Err(PrimitivesError::UnexpectedEof);
62                }
63                let val = u16::from_le_bytes([data[1], data[2]]) as u64;
64                Ok((VarInt(val), 3))
65            }
66            b => {
67                Ok((VarInt(b as u64), 1))
68            }
69        }
70    }
71
72    /// Return the wire-format byte length of this VarInt.
73    ///
74    /// # Returns
75    /// 1, 3, 5, or 9 depending on the value.
76    pub fn length(&self) -> usize {
77        if self.0 < 253 {
78            1
79        } else if self.0 < 65536 {
80            3
81        } else if self.0 < 4294967296 {
82            5
83        } else {
84            9
85        }
86    }
87
88    /// Encode the VarInt into a new byte vector.
89    ///
90    /// # Returns
91    /// A `Vec<u8>` of 1, 3, 5, or 9 bytes.
92    pub fn to_bytes(&self) -> Vec<u8> {
93        let mut buf = vec![0u8; self.length()];
94        self.put_bytes(&mut buf);
95        buf
96    }
97
98    /// Write the VarInt into a destination buffer.
99    ///
100    /// The buffer must be at least `self.length()` bytes long.
101    ///
102    /// # Arguments
103    /// * `dst` - Destination buffer to write into.
104    ///
105    /// # Returns
106    /// The number of bytes written.
107    pub fn put_bytes(&self, dst: &mut [u8]) -> usize {
108        let v = self.0;
109        if v < 0xfd {
110            dst[0] = v as u8;
111            1
112        } else if v < 0x10000 {
113            dst[0] = 0xfd;
114            dst[1..3].copy_from_slice(&(v as u16).to_le_bytes());
115            3
116        } else if v < 0x100000000 {
117            dst[0] = 0xfe;
118            dst[1..5].copy_from_slice(&(v as u32).to_le_bytes());
119            5
120        } else {
121            dst[0] = 0xff;
122            dst[1..9].copy_from_slice(&v.to_le_bytes());
123            9
124        }
125    }
126
127    /// Check if this value is at the upper boundary of a VarInt size class.
128    ///
129    /// Returns how many extra bytes would be needed if the value were
130    /// incremented by 1. Returns -1 at `u64::MAX` (cannot increment).
131    ///
132    /// # Returns
133    /// 0 if not at a boundary, 2 or 4 for size-class transitions, -1 at max.
134    pub fn upper_limit_inc(&self) -> i32 {
135        match self.0 {
136            252 | 65535 => 2,
137            4294967295 => 4,
138            u64::MAX => -1,
139            _ => 0,
140        }
141    }
142
143    /// Return the underlying u64 value.
144    ///
145    /// # Returns
146    /// The integer value.
147    pub fn value(&self) -> u64 {
148        self.0
149    }
150}
151
152impl From<u64> for VarInt {
153    fn from(v: u64) -> Self {
154        VarInt(v)
155    }
156}
157
158impl From<usize> for VarInt {
159    fn from(v: usize) -> Self {
160        VarInt(v as u64)
161    }
162}
163
164// ---------------------------------------------------------------------------
165// BsvReader
166// ---------------------------------------------------------------------------
167
168/// A cursor-based reader for Bitcoin protocol binary data.
169///
170/// Wraps a byte slice and maintains a read position, providing methods
171/// to read fixed-size integers and VarInt values in little-endian order.
172pub struct BsvReader<'a> {
173    data: &'a [u8],
174    pos: usize,
175}
176
177impl<'a> BsvReader<'a> {
178    /// Create a new reader over the given byte slice.
179    ///
180    /// # Arguments
181    /// * `data` - The byte slice to read from.
182    ///
183    /// # Returns
184    /// A `BsvReader` positioned at the start of the data.
185    pub fn new(data: &'a [u8]) -> Self {
186        BsvReader { data, pos: 0 }
187    }
188
189    /// Read `n` bytes and advance the position.
190    ///
191    /// # Arguments
192    /// * `n` - Number of bytes to read.
193    ///
194    /// # Returns
195    /// A byte slice of length `n`, or an error if insufficient data remains.
196    pub fn read_bytes(&mut self, n: usize) -> Result<&'a [u8], PrimitivesError> {
197        if self.pos + n > self.data.len() {
198            return Err(PrimitivesError::UnexpectedEof);
199        }
200        let slice = &self.data[self.pos..self.pos + n];
201        self.pos += n;
202        Ok(slice)
203    }
204
205    /// Read a single byte and advance the position.
206    ///
207    /// # Returns
208    /// The byte value, or an error if no data remains.
209    pub fn read_u8(&mut self) -> Result<u8, PrimitivesError> {
210        let bytes = self.read_bytes(1)?;
211        Ok(bytes[0])
212    }
213
214    /// Read a little-endian u16 and advance the position by 2 bytes.
215    ///
216    /// # Returns
217    /// The decoded u16, or an error if insufficient data.
218    pub fn read_u16_le(&mut self) -> Result<u16, PrimitivesError> {
219        let bytes = self.read_bytes(2)?;
220        Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
221    }
222
223    /// Read a little-endian u32 and advance the position by 4 bytes.
224    ///
225    /// # Returns
226    /// The decoded u32, or an error if insufficient data.
227    pub fn read_u32_le(&mut self) -> Result<u32, PrimitivesError> {
228        let bytes = self.read_bytes(4)?;
229        Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
230    }
231
232    /// Read a little-endian u64 and advance the position by 8 bytes.
233    ///
234    /// # Returns
235    /// The decoded u64, or an error if insufficient data.
236    pub fn read_u64_le(&mut self) -> Result<u64, PrimitivesError> {
237        let bytes = self.read_bytes(8)?;
238        Ok(u64::from_le_bytes([
239            bytes[0], bytes[1], bytes[2], bytes[3],
240            bytes[4], bytes[5], bytes[6], bytes[7],
241        ]))
242    }
243
244    /// Read a VarInt and advance the position accordingly.
245    ///
246    /// # Returns
247    /// The decoded `VarInt`, or an error if insufficient data.
248    pub fn read_varint(&mut self) -> Result<VarInt, PrimitivesError> {
249        let first = self.read_u8()?;
250        match first {
251            0xff => {
252                let val = self.read_u64_le()?;
253                Ok(VarInt(val))
254            }
255            0xfe => {
256                let val = self.read_u32_le()? as u64;
257                Ok(VarInt(val))
258            }
259            0xfd => {
260                let val = self.read_u16_le()? as u64;
261                Ok(VarInt(val))
262            }
263            b => Ok(VarInt(b as u64)),
264        }
265    }
266
267    /// Return the number of bytes remaining.
268    ///
269    /// # Returns
270    /// The count of unread bytes.
271    pub fn remaining(&self) -> usize {
272        self.data.len() - self.pos
273    }
274}
275
276// ---------------------------------------------------------------------------
277// BsvWriter
278// ---------------------------------------------------------------------------
279
280/// A buffer-based writer for Bitcoin protocol binary data.
281///
282/// Wraps a `Vec<u8>` and provides methods to append fixed-size integers
283/// and VarInt values in little-endian order.
284pub struct BsvWriter {
285    buf: Vec<u8>,
286}
287
288impl BsvWriter {
289    /// Create a new empty writer.
290    ///
291    /// # Returns
292    /// A `BsvWriter` with an empty internal buffer.
293    pub fn new() -> Self {
294        BsvWriter { buf: Vec::new() }
295    }
296
297    /// Create a new writer with a pre-allocated capacity.
298    ///
299    /// # Arguments
300    /// * `capacity` - Initial byte capacity of the internal buffer.
301    ///
302    /// # Returns
303    /// A `BsvWriter` with the given capacity.
304    pub fn with_capacity(capacity: usize) -> Self {
305        BsvWriter { buf: Vec::with_capacity(capacity) }
306    }
307
308    /// Append raw bytes to the buffer.
309    ///
310    /// # Arguments
311    /// * `bytes` - The bytes to append.
312    pub fn write_bytes(&mut self, bytes: &[u8]) {
313        self.buf.extend_from_slice(bytes);
314    }
315
316    /// Append a single byte to the buffer.
317    ///
318    /// # Arguments
319    /// * `val` - The byte value.
320    pub fn write_u8(&mut self, val: u8) {
321        self.buf.push(val);
322    }
323
324    /// Append a little-endian u16 (2 bytes) to the buffer.
325    ///
326    /// # Arguments
327    /// * `val` - The u16 value.
328    pub fn write_u16_le(&mut self, val: u16) {
329        self.buf.extend_from_slice(&val.to_le_bytes());
330    }
331
332    /// Append a little-endian u32 (4 bytes) to the buffer.
333    ///
334    /// # Arguments
335    /// * `val` - The u32 value.
336    pub fn write_u32_le(&mut self, val: u32) {
337        self.buf.extend_from_slice(&val.to_le_bytes());
338    }
339
340    /// Append a little-endian u64 (8 bytes) to the buffer.
341    ///
342    /// # Arguments
343    /// * `val` - The u64 value.
344    pub fn write_u64_le(&mut self, val: u64) {
345        self.buf.extend_from_slice(&val.to_le_bytes());
346    }
347
348    /// Append a VarInt to the buffer.
349    ///
350    /// # Arguments
351    /// * `varint` - The VarInt value to encode and append.
352    pub fn write_varint(&mut self, varint: VarInt) {
353        let bytes = varint.to_bytes();
354        self.buf.extend_from_slice(&bytes);
355    }
356
357    /// Consume the writer and return the accumulated bytes.
358    ///
359    /// # Returns
360    /// The internal byte buffer.
361    pub fn into_bytes(self) -> Vec<u8> {
362        self.buf
363    }
364
365    /// Return a reference to the current buffer contents.
366    ///
367    /// # Returns
368    /// A byte slice of the written data.
369    pub fn as_bytes(&self) -> &[u8] {
370        &self.buf
371    }
372
373    /// Return the current length of the buffer.
374    ///
375    /// # Returns
376    /// The number of bytes written so far.
377    pub fn len(&self) -> usize {
378        self.buf.len()
379    }
380
381    /// Check if the buffer is empty.
382    ///
383    /// # Returns
384    /// `true` if no bytes have been written.
385    pub fn is_empty(&self) -> bool {
386        self.buf.is_empty()
387    }
388}
389
390impl Default for BsvWriter {
391    fn default() -> Self {
392        Self::new()
393    }
394}
395
396#[cfg(test)]
397mod tests {
398    use super::*;
399
400    // -- VarInt decode tests (from Go varint_test.go TestDecodeVarInt) --
401
402    /// Helper to convert a u64 to 8 little-endian bytes.
403    fn le_bytes(v: u64) -> Vec<u8> {
404        v.to_le_bytes().to_vec()
405    }
406
407    #[test]
408    fn test_decode_varint() {
409        // 0xff prefix -> reads 8 bytes after prefix -> value 0, size 9
410        let mut input = vec![0xff, 0, 0, 0, 0, 0, 0, 0, 0]; // 1 prefix + 8 data bytes
411        let (vi, sz) = VarInt::from_bytes(&input).unwrap();
412        assert_eq!(vi.0, 0);
413        assert_eq!(sz, 9);
414
415        // 0xfe prefix -> reads 4 bytes after prefix -> value 0, size 5
416        input = vec![0xfe, 0, 0, 0, 0];
417        let (vi, sz) = VarInt::from_bytes(&input).unwrap();
418        assert_eq!(vi.0, 0);
419        assert_eq!(sz, 5);
420
421        // 0xfd prefix -> reads 2 bytes after prefix -> value 0, size 3
422        input = vec![0xfd, 0, 0];
423        let (vi, sz) = VarInt::from_bytes(&input).unwrap();
424        assert_eq!(vi.0, 0);
425        assert_eq!(sz, 3);
426
427        // value 1 -> single byte, size 1
428        let input = le_bytes(1);
429        let (vi, sz) = VarInt::from_bytes(&input).unwrap();
430        assert_eq!(vi.0, 1);
431        assert_eq!(sz, 1);
432    }
433
434    #[test]
435    fn test_decode_varint_too_short() {
436        assert!(VarInt::from_bytes(&[]).is_err());
437        assert!(VarInt::from_bytes(&[0xff, 0, 0]).is_err());
438        assert!(VarInt::from_bytes(&[0xfe, 0]).is_err());
439        assert!(VarInt::from_bytes(&[0xfd]).is_err());
440    }
441
442    // -- VarInt upper-limit-inc tests --
443
444    #[test]
445    fn test_varint_upper_limit_inc() {
446        assert_eq!(VarInt(0).upper_limit_inc(), 0);
447        assert_eq!(VarInt(10).upper_limit_inc(), 0);
448        assert_eq!(VarInt(100).upper_limit_inc(), 0);
449        assert_eq!(VarInt(252).upper_limit_inc(), 2);
450        assert_eq!(VarInt(65535).upper_limit_inc(), 2);
451        assert_eq!(VarInt(4294967295).upper_limit_inc(), 4);
452        assert_eq!(VarInt(u64::MAX).upper_limit_inc(), -1);
453    }
454
455    // -- VarInt byte-length tests --
456
457    #[test]
458    fn test_varint_byte_length() {
459        assert_eq!(VarInt(0).to_bytes().len(), 1);        // 1 byte lower
460        assert_eq!(VarInt(252).to_bytes().len(), 1);       // 1 byte upper
461        assert_eq!(VarInt(253).to_bytes().len(), 3);       // 3 byte lower
462        assert_eq!(VarInt(65535).to_bytes().len(), 3);     // 3 byte upper
463        assert_eq!(VarInt(65536).to_bytes().len(), 5);     // 5 byte lower
464        assert_eq!(VarInt(4294967295).to_bytes().len(), 5);// 5 byte upper
465        assert_eq!(VarInt(4294967296).to_bytes().len(), 9);// 9 byte lower
466        assert_eq!(VarInt(u64::MAX).to_bytes().len(), 9);  // 9 byte upper
467    }
468
469    // -- VarInt size (length) tests --
470
471    #[test]
472    fn test_varint_size() {
473        assert_eq!(VarInt(252).length(), 1);
474        assert_eq!(VarInt(253).length(), 3);
475        assert_eq!(VarInt(65535).length(), 3);
476        assert_eq!(VarInt(65536).length(), 5);
477        assert_eq!(VarInt(4294967295).length(), 5);
478        assert_eq!(VarInt(4294967296).length(), 9);
479    }
480
481    // -- VarInt put_bytes tests --
482
483    #[test]
484    fn test_varint_put_bytes() {
485        let cases: Vec<(u64, Vec<u8>)> = vec![
486            (0, vec![0x00]),
487            (1, vec![0x01]),
488            (252, vec![0xfc]),
489            (253, vec![0xfd, 0xfd, 0x00]),
490            (65535, vec![0xfd, 0xff, 0xff]),
491            (65536, vec![0xfe, 0x00, 0x00, 0x01, 0x00]),
492            (4294967295, vec![0xfe, 0xff, 0xff, 0xff, 0xff]),
493            (4294967296, vec![0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]),
494            (u64::MAX, vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
495        ];
496
497        for (value, expected) in cases {
498            let vi = VarInt(value);
499            let mut buf = vec![0u8; vi.length()];
500            let n = vi.put_bytes(&mut buf);
501            assert_eq!(n, expected.len(), "put_bytes length mismatch for {}", value);
502            assert_eq!(buf, expected, "put_bytes content mismatch for {}", value);
503            // Verify put_bytes matches to_bytes.
504            assert_eq!(vi.to_bytes(), buf, "to_bytes != put_bytes for {}", value);
505        }
506    }
507
508    // -- BsvReader / BsvWriter round-trip tests --
509
510    #[test]
511    fn test_bsv_reader_writer_roundtrip() {
512        let mut writer = BsvWriter::new();
513        writer.write_u8(0x42);
514        writer.write_u16_le(0x1234);
515        writer.write_u32_le(0xDEADBEEF);
516        writer.write_u64_le(0x0102030405060708);
517        writer.write_varint(VarInt(300));
518        writer.write_bytes(b"hello");
519
520        let data = writer.into_bytes();
521        let mut reader = BsvReader::new(&data);
522
523        assert_eq!(reader.read_u8().unwrap(), 0x42);
524        assert_eq!(reader.read_u16_le().unwrap(), 0x1234);
525        assert_eq!(reader.read_u32_le().unwrap(), 0xDEADBEEF);
526        assert_eq!(reader.read_u64_le().unwrap(), 0x0102030405060708);
527        assert_eq!(reader.read_varint().unwrap(), VarInt(300));
528        assert_eq!(reader.read_bytes(5).unwrap(), b"hello");
529        assert_eq!(reader.remaining(), 0);
530    }
531
532    #[test]
533    fn test_bsv_reader_eof() {
534        let reader_data: &[u8] = &[0x01];
535        let mut reader = BsvReader::new(reader_data);
536        assert!(reader.read_u8().is_ok());
537        assert!(reader.read_u8().is_err());
538    }
539
540    #[test]
541    fn test_bsv_reader_varint_sizes() {
542        // 1-byte varint
543        let mut reader = BsvReader::new(&[0x05]);
544        assert_eq!(reader.read_varint().unwrap(), VarInt(5));
545
546        // 3-byte varint (0xfd prefix)
547        let mut reader = BsvReader::new(&[0xfd, 0x00, 0x01]);
548        assert_eq!(reader.read_varint().unwrap(), VarInt(256));
549
550        // 5-byte varint (0xfe prefix)
551        let mut reader = BsvReader::new(&[0xfe, 0x00, 0x00, 0x01, 0x00]);
552        assert_eq!(reader.read_varint().unwrap(), VarInt(65536));
553
554        // 9-byte varint (0xff prefix)
555        let mut reader = BsvReader::new(&[0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]);
556        assert_eq!(reader.read_varint().unwrap(), VarInt(4294967296));
557    }
558}