GithubHelp home page GithubHelp logo

rodrimati1992 / konst Goto Github PK

View Code? Open in Web Editor NEW
79.0 79.0 1.0 670 KB

Const equivalents of std functions, compile-time comparison, and parsing.

License: zlib License

Shell 0.03% Rust 99.97%
compile-time rust

konst's People

Contributors

rodrimati1992 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

kitcatier

konst's Issues

please remove `const_fn_union` feature from `konst_macro_rules-0.2.13/src/lib.rs:3:42`

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 ?

Nested parsing

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:

Click to show code
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}");
        }
    }
}

Vectorize a string slice at compile time ?

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:

  • Convert the slice to a vector using some macro magic:
static PARSED: Vec<&str> = konst::vectorize!(iter::collect_const!(&str =>
    string::split(TEST, ","),
        map(string::trim),
));
  • Be able to count occurrences of a character:
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!

[feature request] Add radix based parsing

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 :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.