2015-09-23 42 views
5

ライブラリを作成しようとしていて、実行時に解析されるデータを持つバイナリ(またはテキスト)ファイルをライブラリに含める必要があります。Rustライブラリにバイナリファイルまたはテキストファイルを含める方法はありますか?

私の意図は、これらのファイルを制御し、常に更新し、各アップデートでライブラリのバージョンを変更することです。

これは貨物経由で可能ですか?もしそうなら、どのように私のライブラリからこれらのファイルにアクセスできますか?

私は考えていたのは、.rsのファイルに構造体や定数を入れてデータを格納する&strのようなものを含めることだと思っていましたが、醜いと感じました。

編集:私は私の場合より多くに合うものに受け入れ答えを変更しました

これはあなたのケースでは、より適していることができて、しかしShepmaster's answerを見てみましょう。

+3

**実行時に解析されます** =>なぜですか?データは静的なので、すでに解析されたデータを実行時に解析するのではなくバイナリに格納する方が効率的です。 Rustはコンパイル時にかなり制限されています(残念なことに)。しかし、あなたの場合は可能なように '.rs'ファイルを保持することに言及しています。これが当てはまる場合、Rustの "build script"である 'build.rs'ファイルを使用して、ソースファイルを解析し、ビルド直前に' .rs'ファイルを生成することをお勧めします。適切な "。 –

+0

より正確にするために、これらのデータはすでに解析されており、 'HashMap'のような初期化できない構造体(少なくともlazy_staticクレートを使用していなくても)に移動する必要があります。これが私が実行時にそれらを "解析"する必要がある理由です。それらをバイナリ(またはテキスト)ファイルにすると、データを更新するときにこのファイルだけを置き換えるのが簡単になります。しかし、 'build.rs'を' lazy_static'と組み合わせて使用​​すると、より良い選択肢のように聞こえ、試してみます。提案していただきありがとうございます! – Otobo

答えて

7

免責事項:私はコメントで、それを述べたが、それは私に詳しく説明するために多くのスペースを与えるように私は、ここで再反復しましょう。 Shepmasterが言ったように

は、include_bytes!include_str!マクロを使用して錆ライブラリ/実行ファイル内のテキストまたはバイナリ逐語を含むことが可能です。

あなたの場合、私はそれを避けるでしょう。実行時にコンテンツの解析を延期することによって:

  • 欠陥のあるアーティファクトを作成することができます。
  • (以上)実行時オーバーヘッド(解析時間)が発生します。
  • あなたは(もっと多くの)スペースオーバーヘッド(解析コード)が発生します。

錆がこの問題を認識し、これらの制限を克服するために運命づけコード生成のための複数のメカニズムを提供しています:

  • マクロを:論理マクロに符号化することができれば、それはソースに含めることができます
  • にファイルを直接
  • プラグイン:パワーアップ、マクロ、任意のロジックをコード化し、精巧なコードを生成することができます(regex!を参照)
  • build.rs:独立した「錆のスクリプトは、」先にその役割GEにある適切なコンパイルの実行中nerateお使いの場合には.rsファイル

build.rsスクリプトはぴったりのように聞こえる:

  • そこ解析コードを移動することで、あなたが事前に解析することで軽量化アーティファクト
  • を提供する、あなたは事前に解析することにより、より高速なアーティファクト
  • を提供する、あなたは正しいアーティファクト

をお届けbuild.rsは任意の有効なRustコードを生成できるため、解析結果を関数から静的(おそらくlazy_static!)までさまざまな方法でエンコードできます。

build.rsの使用方法はthe Cargo Documentationです。それを貨物と統合する方法と、ファイルを作成する方法などがあります。

6

include_bytes!マクロは、あなたが望むものに近いようです。あなたはそれから始まる任意の解析を行う必要があると思いますので、それだけ、しかしあなたにバイト配列への参照を与える:

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]); 
} 

あなたはUTF-8コンテンツを持っている場合はBenjamin Lindleyで指摘したように、あなたは、include_str!を使用することができます:

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

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

バイナリデータではなくテキストをutf8形式にしたいのであれば、 'include_bytes!'を使用する代わりに 'include_str!'を使用して変換することはできませんか? * ie * - 'let host_str = include_str!("/etc/hosts ");' –

+0

@BenjaminLindleyうーん、良い点!私は 'include! 'を見て、正しくないが' include_str!'の直ぐ上にスキップしたことに気づいた。 – Shepmaster

関連する問題