@@ -27,12 +27,14 @@ impl AsciiStr {
27
27
/// Converts `&self` to a `&str` slice.
28
28
#[ inline]
29
29
pub fn as_str ( & self ) -> & str {
30
+ // SAFETY: All variants of `AsciiChar` are valid bytes for a `str`.
30
31
unsafe { & * ( self as * const AsciiStr as * const str ) }
31
32
}
32
33
33
34
/// Converts `&self` into a byte slice.
34
35
#[ inline]
35
36
pub fn as_bytes ( & self ) -> & [ u8 ] {
37
+ // SAFETY: All variants of `AsciiChar` are valid `u8`, given they're `repr(u8)`.
36
38
unsafe { & * ( self as * const AsciiStr as * const [ u8 ] ) }
37
39
}
38
40
@@ -95,6 +97,10 @@ impl AsciiStr {
95
97
/// Converts anything that can be represented as a byte slice to an `AsciiStr` without checking
96
98
/// for non-ASCII characters..
97
99
///
100
+ /// # Safety
101
+ /// If any of the bytes in `bytes` do not represent valid ascii characters, calling
102
+ /// this function is undefined behavior.
103
+ ///
98
104
/// # Examples
99
105
/// ```
100
106
/// # use ascii::AsciiStr;
@@ -103,7 +109,9 @@ impl AsciiStr {
103
109
/// ```
104
110
#[ inline]
105
111
pub unsafe fn from_ascii_unchecked ( bytes : & [ u8 ] ) -> & AsciiStr {
106
- bytes. as_ascii_str_unchecked ( )
112
+ // SAFETY: Caller guarantees all bytes in `bytes` are valid
113
+ // ascii characters.
114
+ unsafe { bytes. as_ascii_str_unchecked ( ) }
107
115
}
108
116
109
117
/// Returns the number of characters / bytes in this ASCII sequence.
@@ -782,6 +790,10 @@ pub trait AsAsciiStr {
782
790
}
783
791
/// Convert to an ASCII slice without checking for non-ASCII characters.
784
792
///
793
+ /// # Safety
794
+ /// Calling this function when `self` contains non-ascii characters is
795
+ /// undefined behavior.
796
+ ///
785
797
/// # Examples
786
798
///
787
799
unsafe fn as_ascii_str_unchecked ( & self ) -> & AsciiStr ;
@@ -793,11 +805,17 @@ pub trait AsMutAsciiStr: AsAsciiStr {
793
805
fn slice_ascii_mut < R > ( & mut self , range : R ) -> Result < & mut AsciiStr , AsAsciiStrError >
794
806
where
795
807
R : SliceIndex < [ Self :: Inner ] , Output = [ Self :: Inner ] > ;
808
+
796
809
/// Convert to a mutable ASCII slice.
797
810
fn as_mut_ascii_str ( & mut self ) -> Result < & mut AsciiStr , AsAsciiStrError > {
798
811
self . slice_ascii_mut ( ..)
799
812
}
813
+
800
814
/// Convert to a mutable ASCII slice without checking for non-ASCII characters.
815
+ ///
816
+ /// # Safety
817
+ /// Calling this function when `self` contains non-ascii characters is
818
+ /// undefined behavior.
801
819
unsafe fn as_mut_ascii_str_unchecked ( & mut self ) -> & mut AsciiStr ;
802
820
}
803
821
@@ -813,8 +831,10 @@ where
813
831
{
814
832
<T as AsAsciiStr >:: slice_ascii ( * self , range)
815
833
}
834
+
816
835
unsafe fn as_ascii_str_unchecked ( & self ) -> & AsciiStr {
817
- <T as AsAsciiStr >:: as_ascii_str_unchecked ( * self )
836
+ // SAFETY: Caller guarantees `self` does not contain non-ascii characters
837
+ unsafe { <T as AsAsciiStr >:: as_ascii_str_unchecked ( * self ) }
818
838
}
819
839
}
820
840
@@ -831,7 +851,8 @@ where
831
851
}
832
852
833
853
unsafe fn as_ascii_str_unchecked ( & self ) -> & AsciiStr {
834
- <T as AsAsciiStr >:: as_ascii_str_unchecked ( * self )
854
+ // SAFETY: Caller guarantees `self` does not contain non-ascii characters
855
+ unsafe { <T as AsAsciiStr >:: as_ascii_str_unchecked ( * self ) }
835
856
}
836
857
}
837
858
@@ -847,26 +868,31 @@ where
847
868
}
848
869
849
870
unsafe fn as_mut_ascii_str_unchecked ( & mut self ) -> & mut AsciiStr {
850
- <T as AsMutAsciiStr >:: as_mut_ascii_str_unchecked ( * self )
871
+ // SAFETY: Caller guarantees `self` does not contain non-ascii characters
872
+ unsafe { <T as AsMutAsciiStr >:: as_mut_ascii_str_unchecked ( * self ) }
851
873
}
852
874
}
853
875
854
876
impl AsAsciiStr for AsciiStr {
855
877
type Inner = AsciiChar ;
878
+
856
879
fn slice_ascii < R > ( & self , range : R ) -> Result < & AsciiStr , AsAsciiStrError >
857
880
where
858
881
R : SliceIndex < [ AsciiChar ] , Output = [ AsciiChar ] > ,
859
882
{
860
883
self . slice . slice_ascii ( range)
861
884
}
885
+
862
886
#[ inline]
863
887
fn as_ascii_str ( & self ) -> Result < & AsciiStr , AsAsciiStrError > {
864
888
Ok ( self )
865
889
}
890
+
866
891
#[ inline]
867
892
unsafe fn as_ascii_str_unchecked ( & self ) -> & AsciiStr {
868
893
self
869
894
}
895
+
870
896
#[ inline]
871
897
fn get_ascii ( & self , index : usize ) -> Option < AsciiChar > {
872
898
self . slice . get_ascii ( index)
@@ -879,6 +905,7 @@ impl AsMutAsciiStr for AsciiStr {
879
905
{
880
906
self . slice . slice_ascii_mut ( range)
881
907
}
908
+
882
909
#[ inline]
883
910
unsafe fn as_mut_ascii_str_unchecked ( & mut self ) -> & mut AsciiStr {
884
911
self
@@ -896,14 +923,17 @@ impl AsAsciiStr for [AsciiChar] {
896
923
None => Err ( AsAsciiStrError ( self . len ( ) ) ) ,
897
924
}
898
925
}
926
+
899
927
#[ inline]
900
928
fn as_ascii_str ( & self ) -> Result < & AsciiStr , AsAsciiStrError > {
901
929
Ok ( self . into ( ) )
902
930
}
931
+
903
932
#[ inline]
904
933
unsafe fn as_ascii_str_unchecked ( & self ) -> & AsciiStr {
905
- self . into ( )
934
+ < & AsciiStr > :: from ( self )
906
935
}
936
+
907
937
#[ inline]
908
938
fn get_ascii ( & self , index : usize ) -> Option < AsciiChar > {
909
939
self . get ( index) . cloned ( )
@@ -922,12 +952,13 @@ impl AsMutAsciiStr for [AsciiChar] {
922
952
}
923
953
#[ inline]
924
954
unsafe fn as_mut_ascii_str_unchecked ( & mut self ) -> & mut AsciiStr {
925
- self . into ( )
955
+ < & mut AsciiStr > :: from ( self )
926
956
}
927
957
}
928
958
929
959
impl AsAsciiStr for [ u8 ] {
930
960
type Inner = u8 ;
961
+
931
962
fn slice_ascii < R > ( & self , range : R ) -> Result < & AsciiStr , AsAsciiStrError >
932
963
where
933
964
R : SliceIndex < [ u8 ] , Output = [ u8 ] > ,
@@ -941,20 +972,23 @@ impl AsAsciiStr for [u8] {
941
972
Err ( AsAsciiStrError ( self . len ( ) ) )
942
973
}
943
974
}
975
+
944
976
fn as_ascii_str ( & self ) -> Result < & AsciiStr , AsAsciiStrError > {
977
+ // is_ascii is likely optimized
945
978
if self . is_ascii ( ) {
946
- // is_ascii is likely optimized
979
+ // SAFETY: ` is_ascii` guarantees all bytes are within ascii range.
947
980
unsafe { Ok ( self . as_ascii_str_unchecked ( ) ) }
948
981
} else {
949
982
Err ( AsAsciiStrError (
950
983
self . iter ( ) . take_while ( |& b| b. is_ascii ( ) ) . count ( ) ,
951
984
) )
952
985
}
953
986
}
987
+
954
988
#[ inline]
955
989
unsafe fn as_ascii_str_unchecked ( & self ) -> & AsciiStr {
956
- let ptr = self as * const [ u8 ] as * const AsciiStr ;
957
- & * ptr
990
+ // SAFETY: Caller guarantees ` self` does not contain non-ascii characters
991
+ unsafe { & * ( self as * const [ u8 ] as * const AsciiStr ) }
958
992
}
959
993
}
960
994
impl AsMutAsciiStr for [ u8 ] {
@@ -975,20 +1009,23 @@ impl AsMutAsciiStr for [u8] {
975
1009
Err ( AsAsciiStrError ( len) )
976
1010
}
977
1011
}
1012
+
978
1013
fn as_mut_ascii_str ( & mut self ) -> Result < & mut AsciiStr , AsAsciiStrError > {
1014
+ // is_ascii() is likely optimized
979
1015
if self . is_ascii ( ) {
980
- // is_ascii() is likely optimized
1016
+ // SAFETY: ` is_ascii` guarantees all bytes are within ascii range.
981
1017
unsafe { Ok ( self . as_mut_ascii_str_unchecked ( ) ) }
982
1018
} else {
983
1019
Err ( AsAsciiStrError (
984
1020
self . iter ( ) . take_while ( |& b| b. is_ascii ( ) ) . count ( ) ,
985
1021
) )
986
1022
}
987
1023
}
1024
+
988
1025
#[ inline]
989
1026
unsafe fn as_mut_ascii_str_unchecked ( & mut self ) -> & mut AsciiStr {
990
- let ptr = self as * mut [ u8 ] as * mut AsciiStr ;
991
- & mut * ptr
1027
+ // SAFETY: Caller guarantees ` self` does not contain non-ascii characters
1028
+ unsafe { & mut * ( self as * mut [ u8 ] as * mut AsciiStr ) }
992
1029
}
993
1030
}
994
1031
@@ -1005,40 +1042,52 @@ impl AsAsciiStr for str {
1005
1042
}
1006
1043
#[ inline]
1007
1044
unsafe fn as_ascii_str_unchecked ( & self ) -> & AsciiStr {
1008
- self . as_bytes ( ) . as_ascii_str_unchecked ( )
1045
+ // SAFETY: Caller guarantees `self` does not contain non-ascii characters
1046
+ unsafe { self . as_bytes ( ) . as_ascii_str_unchecked ( ) }
1009
1047
}
1010
1048
}
1011
1049
impl AsMutAsciiStr for str {
1012
1050
fn slice_ascii_mut < R > ( & mut self , range : R ) -> Result < & mut AsciiStr , AsAsciiStrError >
1013
1051
where
1014
1052
R : SliceIndex < [ u8 ] , Output = [ u8 ] > ,
1015
1053
{
1016
- let ( ptr, len) = if let Some ( slice) = self . as_bytes ( ) . get ( range) {
1017
- if !slice. is_ascii ( ) {
1054
+ // SAFETY: We don't modify the reference in this function, and the caller may
1055
+ // only modify it to include valid ascii characters.
1056
+ let bytes = unsafe { self . as_bytes_mut ( ) } ;
1057
+ match bytes. get_mut ( range) {
1058
+ // Valid ascii slice
1059
+ Some ( slice) if slice. is_ascii ( ) => {
1060
+ // SAFETY: All bytes are ascii, so this cast is valid
1061
+ let ptr = slice. as_mut_ptr ( ) as * mut AsciiChar ;
1062
+ let len = slice. len ( ) ;
1063
+
1064
+ // SAFETY: The pointer is valid for `len` elements, as it came
1065
+ // from a slice.
1066
+ unsafe {
1067
+ let slice = core:: slice:: from_raw_parts_mut ( ptr, len) ;
1068
+ Ok ( <& mut AsciiStr >:: from ( slice) )
1069
+ }
1070
+ }
1071
+ Some ( slice) => {
1072
+ let not_ascii_len = slice. iter ( ) . copied ( ) . take_while ( u8:: is_ascii) . count ( ) ;
1018
1073
let offset = slice. as_ptr ( ) as usize - self . as_ptr ( ) as usize ;
1019
- let not_ascii = slice . iter ( ) . take_while ( | & b| b . is_ascii ( ) ) . count ( ) ;
1020
- return Err ( AsAsciiStrError ( offset + not_ascii ) ) ;
1074
+
1075
+ Err ( AsAsciiStrError ( offset + not_ascii_len ) )
1021
1076
}
1022
- ( slice. as_ptr ( ) , slice. len ( ) )
1023
- } else {
1024
- return Err ( AsAsciiStrError ( self . len ( ) ) ) ;
1025
- } ;
1026
- unsafe {
1027
- let ptr = ptr as * const AsciiChar as * mut AsciiChar ;
1028
- let slice = core:: slice:: from_raw_parts_mut ( ptr, len) ;
1029
- Ok ( slice. into ( ) )
1077
+ None => Err ( AsAsciiStrError ( self . len ( ) ) ) ,
1030
1078
}
1031
1079
}
1032
1080
fn as_mut_ascii_str ( & mut self ) -> Result < & mut AsciiStr , AsAsciiStrError > {
1033
- match self . bytes ( ) . position ( |b| b > 127 ) {
1081
+ match self . bytes ( ) . position ( |b| !b . is_ascii ( ) ) {
1034
1082
Some ( index) => Err ( AsAsciiStrError ( index) ) ,
1083
+ // SAFETY: All bytes were iterated, and all were ascii
1035
1084
None => unsafe { Ok ( self . as_mut_ascii_str_unchecked ( ) ) } ,
1036
1085
}
1037
1086
}
1038
1087
#[ inline]
1039
1088
unsafe fn as_mut_ascii_str_unchecked ( & mut self ) -> & mut AsciiStr {
1040
- let ptr = self as * mut str as * mut AsciiStr ;
1041
- & mut * ptr
1089
+ // SAFETY: Caller guarantees ` self` does not contain non-ascii characters
1090
+ & mut * ( self as * mut str as * mut AsciiStr )
1042
1091
}
1043
1092
}
1044
1093
@@ -1058,7 +1107,8 @@ impl AsAsciiStr for CStr {
1058
1107
}
1059
1108
#[ inline]
1060
1109
unsafe fn as_ascii_str_unchecked ( & self ) -> & AsciiStr {
1061
- self . to_bytes ( ) . as_ascii_str_unchecked ( )
1110
+ // SAFETY: Caller guarantees `self` does not contain non-ascii characters
1111
+ unsafe { self . to_bytes ( ) . as_ascii_str_unchecked ( ) }
1062
1112
}
1063
1113
}
1064
1114
0 commit comments