use bytes::Bytes; use common_types::*; use failure::{ResultExt, Fail}; use ser::text::{DnsTextFormatter, next_field}; use ser::packet::remaining_bytes; use common_types::binary::HEXLOWER_PERMISSIVE_ALLOW_WS; use std::fmt; use errors::*; #[derive(Clone, PartialEq, Eq, Debug)] pub struct UnknownRecord { rr_type: Type, raw: Bytes, } impl UnknownRecord { pub fn new(rr_type: Type, raw: Bytes) -> Self { UnknownRecord { rr_type: rr_type, raw: raw, } } pub fn deserialize(rr_type: Type, data: &mut ::std::io::Cursor) -> Result { Ok(UnknownRecord::new(rr_type, remaining_bytes(data))) } pub fn dns_parse(rr_type: Type, data: &mut &str) -> Result { let field = next_field(data)?; ensure!(field == r"\#", "expect \\# token to mark generic encoding"); let field = next_field(data).context("generic record data length")?; let len: usize = field.parse()?; let result = HEXLOWER_PERMISSIVE_ALLOW_WS.decode(data.as_bytes()) .with_context(|e| e.context(format!("invalid hex: {:?}", data)))?; ensure!(len == result.len(), "length {} doesn't match length of encoded data {}", len, result.len()); Ok(UnknownRecord { rr_type, raw: result.into(), }) } pub fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { write!(f, "TYPE{} \\# {} {}", self.rr_type.0, self.raw.len(), HEXLOWER_PERMISSIVE_ALLOW_WS.encode(&self.raw)) } }