Add a type for <character-string>.

This commit is contained in:
Martin Hoffmann
2016-03-25 16:52:35 +01:00
parent edb8aea89d
commit b596d1e91e
6 changed files with 253 additions and 1 deletions
+4
View File
@@ -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<D: DName>(&mut self, name: &D)
-> ComposeResult<()>;
fn push_cstring<S: CString>(&mut self, cstring: &S) -> ComposeResult<()> {
cstring.compose(self)
}
//--- Checkpoint and rollback.
+232
View File
@@ -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<C: ComposeBytes>(&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<P: ParseBytes<'a>>(parser: &mut P) -> ParseResult<Self> {
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<C: ComposeBytes>(&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<T> 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<T> for CStringRef<'a> {
fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
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<H: hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}
//--- Display
// XXX TODO
//------------ OwnedCString -------------------------------------------------
#[derive(Clone, Debug)]
pub struct OwnedCString {
inner: Vec<u8>
}
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<Self> {
Ok(try!(CStringRef::parse(parser)).to_owned())
}
pub fn as_slice(&self) -> &[u8] {
self
}
}
// XXX TODO Manipulations.
//--- CString
impl CString for OwnedCString {
fn compose<C: ComposeBytes>(&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<T: AsRef<[u8]>> PartialEq<T> for OwnedCString {
fn eq(&self, other: &T) -> bool {
self.deref().eq(other.as_ref())
}
}
impl Eq for OwnedCString { }
//--- PartialOrd and Ord
impl<T: AsRef<[u8]>> PartialOrd<T> for OwnedCString {
fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
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<H: hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}
//--- Display
// XXX TODO
+5
View File
@@ -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> {
+1
View File
@@ -1,6 +1,7 @@
//! DNS data.
pub mod compose;
pub mod cstring;
pub mod error;
pub mod flavor;
pub mod header;
+1 -1
View File
@@ -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)
}
}
+10
View File
@@ -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<F::DName>;
fn parse_cstring(&mut self) -> ParseResult<F::CString>;
fn parse_nest(&mut self, len: usize) -> ParseResult<F::Nest>;
}
@@ -73,6 +75,10 @@ impl<'a, P: ParseBytes<'a>> ParseFlavor<'a, flavor::Ref<'a>> for P {
fn parse_name(&mut self) -> ParseResult<DNameRef<'a>> {
DNameRef::parse(self)
}
fn parse_cstring(&mut self) -> ParseResult<CStringRef<'a>> {
CStringRef::parse(self)
}
fn parse_nest(&mut self, len: usize) -> ParseResult<NestRef<'a>> {
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<'a>> {
CStringRef::parse(self)
}
fn parse_nest(&mut self, len: usize) -> ParseResult<LazyNest<'a>> {
LazyNest::parse(self, len)
}