use bytes::Bytes; use errors::*; use failure::Fail; use ser::packet::{DnsPacketData, DnsPacketWriteContext}; use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field}; use std::fmt; use std::io::Cursor; /// Optional TTL /// /// Always present in wire format, but optional in zone; defaults to TTL /// of the RR. /// /// Must be followed by a field that doesn't accept any unsigned 32-bit /// integer as text representation (like `TimeStrict` for `SIG`). /// /// If field is missing in zone representation the context must provide /// a TTL. #[derive(Clone, PartialEq, Eq, Debug)] pub struct OptionalTTL(pub u32); impl DnsPacketData for OptionalTTL { fn deserialize(data: &mut Cursor) -> Result { Ok(OptionalTTL(DnsPacketData::deserialize(data)?)) } fn serialize(&self, context: &mut DnsPacketWriteContext, packet: &mut Vec) -> Result<()> { self.0.serialize(context, packet) } } impl DnsTextData for OptionalTTL { fn dns_parse(context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let mut data_found = *data; let field = next_field(&mut data_found)?; match field.parse::() { Ok(ttl) => { *data = data_found; Ok(OptionalTTL(ttl)) }, Err(e) => { Ok(OptionalTTL(context.last_ttl() .ok_or_else(|| e.context("TTL not available in context, failed parsing optional TTL"))? )) }, } } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { self.0.dns_format(f) } }