domain_core/bits/opt/
rfc6975.rs

1//! EDNS Options from RFC 6975.
2
3use std::slice;
4use bytes::{BufMut, Bytes};
5use ::bits::compose::Compose;
6use ::bits::message_builder::OptBuilder;
7use ::bits::parse::{ParseAll, Parser, ShortBuf};
8use ::iana::{OptionCode, SecAlg};
9use super::CodeOptData;
10
11
12//------------ Dau, Dhu, N3u -------------------------------------------------
13
14macro_rules! option_type {
15    ( $name:ident ) => {
16        #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
17        pub struct $name {
18            bytes: Bytes,
19        }
20
21        impl $name {
22
23            pub fn from_bytes(bytes: Bytes) -> Self {
24                $name { bytes }
25            }
26
27            pub fn iter(&self) -> SecAlgsIter {
28                SecAlgsIter::new(self.bytes.as_ref())
29            }
30
31            pub fn push(builder: &mut OptBuilder, algs: &[SecAlg])
32                        -> Result<(), ShortBuf> {
33                assert!(algs.len() <= ::std::u16::MAX as usize);
34                builder.build(OptionCode::$name, algs.len() as u16, |buf| {
35                    for alg in algs {
36                        buf.compose(&alg.to_int())?
37                    }
38                    Ok(())
39                })
40            }
41        }
42
43        //--- ParseAll, Compose
44
45        impl ParseAll for $name {
46            type Err = ShortBuf;
47
48            fn parse_all(parser: &mut Parser, len: usize)
49                         -> Result<Self, Self::Err> {
50                parser.parse_bytes(len).map(Self::from_bytes)
51            }
52        }
53
54        impl Compose for $name {
55            fn compose_len(&self) -> usize {
56                self.bytes.len()
57            }
58
59            fn compose<B: BufMut>(&self, buf: &mut B) {
60                buf.put_slice(self.bytes.as_ref())
61            }
62        }
63
64
65        //--- CodeOptData
66        
67        impl CodeOptData for $name {
68            const CODE: OptionCode = OptionCode::$name;
69        }
70
71        
72        //--- IntoIter
73
74        impl<'a> IntoIterator for &'a $name {
75            type Item = SecAlg;
76            type IntoIter = SecAlgsIter<'a>;
77
78            fn into_iter(self) -> Self::IntoIter {
79                self.iter()
80            }
81        }
82    }
83}
84
85option_type!(Dau);
86option_type!(Dhu);
87option_type!(N3u);
88
89
90//------------ SecAlgsIter ---------------------------------------------------
91
92pub struct SecAlgsIter<'a>(slice::Iter<'a, u8>);
93
94impl<'a> SecAlgsIter<'a> {
95    fn new(slice: &'a [u8]) -> Self {
96        SecAlgsIter(slice.iter())
97    }
98}
99
100impl<'a> Iterator for SecAlgsIter<'a> {
101    type Item = SecAlg;
102
103    fn next(&mut self) -> Option<Self::Item> {
104        self.0.next().map(|x| SecAlg::from_int(*x))
105    }
106}