use super::scan_len;
use crate::{Error, Visit};
use crate::{ParseResult, SResult, Visitor};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Witness<'a> {
slice: &'a [u8],
n: usize,
}
impl<'a> AsRef<[u8]> for Witness<'a> {
fn as_ref(&self) -> &[u8] {
self.slice
}
}
impl<'a> Visit<'a> for Witness<'a> {
#[inline(always)]
fn visit<'b, V: Visitor>(slice: &'a [u8], visit: &'b mut V) -> SResult<'a, Witness<'a>> {
let mut consumed = 0usize;
let n = scan_len(slice, &mut consumed)?;
let witness_total_element = n as usize;
visit.visit_witness_total_element(witness_total_element);
for i in 0..witness_total_element {
let len = scan_len(&slice[consumed..], &mut consumed)? as usize;
let end = consumed.saturating_add(len);
if end > slice.len() {
return Err(Error::MoreBytesNeeded);
}
let witness_element = &slice[consumed..end];
consumed = end;
visit.visit_witness_element(i, witness_element);
}
let witness = Witness {
slice: &slice[..consumed],
n: witness_total_element,
};
Ok(ParseResult::new(&slice[consumed..], witness))
}
}
impl<'a> Witness<'a> {
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.n == 0
}
}
#[cfg(test)]
mod test {
use crate::{bsl::Witness, Parse, ParseResult, Visit, Visitor};
use hex_lit::hex;
const FUZZ_DATA: [u8; 14] = [
189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 2,
];
#[test]
fn parse_witness() {
let witness = hex!("0201000100");
let expected = Witness {
slice: &witness[..],
n: 2,
};
assert_eq!(
Witness::parse(&witness[..]),
Ok(ParseResult::new_exact(expected))
);
let malformed_witness = hex!("02010001");
assert_eq!(
Witness::parse(&malformed_witness[..]),
Err(crate::Error::MoreBytesNeeded)
);
assert_eq!(
Witness::parse(&FUZZ_DATA),
Err(crate::Error::MoreBytesNeeded)
);
}
#[test]
fn visit_witness() {
let witness = hex!("0201000101");
struct WitnessVisititor(usize);
impl Visitor for WitnessVisititor {
fn visit_witness_total_element(&mut self, witness_total: usize) {
assert_eq!(witness_total, 2);
}
fn visit_witness_element(&mut self, witness_i: usize, witness_element: &[u8]) {
assert_eq!(witness_i, self.0);
assert_eq!(witness_element, &[self.0 as u8]);
self.0 += 1;
}
}
Witness::visit(&witness[..], &mut WitnessVisititor(0)).unwrap();
}
}