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, 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#[derive(Clone)]
121#[repr(transparent)]
122pub struct CharStr<Octs: ?Sized>(Octs);
123
124impl CharStr<()> {
125 pub const MAX_LEN: usize = 255;
127}
128
129impl<Octs: ?Sized> CharStr<Octs> {
130 #[must_use]
132 pub fn empty() -> Self
133 where
134 Octs: From<&'static [u8]>,
135 {
136 CharStr(b"".as_ref().into())
137 }
138
139 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 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 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 #[must_use]
174 pub fn empty_slice() -> &'static Self {
175 unsafe { Self::from_slice_unchecked(b"".as_ref()) }
176 }
177
178 #[must_use]
185 pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
186 mem::transmute(slice)
188 }
189
190 unsafe fn from_slice_mut_unchecked(slice: &mut [u8]) -> &mut Self {
197 mem::transmute(slice)
199 }
200
201 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 #[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 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 pub fn into_octets(self) -> Octs
237 where
238 Octs: Sized,
239 {
240 self.0
241 }
242
243 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 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 pub fn as_slice(&self) -> &[u8]
261 where
262 Octs: AsRef<[u8]>,
263 {
264 self.0.as_ref()
265 }
266
267 pub fn as_slice_mut(&mut self) -> &mut [u8]
269 where
270 Octs: AsMut<[u8]>,
271 {
272 self.0.as_mut()
273 }
274
275 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 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 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 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 pub fn len(&self) -> usize {
341 self.as_slice().len()
342 }
343
344 pub fn is_empty(&self) -> bool {
346 self.as_slice().is_empty()
347 }
348
349 pub fn iter(&self) -> Iter {
351 Iter {
352 octets: self.as_slice(),
353 }
354 }
355}
356
357impl CharStr<[u8]> {
358 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 pub fn compose_len(&self) -> u16 {
370 u16::try_from(self.0.as_ref().len() + 1).expect("long charstr")
371 }
372
373 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 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 pub fn display_quoted(&self) -> DisplayQuoted {
401 DisplayQuoted(self.for_slice())
402 }
403
404 pub fn display_unquoted(&self) -> DisplayUnquoted {
410 DisplayUnquoted(self.for_slice())
411 }
412}
413
414impl<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
430impl<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 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
453impl<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
469impl<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
483impl<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
523impl<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
535impl<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
572impl<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#[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#[derive(Clone)]
722pub struct CharStrBuilder<Builder>(Builder);
723
724impl<Builder: EmptyBuilder> CharStrBuilder<Builder> {
725 #[must_use]
727 pub fn new() -> Self {
728 CharStrBuilder(Builder::empty())
729 }
730
731 #[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 unsafe fn from_builder_unchecked(builder: Builder) -> Self {
744 CharStrBuilder(builder)
745 }
746
747 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 #[must_use]
764 pub fn new_vec() -> Self {
765 Self::new()
766 }
767
768 #[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 pub fn new_bytes() -> Self {
779 Self::new()
780 }
781
782 pub fn bytes_with_capacity(capacity: usize) -> Self {
784 Self::with_capacity(capacity)
785 }
786}
787
788impl<Builder> CharStrBuilder<Builder> {
789 pub fn as_slice(&self) -> &[u8]
791 where
792 Builder: AsRef<[u8]>,
793 {
794 self.0.as_ref()
795 }
796
797 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 pub fn len(&self) -> usize {
812 self.as_slice().len()
813 }
814
815 pub fn is_empty(&self) -> bool {
817 self.as_slice().is_empty()
818 }
819}
820
821impl<Builder: EmptyBuilder> Default for CharStrBuilder<Builder> {
824 fn default() -> Self {
825 Self::new()
826 }
827}
828
829impl<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
854impl<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
868pub 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
901pub 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#[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#[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#[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 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 type Value = ();
988
989 fn deserialize<D: serde::de::Deserializer<'de>>(
990 self,
991 deserializer: D,
992 ) -> Result<Self::Value, D::Error> {
993 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 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 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 let len = CharStr::append_from_str(value, self.0.builder)
1054 .map_err(E::custom)?;
1055
1056 self.0.builder.as_mut()[start] = len;
1058 Ok(())
1059 }
1060 }
1061
1062 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#[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#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1116pub enum FromStrError {
1117 Presentation(PresentationError),
1119
1120 ShortBuf,
1122}
1123
1124impl<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
1138impl 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#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1156pub struct PresentationError(PresentationErrorEnum);
1157
1158#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1159enum PresentationErrorEnum {
1160 LongString,
1162
1163 SymbolChars(SymbolCharsError),
1164
1165 BadSymbol(BadSymbol),
1169}
1170
1171impl 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
1191impl 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#[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}