include_str! în Rust

Citește un fișier text la compilare și îl pune în program ca &'static str. Fișierul nu mai este necesar la rulare.

Sintaxă
const TEXT: &str = include_str!("cale/fisier.txt");      // cale relativă la fișierul sursă
const DATE: &[u8] = include_bytes!("imagine.png");

Ce face include_str!

include_str!("fisier") citește fișierul la compilare și îl înlocuiește cu conținutul lui, ca un literal de text (&'static str). Executabilul conține textul, deci nu mai trebuie să distribui fișierul alături de program. include_bytes! face același lucru pentru fișiere binare și dă un &'static [u8; N].

Calea este relativă la fișierul sursă care conține macro-ul (de exemplu src/main.rs), nu la directorul din care rulezi programul. Fișierul trebuie să fie UTF-8 valid; dacă nu există, compilarea eșuează.

Este potrivit pentru date mici care nu se schimbă des: șabloane HTML, texte de ajutor, fișiere SQL, liste de cuvinte. Dacă fișierul se modifică, trebuie recompilat programul (Cargo face asta automat).

Ce returnează

Un &'static str cu tot conținutul fișierului.

Exemple

Exemplul 1: Programul își include propriul cod sursă

În acest exemplu, singurul fișier care există la compilare este chiar main.rs, deci programul îl include pe el însuși și îl analizează. Textul este în executabil, nu se citește nimic de pe disc la rulare. Între liniile cu println! este numărată și cea care caută acest text.

const SURSA: &str = include_str!("main.rs");

fn main() {
    let linii = SURSA.lines().count();
    let cu_println = SURSA.lines().filter(|l| l.contains("println!")).count();
    println!("main.rs are {linii} linii și {} octeți", SURSA.len());
    println!("{cu_println} linii conțin println!");
    println!("Prima linie: {}", SURSA.lines().next().unwrap());
}

Rezultat

main.rs are 9 linii și 365 octeți
4 linii conțin println!
Prima linie: const SURSA: &str = include_str!("main.rs");

Exemplul 2: Un șablon inclus într-un proiect Cargo

Fișierul src/sabloane/factura.txt este inclus în executabil. Calea din include_str! pornește din directorul lui src/main.rs.

// src/sabloane/factura.txt conține:
// Factura nr. {nr}
// Client: {client}
// Total: {total} lei

const SABLON: &str = include_str!("sabloane/factura.txt");

fn main() {
    let text = SABLON
        .replace("{nr}", "2026-0042")
        .replace("{client}", "Ana Popescu")
        .replace("{total}", "1.249,90");
    print!("{text}");
}

Rezultat (cu fișierul sabloane/factura.txt)

Factura nr. 2026-0042
Client: Ana Popescu
Total: 1.249,90 lei

Greșeli frecvente

  • Dai o cale relativă la directorul proiectului (include_str!("src/date.txt") din src/main.rs): couldn't read `src/src/date.txt`. Calea este relativă la fișierul sursă.
  • Folosești include_str! pentru un fișier pe care utilizatorul trebuie să-l poată schimba (o configurare). Modificarea nu are efect până la recompilare; citește-l la rulare cu fs::read_to_string.
  • Incluzi fișiere foarte mari: executabilul crește și compilarea devine lentă.

Comenzi înrudite

  • env! (și option_env!): Citește o variabilă de mediu la compilare și o pune în program ca &’static str. Pentru valori la rulare se folosește std::env::var.
  • concat!: Lipește literali (texte, numere, bool, char) într-un singur &’static str, la compilare, fără niciun cost la rulare.
  • line!, file! și column!: Dau poziția din codul sursă unde sunt scrise: numărul liniei, coloana și numele fișierului. Utile în mesaje de jurnal și erori.
  • const și static: const definește o valoare fixă calculată la compilare; static definește o variabilă globală cu o singură adresă, care trăiește tot programul.