2015-09-23 10 views
5

Sto provando a creare una libreria e voglio includere alcuni file binari (o di testo) che avranno dati che verranno analizzati in fase di esecuzione.C'è un modo per includere file binari o di testo in una libreria Rust?

La mia intenzione è di avere il controllo di questi file, aggiornarli costantemente e modificare la versione della libreria in ogni aggiornamento.

È possibile tramite carico? In tal caso, come posso accedere a questi file dalla mia biblioteca?

Una soluzione che ho pensato è quella di includere alcuni file .rs con strutture e/o costanti come &str che memorizzeranno i dati ma trovo un po 'brutto

EDIT:

ho cambiato la risposta accettata per quello che si adatta di più il mio caso, ma dare un'occhiata a Shepmaster's answer come questo può essere più adatto nel vostro caso.

+3

** che verrà analizzato in fase di esecuzione ** => perché? Poiché i dati sono statici, sarebbe più efficiente memorizzare i dati già analizzati nel binario piuttosto che analizzarli in fase di esecuzione. La ruggine è abbastanza limitata in ciò che può rappresentare in fase di compilazione (molto sfortunatamente), tuttavia si menziona il mantenimento di un file '.rs', quindi sembra possibile nel tuo caso. Se questo è il caso, allora consiglio di usare un file 'build.rs', che è uno" script di build "in Rust che ti permetterà di analizzare i file sorgente e generare file' .rs' prima di costruire " corretta". –

+0

Per essere più precisi, questi dati sono già analizzati e devono essere spostati nelle strutture, come 'HashMap', che non può essere inizializzato (almeno non senza usare la gabbia' lazy_static'). Questo è il motivo per cui ho bisogno di "analizzarli" in fase di runtime. Averli in un file binario (o di testo) rende più facile sostituire solo questo file quando voglio aggiornare i dati. Comunque usare 'build.rs' in combinazione con la gabbia' lazy_static' suona come un'alternativa migliore e farò un tentativo. Grazie per il suggerimento! – Otobo

risposta

7

Disclaimer: ho parlato in un commento, ma mi permetta di ribadire qui, in quanto mi dà più spazio per elaborare.

Come ha detto Shepmaster, è possibile includere testo o binari testualmente in una libreria di Rust/eseguibile utilizzando le include_bytes! e include_str! macro.

Nel tuo caso, tuttavia, lo eviterei. Rimandando l'analisi del contenuto in fase di esecuzione:

  • consente di creare un artefatto difettoso.
  • si verificano (più) tempo di esecuzione (tempo di analisi).
  • si incorrere (più) spazio in testa (codice di analisi).

ruggine riconosce questo problema e offre molteplici meccanismi di generazione di codice destinata a superare queste limitazioni:

  • macro: se la logica può essere codificato in una macro, allora può essere inclusa in una sorgente file direttamente
  • plugin: alimentati fino macro, che possono codificare qualsiasi logica arbitraria e generare il codice elaborato (vedi regex!)
  • build.rs: un "copione Ruggine" indipendente in esecuzione in vista della compilazione corretta il cui ruolo è quello di ge nerate .rs file

Nel tuo caso, lo script build.rs suona come una buona misura:

  • spostando il codice di analisi lì, si esprime un manufatto più leggero
  • analizzando prima del tempo, si fornire un manufatto più veloce
  • analizzando prima del tempo, si trasporta una corretta artefatto

Il risultato della tua analisi può essere codificato in diversi modi, dalle funzioni alla statica (eventualmente lazy_static!), poiché build.rs può generare qualsiasi codice Rust valido.

È possibile vedere come utilizzare build.rs in the Cargo Documentation; troverai lì come integrarlo con Cargo e come creare file (e altro).

6

La macro include_bytes! sembra vicina a ciò che si desidera. Ti dà solo un riferimento ad un array di byte, però, in modo che avrebbe dovuto fare qualsiasi analisi a partire da quel:

static HOST_FILE: &'static [u8] = include_bytes!("/etc/hosts"); 

fn main() { 
    let host_str = std::str::from_utf8(HOST_FILE).unwrap(); 

    println!("Hosts are:\n{}", &host_str[..42]); 
} 

Se si dispone di UTF-8 di contenuti, è possibile utilizzare include_str!, come sottolineato da Benjamin Lindley :

static HOST_FILE: &'static str = include_str!("/etc/hosts"); 

fn main() { 
    println!("Hosts are:\n{}", &HOST_FILE[..42]); 
} 
+3

Se vuoi il testo (piuttosto che i dati binari), ed è già in formato utf8, non puoi semplicemente usare 'include_str!', Invece di usare 'include_bytes!' E poi convertirlo? * i.e. * - 'let host_str = include_str! ("/etc/hosts ");' –

+0

@BenjaminLindley hmm, buon punto! Ho visto "include!" E ho capito che non era giusto, ma saltato proprio su "include_str!". – Shepmaster

Problemi correlati