123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- use super::{Error, Ipv6Option, Ipv6OptionRepr, Ipv6OptionsIterator, Result};
- use heapless::Vec;
- pub struct Header<T: AsRef<[u8]>> {
- buffer: T,
- }
- impl<T: AsRef<[u8]>> Header<T> {
-
- pub const fn new_unchecked(buffer: T) -> Self {
- Header { buffer }
- }
-
-
-
-
- pub fn new_checked(buffer: T) -> Result<Self> {
- let header = Self::new_unchecked(buffer);
- header.check_len()?;
- Ok(header)
- }
-
-
-
-
-
-
- pub fn check_len(&self) -> Result<()> {
- if self.buffer.as_ref().is_empty() {
- return Err(Error);
- }
- Ok(())
- }
-
- pub fn into_inner(self) -> T {
- self.buffer
- }
- }
- impl<'a, T: AsRef<[u8]> + ?Sized> Header<&'a T> {
-
- pub fn options(&self) -> &'a [u8] {
- self.buffer.as_ref()
- }
- }
- impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Header<&'a mut T> {
-
- pub fn options_mut(&mut self) -> &mut [u8] {
- self.buffer.as_mut()
- }
- }
- #[derive(Debug, PartialEq, Eq, Clone)]
- #[cfg_attr(feature = "defmt", derive(defmt::Format))]
- pub struct Repr<'a> {
- pub options: heapless::Vec<Ipv6OptionRepr<'a>, { crate::config::IPV6_HBH_MAX_OPTIONS }>,
- }
- impl<'a> Repr<'a> {
-
- pub fn parse<T>(header: &'a Header<&'a T>) -> Result<Repr<'a>>
- where
- T: AsRef<[u8]> + ?Sized,
- {
- let mut options = Vec::new();
- let iter = Ipv6OptionsIterator::new(header.options());
- for option in iter {
- let option = option?;
- if let Err(e) = options.push(option) {
- net_trace!("eror when parsing hop-by-hop options: {}", e);
- break;
- }
- }
- Ok(Self { options })
- }
-
-
- pub fn buffer_len(&self) -> usize {
- self.options.iter().map(|o| o.buffer_len()).sum()
- }
-
- pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, header: &mut Header<&mut T>) {
- let mut buffer = header.options_mut();
- for opt in &self.options {
- opt.emit(&mut Ipv6Option::new_unchecked(
- &mut buffer[..opt.buffer_len()],
- ));
- buffer = &mut buffer[opt.buffer_len()..];
- }
- }
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- use crate::wire::Error;
-
- static REPR_PACKET_PAD4: [u8; 6] = [0x1, 0x4, 0x0, 0x0, 0x0, 0x0];
-
- static REPR_PACKET_PAD12: [u8; 14] = [
- 0x1, 0x0C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- ];
- #[test]
- fn test_check_len() {
-
- assert_eq!(
- Err(Error),
- Header::new_unchecked(&REPR_PACKET_PAD4[..0]).check_len()
- );
-
- assert_eq!(Ok(()), Header::new_unchecked(&REPR_PACKET_PAD4).check_len());
-
- assert_eq!(
- Ok(()),
- Header::new_unchecked(&REPR_PACKET_PAD12).check_len()
- );
- }
- #[test]
- fn test_repr_parse_valid() {
- let header = Header::new_unchecked(&REPR_PACKET_PAD4);
- let repr = Repr::parse(&header).unwrap();
- let mut options = Vec::new();
- options.push(Ipv6OptionRepr::PadN(4)).unwrap();
- assert_eq!(repr, Repr { options });
- let header = Header::new_unchecked(&REPR_PACKET_PAD12);
- let repr = Repr::parse(&header).unwrap();
- let mut options = Vec::new();
- options.push(Ipv6OptionRepr::PadN(12)).unwrap();
- assert_eq!(repr, Repr { options });
- }
- #[test]
- fn test_repr_emit() {
- let mut options = Vec::new();
- options.push(Ipv6OptionRepr::PadN(4)).unwrap();
- let repr = Repr { options };
- let mut bytes = [0u8; 6];
- let mut header = Header::new_unchecked(&mut bytes);
- repr.emit(&mut header);
- assert_eq!(header.into_inner(), &REPR_PACKET_PAD4[..]);
- let mut options = Vec::new();
- options.push(Ipv6OptionRepr::PadN(12)).unwrap();
- let repr = Repr { options };
- let mut bytes = [0u8; 14];
- let mut header = Header::new_unchecked(&mut bytes);
- repr.emit(&mut header);
- assert_eq!(header.into_inner(), &REPR_PACKET_PAD12[..]);
- }
- }
|