Skip to content

Instantly share code, notes, and snippets.

@DutchGhost
Created November 24, 2022 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DutchGhost/112ab45cda7ed2b85ac34475a43bbd22 to your computer and use it in GitHub Desktop.
Save DutchGhost/112ab45cda7ed2b85ac34475a43bbd22 to your computer and use it in GitHub Desktop.
Parsed. Const parsing of strings to integral types
#![feature(const_for)]
#![feature(const_refs_to_cell)]
#![feature(const_trait_impl)]
#![feature(generic_const_exprs)]
use {
core::{
ops::{Div, Mul, Not, Add}
},
};
trait Properties:
~const From<u8> +
~const PartialEq +
~const PartialOrd +
~const Mul<Output = Self> +
~const Div<Output = Self> +
~const Not<Output = Self> +
Copy
{
const ZERO: Self = Self::from(0u8);
const MAX: Self = !Self::from(0u8);
const DIGITS10: usize = {
let ten = Self::from(10);
let multipliers = [
ten,
ten * ten,
ten * ten * ten,
ten * ten * ten * ten
];
let mut result: usize = 1;
let mut current = Self::MAX;
loop {
if current < multipliers[0] { break result }
if current < multipliers[1] { break result + 1 }
if current < multipliers[2] { break result + 2 }
if current < multipliers[3] { break result + 3 }
current = current / multipliers[3];
result += 4;
}
};
}
impl <T> Properties for T where T:
~const From<u8> +
~const PartialEq +
~const PartialOrd +
~const Mul<Output = Self> +
~const Div<Output = Self> +
~const Not<Output = Self> +
Copy
{}
trait Table:
Properties +
~const From<u8> +
~const Mul<Output = Self>
where
[(); <Self as Properties>::DIGITS10]:
{
const TABLE: [Self; Self::DIGITS10] = {
let mut a = [Self::from(0); Self::DIGITS10];
let multiplier: Self = Self::from(10u8);
let mut current: Self = Self::from(1u8);
let mut idx = <Self as Properties>::DIGITS10 - 1;
// do while...
while {
a[idx] = current;
idx != 0
}
{
current = current * multiplier;
idx -= 1;
}
a
};
}
impl <T> Table for T where T:
Properties +
~const Default +
~const From<u8> +
~const Mul<Output = Self>,
[(); <Self as Properties>::DIGITS10]:
{}
#[derive(Clone, Copy, Debug)]
enum ParseIntError {
InvalidDigit,
}
const fn parse_byte<T>(b: u8, pow10: T) -> Result<T, ParseIntError>
where
T: ~const From<u8> + ~const Mul<Output = T> + Copy,
{
let r = b.wrapping_sub(48);
if r > 9 {
Err(ParseIntError::InvalidDigit)
} else {
Ok(T::from(r) * pow10)
}
}
const fn parse<T>(b: &str) -> Result<T, ParseIntError>
where
T: Table +
Properties +
~const From<u8> +
~const Mul<Output = T> +
~const Add<Output = T>,
[(); <T as Properties>::DIGITS10]:
{
let bytes = b.as_bytes();
let mut result: T = T::ZERO;
let len = bytes.len();
// Start at the correct index of the table,
// (skip the power's that are too large)
let mut index_const_table = <T as Table>::TABLE.len() - len;
let mut index = 0;
while index < b.len() {
let a = bytes[index];
let p = <T as Table>::TABLE[index_const_table];
let r = match parse_byte(a, p) {
Err(e) => return Err(e),
Ok(d) => d,
};
result = result + r;
index += 1;
index_const_table += 1;
}
Ok(result)
}
const fn unwarp<T: Copy>(opt: Result<T, ParseIntError>) -> T {
match opt {
Ok(t) => t,
_ => loop {}
}
}
const A: u16 = unwarp(parse::<u16>("1234"));
const B: u32 = unwarp(parse::<u32>("1234"));
const C: u64 = unwarp(parse::<u64>("1234"));
const D: usize = unwarp(parse::<usize>("1234"));
fn main() {
dbg!(A, B, C, D);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment