domain_core/bits/opt/
rfc8145.rs1use bytes::{BigEndian, BufMut, ByteOrder, Bytes};
4use ::bits::compose::Compose;
5use ::bits::message_builder::OptBuilder;
6use ::bits::parse::{ParseAll, ParseAllError, Parser, ShortBuf};
7use ::iana::OptionCode;
8use super::CodeOptData;
9
10
11#[derive(Clone, Debug, Eq, Hash, PartialEq)]
14pub struct KeyTag {
15 bytes: Bytes,
16}
17
18impl KeyTag {
19 pub fn new(bytes: Bytes) -> Self {
20 KeyTag { bytes }
21 }
22
23 pub fn push(builder: &mut OptBuilder, tags: &[u16])
24 -> Result<(), ShortBuf> {
25 let len = tags.len() * 2;
26 assert!(len <= ::std::u16::MAX as usize);
27 builder.build(OptionCode::KeyTag, len as u16, |buf| {
28 for tag in tags {
29 buf.compose(&tag)?
30 }
31 Ok(())
32 })
33 }
34
35 pub fn iter(&self) -> KeyTagIter {
36 KeyTagIter(self.bytes.as_ref())
37 }
38}
39
40
41impl ParseAll for KeyTag {
44 type Err = ParseAllError;
45
46 fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
47 if len % 2 == 1 {
48 Err(ParseAllError::TrailingData)
49 }
50 else {
51 Ok(Self::new(parser.parse_bytes(len)?))
52 }
53 }
54}
55
56impl Compose for KeyTag {
57 fn compose_len(&self) -> usize {
58 self.bytes.len()
59 }
60
61 fn compose<B: BufMut>(&self, buf: &mut B) {
62 buf.put_slice(self.bytes.as_ref())
63 }
64}
65
66
67impl CodeOptData for KeyTag {
70 const CODE: OptionCode = OptionCode::KeyTag;
71}
72
73
74impl<'a> IntoIterator for &'a KeyTag {
77 type Item = u16;
78 type IntoIter = KeyTagIter<'a>;
79
80 fn into_iter(self) -> Self::IntoIter {
81 self.iter()
82 }
83}
84
85
86#[derive(Clone, Copy, Debug)]
89pub struct KeyTagIter<'a>(&'a [u8]);
90
91impl<'a> Iterator for KeyTagIter<'a> {
92 type Item = u16;
93
94 fn next(&mut self) -> Option<Self::Item> {
95 if self.0.len() < 2 {
96 None
97 }
98 else {
99 let (item, tail) = self.0.split_at(2);
100 self.0 = tail;
101 Some(BigEndian::read_u16(item))
102 }
103 }
104}
105