@@ -227,10 +227,8 @@ impl Log for AndroidLogger {
227
227
// In case we end up allocating, keep the CString alive.
228
228
let _owned_tag;
229
229
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)
234
232
} else {
235
233
// Tag longer than available stack buffer; allocate.
236
234
// We're using either
@@ -264,23 +262,38 @@ impl Log for AndroidLogger {
264
262
fn flush ( & self ) { }
265
263
}
266
264
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) ;
282
284
}
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" )
284
297
}
285
298
286
299
/// Filter for android logger.
@@ -369,7 +382,7 @@ pub struct PlatformLogWriter<'a> {
369
382
buffer : [ MaybeUninit < u8 > ; LOGGING_MSG_MAX_LEN + 1 ] ,
370
383
}
371
384
372
- impl < ' a > PlatformLogWriter < ' a > {
385
+ impl PlatformLogWriter < ' _ > {
373
386
#[ cfg( target_os = "android" ) ]
374
387
pub fn new_with_priority (
375
388
buf_id : Option < LogId > ,
@@ -432,11 +445,11 @@ impl<'a> PlatformLogWriter<'a> {
432
445
let copy_from_index = self . last_newline_index ;
433
446
let remaining_chunk_len = total_len - copy_from_index;
434
447
435
- self . output_specified_len ( copy_from_index) ;
448
+ unsafe { self . output_specified_len ( copy_from_index) } ;
436
449
self . copy_bytes_to_start ( copy_from_index, remaining_chunk_len) ;
437
450
self . len = remaining_chunk_len;
438
451
} else {
439
- self . output_specified_len ( total_len) ;
452
+ unsafe { self . output_specified_len ( total_len) } ;
440
453
self . len = 0 ;
441
454
}
442
455
self . last_newline_index = 0 ;
@@ -450,20 +463,26 @@ impl<'a> PlatformLogWriter<'a> {
450
463
return ;
451
464
}
452
465
453
- self . output_specified_len ( total_len) ;
466
+ unsafe { self . output_specified_len ( total_len) } ;
454
467
self . len = 0 ;
455
468
self . last_newline_index = 0 ;
456
469
}
457
470
458
471
/// 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 ) {
460
476
let mut last_byte = MaybeUninit :: new ( b'\0' ) ;
461
477
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
+ ) ;
465
482
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`" ) ;
467
486
android_log ( self . buf_id , self . priority , self . tag , msg) ;
468
487
469
488
unsafe { * self . buffer . get_unchecked_mut ( len) = last_byte } ;
@@ -477,18 +496,18 @@ impl<'a> PlatformLogWriter<'a> {
477
496
}
478
497
}
479
498
480
- impl < ' a > fmt:: Write for PlatformLogWriter < ' a > {
499
+ impl fmt:: Write for PlatformLogWriter < ' _ > {
481
500
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 ( ) ;
483
502
484
- while !incomming_bytes . is_empty ( ) {
503
+ while !incoming_bytes . is_empty ( ) {
485
504
let len = self . len ;
486
505
487
506
// 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 ( ) ;
489
508
let last_newline = self . buffer [ len..LOGGING_MSG_MAX_LEN ]
490
509
. iter_mut ( )
491
- . zip ( incomming_bytes )
510
+ . zip ( incoming_bytes )
492
511
. enumerate ( )
493
512
. fold ( None , |acc, ( i, ( output, input) ) | {
494
513
output. write ( * input) ;
@@ -517,7 +536,7 @@ impl<'a> fmt::Write for PlatformLogWriter<'a> {
517
536
LOGGING_MSG_MAX_LEN - len // written len
518
537
} ;
519
538
520
- incomming_bytes = & incomming_bytes [ written_len..] ;
539
+ incoming_bytes = & incoming_bytes [ written_len..] ;
521
540
}
522
541
523
542
Ok ( ( ) )
@@ -558,6 +577,11 @@ fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] {
558
577
unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) }
559
578
}
560
579
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
+
561
585
#[ cfg( test) ]
562
586
mod tests {
563
587
use super :: * ;
@@ -618,28 +642,26 @@ mod tests {
618
642
619
643
#[ test]
620
644
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 ] ;
623
646
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) ;
626
649
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 ] ;
628
651
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) ;
630
653
}
631
654
632
655
#[ test]
633
656
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 ] ;
636
658
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) ;
639
661
640
662
let mut expected_result = short_tag. to_vec ( ) ;
641
663
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) ;
643
665
}
644
666
645
667
#[ test]
@@ -668,7 +690,7 @@ mod tests {
668
690
assert_eq ! ( writer. len, 3 ) ;
669
691
assert_eq ! ( writer. last_newline_index, 0 ) ;
670
692
assert_eq ! (
671
- unsafe { assume_init_slice ( & writer. buffer[ ..writer. len] ) } ,
693
+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..writer. len] ) } ,
672
694
"\n 90" . as_bytes( )
673
695
) ;
674
696
@@ -710,10 +732,10 @@ mod tests {
710
732
. write_str ( log_string)
711
733
. expect ( "Unable to write to PlatformLogWriter" ) ;
712
734
713
- writer. output_specified_len ( 5 ) ;
735
+ unsafe { writer. output_specified_len ( 5 ) } ;
714
736
715
737
assert_eq ! (
716
- unsafe { assume_init_slice ( & writer. buffer[ ..log_string. len( ) ] ) } ,
738
+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..log_string. len( ) ] ) } ,
717
739
log_string. as_bytes( )
718
740
) ;
719
741
}
@@ -728,7 +750,7 @@ mod tests {
728
750
writer. copy_bytes_to_start ( 3 , 2 ) ;
729
751
730
752
assert_eq ! (
731
- unsafe { assume_init_slice ( & writer. buffer[ ..10 ] ) } ,
753
+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..10 ] ) } ,
732
754
"3423456789" . as_bytes( )
733
755
) ;
734
756
}
@@ -745,7 +767,7 @@ mod tests {
745
767
writer. copy_bytes_to_start ( 10 , 0 ) ;
746
768
747
769
assert_eq ! (
748
- unsafe { assume_init_slice ( & writer. buffer[ ..test_string. len( ) ] ) } ,
770
+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..test_string. len( ) ] ) } ,
749
771
test_string. as_bytes( )
750
772
) ;
751
773
}
@@ -757,8 +779,4 @@ mod tests {
757
779
CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ,
758
780
)
759
781
}
760
-
761
- unsafe fn assume_init_slice < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
762
- & * ( slice as * const [ MaybeUninit < T > ] as * const [ T ] )
763
- }
764
782
}
0 commit comments