Skip to content

Commit aa00732

Browse files
committed
consensus_encoding: Add CompactSizeEncoder implementation
This addresses the need for a dedicated compact size encoder that was discussed in rust-bitcoin#5077
1 parent b33216c commit aa00732

File tree

1 file changed

+60
-1
lines changed

1 file changed

+60
-1
lines changed

consensus_encoding/src/encode/encoders.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//!
1313
1414
use internals::array_vec::ArrayVec;
15-
use internals::compact_size;
15+
use internals::{compact_size, ToU64};
1616

1717
use super::{Encodable, Encoder};
1818

@@ -250,6 +250,27 @@ impl<A: Encoder, B: Encoder, C: Encoder, D: Encoder, E: Encoder, F: Encoder> Enc
250250
fn advance(&mut self) -> bool { self.inner.advance() }
251251
}
252252

253+
/// Encoder for a compact size encoded integer.
254+
pub struct CompactSizeEncoder {
255+
buf: Option<ArrayVec<u8, SIZE>>,
256+
}
257+
258+
impl CompactSizeEncoder {
259+
/// Constructs a new `CompactSizeEncoder`.
260+
pub fn new(value: impl ToU64) -> Self { Self { buf: Some(compact_size::encode(value)) } }
261+
}
262+
263+
impl Encoder for CompactSizeEncoder {
264+
#[inline]
265+
fn current_chunk(&self) -> Option<&[u8]> { self.buf.as_ref().map(|b| &b[..]) }
266+
267+
#[inline]
268+
fn advance(&mut self) -> bool {
269+
self.buf = None;
270+
false
271+
}
272+
}
273+
253274
#[cfg(test)]
254275
mod tests {
255276
use super::*;
@@ -651,4 +672,42 @@ mod tests {
651672
assert!(!encoder.advance());
652673
assert_eq!(encoder.current_chunk(), None);
653674
}
675+
#[test]
676+
fn encode_compact_size() {
677+
// 1-byte
678+
let mut e = CompactSizeEncoder::new(0x10u64);
679+
assert_eq!(e.current_chunk(), Some(&[0x10][..]));
680+
assert!(!e.advance());
681+
assert_eq!(e.current_chunk(), None);
682+
683+
let mut e = CompactSizeEncoder::new(0xFCu64);
684+
assert_eq!(e.current_chunk(), Some(&[0xFC][..]));
685+
assert!(!e.advance());
686+
687+
// 0xFD + u16
688+
let mut e = CompactSizeEncoder::new(0x00FDu64);
689+
assert_eq!(e.current_chunk(), Some(&[0xFD, 0xFD, 0x00][..]));
690+
assert!(!e.advance());
691+
692+
let mut e = CompactSizeEncoder::new(0x0FFFu64);
693+
assert_eq!(e.current_chunk(), Some(&[0xFD, 0xFF, 0x0F][..]));
694+
assert!(!e.advance());
695+
696+
// 0xFE + u32
697+
let mut e = CompactSizeEncoder::new(0x0001_0000u64);
698+
assert_eq!(e.current_chunk(), Some(&[0xFE, 0x00, 0x00, 0x01, 0x00][..]));
699+
assert!(!e.advance());
700+
701+
let mut e = CompactSizeEncoder::new(0x0F0F_0F0Fu64);
702+
assert_eq!(e.current_chunk(), Some(&[0xFE, 0x0F, 0x0F, 0x0F, 0x0F][..]));
703+
assert!(!e.advance());
704+
705+
// 0xFF + u64
706+
let mut e = CompactSizeEncoder::new(0x0000_F0F0_F0F0_F0E0u64);
707+
assert_eq!(
708+
e.current_chunk(),
709+
Some(&[0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00][..])
710+
);
711+
assert!(!e.advance());
712+
}
654713
}

0 commit comments

Comments
 (0)