This project is currently only an experiment. At this point, it is highly uncertain if the project will be continued or dropped soon.See the on-going discussion on literal prefixes here
Prefixes delivers various prefix-like proc macro attributes for literals to easily create common types.
Quick example:
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
use prefixes::{f, ms, P, s};
fn _deep_thought2() -> String {
let answer_path = #[P]"./answer.txt";
let answer = if answer_path.exists() {
std::fs::read_to_string(&answer_path).unwrap()
} else {
std::thread::sleep(#[s]6 + #[ms]9);
#[f]"42"
};
#[f]"Answer to the Ultimate Question of Life, the Universe, and Everything = {answer}"
}
To use prefixes, first add it to your project in Cargo.toml
:
[dependencies]
prefixes = "0.1.0"
Then enable stmt_expr_attributes
and proc_macro_hygiene
features (this is possible only on nightly Rust):
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
Finally, use prefixes that you need, e.g.
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
use prefixes::f;
fn greeting(name: &str) -> String {
#[f]"Welcome, {name}!"
}
Build formatted string from a string literal using the format!
macro.
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
use prefixes::f;
let n = 2137;
let s1 = format!("n = {n}");
let s2 = #[f]"n = {n}";
assert_eq!(s1, s2);
Might be also useful for creating owned strings, e.g.
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
use prefixes::f;
let s1 = #[f]"2137";
let s2 = "2137".to_string();
assert_eq!(s1, s2);
Build builds std::time::Duration
from an integer literal using from_millis
(#[ms]
) or from_secs[_f32|_f64]
methods (#[s]
).
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
use std::time::Duration;
use prefixes::{ms, s};
let d1 = Duration::from_millis(1000);
let d2 = #[ms]1000;
assert_eq!(d1, d2);
let d3 = Duration::from_secs(2);
let d4 = #[s]2;
assert_eq!(d3, d4);
let d5 = Duration::from_secs_f32(3.0f32);
let d6 = #[s]3.0f32;
assert_eq!(d5, d6);
let d7 = Duration::from_secs_f64(4.0f64);
let d8 = #[s]4.0f64;
assert_eq!(d7, d8);
Build OsStr
(#[os]
) or OsString
(#[OS]
) from a string literal. Additionally, #[OS]
supports string interpolation like #[f]
.
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
use std::ffi::{OsStr, OsString};
use prefixes::{os, OS};
let os1 = OsStr::new("foo");
let os2 = #[os]"foo";
assert_eq!(os1, os2);
let n = 42;
let os3 = OsString::from(format!("n = 42"));
let os4 = #[OS]"n = 42";
assert_eq!(os3, os4);
Build Path
(#[p]
) or PathBuf
(#[P]
) from a string literal. Additionally, #[P]
supports string interpolation.
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
use std::path::{Path, PathBuf};
use prefixes::{p, P};
let p1 = Path::new("/foo");
let p2 = #[p]"/foo";
assert_eq!(p1, p2);
let ext = "txt";
let p3 = PathBuf::from(format!("/foo.{ext}"));
let p4 = #[P]"/foo.{ext}";
assert_eq!(p3, p4);
Build Regex from a string literal. Additionally, #[RE]
calls .unwrap()
on the result. Works only if regex
crate is included in the dependencies. Doesn't require explicit use regex::Regex
.
#![feature(stmt_expr_attributes, proc_macro_hygiene)]
use regex::Regex;
use prefixes::{re, RE};
let re1 = Regex::new("1|2");
let re2 = #[re]"1|2";
assert_eq!(format!("{re1:?}"), format!("{re2:?}"));
let re3 = Regex::new("[A-Z]").unwrap();
let re4 = #[RE]"[A-Z]";
assert_eq!(format!("{re3:?}"), format!("{re4:?}"));
This project is licensed under the MIT License - see the LICENSE file for details.