rodrimati1992 / konst Goto Github PK
View Code? Open in Web Editor NEWConst equivalents of std functions, compile-time comparison, and parsing.
License: zlib License
Const equivalents of std functions, compile-time comparison, and parsing.
License: zlib License
It'd be super useful!
im building my code with stable
compiler
error
error[E0554]: `#![feature]` may not be used on the stable release channel
--> /home/alexzander/.cargo/registry/src/github.com-1ecc6299db9ec823/konst_macro_rules-0.2.13/src/lib.rs:3:42
|
3 | #![cfg_attr(feature = "deref_raw_in_fn", feature(const_fn_union))]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: remove the attribute
|
= help: the feature `const_fn_union` has been stable since 1.56.0 and no longer requires an attribute to enable
rustc -V
: rustc 1.62.0 (a8314ef7d 2022-06-27)
question: must i have a nightly
compiler to use this crate ?
Hey! Again, thanks for your work, I'm more and more amazed by Rust and what can be done at compile time, and that's clearly made possible thanks to your crate.
Not a real issue, sorry about that. Yet I was hoping you could help me with that one, I guess it could help others as well.
I'm trying to parse a string at compile time, which represents an array of structs, and the structs contain a slice of strings.
Let's say I have the following struct:
struct Person<'p> {
name: &'p str,
age: u8,
hobbies: &'p[&'p str],
}
And in an environment variable I have the following string (I added line returns and whitespaces for clarity, but there aren't any):
bob[FIELD_DELIM]
42[FIELD_DELIM]
[HOBBY_START]soccer
[HOBBY_START]paint
[PERSON_DELIM]
alice[FIELD_DELIM]
4[FIELD_DELIM]
Alice has no hobby.
I don't use a "delimiter" for the hobbies but rather a "start" token so that I can easily count how many hobbies a person has using something like:
const HOBBIES_COUNT: usize = collect_const!(&str => split(person, "[HOBBY_START]")).len() - 1;
First, I started by splitting the string on the person delimiter and convert it to an array like so:
const PERSON_SLICE: &[&str] = &iter::collect_const!(&str => split(PARSE_ME, PERSON_DELIM));
const PERSON_ARRAY: &[&str; PERSON_SLICE.len()] = unwrap_ctx!(slice::try_into_array(PERSON_SLICE));
Then I want to build an array of Person
by calling the parse_person()
const function:
const PEOPLE: &[Person; PERSON_SLICE.len()] = &array::map!(PERSON_ARRAY, |person| unwrap_ctx!(
parse_person(Parser::new(person))
)
.0);
Here's what my parse_person
function looks like:
const fn parse_person(parser: Parser<'_>) -> ParseValueResult<'_, Person> {
let (name, parser) = try_!(parser.split(FIELD_DELIM));
let (age_str, parser) = try_!(parser.split(FIELD_DELIM));
let (hobbies_str, parser) = try_!(parser.split(FIELD_DELIM));
let mut hobbies = [""; 100]; // FIXME: how to set the approriate size ?
let splittable_hobbies = find_skip(hobbies_str, HOBBY_START);
if let Some(splittable_hobbies) = splittable_hobbies {
let hobbies_iter = split(splittable_hobbies, HOBBY_START);
for_each! { (i, hobby) in hobbies_iter,enumerate() =>
hobbies[i] = hobby
};
}
Ok((
Person {
name,
age: unwrap_ctx!(parse_u8(age_str)),
hobbies: &hobbies,
},
parser,
))
}
Obviously it doesn't compile because I'm trying to put a reference to a local variable in the struct. But I guess it illustrates what I'm trying to do. Also, I'm unable to get the hobbies count because it is considered "dynamic in a const context".
Is what I'm trying to do even possible ? How would you proceed ?
Here's the full code of my POC:
use konst::{
array,
iter::{self, for_each},
parsing::ParseValueResult,
primitive::parse_u8,
slice,
string::{find_skip, split},
try_, unwrap_ctx, Parser,
};
const PERSON_DELIM: &str = "[PERSON_DELIM]";
const FIELD_DELIM: &str = "[FIELD_DELIM]";
const HOBBY_START: &str = "[HOBBY_START]";
const PARSE_ME: &str = "bob[FIELD_DELIM]42[FIELD_DELIM][HOBBY_START]soccer[HOBBY_START]paint[PERSON_DELIM]alice[FIELD_DELIM]4[FIELD_DELIM]";
const PERSON_SLICE: &[&str] = &iter::collect_const!(&str => split(PARSE_ME, PERSON_DELIM));
const PERSON_ARRAY: &[&str; PERSON_SLICE.len()] = unwrap_ctx!(slice::try_into_array(PERSON_SLICE));
const PEOPLE: &[Person; PERSON_SLICE.len()] = &array::map!(PERSON_ARRAY, |person| unwrap_ctx!(
parse_person(Parser::new(person))
)
.0);
struct Person<'p> {
name: &'p str,
age: u8,
hobbies: &'p [&'p str],
}
const fn parse_person(parser: Parser<'_>) -> ParseValueResult<'_, Person> {
let (name, parser) = try_!(parser.split(FIELD_DELIM));
let (age_str, parser) = try_!(parser.split(FIELD_DELIM));
let (hobbies_str, parser) = try_!(parser.split(FIELD_DELIM));
let mut hobbies = [""; 100]; // FIXME: how to set the approriate size ?
let splittable_hobbies = find_skip(hobbies_str, HOBBY_START);
if let Some(splittable_hobbies) = splittable_hobbies {
let hobbies_iter = split(splittable_hobbies, HOBBY_START);
for_each! { (i, hobby) in hobbies_iter,enumerate() =>
hobbies[i] = hobby
};
}
Ok((
Person {
name,
age: unwrap_ctx!(parse_u8(age_str)),
hobbies: &hobbies,
},
parser,
))
}
fn main() {
for person in PEOPLE {
println!("===========");
println!("Name: {}", person.name);
println!("Age: {}", person.age);
println!("Hobbies:");
for hobby in person.hobbies {
println!("- {hobby}");
}
}
}
Hey, thanks a lot for your work!
I adapted your CSV example to this:
const TEST: &str = env!("TEST");
static PARSED: [&str; 2] = iter::collect_const!(&str =>
string::split(TEST, ","),
map(string::trim),
);
Unfortunately the Rust compiler doesn't let me compile the code if there are not exactly 4 delimiters in the TEST environment variable. I looked at the documentation and didn't find anything that would allow me to use any size without having to change the source code.
I'm pretty new to Rust and I'm not even sure what I'm asking for is possible, but I imagined one of the two things:
static PARSED: Vec<&str> = konst::vectorize!(iter::collect_const!(&str =>
string::split(TEST, ","),
map(string::trim),
));
static ENTRIES_COUNT = iter::count_const!(TEST, ',');
static PARSED: [&str; ENTRIES_COUNT] = iter::collect_const!(&str =>
string::split(TEST, ","),
map(string::trim),
);
I'm pretty sure there are better solutions than this (if any), this is just to illustrate my need.
Let me know what you think!
The from_str_radix
from core is not even an unstable const fn so it will be very useful to have it available in konst.
BTW thanks your library saved me a lot of work :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.