@@ -224,9 +224,7 @@ impl Log for AndroidLogger {
224224 . unwrap_or_else ( || module_path. as_bytes ( ) ) ;
225225
226226 // truncate the tag here to fit into LOGGING_TAG_MAX_LEN
227- self . fill_tag_bytes ( & mut tag_bytes, tag) ;
228- // use stack array as C string
229- let tag: & CStr = unsafe { CStr :: from_ptr ( mem:: transmute ( tag_bytes. as_ptr ( ) ) ) } ;
227+ let tag = fill_tag_bytes ( & mut tag_bytes, tag) ;
230228
231229 // message must not exceed LOGGING_MSG_MAX_LEN
232230 // therefore split log message into multiple log calls
@@ -250,23 +248,32 @@ impl Log for AndroidLogger {
250248 fn flush ( & self ) { }
251249}
252250
253- impl AndroidLogger {
254- fn fill_tag_bytes ( & self , array : & mut [ MaybeUninit < u8 > ] , tag : & [ u8 ] ) {
255- if tag. len ( ) > LOGGING_TAG_MAX_LEN {
256- for ( input, output) in tag
257- . iter ( )
258- . take ( LOGGING_TAG_MAX_LEN - 2 )
259- . chain ( b"..\0 " . iter ( ) )
260- . zip ( array. iter_mut ( ) )
261- {
262- output. write ( * input) ;
263- }
264- } else {
265- for ( input, output) in tag. iter ( ) . chain ( b"\0 " . iter ( ) ) . zip ( array. iter_mut ( ) ) {
266- output. write ( * input) ;
267- }
251+ fn fill_tag_bytes < ' a > (
252+ array : & ' a mut [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] ,
253+ tag : & [ u8 ] ,
254+ ) -> & ' a CStr {
255+ // FIXME: Simplify when maybe_uninit_fill with MaybeUninit::fill_from() is stabilized
256+ let initialized;
257+ if tag. len ( ) > LOGGING_TAG_MAX_LEN {
258+ for ( input, output) in tag
259+ . iter ( )
260+ . take ( LOGGING_TAG_MAX_LEN - 2 )
261+ . chain ( b"..\0 " )
262+ . zip ( array. iter_mut ( ) )
263+ {
264+ output. write ( * input) ;
265+ }
266+ initialized = array. as_slice ( ) ;
267+ } else {
268+ for ( input, output) in tag. iter ( ) . chain ( b"\0 " . iter ( ) ) . zip ( array. iter_mut ( ) ) {
269+ output. write ( * input) ;
268270 }
271+ initialized = & array[ ..tag. len ( ) + 1 ] ;
269272 }
273+
274+ // SAFETY: The above code initialized the length of the tag plus a nul terminator, or the whole length of the slice
275+ let initialized = unsafe { slice_assume_init_ref ( initialized) } ;
276+ CStr :: from_bytes_with_nul ( initialized) . expect ( "Unreachable: we wrote a nul terminator" )
270277}
271278
272279/// Filter for android logger.
@@ -449,7 +456,11 @@ impl<'a> PlatformLogWriter<'a> {
449456 self . buffer . get_unchecked_mut ( len)
450457 } ) ;
451458
452- let msg: & CStr = unsafe { CStr :: from_ptr ( self . buffer . as_ptr ( ) . cast ( ) ) } ;
459+ // TODO: This function must be `unsafe` - or receive an initialized slice or CStr directly -
460+ // as we can't otherwise guarantee safety here.
461+ let initialized = unsafe { slice_assume_init_ref ( & self . buffer [ ..len + 1 ] ) } ;
462+ let msg = CStr :: from_bytes_with_nul ( initialized)
463+ . expect ( "Unreachable: nul terminator was placed at `len`" ) ;
453464 android_log ( self . buf_id , self . priority , self . tag , msg) ;
454465
455466 unsafe { * self . buffer . get_unchecked_mut ( len) = last_byte } ;
@@ -544,6 +555,11 @@ fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] {
544555 unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) }
545556}
546557
558+ // FIXME: Remove when maybe_uninit_slice is stabilized to provide MaybeUninit::slice_assume_init_ref()
559+ unsafe fn slice_assume_init_ref < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
560+ & * ( slice as * const [ MaybeUninit < T > ] as * const [ T ] )
561+ }
562+
547563#[ cfg( test) ]
548564mod tests {
549565 use super :: * ;
@@ -604,28 +620,26 @@ mod tests {
604620
605621 #[ test]
606622 fn fill_tag_bytes_truncates_long_tag ( ) {
607- let logger = AndroidLogger :: new ( Config :: default ( ) ) ;
608- let too_long_tag: [ u8 ; LOGGING_TAG_MAX_LEN + 20 ] = [ b'a' ; LOGGING_TAG_MAX_LEN + 20 ] ;
623+ let too_long_tag = [ b'a' ; LOGGING_TAG_MAX_LEN + 20 ] ;
609624
610- let mut result: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
611- logger . fill_tag_bytes ( & mut result, & too_long_tag) ;
625+ let mut result = uninit_array ( ) ;
626+ let tag = fill_tag_bytes ( & mut result, & too_long_tag) ;
612627
613- let mut expected_result = [ b'a' ; LOGGING_TAG_MAX_LEN - 2 ] . to_vec ( ) ;
628+ let mut expected_result = vec ! [ b'a' ; LOGGING_TAG_MAX_LEN - 2 ] ;
614629 expected_result. extend ( "..\0 " . as_bytes ( ) ) ;
615- assert_eq ! ( unsafe { assume_init_slice ( & result ) } , expected_result) ;
630+ assert_eq ! ( tag . to_bytes_with_nul ( ) , expected_result) ;
616631 }
617632
618633 #[ test]
619634 fn fill_tag_bytes_keeps_short_tag ( ) {
620- let logger = AndroidLogger :: new ( Config :: default ( ) ) ;
621- let short_tag: [ u8 ; 3 ] = [ b'a' ; 3 ] ;
635+ let short_tag = [ b'a' ; 3 ] ;
622636
623- let mut result: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
624- logger . fill_tag_bytes ( & mut result, & short_tag) ;
637+ let mut result = uninit_array ( ) ;
638+ let tag = fill_tag_bytes ( & mut result, & short_tag) ;
625639
626640 let mut expected_result = short_tag. to_vec ( ) ;
627641 expected_result. push ( 0 ) ;
628- assert_eq ! ( unsafe { assume_init_slice ( & result [ .. 4 ] ) } , expected_result) ;
642+ assert_eq ! ( tag . to_bytes_with_nul ( ) , expected_result) ;
629643 }
630644
631645 #[ test]
@@ -654,7 +668,7 @@ mod tests {
654668 assert_eq ! ( writer. len, 3 ) ;
655669 assert_eq ! ( writer. last_newline_index, 0 ) ;
656670 assert_eq ! (
657- unsafe { assume_init_slice ( & writer. buffer[ ..writer. len] ) } ,
671+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..writer. len] ) } ,
658672 "\n 90" . as_bytes( )
659673 ) ;
660674
@@ -699,7 +713,7 @@ mod tests {
699713 writer. output_specified_len ( 5 ) ;
700714
701715 assert_eq ! (
702- unsafe { assume_init_slice ( & writer. buffer[ ..log_string. len( ) ] ) } ,
716+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..log_string. len( ) ] ) } ,
703717 log_string. as_bytes( )
704718 ) ;
705719 }
@@ -714,7 +728,7 @@ mod tests {
714728 writer. copy_bytes_to_start ( 3 , 2 ) ;
715729
716730 assert_eq ! (
717- unsafe { assume_init_slice ( & writer. buffer[ ..10 ] ) } ,
731+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..10 ] ) } ,
718732 "3423456789" . as_bytes( )
719733 ) ;
720734 }
@@ -731,7 +745,7 @@ mod tests {
731745 writer. copy_bytes_to_start ( 10 , 0 ) ;
732746
733747 assert_eq ! (
734- unsafe { assume_init_slice ( & writer. buffer[ ..test_string. len( ) ] ) } ,
748+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..test_string. len( ) ] ) } ,
735749 test_string. as_bytes( )
736750 ) ;
737751 }
@@ -743,8 +757,4 @@ mod tests {
743757 CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ,
744758 )
745759 }
746-
747- unsafe fn assume_init_slice < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
748- & * ( slice as * const [ MaybeUninit < T > ] as * const [ T ] )
749- }
750760}
0 commit comments