use zeroize::Zeroize;
#[cfg(not(feature = "std"))]
use crate::prelude::*;
pub(crate) struct LcCBB {
buf: Vec<u8>,
}
impl LcCBB {
pub(crate) fn new(initial_capacity: usize) -> Self {
Self {
buf: Vec::with_capacity(initial_capacity.max(64)),
}
}
pub(crate) fn into_vec(mut self) -> Result<Vec<u8>, crate::error::Unspecified> {
Ok(core::mem::take(&mut self.buf))
}
#[allow(dead_code)]
pub(crate) fn extend(&mut self, data: &[u8]) {
self.buf.extend_from_slice(data);
}
#[allow(dead_code)]
pub(crate) fn len(&self) -> usize {
self.buf.len()
}
pub(crate) unsafe fn reserve_uninit(&mut self, n: usize) -> *mut u8 {
self.buf.reserve(n);
let pos = self.buf.len();
self.buf.set_len(pos + n);
self.buf.as_mut_ptr().add(pos)
}
#[allow(dead_code)]
pub(crate) fn add_asn1_bool(&mut self, value: bool) {
self.buf.push(0x01); self.buf.push(0x01); self.buf.push(if value { 0xFF } else { 0x00 });
}
}
impl Drop for LcCBB {
fn drop(&mut self) {
self.buf.zeroize();
}
}
#[cfg(test)]
mod tests {
use super::LcCBB;
#[test]
fn dynamic_vec() {
let mut cbb = LcCBB::new(4);
cbb.add_asn1_bool(true);
let vec = cbb.into_vec().expect("be copied to buffer");
assert_eq!(vec.as_slice(), &[1, 1, 255]);
}
#[test]
fn dynamic_buffer_grows() {
let mut cbb = LcCBB::new(1);
cbb.add_asn1_bool(true);
let vec = cbb.into_vec().expect("be copied to buffer");
assert_eq!(vec.as_slice(), &[1, 1, 255]);
}
#[test]
fn extend_bytes() {
let mut cbb = LcCBB::new(8);
cbb.extend(&[0x01, 0x02, 0x03]);
cbb.extend(&[0x04, 0x05]);
let vec = cbb.into_vec().expect("get vec");
assert_eq!(vec.as_slice(), &[0x01, 0x02, 0x03, 0x04, 0x05]);
}
#[test]
fn reserve_uninit() {
let mut cbb = LcCBB::new(8);
unsafe {
let ptr = cbb.reserve_uninit(3);
*ptr = 0xAA;
*ptr.add(1) = 0xBB;
*ptr.add(2) = 0xCC;
}
let vec = cbb.into_vec().expect("get vec");
assert_eq!(vec.as_slice(), &[0xAA, 0xBB, 0xCC]);
}
#[test]
fn add_asn1_bool_false() {
let mut cbb = LcCBB::new(4);
cbb.add_asn1_bool(false);
let vec = cbb.into_vec().expect("get vec");
assert_eq!(vec.as_slice(), &[1, 1, 0]);
}
}