allow non-FQDN in prep for search domains
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -2,6 +2,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## 0.11.0
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `Name::FromStr` for simpler parsing, specify trailing `.` for FQDN
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- *breaking* All `ClientHandle` traits now take `&Handle` instead of `Handle` (@rushmorem)
|
||||||
|
- *warning* `Name` now tracks if it is a fully qualified domain name, slightly changes name parsing rules, allowing `www.example.com` without the trailing `.`, which means that FQDN names are not enforced.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- deprecated `Name::with_labels` see `Name::from_labels`
|
||||||
|
|
||||||
## 0.10.5
|
## 0.10.5
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@@ -33,18 +33,24 @@ use error::*;
|
|||||||
/// TODO: Currently this probably doesn't support binary names, it would be nice to do that.
|
/// TODO: Currently this probably doesn't support binary names, it would be nice to do that.
|
||||||
#[derive(Debug, Eq, Clone)]
|
#[derive(Debug, Eq, Clone)]
|
||||||
pub struct Name {
|
pub struct Name {
|
||||||
|
is_fqdn: bool,
|
||||||
labels: Rc<Vec<Rc<String>>>,
|
labels: Rc<Vec<Rc<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Name {
|
impl Name {
|
||||||
/// Create a new domain::Name, i.e. label
|
/// Create a new domain::Name, i.e. label
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Name { labels: Rc::new(Vec::new()) }
|
Name {
|
||||||
|
is_fqdn: false,
|
||||||
|
labels: Rc::new(Vec::new()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the root label, i.e. no labels, can probably make this better in the future.
|
/// Returns the root label, i.e. no labels, can probably make this better in the future.
|
||||||
pub fn root() -> Self {
|
pub fn root() -> Self {
|
||||||
Self::new()
|
let mut this = Self::new();
|
||||||
|
this.is_fqdn = true;
|
||||||
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if there are no labels, i.e. it's empty.
|
/// Returns true if there are no labels, i.e. it's empty.
|
||||||
@@ -63,6 +69,32 @@ impl Name {
|
|||||||
self.labels.is_empty()
|
self.labels.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the name is a fully qualified domain name.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::str::FromStr;
|
||||||
|
/// use trust_dns::rr::domain::Name;
|
||||||
|
///
|
||||||
|
/// let name = Name::from_str("www").unwrap();
|
||||||
|
/// assert!(!name.is_fqdn());
|
||||||
|
///
|
||||||
|
/// let name = Name::from_str("www.example.com").unwrap();
|
||||||
|
/// assert!(!name.is_fqdn());
|
||||||
|
///
|
||||||
|
/// let name = Name::from_str("www.example.com.").unwrap();
|
||||||
|
/// assert!(name.is_fqdn());
|
||||||
|
/// ```
|
||||||
|
pub fn is_fqdn(&self) -> bool {
|
||||||
|
self.is_fqdn
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specifies this name is a fully qualified domain name
|
||||||
|
pub fn set_fqdn(&mut self, val: bool) {
|
||||||
|
self.is_fqdn = val
|
||||||
|
}
|
||||||
|
|
||||||
/// inline builder
|
/// inline builder
|
||||||
pub fn label(mut self, label: &'static str) -> Self {
|
pub fn label(mut self, label: &'static str) -> Self {
|
||||||
// TODO get_mut() on Arc was unstable when this was written
|
// TODO get_mut() on Arc was unstable when this was written
|
||||||
@@ -86,14 +118,17 @@ impl Name {
|
|||||||
/// use trust_dns::rr::domain::Name;
|
/// use trust_dns::rr::domain::Name;
|
||||||
///
|
///
|
||||||
/// let from_labels = Name::from_labels(vec!["www", "example", "com"]);
|
/// let from_labels = Name::from_labels(vec!["www", "example", "com"]);
|
||||||
/// assert_eq!(from_labels, Name::from_str("www.example.com.").unwrap());
|
/// assert_eq!(from_labels, Name::from_str("www.example.com").unwrap());
|
||||||
///
|
///
|
||||||
/// let root = Name::from_labels::<String>(vec![]);
|
/// let root = Name::from_labels::<String>(vec![]);
|
||||||
/// assert!(root.is_root());
|
/// assert!(root.is_root());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_labels<S: Into<String>>(labels: Vec<S>) -> Self {
|
pub fn from_labels<S: Into<String>>(labels: Vec<S>) -> Self {
|
||||||
assert!(labels.len() < 256); // this should be an error
|
assert!(labels.len() < 256); // this should be an error
|
||||||
Name { labels: Rc::new(labels.into_iter().map(|s| Rc::new(s.into())).collect()) }
|
Name {
|
||||||
|
is_fqdn: false,
|
||||||
|
labels: Rc::new(labels.into_iter().map(|s| Rc::new(s.into())).collect()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated in favor of `from_labels`
|
/// Deprecated in favor of `from_labels`
|
||||||
@@ -112,7 +147,10 @@ impl Name {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert!(new_labels.len() < 256); // this should be an error
|
assert!(new_labels.len() < 256); // this should be an error
|
||||||
Name { labels: Rc::new(new_labels) }
|
Name {
|
||||||
|
is_fqdn: self.is_fqdn,
|
||||||
|
labels: Rc::new(new_labels),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// appends the String to this label at the end
|
/// appends the String to this label at the end
|
||||||
@@ -145,13 +183,15 @@ impl Name {
|
|||||||
/// let example_com = Name::new().label("Example").label("Com");
|
/// let example_com = Name::new().label("Example").label("Com");
|
||||||
/// assert_eq!(example_com.to_lowercase().cmp_with_case(&Name::new().label("example").label("com"), false), Ordering::Equal);
|
/// assert_eq!(example_com.to_lowercase().cmp_with_case(&Name::new().label("example").label("com"), false), Ordering::Equal);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn to_lowercase(&self) -> Name {
|
pub fn to_lowercase(&self) -> Self {
|
||||||
let mut new_labels = Vec::with_capacity(self.labels.len());
|
let mut new_labels = Vec::with_capacity(self.labels.len());
|
||||||
for label in self.labels.iter() {
|
for label in self.labels.iter() {
|
||||||
new_labels.push(label.to_lowercase());
|
new_labels.push(label.to_lowercase());
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::from_labels(new_labels)
|
let mut this = Self::from_labels(new_labels);
|
||||||
|
this.is_fqdn = self.is_fqdn;
|
||||||
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trims off the first part of the name, to help with searching for the domain piece
|
/// Trims off the first part of the name, to help with searching for the domain piece
|
||||||
@@ -190,7 +230,10 @@ impl Name {
|
|||||||
pub fn trim_to(&self, num_labels: usize) -> Name {
|
pub fn trim_to(&self, num_labels: usize) -> Name {
|
||||||
if self.labels.len() >= num_labels {
|
if self.labels.len() >= num_labels {
|
||||||
let trim = self.labels.len() - num_labels;
|
let trim = self.labels.len() - num_labels;
|
||||||
Name { labels: Rc::new(self.labels[trim..].to_vec()) }
|
Name {
|
||||||
|
is_fqdn: self.is_fqdn,
|
||||||
|
labels: Rc::new(self.labels[trim..].to_vec()),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Self::root()
|
Self::root()
|
||||||
}
|
}
|
||||||
@@ -282,6 +325,7 @@ impl Name {
|
|||||||
|
|
||||||
// short cirtuit root parse
|
// short cirtuit root parse
|
||||||
if local == "." {
|
if local == "." {
|
||||||
|
name.set_fqdn(true);
|
||||||
return Ok(name);
|
return Ok(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,10 +407,14 @@ impl Name {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if !local.ends_with('.') {
|
// FIXME: mark as FQDN or not_FQDN
|
||||||
name.append(try!(origin.ok_or(ParseError::from(
|
if local.ends_with('.') {
|
||||||
ParseErrorKind::Message("$ORIGIN was not specified"),
|
name.set_fqdn(true);
|
||||||
))));
|
} else {
|
||||||
|
if let Some(other) = origin {
|
||||||
|
name.append(other);
|
||||||
|
name.set_fqdn(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(name)
|
Ok(name)
|
||||||
@@ -628,7 +676,10 @@ impl BinSerializable<Name> for Name {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Name { labels: Rc::new(labels) })
|
Ok(Name {
|
||||||
|
is_fqdn: true,
|
||||||
|
labels: Rc::new(labels),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit(&self, encoder: &mut BinEncoder) -> EncodeResult {
|
fn emit(&self, encoder: &mut BinEncoder) -> EncodeResult {
|
||||||
@@ -738,7 +789,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn num_labels() {
|
fn test_num_labels() {
|
||||||
assert_eq!(Name::new().label("*").num_labels(), 0);
|
assert_eq!(Name::new().label("*").num_labels(), 0);
|
||||||
assert_eq!(Name::new().label("a").num_labels(), 1);
|
assert_eq!(Name::new().label("a").num_labels(), 1);
|
||||||
assert_eq!(Name::new().label("*").label("b").num_labels(), 1);
|
assert_eq!(Name::new().label("*").label("b").num_labels(), 1);
|
||||||
@@ -748,12 +799,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse() {
|
fn test_read() {
|
||||||
test_read_data_set(get_data(), |ref mut d| Name::read(d));
|
test_read_data_set(get_data(), |ref mut d| Name::read(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn write_to() {
|
fn test_write_to() {
|
||||||
test_emit_data_set(get_data(), |e, n| n.emit(e));
|
test_emit_data_set(get_data(), |e, n| n.emit(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -843,7 +894,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_partial_cmp_eq() {
|
fn test_partial_cmp_eq() {
|
||||||
let root = Some(Name::with_labels(vec![]));
|
let root = Some(Name::from_labels(Vec::<String>::new()));
|
||||||
let comparisons: Vec<(Name, Name)> = vec![
|
let comparisons: Vec<(Name, Name)> = vec![
|
||||||
(root.clone().unwrap(), root.clone().unwrap()),
|
(root.clone().unwrap(), root.clone().unwrap()),
|
||||||
(
|
(
|
||||||
@@ -860,7 +911,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_partial_cmp() {
|
fn test_partial_cmp() {
|
||||||
let root = Some(Name::with_labels(vec![]));
|
let root = Some(Name::from_labels(Vec::<String>::new()));
|
||||||
let comparisons: Vec<(Name, Name)> =
|
let comparisons: Vec<(Name, Name)> =
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
@@ -905,7 +956,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cmp_ignore_case() {
|
fn test_cmp_ignore_case() {
|
||||||
let root = Some(Name::with_labels(vec![]));
|
let root = Some(Name::from_labels(Vec::<String>::new()));
|
||||||
let comparisons: Vec<(Name, Name)> = vec![
|
let comparisons: Vec<(Name, Name)> = vec![
|
||||||
(
|
(
|
||||||
Name::parse("ExAmPle", root.as_ref()).unwrap(),
|
Name::parse("ExAmPle", root.as_ref()).unwrap(),
|
||||||
@@ -985,6 +1036,19 @@ mod tests {
|
|||||||
Name::from_str("www.example.com.").unwrap(),
|
Name::from_str("www.example.com.").unwrap(),
|
||||||
Name::from_labels(vec!["www", "example", "com"])
|
Name::from_labels(vec!["www", "example", "com"])
|
||||||
);
|
);
|
||||||
assert_eq!(Name::from_str(".").unwrap(), Name::with_labels(vec![]));
|
assert_eq!(Name::from_str(".").unwrap(), Name::from_labels(Vec::<String>::new()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fqdn() {
|
||||||
|
assert!(Name::root().is_fqdn());
|
||||||
|
assert!(Name::from_str(".").unwrap().is_fqdn());
|
||||||
|
assert!(Name::from_str("www.example.com.").unwrap().is_fqdn());
|
||||||
|
|
||||||
|
assert!(!Name::new().is_fqdn());
|
||||||
|
assert!(!Name::from_labels(vec!["www", "example", "com"]).is_fqdn());
|
||||||
|
assert!(!Name::from_str("www.example.com").unwrap().is_fqdn());
|
||||||
|
assert!(!Name::from_str("www.example").unwrap().is_fqdn());
|
||||||
|
assert!(!Name::from_str("www").unwrap().is_fqdn());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -659,10 +659,11 @@ pub enum RData {
|
|||||||
|
|
||||||
impl RData {
|
impl RData {
|
||||||
/// Parse the RData from a set of Tokens
|
/// Parse the RData from a set of Tokens
|
||||||
pub fn parse(record_type: RecordType,
|
pub fn parse(
|
||||||
tokens: &Vec<Token>,
|
record_type: RecordType,
|
||||||
origin: Option<&Name>)
|
tokens: &Vec<Token>,
|
||||||
-> ParseResult<Self> {
|
origin: Option<&Name>,
|
||||||
|
) -> ParseResult<Self> {
|
||||||
let rdata = match record_type {
|
let rdata = match record_type {
|
||||||
RecordType::A => RData::A(try!(rdata::a::parse(tokens))),
|
RecordType::A => RData::A(try!(rdata::a::parse(tokens))),
|
||||||
RecordType::AAAA => RData::AAAA(try!(rdata::aaaa::parse(tokens))),
|
RecordType::AAAA => RData::AAAA(try!(rdata::aaaa::parse(tokens))),
|
||||||
@@ -695,20 +696,20 @@ impl RData {
|
|||||||
let mut buf: Vec<u8> = Vec::new();
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
{
|
{
|
||||||
let mut encoder: BinEncoder = BinEncoder::new(&mut buf);
|
let mut encoder: BinEncoder = BinEncoder::new(&mut buf);
|
||||||
self.emit(&mut encoder)
|
self.emit(&mut encoder).unwrap_or_else(|_| {
|
||||||
.unwrap_or_else(|_| {
|
warn!("could not encode RDATA: {:?}", self);
|
||||||
warn!("could not encode RDATA: {:?}", self);
|
()
|
||||||
()
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the RData from the given Decoder
|
/// Read the RData from the given Decoder
|
||||||
pub fn read(decoder: &mut BinDecoder,
|
pub fn read(
|
||||||
record_type: RecordType,
|
decoder: &mut BinDecoder,
|
||||||
rdata_length: u16)
|
record_type: RecordType,
|
||||||
-> DecodeResult<Self> {
|
rdata_length: u16,
|
||||||
|
) -> DecodeResult<Self> {
|
||||||
let start_idx = decoder.index();
|
let start_idx = decoder.index();
|
||||||
|
|
||||||
let result = match record_type {
|
let result = match record_type {
|
||||||
@@ -802,8 +803,9 @@ impl RData {
|
|||||||
// we should have read rdata_length, but we did not
|
// we should have read rdata_length, but we did not
|
||||||
let read = decoder.index() - start_idx;
|
let read = decoder.index() - start_idx;
|
||||||
if read != rdata_length as usize {
|
if read != rdata_length as usize {
|
||||||
return Err(DecodeErrorKind::IncorrectRDataLengthRead(read, rdata_length as usize)
|
return Err(
|
||||||
.into());
|
DecodeErrorKind::IncorrectRDataLengthRead(read, rdata_length as usize).into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@@ -953,125 +955,263 @@ mod tests {
|
|||||||
use rr::rdata::{MX, SOA, SRV, TXT};
|
use rr::rdata::{MX, SOA, SRV, TXT};
|
||||||
|
|
||||||
fn get_data() -> Vec<(RData, Vec<u8>)> {
|
fn get_data() -> Vec<(RData, Vec<u8>)> {
|
||||||
vec![(RData::CNAME(Name::with_labels(vec!["www".to_string(),
|
vec![
|
||||||
"example".to_string(),
|
(
|
||||||
"com".to_string()])),
|
RData::CNAME(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
vec![3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
|
vec![
|
||||||
b'o', b'm', 0]),
|
3,
|
||||||
(RData::MX(MX::new(256, Name::with_labels(vec!["n".to_string()]))),
|
b'w',
|
||||||
vec![1, 0, 1, b'n', 0]),
|
b'w',
|
||||||
(RData::NS(Name::with_labels(vec!["www".to_string(),
|
b'w',
|
||||||
"example".to_string(),
|
7,
|
||||||
"com".to_string()])),
|
b'e',
|
||||||
vec![3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
|
b'x',
|
||||||
b'o', b'm', 0]),
|
b'a',
|
||||||
(RData::PTR(Name::with_labels(vec!["www".to_string(),
|
b'm',
|
||||||
"example".to_string(),
|
b'p',
|
||||||
"com".to_string()])),
|
b'l',
|
||||||
vec![3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
|
b'e',
|
||||||
b'o', b'm', 0]),
|
3,
|
||||||
(RData::SOA(SOA::new(Name::with_labels(vec!["www".to_string(),
|
b'c',
|
||||||
"example".to_string(),
|
b'o',
|
||||||
"com".to_string()]),
|
b'm',
|
||||||
Name::with_labels(vec!["xxx".to_string(),
|
0,
|
||||||
"example".to_string(),
|
]
|
||||||
"com".to_string()]),
|
),
|
||||||
u32::max_value(),
|
(
|
||||||
-1 as i32,
|
RData::MX(MX::new(256, Name::from_labels(vec!["n"]))),
|
||||||
-1 as i32,
|
vec![1, 0, 1, b'n', 0]
|
||||||
-1 as i32,
|
),
|
||||||
u32::max_value())),
|
(
|
||||||
vec![3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
|
RData::NS(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
b'o', b'm', 0, 3, b'x', b'x', b'x', 0xC0, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
vec![
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
3,
|
||||||
0xFF, 0xFF]),
|
b'w',
|
||||||
(RData::TXT(TXT::new(vec!["abcdef".to_string(),
|
b'w',
|
||||||
"ghi".to_string(),
|
b'w',
|
||||||
"".to_string(),
|
7,
|
||||||
"j".to_string()])),
|
b'e',
|
||||||
vec![6, b'a', b'b', b'c', b'd', b'e', b'f', 3, b'g', b'h', b'i', 0, 1, b'j']),
|
b'x',
|
||||||
(RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()), vec![0, 0, 0, 0]),
|
b'a',
|
||||||
(RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
|
b'm',
|
||||||
vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
b'p',
|
||||||
(RData::SRV(SRV::new(1,
|
b'l',
|
||||||
2,
|
b'e',
|
||||||
3,
|
3,
|
||||||
Name::with_labels(vec!["www".to_string(),
|
b'c',
|
||||||
"example".to_string(),
|
b'o',
|
||||||
"com".to_string()]))),
|
b'm',
|
||||||
vec![0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 3, b'w', b'w', b'w', 7, b'e', b'x', b'a',
|
0,
|
||||||
b'm', b'p', b'l', b'e', 3, b'c', b'o', b'm', 0])]
|
]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
RData::PTR(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
|
vec![
|
||||||
|
3,
|
||||||
|
b'w',
|
||||||
|
b'w',
|
||||||
|
b'w',
|
||||||
|
7,
|
||||||
|
b'e',
|
||||||
|
b'x',
|
||||||
|
b'a',
|
||||||
|
b'm',
|
||||||
|
b'p',
|
||||||
|
b'l',
|
||||||
|
b'e',
|
||||||
|
3,
|
||||||
|
b'c',
|
||||||
|
b'o',
|
||||||
|
b'm',
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
RData::SOA(SOA::new(
|
||||||
|
Name::from_labels(vec!["www", "example", "com"]),
|
||||||
|
Name::from_labels(vec!["xxx", "example", "com"]),
|
||||||
|
u32::max_value(),
|
||||||
|
-1 as i32,
|
||||||
|
-1 as i32,
|
||||||
|
-1 as i32,
|
||||||
|
u32::max_value(),
|
||||||
|
)),
|
||||||
|
vec![
|
||||||
|
3,
|
||||||
|
b'w',
|
||||||
|
b'w',
|
||||||
|
b'w',
|
||||||
|
7,
|
||||||
|
b'e',
|
||||||
|
b'x',
|
||||||
|
b'a',
|
||||||
|
b'm',
|
||||||
|
b'p',
|
||||||
|
b'l',
|
||||||
|
b'e',
|
||||||
|
3,
|
||||||
|
b'c',
|
||||||
|
b'o',
|
||||||
|
b'm',
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
b'x',
|
||||||
|
b'x',
|
||||||
|
b'x',
|
||||||
|
0xC0,
|
||||||
|
0x04,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
RData::TXT(TXT::new(vec![
|
||||||
|
"abcdef".to_string(),
|
||||||
|
"ghi".to_string(),
|
||||||
|
"".to_string(),
|
||||||
|
"j".to_string(),
|
||||||
|
])),
|
||||||
|
vec![
|
||||||
|
6,
|
||||||
|
b'a',
|
||||||
|
b'b',
|
||||||
|
b'c',
|
||||||
|
b'd',
|
||||||
|
b'e',
|
||||||
|
b'f',
|
||||||
|
3,
|
||||||
|
b'g',
|
||||||
|
b'h',
|
||||||
|
b'i',
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
b'j',
|
||||||
|
]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
|
||||||
|
vec![0, 0, 0, 0]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
|
||||||
|
vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
RData::SRV(SRV::new(
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
Name::from_labels(vec!["www", "example", "com"]),
|
||||||
|
)),
|
||||||
|
vec![
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x03,
|
||||||
|
3,
|
||||||
|
b'w',
|
||||||
|
b'w',
|
||||||
|
b'w',
|
||||||
|
7,
|
||||||
|
b'e',
|
||||||
|
b'x',
|
||||||
|
b'a',
|
||||||
|
b'm',
|
||||||
|
b'p',
|
||||||
|
b'l',
|
||||||
|
b'e',
|
||||||
|
3,
|
||||||
|
b'c',
|
||||||
|
b'o',
|
||||||
|
b'm',
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this test kinda sucks, shows the problem with not storing the binary parts
|
// TODO this test kinda sucks, shows the problem with not storing the binary parts
|
||||||
#[test]
|
#[test]
|
||||||
fn test_order() {
|
fn test_order() {
|
||||||
let ordered: Vec<RData> = vec![RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
|
let ordered: Vec<RData> =
|
||||||
RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
|
vec![
|
||||||
RData::SRV(SRV::new(1,
|
RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
|
||||||
2,
|
RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
|
||||||
3,
|
RData::SRV(SRV::new(
|
||||||
Name::with_labels(vec!["www".to_string(),
|
1,
|
||||||
"example".to_string(),
|
2,
|
||||||
"com".to_string()]))),
|
3,
|
||||||
RData::MX(MX::new(256, Name::with_labels(vec!["n".to_string()]))),
|
Name::from_labels(vec!["www", "example", "com"]),
|
||||||
RData::CNAME(Name::with_labels(vec!["www".to_string(),
|
)),
|
||||||
"example".to_string(),
|
RData::MX(MX::new(256, Name::from_labels(vec!["n"]))),
|
||||||
"com".to_string()])),
|
RData::CNAME(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
RData::PTR(Name::with_labels(vec!["www".to_string(),
|
RData::PTR(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
"example".to_string(),
|
RData::NS(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
"com".to_string()])),
|
RData::SOA(SOA::new(
|
||||||
RData::NS(Name::with_labels(vec!["www".to_string(),
|
Name::from_labels(vec!["www", "example", "com"]),
|
||||||
"example".to_string(),
|
Name::from_labels(vec!["xxx", "example", "com"]),
|
||||||
"com".to_string()])),
|
u32::max_value(),
|
||||||
RData::SOA(SOA::new(Name::with_labels(vec!["www".to_string(),
|
-1 as i32,
|
||||||
"example".to_string(),
|
-1 as i32,
|
||||||
"com".to_string()]),
|
-1 as i32,
|
||||||
Name::with_labels(vec!["xxx".to_string(),
|
u32::max_value(),
|
||||||
"example".to_string(),
|
)),
|
||||||
"com".to_string()]),
|
RData::TXT(TXT::new(vec![
|
||||||
u32::max_value(),
|
"abcdef".to_string(),
|
||||||
-1 as i32,
|
"ghi".to_string(),
|
||||||
-1 as i32,
|
"".to_string(),
|
||||||
-1 as i32,
|
"j".to_string(),
|
||||||
u32::max_value())),
|
])),
|
||||||
RData::TXT(TXT::new(vec!["abcdef".to_string(),
|
];
|
||||||
"ghi".to_string(),
|
let mut unordered = vec![
|
||||||
"".to_string(),
|
RData::CNAME(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
"j".to_string()]))];
|
RData::MX(MX::new(256, Name::from_labels(vec!["n"]))),
|
||||||
let mut unordered = vec![RData::CNAME(Name::with_labels(vec!["www".to_string(),
|
RData::PTR(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
"example".to_string(),
|
RData::NS(Name::from_labels(vec!["www", "example", "com"])),
|
||||||
"com".to_string()])),
|
RData::SOA(SOA::new(
|
||||||
RData::MX(MX::new(256, Name::with_labels(vec!["n".to_string()]))),
|
Name::from_labels(vec!["www", "example", "com"]),
|
||||||
RData::PTR(Name::with_labels(vec!["www".to_string(),
|
Name::from_labels(vec!["xxx", "example", "com"]),
|
||||||
"example".to_string(),
|
u32::max_value(),
|
||||||
"com".to_string()])),
|
-1 as i32,
|
||||||
RData::NS(Name::with_labels(vec!["www".to_string(),
|
-1 as i32,
|
||||||
"example".to_string(),
|
-1 as i32,
|
||||||
"com".to_string()])),
|
u32::max_value(),
|
||||||
RData::SOA(SOA::new(Name::with_labels(vec!["www".to_string(),
|
)),
|
||||||
"example".to_string(),
|
RData::TXT(TXT::new(vec![
|
||||||
"com".to_string()]),
|
"abcdef".to_string(),
|
||||||
Name::with_labels(vec!["xxx".to_string(),
|
"ghi".to_string(),
|
||||||
"example".to_string(),
|
"".to_string(),
|
||||||
"com".to_string()]),
|
"j".to_string(),
|
||||||
u32::max_value(),
|
])),
|
||||||
-1 as i32,
|
RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
|
||||||
-1 as i32,
|
RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
|
||||||
-1 as i32,
|
RData::SRV(SRV::new(
|
||||||
u32::max_value())),
|
1,
|
||||||
RData::TXT(TXT::new(vec!["abcdef".to_string(),
|
2,
|
||||||
"ghi".to_string(),
|
3,
|
||||||
"".to_string(),
|
Name::from_labels(vec!["www", "example", "com"]),
|
||||||
"j".to_string()])),
|
)),
|
||||||
RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
|
];
|
||||||
RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
|
|
||||||
RData::SRV(SRV::new(1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
Name::with_labels(vec!["www".to_string(),
|
|
||||||
"example".to_string(),
|
|
||||||
"com".to_string()])))];
|
|
||||||
|
|
||||||
unordered.sort();
|
unordered.sort();
|
||||||
assert_eq!(ordered, unordered);
|
assert_eq!(ordered, unordered);
|
||||||
@@ -1086,11 +1226,14 @@ mod tests {
|
|||||||
let length = binary.len() as u16; // pre exclusive borrow
|
let length = binary.len() as u16; // pre exclusive borrow
|
||||||
let mut decoder = BinDecoder::new(&binary);
|
let mut decoder = BinDecoder::new(&binary);
|
||||||
|
|
||||||
assert_eq!(RData::read(&mut decoder,
|
assert_eq!(
|
||||||
::rr::record_type::RecordType::from(&expect),
|
RData::read(
|
||||||
length)
|
&mut decoder,
|
||||||
.unwrap(),
|
::rr::record_type::RecordType::from(&expect),
|
||||||
expect);
|
length,
|
||||||
|
).unwrap(),
|
||||||
|
expect
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user