From b596d1e91e0ff4680a18307f26d1700a0a1ca3ee Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Fri, 25 Mar 2016 16:52:35 +0100 Subject: [PATCH] Add a type for . --- src/bits/compose.rs | 4 + src/bits/cstring.rs | 232 ++++++++++++++++++++++++++++++++++++++++++++ src/bits/flavor.rs | 5 + src/bits/mod.rs | 1 + src/bits/name.rs | 2 +- src/bits/parse.rs | 10 ++ 6 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 src/bits/cstring.rs diff --git a/src/bits/compose.rs b/src/bits/compose.rs index 00241124..07829a4a 100644 --- a/src/bits/compose.rs +++ b/src/bits/compose.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use std::fmt; use std::mem; use std::ptr; +use super::cstring::CString; use super::error::{ComposeError, ComposeResult}; use super::name::{DName, DNameSlice, Label, OwnedDName}; @@ -62,6 +63,9 @@ pub trait ComposeBytes: Sized + fmt::Debug { fn push_dname_compressed(&mut self, name: &D) -> ComposeResult<()>; + fn push_cstring(&mut self, cstring: &S) -> ComposeResult<()> { + cstring.compose(self) + } //--- Checkpoint and rollback. diff --git a/src/bits/cstring.rs b/src/bits/cstring.rs new file mode 100644 index 00000000..d6b17495 --- /dev/null +++ b/src/bits/cstring.rs @@ -0,0 +1,232 @@ +//! Character strings. + +use std::borrow::Borrow; +use std::cmp; +use std::hash; +use std::ops::Deref; +use super::compose::ComposeBytes; +use super::error::{ComposeResult, ParseResult}; +use super::parse::ParseBytes; + +//------------ CString ------------------------------------------------------ + +pub trait CString { + fn compose(&self, target: &mut C) -> ComposeResult<()>; +} + +//------------ CStringRef --------------------------------------------------- + +#[derive(Clone, Debug)] +pub struct CStringRef<'a> { + inner: &'a [u8] +} + +impl <'a> CStringRef<'a> { + unsafe fn from_bytes(bytes: &'a [u8]) -> Self { + CStringRef { inner: bytes } + } + + pub fn as_slice(&self) -> &CStringRef { + self + } + + pub fn to_owned(&self) -> OwnedCString { + unsafe { OwnedCString::from_bytes(self.inner) } + } + + pub fn parse>(parser: &mut P) -> ParseResult { + let len = try!(parser.parse_u8()) as usize; + parser.parse_bytes(len) + .map(|bytes| unsafe {CStringRef::from_bytes(bytes) }) + } +} + + +//--- CString + +impl<'a> CString for CStringRef<'a> { + fn compose(&self, target: &mut C) -> ComposeResult<()> { + assert!(self.inner.len() < 256); + try!(target.push_u8(self.inner.len() as u8)); + try!(target.push_bytes(self.inner)); + Ok(()) + } +} + + +//--- Deref, Borrow, AsRef + +impl<'a> Deref for CStringRef<'a> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + self.inner + } +} + +impl<'a> Borrow<[u8]> for CStringRef<'a> { + fn borrow(&self) -> &[u8] { + self.deref() + } +} + +impl<'a> AsRef<[u8]> for CStringRef<'a> { + fn as_ref(&self) -> &[u8] { + self.deref() + } +} + + +//--- PartialEq, Eq + +impl<'a, T: AsRef<[u8]>> PartialEq for CStringRef<'a> { + fn eq(&self, other: &T) -> bool { + self.deref().eq(other.as_ref()) + } +} + +impl<'a> Eq for CStringRef<'a> { } + + +//--- PartialOrd, Ord + +impl<'a, T: AsRef<[u8]>> PartialOrd for CStringRef<'a> { + fn partial_cmp(&self, other: &T) -> Option { + self.deref().partial_cmp(other.as_ref()) + } +} + +impl<'a> Ord for CStringRef<'a> { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.deref().cmp(other.deref()) + } +} + + +//--- Hash + +impl<'a> hash::Hash for CStringRef<'a> { + fn hash(&self, state: &mut H) { + self.deref().hash(state) + } +} + + +//--- Display + +// XXX TODO + + +//------------ OwnedCString ------------------------------------------------- + +#[derive(Clone, Debug)] +pub struct OwnedCString { + inner: Vec +} + + +impl OwnedCString { + unsafe fn from_bytes(bytes: &[u8]) -> Self { + OwnedCString { inner: Vec::from(bytes) } + } + + pub fn new() -> Self { + OwnedCString { inner: Vec::new() } + } + + // XXX TODO from_str + + pub fn parse<'a, P: ParseBytes<'a>>(parser: &mut P) + -> ParseResult { + Ok(try!(CStringRef::parse(parser)).to_owned()) + } + + pub fn as_slice(&self) -> &[u8] { + self + } +} + + +// XXX TODO Manipulations. + + +//--- CString + +impl CString for OwnedCString { + fn compose(&self, target: &mut C) -> ComposeResult<()> { + assert!(self.inner.len() < 256); + try!(target.push_u8(self.inner.len() as u8)); + try!(target.push_bytes(&self.inner)); + Ok(()) + } +} + + +//--- FromStr + +// XXX TODO + + +//--- Deref, Borrow, AsRef + +impl Deref for OwnedCString { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + self.inner.deref() + } +} + +impl Borrow<[u8]> for OwnedCString { + fn borrow(&self) -> &[u8] { + self.deref() + } +} + +impl AsRef<[u8]> for OwnedCString { + fn as_ref(&self) -> &[u8] { + self + } +} + + +//--- PartialEq and Eq + +impl> PartialEq for OwnedCString { + fn eq(&self, other: &T) -> bool { + self.deref().eq(other.as_ref()) + } +} + +impl Eq for OwnedCString { } + + +//--- PartialOrd and Ord + +impl> PartialOrd for OwnedCString { + fn partial_cmp(&self, other: &T) -> Option { + self.deref().partial_cmp(other.as_ref()) + } +} + +impl Ord for OwnedCString { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.deref().cmp(other.deref()) + } +} + + +//--- Hash + +impl hash::Hash for OwnedCString { + fn hash(&self, state: &mut H) { + self.deref().hash(state) + } +} + + +//--- Display + +// XXX TODO + + diff --git a/src/bits/flavor.rs b/src/bits/flavor.rs index e030b6a8..ae1a79fd 100644 --- a/src/bits/flavor.rs +++ b/src/bits/flavor.rs @@ -10,6 +10,7 @@ //! flavors as well as the actual flavors as types. use std::marker::PhantomData; +use super::cstring; use super::name; use super::nest; @@ -20,6 +21,7 @@ use super::nest; /// the associated types for each flavor. pub trait Flavor: Sized { type DName: name::DName; + type CString: cstring::CString; } /// The trait for DNS data that is stored in unparsed format. @@ -32,6 +34,7 @@ pub struct Owned; impl Flavor for Owned { type DName = name::OwnedDName; + type CString = cstring::OwnedCString; } /// The flavor for DNS data referencing an underlying bytes slice. @@ -41,6 +44,7 @@ pub struct Ref<'a> { impl<'a> Flavor for Ref<'a> { type DName = name::DNameRef<'a>; + type CString = cstring::CStringRef<'a>; } impl<'a> FlatFlavor<'a> for Ref<'a> { @@ -55,6 +59,7 @@ pub struct Lazy<'a> { impl<'a> Flavor for Lazy<'a> { type DName = name::LazyDName<'a>; + type CString = cstring::CStringRef<'a>; } impl<'a> FlatFlavor<'a> for Lazy<'a> { diff --git a/src/bits/mod.rs b/src/bits/mod.rs index 0da2cceb..d99461fc 100644 --- a/src/bits/mod.rs +++ b/src/bits/mod.rs @@ -1,6 +1,7 @@ //! DNS data. pub mod compose; +pub mod cstring; pub mod error; pub mod flavor; pub mod header; diff --git a/src/bits/name.rs b/src/bits/name.rs index 4a00067c..bce94e4f 100644 --- a/src/bits/name.rs +++ b/src/bits/name.rs @@ -398,7 +398,7 @@ impl<'a> DName for DNameRef<'a> { //--- From impl<'a> From<&'a DNameSlice> for DNameRef<'a> { - fn from(slice: &'a DNameSlice) -> DNameRef { + fn from(slice: &'a DNameSlice) -> Self { Self::from_slice(slice) } } diff --git a/src/bits/parse.rs b/src/bits/parse.rs index 068ce913..60d20a15 100644 --- a/src/bits/parse.rs +++ b/src/bits/parse.rs @@ -1,6 +1,7 @@ //! Parsing of wire-format DNS data. use std::mem; +use super::cstring::CStringRef; use super::error::{ParseResult, ParseError}; use super::flavor::{self, FlatFlavor}; use super::name::{DNameRef, LazyDName}; @@ -66,6 +67,7 @@ pub trait ParseLazy<'a>: ParseBytes<'a> { /// `ParseBytes` trait only for specific flavors. pub trait ParseFlavor<'a, F: FlatFlavor<'a>>: ParseBytes<'a> { fn parse_name(&mut self) -> ParseResult; + fn parse_cstring(&mut self) -> ParseResult; fn parse_nest(&mut self, len: usize) -> ParseResult; } @@ -73,6 +75,10 @@ impl<'a, P: ParseBytes<'a>> ParseFlavor<'a, flavor::Ref<'a>> for P { fn parse_name(&mut self) -> ParseResult> { DNameRef::parse(self) } + + fn parse_cstring(&mut self) -> ParseResult> { + CStringRef::parse(self) + } fn parse_nest(&mut self, len: usize) -> ParseResult> { NestRef::parse(self, len) @@ -84,6 +90,10 @@ impl<'a> ParseFlavor<'a, flavor::Lazy<'a>> for ContextParser<'a> { LazyDName::parse(self) } + fn parse_cstring(&mut self) -> ParseResult> { + CStringRef::parse(self) + } + fn parse_nest(&mut self, len: usize) -> ParseResult> { LazyNest::parse(self, len) }