• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# `litrs`: parsing and inspecting Rust literals
2
3[<img alt="CI status of main" src="https://img.shields.io/github/actions/workflow/status/LukasKalbertodt/litrs/ci.yml?branch=main&label=CI&logo=github&logoColor=white&style=for-the-badge" height="23">](https://github.com/LukasKalbertodt/litrs/actions/workflows/ci.yml)
4[<img alt="Crates.io Version" src="https://img.shields.io/crates/v/litrs?logo=rust&style=for-the-badge" height="23">](https://crates.io/crates/litrs)
5[<img alt="docs.rs" src="https://img.shields.io/crates/v/litrs?color=blue&label=docs&style=for-the-badge" height="23">](https://docs.rs/litrs)
6
7`litrs` offers functionality to parse Rust literals, i.e. tokens in the Rust programming language that represent fixed values.
8For example: `27`, `"crab"`, `bool`.
9This is particularly useful for proc macros, but can also be used outside of a proc-macro context.
10
11**Why this library?**
12Unfortunately, the `proc_macro` API shipped with the compiler offers no easy way to inspect literals.
13There are mainly two libraries for this purpose:
14[`syn`](https://github.com/dtolnay/syn) and [`literalext`](https://github.com/mystor/literalext).
15The latter is deprecated.
16And `syn` is oftentimes overkill for the task at hand, especially when developing function-like proc-macros (e.g. `foo!(..)`).
17This crate is a lightweight alternative.
18Also, when it comes to literals, `litrs` offers a bit more flexibility and a few more features compared to `syn`.
19
20I'm interested in community feedback!
21If you consider using this, please speak your mind [in this issue](https://github.com/LukasKalbertodt/litrs/issues/1).
22
23## Example
24
25### In proc macro
26
27```rust
28use std::convert::TryFrom;
29use proc_macro::TokenStream;
30use litrs::Literal;
31
32#[proc_macro]
33pub fn foo(input: TokenStream) -> TokenStream {
34    // Please do proper error handling in your real code!
35    let first_token = input.into_iter().next().expect("no input");
36
37    // `try_from` will return an error if the token is not a literal.
38    match Literal::try_from(first_token) {
39        // Convenient methods to produce decent errors via `compile_error!`.
40        Err(e) => return e.to_compile_error(),
41
42        // You can now inspect your literal!
43        Ok(Literal::Integer(i)) => {
44            println!("Got an integer specified in base {:?}", i.base());
45
46            let value = i.value::<u64>().expect("integer literal too large");
47            println!("Is your integer even? {}", value % 2 == 0);
48        }
49        Ok(other) => {
50            println!("Got a non-integer literal");
51        }
52    }
53
54    TokenStream::new() // dummy output
55}
56```
57
58If you are expecting a specific kind of literal, you can also use this, which will return an error if the token is not a float literal.
59
60```rust
61FloatLit::try_from(first_token)
62```
63
64### Parsing from a `&str`
65
66Outside of a proc macro context you might want to parse a string directly.
67
68```rust
69use litrs::{FloatLit, Literal};
70
71let lit = Literal::parse("'��'").expect("failed to parse literal");
72let float_lit = FloatLit::parse("2.7e3").expect("failed to parse as float literal");
73```
74
75See [**the documentation**](https://docs.rs/litrs) or the `examples/` directory for more examples and information.
76
77
78<br />
79
80---
81
82## License
83
84Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
852.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
86Unless you explicitly state otherwise, any contribution intentionally submitted
87for inclusion in this project by you, as defined in the Apache-2.0 license,
88shall be dual licensed as above, without any additional terms or conditions.
89