use std::fmt; use std::net::{Ipv4Addr, Ipv6Addr}; use crate::ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field}; impl DnsTextData for () { fn dns_parse(_context: &DnsTextContext, _data: &mut &str) -> crate::errors::Result { Ok(()) } fn dns_format(&self, _f: &mut DnsTextFormatter) -> fmt::Result { Ok(()) } } impl DnsTextData for std::marker::PhantomData { fn dns_parse(_context: &DnsTextContext, _data: &mut &str) -> crate::errors::Result { Ok(std::marker::PhantomData) } fn dns_format(&self, _f: &mut DnsTextFormatter) -> fmt::Result { Ok(()) } } /* only decimal representations are used for numbers */ impl DnsTextData for u8 { fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> crate::errors::Result { Ok(next_field(data)?.parse()?) } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { write!(f, "{}", self) } } impl DnsTextData for u16 { fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> crate::errors::Result { Ok(next_field(data)?.parse()?) } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { write!(f, "{}", self) } } impl DnsTextData for u32 { fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> crate::errors::Result { Ok(next_field(data)?.parse()?) } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { write!(f, "{}", self) } } /* only decimal representations are needed for octets */ impl DnsTextData for Ipv4Addr { fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> crate::errors::Result { Ok(next_field(data)?.parse()?) } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { write!(f, "{}", self) } } /* representation as in RFC 3513: https://tools.ietf.org/html/rfc3513#section-2.2 */ impl DnsTextData for Ipv6Addr { fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> crate::errors::Result { Ok(next_field(data)?.parse()?) } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { write!(f, "{}", self) } } #[cfg(test)] mod tests { use super::*; fn deserialize(data: &str) -> crate::errors::Result { let context = DnsTextContext::new(); let mut data = data; let res = T::dns_parse(&context, &mut data)?; let data = data.trim(); failure::ensure!(data.is_empty(), "didn't read data completely"); Ok(res) } #[test] fn test_ipv6() { assert_eq!( deserialize::("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210").unwrap(), Ipv6Addr::new( 0xfedc, 0xba98, 0x7654, 0x3210, 0xfedc, 0xba98, 0x7654, 0x3210 ) ); assert_eq!( deserialize::("1080::8:800:200C:417A").unwrap(), Ipv6Addr::new( 0x1080, 0, 0, 0, 0x8, 0x800, 0x200c, 0x417a ) ); assert_eq!( deserialize::("::13.1.68.3").unwrap(), Ipv6Addr::new( 0, 0, 0, 0, 0, 0, 0x0d01, 0x4403 ) ); assert_eq!( deserialize::("::FFFF:129.144.52.38").unwrap(), Ipv6Addr::new( 0, 0, 0, 0, 0, 0xffff, 0x8190, 0x3426 ) ); } #[derive(DnsTextData, PartialEq, Eq, Debug)] struct Unit; #[test] fn test_unit() { assert_eq!(deserialize::("").unwrap(), Unit); } #[derive(DnsTextData, PartialEq, Eq, Debug)] struct Tuple(u16); #[test] fn test_tuple() { assert_eq!(deserialize::("1234").unwrap(), Tuple(1234)); } }