1 // SPDX-License-Identifier: GPL-2.0 2 3 //! String representations. 4 5 use core::fmt; 6 7 /// Byte string without UTF-8 validity guarantee. 8 /// 9 /// `BStr` is simply an alias to `[u8]`, but has a more evident semantical meaning. 10 pub type BStr = [u8]; 11 12 /// Creates a new [`BStr`] from a string literal. 13 /// 14 /// `b_str!` converts the supplied string literal to byte string, so non-ASCII 15 /// characters can be included. 16 /// 17 /// # Examples 18 /// 19 /// ``` 20 /// # use kernel::b_str; 21 /// # use kernel::str::BStr; 22 /// const MY_BSTR: &BStr = b_str!("My awesome BStr!"); 23 /// ``` 24 #[macro_export] 25 macro_rules! b_str { 26 ($str:literal) => {{ 27 const S: &'static str = $str; 28 const C: &'static $crate::str::BStr = S.as_bytes(); 29 C 30 }}; 31 } 32 33 /// Allows formatting of [`fmt::Arguments`] into a raw buffer. 34 /// 35 /// It does not fail if callers write past the end of the buffer so that they can calculate the 36 /// size required to fit everything. 37 /// 38 /// # Invariants 39 /// 40 /// The memory region between `pos` (inclusive) and `end` (exclusive) is valid for writes if `pos` 41 /// is less than `end`. 42 pub(crate) struct RawFormatter { 43 // Use `usize` to use `saturating_*` functions. 44 #[allow(dead_code)] 45 beg: usize, 46 pos: usize, 47 end: usize, 48 } 49 50 impl RawFormatter { 51 /// Creates a new instance of [`RawFormatter`] with the given buffer pointers. 52 /// 53 /// # Safety 54 /// 55 /// If `pos` is less than `end`, then the region between `pos` (inclusive) and `end` 56 /// (exclusive) must be valid for writes for the lifetime of the returned [`RawFormatter`]. 57 pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self { 58 // INVARIANT: The safety requierments guarantee the type invariants. 59 Self { 60 beg: pos as _, 61 pos: pos as _, 62 end: end as _, 63 } 64 } 65 66 /// Returns the current insert position. 67 /// 68 /// N.B. It may point to invalid memory. 69 pub(crate) fn pos(&self) -> *mut u8 { 70 self.pos as _ 71 } 72 } 73 74 impl fmt::Write for RawFormatter { 75 fn write_str(&mut self, s: &str) -> fmt::Result { 76 // `pos` value after writing `len` bytes. This does not have to be bounded by `end`, but we 77 // don't want it to wrap around to 0. 78 let pos_new = self.pos.saturating_add(s.len()); 79 80 // Amount that we can copy. `saturating_sub` ensures we get 0 if `pos` goes past `end`. 81 let len_to_copy = core::cmp::min(pos_new, self.end).saturating_sub(self.pos); 82 83 if len_to_copy > 0 { 84 // SAFETY: If `len_to_copy` is non-zero, then we know `pos` has not gone past `end` 85 // yet, so it is valid for write per the type invariants. 86 unsafe { 87 core::ptr::copy_nonoverlapping( 88 s.as_bytes().as_ptr(), 89 self.pos as *mut u8, 90 len_to_copy, 91 ) 92 }; 93 } 94 95 self.pos = pos_new; 96 Ok(()) 97 } 98 } 99