proxy_header/
util.rs

1use std::{
2    net::{IpAddr, Ipv4Addr, Ipv6Addr},
3    str::FromStr,
4};
5
6pub fn read_until(buf: &[u8], delim: u8) -> Option<&[u8]> {
7    for i in 0..buf.len() {
8        if buf[i] == delim {
9            return Some(&buf[..i]);
10        }
11    }
12    None
13}
14
15pub trait AddressFamily: FromStr {
16    const BYTES: usize;
17
18    fn to_ip_addr(self) -> IpAddr;
19    fn from_slice(slice: &[u8]) -> Self;
20}
21
22impl AddressFamily for Ipv4Addr {
23    const BYTES: usize = 4;
24
25    fn to_ip_addr(self) -> IpAddr {
26        IpAddr::V4(self)
27    }
28
29    fn from_slice(slice: &[u8]) -> Self {
30        let arr: [u8; 4] = slice.try_into().expect("slice must be 4 bytes");
31        arr.into()
32    }
33}
34
35impl AddressFamily for Ipv6Addr {
36    const BYTES: usize = 16;
37
38    fn to_ip_addr(self) -> IpAddr {
39        IpAddr::V6(self)
40    }
41
42    fn from_slice(slice: &[u8]) -> Self {
43        let arr: [u8; 16] = slice.try_into().expect("slice must be 16 bytes");
44        arr.into()
45    }
46}
47
48macro_rules! tlv {
49    ($self:expr, $kind:ident) => {{
50        $self.tlvs().find_map(|f| match f {
51            Ok(crate::Tlv::$kind(v)) => Some(v),
52            _ => None,
53        })
54    }};
55}
56
57macro_rules! tlv_borrowed {
58    ($self:expr, $kind:ident) => {{
59        $self.tlvs().find_map(|f| match f {
60            Ok(crate::Tlv::$kind(v)) => match v {
61                // It is more ergonomic to return the borrowed value directly rather
62                // than it wrapped in a `Cow::Borrowed`. We know that tlvs always borrows
63                // so we can safely unwrap the `Cow::Borrowed` and return the borrowed value.
64                Cow::Owned(_) => unreachable!(),
65                Cow::Borrowed(v) => Some(v),
66            },
67            _ => None,
68        })
69    }};
70}
71
72pub(crate) use {tlv, tlv_borrowed};