@@ -72,15 +72,15 @@ extern crate log;
72
72
73
73
extern crate env_logger;
74
74
75
+ use log:: { Level , Log , Metadata , Record } ;
75
76
#[ cfg( target_os = "android" ) ]
76
77
use log_ffi:: LogPriority ;
77
- use log:: { Level , Log , Metadata , Record } ;
78
78
use std:: ffi:: { CStr , CString } ;
79
- use std:: mem;
80
79
use std:: fmt;
80
+ use std:: mem:: { self , MaybeUninit } ;
81
81
use std:: ptr;
82
82
83
- pub use env_logger:: filter:: { Filter , Builder as FilterBuilder } ;
83
+ pub use env_logger:: filter:: { Builder as FilterBuilder , Filter } ;
84
84
pub use env_logger:: fmt:: Formatter ;
85
85
86
86
pub ( crate ) type FormatFn = Box < dyn Fn ( & mut dyn fmt:: Write , & Record ) -> fmt:: Result + Sync + Send > ;
@@ -115,7 +115,6 @@ impl AndroidLogger {
115
115
}
116
116
}
117
117
118
-
119
118
static ANDROID_LOGGER : OnceCell < AndroidLogger > = OnceCell :: new ( ) ;
120
119
121
120
const LOGGING_TAG_MAX_LEN : usize = 23 ;
@@ -136,22 +135,23 @@ impl Log for AndroidLogger {
136
135
}
137
136
138
137
fn log ( & self , record : & Record ) {
139
- let config = self . config
140
- . get_or_init ( Config :: default) ;
138
+ let config = self . config . get_or_init ( Config :: default) ;
141
139
142
140
if !config. filter_matches ( record) {
143
141
return ;
144
142
}
145
143
146
144
// tag must not exceed LOGGING_TAG_MAX_LEN
147
- #[ allow( deprecated) ] // created an issue #35 for this
148
- let mut tag_bytes: [ u8 ; LOGGING_TAG_MAX_LEN + 1 ] = unsafe { mem:: uninitialized ( ) } ;
145
+ let mut tag_bytes: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
149
146
150
147
let module_path = record. module_path ( ) . unwrap_or_default ( ) . to_owned ( ) ;
151
148
152
149
// If no tag was specified, use module name
153
150
let custom_tag = & config. tag ;
154
- let tag = custom_tag. as_ref ( ) . map ( |s| s. as_bytes ( ) ) . unwrap_or_else ( || module_path. as_bytes ( ) ) ;
151
+ let tag = custom_tag
152
+ . as_ref ( )
153
+ . map ( |s| s. as_bytes ( ) )
154
+ . unwrap_or_else ( || module_path. as_bytes ( ) ) ;
155
155
156
156
// truncate the tag here to fit into LOGGING_TAG_MAX_LEN
157
157
self . fill_tag_bytes ( & mut tag_bytes, tag) ;
@@ -181,21 +181,19 @@ impl Log for AndroidLogger {
181
181
}
182
182
183
183
impl AndroidLogger {
184
- fn fill_tag_bytes ( & self , array : & mut [ u8 ] , tag : & [ u8 ] ) {
184
+ fn fill_tag_bytes ( & self , array : & mut [ MaybeUninit < u8 > ] , tag : & [ u8 ] ) {
185
185
if tag. len ( ) > LOGGING_TAG_MAX_LEN {
186
- for ( input, output) in tag. iter ( )
186
+ for ( input, output) in tag
187
+ . iter ( )
187
188
. take ( LOGGING_TAG_MAX_LEN - 2 )
188
189
. chain ( b"..\0 " . iter ( ) )
189
190
. zip ( array. iter_mut ( ) )
190
191
{
191
- * output = * input;
192
+ output. write ( * input) ;
192
193
}
193
194
} else {
194
- for ( input, output) in tag. iter ( )
195
- . chain ( b"\0 " . iter ( ) )
196
- . zip ( array. iter_mut ( ) )
197
- {
198
- * output = * input;
195
+ for ( input, output) in tag. iter ( ) . chain ( b"\0 " . iter ( ) ) . zip ( array. iter_mut ( ) ) {
196
+ output. write ( * input) ;
199
197
}
200
198
}
201
199
}
@@ -257,12 +255,14 @@ impl Config {
257
255
}
258
256
259
257
pub struct PlatformLogWriter < ' a > {
260
- #[ cfg( target_os = "android" ) ] priority : LogPriority ,
261
- #[ cfg( not( target_os = "android" ) ) ] priority : Level ,
258
+ #[ cfg( target_os = "android" ) ]
259
+ priority : LogPriority ,
260
+ #[ cfg( not( target_os = "android" ) ) ]
261
+ priority : Level ,
262
262
len : usize ,
263
263
last_newline_index : usize ,
264
264
tag : & ' a CStr ,
265
- buffer : [ u8 ; LOGGING_MSG_MAX_LEN + 1 ] ,
265
+ buffer : [ MaybeUninit < u8 > ; LOGGING_MSG_MAX_LEN + 1 ] ,
266
266
}
267
267
268
268
impl < ' a > PlatformLogWriter < ' a > {
@@ -280,7 +280,7 @@ impl<'a> PlatformLogWriter<'a> {
280
280
len : 0 ,
281
281
last_newline_index : 0 ,
282
282
tag,
283
- buffer : unsafe { mem :: uninitialized ( ) } ,
283
+ buffer : uninit_array ( ) ,
284
284
}
285
285
}
286
286
@@ -292,7 +292,7 @@ impl<'a> PlatformLogWriter<'a> {
292
292
len : 0 ,
293
293
last_newline_index : 0 ,
294
294
tag,
295
- buffer : unsafe { mem :: uninitialized ( ) } ,
295
+ buffer : uninit_array ( ) ,
296
296
}
297
297
}
298
298
@@ -338,21 +338,22 @@ impl<'a> PlatformLogWriter<'a> {
338
338
339
339
/// Output buffer up until the \0 which will be placed at `len` position.
340
340
fn output_specified_len ( & mut self , len : usize ) {
341
- let mut last_byte: u8 = b'\0' ;
341
+ let mut last_byte = MaybeUninit :: new ( b'\0' ) ;
342
+
342
343
mem:: swap ( & mut last_byte, unsafe {
343
344
self . buffer . get_unchecked_mut ( len)
344
345
} ) ;
345
346
346
- let msg: & CStr = unsafe { CStr :: from_ptr ( mem :: transmute ( self . buffer . as_ptr ( ) ) ) } ;
347
+ let msg: & CStr = unsafe { CStr :: from_ptr ( self . buffer . as_ptr ( ) . cast ( ) ) } ;
347
348
android_log ( self . priority , self . tag , msg) ;
348
349
349
- * unsafe { self . buffer . get_unchecked_mut ( len) } = last_byte;
350
+ unsafe { * self . buffer . get_unchecked_mut ( len) = last_byte } ;
350
351
}
351
352
352
353
/// Copy `len` bytes from `index` position to starting position.
353
354
fn copy_bytes_to_start ( & mut self , index : usize , len : usize ) {
354
- let src = unsafe { self . buffer . as_ptr ( ) . add ( index) } ;
355
355
let dst = self . buffer . as_mut_ptr ( ) ;
356
+ let src = unsafe { self . buffer . as_ptr ( ) . add ( index) } ;
356
357
unsafe { ptr:: copy ( src, dst, len) } ;
357
358
}
358
359
}
@@ -371,7 +372,7 @@ impl<'a> fmt::Write for PlatformLogWriter<'a> {
371
372
. zip ( incomming_bytes)
372
373
. enumerate ( )
373
374
. fold ( None , |acc, ( i, ( output, input) ) | {
374
- * output = * input;
375
+ output. write ( * input) ;
375
376
if * input == b'\n' {
376
377
Some ( i)
377
378
} else {
@@ -409,7 +410,9 @@ impl<'a> fmt::Write for PlatformLogWriter<'a> {
409
410
/// This action does not require initialization. However, without initialization it
410
411
/// will use the default filter, which allows all logs.
411
412
pub fn log ( record : & Record ) {
412
- ANDROID_LOGGER . get_or_init ( AndroidLogger :: default) . log ( record)
413
+ ANDROID_LOGGER
414
+ . get_or_init ( AndroidLogger :: default)
415
+ . log ( record)
413
416
}
414
417
415
418
/// Initializes the global logger with an android logger.
@@ -430,6 +433,12 @@ pub fn init_once(config: Config) {
430
433
}
431
434
}
432
435
436
+ // FIXME: When `maybe_uninit_uninit_array ` is stabilized, use it instead of this helper
437
+ fn uninit_array < const N : usize , T > ( ) -> [ MaybeUninit < T > ; N ] {
438
+ // SAFETY: Array contains MaybeUninit, which is fine to be uninit
439
+ unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) }
440
+ }
441
+
433
442
#[ cfg( test) ]
434
443
mod tests {
435
444
use super :: * ;
@@ -489,25 +498,25 @@ mod tests {
489
498
let logger = AndroidLogger :: new ( Config :: default ( ) ) ;
490
499
let too_long_tag: [ u8 ; LOGGING_TAG_MAX_LEN + 20 ] = [ b'a' ; LOGGING_TAG_MAX_LEN + 20 ] ;
491
500
492
- let mut result: [ u8 ; LOGGING_TAG_MAX_LEN + 1 ] = Default :: default ( ) ;
501
+ let mut result: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
493
502
logger. fill_tag_bytes ( & mut result, & too_long_tag) ;
494
503
495
504
let mut expected_result = [ b'a' ; LOGGING_TAG_MAX_LEN - 2 ] . to_vec ( ) ;
496
505
expected_result. extend ( "..\0 " . as_bytes ( ) ) ;
497
- assert_eq ! ( result . to_vec ( ) , expected_result) ;
506
+ assert_eq ! ( unsafe { assume_init_slice ( & result ) } , expected_result) ;
498
507
}
499
508
500
509
#[ test]
501
510
fn fill_tag_bytes_keeps_short_tag ( ) {
502
511
let logger = AndroidLogger :: new ( Config :: default ( ) ) ;
503
512
let short_tag: [ u8 ; 3 ] = [ b'a' ; 3 ] ;
504
513
505
- let mut result: [ u8 ; LOGGING_TAG_MAX_LEN + 1 ] = Default :: default ( ) ;
514
+ let mut result: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
506
515
logger. fill_tag_bytes ( & mut result, & short_tag) ;
507
516
508
517
let mut expected_result = short_tag. to_vec ( ) ;
509
518
expected_result. push ( 0 ) ;
510
- assert_eq ! ( result . to_vec ( ) [ ..4 ] , expected_result) ;
519
+ assert_eq ! ( unsafe { assume_init_slice ( & result [ ..4 ] ) } , expected_result) ;
511
520
}
512
521
513
522
#[ test]
@@ -535,7 +544,10 @@ mod tests {
535
544
// Should have flushed up until the last newline.
536
545
assert_eq ! ( writer. len, 3 ) ;
537
546
assert_eq ! ( writer. last_newline_index, 0 ) ;
538
- assert_eq ! ( & writer. buffer. to_vec( ) [ ..writer. len] , "\n 90" . as_bytes( ) ) ;
547
+ assert_eq ! (
548
+ unsafe { assume_init_slice( & writer. buffer[ ..writer. len] ) } ,
549
+ "\n 90" . as_bytes( )
550
+ ) ;
539
551
540
552
writer. temporal_flush ( ) ;
541
553
// Should have flushed all remaining bytes.
@@ -578,7 +590,7 @@ mod tests {
578
590
writer. output_specified_len ( 5 ) ;
579
591
580
592
assert_eq ! (
581
- writer. buffer[ ..log_string. len( ) ] . to_vec ( ) ,
593
+ unsafe { assume_init_slice ( & writer. buffer[ ..log_string. len( ) ] ) } ,
582
594
log_string. as_bytes( )
583
595
) ;
584
596
}
@@ -592,7 +604,10 @@ mod tests {
592
604
593
605
writer. copy_bytes_to_start ( 3 , 2 ) ;
594
606
595
- assert_eq ! ( writer. buffer[ ..10 ] . to_vec( ) , "3423456789" . as_bytes( ) ) ;
607
+ assert_eq ! (
608
+ unsafe { assume_init_slice( & writer. buffer[ ..10 ] ) } ,
609
+ "3423456789" . as_bytes( )
610
+ ) ;
596
611
}
597
612
598
613
#[ test]
@@ -607,12 +622,16 @@ mod tests {
607
622
writer. copy_bytes_to_start ( 10 , 0 ) ;
608
623
609
624
assert_eq ! (
610
- writer. buffer[ ..test_string. len( ) ] . to_vec ( ) ,
625
+ unsafe { assume_init_slice ( & writer. buffer[ ..test_string. len( ) ] ) } ,
611
626
test_string. as_bytes( )
612
627
) ;
613
628
}
614
629
615
630
fn get_tag_writer ( ) -> PlatformLogWriter < ' static > {
616
631
PlatformLogWriter :: new ( Level :: Warn , CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) )
617
632
}
633
+
634
+ unsafe fn assume_init_slice < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
635
+ & * ( slice as * const [ MaybeUninit < T > ] as * const [ T ] )
636
+ }
618
637
}
0 commit comments