Wedson Almeida Filhorust: add `kernel` crate247b3654 years agoHistory
72 lines · 2.2 KB · Rust
RawDownload
// SPDX-License-Identifier: GPL-2.0 //! String representations. use core::fmt; /// Allows formatting of [`fmt::Arguments`] into a raw buffer.////// It does not fail if callers write past the end of the buffer so that they can calculate the/// size required to fit everything.////// # Invariants////// The memory region between `pos` (inclusive) and `end` (exclusive) is valid for writes if `pos`/// is less than `end`.pub(crate) struct RawFormatter {    // Use `usize` to use `saturating_*` functions.    #[allow(dead_code)]    beg: usize,    pos: usize,    end: usize,} impl RawFormatter {    /// Creates a new instance of [`RawFormatter`] with the given buffer pointers.    ///    /// # Safety    ///    /// If `pos` is less than `end`, then the region between `pos` (inclusive) and `end`    /// (exclusive) must be valid for writes for the lifetime of the returned [`RawFormatter`].    pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self {        // INVARIANT: The safety requierments guarantee the type invariants.        Self {            beg: pos as _,            pos: pos as _,            end: end as _,        }    }     /// Returns the current insert position.    ///    /// N.B. It may point to invalid memory.    pub(crate) fn pos(&self) -> *mut u8 {        self.pos as _    }} impl fmt::Write for RawFormatter {    fn write_str(&mut self, s: &str) -> fmt::Result {        // `pos` value after writing `len` bytes. This does not have to be bounded by `end`, but we        // don't want it to wrap around to 0.        let pos_new = self.pos.saturating_add(s.len());         // Amount that we can copy. `saturating_sub` ensures we get 0 if `pos` goes past `end`.        let len_to_copy = core::cmp::min(pos_new, self.end).saturating_sub(self.pos);         if len_to_copy > 0 {            // SAFETY: If `len_to_copy` is non-zero, then we know `pos` has not gone past `end`            // yet, so it is valid for write per the type invariants.            unsafe {                core::ptr::copy_nonoverlapping(                    s.as_bytes().as_ptr(),                    self.pos as *mut u8,                    len_to_copy,                )            };        }         self.pos = pos_new;        Ok(())    }}