domain_core/bits/
charstr.rs

1//! Character strings.
2//!
3//! The somewhat ill-named `<character-string>` is defined in [RFC 1035] as
4//! binary information of up to 255 octets. As such, it doesn’t necessarily
5//! contain (ASCII-) characters nor is it a string in a Rust-sense.
6//!
7//! An existing, immutable character string is represented by the type
8//! [`CharStr`]. The type [`CharStrMut`] allows constructing a character
9//! string from individual octets or byte slices.
10//!
11//! In wire-format, character strings are encoded as one octet giving the
12//! length followed by the actual data in that many octets. The length octet
13//! is not part of the content wrapped by these two types.
14//!
15//! A `CharStr` can be constructed from a string slice via the `FromStr`
16//! trait. In this case, the string must consist only of printable ASCII
17//! characters. Space and double quote are allowed and will be accepted with
18//! their ASCII value. Other values need to be escaped via a backslash
19//! followed by the three-digit decimal representation of the value. In
20//! addition, a backslash followed by a non-digit printable ASCII character
21//! is accepted, too, with the ASCII value of this character used.
22//!
23//! [`CharStr`]: struct.CharStr.html
24//! [`CharStrMut`]: struct.CharStrMut.html
25//! [RFC 1035]: https://tools.ietf.org/html/rfc1035
26
27use std::{cmp, fmt, hash, ops, str};
28use bytes::{BufMut, Bytes, BytesMut};
29use ::master::scan::{BadSymbol, CharSource, Scan, Scanner, ScanError, Symbol,
30                     SymbolError, SyntaxError};
31use super::compose::Compose;
32use super::parse::{ParseAll, ParseAllError, Parse, Parser, ShortBuf};
33
34
35//------------ CharStr -------------------------------------------------------
36
37/// The content of a DNS character string.
38///
39/// A character string consists of up to 255 bytes of binary data. This type
40/// wraps a bytes value enforcing the length limitation. It derefs into the
41/// underlying bytes value for working with the actual content in a familiar
42/// way.
43///
44/// As per [RFC 1035], character strings compare ignoring ASCII case.
45/// `CharStr`’s implementations of the `std::cmp` traits act accordingly.
46#[derive(Clone)]
47pub struct CharStr {
48    /// The underlying bytes slice.
49    inner: Bytes
50}
51
52
53/// # Creation and Conversion
54///
55impl CharStr {
56    /// Creates a new empty character string.
57    pub fn empty() -> Self {
58        CharStr { inner: Bytes::from_static(b"") }
59    }
60
61    /// Creates a character string from a bytes value without length check.
62    ///
63    /// As this can break the guarantees made by the type, it is unsafe.
64    unsafe fn from_bytes_unchecked(bytes: Bytes) -> Self {
65        CharStr { inner: bytes }
66    }
67
68    /// Creates a new character string from a bytes value.
69    ///
70    /// Returns succesfully if the bytes slice can indeed be used as a
71    /// character string, i.e., it is not longer than 255 bytes.
72    pub fn from_bytes(bytes: Bytes) -> Result<Self, CharStrError> {
73        if bytes.len() > 255 { Err(CharStrError) }
74        else { Ok(unsafe { Self::from_bytes_unchecked(bytes) })}
75    }
76
77    /// Creates a new character string from a byte slice.
78    ///
79    /// The function will create a new bytes value and copy the slice’s
80    /// content.
81    ///
82    /// If the byte slice is longer than 255 bytes, the function will return
83    /// an error.
84    pub fn from_slice(slice: &[u8]) -> Result<Self, CharStrError> {
85        if slice.len() > 255 { Err(CharStrError) }
86        else { Ok(unsafe { Self::from_bytes_unchecked(slice.into()) })}
87    }
88
89    /// Converts the value into its underlying bytes value.
90    pub fn into_bytes(self) -> Bytes {
91        self.inner
92    }
93
94    /// Returns a reference to the underlying bytes value.
95    pub fn as_bytes(&self) -> &Bytes {
96        &self.inner
97    }
98
99    /// Returns a reference to a byte slice of the character string’s data.
100    pub fn as_slice(&self) -> &[u8] {
101        self.inner.as_ref()
102    }
103
104    /// Attempts to make the character string mutable.
105    ///
106    /// This will only succeed if the underlying bytes value has unique
107    /// access to its memory. If this fails, you’ll simply get `self` back
108    /// for further consideration.
109    ///
110    /// See [`into_mut`](#method.into_mut) for a variation that copies the
111    /// data if necessary.
112    pub fn try_into_mut(self) -> Result<CharStrMut, Self> {
113        self.inner.try_mut()
114            .map(|b| unsafe { CharStrMut::from_bytes_unchecked(b) })
115            .map_err(|b| unsafe { CharStr::from_bytes_unchecked(b) })
116    }
117
118    /// Provides a mutable version of the character string.
119    ///
120    /// If the underlying bytes value has exclusive access to its memory,
121    /// the function will reuse the bytes value. Otherwise, it will create
122    /// a new buffer and copy `self`’s content into it.
123    pub fn into_mut(self) -> CharStrMut {
124        unsafe { CharStrMut::from_bytes_unchecked(self.inner.into()) }
125    }
126
127    /// Scans a character string given as a word of hexadecimal digits.
128    pub fn scan_hex<C: CharSource>(
129        scanner: &mut Scanner<C>
130    ) -> Result<Self, ScanError> {
131        scanner.scan_hex_word(|b| unsafe {
132            Ok(CharStr::from_bytes_unchecked(b))
133        })
134    }
135
136    /// Displays a character string as a word in hexadecimal digits.
137    pub fn display_hex(&self, f: &mut fmt::Formatter) -> fmt::Result {
138        for ch in self {
139            write!(f, "{:02X}", ch)?;
140        }
141        Ok(())
142    }
143}
144
145
146//--- FromStr
147
148impl str::FromStr for CharStr {
149    type Err = FromStrError;
150
151    fn from_str(s: &str) -> Result<Self, Self::Err> {
152        // Most likely, everything is ASCII so take `s`’s length as capacity.
153        let mut res = CharStrMut::with_capacity(s.len());
154        let mut chars = s.chars();
155        while let Some(symbol) = Symbol::from_chars(&mut chars)? {
156            res.push(symbol.into_byte()?)?
157        }
158        Ok(res.freeze())
159    }
160}
161
162
163
164//--- Parse, ParseAll, and Compose
165
166impl Parse for CharStr {
167    type Err = ShortBuf;
168
169    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
170        let len = parser.parse_u8()? as usize;
171        parser.parse_bytes(len).map(|bytes| {
172            unsafe { Self::from_bytes_unchecked(bytes) }
173        })
174    }
175
176    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
177        let len = parser.parse_u8()? as usize;
178        parser.advance(len)
179    }
180}
181
182impl ParseAll for CharStr {
183    type Err = ParseAllError;
184
185    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
186        let char_len = parser.parse_u8()? as usize;
187        ParseAllError::check(char_len + 1, len)?;
188        parser.parse_bytes(char_len).map_err(Into::into).map(|bytes| {
189            unsafe { Self::from_bytes_unchecked(bytes) }
190        })
191    }
192}
193
194impl Compose for CharStr {
195    fn compose_len(&self) -> usize {
196        self.len() + 1
197    }
198
199    fn compose<B: BufMut>(&self, buf: &mut B) {
200        buf.put_u8(self.len() as u8);
201        buf.put_slice(self.as_ref());
202    }
203}
204
205
206//--- Scan and Display
207
208impl Scan for CharStr {
209    fn scan<C: CharSource>(scanner: &mut Scanner<C>)
210                           -> Result<Self, ScanError> {
211        scanner.scan_byte_phrase(|res| {
212            if res.len() > 255 {
213                Err(SyntaxError::LongCharStr)
214            }
215            else {
216                Ok(unsafe { CharStr::from_bytes_unchecked(res) })
217            }
218        })
219    }
220}
221
222impl fmt::Display for CharStr {
223    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224        for ch in &self.inner {
225            fmt::Display::fmt(&Symbol::from_byte(ch), f)?
226        }
227        Ok(())
228    }
229}
230
231
232//--- Deref and AsRef
233
234impl ops::Deref for CharStr {
235    type Target = Bytes;
236
237    fn deref(&self) -> &Self::Target {
238        &self.inner
239    }
240}
241
242impl AsRef<Bytes> for CharStr {
243    fn as_ref(&self) -> &Bytes {
244        &self.inner
245    }
246}
247
248impl AsRef<[u8]> for CharStr {
249    fn as_ref(&self) -> &[u8] {
250        &self.inner
251    }
252}
253
254
255//--- IntoIterator
256
257impl IntoIterator for CharStr {
258    type Item = u8;
259    type IntoIter = ::bytes::buf::Iter<::std::io::Cursor<Bytes>>;
260
261    fn into_iter(self) -> Self::IntoIter {
262        self.inner.into_iter()
263    }
264}
265
266impl<'a> IntoIterator for &'a CharStr {
267    type Item = u8;
268    type IntoIter = ::bytes::buf::Iter<::std::io::Cursor<&'a Bytes>>;
269
270    fn into_iter(self) -> Self::IntoIter {
271        (&self.inner).into_iter()
272    }
273}
274
275
276//--- PartialEq, Eq
277
278impl<T: AsRef<[u8]>> PartialEq<T> for CharStr {
279    fn eq(&self, other: &T) -> bool {
280        self.as_slice().eq_ignore_ascii_case(other.as_ref())
281    }
282}
283
284impl Eq for CharStr { }
285
286
287//--- PartialOrd, Ord
288
289impl<T: AsRef<[u8]>> PartialOrd<T> for CharStr {
290    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
291        self.iter().map(u8::to_ascii_lowercase)
292            .partial_cmp(other.as_ref().iter()
293                              .map(u8::to_ascii_lowercase))
294    }
295}
296
297impl Ord for CharStr {
298    fn cmp(&self, other: &Self) -> cmp::Ordering {
299        self.iter().map(u8::to_ascii_lowercase)
300            .cmp(other.iter().map(u8::to_ascii_lowercase))
301    }
302}
303
304
305//--- Hash
306
307impl hash::Hash for CharStr {
308    fn hash<H: hash::Hasher>(&self, state: &mut H) {
309        self.iter().map(u8::to_ascii_lowercase)
310            .for_each(|ch| ch.hash(state))
311    }
312}
313
314
315//--- Debug
316
317impl fmt::Debug for CharStr {
318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319        try!("CharStr(\"".fmt(f));
320        try!(fmt::Display::fmt(self, f));
321        "\")".fmt(f)
322    }
323}
324
325
326//------------ CharStrMut ----------------------------------------------------
327
328/// A mutable DNS character string.
329///
330/// This type is solely intended to be used when constructing a character
331/// string from individual bytes or byte slices. It derefs directly to
332/// `[u8]` to allow you to manipulate the acutal content but not to extend
333/// it other than through the methods provided by itself.
334#[derive(Default)]
335pub struct CharStrMut {
336    bytes: BytesMut,
337}
338
339
340impl CharStrMut {
341    /// Creates a new value from a bytes buffer unchecked.
342    ///
343    /// Since the buffer may already be longer than it is allowed to be, this
344    /// is unsafe.
345    unsafe fn from_bytes_unchecked(bytes: BytesMut) -> Self {
346        CharStrMut { bytes }
347    }
348
349    /// Creates a new mutable character string from a given bytes buffer.
350    ///
351    /// If `bytes` is longer than 255 bytes, an error is returned.
352    pub fn from_bytes(bytes: BytesMut) -> Result<Self, CharStrError> {
353        if bytes.len() > 255 {
354            Err(CharStrError)
355        }
356        else {
357            Ok(unsafe { Self::from_bytes_unchecked(bytes) })
358        }
359    }
360
361    /// Creates a new mutable character string with the given capacity.
362    ///
363    /// The capacity may be larger than the allowed size of a character
364    /// string.
365    pub fn with_capacity(capacity: usize) -> Self {
366        unsafe {
367            CharStrMut::from_bytes_unchecked(BytesMut::with_capacity(capacity))
368        }
369    }
370
371    /// Creates a new mutable character string with a default capacity.
372    pub fn new() -> Self {
373        Self::default()
374    }
375
376    /// Returns the length of the character string assembled so far.
377    pub fn len(&self) -> usize {
378        self.bytes.len()
379    }
380
381    /// Returns whether the character string is still empty.
382    pub fn is_empty(&self) -> bool {
383        self.bytes.is_empty()
384    }
385
386    /// Returns the current capacity of the bytes buffer used for building.
387    pub fn capacity(&self) -> usize {
388        self.bytes.capacity()
389    }
390
391    /// Turns the value into an imutable character string.
392    pub fn freeze(self) -> CharStr {
393        unsafe { CharStr::from_bytes_unchecked(self.bytes.freeze()) }
394    }
395}
396
397/// # Manipulations
398///
399impl CharStrMut {
400    /// Reserves an `additional` bytes of capacity.
401    ///
402    /// The resulting capacity may be larger than the allowed size of a
403    /// character string.
404    pub fn reserve(&mut self, additional: usize) {
405        self.bytes.reserve(additional)
406    }
407
408    /// Pushes a byte to the end of the character string.
409    ///
410    /// If this would result in a string longer than the allowed 255 bytes,
411    /// returns an error and leaves the string be.
412    pub fn push(&mut self, ch: u8) -> Result<(), PushError> {
413        self.extend_from_slice(&[ch])
414    }
415
416    /// Pushes the content of a byte slice to the end of the character string.
417    ///
418    /// If this would result in a string longer than the allowed 255 bytes,
419    /// returns an error and leaves the string be.
420    pub fn extend_from_slice(&mut self, extend: &[u8])
421                             -> Result<(), PushError> {
422        if self.bytes.len() + extend.len() > 255 {
423            Err(PushError)
424        }
425        else {
426            self.bytes.extend_from_slice(extend);
427            Ok(())
428        }
429    }
430}
431
432
433//--- Deref and DerefMut
434
435impl ops::Deref for CharStrMut {
436    type Target = [u8];
437
438    fn deref(&self) -> &[u8] {
439        self.bytes.as_ref()
440    }
441}
442
443impl ops::DerefMut for CharStrMut {
444    fn deref_mut(&mut self) -> &mut [u8] {
445        self.bytes.as_mut()
446    }
447}
448
449
450//--- AsRef and AsMut
451
452impl AsRef<[u8]> for CharStrMut {
453    fn as_ref(&self) -> &[u8] {
454        self.bytes.as_ref()
455    }
456}
457
458impl AsMut<[u8]> for CharStrMut {
459    fn as_mut(&mut self) -> &mut [u8] {
460        self.bytes.as_mut()
461    }
462}
463
464
465//------------ CharStrError --------------------------------------------------
466
467/// A byte sequence does not represent a valid character string.
468///
469/// This can only mean that the sequence is longer than 255 bytes.
470#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
471#[fail(display="illegal character string")]
472pub struct CharStrError;
473
474
475//------------ FromStrError --------------------------------------------
476
477/// An error happened when converting a Rust string to a DNS character string.
478#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
479pub enum FromStrError {
480    /// The string ended when there should have been more characters.
481    ///
482    /// This most likely happens inside escape sequences and quoting.
483    #[fail(display="unexpected end of input")]
484    ShortInput,
485
486    /// A character string has more than 255 octets.
487    #[fail(display="character string with more than 255 octets")]
488    LongString,
489
490    /// An illegal escape sequence was encountered.
491    ///
492    /// Escape sequences are a backslash character followed by either a
493    /// three decimal digit sequence encoding a byte value or a single
494    /// other printable ASCII character.
495    #[fail(display="illegal escape sequence")]
496    BadEscape,
497
498    /// An illegal character was encountered.
499    ///
500    /// Only printable ASCII characters are allowed.
501    #[fail(display="illegal character '{}'", _0)]
502    BadSymbol(Symbol),
503}
504
505
506//--- From
507
508impl From<SymbolError> for FromStrError {
509    fn from(err: SymbolError) -> FromStrError {
510        match err {
511            SymbolError::BadEscape => FromStrError::BadEscape,
512            SymbolError::ShortInput => FromStrError::ShortInput,
513        }
514    }
515}
516
517impl From<BadSymbol> for FromStrError {
518    fn from(err: BadSymbol) -> FromStrError {
519        FromStrError::BadSymbol(err.0)
520    }
521}
522
523impl From<PushError> for FromStrError {
524    fn from(_: PushError) -> FromStrError {
525        FromStrError::LongString
526    }
527}
528
529
530//------------ PushError -----------------------------------------------------
531
532/// An error happened while adding data to a [`CharStrMut`].
533///
534/// The only error possible is that the resulting character string would have
535/// exceeded the length limit of 255 octets.
536///
537/// [`CharStrMut`]: ../struct.CharStrMut.html
538#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
539#[fail(display="adding bytes would exceed the size limit")]
540pub struct PushError;
541
542
543//============ Testing ======================================================
544
545#[cfg(test)]
546mod test {
547    use super::*;
548    use ::master::scan::Symbol;
549
550    #[test]
551    fn from_slice() {
552        assert_eq!(CharStr::from_slice(b"01234").unwrap().as_slice(),
553                   b"01234");
554        assert_eq!(CharStr::from_slice(b"").unwrap().as_slice(), b"");
555        assert!(CharStr::from_slice(&vec![0; 255]).is_ok());
556        assert!(CharStr::from_slice(&vec![0; 256]).is_err());
557    }
558
559    #[test]
560    fn from_bytes() {
561        assert_eq!(CharStr::from_bytes(Bytes::from_static(b"01234"))
562                           .unwrap() .as_slice(),
563                   b"01234");
564        assert_eq!(CharStr::from_bytes(Bytes::from_static(b""))
565                           .unwrap().as_slice(),
566                   b"");
567        assert!(CharStr::from_bytes(vec![0; 255].into()).is_ok());
568        assert!(CharStr::from_bytes(vec![0; 256].into()).is_err());
569    }
570
571    #[test]
572    fn from_str() {
573        use std::str::FromStr;
574
575        assert_eq!(CharStr::from_str("foo").unwrap().as_slice(),
576                   b"foo");
577        assert_eq!(CharStr::from_str("f\\oo").unwrap().as_slice(),
578                   b"foo");
579        assert_eq!(CharStr::from_str("foo\\112").unwrap().as_slice(),
580                   b"foo\x70");
581        assert_eq!(CharStr::from_str("\"foo\\\"2\"").unwrap().as_slice(),
582                   b"\"foo\"2\"");
583        assert_eq!(CharStr::from_str("06 dii").unwrap().as_slice(),
584                   b"06 dii");
585        assert_eq!(CharStr::from_str("0\\"), Err(FromStrError::ShortInput));
586        assert_eq!(CharStr::from_str("0\\2"), Err(FromStrError::ShortInput));
587        assert_eq!(CharStr::from_str("0\\2a"),
588                   Err(FromStrError::BadEscape));
589        assert_eq!(CharStr::from_str("ö"),
590                   Err(FromStrError::BadSymbol(Symbol::Char('ö'))));
591        assert_eq!(CharStr::from_str("\x06"),
592                   Err(FromStrError::BadSymbol(Symbol::Char('\x06'))));
593    }
594
595    #[test]
596    fn parse() {
597        use ::bits::parse::{Parse, Parser, ShortBuf};
598
599        let mut parser = Parser::from_static(b"12\x03foo\x02bartail");
600        parser.advance(2).unwrap();
601        let foo = CharStr::parse(&mut parser).unwrap();
602        let bar = CharStr::parse(&mut parser).unwrap();
603        assert_eq!(foo.as_slice(), b"foo");
604        assert_eq!(bar.as_slice(), b"ba");
605        assert_eq!(parser.peek_all(), b"rtail");
606
607        assert_eq!(CharStr::parse(&mut Parser::from_static(b"\x04foo")),
608                   Err(ShortBuf))
609    }
610
611    #[test]
612    fn parse_all() {
613        use ::bits::parse::{ParseAll, ParseAllError, Parser};
614
615        let mut parser = Parser::from_static(b"12\x03foo12");
616        parser.advance(2).unwrap();
617        assert_eq!(CharStr::parse_all(&mut parser.clone(), 5),
618                   Err(ParseAllError::TrailingData));
619        assert_eq!(CharStr::parse_all(&mut parser.clone(), 2),
620                   Err(ParseAllError::ShortField));
621        let foo = CharStr::parse_all(&mut parser, 4).unwrap();
622        let bar = u8::parse_all(&mut parser, 1).unwrap();
623        assert_eq!(foo.as_slice(), b"foo");
624        assert_eq!(bar, b'1');
625        assert_eq!(parser.peek_all(), b"2");
626        
627        assert_eq!(CharStr::parse_all(&mut Parser::from_static(b"\x04foo"), 5),
628                   Err(ParseAllError::ShortBuf));
629    }
630
631    #[test]
632    fn compose() {
633        use bytes::BytesMut;
634        use bits::compose::Compose;
635
636        let mut buf = BytesMut::with_capacity(10);
637        let val = CharStr::from_bytes(Bytes::from_static(b"foo")).unwrap();
638        assert_eq!(val.compose_len(), 4);
639        val.compose(&mut buf);
640        assert_eq!(buf, &b"\x03foo"[..]);
641
642        let mut buf = BytesMut::with_capacity(10);
643        let val = CharStr::from_bytes(Bytes::from_static(b"")).unwrap();
644        assert_eq!(val.compose_len(), 1);
645        val.compose(&mut buf);
646        assert_eq!(buf, &b"\x00"[..]);
647    }
648
649    fn are_eq(l: &[u8], r: &[u8]) -> bool {
650        CharStr::from_slice(l).unwrap() == CharStr::from_slice(r).unwrap()
651    }
652
653    #[test]
654    fn eq() {
655        assert!(are_eq(b"abc", b"abc"));
656        assert!(!are_eq(b"abc", b"def"));
657        assert!(!are_eq(b"abc", b"ab"));
658        assert!(!are_eq(b"abc", b"abcd"));
659        assert!(are_eq(b"ABC", b"abc"));
660        assert!(!are_eq(b"ABC", b"def"));
661        assert!(!are_eq(b"ABC", b"ab"));
662        assert!(!are_eq(b"ABC", b"abcd"));
663        assert!(are_eq(b"", b""));
664        assert!(!are_eq(b"", b"A"));
665    }
666
667    fn is_ord(l: &[u8], r: &[u8], order: cmp::Ordering) {
668        assert_eq!(CharStr::from_slice(l)
669                           .unwrap().cmp(&CharStr::from_slice(r).unwrap()),
670                   order)
671    }
672
673    #[test]
674    fn ord() {
675        use std::cmp::Ordering::*;
676
677        is_ord(b"abc", b"ABC", Equal);
678        is_ord(b"abc", b"a", Greater);
679        is_ord(b"abc", b"A", Greater);
680        is_ord(b"a", b"BC", Less);
681    }
682
683    #[test]
684    fn push() {
685        let mut o = CharStrMut::new();
686        o.push(b'f').unwrap();
687        o.push(b'o').unwrap();
688        o.push(b'o').unwrap();
689        assert_eq!(o.freeze().as_slice(), b"foo");
690
691        let mut o = CharStrMut::from_bytes(vec![0; 254].into()).unwrap();
692        o.push(b'f').unwrap();
693        assert_eq!(o.len(), 255);
694        assert!(o.push(b'f').is_err());
695    }
696
697    #[test]
698    fn extend_from_slice() {
699        let mut o = CharStrMut::from_bytes(vec![b'f', b'o', b'o'].into())
700                               .unwrap();
701        o.extend_from_slice(b"bar").unwrap();
702        assert_eq!(o.as_ref(), b"foobar");
703        assert!(o.extend_from_slice(&[0u8; 250][..]).is_err());
704        o.extend_from_slice(&[0u8; 249][..]).unwrap();
705        assert_eq!(o.len(), 255);
706    }
707}
708