@@ -227,10 +227,8 @@ impl Log for AndroidLogger {
227227 // In case we end up allocating, keep the CString alive.
228228 let _owned_tag;
229229 let tag: & CStr = if tag. len ( ) < tag_bytes. len ( ) {
230- // use stack array as C string
231- self . fill_tag_bytes ( & mut tag_bytes, tag) ;
232- // SAFETY: fill_tag_bytes always puts a nullbyte in tag_bytes.
233- unsafe { CStr :: from_ptr ( mem:: transmute ( tag_bytes. as_ptr ( ) ) ) }
230+ // truncate the tag here to fit into LOGGING_TAG_MAX_LEN
231+ fill_tag_bytes ( & mut tag_bytes, tag)
234232 } else {
235233 // Tag longer than available stack buffer; allocate.
236234 // We're using either
@@ -264,23 +262,38 @@ impl Log for AndroidLogger {
264262 fn flush ( & self ) { }
265263}
266264
267- impl AndroidLogger {
268- fn fill_tag_bytes ( & self , array : & mut [ MaybeUninit < u8 > ] , tag : & [ u8 ] ) {
269- if tag. len ( ) > LOGGING_TAG_MAX_LEN {
270- for ( input, output) in tag
271- . iter ( )
272- . take ( LOGGING_TAG_MAX_LEN - 2 )
273- . chain ( b"..\0 " . iter ( ) )
274- . zip ( array. iter_mut ( ) )
275- {
276- output. write ( * input) ;
277- }
278- } else {
279- for ( input, output) in tag. iter ( ) . chain ( b"\0 " . iter ( ) ) . zip ( array. iter_mut ( ) ) {
280- output. write ( * input) ;
281- }
265+ /// Fills up `storage` with `tag` and a necessary NUL terminator, optionally ellipsizing the input
266+ /// `tag` if it's too large.
267+ ///
268+ /// Returns a [`CStr`] containing the initialized portion of `storage`, including its NUL
269+ /// terminator.
270+ fn fill_tag_bytes < ' a > (
271+ storage : & ' a mut [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] ,
272+ tag : & [ u8 ] ,
273+ ) -> & ' a CStr {
274+ // FIXME: Simplify when maybe_uninit_fill with MaybeUninit::fill_from() is stabilized
275+ let initialized = if tag. len ( ) > LOGGING_TAG_MAX_LEN {
276+ for ( input, output) in tag
277+ . iter ( )
278+ // Elipsize the last two characters (TODO: use special … character)?
279+ . take ( LOGGING_TAG_MAX_LEN - 2 )
280+ . chain ( b"..\0 " )
281+ . zip ( storage. iter_mut ( ) )
282+ {
283+ output. write ( * input) ;
282284 }
283- }
285+ storage. as_slice ( )
286+ } else {
287+ for ( input, output) in tag. iter ( ) . chain ( b"\0 " ) . zip ( storage. iter_mut ( ) ) {
288+ output. write ( * input) ;
289+ }
290+ & storage[ ..tag. len ( ) + 1 ]
291+ } ;
292+
293+ // SAFETY: The above code ensures that `initialized` only refers to a portion of the `array`
294+ // slice that was initialized, thus it is safe to cast those `MaybeUninit<u8>`s to `u8`:
295+ let initialized = unsafe { slice_assume_init_ref ( initialized) } ;
296+ CStr :: from_bytes_with_nul ( initialized) . expect ( "Unreachable: we wrote a nul terminator" )
284297}
285298
286299/// Filter for android logger.
@@ -369,7 +382,7 @@ pub struct PlatformLogWriter<'a> {
369382 buffer : [ MaybeUninit < u8 > ; LOGGING_MSG_MAX_LEN + 1 ] ,
370383}
371384
372- impl < ' a > PlatformLogWriter < ' a > {
385+ impl PlatformLogWriter < ' _ > {
373386 #[ cfg( target_os = "android" ) ]
374387 pub fn new_with_priority (
375388 buf_id : Option < LogId > ,
@@ -432,11 +445,11 @@ impl<'a> PlatformLogWriter<'a> {
432445 let copy_from_index = self . last_newline_index ;
433446 let remaining_chunk_len = total_len - copy_from_index;
434447
435- self . output_specified_len ( copy_from_index) ;
448+ unsafe { self . output_specified_len ( copy_from_index) } ;
436449 self . copy_bytes_to_start ( copy_from_index, remaining_chunk_len) ;
437450 self . len = remaining_chunk_len;
438451 } else {
439- self . output_specified_len ( total_len) ;
452+ unsafe { self . output_specified_len ( total_len) } ;
440453 self . len = 0 ;
441454 }
442455 self . last_newline_index = 0 ;
@@ -450,20 +463,26 @@ impl<'a> PlatformLogWriter<'a> {
450463 return ;
451464 }
452465
453- self . output_specified_len ( total_len) ;
466+ unsafe { self . output_specified_len ( total_len) } ;
454467 self . len = 0 ;
455468 self . last_newline_index = 0 ;
456469 }
457470
458471 /// Output buffer up until the \0 which will be placed at `len` position.
459- fn output_specified_len ( & mut self , len : usize ) {
472+ ///
473+ /// # Safety
474+ /// The first `len` bytes of `self.buffer` must be initialized.
475+ unsafe fn output_specified_len ( & mut self , len : usize ) {
460476 let mut last_byte = MaybeUninit :: new ( b'\0' ) ;
461477
462- mem:: swap ( & mut last_byte, unsafe {
463- self . buffer . get_unchecked_mut ( len)
464- } ) ;
478+ mem:: swap (
479+ & mut last_byte,
480+ self . buffer . get_mut ( len) . expect ( "`len` is out of bounds" ) ,
481+ ) ;
465482
466- let msg: & CStr = unsafe { CStr :: from_ptr ( self . buffer . as_ptr ( ) . cast ( ) ) } ;
483+ let initialized = unsafe { slice_assume_init_ref ( & self . buffer [ ..len + 1 ] ) } ;
484+ let msg = CStr :: from_bytes_with_nul ( initialized)
485+ . expect ( "Unreachable: nul terminator was placed at `len`" ) ;
467486 android_log ( self . buf_id , self . priority , self . tag , msg) ;
468487
469488 unsafe { * self . buffer . get_unchecked_mut ( len) = last_byte } ;
@@ -477,18 +496,18 @@ impl<'a> PlatformLogWriter<'a> {
477496 }
478497}
479498
480- impl < ' a > fmt:: Write for PlatformLogWriter < ' a > {
499+ impl fmt:: Write for PlatformLogWriter < ' _ > {
481500 fn write_str ( & mut self , s : & str ) -> fmt:: Result {
482- let mut incomming_bytes = s. as_bytes ( ) ;
501+ let mut incoming_bytes = s. as_bytes ( ) ;
483502
484- while !incomming_bytes . is_empty ( ) {
503+ while !incoming_bytes . is_empty ( ) {
485504 let len = self . len ;
486505
487506 // write everything possible to buffer and mark last \n
488- let new_len = len + incomming_bytes . len ( ) ;
507+ let new_len = len + incoming_bytes . len ( ) ;
489508 let last_newline = self . buffer [ len..LOGGING_MSG_MAX_LEN ]
490509 . iter_mut ( )
491- . zip ( incomming_bytes )
510+ . zip ( incoming_bytes )
492511 . enumerate ( )
493512 . fold ( None , |acc, ( i, ( output, input) ) | {
494513 output. write ( * input) ;
@@ -517,7 +536,7 @@ impl<'a> fmt::Write for PlatformLogWriter<'a> {
517536 LOGGING_MSG_MAX_LEN - len // written len
518537 } ;
519538
520- incomming_bytes = & incomming_bytes [ written_len..] ;
539+ incoming_bytes = & incoming_bytes [ written_len..] ;
521540 }
522541
523542 Ok ( ( ) )
@@ -558,6 +577,11 @@ fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] {
558577 unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) }
559578}
560579
580+ // FIXME: Remove when maybe_uninit_slice is stabilized to provide MaybeUninit::slice_assume_init_ref()
581+ unsafe fn slice_assume_init_ref < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
582+ & * ( slice as * const [ MaybeUninit < T > ] as * const [ T ] )
583+ }
584+
561585#[ cfg( test) ]
562586mod tests {
563587 use super :: * ;
@@ -618,28 +642,26 @@ mod tests {
618642
619643 #[ test]
620644 fn fill_tag_bytes_truncates_long_tag ( ) {
621- let logger = AndroidLogger :: new ( Config :: default ( ) ) ;
622- let too_long_tag: [ u8 ; LOGGING_TAG_MAX_LEN + 20 ] = [ b'a' ; LOGGING_TAG_MAX_LEN + 20 ] ;
645+ let too_long_tag = [ b'a' ; LOGGING_TAG_MAX_LEN + 20 ] ;
623646
624- let mut result: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
625- logger . fill_tag_bytes ( & mut result, & too_long_tag) ;
647+ let mut result = uninit_array ( ) ;
648+ let tag = fill_tag_bytes ( & mut result, & too_long_tag) ;
626649
627- let mut expected_result = [ b'a' ; LOGGING_TAG_MAX_LEN - 2 ] . to_vec ( ) ;
650+ let mut expected_result = vec ! [ b'a' ; LOGGING_TAG_MAX_LEN - 2 ] ;
628651 expected_result. extend ( "..\0 " . as_bytes ( ) ) ;
629- assert_eq ! ( unsafe { assume_init_slice ( & result ) } , expected_result) ;
652+ assert_eq ! ( tag . to_bytes_with_nul ( ) , expected_result) ;
630653 }
631654
632655 #[ test]
633656 fn fill_tag_bytes_keeps_short_tag ( ) {
634- let logger = AndroidLogger :: new ( Config :: default ( ) ) ;
635- let short_tag: [ u8 ; 3 ] = [ b'a' ; 3 ] ;
657+ let short_tag = [ b'a' ; 3 ] ;
636658
637- let mut result: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
638- logger . fill_tag_bytes ( & mut result, & short_tag) ;
659+ let mut result = uninit_array ( ) ;
660+ let tag = fill_tag_bytes ( & mut result, & short_tag) ;
639661
640662 let mut expected_result = short_tag. to_vec ( ) ;
641663 expected_result. push ( 0 ) ;
642- assert_eq ! ( unsafe { assume_init_slice ( & result [ .. 4 ] ) } , expected_result) ;
664+ assert_eq ! ( tag . to_bytes_with_nul ( ) , expected_result) ;
643665 }
644666
645667 #[ test]
@@ -668,7 +690,7 @@ mod tests {
668690 assert_eq ! ( writer. len, 3 ) ;
669691 assert_eq ! ( writer. last_newline_index, 0 ) ;
670692 assert_eq ! (
671- unsafe { assume_init_slice ( & writer. buffer[ ..writer. len] ) } ,
693+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..writer. len] ) } ,
672694 "\n 90" . as_bytes( )
673695 ) ;
674696
@@ -710,10 +732,10 @@ mod tests {
710732 . write_str ( log_string)
711733 . expect ( "Unable to write to PlatformLogWriter" ) ;
712734
713- writer. output_specified_len ( 5 ) ;
735+ unsafe { writer. output_specified_len ( 5 ) } ;
714736
715737 assert_eq ! (
716- unsafe { assume_init_slice ( & writer. buffer[ ..log_string. len( ) ] ) } ,
738+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..log_string. len( ) ] ) } ,
717739 log_string. as_bytes( )
718740 ) ;
719741 }
@@ -728,7 +750,7 @@ mod tests {
728750 writer. copy_bytes_to_start ( 3 , 2 ) ;
729751
730752 assert_eq ! (
731- unsafe { assume_init_slice ( & writer. buffer[ ..10 ] ) } ,
753+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..10 ] ) } ,
732754 "3423456789" . as_bytes( )
733755 ) ;
734756 }
@@ -745,7 +767,7 @@ mod tests {
745767 writer. copy_bytes_to_start ( 10 , 0 ) ;
746768
747769 assert_eq ! (
748- unsafe { assume_init_slice ( & writer. buffer[ ..test_string. len( ) ] ) } ,
770+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..test_string. len( ) ] ) } ,
749771 test_string. as_bytes( )
750772 ) ;
751773 }
@@ -757,8 +779,4 @@ mod tests {
757779 CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ,
758780 )
759781 }
760-
761- unsafe fn assume_init_slice < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
762- & * ( slice as * const [ MaybeUninit < T > ] as * const [ T ] )
763- }
764782}
0 commit comments