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