1use 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, 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#[derive(Clone)]
56pub struct CharStr<Octs: ?Sized>(Octs);
57
58impl CharStr<()> {
59 pub const MAX_LEN: usize = 255;
61}
62
63impl<Octs: ?Sized> CharStr<Octs> {
64 #[must_use]
66 pub fn empty() -> Self
67 where
68 Octs: From<&'static [u8]>,
69 {
70 CharStr(b"".as_ref().into())
71 }
72
73 pub fn from_octets(octets: Octs) -> Result<Self, CharStrError>
78 where
79 Octs: AsRef<[u8]> + Sized,
80 {
81 CharStr::check_slice(octets.as_ref())?;
82 Ok(unsafe { Self::from_octets_unchecked(octets) })
83 }
84
85 pub unsafe fn from_octets_unchecked(octets: Octs) -> Self
92 where
93 Octs: Sized,
94 {
95 CharStr(octets)
96 }
97}
98
99impl CharStr<[u8]> {
100 pub fn from_slice(slice: &[u8]) -> Result<&Self, CharStrError> {
102 Self::check_slice(slice)?;
103 Ok(unsafe { Self::from_slice_unchecked(slice) })
104 }
105
106 #[must_use]
108 pub fn empty_slice() -> &'static Self {
109 unsafe { Self::from_slice_unchecked(b"".as_ref()) }
110 }
111
112 #[must_use]
119 pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
120 &*(slice as *const [u8] as *const Self)
121 }
122
123 unsafe fn from_slice_mut_unchecked(slice: &mut [u8]) -> &mut Self {
130 &mut *(slice as *mut [u8] as *mut Self)
131 }
132
133 fn check_slice(slice: &[u8]) -> Result<(), CharStrError> {
135 if slice.len() > CharStr::MAX_LEN {
136 Err(CharStrError)
137 } else {
138 Ok(())
139 }
140 }
141}
142
143impl<Octs: ?Sized> CharStr<Octs> {
144 #[must_use]
146 pub fn builder() -> CharStrBuilder<Octs::Builder>
147 where
148 Octs: IntoBuilder,
149 Octs::Builder: EmptyBuilder,
150 {
151 CharStrBuilder::new()
152 }
153
154 pub fn into_builder(self) -> CharStrBuilder<Octs::Builder>
156 where
157 Octs: IntoBuilder + Sized,
158 <Octs as IntoBuilder>::Builder: AsRef<[u8]>,
159 {
160 unsafe {
161 CharStrBuilder::from_builder_unchecked(IntoBuilder::into_builder(
162 self.0,
163 ))
164 }
165 }
166
167 pub fn into_octets(self) -> Octs
169 where
170 Octs: Sized,
171 {
172 self.0
173 }
174
175 pub fn for_slice(&self) -> &CharStr<[u8]>
177 where
178 Octs: AsRef<[u8]>,
179 {
180 unsafe { CharStr::from_slice_unchecked(self.0.as_ref()) }
181 }
182
183 pub fn for_slice_mut(&mut self) -> &mut CharStr<[u8]>
185 where
186 Octs: AsMut<[u8]>,
187 {
188 unsafe { CharStr::from_slice_mut_unchecked(self.0.as_mut()) }
189 }
190
191 pub fn as_slice(&self) -> &[u8]
193 where
194 Octs: AsRef<[u8]>,
195 {
196 self.0.as_ref()
197 }
198
199 pub fn as_slice_mut(&mut self) -> &mut [u8]
201 where
202 Octs: AsMut<[u8]>,
203 {
204 self.0.as_mut()
205 }
206
207 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
209 parser: &mut Parser<'a, Src>,
210 ) -> Result<Self, ParseError>
211 where
212 Octs: Sized,
213 {
214 let len = parser.parse_u8()? as usize;
215 parser
216 .parse_octets(len)
217 .map(|bytes| unsafe { Self::from_octets_unchecked(bytes) })
218 .map_err(Into::into)
219 }
220}
221
222impl<Octs: AsRef<[u8]> + ?Sized> CharStr<Octs> {
223 pub fn len(&self) -> usize {
228 self.as_slice().len()
229 }
230
231 pub fn is_empty(&self) -> bool {
233 self.as_slice().is_empty()
234 }
235
236 pub fn iter(&self) -> Iter {
238 Iter {
239 octets: self.as_slice(),
240 }
241 }
242}
243
244impl CharStr<[u8]> {
245 pub fn skip<Src: Octets + ?Sized>(
247 parser: &mut Parser<Src>,
248 ) -> Result<(), ParseError> {
249 let len = parser.parse_u8()?;
250 parser.advance(len.into()).map_err(Into::into)
251 }
252}
253
254impl<Octs: AsRef<[u8]> + ?Sized> CharStr<Octs> {
255 pub fn compose_len(&self) -> u16 {
257 u16::try_from(self.0.as_ref().len() + 1).expect("long charstr")
258 }
259
260 pub fn compose<Target: OctetsBuilder + ?Sized>(
262 &self,
263 target: &mut Target,
264 ) -> Result<(), Target::AppendError> {
265 u8::try_from(self.0.as_ref().len())
266 .expect("long charstr")
267 .compose(target)?;
268 target.append_slice(self.0.as_ref())
269 }
270}
271
272impl<Octets> CharStr<Octets> {
273 pub fn scan<S: Scanner<Octets = Octets>>(
275 scanner: &mut S,
276 ) -> Result<Self, S::Error> {
277 scanner.scan_charstr()
278 }
279}
280
281impl<Octs, SrcOcts> OctetsFrom<CharStr<SrcOcts>> for CharStr<Octs>
284where
285 Octs: OctetsFrom<SrcOcts>,
286{
287 type Error = Octs::Error;
288
289 fn try_octets_from(
290 source: CharStr<SrcOcts>,
291 ) -> Result<Self, Self::Error> {
292 Octs::try_octets_from(source.0)
293 .map(|octets| unsafe { Self::from_octets_unchecked(octets) })
294 }
295}
296
297impl<Octets> str::FromStr for CharStr<Octets>
300where
301 Octets: FromBuilder,
302 <Octets as FromBuilder>::Builder: OctetsBuilder
303 + FreezeBuilder<Octets = Octets>
304 + EmptyBuilder
305 + AsRef<[u8]>,
306{
307 type Err = FromStrError;
308
309 fn from_str(s: &str) -> Result<Self, Self::Err> {
310 let mut builder =
312 CharStrBuilder::<<Octets as FromBuilder>::Builder>::with_capacity(
313 s.len(),
314 );
315 let mut chars = s.chars();
316 while let Some(symbol) = Symbol::from_chars(&mut chars)? {
317 if builder.len() == CharStr::MAX_LEN {
318 return Err(FromStrError::LongString);
319 }
320 builder.append_slice(&[symbol.into_octet()?])?
321 }
322 Ok(builder.finish())
323 }
324}
325
326impl<Octets: AsRef<U> + ?Sized, U: ?Sized> AsRef<U> for CharStr<Octets> {
331 fn as_ref(&self) -> &U {
332 self.0.as_ref()
333 }
334}
335
336impl<Octets: AsMut<U> + ?Sized, U: ?Sized> AsMut<U> for CharStr<Octets> {
337 fn as_mut(&mut self) -> &mut U {
338 self.0.as_mut()
339 }
340}
341
342impl<T, U> PartialEq<U> for CharStr<T>
345where
346 T: AsRef<[u8]> + ?Sized,
347 U: AsRef<[u8]> + ?Sized,
348{
349 fn eq(&self, other: &U) -> bool {
350 self.as_slice().eq_ignore_ascii_case(other.as_ref())
351 }
352}
353
354impl<T: AsRef<[u8]> + ?Sized> Eq for CharStr<T> {}
355
356impl<T, U> PartialOrd<U> for CharStr<T>
359where
360 T: AsRef<[u8]> + ?Sized,
361 U: AsRef<[u8]> + ?Sized,
362{
363 fn partial_cmp(&self, other: &U) -> Option<cmp::Ordering> {
364 self.0
365 .as_ref()
366 .iter()
367 .map(u8::to_ascii_lowercase)
368 .partial_cmp(other.as_ref().iter().map(u8::to_ascii_lowercase))
369 }
370}
371
372impl<T: AsRef<[u8]> + ?Sized> Ord for CharStr<T> {
373 fn cmp(&self, other: &Self) -> cmp::Ordering {
374 self.0
375 .as_ref()
376 .iter()
377 .map(u8::to_ascii_lowercase)
378 .cmp(other.0.as_ref().iter().map(u8::to_ascii_lowercase))
379 }
380}
381
382impl<T, U> CanonicalOrd<CharStr<U>> for CharStr<T>
383where
384 T: AsRef<[u8]> + ?Sized,
385 U: AsRef<[u8]> + ?Sized,
386{
387 fn canonical_cmp(&self, other: &CharStr<U>) -> cmp::Ordering {
388 match self.0.as_ref().len().cmp(&other.0.as_ref().len()) {
389 cmp::Ordering::Equal => {}
390 other => return other,
391 }
392 self.as_slice().cmp(other.as_slice())
393 }
394}
395
396impl<T: AsRef<[u8]> + ?Sized> hash::Hash for CharStr<T> {
399 fn hash<H: hash::Hasher>(&self, state: &mut H) {
400 self.0
401 .as_ref()
402 .iter()
403 .map(u8::to_ascii_lowercase)
404 .for_each(|ch| ch.hash(state))
405 }
406}
407
408impl<T: AsRef<[u8]> + ?Sized> fmt::Display for CharStr<T> {
411 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412 for &ch in self.0.as_ref() {
413 fmt::Display::fmt(&Symbol::from_octet(ch), f)?;
414 }
415 Ok(())
416 }
417}
418
419impl<T: AsRef<[u8]> + ?Sized> fmt::LowerHex for CharStr<T> {
420 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
421 for ch in self.0.as_ref() {
422 write!(f, "{:02x}", ch)?;
423 }
424 Ok(())
425 }
426}
427
428impl<T: AsRef<[u8]> + ?Sized> fmt::UpperHex for CharStr<T> {
429 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
430 for ch in self.0.as_ref() {
431 write!(f, "{:02X}", ch)?;
432 }
433 Ok(())
434 }
435}
436
437impl<T: AsRef<[u8]> + ?Sized> fmt::Debug for CharStr<T> {
438 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
439 f.debug_tuple("CharStr")
440 .field(&format_args!("{}", self))
441 .finish()
442 }
443}
444
445impl<T: AsRef<[u8]>> IntoIterator for CharStr<T> {
448 type Item = u8;
449 type IntoIter = IntoIter<T>;
450
451 fn into_iter(self) -> Self::IntoIter {
452 IntoIter::new(self.0)
453 }
454}
455
456impl<'a, T: AsRef<[u8]> + ?Sized + 'a> IntoIterator for &'a CharStr<T> {
457 type Item = u8;
458 type IntoIter = Iter<'a>;
459
460 fn into_iter(self) -> Self::IntoIter {
461 Iter::new(self.0.as_ref())
462 }
463}
464
465#[cfg(feature = "serde")]
468impl<T> serde::Serialize for CharStr<T>
469where
470 T: AsRef<[u8]> + SerializeOctets + ?Sized,
471{
472 fn serialize<S: serde::Serializer>(
473 &self,
474 serializer: S,
475 ) -> Result<S::Ok, S::Error> {
476 if serializer.is_human_readable() {
477 serializer.serialize_newtype_struct(
478 "CharStr",
479 &format_args!("{}", self),
480 )
481 } else {
482 serializer.serialize_newtype_struct(
483 "CharStr",
484 &self.0.as_serialized_octets(),
485 )
486 }
487 }
488}
489
490#[cfg(feature = "serde")]
491impl<'de, Octets> serde::Deserialize<'de> for CharStr<Octets>
492where
493 Octets: FromBuilder + DeserializeOctets<'de>,
494 <Octets as FromBuilder>::Builder: OctetsBuilder
495 + FreezeBuilder<Octets = Octets>
496 + EmptyBuilder
497 + AsRef<[u8]>,
498{
499 fn deserialize<D: serde::Deserializer<'de>>(
500 deserializer: D,
501 ) -> Result<Self, D::Error> {
502 use core::marker::PhantomData;
503 use core::str::FromStr;
504
505 struct InnerVisitor<'de, T: DeserializeOctets<'de>>(T::Visitor);
506
507 impl<'de, Octets> serde::de::Visitor<'de> for InnerVisitor<'de, Octets>
508 where
509 Octets: FromBuilder + DeserializeOctets<'de>,
510 <Octets as FromBuilder>::Builder: OctetsBuilder
511 + FreezeBuilder<Octets = Octets>
512 + EmptyBuilder
513 + AsRef<[u8]>,
514 {
515 type Value = CharStr<Octets>;
516
517 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
518 f.write_str("a character string")
519 }
520
521 fn visit_str<E: serde::de::Error>(
522 self,
523 v: &str,
524 ) -> Result<Self::Value, E> {
525 CharStr::from_str(v).map_err(E::custom)
526 }
527
528 fn visit_borrowed_bytes<E: serde::de::Error>(
529 self,
530 value: &'de [u8],
531 ) -> Result<Self::Value, E> {
532 self.0.visit_borrowed_bytes(value).and_then(|octets| {
533 CharStr::from_octets(octets).map_err(E::custom)
534 })
535 }
536
537 #[cfg(feature = "std")]
538 fn visit_byte_buf<E: serde::de::Error>(
539 self,
540 value: std::vec::Vec<u8>,
541 ) -> Result<Self::Value, E> {
542 self.0.visit_byte_buf(value).and_then(|octets| {
543 CharStr::from_octets(octets).map_err(E::custom)
544 })
545 }
546 }
547
548 struct NewtypeVisitor<T>(PhantomData<T>);
549
550 impl<'de, Octets> serde::de::Visitor<'de> for NewtypeVisitor<Octets>
551 where
552 Octets: FromBuilder + DeserializeOctets<'de>,
553 <Octets as FromBuilder>::Builder: OctetsBuilder
554 + FreezeBuilder<Octets = Octets>
555 + EmptyBuilder
556 + AsRef<[u8]>,
557 {
558 type Value = CharStr<Octets>;
559
560 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
561 f.write_str("a character string")
562 }
563
564 fn visit_newtype_struct<D: serde::Deserializer<'de>>(
565 self,
566 deserializer: D,
567 ) -> Result<Self::Value, D::Error> {
568 if deserializer.is_human_readable() {
569 deserializer
570 .deserialize_str(InnerVisitor(Octets::visitor()))
571 } else {
572 Octets::deserialize_with_visitor(
573 deserializer,
574 InnerVisitor(Octets::visitor()),
575 )
576 }
577 }
578 }
579
580 deserializer.deserialize_newtype_struct(
581 "CharStr",
582 NewtypeVisitor(PhantomData),
583 )
584 }
585}
586
587#[derive(Clone)]
595pub struct CharStrBuilder<Builder>(Builder);
596
597impl<Builder: EmptyBuilder> CharStrBuilder<Builder> {
598 #[must_use]
600 pub fn new() -> Self {
601 CharStrBuilder(Builder::empty())
602 }
603
604 #[must_use]
606 pub fn with_capacity(capacity: usize) -> Self {
607 CharStrBuilder(Builder::with_capacity(capacity))
608 }
609}
610
611impl<Builder: OctetsBuilder + AsRef<[u8]>> CharStrBuilder<Builder> {
612 unsafe fn from_builder_unchecked(builder: Builder) -> Self {
617 CharStrBuilder(builder)
618 }
619
620 pub fn from_builder(builder: Builder) -> Result<Self, CharStrError> {
625 if builder.as_ref().len() > CharStr::MAX_LEN {
626 Err(CharStrError)
627 } else {
628 Ok(unsafe { Self::from_builder_unchecked(builder) })
629 }
630 }
631}
632
633#[cfg(feature = "std")]
634impl CharStrBuilder<Vec<u8>> {
635 #[must_use]
637 pub fn new_vec() -> Self {
638 Self::new()
639 }
640
641 #[must_use]
643 pub fn vec_with_capacity(capacity: usize) -> Self {
644 Self::with_capacity(capacity)
645 }
646}
647
648#[cfg(feature = "bytes")]
649impl CharStrBuilder<BytesMut> {
650 pub fn new_bytes() -> Self {
652 Self::new()
653 }
654
655 pub fn bytes_with_capacity(capacity: usize) -> Self {
657 Self::with_capacity(capacity)
658 }
659}
660
661impl<Builder> CharStrBuilder<Builder> {
662 pub fn as_slice(&self) -> &[u8]
664 where
665 Builder: AsRef<[u8]>,
666 {
667 self.0.as_ref()
668 }
669
670 pub fn finish(self) -> CharStr<Builder::Octets>
672 where
673 Builder: FreezeBuilder,
674 {
675 unsafe { CharStr::from_octets_unchecked(self.0.freeze()) }
676 }
677}
678
679impl<Builder: AsRef<[u8]>> CharStrBuilder<Builder> {
680 pub fn len(&self) -> usize {
685 self.as_slice().len()
686 }
687
688 pub fn is_empty(&self) -> bool {
690 self.as_slice().is_empty()
691 }
692}
693
694impl<Builder: EmptyBuilder> Default for CharStrBuilder<Builder> {
697 fn default() -> Self {
698 Self::new()
699 }
700}
701
702impl<Builder> OctetsBuilder for CharStrBuilder<Builder>
705where
706 Builder: OctetsBuilder + AsRef<[u8]>,
707{
708 type AppendError = ShortBuf;
709
710 fn append_slice(
711 &mut self,
712 slice: &[u8],
713 ) -> Result<(), Self::AppendError> {
714 if self.0.as_ref().len() + slice.len() > CharStr::MAX_LEN {
715 return Err(ShortBuf);
716 }
717 self.0.append_slice(slice).map_err(Into::into)
718 }
719}
720
721impl<Builder: Truncate> Truncate for CharStrBuilder<Builder> {
722 fn truncate(&mut self, len: usize) {
723 self.0.truncate(len)
724 }
725}
726
727impl<Builder: AsRef<[u8]>> AsRef<[u8]> for CharStrBuilder<Builder> {
730 fn as_ref(&self) -> &[u8] {
731 self.0.as_ref()
732 }
733}
734
735impl<Builder: AsMut<[u8]>> AsMut<[u8]> for CharStrBuilder<Builder> {
736 fn as_mut(&mut self) -> &mut [u8] {
737 self.0.as_mut()
738 }
739}
740
741pub struct IntoIter<T> {
745 octets: T,
746 len: usize,
747 pos: usize,
748}
749
750impl<T: AsRef<[u8]>> IntoIter<T> {
751 pub(crate) fn new(octets: T) -> Self {
752 IntoIter {
753 len: octets.as_ref().len(),
754 octets,
755 pos: 0,
756 }
757 }
758}
759
760impl<T: AsRef<[u8]>> Iterator for IntoIter<T> {
761 type Item = u8;
762
763 fn next(&mut self) -> Option<Self::Item> {
764 if self.pos == self.len {
765 None
766 } else {
767 let res = self.octets.as_ref()[self.pos];
768 self.pos += 1;
769 Some(res)
770 }
771 }
772}
773
774pub struct Iter<'a> {
778 octets: &'a [u8],
779}
780
781impl<'a> Iter<'a> {
782 pub(crate) fn new(octets: &'a [u8]) -> Self {
783 Iter { octets }
784 }
785}
786
787impl<'a> Iterator for Iter<'a> {
788 type Item = u8;
789
790 fn next(&mut self) -> Option<Self::Item> {
791 let (res, octets) = self.octets.split_first()?;
792 self.octets = octets;
793 Some(*res)
794 }
795}
796
797#[derive(Clone, Copy, Debug, Eq, PartialEq)]
805pub struct CharStrError;
806
807impl fmt::Display for CharStrError {
808 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
809 f.write_str("long character string")
810 }
811}
812
813#[cfg(feature = "std")]
814impl std::error::Error for CharStrError {}
815
816#[derive(Clone, Copy, Debug, Eq, PartialEq)]
820#[non_exhaustive]
821pub enum FromStrError {
822 LongString,
824
825 SymbolChars(SymbolCharsError),
826
827 BadSymbol(BadSymbol),
831
832 ShortBuf,
834}
835
836impl From<SymbolCharsError> for FromStrError {
839 fn from(err: SymbolCharsError) -> FromStrError {
840 FromStrError::SymbolChars(err)
841 }
842}
843
844impl From<BadSymbol> for FromStrError {
845 fn from(err: BadSymbol) -> FromStrError {
846 FromStrError::BadSymbol(err)
847 }
848}
849
850impl From<ShortBuf> for FromStrError {
851 fn from(_: ShortBuf) -> FromStrError {
852 FromStrError::ShortBuf
853 }
854}
855
856impl fmt::Display for FromStrError {
859 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
860 match *self {
861 FromStrError::LongString => {
862 f.write_str("character string with more than 255 octets")
863 }
864 FromStrError::SymbolChars(ref err) => err.fmt(f),
865 FromStrError::BadSymbol(ref err) => err.fmt(f),
866 FromStrError::ShortBuf => ShortBuf.fmt(f),
867 }
868 }
869}
870
871#[cfg(feature = "std")]
872impl std::error::Error for FromStrError {}
873
874#[cfg(test)]
877#[cfg(feature = "std")]
878mod test {
879 use super::*;
880 use octseq::builder::infallible;
881 use std::vec::Vec;
882
883 type CharStrRef<'a> = CharStr<&'a [u8]>;
884
885 #[test]
886 fn from_slice() {
887 assert_eq!(
888 CharStr::from_slice(b"01234").unwrap().as_slice(),
889 b"01234"
890 );
891 assert_eq!(CharStr::from_slice(b"").unwrap().as_slice(), b"");
892 assert!(CharStr::from_slice(&vec![0; 255]).is_ok());
893 assert!(CharStr::from_slice(&vec![0; 256]).is_err());
894 }
895
896 #[test]
897 fn from_octets() {
898 assert_eq!(
899 CharStr::from_octets("01234").unwrap().as_slice(),
900 b"01234"
901 );
902 assert_eq!(CharStr::from_octets("").unwrap().as_slice(), b"");
903 assert!(CharStr::from_octets(vec![0; 255]).is_ok());
904 assert!(CharStr::from_octets(vec![0; 256]).is_err());
905 }
906
907 #[test]
908 fn from_str() {
909 use std::str::{from_utf8, FromStr};
910
911 type Cs = CharStr<Vec<u8>>;
912
913 assert_eq!(Cs::from_str("foo").unwrap().as_slice(), b"foo");
914 assert_eq!(Cs::from_str("f\\oo").unwrap().as_slice(), b"foo");
915 assert_eq!(Cs::from_str("foo\\112").unwrap().as_slice(), b"foo\x70");
916 assert_eq!(
917 Cs::from_str("\"foo\\\"2\"").unwrap().as_slice(),
918 b"\"foo\"2\""
919 );
920 assert_eq!(Cs::from_str("06 dii").unwrap().as_slice(), b"06 dii");
921 assert!(Cs::from_str("0\\").is_err());
922 assert!(Cs::from_str("0\\2").is_err());
923 assert!(Cs::from_str("0\\2a").is_err());
924 assert!(Cs::from_str("ö").is_err());
925 assert!(Cs::from_str("\x06").is_err());
926 assert!(Cs::from_str(from_utf8(&[b'a'; 256]).unwrap()).is_err());
927 }
928
929 #[test]
930 fn parse() {
931 let mut parser = Parser::from_static(b"12\x03foo\x02bartail");
932 parser.advance(2).unwrap();
933 let foo = CharStrRef::parse(&mut parser).unwrap();
934 let bar = CharStrRef::parse(&mut parser).unwrap();
935 assert_eq!(foo.as_slice(), b"foo");
936 assert_eq!(bar.as_slice(), b"ba");
937 assert_eq!(parser.peek_all(), b"rtail");
938
939 assert!(
940 CharStrRef::parse(&mut Parser::from_static(b"\x04foo")).is_err(),
941 )
942 }
943
944 #[test]
945 fn compose() {
946 let mut target = Vec::new();
947 let val = CharStr::from_slice(b"foo").unwrap();
948 infallible(val.compose(&mut target));
949 assert_eq!(target, b"\x03foo".as_ref());
950
951 let mut target = Vec::new();
952 let val = CharStr::from_slice(b"").unwrap();
953 infallible(val.compose(&mut target));
954 assert_eq!(target, &b"\x00"[..]);
955 }
956
957 fn are_eq(l: &[u8], r: &[u8]) -> bool {
958 CharStr::from_slice(l).unwrap() == CharStr::from_slice(r).unwrap()
959 }
960
961 #[test]
962 fn eq() {
963 assert!(are_eq(b"abc", b"abc"));
964 assert!(!are_eq(b"abc", b"def"));
965 assert!(!are_eq(b"abc", b"ab"));
966 assert!(!are_eq(b"abc", b"abcd"));
967 assert!(are_eq(b"ABC", b"abc"));
968 assert!(!are_eq(b"ABC", b"def"));
969 assert!(!are_eq(b"ABC", b"ab"));
970 assert!(!are_eq(b"ABC", b"abcd"));
971 assert!(are_eq(b"", b""));
972 assert!(!are_eq(b"", b"A"));
973 }
974
975 fn is_ord(l: &[u8], r: &[u8], order: cmp::Ordering) {
976 assert_eq!(
977 CharStr::from_slice(l)
978 .unwrap()
979 .cmp(CharStr::from_slice(r).unwrap()),
980 order
981 )
982 }
983
984 #[test]
985 fn ord() {
986 use std::cmp::Ordering::*;
987
988 is_ord(b"abc", b"ABC", Equal);
989 is_ord(b"abc", b"a", Greater);
990 is_ord(b"abc", b"A", Greater);
991 is_ord(b"a", b"BC", Less);
992 }
993
994 #[test]
995 fn append_slice() {
996 let mut o = CharStrBuilder::new_vec();
997 o.append_slice(b"foo").unwrap();
998 assert_eq!(o.finish().as_slice(), b"foo");
999
1000 let mut o = CharStrBuilder::from_builder(vec![0; 254]).unwrap();
1001 o.append_slice(b"f").unwrap();
1002 assert_eq!(o.len(), 255);
1003 assert!(o.append_slice(b"f").is_err());
1004
1005 let mut o =
1006 CharStrBuilder::from_builder(vec![b'f', b'o', b'o']).unwrap();
1007 o.append_slice(b"bar").unwrap();
1008 assert_eq!(o.as_ref(), b"foobar");
1009 assert!(o.append_slice(&[0u8; 250][..]).is_err());
1010 o.append_slice(&[0u8; 249][..]).unwrap();
1011 assert_eq!(o.len(), 255);
1012 }
1013
1014 #[cfg(feature = "serde")]
1015 #[test]
1016 fn ser_de() {
1017 use serde_test::{assert_tokens, Configure, Token};
1018
1019 assert_tokens(
1020 &CharStr::from_octets(vec![b'f', b'o', 0x12])
1021 .unwrap()
1022 .compact(),
1023 &[
1024 Token::NewtypeStruct { name: "CharStr" },
1025 Token::ByteBuf(b"fo\x12"),
1026 ],
1027 );
1028
1029 assert_tokens(
1030 &CharStr::from_octets(vec![b'f', b'o', 0x12])
1031 .unwrap()
1032 .readable(),
1033 &[
1034 Token::NewtypeStruct { name: "CharStr" },
1035 Token::Str("fo\\018"),
1036 ],
1037 );
1038 }
1039}