2015-09-23 14 views
5

Tôi đang cố gắng tạo một thư viện và tôi muốn bao gồm một số tệp nhị phân (hoặc văn bản) trong đó sẽ có dữ liệu sẽ được phân tích cú pháp khi chạy.Có cách nào để bao gồm tệp nhị phân hoặc tệp văn bản trong thư viện Rust không?

Mục đích của tôi là có quyền kiểm soát các tệp này, cập nhật chúng liên tục và thay đổi phiên bản của thư viện trong mỗi lần cập nhật.

Điều này có thể thông qua hàng hóa không? Nếu có, làm cách nào để truy cập các tệp này từ thư viện của tôi?

Cách giải quyết mà tôi nghĩ là bao gồm một số tệp .rs với cấu trúc và/hoặc hằng số như &str sẽ lưu trữ dữ liệu nhưng tôi thấy nó xấu xí.

EDIT:

Tôi đã thay đổi câu trả lời chấp nhận để một trong đó phù hợp hơn trường hợp của tôi, tuy nhiên hãy nhìn vào Shepmaster's answer vì điều này có thể phù hợp hơn trong trường hợp của bạn.

+3

** sẽ được phân tích cú pháp khi chạy ** => tại sao? Vì dữ liệu là tĩnh, sẽ hiệu quả hơn khi lưu trữ dữ liệu đã được phân tích cú pháp trong tệp nhị phân thay vì phân tích cú pháp trong thời gian chạy. Rust là khá hạn chế trong những gì nó có thể đại diện tại thời gian biên dịch (khá tiếc), tuy nhiên bạn đề cập đến việc duy trì một tập tin '.rs' để nó có vẻ như có thể trong trường hợp của bạn. Nếu đây là trường hợp, thì tôi khuyên bạn nên sử dụng tệp 'build.rs', đây là" tập lệnh xây dựng "trong Rust, cho phép bạn phân tích (các) tệp nguồn và tạo tệp' .rs' ngay trước khi tạo " đúng ". –

+0

Để chính xác hơn, các dữ liệu này đã được phân tích cú pháp và cần di chuyển đến các cấu trúc, như 'HashMap', không thể khởi tạo được (ít nhất là không sử dụng' lazy_static' crate). Đây là lý do tại sao tôi cần phải "phân tích" chúng khi chạy. Có chúng trong một tập tin nhị phân (hoặc văn bản) làm cho dễ dàng hơn để thay thế chỉ tập tin này khi tôi muốn cập nhật dữ liệu. Tuy nhiên bằng cách sử dụng 'build.rs' kết hợp với' lazy_static' crate âm thanh như một lựa chọn tốt hơn và tôi sẽ cho nó một thử. Cám ơn vì sự gợi ý! – Otobo

Trả lời

7

Disclaimer: tôi đề cập đến nó trong một chú thích, nhưng hãy để tôi tái lặp ở đây, vì nó mang lại cho tôi nhiều không gian để xây dựng.

Như Shepmaster đã nói, có thể bao gồm văn bản hoặc nguyên văn nhị phân trong thư viện Rust/thực thi bằng cách sử dụng các macro include_bytes!include_str!.

Trong trường hợp của bạn, tuy nhiên, tôi sẽ tránh điều đó. Bằng cách trì hoãn việc phân tích cú pháp nội dung thành thời gian chạy:

  • bạn cho phép tạo thành một tạo phẩm thiếu sót.
  • bạn phải chịu thêm (chi phí) cao hơn thời gian chạy (thời gian phân tích cú pháp).
  • bạn phải chịu thêm (không gian) trên không (mã phân tích cú pháp).

Rust thừa nhận vấn đề này, và cung cấp nhiều cơ chế cho việc tạo mã mệnh để vượt qua những hạn chế:

  • macro: nếu logic có thể được mã hóa thành một vĩ mô, sau đó nó có thể được bao gồm trong một nguồn nộp trực tiếp
  • plugins: cấp nguồn macro, mà có thể mã hóa bất kỳ logic tùy ý và tạo mã phức tạp (xem regex!)
  • build.rs: một "Rust kịch bản" độc lập chạy trước khi biên soạn phù hợp có vai trò là ge nerate .rs file

Trong trường hợp của bạn, kịch bản build.rs âm thanh như một sự phù hợp tốt:

  • bằng cách di chuyển các mã phân tích đó, bạn cung cấp một vật nhẹ
  • bằng cách phân tích trước thời hạn, bạn cung cấp một tạo phẩm nhanh hơn
  • bằng cách phân tích trước thời hạn, bạn phân phối một tạo tác chính xác

Kết quả phân tích cú pháp của bạn có thể được mã hóa theo nhiều cách khác nhau, từ các hàm sang số liệu thống kê (có thể là lazy_static!), vì build.rs có thể tạo bất kỳ mã Rust hợp lệ nào.

Bạn có thể xem cách sử dụng build.rs trong the Cargo Documentation; bạn sẽ tìm thấy cách tích hợp nó với Cargo và cách tạo tệp (và nhiều hơn nữa).

6

Macro include_bytes! có vẻ gần với những gì bạn muốn. Nó chỉ mang đến cho bạn một tham chiếu đến một mảng byte mặc dù, vì vậy bạn sẽ phải làm bất cứ phân tích bắt đầu từ đó:

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

Nếu bạn có UTF-8 nội dung, bạn có thể sử dụng include_str!, như đã chỉ ra bởi Benjamin Lindley :

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

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

Nếu bạn muốn văn bản (thay vì dữ liệu nhị phân), và nó đã ở định dạng utf8, bạn không thể sử dụng 'include_str!', Thay vì sử dụng 'include_bytes!' Và sau đó chuyển đổi nó? * tức là * - 'cho phép host_str = include_str! ("/etc/hosts ");' –

+0

@BenjaminLindley hmm, điểm tốt! Tôi thấy 'bao gồm!' Và nhận ra nó không đúng nhưng bỏ qua ngay 'include_str!'. – Shepmaster

Các vấn đề liên quan