use super::SignatureAndHashAlgorithm;
use crate::buffer::Buf;
use nom::number::complete::be_u16;
use nom::{IResult, bytes::complete::take};
use std::ops::Range;
#[derive(Debug, PartialEq, Eq)]
pub struct DigitallySigned {
pub algorithm: SignatureAndHashAlgorithm,
pub signature_range: Range<usize>,
}
impl DigitallySigned {
pub fn signature<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
&buf[self.signature_range.clone()]
}
pub fn parse(input: &[u8], base_offset: usize) -> IResult<&[u8], DigitallySigned> {
let original_input = input;
let (rest, algorithm) = SignatureAndHashAlgorithm::parse(input)?;
let (rest, signature_len) = be_u16(rest)?;
let (rest, signature_slice) = take(signature_len)(rest)?;
let relative_offset = signature_slice.as_ptr() as usize - original_input.as_ptr() as usize;
let start = base_offset + relative_offset;
let end = start + signature_slice.len();
Ok((
rest,
DigitallySigned {
algorithm,
signature_range: start..end,
},
))
}
pub fn serialize(&self, buf: &[u8], output: &mut Buf) {
output.extend_from_slice(&self.algorithm.as_u16().to_be_bytes());
let signature = self.signature(buf);
output.extend_from_slice(&(signature.len() as u16).to_be_bytes());
output.extend_from_slice(signature);
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::buffer::Buf;
const MESSAGE: &[u8] = &[
0x04, 0x01, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, ];
#[test]
fn roundtrip() {
let (rest, parsed) = DigitallySigned::parse(MESSAGE, 0).unwrap();
assert!(rest.is_empty());
let mut serialized = Buf::new();
parsed.serialize(MESSAGE, &mut serialized);
assert_eq!(&*serialized, MESSAGE);
}
}