@@ -29,7 +29,7 @@ impl StrLike for CStr {
2929 if self . to_str ( ) . is_ok ( ) {
3030 sys:: kCFStringEncodingUTF8
3131 } else {
32- sys:: kCFStringEncodingNonLossyASCII
32+ sys:: kCFStringEncodingASCII
3333 }
3434 }
3535
@@ -139,7 +139,7 @@ impl CFString {
139139 }
140140
141141 /// Get this value as a null-terminated C-string
142- pub fn get_cstring ( & self ) -> CString {
142+ pub fn get_cstring ( & self ) -> Option < CString > {
143143 let len = self . len ( ) * 4 + 1 ;
144144 let mut buf = vec ! [ 0 ; len] ;
145145 // SAFETY: Self is guaranteed valid. Buffer is definitely of sufficient length to hold the
@@ -154,24 +154,61 @@ impl CFString {
154154 } ;
155155 if res {
156156 let buf = buf. into_iter ( ) . take_while ( |& c| c != 0 ) . collect :: < Vec < _ > > ( ) ;
157- CString :: new ( buf) . unwrap ( )
157+ if buf. len ( ) != self . len ( ) {
158+ None
159+ } else {
160+ Some ( CString :: new ( buf) . unwrap ( ) )
161+ }
158162 } else {
159- panic ! ( "Invalid C String" )
163+ None
160164 }
161165 }
162166
163167 /// Attempt to get a reference to this value as a `CStr`, if the value is natively UTF-8,
164168 /// otherwise allocate a CString in that encoding.
165- pub fn as_cstr ( & self ) -> Cow < ' _ , CStr > {
169+ pub fn as_cstr ( & self ) -> Option < Cow < ' _ , CStr > > {
166170 // SAFETY: Self is guaranteed valid
167171 let cstr =
168172 unsafe { sys:: CFStringGetCStringPtr ( self . as_type_ref ( ) , sys:: kCFStringEncodingUTF8) } ;
169173 if cstr. is_null ( ) {
170- Cow :: Owned ( self . get_cstring ( ) )
174+ self . get_cstring ( ) . map ( Cow :: Owned )
171175 } else {
172176 // SAFETY: If non-null, the return value of CFStringGetCStringPtr is guaranteed to be a
173177 // valid C-string
174- Cow :: Borrowed ( unsafe { CStr :: from_ptr ( cstr) } )
178+ Some ( Cow :: Borrowed ( unsafe { CStr :: from_ptr ( cstr) } ) )
175179 }
176180 }
177181}
182+
183+ #[ cfg( test) ]
184+ mod tests {
185+ use super :: * ;
186+
187+ #[ test]
188+ fn test_as_str ( ) {
189+ let str = CFString :: new ( "foo" ) ;
190+ assert_eq ! ( str . as_str( ) , Cow :: Borrowed ( "foo" ) ) ;
191+
192+ let cstr = CFString :: new ( c"foo" ) ;
193+ assert_eq ! ( cstr. as_str( ) , Cow :: Borrowed ( "foo" ) ) ;
194+
195+ // Invalid UTF-8 CStrings are treated as extended-ASCII.
196+ let non_str = CFString :: new ( c"\xC3 \x28 bar" ) ;
197+ assert_eq ! ( non_str. as_str( ) , Cow :: <str >:: Owned ( "Ã(bar" . to_string( ) ) ) ;
198+ }
199+
200+ #[ test]
201+ fn test_as_cstr ( ) {
202+ let str = CFString :: new ( "foo" ) ;
203+ assert_eq ! ( str . as_cstr( ) , Some ( Cow :: <CStr >:: Owned ( c"foo" . to_owned( ) ) ) ) ;
204+
205+ let cstr = CFString :: new ( c"foo" ) ;
206+ assert_eq ! ( cstr. as_cstr( ) , Some ( Cow :: Borrowed ( c"foo" ) ) ) ;
207+ }
208+
209+ #[ test]
210+ fn test_as_non_cstr ( ) {
211+ let non_cstr = CFString :: new ( "fo\0 o" ) ;
212+ assert ! ( non_cstr. as_cstr( ) . is_none( ) ) ;
213+ }
214+ }
0 commit comments