Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/debugfs/traits.rs
29266 views
1
// SPDX-License-Identifier: GPL-2.0
2
// Copyright (C) 2025 Google LLC.
3
4
//! Traits for rendering or updating values exported to DebugFS.
5
6
use crate::prelude::*;
7
use crate::sync::Mutex;
8
use crate::uaccess::UserSliceReader;
9
use core::fmt::{self, Debug, Formatter};
10
use core::str::FromStr;
11
use core::sync::atomic::{
12
AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64,
13
AtomicU8, AtomicUsize, Ordering,
14
};
15
16
/// A trait for types that can be written into a string.
17
///
18
/// This works very similarly to `Debug`, and is automatically implemented if `Debug` is
19
/// implemented for a type. It is also implemented for any writable type inside a `Mutex`.
20
///
21
/// The derived implementation of `Debug` [may
22
/// change](https://doc.rust-lang.org/std/fmt/trait.Debug.html#stability)
23
/// between Rust versions, so if stability is key for your use case, please implement `Writer`
24
/// explicitly instead.
25
pub trait Writer {
26
/// Formats the value using the given formatter.
27
fn write(&self, f: &mut Formatter<'_>) -> fmt::Result;
28
}
29
30
impl<T: Writer> Writer for Mutex<T> {
31
fn write(&self, f: &mut Formatter<'_>) -> fmt::Result {
32
self.lock().write(f)
33
}
34
}
35
36
impl<T: Debug> Writer for T {
37
fn write(&self, f: &mut Formatter<'_>) -> fmt::Result {
38
writeln!(f, "{self:?}")
39
}
40
}
41
42
/// A trait for types that can be updated from a user slice.
43
///
44
/// This works similarly to `FromStr`, but operates on a `UserSliceReader` rather than a &str.
45
///
46
/// It is automatically implemented for all atomic integers, or any type that implements `FromStr`
47
/// wrapped in a `Mutex`.
48
pub trait Reader {
49
/// Updates the value from the given user slice.
50
fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result;
51
}
52
53
impl<T: FromStr> Reader for Mutex<T> {
54
fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
55
let mut buf = [0u8; 128];
56
if reader.len() > buf.len() {
57
return Err(EINVAL);
58
}
59
let n = reader.len();
60
reader.read_slice(&mut buf[..n])?;
61
62
let s = core::str::from_utf8(&buf[..n]).map_err(|_| EINVAL)?;
63
let val = s.trim().parse::<T>().map_err(|_| EINVAL)?;
64
*self.lock() = val;
65
Ok(())
66
}
67
}
68
69
macro_rules! impl_reader_for_atomic {
70
($(($atomic_type:ty, $int_type:ty)),*) => {
71
$(
72
impl Reader for $atomic_type {
73
fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
74
let mut buf = [0u8; 21]; // Enough for a 64-bit number.
75
if reader.len() > buf.len() {
76
return Err(EINVAL);
77
}
78
let n = reader.len();
79
reader.read_slice(&mut buf[..n])?;
80
81
let s = core::str::from_utf8(&buf[..n]).map_err(|_| EINVAL)?;
82
let val = s.trim().parse::<$int_type>().map_err(|_| EINVAL)?;
83
self.store(val, Ordering::Relaxed);
84
Ok(())
85
}
86
}
87
)*
88
};
89
}
90
91
impl_reader_for_atomic!(
92
(AtomicI16, i16),
93
(AtomicI32, i32),
94
(AtomicI64, i64),
95
(AtomicI8, i8),
96
(AtomicIsize, isize),
97
(AtomicU16, u16),
98
(AtomicU32, u32),
99
(AtomicU64, u64),
100
(AtomicU8, u8),
101
(AtomicUsize, usize)
102
);
103
104