From 302300c184c8eea998ba229786796b39138715d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 26 Dec 2017 22:23:51 +0100 Subject: [PATCH] step --- lib/dnsbox-base/src/common_types/binary.rs | 6 +- lib/dnsbox-base/src/common_types/classes.rs | 6 +- .../src/common_types/name/name_text_parser.rs | 36 +++++---- lib/dnsbox-base/src/common_types/nsec.rs | 8 +- lib/dnsbox-base/src/common_types/nxt.rs | 6 +- lib/dnsbox-base/src/common_types/text.rs | 8 +- lib/dnsbox-base/src/common_types/time.rs | 4 +- lib/dnsbox-base/src/common_types/types.rs | 6 +- lib/dnsbox-base/src/common_types/uri.rs | 2 +- lib/dnsbox-base/src/records/tests.rs | 18 +++-- lib/dnsbox-base/src/records/weird_structs.rs | 12 +-- lib/dnsbox-base/src/ser/rrdata.rs | 12 +-- lib/dnsbox-base/src/ser/text/mod.rs | 75 ++++++++++++++++++- lib/dnsbox-base/src/ser/text/std_impls.rs | 15 ++-- lib/dnsbox-derive/src/dns_text_data.rs | 4 +- 15 files changed, 148 insertions(+), 70 deletions(-) diff --git a/lib/dnsbox-base/src/common_types/binary.rs b/lib/dnsbox-base/src/common_types/binary.rs index 37394a0..f9203af 100644 --- a/lib/dnsbox-base/src/common_types/binary.rs +++ b/lib/dnsbox-base/src/common_types/binary.rs @@ -40,7 +40,7 @@ impl DnsPacketData for HexShortBlob { } impl DnsTextData for HexShortBlob { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let s = next_field(data)?; if s == "-" { Ok(HexShortBlob(Bytes::new())) @@ -76,7 +76,7 @@ impl DnsPacketData for Base64RemainingBlob { } impl DnsTextData for Base64RemainingBlob { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { skip_whitespace(data); let result = BASE64_ALLOW_WS.decode(data.as_bytes()) .with_context(|e| e.context(format!("invalid base64: {:?}", data)))?; @@ -101,7 +101,7 @@ impl DnsPacketData for HexRemainingBlob { } impl DnsTextData for HexRemainingBlob { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { skip_whitespace(data); let result = HEXLOWER_PERMISSIVE_ALLOW_WS.decode(data.as_bytes()) .with_context(|e| e.context(format!("invalid hex: {:?}", data)))?; diff --git a/lib/dnsbox-base/src/common_types/classes.rs b/lib/dnsbox-base/src/common_types/classes.rs index 3daa2f2..4200d65 100644 --- a/lib/dnsbox-base/src/common_types/classes.rs +++ b/lib/dnsbox-base/src/common_types/classes.rs @@ -3,7 +3,7 @@ use bytes::Bytes; use errors::*; use ser::DnsPacketData; -use ser::text::{DnsTextData, DnsTextFormatter, next_field}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field}; use std::fmt; use std::io::Cursor; use std::borrow::Cow; @@ -153,7 +153,7 @@ impl Class { /// parses generic names of the form "CLASS..." pub fn from_generic_name(name: &str) -> Option { use std::ascii::AsciiExt; - if name.as_bytes()[0..5].eq_ignore_ascii_case(b"CLASS") { + if name.len() > 5 && name.as_bytes()[0..5].eq_ignore_ascii_case(b"CLASS") { name[5..].parse::().ok().map(Class) } else { None @@ -204,7 +204,7 @@ impl DnsPacketData for Class { } impl DnsTextData for Class { - fn dns_parse(data: &mut &str) -> Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> Result { let field = next_field(data)?; Class::from_name(field).ok_or_else(|| format_err!("unknown CLASS {:?}", field)) } diff --git a/lib/dnsbox-base/src/common_types/name/name_text_parser.rs b/lib/dnsbox-base/src/common_types/name/name_text_parser.rs index 99b7b61..9e3ab0d 100644 --- a/lib/dnsbox-base/src/common_types/name/name_text_parser.rs +++ b/lib/dnsbox-base/src/common_types/name/name_text_parser.rs @@ -1,19 +1,19 @@ use super::*; -use ser::text::{DnsTextData, DnsTextFormatter, next_field, quoted}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field, quoted}; impl DnsName { /// Parse text representation of a domain name - pub fn parse<'a, O>(value: &str, origin: O) -> ::errors::Result - where - O: IntoIterator> + pub fn parse(context: &DnsTextContext, value: &str) -> Result { let raw = value.as_bytes(); let mut name = DnsName::new_root(); if raw == b"." { return Ok(name); } else if raw == b"@" { - for l in origin.into_iter() { name.push_back(l)?; } - return Ok(name); + match context.origin() { + Some(o) => return Ok(o.clone()), + None => bail!("@ invalid without $ORIGIN"), + } } ensure!(!raw.is_empty(), "invalid empty name"); let mut label = Vec::new(); @@ -48,8 +48,16 @@ impl DnsName { if !label.is_empty() { // no trailing dot, relative name + + // push last label name.push_back(DnsLabelRef::new(&label)?)?; - for l in origin.into_iter() { name.push_back(l)?; } + + match context.origin() { + Some(o) => { + for l in o { name.push_back(l)?; } + }, + None => bail!("missing trailing dot without $ORIGIN"), + } } Ok(name) @@ -57,9 +65,9 @@ impl DnsName { } impl DnsTextData for DnsName { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(context: &DnsTextContext, data: &mut &str) -> Result { let field = next_field(data)?; - DnsName::parse(field, &DnsName::new_root()) + DnsName::parse(context, field) } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { @@ -69,18 +77,16 @@ impl DnsTextData for DnsName { impl DnsCompressedName { /// Parse text representation of a domain name - pub fn parse<'a, O>(value: &str, origin: O) -> ::errors::Result - where - O: IntoIterator> + pub fn parse(context: &DnsTextContext, value: &str) -> Result { - Ok(DnsCompressedName(DnsName::parse(value, origin)?)) + Ok(DnsCompressedName(DnsName::parse(context, value)?)) } } impl DnsTextData for DnsCompressedName { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(context: &DnsTextContext, data: &mut &str) -> Result { let field = next_field(data)?; - DnsCompressedName::parse(field, &DnsName::new_root()) + DnsCompressedName::parse(context, field) } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { diff --git a/lib/dnsbox-base/src/common_types/nsec.rs b/lib/dnsbox-base/src/common_types/nsec.rs index 4f922b4..72f8d47 100644 --- a/lib/dnsbox-base/src/common_types/nsec.rs +++ b/lib/dnsbox-base/src/common_types/nsec.rs @@ -4,7 +4,7 @@ use data_encoding; use errors::*; use failure::{Fail, ResultExt}; use ser::packet::{DnsPacketData, remaining_bytes, short_blob}; -use ser::text::{DnsTextData, DnsTextFormatter, skip_whitespace, next_field}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, skip_whitespace, next_field}; use std::collections::BTreeSet; use std::fmt; use std::io::Cursor; @@ -103,11 +103,11 @@ impl DnsPacketData for NsecTypeBitmap { } impl DnsTextData for NsecTypeBitmap { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let mut set = BTreeSet::new(); skip_whitespace(data); while !data.is_empty() { - let t = Type::dns_parse(data)?; + let t = Type::dns_parse(context, data)?; set.insert(t); } Ok(NsecTypeBitmap::from_set(set)) @@ -137,7 +137,7 @@ impl DnsPacketData for NextHashedOwnerName { } impl DnsTextData for NextHashedOwnerName { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let field = next_field(data)?; let raw = BASE32HEX_NOPAD_ALLOW_WS.decode(field.as_bytes()) .with_context(|e| e.context(format!("invalid base32hex (no padding): {:?}", field)))?; diff --git a/lib/dnsbox-base/src/common_types/nxt.rs b/lib/dnsbox-base/src/common_types/nxt.rs index b148dae..1b86ecf 100644 --- a/lib/dnsbox-base/src/common_types/nxt.rs +++ b/lib/dnsbox-base/src/common_types/nxt.rs @@ -2,7 +2,7 @@ use bytes::{Bytes, Buf}; use common_types::Type; use errors::*; use ser::packet::{DnsPacketData, remaining_bytes}; -use ser::text::{DnsTextData, DnsTextFormatter, skip_whitespace}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, skip_whitespace}; use std::collections::BTreeSet; use std::fmt; use std::io::Cursor; @@ -75,11 +75,11 @@ impl DnsPacketData for NxtTypeBitmap { } impl DnsTextData for NxtTypeBitmap { - fn dns_parse(data: &mut &str) -> Result { + fn dns_parse(context: &DnsTextContext, data: &mut &str) -> Result { let mut set = BTreeSet::new(); skip_whitespace(data); while !data.is_empty() { - let t = Type::dns_parse(data)?; + let t = Type::dns_parse(context, data)?; set.insert(t); } NxtTypeBitmap::from_set(set) diff --git a/lib/dnsbox-base/src/common_types/text.rs b/lib/dnsbox-base/src/common_types/text.rs index 3d4f394..5642ba8 100644 --- a/lib/dnsbox-base/src/common_types/text.rs +++ b/lib/dnsbox-base/src/common_types/text.rs @@ -16,7 +16,7 @@ impl DnsPacketData for ShortText { } impl DnsTextData for ShortText { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let raw = next_quoted_field(data)?; ensure!(raw.len() < 256, "short text must be at most 255 bytes long"); Ok(ShortText(raw.into())) @@ -46,7 +46,7 @@ impl DnsPacketData for LongText { } impl DnsTextData for LongText { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let mut result = Vec::new(); // `next_quoted_field` should skip trailing whitespace, we only // need to skip the beginning whitespace for the first @@ -80,7 +80,7 @@ impl DnsPacketData for UnquotedShortText { } impl DnsTextData for UnquotedShortText { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let raw = next_quoted_field(data)?; ensure!(raw.len() < 256, "short text must be at most 255 bytes long"); Ok(UnquotedShortText(raw.into())) @@ -105,7 +105,7 @@ impl DnsPacketData for RemainingText { } impl DnsTextData for RemainingText { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { Ok(RemainingText(next_quoted_field(data)?.into())) } diff --git a/lib/dnsbox-base/src/common_types/time.rs b/lib/dnsbox-base/src/common_types/time.rs index 2ed8962..5deaed0 100644 --- a/lib/dnsbox-base/src/common_types/time.rs +++ b/lib/dnsbox-base/src/common_types/time.rs @@ -1,7 +1,7 @@ use bytes::Bytes; use errors::*; use ser::packet::DnsPacketData; -use ser::text::{DnsTextData, DnsTextFormatter, next_field}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field}; use std::fmt; use std::io::Cursor; @@ -18,7 +18,7 @@ impl DnsPacketData for Time { } impl DnsTextData for Time { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let field = next_field(data)?; let epoch = field.parse::(); if field.len() == 14 && epoch.is_err() { diff --git a/lib/dnsbox-base/src/common_types/types.rs b/lib/dnsbox-base/src/common_types/types.rs index 1c30862..3ca06a4 100644 --- a/lib/dnsbox-base/src/common_types/types.rs +++ b/lib/dnsbox-base/src/common_types/types.rs @@ -4,7 +4,7 @@ use bytes::Bytes; use errors::*; use records::registry::{lookup_type_to_name, lookup_type_name}; use ser::DnsPacketData; -use ser::text::{DnsTextData, DnsTextFormatter, next_field}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field}; use std::borrow::Cow; use std::fmt; use std::io::Cursor; @@ -475,7 +475,7 @@ impl Type { /// parses generic names of the form "TYPE..." pub fn from_generic_name(name: &str) -> Option { use std::ascii::AsciiExt; - if name.as_bytes()[0..4].eq_ignore_ascii_case(b"TYPE") { + if name.len() > 4 && name.as_bytes()[0..4].eq_ignore_ascii_case(b"TYPE") { name[4..].parse::().ok().map(Type) } else { None @@ -576,7 +576,7 @@ impl DnsPacketData for Type { } impl DnsTextData for Type { - fn dns_parse(data: &mut &str) -> Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> Result { let field = next_field(data)?; Type::from_name(field).ok_or_else(|| format_err!("unknown TYPE {:?}", field)) } diff --git a/lib/dnsbox-base/src/common_types/uri.rs b/lib/dnsbox-base/src/common_types/uri.rs index 1ab94f8..993f7aa 100644 --- a/lib/dnsbox-base/src/common_types/uri.rs +++ b/lib/dnsbox-base/src/common_types/uri.rs @@ -24,7 +24,7 @@ impl DnsPacketData for UriText { } impl DnsTextData for UriText { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { let raw = next_quoted_field(data)?; ensure!(!raw.is_empty(), "URI must not be empty"); Ok(UriText(raw.into())) diff --git a/lib/dnsbox-base/src/records/tests.rs b/lib/dnsbox-base/src/records/tests.rs index 34e126f..47f39df 100644 --- a/lib/dnsbox-base/src/records/tests.rs +++ b/lib/dnsbox-base/src/records/tests.rs @@ -20,11 +20,13 @@ fn rrdata_parse(data: &str) -> ::errors::Result where T: StaticRRData { - let mut data = data; - let result = T::dns_parse_rr_data(3600, classes::IN, T::TYPE, &mut data)?; - let data = data.trim(); - ensure!(data.is_empty(), "didn't parse complete rrdata text, remaining: {:?}", data); - Ok(result) + let mut ctx = text::DnsTextContext::new(); + ctx.set_zone_class(classes::IN); + ctx.set_record_type(T::TYPE); + ctx.set_last_ttl(3600); + text::parse_with(data, |data| { + T::dns_parse_rr_data(&ctx, data) + }) } fn check(txt: &str, data: &'static [u8]) -> ::errors::Result<()> @@ -109,8 +111,8 @@ fn test_nsec3() { check::("1 2 300 ab vs A NS", b"\x01\x02\x01\x2c\x01\xab\x01\xff\x00\x01\x60").unwrap(); // invalid base32 texts - text::parse::("1 2 300 - v").unwrap_err(); - text::parse::("1 2 300 - vv").unwrap_err(); + rrdata_parse::("1 2 300 - v").unwrap_err(); + rrdata_parse::("1 2 300 - vv").unwrap_err(); // invalid (empty) next-hashed values packet::deserialize::(Bytes::from_static(b"\x01\x02\x01\x2c\x00\x00")).unwrap_err(); @@ -121,7 +123,7 @@ fn test_nsec3param() { check::("1 2 300 -", b"\x01\x02\x01\x2c\x00").unwrap(); check::("1 2 300 ab", b"\x01\x02\x01\x2c\x01\xab").unwrap(); // `salt` hex string must not contain spaces - text::parse::("1 2 300 a b").unwrap_err(); + rrdata_parse::("1 2 300 a b").unwrap_err(); } #[test] diff --git a/lib/dnsbox-base/src/records/weird_structs.rs b/lib/dnsbox-base/src/records/weird_structs.rs index 4ab8a69..fdb288d 100644 --- a/lib/dnsbox-base/src/records/weird_structs.rs +++ b/lib/dnsbox-base/src/records/weird_structs.rs @@ -2,7 +2,7 @@ use bytes::{Bytes, Buf}; use common_types::*; use failure::ResultExt; use ser::DnsPacketData; -use ser::text::{DnsTextData, DnsTextFormatter}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext}; use std::fmt; use std::io::Read; use std::net::Ipv6Addr; @@ -36,7 +36,7 @@ impl DnsPacketData for LOC { } impl DnsTextData for LOC { - fn dns_parse(_data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, _data: &mut &str) -> ::errors::Result { unimplemented!() } @@ -101,15 +101,15 @@ impl DnsPacketData for A6 { } impl DnsTextData for A6 { - fn dns_parse(data: &mut &str) -> ::errors::Result { - let prefix: u8 = DnsTextData::dns_parse(data) + fn dns_parse(context: &DnsTextContext, data: &mut &str) -> ::errors::Result { + let prefix: u8 = DnsTextData::dns_parse(context, data) .context("failed parsing field A6::prefix")?; ensure!(prefix <= 128, "invalid A6::prefix {}", prefix); let suffix_offset = (prefix / 8) as usize; debug_assert!(suffix_offset <= 16); - let suffix: Ipv6Addr = DnsTextData::dns_parse(data) + let suffix: Ipv6Addr = DnsTextData::dns_parse(context, data) .context("failed parsing field A6::suffix")?; // clear prefix bits @@ -124,7 +124,7 @@ impl DnsTextData for A6 { let suffix = Ipv6Addr::from(suffix); let prefix_name = if !data.is_empty() { - Some(DnsTextData::dns_parse(data) + Some(DnsTextData::dns_parse(context, data) .context("failed parsing field A6::prefix_name")?) } else { None diff --git a/lib/dnsbox-base/src/ser/rrdata.rs b/lib/dnsbox-base/src/ser/rrdata.rs index 80aed9b..2081f9e 100644 --- a/lib/dnsbox-base/src/ser/rrdata.rs +++ b/lib/dnsbox-base/src/ser/rrdata.rs @@ -2,7 +2,7 @@ use bytes::Bytes; use common_types::{Class, Type, classes}; use errors::*; use ser::DnsPacketData; -use ser::text::{DnsTextData, DnsTextFormatter}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext}; use std::borrow::Cow; use std::fmt; use std::io::Cursor; @@ -31,7 +31,7 @@ impl RRDataPacket for T { } pub trait RRDataText { - fn dns_parse_rr_data(ttl: u32, rr_class: Class, rr_type: Type, data: &mut &str) -> Result + fn dns_parse_rr_data(context: &DnsTextContext, data: &mut &str) -> Result where Self: Sized, ; @@ -59,15 +59,17 @@ pub trait RRDataText { } impl RRDataText for T { - fn dns_parse_rr_data(_ttl: u32, rr_class: Class, rr_type: Type, data: &mut &str) -> Result + fn dns_parse_rr_data(context: &DnsTextContext, data: &mut &str) -> Result where Self: Sized, { - ensure!(rr_type == T::TYPE, "type mismatch"); + ensure!(context.record_type() == Some(T::TYPE), "type mismatch"); + let rr_class = context.zone_class().expect("require zone CLASS to parse record"); if T::CLASS != classes::ANY { ensure!(rr_class == T::CLASS, "class mismatch: got {}, need {}", rr_class, T::CLASS); } - T::dns_parse(data) + ensure!(context.last_ttl().is_some(), "require TTL to parse record"); + T::dns_parse(context, data) } fn dns_format_rr_data(&self, f: &mut DnsTextFormatter) -> fmt::Result { diff --git a/lib/dnsbox-base/src/ser/text/mod.rs b/lib/dnsbox-base/src/ser/text/mod.rs index 692c6f5..385107c 100644 --- a/lib/dnsbox-base/src/ser/text/mod.rs +++ b/lib/dnsbox-base/src/ser/text/mod.rs @@ -1,3 +1,4 @@ +use common_types; use std::fmt; mod std_impls; @@ -94,8 +95,74 @@ impl<'a, 'b> DnsTextFormatter<'a, 'b> { } } +#[derive(Clone, Debug, Default)] +pub struct DnsTextContext { + zone_class: Option, + origin: Option, + record_type: Option, + last_ttl: Option, +} + +impl DnsTextContext { + pub fn new() -> Self { + Self::default() + } + + pub fn zone_class(&self) -> Option { + self.zone_class + } + + pub fn set_zone_class(&mut self, zone_class: common_types::Class) -> &mut Self { + self.zone_class = Some(zone_class); + self + } + + pub fn unset_zone_class(&mut self) -> &mut Self { + self + } + + pub fn origin(&self) -> Option<&common_types::DnsName> { + self.origin.as_ref() + } + + pub fn set_origin(&mut self, origin: common_types::DnsName) -> &mut Self { + self.origin = Some(origin); + self + } + + pub fn unset_origin(&mut self) -> &mut Self { + self + } + + pub fn record_type(&self) -> Option { + self.record_type + } + + pub fn set_record_type(&mut self, record_type: common_types::Type) -> &mut Self { + self.record_type = Some(record_type); + self + } + + pub fn unset_record_type(&mut self) -> &mut Self { + self + } + + pub fn last_ttl(&self) -> Option { + self.last_ttl + } + + pub fn set_last_ttl(&mut self, last_ttl: u32) -> &mut Self { + self.last_ttl = Some(last_ttl); + self + } + + pub fn unset_last_ttl(&mut self) -> &mut Self { + self + } +} + pub trait DnsTextData { - fn dns_parse(data: &mut &str) -> ::errors::Result + fn dns_parse(context: &DnsTextContext, data: &mut &str) -> ::errors::Result where Self: Sized, ; @@ -103,12 +170,12 @@ pub trait DnsTextData { fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result; } -pub fn parse(data: &str) -> ::errors::Result +pub fn parse_with<'a, F, O>(data: &'a str, parser: F) -> ::errors::Result where - T: DnsTextData + for<'b> F: FnOnce(&'b mut &'a str) -> ::errors::Result, { let mut data = data; - let result = T::dns_parse(&mut data)?; + let result = parser(&mut data)?; let data = data.trim(); ensure!(data.is_empty(), "didn't parse complete text, remaining: {:?}", data); Ok(result) diff --git a/lib/dnsbox-base/src/ser/text/std_impls.rs b/lib/dnsbox-base/src/ser/text/std_impls.rs index 859fb5c..a31e7ca 100644 --- a/lib/dnsbox-base/src/ser/text/std_impls.rs +++ b/lib/dnsbox-base/src/ser/text/std_impls.rs @@ -1,10 +1,10 @@ use std::fmt; use std::net::{Ipv4Addr, Ipv6Addr}; -use ser::text::{DnsTextData, DnsTextFormatter, next_field}; +use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field}; /* only decimal representations are used for numbers */ impl DnsTextData for u8 { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { Ok(next_field(data)?.parse()?) } @@ -14,7 +14,7 @@ impl DnsTextData for u8 { } impl DnsTextData for u16 { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { Ok(next_field(data)?.parse()?) } @@ -24,7 +24,7 @@ impl DnsTextData for u16 { } impl DnsTextData for u32 { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { Ok(next_field(data)?.parse()?) } @@ -35,7 +35,7 @@ impl DnsTextData for u32 { /* only decimal representations are needed for octets */ impl DnsTextData for Ipv4Addr { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { Ok(next_field(data)?.parse()?) } @@ -46,7 +46,7 @@ impl DnsTextData for Ipv4Addr { /* representation as in RFC 3513: https://tools.ietf.org/html/rfc3513#section-2.2 */ impl DnsTextData for Ipv6Addr { - fn dns_parse(data: &mut &str) -> ::errors::Result { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result { Ok(next_field(data)?.parse()?) } @@ -60,8 +60,9 @@ mod tests { use super::*; fn deserialize(data: &str) -> ::errors::Result { + let context = DnsTextContext::new(); let mut data = data; - let res = T::dns_parse(&mut data)?; + let res = T::dns_parse(&context, &mut data)?; let data = data.trim(); ensure!(data.is_empty(), "didn't read data completely"); Ok(res) diff --git a/lib/dnsbox-derive/src/dns_text_data.rs b/lib/dnsbox-derive/src/dns_text_data.rs index 8a351a7..8212757 100644 --- a/lib/dnsbox-derive/src/dns_text_data.rs +++ b/lib/dnsbox-derive/src/dns_text_data.rs @@ -28,7 +28,7 @@ pub fn build(ast: &syn::DeriveInput) -> quote::Tokens { let field_name = field.ident.as_ref().unwrap(); parse_fields = quote!{#parse_fields - #field_name: DnsTextData::dns_parse(_data).with_context(|_| format!("failed parsing field {}::{}", stringify!(#name), stringify!(#field_name)))?, + #field_name: DnsTextData::dns_parse(_context, _data).with_context(|_| format!("failed parsing field {}::{}", stringify!(#name), stringify!(#field_name)))?, }; format_fields = quote!{#format_fields @@ -39,7 +39,7 @@ pub fn build(ast: &syn::DeriveInput) -> quote::Tokens { quote!{ #[allow(unused_imports)] impl ::dnsbox_base::ser::DnsTextData for #name { - fn dns_parse(_data: &mut &str) -> ::dnsbox_base::errors::Result { + fn dns_parse(_context: &::dnsbox_base::ser::text::DnsTextContext, _data: &mut &str) -> ::dnsbox_base::errors::Result { use dnsbox_base::failure::ResultExt; use dnsbox_base::ser::DnsTextData; Ok(#name{ #parse_fields })