domain/base/
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 [`CharStrBuilder`] allows constructing a character
9//! string from individual octets or octets 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 [`CharStr`], it contains the data
14//! only.
15//!
16//! A [`CharStr`] can be constructed from a string via the `FromStr`
17//! trait. In this case, the string must consist only of printable ASCII
18//! characters. Space and double quote are allowed and will be accepted with
19//! their ASCII value. Other values need to be escaped via a backslash
20//! followed by the three-digit decimal representation of the value. In
21//! addition, a backslash followed by a non-digit printable ASCII character
22//! is accepted, too, with the ASCII value of this character used.
23//!
24//! [RFC 1035]: https://tools.ietf.org/html/rfc1035
25
26use super::cmp::CanonicalOrd;
27use super::scan::{BadSymbol, Scanner, Symbol, SymbolCharsError};
28use super::wire::{Compose, ParseError};
29#[cfg(feature = "bytes")]
30use bytes::BytesMut;
31use core::{cmp, fmt, hash, mem, str};
32use octseq::builder::FreezeBuilder;
33#[cfg(feature = "serde")]
34use octseq::serde::{DeserializeOctets, SerializeOctets};
35use octseq::{
36    EmptyBuilder, FromBuilder, IntoBuilder, Octets, OctetsBuilder,
37    OctetsFrom, Parser, ShortBuf, Truncate,
38};
39#[cfg(feature = "std")]
40use std::vec::Vec;
41
42//------------ CharStr -------------------------------------------------------
43
44/// The content of a DNS character string.
45///
46/// A character string consists of up to 255 octets of binary data. This type
47/// wraps an octets sequence. It is guaranteed to always be at most 255 octets
48/// in length. It derefs into the underlying octets for working with the
49/// content in a familiar way.
50///
51/// As per [RFC 1035], character strings compare ignoring ASCII case.
52/// `CharStr`’s implementations of the `std::cmp` traits act accordingly.
53///
54/// # Presentation format
55///
56/// The text representation of a character string comes in two flavors:
57/// Quoted and unquoted. In both cases, the content is interpreted as ASCII
58/// text and those octets that aren’t printable ASCII characters, as well as
59/// some special symbols, are escaped.
60///
61/// There are two escaping mechanisms: octets that are printable ASCII
62/// characters but need to be escaped anyway use what we call a “simple
63/// escape” that precedes the character with an ASCII backslash. For all
64/// non-printable octets “decimal escapes” are used: an ASCII backslash is
65/// followed by three decimal digits representing the decimal value of the
66/// octet. A consequence if this is that you cannot escape the digits 0, 1,
67/// and 2 using simple escapes and you probably shouldn’t do it for the other
68/// digits.
69///
70/// In the quoted form, the content is preceded and followed by exactly one
71/// ASCII double quote. Inside, only double quotes, backslashes, and
72/// non-printable octets need to be escaped.
73///
74/// In the unquoted form, the content is formatted without any explicit
75/// delimiters. Instead, it ends at the first ASCII space or any other
76/// delimiting symbol, normally ASCII control characters or an ASCII
77/// semicolon which marks the start of a comment. These characters, as well
78/// as the double quote, also need to be escaped.
79///
80/// # `Display` and `FromStr`
81///
82/// When formatting a character string using the `Display` trait, a variation
83/// of the unquoted form is used where only backslashes and non-printable
84/// octets are escaped. Two methods are available that make it possible to
85/// format the character string in quoted and unquoted formats,
86/// [`display_quoted`][Self::display_quoted] and
87/// [`display_unquoted`][Self::display_unquoted]. They return a temporary
88/// value that can be given to a formatting macro.
89///
90/// The `FromStr` implementation reads a character string from a Rust string
91/// in the format created by `Display` but is more relaxed about escape
92/// sequences – it accepts all of them as long as they lead to a valid
93/// character string.
94///
95/// # Serde support
96///
97/// When the `serde` feature is enabled, the type supports serialization and
98/// deserialization. The format differs for human readable and compact
99/// serialization formats.
100///
101/// For human readable formats, character strings are serialized as a newtype
102/// `CharStr` wrapping a string with the content as an ASCII string.
103/// Non-printable ASCII characters (i.e., those with a byte value below 32
104/// and above 176) are escaped using the decimal escape sequences as used by
105/// the presentation format. In addition, backslashes are escaped using a
106/// simple escape sequence and thus are doubled.
107///
108/// This leads to a slightly unfortunate situation in serialization formats
109/// that in turn use backslash as an escape sequence marker in their own
110/// string representation, such as JSON, where a backslash ends up as four
111/// backslashes.
112///
113/// When deserializing, escape sequences are excepted for all octets and
114/// translated. Non-ASCII characters are not accepted and lead to error.
115///
116/// For compact formats, character strings are serialized as a
117/// newtype `CharStr` wrapping a byte array with the content as is.
118///
119/// [RFC 1035]: https://tools.ietf.org/html/rfc1035
120#[derive(Clone)]
121#[repr(transparent)]
122pub struct CharStr<Octs: ?Sized>(Octs);
123
124impl CharStr<()> {
125    /// Character strings have a maximum length of 255 octets.
126    pub const MAX_LEN: usize = 255;
127}
128
129impl<Octs: ?Sized> CharStr<Octs> {
130    /// Creates a new empty character string.
131    #[must_use]
132    pub fn empty() -> Self
133    where
134        Octs: From<&'static [u8]>,
135    {
136        CharStr(b"".as_ref().into())
137    }
138
139    /// Creates a new character string from an octets value.
140    ///
141    /// Returns succesfully if `octets` can indeed be used as a
142    /// character string, i.e., it is not longer than 255 bytes.
143    pub fn from_octets(octets: Octs) -> Result<Self, CharStrError>
144    where
145        Octs: AsRef<[u8]> + Sized,
146    {
147        CharStr::check_slice(octets.as_ref())?;
148        Ok(unsafe { Self::from_octets_unchecked(octets) })
149    }
150
151    /// Creates a character string from octets without length check.
152    ///
153    /// # Safety
154    ///
155    /// The caller has to make sure that `octets` is at most 255 octets
156    /// long. Otherwise, the behavior is undefined.
157    pub unsafe fn from_octets_unchecked(octets: Octs) -> Self
158    where
159        Octs: Sized,
160    {
161        CharStr(octets)
162    }
163}
164
165impl CharStr<[u8]> {
166    /// Creates a character string from an octets slice.
167    pub fn from_slice(slice: &[u8]) -> Result<&Self, CharStrError> {
168        Self::check_slice(slice)?;
169        Ok(unsafe { Self::from_slice_unchecked(slice) })
170    }
171
172    /// Creates a new empty character string on an octets slice.
173    #[must_use]
174    pub fn empty_slice() -> &'static Self {
175        unsafe { Self::from_slice_unchecked(b"".as_ref()) }
176    }
177
178    /// Creates a character string from an octets slice without checking.
179    ///
180    /// # Safety
181    ///
182    /// The caller has to make sure that `octets` is at most 255 octets
183    /// long. Otherwise, the behaviour is undefined.
184    #[must_use]
185    pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
186        // SAFETY: Charstr has repr(transparent)
187        mem::transmute(slice)
188    }
189
190    /// Creates a character string from a mutable slice without checking.
191    ///
192    /// # Safety
193    ///
194    /// The caller has to make sure that `octets` is at most 255 octets
195    /// long. Otherwise, the behaviour is undefined.
196    unsafe fn from_slice_mut_unchecked(slice: &mut [u8]) -> &mut Self {
197        // SAFETY: Charstr has repr(transparent)
198        mem::transmute(slice)
199    }
200
201    /// Checks whether an octets slice contains a correct character string.
202    fn check_slice(slice: &[u8]) -> Result<(), CharStrError> {
203        if slice.len() > CharStr::MAX_LEN {
204            Err(CharStrError(()))
205        } else {
206            Ok(())
207        }
208    }
209}
210
211impl<Octs: ?Sized> CharStr<Octs> {
212    /// Creates a new empty builder for this character string type.
213    #[must_use]
214    pub fn builder() -> CharStrBuilder<Octs::Builder>
215    where
216        Octs: IntoBuilder,
217        Octs::Builder: EmptyBuilder,
218    {
219        CharStrBuilder::new()
220    }
221
222    /// Converts the character string into a builder.
223    pub fn into_builder(self) -> CharStrBuilder<Octs::Builder>
224    where
225        Octs: IntoBuilder + Sized,
226        <Octs as IntoBuilder>::Builder: AsRef<[u8]>,
227    {
228        unsafe {
229            CharStrBuilder::from_builder_unchecked(IntoBuilder::into_builder(
230                self.0,
231            ))
232        }
233    }
234
235    /// Converts the character string into its underlying octets value.
236    pub fn into_octets(self) -> Octs
237    where
238        Octs: Sized,
239    {
240        self.0
241    }
242
243    /// Returns a character string atop a slice of the content.
244    pub fn for_slice(&self) -> &CharStr<[u8]>
245    where
246        Octs: AsRef<[u8]>,
247    {
248        unsafe { CharStr::from_slice_unchecked(self.0.as_ref()) }
249    }
250
251    /// Returns a character string atop a mutable slice of the content.
252    pub fn for_slice_mut(&mut self) -> &mut CharStr<[u8]>
253    where
254        Octs: AsMut<[u8]>,
255    {
256        unsafe { CharStr::from_slice_mut_unchecked(self.0.as_mut()) }
257    }
258
259    /// Returns a reference to a slice of the character string’s data.
260    pub fn as_slice(&self) -> &[u8]
261    where
262        Octs: AsRef<[u8]>,
263    {
264        self.0.as_ref()
265    }
266
267    /// Returns a reference to a mutable slice of the character string’s data.
268    pub fn as_slice_mut(&mut self) -> &mut [u8]
269    where
270        Octs: AsMut<[u8]>,
271    {
272        self.0.as_mut()
273    }
274
275    /// Parses a character string from the beginning of a parser.
276    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
277        parser: &mut Parser<'a, Src>,
278    ) -> Result<Self, ParseError>
279    where
280        Octs: Sized,
281    {
282        let len = parser.parse_u8()? as usize;
283        parser
284            .parse_octets(len)
285            .map(|bytes| unsafe { Self::from_octets_unchecked(bytes) })
286            .map_err(Into::into)
287    }
288}
289
290impl CharStr<[u8]> {
291    /// Parses a character string from a parser atop a slice.
292    pub fn parse_slice<'a>(
293        parser: &mut Parser<'a, [u8]>,
294    ) -> Result<&'a Self, ParseError> {
295        let len = parser.parse_u8()? as usize;
296        parser
297            .parse_octets(len)
298            .map(|bytes| unsafe { Self::from_slice_unchecked(bytes) })
299            .map_err(Into::into)
300    }
301
302    /// Decodes the readable presentation and appends it to a builder.
303    ///
304    /// This is a helper function used both by the [`FromStr`] impl and
305    /// deserialization. It reads the string in unquoted form and appends its
306    /// wire format to the builder. Note that this does _not_ contain the
307    /// length octet. The function does, however, return the value of the
308    /// length octet.
309    ///
310    /// The function is here on `CharStr<[u8]>` so that it can be called
311    /// simply via [`CharStr::append_from_str`] without having to provide a
312    /// type argument.
313    ///
314    /// [`FromStr`]: std::str::FromStr
315    fn append_from_str(
316        s: &str,
317        target: &mut impl OctetsBuilder,
318    ) -> Result<u8, FromStrError> {
319        let mut len = 0u8;
320        let mut chars = s.chars();
321        while let Some(symbol) = Symbol::from_chars(&mut chars)? {
322            // We have the max length but there’s another character. Error!
323            if len == u8::MAX {
324                return Err(PresentationErrorEnum::LongString.into());
325            }
326            target
327                .append_slice(&[symbol.into_octet()?])
328                .map_err(Into::into)?;
329            len += 1;
330        }
331        Ok(len)
332    }
333}
334
335impl<Octs: AsRef<[u8]> + ?Sized> CharStr<Octs> {
336    /// Returns the length of the character string.
337    ///
338    /// This is the length of the content only, i.e., without the extra
339    /// length octet added for the wire format.
340    pub fn len(&self) -> usize {
341        self.as_slice().len()
342    }
343
344    /// Returns whether the character string is empty.
345    pub fn is_empty(&self) -> bool {
346        self.as_slice().is_empty()
347    }
348
349    /// Returns an iterator over the octets of the character string.
350    pub fn iter(&self) -> Iter {
351        Iter {
352            octets: self.as_slice(),
353        }
354    }
355}
356
357impl CharStr<[u8]> {
358    /// Skips over a character string at the beginning of a parser.
359    pub fn skip<Src: Octets + ?Sized>(
360        parser: &mut Parser<Src>,
361    ) -> Result<(), ParseError> {
362        let len = parser.parse_u8()?;
363        parser.advance(len.into()).map_err(Into::into)
364    }
365}
366
367impl<Octs: AsRef<[u8]> + ?Sized> CharStr<Octs> {
368    /// Returns the length of the wire format representation.
369    pub fn compose_len(&self) -> u16 {
370        u16::try_from(self.0.as_ref().len() + 1).expect("long charstr")
371    }
372
373    /// Appends the wire format representation to an octets builder.
374    pub fn compose<Target: OctetsBuilder + ?Sized>(
375        &self,
376        target: &mut Target,
377    ) -> Result<(), Target::AppendError> {
378        u8::try_from(self.0.as_ref().len())
379            .expect("long charstr")
380            .compose(target)?;
381        target.append_slice(self.0.as_ref())
382    }
383}
384
385impl<Octs> CharStr<Octs> {
386    /// Scans the presentation format from a scanner.
387    pub fn scan<S: Scanner<Octets = Octs>>(
388        scanner: &mut S,
389    ) -> Result<Self, S::Error> {
390        scanner.scan_charstr()
391    }
392}
393
394impl<Octs: AsRef<[u8]> + ?Sized> CharStr<Octs> {
395    /// Returns an object that formats in quoted presentation format.
396    ///
397    /// The returned object will display the content surrounded by double
398    /// quotes. It will escape double quotes, backslashes, and non-printable
399    /// octets only.
400    pub fn display_quoted(&self) -> DisplayQuoted {
401        DisplayQuoted(self.for_slice())
402    }
403
404    /// Returns an object that formats in unquoted presentation format.
405    ///
406    /// The returned object will display the content without explicit
407    /// delimiters and escapes space, double quotes, semicolons, backslashes,
408    /// and non-printable octets.
409    pub fn display_unquoted(&self) -> DisplayUnquoted {
410        DisplayUnquoted(self.for_slice())
411    }
412}
413
414//--- OctetsFrom
415
416impl<Octs, SrcOcts> OctetsFrom<CharStr<SrcOcts>> for CharStr<Octs>
417where
418    Octs: OctetsFrom<SrcOcts>,
419{
420    type Error = Octs::Error;
421
422    fn try_octets_from(
423        source: CharStr<SrcOcts>,
424    ) -> Result<Self, Self::Error> {
425        Octs::try_octets_from(source.0)
426            .map(|octets| unsafe { Self::from_octets_unchecked(octets) })
427    }
428}
429
430//--- FromStr
431
432impl<Octets> str::FromStr for CharStr<Octets>
433where
434    Octets: FromBuilder,
435    <Octets as FromBuilder>::Builder: OctetsBuilder
436        + FreezeBuilder<Octets = Octets>
437        + EmptyBuilder
438        + AsRef<[u8]>,
439{
440    type Err = FromStrError;
441
442    fn from_str(s: &str) -> Result<Self, Self::Err> {
443        // Most likely, everything is ASCII so take `s`’s length as capacity.
444        let mut builder =
445            CharStrBuilder::<<Octets as FromBuilder>::Builder>::with_capacity(
446                s.len(),
447            );
448        CharStr::append_from_str(s, &mut builder)?;
449        Ok(builder.finish())
450    }
451}
452
453//--- AsRef and AsMut
454//
455// No Borrow as character strings compare ignoring case.
456
457impl<Octets: AsRef<U> + ?Sized, U: ?Sized> AsRef<U> for CharStr<Octets> {
458    fn as_ref(&self) -> &U {
459        self.0.as_ref()
460    }
461}
462
463impl<Octets: AsMut<U> + ?Sized, U: ?Sized> AsMut<U> for CharStr<Octets> {
464    fn as_mut(&mut self) -> &mut U {
465        self.0.as_mut()
466    }
467}
468
469//--- PartialEq and Eq
470
471impl<T, U> PartialEq<U> for CharStr<T>
472where
473    T: AsRef<[u8]> + ?Sized,
474    U: AsRef<[u8]> + ?Sized,
475{
476    fn eq(&self, other: &U) -> bool {
477        self.as_slice().eq_ignore_ascii_case(other.as_ref())
478    }
479}
480
481impl<T: AsRef<[u8]> + ?Sized> Eq for CharStr<T> {}
482
483//--- PartialOrd, Ord, and CanonicalOrd
484
485impl<T, U> PartialOrd<U> for CharStr<T>
486where
487    T: AsRef<[u8]> + ?Sized,
488    U: AsRef<[u8]> + ?Sized,
489{
490    fn partial_cmp(&self, other: &U) -> Option<cmp::Ordering> {
491        self.0
492            .as_ref()
493            .iter()
494            .map(u8::to_ascii_lowercase)
495            .partial_cmp(other.as_ref().iter().map(u8::to_ascii_lowercase))
496    }
497}
498
499impl<T: AsRef<[u8]> + ?Sized> Ord for CharStr<T> {
500    fn cmp(&self, other: &Self) -> cmp::Ordering {
501        self.0
502            .as_ref()
503            .iter()
504            .map(u8::to_ascii_lowercase)
505            .cmp(other.0.as_ref().iter().map(u8::to_ascii_lowercase))
506    }
507}
508
509impl<T, U> CanonicalOrd<CharStr<U>> for CharStr<T>
510where
511    T: AsRef<[u8]> + ?Sized,
512    U: AsRef<[u8]> + ?Sized,
513{
514    fn canonical_cmp(&self, other: &CharStr<U>) -> cmp::Ordering {
515        match self.0.as_ref().len().cmp(&other.0.as_ref().len()) {
516            cmp::Ordering::Equal => {}
517            other => return other,
518        }
519        self.as_slice().cmp(other.as_slice())
520    }
521}
522
523//--- Hash
524
525impl<T: AsRef<[u8]> + ?Sized> hash::Hash for CharStr<T> {
526    fn hash<H: hash::Hasher>(&self, state: &mut H) {
527        self.0
528            .as_ref()
529            .iter()
530            .map(u8::to_ascii_lowercase)
531            .for_each(|ch| ch.hash(state))
532    }
533}
534
535//--- Display and Debug
536
537impl<T: AsRef<[u8]> + ?Sized> fmt::Display for CharStr<T> {
538    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
539        for &ch in self.0.as_ref() {
540            fmt::Display::fmt(&Symbol::display_from_octet(ch), f)?;
541        }
542        Ok(())
543    }
544}
545
546impl<T: AsRef<[u8]> + ?Sized> fmt::LowerHex for CharStr<T> {
547    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
548        for ch in self.0.as_ref() {
549            write!(f, "{:02x}", ch)?;
550        }
551        Ok(())
552    }
553}
554
555impl<T: AsRef<[u8]> + ?Sized> fmt::UpperHex for CharStr<T> {
556    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
557        for ch in self.0.as_ref() {
558            write!(f, "{:02X}", ch)?;
559        }
560        Ok(())
561    }
562}
563
564impl<T: AsRef<[u8]> + ?Sized> fmt::Debug for CharStr<T> {
565    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
566        f.debug_tuple("CharStr")
567            .field(&format_args!("{}", self))
568            .finish()
569    }
570}
571
572//--- IntoIterator
573
574impl<T: AsRef<[u8]>> IntoIterator for CharStr<T> {
575    type Item = u8;
576    type IntoIter = IntoIter<T>;
577
578    fn into_iter(self) -> Self::IntoIter {
579        IntoIter::new(self.0)
580    }
581}
582
583impl<'a, T: AsRef<[u8]> + ?Sized + 'a> IntoIterator for &'a CharStr<T> {
584    type Item = u8;
585    type IntoIter = Iter<'a>;
586
587    fn into_iter(self) -> Self::IntoIter {
588        Iter::new(self.0.as_ref())
589    }
590}
591
592//--- Serialize and Deserialize
593
594#[cfg(feature = "serde")]
595impl<T> serde::Serialize for CharStr<T>
596where
597    T: AsRef<[u8]> + SerializeOctets + ?Sized,
598{
599    fn serialize<S: serde::Serializer>(
600        &self,
601        serializer: S,
602    ) -> Result<S::Ok, S::Error> {
603        if serializer.is_human_readable() {
604            serializer.serialize_newtype_struct(
605                "CharStr",
606                &format_args!("{}", self),
607            )
608        } else {
609            serializer.serialize_newtype_struct(
610                "CharStr",
611                &self.0.as_serialized_octets(),
612            )
613        }
614    }
615}
616
617#[cfg(feature = "serde")]
618impl<'de, Octets> serde::Deserialize<'de> for CharStr<Octets>
619where
620    Octets: FromBuilder + DeserializeOctets<'de>,
621    <Octets as FromBuilder>::Builder: OctetsBuilder
622        + FreezeBuilder<Octets = Octets>
623        + EmptyBuilder
624        + AsRef<[u8]>,
625{
626    fn deserialize<D: serde::Deserializer<'de>>(
627        deserializer: D,
628    ) -> Result<Self, D::Error> {
629        use core::marker::PhantomData;
630        use core::str::FromStr;
631
632        struct InnerVisitor<'de, T: DeserializeOctets<'de>>(T::Visitor);
633
634        impl<'de, Octets> serde::de::Visitor<'de> for InnerVisitor<'de, Octets>
635        where
636            Octets: FromBuilder + DeserializeOctets<'de>,
637            <Octets as FromBuilder>::Builder: OctetsBuilder
638                + FreezeBuilder<Octets = Octets>
639                + EmptyBuilder
640                + AsRef<[u8]>,
641        {
642            type Value = CharStr<Octets>;
643
644            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
645                f.write_str("a character string")
646            }
647
648            fn visit_str<E: serde::de::Error>(
649                self,
650                v: &str,
651            ) -> Result<Self::Value, E> {
652                CharStr::from_str(v).map_err(E::custom)
653            }
654
655            fn visit_borrowed_bytes<E: serde::de::Error>(
656                self,
657                value: &'de [u8],
658            ) -> Result<Self::Value, E> {
659                self.0.visit_borrowed_bytes(value).and_then(|octets| {
660                    CharStr::from_octets(octets).map_err(E::custom)
661                })
662            }
663
664            #[cfg(feature = "std")]
665            fn visit_byte_buf<E: serde::de::Error>(
666                self,
667                value: std::vec::Vec<u8>,
668            ) -> Result<Self::Value, E> {
669                self.0.visit_byte_buf(value).and_then(|octets| {
670                    CharStr::from_octets(octets).map_err(E::custom)
671                })
672            }
673        }
674
675        struct NewtypeVisitor<T>(PhantomData<T>);
676
677        impl<'de, Octets> serde::de::Visitor<'de> for NewtypeVisitor<Octets>
678        where
679            Octets: FromBuilder + DeserializeOctets<'de>,
680            <Octets as FromBuilder>::Builder: OctetsBuilder
681                + FreezeBuilder<Octets = Octets>
682                + EmptyBuilder
683                + AsRef<[u8]>,
684        {
685            type Value = CharStr<Octets>;
686
687            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
688                f.write_str("a character string")
689            }
690
691            fn visit_newtype_struct<D: serde::Deserializer<'de>>(
692                self,
693                deserializer: D,
694            ) -> Result<Self::Value, D::Error> {
695                if deserializer.is_human_readable() {
696                    deserializer
697                        .deserialize_str(InnerVisitor(Octets::visitor()))
698                } else {
699                    Octets::deserialize_with_visitor(
700                        deserializer,
701                        InnerVisitor(Octets::visitor()),
702                    )
703                }
704            }
705        }
706
707        deserializer.deserialize_newtype_struct(
708            "CharStr",
709            NewtypeVisitor(PhantomData),
710        )
711    }
712}
713
714//------------ CharStrBuilder ------------------------------------------------
715
716/// A builder for a character string.
717///
718/// This type wraps an [`OctetsBuilder`] and in turn implements the
719/// [`OctetsBuilder`] trait, making sure that the content cannot grow beyond
720/// the 255 octet limit of a character string.
721#[derive(Clone)]
722pub struct CharStrBuilder<Builder>(Builder);
723
724impl<Builder: EmptyBuilder> CharStrBuilder<Builder> {
725    /// Creates a new empty builder with default capacity.
726    #[must_use]
727    pub fn new() -> Self {
728        CharStrBuilder(Builder::empty())
729    }
730
731    /// Creates a new empty builder with the given capacity.
732    #[must_use]
733    pub fn with_capacity(capacity: usize) -> Self {
734        CharStrBuilder(Builder::with_capacity(capacity))
735    }
736}
737
738impl<Builder: OctetsBuilder + AsRef<[u8]>> CharStrBuilder<Builder> {
739    /// Creates a character string builder from an octet sequence unchecked.
740    ///
741    /// Since the buffer may already be longer than it is allowed to be, this
742    /// is unsafe.
743    unsafe fn from_builder_unchecked(builder: Builder) -> Self {
744        CharStrBuilder(builder)
745    }
746
747    /// Creates a character string builder from an octet sequence.
748    ///
749    /// If the octet sequence is longer than 255 octets, an error is
750    /// returned.
751    pub fn from_builder(builder: Builder) -> Result<Self, CharStrError> {
752        if builder.as_ref().len() > CharStr::MAX_LEN {
753            Err(CharStrError(()))
754        } else {
755            Ok(unsafe { Self::from_builder_unchecked(builder) })
756        }
757    }
758}
759
760#[cfg(feature = "std")]
761impl CharStrBuilder<Vec<u8>> {
762    /// Creates a new empty characater string builder atop an octets vec.
763    #[must_use]
764    pub fn new_vec() -> Self {
765        Self::new()
766    }
767
768    /// Creates a new empty builder atop an octets vec with a given capacity.
769    #[must_use]
770    pub fn vec_with_capacity(capacity: usize) -> Self {
771        Self::with_capacity(capacity)
772    }
773}
774
775#[cfg(feature = "bytes")]
776impl CharStrBuilder<BytesMut> {
777    /// Creates a new empty builder for a bytes value.
778    pub fn new_bytes() -> Self {
779        Self::new()
780    }
781
782    /// Creates a new empty builder for a bytes value with a given capacity.
783    pub fn bytes_with_capacity(capacity: usize) -> Self {
784        Self::with_capacity(capacity)
785    }
786}
787
788impl<Builder> CharStrBuilder<Builder> {
789    /// Returns an octet slice of the string assembled so far.
790    pub fn as_slice(&self) -> &[u8]
791    where
792        Builder: AsRef<[u8]>,
793    {
794        self.0.as_ref()
795    }
796
797    /// Converts the builder into an imutable character string.
798    pub fn finish(self) -> CharStr<Builder::Octets>
799    where
800        Builder: FreezeBuilder,
801    {
802        unsafe { CharStr::from_octets_unchecked(self.0.freeze()) }
803    }
804}
805
806impl<Builder: AsRef<[u8]>> CharStrBuilder<Builder> {
807    /// Returns the length of the assembled character string.
808    ///
809    /// This is the length of the content only, i.e., without the extra
810    /// length octet added for the wire format.
811    pub fn len(&self) -> usize {
812        self.as_slice().len()
813    }
814
815    /// Returns whether the character string is empty.
816    pub fn is_empty(&self) -> bool {
817        self.as_slice().is_empty()
818    }
819}
820
821//--- Default
822
823impl<Builder: EmptyBuilder> Default for CharStrBuilder<Builder> {
824    fn default() -> Self {
825        Self::new()
826    }
827}
828
829//--- OctetsBuilder and Truncate
830
831impl<Builder> OctetsBuilder for CharStrBuilder<Builder>
832where
833    Builder: OctetsBuilder + AsRef<[u8]>,
834{
835    type AppendError = ShortBuf;
836
837    fn append_slice(
838        &mut self,
839        slice: &[u8],
840    ) -> Result<(), Self::AppendError> {
841        if self.0.as_ref().len() + slice.len() > CharStr::MAX_LEN {
842            return Err(ShortBuf);
843        }
844        self.0.append_slice(slice).map_err(Into::into)
845    }
846}
847
848impl<Builder: Truncate> Truncate for CharStrBuilder<Builder> {
849    fn truncate(&mut self, len: usize) {
850        self.0.truncate(len)
851    }
852}
853
854//--- AsRef and AsMut
855
856impl<Builder: AsRef<[u8]>> AsRef<[u8]> for CharStrBuilder<Builder> {
857    fn as_ref(&self) -> &[u8] {
858        self.0.as_ref()
859    }
860}
861
862impl<Builder: AsMut<[u8]>> AsMut<[u8]> for CharStrBuilder<Builder> {
863    fn as_mut(&mut self) -> &mut [u8] {
864        self.0.as_mut()
865    }
866}
867
868//------------ IntoIter ------------------------------------------------------
869
870/// The iterator type for `IntoIterator` for a character string itself.
871pub struct IntoIter<T> {
872    octets: T,
873    len: usize,
874    pos: usize,
875}
876
877impl<T: AsRef<[u8]>> IntoIter<T> {
878    pub(crate) fn new(octets: T) -> Self {
879        IntoIter {
880            len: octets.as_ref().len(),
881            octets,
882            pos: 0,
883        }
884    }
885}
886
887impl<T: AsRef<[u8]>> Iterator for IntoIter<T> {
888    type Item = u8;
889
890    fn next(&mut self) -> Option<Self::Item> {
891        if self.pos == self.len {
892            None
893        } else {
894            let res = self.octets.as_ref()[self.pos];
895            self.pos += 1;
896            Some(res)
897        }
898    }
899}
900
901//------------ Iter ----------------------------------------------------------
902
903/// The iterator type for `IntoIterator` for a reference to a character string.
904pub struct Iter<'a> {
905    octets: &'a [u8],
906}
907
908impl<'a> Iter<'a> {
909    pub(crate) fn new(octets: &'a [u8]) -> Self {
910        Iter { octets }
911    }
912}
913
914impl Iterator for Iter<'_> {
915    type Item = u8;
916
917    fn next(&mut self) -> Option<Self::Item> {
918        let (res, octets) = self.octets.split_first()?;
919        self.octets = octets;
920        Some(*res)
921    }
922}
923
924//------------ DisplayQuoted -------------------------------------------------
925
926/// Helper struct for displaying in quoted presentation format.
927///
928/// A value of this type can be obtained via `CharStr::display_quoted`.
929#[derive(Clone, Copy, Debug)]
930pub struct DisplayQuoted<'a>(&'a CharStr<[u8]>);
931
932impl fmt::Display for DisplayQuoted<'_> {
933    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
934        f.write_str("\"")?;
935        for &ch in self.0.as_ref() {
936            fmt::Display::fmt(&Symbol::quoted_from_octet(ch), f)?;
937        }
938        f.write_str("\"")
939    }
940}
941
942//------------ DisplayUnquoted -----------------------------------------------
943
944/// Helper struct for displaying in serialization format.
945///
946/// A value of this type can be obtained via `CharStr::display_serialized`.
947#[derive(Clone, Copy, Debug)]
948pub struct DisplayUnquoted<'a>(&'a CharStr<[u8]>);
949
950impl fmt::Display for DisplayUnquoted<'_> {
951    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
952        for &ch in self.0.as_ref() {
953            fmt::Display::fmt(&Symbol::from_octet(ch), f)?;
954        }
955        Ok(())
956    }
957}
958
959//------------ DeserializeCharStrSeed ----------------------------------------
960
961/// A helper type to deserialize a character string into an octets builder.
962///
963/// This type can be used when deserializing a type that keeps a character
964/// string in wire format as part of a longer octets sequence. It uses the
965/// `DeserializeSeed` trait to append the content to an octets builder and
966/// returns `()` as the actual value.
967#[cfg(feature = "serde")]
968pub struct DeserializeCharStrSeed<'a, Builder> {
969    builder: &'a mut Builder,
970}
971
972#[cfg(feature = "serde")]
973impl<'a, Builder> DeserializeCharStrSeed<'a, Builder> {
974    /// Creates a new value wrapping a ref mut to the builder to append to.
975    pub fn new(builder: &'a mut Builder) -> Self {
976        Self { builder }
977    }
978}
979
980#[cfg(feature = "serde")]
981impl<'de, Builder> serde::de::DeserializeSeed<'de>
982    for DeserializeCharStrSeed<'_, Builder>
983where
984    Builder: OctetsBuilder + AsMut<[u8]>,
985{
986    // We don’t return anything but append the value to `self.builder`.
987    type Value = ();
988
989    fn deserialize<D: serde::de::Deserializer<'de>>(
990        self,
991        deserializer: D,
992    ) -> Result<Self::Value, D::Error> {
993        // Here’s how this all hangs together: CharStr serializes as a
994        // newtype, so we have a visitor for that. It dispatches to an
995        // inner vistor that differs for binary and human-readable formats.
996        // All of them just wrap around the `self` we’ve been given.
997
998        // Visitor for the outer newtype
999        struct NewtypeVisitor<'a, Builder>(
1000            DeserializeCharStrSeed<'a, Builder>,
1001        );
1002
1003        impl<'de, Builder> serde::de::Visitor<'de> for NewtypeVisitor<'_, Builder>
1004        where
1005            Builder: OctetsBuilder + AsMut<[u8]>,
1006        {
1007            type Value = ();
1008
1009            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
1010                f.write_str("a character string")
1011            }
1012
1013            fn visit_newtype_struct<D: serde::Deserializer<'de>>(
1014                self,
1015                deserializer: D,
1016            ) -> Result<Self::Value, D::Error> {
1017                if deserializer.is_human_readable() {
1018                    deserializer.deserialize_str(ReadableVisitor(self.0))
1019                } else {
1020                    deserializer.deserialize_bytes(BinaryVisitor(self.0))
1021                }
1022            }
1023        }
1024
1025        // Visitor for a human readable inner value
1026        struct ReadableVisitor<'a, Builder>(
1027            DeserializeCharStrSeed<'a, Builder>,
1028        );
1029
1030        impl<Builder> serde::de::Visitor<'_> for ReadableVisitor<'_, Builder>
1031        where
1032            Builder: OctetsBuilder + AsMut<[u8]>,
1033        {
1034            type Value = ();
1035
1036            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
1037                f.write_str("a character string")
1038            }
1039
1040            fn visit_str<E: serde::de::Error>(
1041                self,
1042                value: &str,
1043            ) -> Result<Self::Value, E> {
1044                // Append a placeholder for the length octet, remember its
1045                // index.
1046                let start = self.0.builder.as_mut().len();
1047                self.0
1048                    .builder
1049                    .append_slice(&[0])
1050                    .map_err(|_| E::custom(ShortBuf))?;
1051
1052                // Decode and append the string.
1053                let len = CharStr::append_from_str(value, self.0.builder)
1054                    .map_err(E::custom)?;
1055
1056                // Update the length octet.
1057                self.0.builder.as_mut()[start] = len;
1058                Ok(())
1059            }
1060        }
1061
1062        // Visitor for a binary inner value
1063        struct BinaryVisitor<'a, Builder>(
1064            DeserializeCharStrSeed<'a, Builder>,
1065        );
1066
1067        impl<Builder> serde::de::Visitor<'_> for BinaryVisitor<'_, Builder>
1068        where
1069            Builder: OctetsBuilder,
1070        {
1071            type Value = ();
1072
1073            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
1074                f.write_str("a character string")
1075            }
1076
1077            fn visit_bytes<E: serde::de::Error>(
1078                self,
1079                value: &[u8],
1080            ) -> Result<Self::Value, E> {
1081                CharStr::from_slice(value)
1082                    .map_err(E::custom)?
1083                    .compose(self.0.builder)
1084                    .map_err(|_| E::custom(ShortBuf))
1085            }
1086        }
1087
1088        deserializer
1089            .deserialize_newtype_struct("CharStr", NewtypeVisitor(self))
1090    }
1091}
1092
1093//============ Error Types ===================================================
1094
1095//------------ CharStrError --------------------------------------------------
1096
1097/// A byte sequence does not represent a valid character string.
1098///
1099/// This can only mean that the sequence is longer than 255 bytes.
1100#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
1101pub struct CharStrError(());
1102
1103impl fmt::Display for CharStrError {
1104    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1105        f.write_str("long character string")
1106    }
1107}
1108
1109#[cfg(feature = "std")]
1110impl std::error::Error for CharStrError {}
1111
1112//------------ FromStrError --------------------------------------------------
1113
1114/// An error happened when converting a Rust string to a DNS character string.
1115#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1116pub enum FromStrError {
1117    /// The string content was wrongly formatted.
1118    Presentation(PresentationError),
1119
1120    /// The octet builder’s buffer was too short for the data.
1121    ShortBuf,
1122}
1123
1124//--- From
1125
1126impl<T: Into<PresentationError>> From<T> for FromStrError {
1127    fn from(err: T) -> Self {
1128        Self::Presentation(err.into())
1129    }
1130}
1131
1132impl From<ShortBuf> for FromStrError {
1133    fn from(_: ShortBuf) -> FromStrError {
1134        FromStrError::ShortBuf
1135    }
1136}
1137
1138//--- Display and Error
1139
1140impl fmt::Display for FromStrError {
1141    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1142        match *self {
1143            FromStrError::Presentation(ref err) => err.fmt(f),
1144            FromStrError::ShortBuf => ShortBuf.fmt(f),
1145        }
1146    }
1147}
1148
1149#[cfg(feature = "std")]
1150impl std::error::Error for FromStrError {}
1151
1152//------------ PresentationError ---------------------------------------------
1153
1154/// An illegal presentation format was encountered.
1155#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1156pub struct PresentationError(PresentationErrorEnum);
1157
1158#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1159enum PresentationErrorEnum {
1160    /// A character string has more than 255 octets.
1161    LongString,
1162
1163    SymbolChars(SymbolCharsError),
1164
1165    /// An illegal character was encountered.
1166    ///
1167    /// Only printable ASCII characters are allowed.
1168    BadSymbol(BadSymbol),
1169}
1170
1171//--- From
1172
1173impl From<SymbolCharsError> for PresentationError {
1174    fn from(err: SymbolCharsError) -> Self {
1175        Self(PresentationErrorEnum::SymbolChars(err))
1176    }
1177}
1178
1179impl From<BadSymbol> for PresentationError {
1180    fn from(err: BadSymbol) -> Self {
1181        Self(PresentationErrorEnum::BadSymbol(err))
1182    }
1183}
1184
1185impl From<PresentationErrorEnum> for PresentationError {
1186    fn from(err: PresentationErrorEnum) -> Self {
1187        Self(err)
1188    }
1189}
1190
1191//--- Display and Error
1192
1193impl fmt::Display for PresentationError {
1194    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1195        match self.0 {
1196            PresentationErrorEnum::LongString => {
1197                f.write_str("character string with more than 255 octets")
1198            }
1199            PresentationErrorEnum::SymbolChars(ref err) => err.fmt(f),
1200            PresentationErrorEnum::BadSymbol(ref err) => err.fmt(f),
1201        }
1202    }
1203}
1204
1205#[cfg(feature = "std")]
1206impl std::error::Error for PresentationError {}
1207
1208//============ Testing =======================================================
1209
1210#[cfg(test)]
1211#[cfg(feature = "std")]
1212mod test {
1213    use super::*;
1214    use octseq::builder::infallible;
1215
1216    type CharStrRef<'a> = CharStr<&'a [u8]>;
1217
1218    #[test]
1219    fn from_slice() {
1220        assert_eq!(
1221            CharStr::from_slice(b"01234").unwrap().as_slice(),
1222            b"01234"
1223        );
1224        assert_eq!(CharStr::from_slice(b"").unwrap().as_slice(), b"");
1225        assert!(CharStr::from_slice(&vec![0; 255]).is_ok());
1226        assert!(CharStr::from_slice(&vec![0; 256]).is_err());
1227    }
1228
1229    #[test]
1230    fn from_octets() {
1231        assert_eq!(
1232            CharStr::from_octets("01234").unwrap().as_slice(),
1233            b"01234"
1234        );
1235        assert_eq!(CharStr::from_octets("").unwrap().as_slice(), b"");
1236        assert!(CharStr::from_octets(vec![0; 255]).is_ok());
1237        assert!(CharStr::from_octets(vec![0; 256]).is_err());
1238    }
1239
1240    #[test]
1241    fn from_str() {
1242        use std::str::{from_utf8, FromStr};
1243
1244        type Cs = CharStr<Vec<u8>>;
1245
1246        assert_eq!(Cs::from_str("foo").unwrap().as_slice(), b"foo");
1247        assert_eq!(Cs::from_str("f\\oo").unwrap().as_slice(), b"foo");
1248        assert_eq!(Cs::from_str("foo\\112").unwrap().as_slice(), b"foo\x70");
1249        assert_eq!(
1250            Cs::from_str("\"foo\\\"2\"").unwrap().as_slice(),
1251            b"\"foo\"2\""
1252        );
1253        assert_eq!(Cs::from_str("06 dii").unwrap().as_slice(), b"06 dii");
1254        assert!(Cs::from_str("0\\").is_err());
1255        assert!(Cs::from_str("0\\2").is_err());
1256        assert!(Cs::from_str("0\\2a").is_err());
1257        assert!(Cs::from_str("ö").is_err());
1258        assert!(Cs::from_str("\x06").is_err());
1259        assert!(Cs::from_str(from_utf8(&[b'a'; 256]).unwrap()).is_err());
1260    }
1261
1262    #[test]
1263    fn parse() {
1264        let mut parser = Parser::from_static(b"12\x03foo\x02bartail");
1265        parser.advance(2).unwrap();
1266        let foo = CharStrRef::parse(&mut parser).unwrap();
1267        let bar = CharStrRef::parse(&mut parser).unwrap();
1268        assert_eq!(foo.as_slice(), b"foo");
1269        assert_eq!(bar.as_slice(), b"ba");
1270        assert_eq!(parser.peek_all(), b"rtail");
1271
1272        assert!(
1273            CharStrRef::parse(&mut Parser::from_static(b"\x04foo")).is_err(),
1274        )
1275    }
1276
1277    #[test]
1278    fn compose() {
1279        let mut target = Vec::new();
1280        let val = CharStr::from_slice(b"foo").unwrap();
1281        infallible(val.compose(&mut target));
1282        assert_eq!(target, b"\x03foo".as_ref());
1283
1284        let mut target = Vec::new();
1285        let val = CharStr::from_slice(b"").unwrap();
1286        infallible(val.compose(&mut target));
1287        assert_eq!(target, &b"\x00"[..]);
1288    }
1289
1290    fn are_eq(l: &[u8], r: &[u8]) -> bool {
1291        CharStr::from_slice(l).unwrap() == CharStr::from_slice(r).unwrap()
1292    }
1293
1294    #[test]
1295    fn eq() {
1296        assert!(are_eq(b"abc", b"abc"));
1297        assert!(!are_eq(b"abc", b"def"));
1298        assert!(!are_eq(b"abc", b"ab"));
1299        assert!(!are_eq(b"abc", b"abcd"));
1300        assert!(are_eq(b"ABC", b"abc"));
1301        assert!(!are_eq(b"ABC", b"def"));
1302        assert!(!are_eq(b"ABC", b"ab"));
1303        assert!(!are_eq(b"ABC", b"abcd"));
1304        assert!(are_eq(b"", b""));
1305        assert!(!are_eq(b"", b"A"));
1306    }
1307
1308    fn is_ord(l: &[u8], r: &[u8], order: cmp::Ordering) {
1309        assert_eq!(
1310            CharStr::from_slice(l)
1311                .unwrap()
1312                .cmp(CharStr::from_slice(r).unwrap()),
1313            order
1314        )
1315    }
1316
1317    #[test]
1318    fn ord() {
1319        use std::cmp::Ordering::*;
1320
1321        is_ord(b"abc", b"ABC", Equal);
1322        is_ord(b"abc", b"a", Greater);
1323        is_ord(b"abc", b"A", Greater);
1324        is_ord(b"a", b"BC", Less);
1325    }
1326
1327    #[test]
1328    fn append_slice() {
1329        let mut o = CharStrBuilder::new_vec();
1330        o.append_slice(b"foo").unwrap();
1331        assert_eq!(o.finish().as_slice(), b"foo");
1332
1333        let mut o = CharStrBuilder::from_builder(vec![0; 254]).unwrap();
1334        o.append_slice(b"f").unwrap();
1335        assert_eq!(o.len(), 255);
1336        assert!(o.append_slice(b"f").is_err());
1337
1338        let mut o =
1339            CharStrBuilder::from_builder(vec![b'f', b'o', b'o']).unwrap();
1340        o.append_slice(b"bar").unwrap();
1341        assert_eq!(o.as_ref(), b"foobar");
1342        assert!(o.append_slice(&[0u8; 250][..]).is_err());
1343        o.append_slice(&[0u8; 249][..]).unwrap();
1344        assert_eq!(o.len(), 255);
1345    }
1346
1347    #[cfg(feature = "serde")]
1348    #[test]
1349    fn ser_de() {
1350        use serde_test::{assert_tokens, Configure, Token};
1351
1352        assert_tokens(
1353            &CharStr::from_octets(Vec::from(b"fo\x12 bar".as_ref()))
1354                .unwrap()
1355                .compact(),
1356            &[
1357                Token::NewtypeStruct { name: "CharStr" },
1358                Token::ByteBuf(b"fo\x12 bar"),
1359            ],
1360        );
1361
1362        assert_tokens(
1363            &CharStr::from_octets(Vec::from(b"fo\x12 bar".as_ref()))
1364                .unwrap()
1365                .readable(),
1366            &[
1367                Token::NewtypeStruct { name: "CharStr" },
1368                Token::Str("fo\\018 bar"),
1369            ],
1370        );
1371    }
1372
1373    #[cfg(feature = "serde")]
1374    #[test]
1375    fn cycle_serde_json() {
1376        let json = r#""foo bar\" \\018;""#;
1377
1378        let cstr: CharStr<Vec<u8>> = serde_json::from_str(json).unwrap();
1379        assert_eq!(cstr.as_slice(), b"foo bar\" \x12;");
1380        assert_eq!(serde_json::to_string(&cstr).unwrap(), json);
1381    }
1382
1383    #[test]
1384    fn display() {
1385        fn cmp(input: &[u8], normal: &str, quoted: &str, unquoted: &str) {
1386            let s = CharStr::from_octets(input).unwrap();
1387            assert_eq!(format!("{}", s), normal);
1388            assert_eq!(format!("{}", s.display_quoted()), quoted);
1389            assert_eq!(format!("{}", s.display_unquoted()), unquoted);
1390        }
1391
1392        cmp(br#"foo"#, r#"foo"#, r#""foo""#, r#"foo"#);
1393        cmp(br#"f oo"#, r#"f oo"#, r#""f oo""#, r#"f\ oo"#);
1394        cmp(br#"f"oo"#, r#"f"oo"#, r#""f\"oo""#, r#"f\"oo"#);
1395        cmp(br#"f\oo"#, r#"f\\oo"#, r#""f\\oo""#, r#"f\\oo"#);
1396        cmp(br#"f;oo"#, r#"f;oo"#, r#""f;oo""#, r#"f\;oo"#);
1397        cmp(b"f\noo", r#"f\010oo"#, r#""f\010oo""#, r#"f\010oo"#);
1398    }
1399}