Skip to content

Commit

Permalink
Switch to Rust param ops for all ints
Browse files Browse the repository at this point in the history
  • Loading branch information
adamrk committed Feb 15, 2021
1 parent 0164184 commit 1f96a0f
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 8 deletions.
74 changes: 72 additions & 2 deletions rust/kernel/module_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,76 @@ pub trait ModuleParam : core::fmt::Display + core::marker::Sized {
}
}

/// Trait for parsing integers. Strings begining with `0x`, `0o`, or `0b` are
/// parsed as hex, octal, or binary respectively. Strings beginning with `0`
/// otherwise are parsed as octal. Anything else is parsed as decimal. A
/// leading `+` or `-` is also permitted. Any string parsed by `kstrtol` or
/// `kstrtoul` will be successfully parsed.
trait ParseInt : Sized {
fn from_str_radix(src: &str, radix: u32) -> Result<Self, core::num::ParseIntError>;
fn checked_neg(self) -> Option<Self>;

fn from_str_unsigned(src: &str) -> Result<Self, core::num::ParseIntError> {
let (radix, digits) = if let Some(n) = src.strip_prefix("0x") {
(16, n)
} else if let Some(n) = src.strip_prefix("0X") {
(16, n)
} else if let Some(n) = src.strip_prefix("0o") {
(8, n)
} else if let Some(n) = src.strip_prefix("0O") {
(8, n)
} else if let Some(n) = src.strip_prefix("0b") {
(2, n)
} else if let Some(n) = src.strip_prefix("0B") {
(2, n)
} else if src.starts_with("0") {
(8, src)
} else {
(10, src)
};
Self::from_str_radix(digits, radix)
}

fn from_str(src: &str) -> Option<Self> {
match src.bytes().next() {
None => None,
Some(b'-') => Self::from_str_unsigned(&src[1..]).ok()?.checked_neg(),
Some(b'+') => Some(Self::from_str_unsigned(&src[1..]).ok()?),
Some(_) => Some(Self::from_str_unsigned(src).ok()?),
}
}
}

macro_rules! impl_parse_int {
($ty:ident) => {
impl ParseInt for $ty {
fn from_str_radix(src: &str, radix: u32) -> Result<Self, core::num::ParseIntError> {
$ty::from_str_radix(src, radix)
}
fn checked_neg(self) -> Option<Self> {
self.checked_neg()
}
}
}
}

impl_parse_int!(i8);
impl_parse_int!(u8);
impl_parse_int!(i16);
impl_parse_int!(u16);
impl_parse_int!(i32);
impl_parse_int!(u32);
impl_parse_int!(i64);
impl_parse_int!(u64);
impl_parse_int!(isize);
impl_parse_int!(usize);

macro_rules! make_param_ops {
($ops:ident, $ty:ident) => {
impl ModuleParam for $ty {
fn try_from_param_arg(arg: &[u8]) -> Option<Self> {
let utf8 = core::str::from_utf8(arg).ok()?;
utf8.parse::<$ty>().ok()
<$ty as crate::module_param::ParseInt>::from_str(utf8)
}
}

Expand All @@ -62,6 +126,12 @@ macro_rules! make_param_ops {
}

make_param_ops!(PARAM_OPS_I8, i8);
make_param_ops!(PARAM_OPS_U8, u8);
make_param_ops!(PARAM_OPS_I16, i16);
make_param_ops!(PARAM_OPS_U16, u16);
make_param_ops!(PARAM_OPS_I32, i32);
make_param_ops!(PARAM_OPS_U32, u32);
make_param_ops!(PARAM_OPS_I64, i64);
make_param_ops!(PARAM_OPS_USIZE, usize);
make_param_ops!(PARAM_OPS_U64, u64);
make_param_ops!(PARAM_OPS_ISIZE, isize);
make_param_ops!(PARAM_OPS_USIZE, usize);
12 changes: 6 additions & 6 deletions rust/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,13 +284,13 @@ pub fn module(ts: TokenStream) -> TokenStream {
let (param_kernel_type, ops) = match param_type.as_ref() {
"bool" => ("bool", "kernel::bindings::param_ops_bool"),
"i8" => ("i8", "kernel::module_param::PARAM_OPS_I8"),
"u8" => ("u8", "kernel::bindings::param_ops_char"),
"i16" => ("i16", "kernel::bindings::param_ops_short"),
"u16" => ("u16", "kernel::bindings::param_ops_ushort"),
"i32" => ("i32", "kernel::bindings::param_ops_int"),
"u32" => ("u32", "kernel::bindings::param_ops_uint"),
"u8" => ("u8", "kernel::module_param::PARAM_OPS_U8"),
"i16" => ("i16", "kernel::module_param::PARAM_OPS_I16"),
"u16" => ("u16", "kernel::module_param::PARAM_OPS_U16"),
"i32" => ("i32", "kernel::module_param::PARAM_OPS_I32"),
"u32" => ("u32", "kernel::module_param::PARAM_OPS_U32"),
"i64" => ("i64", "kernel::module_param::PARAM_OPS_I64"),
"u64" => ("u64", "kernel::bindings::param_ops_ullong"),
"u64" => ("u64", "kernel::module_param::PARAM_OPS_U64"),
"isize" => ("isize", "kernel::module_param::PARAM_OPS_ISIZE"),
"usize" => ("usize", "kernel::module_param::PARAM_OPS_USIZE"),
"str" => ("charp", "kernel::bindings::param_ops_charp"),
Expand Down

0 comments on commit 1f96a0f

Please sign in to comment.