3
3
use std:: { fmt, mem} ;
4
4
use std:: borrow:: { Borrow , BorrowMut , Cow } ;
5
5
use std:: error:: Error ;
6
+ use std:: ffi:: { CStr , CString } ;
6
7
use std:: any:: Any ;
7
8
use std:: str:: FromStr ;
8
9
use std:: ops:: { Deref , DerefMut , Add , AddAssign , Index , IndexMut } ;
@@ -447,6 +448,20 @@ impl Into<Vec<u8>> for AsciiString {
447
448
}
448
449
}
449
450
451
+ impl < ' a > From < & ' a AsciiStr > for AsciiString {
452
+ #[ inline]
453
+ fn from ( s : & ' a AsciiStr ) -> Self {
454
+ s. to_ascii_string ( )
455
+ }
456
+ }
457
+
458
+ impl < ' a > From < & ' a [ AsciiChar ] > for AsciiString {
459
+ #[ inline]
460
+ fn from ( s : & ' a [ AsciiChar ] ) -> AsciiString {
461
+ s. into_iter ( ) . map ( |c| * c) . collect ( )
462
+ }
463
+ }
464
+
450
465
impl Into < String > for AsciiString {
451
466
#[ inline]
452
467
fn into ( self ) -> String {
@@ -718,17 +733,6 @@ pub trait IntoAsciiString: Sized {
718
733
fn into_ascii_string ( self ) -> Result < AsciiString , FromAsciiError < Self > > ;
719
734
}
720
735
721
- impl IntoAsciiString for AsciiString {
722
- #[ inline]
723
- unsafe fn into_ascii_string_unchecked ( self ) -> AsciiString {
724
- self
725
- }
726
- #[ inline]
727
- fn into_ascii_string ( self ) -> Result < Self , FromAsciiError < Self > > {
728
- Ok ( self )
729
- }
730
- }
731
-
732
736
impl IntoAsciiString for Vec < AsciiChar > {
733
737
#[ inline]
734
738
unsafe fn into_ascii_string_unchecked ( self ) -> AsciiString {
@@ -740,47 +744,113 @@ impl IntoAsciiString for Vec<AsciiChar> {
740
744
}
741
745
}
742
746
743
- impl IntoAsciiString for Vec < u8 > {
747
+ impl < ' a > IntoAsciiString for & ' a [ AsciiChar ] {
744
748
#[ inline]
745
749
unsafe fn into_ascii_string_unchecked ( self ) -> AsciiString {
746
- AsciiString :: from_ascii_unchecked ( self )
750
+ AsciiString :: from ( self )
747
751
}
748
752
#[ inline]
749
753
fn into_ascii_string ( self ) -> Result < AsciiString , FromAsciiError < Self > > {
750
- AsciiString :: from_ascii ( self )
754
+ Ok ( AsciiString :: from ( self ) )
751
755
}
752
756
}
753
757
754
- impl < ' a > IntoAsciiString for & ' a [ u8 ] {
758
+ impl < ' a > IntoAsciiString for & ' a AsciiStr {
755
759
#[ inline]
756
760
unsafe fn into_ascii_string_unchecked ( self ) -> AsciiString {
757
- AsciiString :: from_ascii_unchecked ( self )
761
+ AsciiString :: from ( self )
758
762
}
759
763
#[ inline]
760
764
fn into_ascii_string ( self ) -> Result < AsciiString , FromAsciiError < Self > > {
761
- AsciiString :: from_ascii ( self )
765
+ Ok ( AsciiString :: from ( self ) )
762
766
}
763
767
}
764
768
765
- impl IntoAsciiString for String {
769
+ macro_rules! impl_into_ascii_string {
770
+ ( ' a, $wider: ty) => {
771
+ impl <' a> IntoAsciiString for $wider {
772
+ #[ inline]
773
+ unsafe fn into_ascii_string_unchecked( self ) -> AsciiString {
774
+ AsciiString :: from_ascii_unchecked( self )
775
+ }
776
+
777
+ #[ inline]
778
+ fn into_ascii_string( self ) -> Result <AsciiString , FromAsciiError <Self >> {
779
+ AsciiString :: from_ascii( self )
780
+ }
781
+ }
782
+ } ;
783
+
784
+ ( $wider: ty) => {
785
+ impl IntoAsciiString for $wider {
786
+ #[ inline]
787
+ unsafe fn into_ascii_string_unchecked( self ) -> AsciiString {
788
+ AsciiString :: from_ascii_unchecked( self )
789
+ }
790
+
791
+ #[ inline]
792
+ fn into_ascii_string( self ) -> Result <AsciiString , FromAsciiError <Self >> {
793
+ AsciiString :: from_ascii( self )
794
+ }
795
+ }
796
+ } ;
797
+ }
798
+
799
+ impl_into_ascii_string ! { AsciiString }
800
+ impl_into_ascii_string ! { Vec <u8 >}
801
+ impl_into_ascii_string ! { ' a, & ' a [ u8 ] }
802
+ impl_into_ascii_string ! { String }
803
+ impl_into_ascii_string ! { ' a, & ' a str }
804
+
805
+ /// Note that the trailing null byte will be removed in the conversion.
806
+ impl IntoAsciiString for CString {
766
807
#[ inline]
767
808
unsafe fn into_ascii_string_unchecked ( self ) -> AsciiString {
768
- AsciiString :: from_ascii_unchecked ( self )
809
+ AsciiString :: from_ascii_unchecked ( self . into_bytes ( ) )
769
810
}
770
- #[ inline]
771
- fn into_ascii_string ( self ) -> Result < AsciiString , FromAsciiError < Self > > {
772
- AsciiString :: from_ascii ( self )
773
- }
774
- }
775
811
776
- impl < ' a > IntoAsciiString for & ' a str {
812
+ fn into_ascii_string ( self ) -> Result < AsciiString , FromAsciiError < Self > > {
813
+ AsciiString :: from_ascii ( self . into_bytes_with_nul ( ) )
814
+ . map_err ( |FromAsciiError { error, owner } | {
815
+ FromAsciiError {
816
+ owner : unsafe {
817
+ // The null byte is preserved from the original
818
+ // `CString`, so this is safe.
819
+ CString :: from_vec_unchecked ( owner)
820
+ } ,
821
+ error : error,
822
+ }
823
+ } )
824
+ . map ( |mut s| {
825
+ let _nul = s. pop ( ) ;
826
+ debug_assert_eq ! ( _nul, Some ( AsciiChar :: Null ) ) ;
827
+ s
828
+ } )
829
+ }
830
+ }
831
+
832
+ /// Note that the trailing null byte will be removed in the conversion.
833
+ impl < ' a > IntoAsciiString for & ' a CStr {
777
834
#[ inline]
778
835
unsafe fn into_ascii_string_unchecked ( self ) -> AsciiString {
779
- AsciiString :: from_ascii_unchecked ( self )
836
+ AsciiString :: from_ascii_unchecked ( self . to_bytes ( ) )
780
837
}
781
- # [ inline ]
838
+
782
839
fn into_ascii_string ( self ) -> Result < AsciiString , FromAsciiError < Self > > {
783
- AsciiString :: from_ascii ( self )
840
+ AsciiString :: from_ascii ( self . to_bytes_with_nul ( ) )
841
+ . map_err ( |FromAsciiError { error, owner } | {
842
+ FromAsciiError {
843
+ owner : unsafe {
844
+ CStr :: from_ptr ( owner. as_ptr ( ) as * const _ )
845
+ } ,
846
+ error : error,
847
+ }
848
+ } )
849
+ . map ( |mut s| {
850
+ let _nul = s. pop ( ) ;
851
+ debug_assert_eq ! ( _nul, Some ( AsciiChar :: Null ) ) ;
852
+ s
853
+ } )
784
854
}
785
855
}
786
856
@@ -844,6 +914,7 @@ impl Arbitrary for AsciiString {
844
914
#[ cfg( test) ]
845
915
mod tests {
846
916
use std:: str:: FromStr ;
917
+ use std:: ffi:: CString ;
847
918
use AsciiChar ;
848
919
use super :: { AsciiString , IntoAsciiString } ;
849
920
@@ -865,6 +936,27 @@ mod tests {
865
936
assert_eq ! ( AsciiString :: from( vec) , AsciiString :: from_str( "AB" ) . unwrap( ) ) ;
866
937
}
867
938
939
+ #[ test]
940
+ fn from_cstring ( ) {
941
+ let cstring = CString :: new ( "baz" ) . unwrap ( ) ;
942
+ let ascii_str = cstring. clone ( ) . into_ascii_string ( ) . unwrap ( ) ;
943
+ let expected_chars = & [ AsciiChar :: b, AsciiChar :: a, AsciiChar :: z] ;
944
+ assert_eq ! ( ascii_str. len( ) , 3 ) ;
945
+ assert_eq ! ( ascii_str. as_slice( ) , expected_chars) ;
946
+
947
+ let ascii_str_unchecked = unsafe {
948
+ cstring. into_ascii_string_unchecked ( )
949
+ } ;
950
+ assert_eq ! ( ascii_str_unchecked. len( ) , 3 ) ;
951
+ assert_eq ! ( ascii_str_unchecked. as_slice( ) , expected_chars) ;
952
+
953
+ let sparkle_heart_bytes = vec ! [ 240u8 , 159 , 146 , 150 ] ;
954
+ let cstring = CString :: new ( sparkle_heart_bytes) . unwrap ( ) ;
955
+ let cstr = & * cstring;
956
+ let ascii_err = cstr. into_ascii_string ( ) . unwrap_err ( ) ;
957
+ assert_eq ! ( ascii_err. into_source( ) , & * cstring) ;
958
+ }
959
+
868
960
#[ test]
869
961
fn fmt_ascii_string ( ) {
870
962
let s = "abc" . to_string ( ) . into_ascii_string ( ) . unwrap ( ) ;
0 commit comments