Browse Source

make text::radix safe and const

master
Alison Watson 2 years ago
parent
commit
8af218386c
  1. 11
      source/framework/data/text.rs
  2. 4
      source/framework/vire/parser/tok.rs

11
source/framework/data/text.rs

@ -102,18 +102,15 @@ pub fn ellipsize_small_str(inp: &str) -> ([u8; 32], usize) {
/// Converts `c` to an integer unsafely. This differs from
/// `char::to_digit` in that it may be optimized into a few
/// instructions, and will convert from any base between 1 and 36.
///
/// # Safety
///
/// This function will cause undefined behaviour if `c` is not
/// `'a'..='z' | 'A'..='Z' | '0'..='9'`.
pub unsafe fn radix(c: char) -> u8 {
/// This will return 0 if `c` is out of range. You will need to ensure
/// the input is correct beforehand.
pub const fn radix(c: char) -> u8 {
c as u8
- match c {
'a'..='z' => 0x61 - 10,
'A'..='Z' => 0x41 - 10,
'0'..='9' => 0x30,
_ => std::hint::unreachable_unchecked(),
_ => 0,
}
}

4
source/framework/vire/parser/tok.rs

@ -123,7 +123,7 @@ fn read_uni_char(rd: &mut PosReader) -> Result<char, Err> {
match rd.next().ok_or(Err::Eof)? {
'}' => break,
c if c.is_digit(16) => {
let cn = unsafe { text::radix(c) }.into();
let cn = text::radix(c).into();
n = n.checked_mul(16).ok_or_else(|| Err::Numb(rd.pos()))?;
n = n.checked_add(cn).ok_or_else(|| Err::Numb(rd.pos()))?;
}
@ -193,7 +193,7 @@ fn integer_rad(rd: &mut PosReader, rad: u32) -> Result<Token, Err> {
c if is_delim(c) => break,
Some(c) if c.is_digit(rad) => {
rd.next();
let c = unsafe { text::radix(c) }.into();
let c = text::radix(c).into();
let res = n.checked_mul(rad.into());
n = res.ok_or_else(|| Err::Numb(rd.pos()))?;
let res = if sign { n.checked_sub(c) } else { n.checked_add(c) };

Loading…
Cancel
Save