| Crates.io | stri |
| lib.rs | stri |
| version | 0.6.0 |
| created_at | 2025-06-13 14:24:46.568043+00 |
| updated_at | 2025-07-23 10:45:18.306469+00 |
| description | string interpolation procedural macro |
| homepage | |
| repository | https://github.com/infinite-xdev-void/stri |
| max_upload_size | |
| id | 1711523 |
| size | 54,000 |
stri is a set of procedural macros for string interpolation.
use stri::{si, sql};
fn main(){
let name = "Ahmed";
let age = 63;
let height = 180.5;
// `si!`: str interpolation used to interpolate variables normally
assert_eq!(
si!("my name is {name}, i am {age} years old and my height is {height}"),
"my name is Ahmed, i am 63 years old and my height is 180.5",
);
//
//
//
let note = r#"My friend's name is Ali"#;
// but for `sql` where `String` must be wrapped with single quote and each quote
// inside it must be escaped then `sql!` is used.
assert_eq!(
sql!("INSERT INTO users (name, age, height, note) VALUES ({name}, {age}, {height}, {note})"),
r#"INSERT INTO users (name, age, height, note) VALUES ('Ahmed', 63, 180.5, 'My friend''s name is Ali')"#,
);
//
//
//
let note = r#"[' " > < &]"#; // these are html special characters: ' " > < &
// if you want to sanitize html special characters then add `~html` as a suffix to
// the variable name (works with `&str` and `String` only)
assert_eq!(
sql!("INSERT INTO users (name, age, height, note) VALUES ({name}, {age}, {height}, {~html note})"),
r#"INSERT INTO users (name, age, height, note) VALUES ('Ahmed', 63, 180.5, '[' " > < &]')"#,
);
//
//
//
//
//
// If the `chrono` feature is enabled
// Note: chrono::{
// DateTime, Duration, FixedOffset, NaiveDate,
// NaiveDateTime, NaiveTime, TimeZone, Weekday
// };
// are the only supported types
use chrono::NaiveDateTime;
let dt = NaiveDateTime::parse_from_str("2015-09-05 23:56:04", "%Y-%m-%d %H:%M:%S").unwrap();
assert_eq!(
si!("date and time is: {dt}"),
"date and time is: 2015-09-05 23:56:04"
);
assert_eq!(
sql!("SELECT {dt}::TIMESTAMP AS date_time"),
"SELECT '2015-09-05 23:56:04'::TIMESTAMP AS date_time"
);
//
//
//
//
//
// if the `rust_decimal` feature is enabled
use rust_decimal::Decimal;
let d = Decimal::new(1225, 2); // 12.25;
assert_eq!(si!("Decimal is: {d}"), "Decimal is: 12.25");
assert_eq!(
sql!("SELECT {d}::DECIMAL AS d"),
"SELECT 12.25::DECIMAL AS d"
);
}
file! macroFor longer string or sql content, you can externalize it into a separate file and use the file! macro to include it. The file! macro intelligently applies the logic of the si! or sql! macros internally, determined by the extension of the specified file.
File: src/example.txt
my name is {name}, i am {age} years old and my height is {height}
File: src/example.sql
INSERT INTO users (name, age, height, note) VALUES ({name}, {age}, {height}, {note})
use stri::file;
fn main(){
let name = "Ahmed";
let age = 63;
let height = 180.5;
let note = r#"My friend's name is Ali"#;
//
//
//
assert_eq!(
file!("src/example.txt"),
"my name is Ahmed, i am 63 years old and my height is 180.5",
);
//
//
//
assert_eq!(
file!("src/example.sql"),
r#"INSERT INTO users (name, age, height, note) VALUES ('Ahmed', 63, 180.5, 'My friend''s name is Ali')"#,
);
}
dir! macroThe dir! macro allows you to concatenate the content of multiple files within a specified directory. It reads all files only at the first level of the given directory, joins their content with a newline character (\n), and intelligently processes them based on the file extensions within the directory:
If all files have the .sql extension: sql! macro's logic will be applied.
Otherwise: si! macro's logic will be applied.
Note: The order in which files are read and concatenated is dependent on the the behavior of std::fs::ReadDir.
Dir: src
src/ ├── sql │ ├── 1_insert.sql │ └── 2_delete.sql ├── txt │ ├── 1_name.txt │ └── 2_age.txt └── main.rs
File: src/sql/1_insert.sql
INSERT INTO users (name, age, height, note) VALUES ({name}, {age}, {height}, {note});
File: src/sql/2_insert.sql
DELETE FROM users WHERE name={name};
File: src/txt/1_name.txt
My name is {name}
File: src/txt/2_age.txt
I am {age} years old
File src/main.rs
use stri::dir;
fn main(){
let name = "Ahmed";
let age = 63;
//
//
//
assert_eq!(
dir!("src/sql"),
"INSERT INTO users (name, age, height, note) VALUES ('Ahmed', 63, 180.5, 'My friend''s name is Ali');\nDELETE FROM users WHERE name='Ahmed';"
);
//
//
//
assert_eq!(dir!("src/txt"), "My name is Ahmed\nI am 63 years old")
}
If you encounter any issues or want to suggest a feature, please open an issue in github.
"stri" is licensed under Ethical Use License (EUL v1.0). see LICENSE for full license details.