summaryrefslogtreecommitdiffstats
path: root/rust/kernel/str.rs
diff options
context:
space:
mode:
authorWedson Almeida Filho <wedsonaf@google.com>2022-02-11 20:25:34 +0100
committerMiguel Ojeda <ojeda@kernel.org>2022-09-28 08:58:24 +0200
commit247b365dc8dc442412c88fe02346cd2bddac7bd6 (patch)
treed918dcc69e0f83ec5f6eb9e56883a1700cf4efcb /rust/kernel/str.rs
parent8326ac05ee8841e625a6a54d225242eec579fa13 (diff)
downloadlinux-247b365dc8dc442412c88fe02346cd2bddac7bd6.tar.bz2
rust: add `kernel` crate
The `kernel` crate currently includes all the abstractions that wrap kernel features written in C. These abstractions call the C side of the kernel via the generated bindings with the `bindgen` tool. Modules developed in Rust should never call the bindings themselves. In the future, as the abstractions grow in number, we may need to split this crate into several, possibly following a similar subdivision in subsystems as the kernel itself and/or moving the code to the actual subsystems. Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com> Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com> Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com> Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com> Co-developed-by: Finn Behrens <me@kloenk.de> Signed-off-by: Finn Behrens <me@kloenk.de> Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com> Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com> Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com> Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com> Co-developed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Gary Guo <gary@garyguo.net> Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de> Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de> Co-developed-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Boqun Feng <boqun.feng@gmail.com> Co-developed-by: Fox Chen <foxhlchen@gmail.com> Signed-off-by: Fox Chen <foxhlchen@gmail.com> Co-developed-by: Viktor Garske <viktor@v-gar.de> Signed-off-by: Viktor Garske <viktor@v-gar.de> Co-developed-by: Dariusz Sosnowski <dsosnowski@dsosnowski.pl> Signed-off-by: Dariusz Sosnowski <dsosnowski@dsosnowski.pl> Co-developed-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com> Signed-off-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com> Co-developed-by: Niklas Mohrin <dev@niklasmohrin.de> Signed-off-by: Niklas Mohrin <dev@niklasmohrin.de> Co-developed-by: Milan Landaverde <milan@mdaverde.com> Signed-off-by: Milan Landaverde <milan@mdaverde.com> Co-developed-by: Morgan Bartlett <mjmouse9999@gmail.com> Signed-off-by: Morgan Bartlett <mjmouse9999@gmail.com> Co-developed-by: Maciej Falkowski <m.falkowski@samsung.com> Signed-off-by: Maciej Falkowski <m.falkowski@samsung.com> Co-developed-by: Nándor István Krácser <bonifaido@gmail.com> Signed-off-by: Nándor István Krácser <bonifaido@gmail.com> Co-developed-by: David Gow <davidgow@google.com> Signed-off-by: David Gow <davidgow@google.com> Co-developed-by: John Baublitz <john.m.baublitz@gmail.com> Signed-off-by: John Baublitz <john.m.baublitz@gmail.com> Co-developed-by: Björn Roy Baron <bjorn3_gh@protonmail.com> Signed-off-by: Björn Roy Baron <bjorn3_gh@protonmail.com> Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com> Co-developed-by: Miguel Ojeda <ojeda@kernel.org> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Diffstat (limited to 'rust/kernel/str.rs')
-rw-r--r--rust/kernel/str.rs72
1 files changed, 72 insertions, 0 deletions
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
new file mode 100644
index 000000000000..e45ff220ae50
--- /dev/null
+++ b/rust/kernel/str.rs
@@ -0,0 +1,72 @@
+// 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(())
+ }
+}