2
2
3
3
//! String representations.
4
4
5
+ use alloc:: vec:: Vec ;
5
6
use core:: fmt:: { self , Write } ;
6
7
use core:: ops:: { self , Deref , Index } ;
7
8
@@ -384,13 +385,22 @@ mod tests {
384
385
/// is less than `end`.
385
386
pub ( crate ) struct RawFormatter {
386
387
// Use `usize` to use `saturating_*` functions.
387
- #[ allow( dead_code) ]
388
388
beg : usize ,
389
389
pos : usize ,
390
390
end : usize ,
391
391
}
392
392
393
393
impl RawFormatter {
394
+ /// Creates a new instance of [`RawFormatter`] with an empty buffer.
395
+ fn new ( ) -> Self {
396
+ // INVARIANT: The buffer is empty, so the region that needs to be writable is empty.
397
+ Self {
398
+ beg : 0 ,
399
+ pos : 0 ,
400
+ end : 0 ,
401
+ }
402
+ }
403
+
394
404
/// Creates a new instance of [`RawFormatter`] with the given buffer pointers.
395
405
///
396
406
/// # Safety
@@ -429,6 +439,11 @@ impl RawFormatter {
429
439
pub ( crate ) fn pos ( & self ) -> * mut u8 {
430
440
self . pos as _
431
441
}
442
+
443
+ /// Return the number of bytes written to the formatter.
444
+ pub ( crate ) fn bytes_written ( & self ) -> usize {
445
+ self . pos - self . beg
446
+ }
432
447
}
433
448
434
449
impl fmt:: Write for RawFormatter {
@@ -469,7 +484,6 @@ impl Formatter {
469
484
///
470
485
/// The memory region starting at `buf` and extending for `len` bytes must be valid for writes
471
486
/// for the lifetime of the returned [`Formatter`].
472
- #[ allow( dead_code) ]
473
487
pub ( crate ) unsafe fn from_buffer ( buf : * mut u8 , len : usize ) -> Self {
474
488
// SAFETY: The safety requirements of this function satisfy those of the callee.
475
489
Self ( unsafe { RawFormatter :: from_buffer ( buf, len) } )
@@ -496,3 +510,76 @@ impl fmt::Write for Formatter {
496
510
}
497
511
}
498
512
}
513
+
514
+ /// An owned string that is guaranteed to have exactly one `NUL` byte, which is at the end.
515
+ ///
516
+ /// Used for interoperability with kernel APIs that take C strings.
517
+ ///
518
+ /// # Invariants
519
+ ///
520
+ /// The string is always `NUL`-terminated and contains no other `NUL` bytes.
521
+ ///
522
+ /// # Examples
523
+ ///
524
+ /// ```
525
+ /// use kernel::str::CString;
526
+ ///
527
+ /// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10, 20)).unwrap();
528
+ /// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes());
529
+ ///
530
+ /// let tmp = "testing";
531
+ /// let s = CString::try_from_fmt(fmt!("{tmp}{}", 123)).unwrap();
532
+ /// assert_eq!(s.as_bytes_with_nul(), "testing123\0".as_bytes());
533
+ ///
534
+ /// // This fails because it has an embedded `NUL` byte.
535
+ /// let s = CString::try_from_fmt(fmt!("a\0b{}", 123));
536
+ /// assert_eq!(s.is_ok(), false);
537
+ /// ```
538
+ pub struct CString {
539
+ buf : Vec < u8 > ,
540
+ }
541
+
542
+ impl CString {
543
+ /// Creates an instance of [`CString`] from the given formatted arguments.
544
+ pub fn try_from_fmt ( args : fmt:: Arguments < ' _ > ) -> Result < Self , Error > {
545
+ // Calculate the size needed (formatted string plus `NUL` terminator).
546
+ let mut f = RawFormatter :: new ( ) ;
547
+ f. write_fmt ( args) ?;
548
+ f. write_str ( "\0 " ) ?;
549
+ let size = f. bytes_written ( ) ;
550
+
551
+ // Allocate a vector with the required number of bytes, and write to it.
552
+ let mut buf = Vec :: try_with_capacity ( size) ?;
553
+ // SAFETY: The buffer stored in `buf` is at least of size `size` and is valid for writes.
554
+ let mut f = unsafe { Formatter :: from_buffer ( buf. as_mut_ptr ( ) , size) } ;
555
+ f. write_fmt ( args) ?;
556
+ f. write_str ( "\0 " ) ?;
557
+
558
+ // SAFETY: The number of bytes that can be written to `f` is bounded by `size`, which is
559
+ // `buf`'s capacity. The contents of the buffer have been initialised by writes to `f`.
560
+ unsafe { buf. set_len ( f. bytes_written ( ) ) } ;
561
+
562
+ // Check that there are no `NUL` bytes before the end.
563
+ // SAFETY: The buffer is valid for read because `f.bytes_written()` is bounded by `size`
564
+ // (which the minimum buffer size) and is non-zero (we wrote at least the `NUL` terminator)
565
+ // so `f.bytes_written() - 1` doesn't underflow.
566
+ let ptr = unsafe { bindings:: memchr ( buf. as_ptr ( ) . cast ( ) , 0 , ( f. bytes_written ( ) - 1 ) as _ ) } ;
567
+ if !ptr. is_null ( ) {
568
+ return Err ( EINVAL ) ;
569
+ }
570
+
571
+ // INVARIANT: We wrote the `NUL` terminator and checked above that no other `NUL` bytes
572
+ // exist in the buffer.
573
+ Ok ( Self { buf } )
574
+ }
575
+ }
576
+
577
+ impl Deref for CString {
578
+ type Target = CStr ;
579
+
580
+ fn deref ( & self ) -> & Self :: Target {
581
+ // SAFETY: The type invariants guarantee that the string is `NUL`-terminated and that no
582
+ // other `NUL` bytes exist.
583
+ unsafe { CStr :: from_bytes_with_nul_unchecked ( self . buf . as_slice ( ) ) }
584
+ }
585
+ }
0 commit comments