domain/base/opt/
expire.rs1use core::fmt;
12use super::super::iana::OptionCode;
13use super::super::message_builder::OptBuilder;
14use super::super::wire::{Compose, Composer, Parse, ParseError};
15use super::{Opt, OptData, ComposeOptData, ParseOptData};
16use octseq::builder::OctetsBuilder;
17use octseq::octets::Octets;
18use octseq::parse::Parser;
19
20
21#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize))]
33pub struct Expire(Option<u32>);
34
35impl Expire {
36 pub(super) const CODE: OptionCode = OptionCode::EXPIRE;
38
39 #[must_use]
41 pub fn new(expire: Option<u32>) -> Self {
42 Expire(expire)
43 }
44
45 #[must_use]
47 pub fn expire(self) -> Option<u32> {
48 self.0
49 }
50
51 pub fn parse<Octs: AsRef<[u8]>>(
53 parser: &mut Parser<Octs>
54 ) -> Result<Self, ParseError> {
55 if parser.remaining() == 0 {
56 Ok(Expire::new(None))
57 }
58 else {
59 u32::parse(parser).map(|res| Expire::new(Some(res)))
60 }
61 }
62
63 pub(super) fn try_octets_from<E>(src: Self) -> Result<Self, E> {
67 Ok(src)
68 }
69}
70
71impl OptData for Expire {
74 fn code(&self) -> OptionCode {
75 OptionCode::EXPIRE
76 }
77}
78
79impl<'a, Octs: AsRef<[u8]>> ParseOptData<'a, Octs> for Expire {
80 fn parse_option(
81 code: OptionCode,
82 parser: &mut Parser<'a, Octs>,
83 ) -> Result<Option<Self>, ParseError> {
84 if code == OptionCode::EXPIRE {
85 Self::parse(parser).map(Some)
86 }
87 else {
88 Ok(None)
89 }
90 }
91}
92
93impl ComposeOptData for Expire {
94 fn compose_len(&self) -> u16 {
95 match self.0 {
96 Some(_) => u32::COMPOSE_LEN,
97 None => 0,
98 }
99 }
100
101 fn compose_option<Target: OctetsBuilder + ?Sized>(
102 &self, target: &mut Target
103 ) -> Result<(), Target::AppendError> {
104 if let Some(value) = self.0 {
105 value.compose(target)?;
106 }
107 Ok(())
108 }
109}
110
111impl fmt::Display for Expire {
114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 match self.0 {
116 Some(expire) => expire.fmt(f),
117 None => Ok(())
118 }
119 }
120}
121
122impl<Octs: Octets> Opt<Octs> {
125 pub fn expire(&self) -> Option<Expire> {
130 self.first()
131 }
132}
133
134impl<Target: Composer> OptBuilder<'_, Target> {
135 pub fn expire(
140 &mut self, expire: Option<u32>
141 ) -> Result<(), Target::AppendError> {
142 self.push(&Expire::new(expire))
143 }
144}
145
146
147#[cfg(test)]
150#[cfg(all(feature = "std", feature = "bytes"))]
151mod test {
152 use super::*;
153 use super::super::test::test_option_compose_parse;
154
155 #[test]
156 #[allow(clippy::redundant_closure)] fn expire_compose_parse() {
158 test_option_compose_parse(
159 &Expire::new(None),
160 |parser| Expire::parse(parser)
161 );
162 test_option_compose_parse(
163 &Expire::new(Some(12)),
164 |parser| Expire::parse(parser)
165 );
166 }
167}
168