├── data ├── test-2.txt ├── char_array.txt ├── test.txt ├── bool_array.txt ├── i32_array-2.txt ├── i8_array.txt ├── string_array.txt ├── u8_array.txt ├── i16_array.txt ├── i32_array.txt ├── string_array-2.txt ├── u16_array.txt ├── u32_array.txt ├── usize_array.txt ├── i64_array.txt ├── isize_array.txt ├── u64_array.txt ├── f32_array.txt ├── f64_array.txt ├── i128_array.txt ├── u128_array.txt └── benchmark.txt ├── .github ├── dependabot.yml └── workflows │ ├── ci-version.yml │ └── ci.yml ├── tests ├── test_mod.rs ├── pub.rs └── macros.rs ├── Cargo.toml ├── LICENSE ├── rustfmt.toml ├── .gitignore ├── benches └── bench.rs ├── src ├── lib.rs ├── macro_include_bytes.rs ├── macro_include_str.rs └── macro_include_array.rs └── README.md /data/test-2.txt: -------------------------------------------------------------------------------- 1 | Some text... -------------------------------------------------------------------------------- /data/char_array.txt: -------------------------------------------------------------------------------- 1 | ['a', 'b', 'c'] -------------------------------------------------------------------------------- /data/test.txt: -------------------------------------------------------------------------------- 1 | This is just a test text. -------------------------------------------------------------------------------- /data/bool_array.txt: -------------------------------------------------------------------------------- 1 | [false, true, false] -------------------------------------------------------------------------------- /data/i32_array-2.txt: -------------------------------------------------------------------------------- 1 | [-1, -2, -3, -4, -5] -------------------------------------------------------------------------------- /data/i8_array.txt: -------------------------------------------------------------------------------- 1 | [12, -34, 56, 7_8, 90i8] -------------------------------------------------------------------------------- /data/string_array.txt: -------------------------------------------------------------------------------- 1 | ["Hi", "Hello", "哈囉"] -------------------------------------------------------------------------------- /data/u8_array.txt: -------------------------------------------------------------------------------- 1 | [12, 34, 56, 7_8, 90u8] -------------------------------------------------------------------------------- /data/i16_array.txt: -------------------------------------------------------------------------------- 1 | [123, -456, 789, 1_000, 5000i16] -------------------------------------------------------------------------------- /data/i32_array.txt: -------------------------------------------------------------------------------- 1 | [123, -456, 789, 1_000, 5000i32] -------------------------------------------------------------------------------- /data/string_array-2.txt: -------------------------------------------------------------------------------- 1 | ["Hello world!", "Rust", "你好"] -------------------------------------------------------------------------------- /data/u16_array.txt: -------------------------------------------------------------------------------- 1 | [123, 456, 789, 1_000, 5000u16] -------------------------------------------------------------------------------- /data/u32_array.txt: -------------------------------------------------------------------------------- 1 | [123, 456, 789, 1_000, 5000u32] -------------------------------------------------------------------------------- /data/usize_array.txt: -------------------------------------------------------------------------------- 1 | [123, 456, 789, 1_000, 5000usize] -------------------------------------------------------------------------------- /data/i64_array.txt: -------------------------------------------------------------------------------- 1 | [123, -456, 789, 1_000, 500000000000i64] -------------------------------------------------------------------------------- /data/isize_array.txt: -------------------------------------------------------------------------------- 1 | [123, -456, 789, 1_000, 5000isize] -------------------------------------------------------------------------------- /data/u64_array.txt: -------------------------------------------------------------------------------- 1 | [123, 456, 789, 1_000, 500000000000u64] -------------------------------------------------------------------------------- /data/f32_array.txt: -------------------------------------------------------------------------------- 1 | [123.0, -456.0, 789.5, 1_000.123f32, 5000f32] -------------------------------------------------------------------------------- /data/f64_array.txt: -------------------------------------------------------------------------------- 1 | [123.0, -456.0, 789.5, 1_000.123f64, 5000.456f64] -------------------------------------------------------------------------------- /data/i128_array.txt: -------------------------------------------------------------------------------- 1 | [123, -456, 789, 1_000, 500000000000000000000000i128] -------------------------------------------------------------------------------- /data/u128_array.txt: -------------------------------------------------------------------------------- 1 | [123, 456, 789, 1_000, 500000000000000000000000u128] -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" -------------------------------------------------------------------------------- /tests/test_mod.rs: -------------------------------------------------------------------------------- 1 | use lazy_static_include::*; 2 | 3 | lazy_static_include_str! { 4 | pub STR => "data/test.txt", 5 | pub(crate) STR2 => "data/test.txt", 6 | } 7 | 8 | lazy_static_include_bytes! { 9 | pub BYTE => "data/test.txt", 10 | pub(crate) BYTE2 => "data/test.txt", 11 | } 12 | 13 | lazy_static_include_array! { 14 | pub ARRAY: [isize; 5] => "data/isize_array.txt", 15 | pub(crate) ARRAY2: [isize; 5] => "data/isize_array.txt", 16 | } 17 | -------------------------------------------------------------------------------- /tests/pub.rs: -------------------------------------------------------------------------------- 1 | mod test_mod; 2 | 3 | #[test] 4 | fn include_str() { 5 | assert_eq!("This is just a test text.", test_mod::STR); 6 | assert_eq!("This is just a test text.", test_mod::STR2); 7 | } 8 | 9 | #[test] 10 | fn include_bytes() { 11 | assert_eq!("This is just a test text.".as_bytes(), test_mod::BYTE); 12 | assert_eq!("This is just a test text.".as_bytes(), test_mod::BYTE2); 13 | } 14 | 15 | #[test] 16 | fn include_array() { 17 | assert_eq!(123, test_mod::ARRAY[0]); 18 | assert_eq!(123, test_mod::ARRAY2[0]); 19 | } 20 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lazy-static-include" 3 | version = "3.2.1" 4 | authors = ["Magic Len "] 5 | edition = "2021" 6 | rust-version = "1.60" 7 | repository = "https://github.com/magiclen/lazy-static-include" 8 | homepage = "https://magiclen.org/lazy-static-include" 9 | keywords = ["lazy", "macro", "static", "include"] 10 | categories = ["memory-management", "rust-patterns"] 11 | description = "This crate provides `lazy_static_include_bytes` and `lazy_static_include_str` macros to replace `include_bytes` and `include_str` macros." 12 | license = "MIT" 13 | include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE", "benches/bench.rs"] 14 | 15 | [dependencies] 16 | lazy_static = "1.4" 17 | manifest-dir-macros = { version = "0.1.6", features = ["tuple"] } 18 | syn = { version = "2", features = ["full"] } 19 | 20 | [dev-dependencies] 21 | bencher = "0.1.5" 22 | serde_json = "1.0" 23 | assert-eq-float = "0.1" 24 | 25 | slash-formatter = "3.1.3" 26 | 27 | [[bench]] 28 | name = "bench" 29 | harness = false 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 magiclen.org (Ron Li) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/ci-version.yml: -------------------------------------------------------------------------------- 1 | name: CI-version 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" 7 | 8 | env: 9 | CARGO_TERM_COLOR: always 10 | 11 | jobs: 12 | tests: 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | os: 17 | - ubuntu-latest 18 | - macos-latest 19 | - windows-latest 20 | toolchain: 21 | - stable 22 | - nightly 23 | features: 24 | - 25 | name: Test ${{ matrix.toolchain }} on ${{ matrix.os }} (${{ matrix.features }}) 26 | runs-on: ${{ matrix.os }} 27 | steps: 28 | - uses: actions/checkout@v4 29 | - uses: actions-rust-lang/setup-rust-toolchain@v1 30 | with: 31 | toolchain: ${{ matrix.toolchain }} 32 | - run: cargo test --release ${{ matrix.features }} 33 | - run: cargo doc --release ${{ matrix.features }} 34 | 35 | MSRV: 36 | strategy: 37 | fail-fast: false 38 | matrix: 39 | os: 40 | - ubuntu-latest 41 | - macos-latest 42 | - windows-latest 43 | toolchain: 44 | - "1.60" 45 | features: 46 | - 47 | name: Test ${{ matrix.toolchain }} on ${{ matrix.os }} (${{ matrix.features }}) 48 | runs-on: ${{ matrix.os }} 49 | steps: 50 | - uses: actions/checkout@v4 51 | - uses: actions-rust-lang/setup-rust-toolchain@v1 52 | with: 53 | toolchain: ${{ matrix.toolchain }} 54 | - run: cargo test --release --lib --bins ${{ matrix.features }} -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [ push, pull_request ] 4 | 5 | env: 6 | CARGO_TERM_COLOR: always 7 | 8 | jobs: 9 | rustfmt: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: actions-rust-lang/setup-rust-toolchain@v1 14 | with: 15 | toolchain: nightly 16 | components: rustfmt 17 | - uses: actions-rust-lang/rustfmt@v1 18 | 19 | clippy: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: actions-rust-lang/setup-rust-toolchain@v1 24 | with: 25 | components: clippy 26 | - run: cargo clippy --all-targets --all-features -- -D warnings 27 | 28 | tests: 29 | strategy: 30 | fail-fast: false 31 | matrix: 32 | os: 33 | - ubuntu-latest 34 | - macos-latest 35 | - windows-latest 36 | toolchain: 37 | - stable 38 | - nightly 39 | features: 40 | - 41 | name: Test ${{ matrix.toolchain }} on ${{ matrix.os }} (${{ matrix.features }}) 42 | runs-on: ${{ matrix.os }} 43 | steps: 44 | - uses: actions/checkout@v4 45 | - uses: actions-rust-lang/setup-rust-toolchain@v1 46 | with: 47 | toolchain: ${{ matrix.toolchain }} 48 | - run: cargo test ${{ matrix.features }} 49 | - run: cargo doc ${{ matrix.features }} 50 | 51 | MSRV: 52 | strategy: 53 | fail-fast: false 54 | matrix: 55 | os: 56 | - ubuntu-latest 57 | - macos-latest 58 | - windows-latest 59 | toolchain: 60 | - "1.60" 61 | features: 62 | - 63 | name: Test ${{ matrix.toolchain }} on ${{ matrix.os }} (${{ matrix.features }}) 64 | runs-on: ${{ matrix.os }} 65 | steps: 66 | - uses: actions/checkout@v4 67 | - uses: actions-rust-lang/setup-rust-toolchain@v1 68 | with: 69 | toolchain: ${{ matrix.toolchain }} 70 | - run: cargo test --lib --bins ${{ matrix.features }} -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # array_width = 60 2 | # attr_fn_like_width = 70 3 | binop_separator = "Front" 4 | blank_lines_lower_bound = 0 5 | blank_lines_upper_bound = 1 6 | brace_style = "PreferSameLine" 7 | # chain_width = 60 8 | color = "Auto" 9 | # comment_width = 100 10 | condense_wildcard_suffixes = true 11 | control_brace_style = "AlwaysSameLine" 12 | empty_item_single_line = true 13 | enum_discrim_align_threshold = 80 14 | error_on_line_overflow = false 15 | error_on_unformatted = false 16 | # fn_call_width = 60 17 | fn_params_layout = "Tall" 18 | fn_single_line = false 19 | force_explicit_abi = true 20 | force_multiline_blocks = false 21 | format_code_in_doc_comments = true 22 | doc_comment_code_block_width = 80 23 | format_generated_files = true 24 | format_macro_matchers = true 25 | format_macro_bodies = true 26 | skip_macro_invocations = [] 27 | format_strings = true 28 | hard_tabs = false 29 | hex_literal_case = "Upper" 30 | imports_indent = "Block" 31 | imports_layout = "Mixed" 32 | indent_style = "Block" 33 | inline_attribute_width = 0 34 | match_arm_blocks = true 35 | match_arm_leading_pipes = "Never" 36 | match_block_trailing_comma = true 37 | max_width = 100 38 | merge_derives = true 39 | imports_granularity = "Crate" 40 | newline_style = "Unix" 41 | normalize_comments = false 42 | normalize_doc_attributes = true 43 | overflow_delimited_expr = true 44 | remove_nested_parens = true 45 | reorder_impl_items = true 46 | reorder_imports = true 47 | group_imports = "StdExternalCrate" 48 | reorder_modules = true 49 | short_array_element_width_threshold = 10 50 | # single_line_if_else_max_width = 50 51 | space_after_colon = true 52 | space_before_colon = false 53 | spaces_around_ranges = false 54 | struct_field_align_threshold = 80 55 | struct_lit_single_line = false 56 | # struct_lit_width = 18 57 | # struct_variant_width = 35 58 | tab_spaces = 4 59 | trailing_comma = "Vertical" 60 | trailing_semicolon = true 61 | type_punctuation_density = "Wide" 62 | use_field_init_shorthand = true 63 | use_small_heuristics = "Max" 64 | use_try_shorthand = true 65 | where_single_line = false 66 | wrap_comments = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/intellij+all 2 | 3 | ### Intellij+all ### 4 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 5 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 6 | 7 | # User-specific stuff 8 | .idea/**/workspace.xml 9 | .idea/**/tasks.xml 10 | .idea/**/usage.statistics.xml 11 | .idea/**/dictionaries 12 | .idea/**/shelf 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | .idea/**/dbnavigator.xml 22 | 23 | # Gradle 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # Gradle and Maven with auto-import 28 | # When using Gradle or Maven with auto-import, you should exclude module files, 29 | # since they will be recreated, and may cause churn. Uncomment if using 30 | # auto-import. 31 | # .idea/modules.xml 32 | # .idea/*.iml 33 | # .idea/modules 34 | 35 | # CMake 36 | cmake-build-*/ 37 | 38 | # Mongo Explorer plugin 39 | .idea/**/mongoSettings.xml 40 | 41 | # File-based project format 42 | *.iws 43 | 44 | # IntelliJ 45 | out/ 46 | 47 | # mpeltonen/sbt-idea plugin 48 | .idea_modules/ 49 | 50 | # JIRA plugin 51 | atlassian-ide-plugin.xml 52 | 53 | # Cursive Clojure plugin 54 | .idea/replstate.xml 55 | 56 | # Crashlytics plugin (for Android Studio and IntelliJ) 57 | com_crashlytics_export_strings.xml 58 | crashlytics.properties 59 | crashlytics-build.properties 60 | fabric.properties 61 | 62 | # Editor-based Rest Client 63 | .idea/httpRequests 64 | 65 | ### Intellij+all Patch ### 66 | # Ignores the whole .idea folder and all .iml files 67 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 68 | 69 | .idea/ 70 | 71 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 72 | 73 | *.iml 74 | modules.xml 75 | .idea/misc.xml 76 | *.ipr 77 | 78 | 79 | # End of https://www.gitignore.io/api/intellij+all 80 | 81 | 82 | ### Rust ### 83 | # Generated by Cargo 84 | # will have compiled files and executables 85 | /target/ 86 | 87 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 88 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 89 | Cargo.lock 90 | 91 | # These are backup files generated by rustfmt 92 | **/*.rs.bk 93 | 94 | 95 | # End of https://www.gitignore.io/api/rust 96 | -------------------------------------------------------------------------------- /benches/bench.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate lazy_static_include; 3 | 4 | use std::{fs::File, io::Read, str::from_utf8_unchecked}; 5 | 6 | use bencher::{benchmark_group, benchmark_main, Bencher}; 7 | use slash_formatter::concat_with_file_separator; 8 | 9 | macro_rules! benchmark_text_path { 10 | () => { 11 | concat_with_file_separator!(env!("CARGO_MANIFEST_DIR"), "data", "benchmark.txt") 12 | }; 13 | } 14 | 15 | fn include_str_no_static(bencher: &mut Bencher) { 16 | bencher.iter(|| { 17 | let mut f = File::open(benchmark_text_path!()).unwrap(); 18 | 19 | let mut v = Vec::new(); 20 | 21 | f.read_to_end(&mut v).unwrap(); 22 | 23 | let s = String::from_utf8(v).unwrap(); 24 | 25 | s.contains("figarofigaro") 26 | }); 27 | } 28 | 29 | fn include_str_native_static(bencher: &mut Bencher) { 30 | let text = include_str!(benchmark_text_path!()); 31 | 32 | bencher.iter(|| text.contains("figarofigaro")); 33 | } 34 | 35 | fn include_str_lazy_static(bencher: &mut Bencher) { 36 | lazy_static_include_str! { 37 | pub TEXT => "data/benchmark.txt" 38 | } 39 | 40 | bencher.iter(|| TEXT.contains("figarofigaro")); 41 | } 42 | 43 | fn include_bytes_no_static(bencher: &mut Bencher) { 44 | bencher.iter(|| { 45 | let mut f = File::open(benchmark_text_path!()).unwrap(); 46 | 47 | let mut v = Vec::new(); 48 | 49 | f.read_to_end(&mut v).unwrap(); 50 | 51 | let text = unsafe { from_utf8_unchecked(&v) }; 52 | 53 | text.contains("figarofigaro") 54 | }); 55 | } 56 | 57 | fn include_bytes_native_static(bencher: &mut Bencher) { 58 | let data = include_bytes!(benchmark_text_path!()); 59 | 60 | bencher.iter(|| { 61 | let text = unsafe { from_utf8_unchecked(data) }; 62 | 63 | text.contains("figarofigaro") 64 | }); 65 | } 66 | 67 | fn include_bytes_lazy_static(bencher: &mut Bencher) { 68 | lazy_static_include_bytes! { 69 | DATA => "data/benchmark.txt" 70 | } 71 | 72 | bencher.iter(|| { 73 | let text = unsafe { from_utf8_unchecked(&DATA) }; 74 | 75 | text.contains("figarofigaro") 76 | }); 77 | } 78 | 79 | fn include_array_no_static(bencher: &mut Bencher) { 80 | let path = concat!(benchmark_text_path!()); 81 | 82 | bencher.iter(|| { 83 | let mut f = File::open(path).unwrap(); 84 | 85 | let mut v = Vec::new(); 86 | 87 | f.read_to_end(&mut v).unwrap(); 88 | 89 | let array: Vec<&str> = serde_json::from_slice(&v).unwrap(); 90 | 91 | array.binary_search(&"figarofigaro").is_ok() 92 | }); 93 | } 94 | 95 | fn include_array_native_static(bencher: &mut Bencher) { 96 | let array = include!(benchmark_text_path!()); 97 | 98 | bencher.iter(|| array.binary_search(&"figarofigaro").is_ok()); 99 | } 100 | 101 | fn include_array_lazy_static(bencher: &mut Bencher) { 102 | lazy_static_include_array! { 103 | ARRAY: [&'static str; 622] => "data/benchmark.txt" 104 | } 105 | 106 | bencher.iter(|| ARRAY.binary_search(&"figarofigaro").is_ok()); 107 | } 108 | 109 | benchmark_group!( 110 | include_str, 111 | include_str_no_static, 112 | include_str_native_static, 113 | include_str_lazy_static 114 | ); 115 | benchmark_group!( 116 | include_bytes, 117 | include_bytes_no_static, 118 | include_bytes_native_static, 119 | include_bytes_lazy_static 120 | ); 121 | benchmark_group!( 122 | include_array, 123 | include_array_no_static, 124 | include_array_native_static, 125 | include_array_lazy_static 126 | ); 127 | 128 | benchmark_main!(include_str, include_bytes, include_array); 129 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | # Lazy Static Include 3 | 4 | This crate provides `lazy_static_include_bytes` and `lazy_static_include_str` macros to replace `include_bytes` and `include_str` macros. 5 | 6 | Why should we do that? 7 | Because the original `include_bytes` and `include_str` macros bring extra data from files into the compiled executable binary file, the time for compiling surges. 8 | 9 | High compilation time is detrimental to software development. `lazy_static_include_bytes` and `lazy_static_include_str` macros can help you **lazy load** data from files 10 | when you are not using the **release** profile. In other words, if you are using `include_bytes` and `include_str` macros, and you think your compilation time is too high to wait, 11 | you can choose to use `lazy_static_include_bytes` and `lazy_static_include_str` macros. 12 | 13 | `lazy_static_include_bytes` and `lazy_static_include_str` macros include data from files into the compiled executable binary file **only** when you are using the **release** profile. 14 | Be careful when you distribute your program. 15 | 16 | The paths used for `lazy_static_include_bytes` and `lazy_static_include_str` are relative to **CARGO_MANIFEST_DIR**. 17 | 18 | ## Examples 19 | 20 | ```rust 21 | use lazy_static_include::*; 22 | 23 | lazy_static_include_str! { 24 | /// doc 25 | TEST => "data/test.txt", 26 | } 27 | 28 | lazy_static_include_str! { 29 | /// doc 30 | pub TEST2 => ("data", "test-2.txt"), 31 | } 32 | 33 | assert_eq!("This is just a test text.", TEST); 34 | assert_eq!("Some text...", TEST2); 35 | ``` 36 | 37 | ```rust 38 | use lazy_static_include::*; 39 | 40 | lazy_static_include_bytes! { 41 | /// doc 42 | TEST => "data/test.txt", 43 | } 44 | 45 | lazy_static_include_bytes! { 46 | /// doc 47 | pub TEST2 => ("data", "test-2.txt"), 48 | } 49 | 50 | assert_eq!("This is just a test text.".as_bytes(), TEST); 51 | assert_eq!("Some text...".as_bytes(), TEST2); 52 | ``` 53 | 54 | You should notice that the value created from `lazy_static_include_bytes` and `lazy_static_include_str` macros isn't equal to `&'static [u8]` or `&'static str`. If you want to get an exact `&'static [u8]` or `&'static str` reference, you can **dereference** the value. 55 | 56 | ```rust 57 | use lazy_static_include::*; 58 | 59 | lazy_static_include_bytes! { 60 | /// doc 61 | TEST => "data/test.txt", 62 | } 63 | 64 | let data: &'static [u8] = *TEST; 65 | ``` 66 | 67 | Also, private items (without `pub`) and public items (with `pub*`) cannot be put together. 68 | 69 | ## Include Array 70 | 71 | There is a special macro `lazy_static_include_array` which can include arrays from files. 72 | The array is fixed sized and can be one of these following types: `bool`, `char`, `usize`, `u8`, `u16`, `u32`, `u64`, `u128`, `isize`, `i8`, `i16`, `i32`, `i64`, `i128`, `f32`, `f64`, `&'static str`. 73 | 74 | Also, the `lazy_static_include_array` macro includes data from files into the compiled executable binary file **only** when you are using the **release** profile. 75 | Be careful when you distribute your program. 76 | 77 | The paths used for `lazy_static_include_array` are relative to **CARGO_MANIFEST_DIR**. 78 | 79 | ```rust 80 | use lazy_static_include::*; 81 | 82 | lazy_static_include_array! { 83 | /// doc 84 | TEST: [u64; 5] => "data/u64_array.txt", 85 | } 86 | 87 | lazy_static_include_array! { 88 | /// doc 89 | pub TEST2: [&'static str; 3] => ("data", "string_array.txt") 90 | } 91 | 92 | assert_eq!(123, TEST[0]); 93 | assert_eq!(456, TEST[1]); 94 | assert_eq!(789, TEST[2]); 95 | assert_eq!(1000, TEST[3]); 96 | assert_eq!(500000000000u64, TEST[4]); 97 | 98 | assert_eq!("Hi", TEST2[0]); 99 | assert_eq!("Hello", TEST2[1]); 100 | assert_eq!("哈囉", TEST2[2]); 101 | ``` 102 | 103 | ## Benchmark 104 | 105 | Using static mechanisms makes your program faster. See my benchmark result below (AMD Ryzen 9 3900X 12-Core Processor 12C/24T 3.90GHz, ran on 2020/07/02): 106 | 107 | ```text 108 | test include_array_lazy_static ... bench: 46 ns/iter (+/- 3) 109 | test include_array_native_static ... bench: 48 ns/iter (+/- 3) 110 | test include_array_no_static ... bench: 22,414 ns/iter (+/- 297) 111 | test include_bytes_lazy_static ... bench: 844 ns/iter (+/- 3) 112 | test include_bytes_native_static ... bench: 863 ns/iter (+/- 5) 113 | test include_bytes_no_static ... bench: 4,764 ns/iter (+/- 189) 114 | test include_str_lazy_static ... bench: 857 ns/iter (+/- 8) 115 | test include_str_native_static ... bench: 842 ns/iter (+/- 10) 116 | test include_str_no_static ... bench: 4,837 ns/iter (+/- 145) 117 | ``` 118 | 119 | When using the **release** profile, the performance of `lazy_static_include_*` is very close to `include_*`. That means you don't need to worry about the overhead, but just enjoy the faster compilation time. 120 | 121 | You can run the benchmark program by executing, 122 | 123 | ```bash 124 | cargo bench 125 | ``` 126 | */ 127 | 128 | #[doc(hidden)] 129 | pub extern crate lazy_static; 130 | 131 | #[doc(hidden)] 132 | pub extern crate manifest_dir_macros; 133 | 134 | #[doc(hidden)] 135 | pub extern crate syn; 136 | 137 | mod macro_include_array; 138 | mod macro_include_bytes; 139 | mod macro_include_str; 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Lazy Static Include 2 | ==================== 3 | 4 | [![CI](https://github.com/magiclen/lazy-static-include/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/lazy-static-include/actions/workflows/ci.yml) 5 | 6 | This crate provides `lazy_static_include_bytes` and `lazy_static_include_str` macros to replace `include_bytes` and `include_str` macros. 7 | 8 | Why should we do that? 9 | Because the original `include_bytes` and `include_str` macros bring extra data from files into the compiled executable binary file, the time for compiling surges. 10 | 11 | High compilation time is detrimental to software development. `lazy_static_include_bytes` and `lazy_static_include_str` macros can help you **lazy load** data from files 12 | when you are not using the **release** profile. In other words, if you are using `include_bytes` and `include_str` macros, and you think your compilation time is too high to wait, 13 | you can choose to use `lazy_static_include_bytes` and `lazy_static_include_str` macros. 14 | 15 | `lazy_static_include_bytes` and `lazy_static_include_str` macros include data from files into the compiled executable binary file **only** when you are using the **release** profile. 16 | Be careful when you distribute your program. 17 | 18 | The paths used for `lazy_static_include_bytes` and `lazy_static_include_str` are relative to **CARGO_MANIFEST_DIR**. 19 | 20 | ## Examples 21 | 22 | ```rust 23 | use lazy_static_include::*; 24 | 25 | lazy_static_include_str! { 26 | /// doc 27 | TEST => "data/test.txt", 28 | } 29 | 30 | lazy_static_include_str! { 31 | /// doc 32 | pub TEST2 => ("data", "test-2.txt"), 33 | } 34 | 35 | assert_eq!("This is just a test text.", TEST); 36 | assert_eq!("Some text...", TEST2); 37 | ``` 38 | 39 | ```rust 40 | use lazy_static_include::*; 41 | 42 | lazy_static_include_bytes! { 43 | /// doc 44 | TEST => "data/test.txt", 45 | } 46 | 47 | lazy_static_include_bytes! { 48 | /// doc 49 | pub TEST2 => ("data", "test-2.txt"), 50 | } 51 | 52 | assert_eq!("This is just a test text.".as_bytes(), TEST); 53 | assert_eq!("Some text...".as_bytes(), TEST2); 54 | ``` 55 | 56 | You should notice that the value created from `lazy_static_include_bytes` and `lazy_static_include_str` macros isn't equal to `&'static [u8]` or `&'static str`. If you want to get an exact `&'static [u8]` or `&'static str` reference, you can **dereference** the value. 57 | 58 | ```rust 59 | use lazy_static_include::*; 60 | 61 | lazy_static_include_bytes! { 62 | /// doc 63 | TEST => "data/test.txt", 64 | } 65 | 66 | let data: &'static [u8] = *TEST; 67 | ``` 68 | 69 | Also, private items (without `pub`) and public items (with `pub*`) cannot be put together. 70 | 71 | ## Include Array 72 | 73 | There is a special macro `lazy_static_include_array` which can include arrays from files. 74 | The array is fixed sized and can be one of these following types: `bool`, `char`, `usize`, `u8`, `u16`, `u32`, `u64`, `u128`, `isize`, `i8`, `i16`, `i32`, `i64`, `i128`, `f32`, `f64`, `&'static str`. 75 | 76 | Also, the `lazy_static_include_array` macro includes data from files into the compiled executable binary file **only** when you are using the **release** profile. 77 | Be careful when you distribute your program. 78 | 79 | The paths used for `lazy_static_include_array` are relative to **CARGO_MANIFEST_DIR**. 80 | 81 | ```rust 82 | use lazy_static_include::*; 83 | 84 | lazy_static_include_array! { 85 | /// doc 86 | TEST: [u64; 5] => "data/u64_array.txt", 87 | } 88 | 89 | lazy_static_include_array! { 90 | /// doc 91 | pub TEST2: [&'static str; 3] => ("data", "string_array.txt") 92 | } 93 | 94 | assert_eq!(123, TEST[0]); 95 | assert_eq!(456, TEST[1]); 96 | assert_eq!(789, TEST[2]); 97 | assert_eq!(1000, TEST[3]); 98 | assert_eq!(500000000000u64, TEST[4]); 99 | 100 | assert_eq!("Hi", TEST2[0]); 101 | assert_eq!("Hello", TEST2[1]); 102 | assert_eq!("哈囉", TEST2[2]); 103 | ``` 104 | 105 | ## Benchmark 106 | 107 | Using static mechanisms makes your program faster. See my benchmark result below (AMD Ryzen 9 3900X 12-Core Processor 12C/24T 3.90GHz, ran on 2020/07/02): 108 | 109 | ```text 110 | test include_array_lazy_static ... bench: 46 ns/iter (+/- 3) 111 | test include_array_native_static ... bench: 48 ns/iter (+/- 3) 112 | test include_array_no_static ... bench: 22,414 ns/iter (+/- 297) 113 | test include_bytes_lazy_static ... bench: 844 ns/iter (+/- 3) 114 | test include_bytes_native_static ... bench: 863 ns/iter (+/- 5) 115 | test include_bytes_no_static ... bench: 4,764 ns/iter (+/- 189) 116 | test include_str_lazy_static ... bench: 857 ns/iter (+/- 8) 117 | test include_str_native_static ... bench: 842 ns/iter (+/- 10) 118 | test include_str_no_static ... bench: 4,837 ns/iter (+/- 145) 119 | ``` 120 | 121 | When using the **release** profile, the performance of `lazy_static_include_*` is very close to `include_*`. That means you don't need to worry about the overhead, but just enjoy the faster compilation time. 122 | 123 | You can run the benchmark program by executing, 124 | 125 | ```bash 126 | cargo bench 127 | ``` 128 | 129 | ## Crates.io 130 | 131 | https://crates.io/crates/lazy-static-include 132 | 133 | ## Documentation 134 | 135 | https://docs.rs/lazy-static-include 136 | 137 | ## License 138 | 139 | [MIT](LICENSE) -------------------------------------------------------------------------------- /src/macro_include_bytes.rs: -------------------------------------------------------------------------------- 1 | #[cfg(debug_assertions)] 2 | /// Includes a file as a reference to a byte array (`&'static [u8]`). 3 | /// 4 | /// The file is located relative to the directory containing the manifest of your package. 5 | #[macro_export] 6 | macro_rules! lazy_static_include_bytes { 7 | ( @impl $name:ident ) => { 8 | impl<'a> ::std::cmp::PartialEq<&'a [u8]> for $name { 9 | fn eq(&self, other: &&'a [u8]) -> bool { 10 | (&*$name).eq(other) 11 | } 12 | } 13 | 14 | impl ::std::cmp::PartialEq for $name { 15 | fn eq(&self, other: &$name) -> bool { 16 | true 17 | } 18 | } 19 | 20 | impl<'a> ::std::cmp::PartialEq<$name> for &'a [u8] { 21 | fn eq(&self, other: &$name) -> bool { 22 | self.eq(&*$name) 23 | } 24 | } 25 | 26 | impl ::std::fmt::Debug for $name { 27 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 28 | ::std::fmt::Debug::fmt(*$name, f) 29 | } 30 | } 31 | 32 | impl ::std::convert::AsRef for $name 33 | where 34 | T: ?Sized, 35 | [u8]: ::std::convert::AsRef, 36 | { 37 | fn as_ref(&self) -> &T { 38 | (*$name).as_ref() 39 | } 40 | } 41 | }; 42 | ( @inner $name:ident, $path:expr ) => { 43 | { 44 | use ::std::fs; 45 | use ::std::mem::{forget, transmute}; 46 | 47 | let path = $crate::manifest_dir_macros::not_directory_path!($path); 48 | 49 | let data = fs::read(path).unwrap(); 50 | 51 | unsafe { 52 | let ret = transmute(data.as_slice()); 53 | forget(data); 54 | ret 55 | } 56 | } 57 | }; 58 | ( @unit $(#[$attr: meta])* $name:ident => $path:expr ) => { 59 | $crate::lazy_static::lazy_static! { 60 | $(#[$attr])* 61 | static ref $name: &'static [u8] = $crate::lazy_static_include_bytes!(@inner $name, $path); 62 | } 63 | 64 | $crate::lazy_static_include_bytes!(@impl $name); 65 | }; 66 | ( @unit $(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident => $path:expr ) => { 67 | $crate::lazy_static::lazy_static! { 68 | $(#[$attr])* 69 | pub$(($($v)+))? static ref $name: &'static [u8] = $crate::lazy_static_include_bytes!(@inner $name, $path); 70 | } 71 | 72 | $crate::lazy_static_include_bytes!(@impl $name); 73 | }; 74 | ( $($(#[$attr: meta])* $name:ident => $path:expr),* $(,)* ) => { 75 | $( 76 | $crate::lazy_static_include_bytes! { 77 | @unit 78 | $(#[$attr])* 79 | $name => $path 80 | } 81 | )* 82 | }; 83 | ( $($(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident => $path:expr),* $(,)* ) => { 84 | $( 85 | $crate::lazy_static_include_bytes! { 86 | @unit 87 | $(#[$attr])* 88 | pub$(($($v)+))? $name => $path 89 | } 90 | )* 91 | }; 92 | } 93 | 94 | #[cfg(not(debug_assertions))] 95 | /// Includes a file as a reference to a byte array (`&'static [u8]`). 96 | /// 97 | /// The file is located relative to the directory containing the manifest of your package. 98 | #[macro_export] 99 | macro_rules! lazy_static_include_bytes { 100 | ( @impl $name:ident ) => { 101 | impl<'a> ::std::cmp::PartialEq<&'a [u8]> for $name { 102 | fn eq(&self, other: &&'a [u8]) -> bool { 103 | (&*$name).eq(other) 104 | } 105 | } 106 | 107 | impl ::std::cmp::PartialEq for $name { 108 | fn eq(&self, other: &$name) -> bool { 109 | true 110 | } 111 | } 112 | 113 | impl<'a> ::std::cmp::PartialEq<$name> for &'a [u8] { 114 | fn eq(&self, other: &$name) -> bool { 115 | self.eq(&*$name) 116 | } 117 | } 118 | 119 | impl ::std::fmt::Debug for $name { 120 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 121 | ::std::fmt::Debug::fmt(*$name, f) 122 | } 123 | } 124 | 125 | impl ::std::convert::AsRef for $name 126 | where 127 | T: ?Sized, 128 | [u8]: ::std::convert::AsRef, 129 | { 130 | fn as_ref(&self) -> &T { 131 | (*$name).as_ref() 132 | } 133 | } 134 | }; 135 | ( @unit $(#[$attr: meta])* $name:ident => $path:expr ) => { 136 | $crate::lazy_static::lazy_static! { 137 | $(#[$attr])* 138 | static ref $name: &'static [u8] = include_bytes!($crate::manifest_dir_macros::path!($path)); 139 | } 140 | 141 | $crate::lazy_static_include_bytes!(@impl $name); 142 | }; 143 | ( @unit $(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident => $path:expr ) => { 144 | $crate::lazy_static::lazy_static! { 145 | $(#[$attr])* 146 | pub$(($($v)+))? static ref $name: &'static [u8] = include_bytes!($crate::manifest_dir_macros::path!($path)); 147 | } 148 | 149 | $crate::lazy_static_include_bytes!(@impl $name); 150 | }; 151 | ( $($(#[$attr: meta])* $name:ident => $path:expr),* $(,)* ) => { 152 | $( 153 | $crate::lazy_static_include_bytes! { 154 | @unit 155 | $(#[$attr])* 156 | $name => $path 157 | } 158 | )* 159 | }; 160 | ( $($(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident => $path:expr),* $(,)* ) => { 161 | $( 162 | $crate::lazy_static_include_bytes! { 163 | @unit 164 | $(#[$attr])* 165 | pub$(($($v)+))? $name => $path 166 | } 167 | )* 168 | }; 169 | } 170 | -------------------------------------------------------------------------------- /data/benchmark.txt: -------------------------------------------------------------------------------- 1 | ["fergie1","fergie2","fergie3","fergie4","fergie5","fergie6","fergie7","fergie8","fergie9","fergie?","fergied","fergieeigref","fergiefergie","fergies","fergiing","ferguS","fergus","fergus!","fergus.","fergus0","fergus1","fergus2","fergus3","fergus4","fergus5","fergus6","fergus7","fergus8","fergus9","fergus?","fergused","ferguses","fergusfergus","fergusing","fergusoN","ferguson","ferguson!","ferguson.","ferguson0","ferguson1","ferguson2","ferguson3","ferguson4","ferguson5","ferguson6","ferguson7","ferguson8","ferguson9","ferguson?","fergusoned","fergusoning","fergusons","fergussugref","fernandO","fernanding","fernando","fernando!","fernando.","fernando0","fernando1","fernando2","fernando3","fernando4","fernando5","fernando6","fernando7","fernando8","fernando9","fernando?","fernandoed","fernandos","ferrarI","ferrari","ferrari!","ferrari.","ferrari0","ferrari1","ferrari1","ferrari2","ferrari3","ferrari4","ferrari5","ferrari6","ferrari7","ferrari8","ferrari9","ferrari?","ferraried","ferraring","ferraris","ferreT","ferret","ferret!","ferret.","ferret0","ferret1","ferret2","ferret3","ferret4","ferret5","ferret6","ferret7","ferret8","ferret9","ferret?","ferreted","ferretferret","ferreting","ferrets","ferretterref","ferriS","ferris","ferris!","ferris.","ferris0","ferris1","ferris2","ferris3","ferris4","ferris5","ferris6","ferris7","ferris8","ferris9","ferris?","ferrised","ferrises","ferrisferris","ferrising","ferrissirref","festeR","fester","fester!","fester.","fester0","fester1","fester2","fester3","fester4","fester5","fester6","fester7","fester8","fester9","fester?","festered","festerfester","festering","festerretsef","festers","festivaL","festival","festival!","festival.","festival0","festival1","festival2","festival3","festival4","festival5","festival6","festival7","festival8","festival9","festival?","festivaled","festivaling","festivals","fetisH","fetish","fetish!","fetish.","fetish0","fetish1","fetish2","fetish3","fetish4","fetish5","fetish6","fetish7","fetish8","fetish9","fetish?","fetished","fetishes","fetishfetish","fetishhsitef","fetishing","fettisH","fettish","fettish!","fettish.","fettish0","fettish1","fettish2","fettish3","fettish4","fettish5","fettish6","fettish7","fettish8","fettish9","fettish?","fettished","fettishes","fettishing","feveR","fever","fever!","fever.","fever0","fever1","fever2","fever3","fever4","fever5","fever6","fever7","fever8","fever9","fever?","fevered","feverfever","fevering","feverrevef","fevers","ffarffiR","ffarffir","ffatS","ffats","ffcr","ffeJ","ffej","ffejffeJ","ffejffej","fffF","ffff","ffff!","ffff.","ffff0","ffff1","ffff2","ffff3","ffff4","ffff5","ffff6","ffff7","ffff8","ffff9","ffff?","ffffF","ffffed","fffff","fffff!","fffff.","fffff0","fffff1","fffff1","fffff2","fffff3","fffff4","fffff5","fffff6","fffff7","fffff8","fffff9","fffff?","fffffF","fffffed","ffffff","ffffff!","ffffff.","ffffff0","ffffff1","ffffff1","ffffff2","ffffff3","ffffff4","ffffff5","ffffff6","ffffff7","ffffff8","ffffff9","ffffff?","ffffffF","ffffffed","fffffff","fffffff!","fffffff.","fffffff0","fffffff1","fffffff2","fffffff3","fffffff4","fffffff5","fffffff6","fffffff7","fffffff8","fffffff9","fffffff?","fffffffF","fffffffed","ffffffff","ffffffff","ffffffff!","ffffffff.","ffffffff0","ffffffff1","ffffffff2","ffffffff3","ffffffff4","ffffffff5","ffffffff6","ffffffff7","ffffffff8","ffffffff9","ffffffff?","ffffffffed","ffffffffff","ffffffffffff","ffffffffing","ffffffffs","fffffffing","fffffffs","ffffffing","ffffffs","fffffing","fffffs","ffffing","ffffs","ffiT","ffidraC","ffidrac","ffilC","ffilc","ffilpS","ffilps","ffirehS","ffirehs","ffit","ffokcaJ","ffokcaj","ffokcuF","ffokcuf","ffokreJ","ffokrej","ffonrimS","ffonrims","ffossiP","ffossip","ffoteG","ffoteg","ffrd","ffshr","ffuB","ffuM","ffuP","ffub","ffulF","ffulf","ffum","ffup","ffutS","ffuts","ffutsnuF","ffutsnuf","ffutstoH","ffutstoh","ffvdj474","fggt","fghjkL","fghjkl","fght","fghtng","fghtr","fhdfv","ficK","fick","fick!","fick.","fick0","fick1","fick2","fick3","fick4","fick5","fick6","fick7","fick8","fick9","fick?","fickeN","ficked","ficken","ficken!","ficken.","ficken0","ficken1","ficken2","ficken3","ficken4","ficken5","ficken6","ficken7","ficken8","ficken9","ficken?","fickened","fickenficken","fickening","fickennekcif","fickens","fickfick","ficking","fickkcif","ficks","fictioN","fiction","fiction!","fiction.","fiction0","fiction1","fiction2","fiction3","fiction4","fiction5","fiction6","fiction7","fiction8","fiction9","fiction?","fictioned","fictioning","fictions","fiddlE","fiddle","fiddle!","fiddle.","fiddle0","fiddle1","fiddle2","fiddle3","fiddle4","fiddle5","fiddle6","fiddle7","fiddle8","fiddle9","fiddle?","fiddled","fiddleelddif","fiddlefiddle","fiddles","fiddling","fideliO","fideliing","fidelio","fidelio!","fidelio.","fidelio0","fidelio1","fidelio2","fidelio3","fidelio4","fidelio5","fidelio6","fidelio7","fidelio8","fidelio9","fidelio?","fidelioed","fidelios","fidelitY","fidelitied","fidelities","fidelity","fidelity!","fidelity.","fidelity0","fidelity1","fidelity2","fidelity3","fidelity4","fidelity5","fidelity6","fidelity7","fidelity8","fidelity9","fidelity?","fidelitying","fielD","field","field!","field.","field0","field1","field2","field3","field4","field5","field6","field7","field8","field9","field?","fieldS","fielddleif","fielded","fieldfield","fielding","fields","fields","fields!","fields.","fields0","fields1","fields2","fields3","fields4","fields5","fields6","fields7","fields8","fields9","fields?","fieldsed","fieldses","fieldsfields","fieldsing","fieldssdleif","fiestA","fiesta","fiesta!","fiesta.","fiesta0","fiesta1","fiesta2","fiesta3","fiesta4","fiesta5","fiesta6","fiesta7","fiesta8","fiesta9","fiesta?","fiestaatseif","fiestaed","fiestafiesta","fiestas","fiesting","figarO","figaring","figaro","figaro!","figaro.","figaro0","figaro1","figaro2","figaro3","figaro4","figaro5","figaro6","figaro7","figaro8","figaro9","figaro?","figaroed","figarofigaro","figarooragif","figaros","fighT","fight","fight!","fight.","fight0","fight1","fight2","fight3","fight4","fight5","fight6","fight7","fight8","fight9","fight?","fighteR","fighted","fighter","fighter!","fighter.","fighter0","fighter1","fighter2","fighter3","fighter4","fighter5","fighter6","fighter7","fighter8","fighter9","fighter?","fightered","fightering","fighters","fightfight","fightinG","fighting","fighting","fighting!","fighting.","fighting0","fighting1","fighting2","fighting3","fighting4","fighting5","fighting6","fighting7","fighting8","fighting9","fighting?","fightingged"] -------------------------------------------------------------------------------- /tests/macros.rs: -------------------------------------------------------------------------------- 1 | use assert_eq_float::assert_eq_float; 2 | use lazy_static_include::*; 3 | 4 | #[test] 5 | fn include_str() { 6 | lazy_static_include_str! { 7 | TEST => "data/test.txt", 8 | TEST2 => "data/test-2.txt", 9 | } 10 | 11 | assert_eq!("This is just a test text.", TEST); 12 | assert_eq!("Some text...", TEST2); 13 | } 14 | 15 | #[test] 16 | fn include_bytes() { 17 | lazy_static_include_bytes! { 18 | TEST => "data/test.txt", 19 | TEST2 => "data/test-2.txt", 20 | } 21 | 22 | assert_eq!("This is just a test text.".as_bytes(), TEST); 23 | assert_eq!("Some text...".as_bytes(), TEST2); 24 | } 25 | 26 | #[test] 27 | fn include_array_isize() { 28 | lazy_static_include_array! { 29 | TEST: [isize; 5] => "data/isize_array.txt", 30 | } 31 | 32 | assert_eq!(123, TEST[0]); 33 | assert_eq!(-456, TEST[1]); 34 | assert_eq!(789, TEST[2]); 35 | assert_eq!(1000, TEST[3]); 36 | assert_eq!(5000, TEST[4]); 37 | } 38 | 39 | #[test] 40 | fn include_array_i8() { 41 | lazy_static_include_array! { 42 | TEST: [i8; 5] => "data/i8_array.txt", 43 | } 44 | 45 | assert_eq!(12, TEST[0]); 46 | assert_eq!(-34, TEST[1]); 47 | assert_eq!(56, TEST[2]); 48 | assert_eq!(78, TEST[3]); 49 | assert_eq!(90, TEST[4]); 50 | } 51 | 52 | #[test] 53 | fn include_array_i16() { 54 | lazy_static_include_array! { 55 | TEST: [i16; 5] => "data/i16_array.txt", 56 | } 57 | 58 | assert_eq!(123, TEST[0]); 59 | assert_eq!(-456, TEST[1]); 60 | assert_eq!(789, TEST[2]); 61 | assert_eq!(1000, TEST[3]); 62 | assert_eq!(5000, TEST[4]); 63 | } 64 | 65 | #[test] 66 | fn include_array_i32() { 67 | lazy_static_include_array! { 68 | TEST: [i32; 5] => "data/i32_array.txt", 69 | } 70 | 71 | assert_eq!(123, TEST[0]); 72 | assert_eq!(-456, TEST[1]); 73 | assert_eq!(789, TEST[2]); 74 | assert_eq!(1000, TEST[3]); 75 | assert_eq!(5000, TEST[4]); 76 | } 77 | 78 | #[test] 79 | fn include_array_i64() { 80 | lazy_static_include_array! { 81 | TEST: [i64; 5] => "data/i64_array.txt", 82 | } 83 | 84 | assert_eq!(123, TEST[0]); 85 | assert_eq!(-456, TEST[1]); 86 | assert_eq!(789, TEST[2]); 87 | assert_eq!(1000, TEST[3]); 88 | assert_eq!(500000000000i64, TEST[4]); 89 | } 90 | 91 | #[test] 92 | fn include_array_i128() { 93 | lazy_static_include_array! { 94 | TEST: [i128; 5] => "data/i128_array.txt", 95 | } 96 | 97 | assert_eq!(123, TEST[0]); 98 | assert_eq!(-456, TEST[1]); 99 | assert_eq!(789, TEST[2]); 100 | assert_eq!(1000, TEST[3]); 101 | assert_eq!(500000000000000000000000i128, TEST[4]); 102 | } 103 | 104 | #[test] 105 | fn include_array_usize() { 106 | lazy_static_include_array! { 107 | TEST: [usize; 5] => "data/usize_array.txt", 108 | } 109 | 110 | assert_eq!(123, TEST[0]); 111 | assert_eq!(456, TEST[1]); 112 | assert_eq!(789, TEST[2]); 113 | assert_eq!(1000, TEST[3]); 114 | assert_eq!(5000, TEST[4]); 115 | } 116 | 117 | #[test] 118 | fn include_array_u8() { 119 | lazy_static_include_array! { 120 | TEST: [u8; 5] => "data/u8_array.txt", 121 | } 122 | 123 | assert_eq!(12, TEST[0]); 124 | assert_eq!(34, TEST[1]); 125 | assert_eq!(56, TEST[2]); 126 | assert_eq!(78, TEST[3]); 127 | assert_eq!(90, TEST[4]); 128 | } 129 | 130 | #[test] 131 | fn include_array_u16() { 132 | lazy_static_include_array! { 133 | TEST: [u16; 5] => "data/u16_array.txt", 134 | } 135 | 136 | assert_eq!(123, TEST[0]); 137 | assert_eq!(456, TEST[1]); 138 | assert_eq!(789, TEST[2]); 139 | assert_eq!(1000, TEST[3]); 140 | assert_eq!(5000, TEST[4]); 141 | } 142 | 143 | #[test] 144 | fn include_array_u32() { 145 | lazy_static_include_array! { 146 | TEST: [u32; 5] => "data/u32_array.txt", 147 | } 148 | 149 | assert_eq!(123, TEST[0]); 150 | assert_eq!(456, TEST[1]); 151 | assert_eq!(789, TEST[2]); 152 | assert_eq!(1000, TEST[3]); 153 | assert_eq!(5000, TEST[4]); 154 | } 155 | 156 | #[test] 157 | fn include_array_u64() { 158 | lazy_static_include_array! { 159 | TEST: [u64; 5] => "data/u64_array.txt", 160 | } 161 | 162 | assert_eq!(123, TEST[0]); 163 | assert_eq!(456, TEST[1]); 164 | assert_eq!(789, TEST[2]); 165 | assert_eq!(1000, TEST[3]); 166 | assert_eq!(500000000000u64, TEST[4]); 167 | } 168 | 169 | #[test] 170 | fn include_array_u128() { 171 | lazy_static_include_array! { 172 | TEST: [u128; 5] => "data/u128_array.txt", 173 | } 174 | 175 | assert_eq!(123, TEST[0]); 176 | assert_eq!(456, TEST[1]); 177 | assert_eq!(789, TEST[2]); 178 | assert_eq!(1000, TEST[3]); 179 | assert_eq!(500000000000000000000000u128, TEST[4]); 180 | } 181 | 182 | #[test] 183 | fn include_array_f32() { 184 | lazy_static_include_array! { 185 | TEST: [f32; 5] => "data/f32_array.txt", 186 | } 187 | 188 | assert_eq_float!(123f32, TEST[0]); 189 | assert_eq_float!(-456f32, TEST[1]); 190 | assert_eq_float!(789.5f32, TEST[2]); 191 | assert_eq_float!(1000.123f32, TEST[3]); 192 | assert_eq_float!(5000f32, TEST[4]); 193 | } 194 | 195 | #[test] 196 | fn include_array_f64() { 197 | lazy_static_include_array! { 198 | TEST: [f64; 5] => "data/f64_array.txt", 199 | } 200 | 201 | assert_eq_float!(123f64, TEST[0]); 202 | assert_eq_float!(-456f64, TEST[1]); 203 | assert_eq_float!(789.5f64, TEST[2]); 204 | assert_eq_float!(1000.123f64, TEST[3]); 205 | assert_eq_float!(5000.456f64, TEST[4]); 206 | } 207 | 208 | #[test] 209 | fn include_array_char() { 210 | lazy_static_include_array! { 211 | TEST: [char; 3] => "data/char_array.txt", 212 | } 213 | 214 | assert_eq!('a', TEST[0]); 215 | assert_eq!('b', TEST[1]); 216 | assert_eq!('c', TEST[2]); 217 | } 218 | 219 | #[test] 220 | fn include_array_bool() { 221 | lazy_static_include_array! { 222 | TEST: [bool; 3] => "data/bool_array.txt", 223 | } 224 | 225 | assert!(!TEST[0]); 226 | assert!(TEST[1]); 227 | assert!(!TEST[2]); 228 | } 229 | 230 | #[test] 231 | fn include_array_string() { 232 | lazy_static_include_array! { 233 | TEST: [&'static str; 3] => "data/string_array.txt", 234 | } 235 | 236 | assert_eq!("Hi", TEST[0]); 237 | assert_eq!("Hello", TEST[1]); 238 | assert_eq!("哈囉", TEST[2]); 239 | } 240 | -------------------------------------------------------------------------------- /src/macro_include_str.rs: -------------------------------------------------------------------------------- 1 | #[cfg(debug_assertions)] 2 | /// Includes a utf8-encoded file as a string slice (`&'static str`). 3 | /// 4 | /// The file is located relative to the directory containing the manifest of your package. 5 | #[macro_export] 6 | macro_rules! lazy_static_include_str { 7 | ( @impl $name:ident ) => { 8 | impl ::std::cmp::PartialEq for $name { 9 | #[inline] 10 | fn eq(&self, other: &str) -> bool { 11 | (*$name).eq(other) 12 | } 13 | } 14 | 15 | impl<'a> ::std::cmp::PartialEq<&'a str> for $name { 16 | #[inline] 17 | fn eq(&self, other: &&'a str) -> bool { 18 | (&*$name).eq(other) 19 | } 20 | } 21 | 22 | impl ::std::cmp::PartialEq for $name { 23 | #[inline] 24 | fn eq(&self, other: &$name) -> bool { 25 | true 26 | } 27 | } 28 | 29 | impl<'a> ::std::cmp::PartialEq<$name> for &'a str { 30 | #[inline] 31 | fn eq(&self, other: &$name) -> bool { 32 | self.eq(&*$name) 33 | } 34 | } 35 | 36 | impl ::std::fmt::Debug for $name { 37 | #[inline] 38 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 39 | ::std::fmt::Debug::fmt(*$name, f) 40 | } 41 | } 42 | 43 | impl ::std::fmt::Display for $name { 44 | #[inline] 45 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 46 | ::std::fmt::Display::fmt(*$name, f) 47 | } 48 | } 49 | 50 | impl ::std::convert::AsRef for $name 51 | where 52 | T: ?Sized, 53 | str: ::std::convert::AsRef, 54 | { 55 | #[inline] 56 | fn as_ref(&self) -> &T { 57 | (*$name).as_ref() 58 | } 59 | } 60 | }; 61 | ( @inner $name:ident, $path:expr ) => { 62 | { 63 | use ::std::fs; 64 | use ::std::mem::{forget, transmute}; 65 | 66 | let path = $crate::manifest_dir_macros::not_directory_path!($path); 67 | 68 | let text = fs::read_to_string(path).unwrap(); 69 | 70 | unsafe { 71 | let ret = transmute(text.as_str()); 72 | forget(text); 73 | ret 74 | } 75 | } 76 | }; 77 | ( @unit $(#[$attr: meta])* $name:ident => $path:expr ) => { 78 | $crate::lazy_static::lazy_static! { 79 | $(#[$attr])* 80 | static ref $name: &'static str = $crate::lazy_static_include_str!(@inner $name, $path); 81 | } 82 | 83 | $crate::lazy_static_include_str!(@impl $name); 84 | }; 85 | ( @unit $(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident => $path:expr ) => { 86 | $crate::lazy_static::lazy_static! { 87 | $(#[$attr])* 88 | pub$(($($v)+))? static ref $name: &'static str = $crate::lazy_static_include_str!(@inner $name, $path); 89 | } 90 | 91 | $crate::lazy_static_include_str!(@impl $name); 92 | }; 93 | ( $($(#[$attr: meta])* $name:ident => $path:expr),* $(,)* ) => { 94 | $( 95 | $crate::lazy_static_include_str! { 96 | @unit 97 | $(#[$attr])* 98 | $name => $path 99 | } 100 | )* 101 | }; 102 | ( $($(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident => $path:expr),* $(,)* ) => { 103 | $( 104 | $crate::lazy_static_include_str! { 105 | @unit 106 | $(#[$attr])* 107 | pub$(($($v)+))? $name => $path 108 | } 109 | )* 110 | }; 111 | } 112 | 113 | #[cfg(not(debug_assertions))] 114 | /// Includes a utf8-encoded file as a string slice (`&'static str`). 115 | /// 116 | /// The file is located relative to the directory containing the manifest of your package. 117 | #[macro_export] 118 | macro_rules! lazy_static_include_str { 119 | ( @impl $name:ident ) => { 120 | impl ::std::cmp::PartialEq for $name { 121 | #[inline] 122 | fn eq(&self, other: &str) -> bool { 123 | (*$name).eq(other) 124 | } 125 | } 126 | 127 | impl<'a> ::std::cmp::PartialEq<&'a str> for $name { 128 | #[inline] 129 | fn eq(&self, other: &&'a str) -> bool { 130 | (&*$name).eq(other) 131 | } 132 | } 133 | 134 | impl ::std::cmp::PartialEq for $name { 135 | #[inline] 136 | fn eq(&self, other: &$name) -> bool { 137 | true 138 | } 139 | } 140 | 141 | impl<'a> ::std::cmp::PartialEq<$name> for &'a str { 142 | #[inline] 143 | fn eq(&self, other: &$name) -> bool { 144 | self.eq(&*$name) 145 | } 146 | } 147 | 148 | impl ::std::fmt::Debug for $name { 149 | #[inline] 150 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 151 | ::std::fmt::Debug::fmt(*$name, f) 152 | } 153 | } 154 | 155 | impl ::std::fmt::Display for $name { 156 | #[inline] 157 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 158 | ::std::fmt::Display::fmt(*$name, f) 159 | } 160 | } 161 | 162 | impl ::std::convert::AsRef for $name 163 | where 164 | T: ?Sized, 165 | str: ::std::convert::AsRef, 166 | { 167 | #[inline] 168 | fn as_ref(&self) -> &T { 169 | (*$name).as_ref() 170 | } 171 | } 172 | }; 173 | ( @unit $(#[$attr: meta])* $name:ident => $path:expr ) => { 174 | $crate::lazy_static::lazy_static! { 175 | $(#[$attr])* 176 | static ref $name: &'static str = include_str!($crate::manifest_dir_macros::path!($path)); 177 | } 178 | 179 | $crate::lazy_static_include_str!(@impl $name); 180 | }; 181 | ( @unit $(#[$attr: meta])* pub $name:ident => $path:expr ) => { 182 | $crate::lazy_static::lazy_static! { 183 | $(#[$attr])* 184 | pub static ref $name: &'static str = include_str!($crate::manifest_dir_macros::path!($path)); 185 | } 186 | 187 | $crate::lazy_static_include_str!(@impl $name); 188 | }; 189 | ( @unit $(#[$attr: meta])* pub($($vis:tt)+) $name:ident => $path:expr ) => { 190 | $crate::lazy_static::lazy_static! { 191 | $(#[$attr])* 192 | pub($($vis)+) static ref $name: &'static str = include_str!($crate::manifest_dir_macros::path!($path)); 193 | } 194 | 195 | $crate::lazy_static_include_str!(@impl $name); 196 | }; 197 | ( $($(#[$attr: meta])* $name:ident => $path:expr),* $(,)* ) => { 198 | $( 199 | $crate::lazy_static_include_str! { 200 | @unit 201 | $(#[$attr])* 202 | $name => $path 203 | } 204 | )* 205 | }; 206 | ( $($(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident => $path:expr),* $(,)* ) => { 207 | $( 208 | $crate::lazy_static_include_str! { 209 | @unit 210 | $(#[$attr])* 211 | pub$(($($v)+))? $name => $path 212 | } 213 | )* 214 | }; 215 | } 216 | -------------------------------------------------------------------------------- /src/macro_include_array.rs: -------------------------------------------------------------------------------- 1 | #[cfg(debug_assertions)] 2 | /// Includes a file containing a rust array. 3 | /// 4 | /// The file is located relative to the directory containing the manifest of your package. 5 | #[macro_export] 6 | macro_rules! lazy_static_include_array { 7 | ( @i $name:ident: [$t:ident; $s:expr], $path:expr ) => { 8 | { 9 | let path = $crate::manifest_dir_macros::not_directory_path!($path); 10 | 11 | let text = ::std::fs::read_to_string(path).unwrap(); 12 | 13 | let s = text.trim(); 14 | 15 | let mut result = [0 as $t; $s]; 16 | 17 | if let Ok($crate::syn::Expr::Array(array)) = $crate::syn::parse_str(s) { 18 | for (i, l) in array.elems.into_iter().enumerate() { 19 | if i >= $s { 20 | panic!("incorrect length, bigger than {}, file: {}", $s, path); 21 | } 22 | 23 | let mut neg = false; 24 | 25 | let exp = match l { 26 | $crate::syn::Expr::Lit(exp) => exp, 27 | $crate::syn::Expr::Unary(exp) => { 28 | neg = true; 29 | 30 | match exp.expr.as_ref() { 31 | $crate::syn::Expr::Lit(exp) => exp.clone(), 32 | _ => { 33 | panic!("incorrect element type, index = {}, file: {}", i, path); 34 | } 35 | } 36 | } 37 | _ => { 38 | panic!("incorrect element type, index = {}, file: {}", i, path); 39 | } 40 | }; 41 | 42 | let accept_suffix = stringify!($t); 43 | 44 | match exp.lit { 45 | $crate::syn::Lit::Int(n) => { 46 | let suffix = n.suffix(); 47 | 48 | if !suffix.is_empty() && suffix != accept_suffix { 49 | panic!("incorrect element type, index = {}, file: {}", i, path); 50 | } 51 | 52 | let n: $t = n.base10_parse().unwrap(); 53 | 54 | result[i] = if neg { 55 | -n 56 | } else { 57 | n 58 | }; 59 | } 60 | _ => { 61 | panic!("incorrect element type, index = {}, file: {}", i, path); 62 | } 63 | } 64 | } 65 | 66 | result 67 | } else { 68 | panic!("incorrect array, file: {}", path); 69 | } 70 | } 71 | }; 72 | ( @u $name:ident: [$t:ident; $s:expr], $path:expr ) => { 73 | { 74 | let path = $crate::manifest_dir_macros::not_directory_path!($path); 75 | 76 | let text = ::std::fs::read_to_string(path).unwrap(); 77 | 78 | let s = text.trim(); 79 | 80 | let mut result = [0 as $t; $s]; 81 | 82 | if let Ok($crate::syn::Expr::Array(array)) = $crate::syn::parse_str(s) { 83 | for (i, l) in array.elems.into_iter().enumerate() { 84 | if i >= $s { 85 | panic!("incorrect length, bigger than {}, file: {}", $s, path); 86 | } 87 | 88 | let mut neg = false; 89 | 90 | let exp = match l { 91 | $crate::syn::Expr::Lit(exp) => exp, 92 | _ => { 93 | panic!("incorrect element type, index = {}, file: {}", i, path); 94 | } 95 | }; 96 | 97 | let accept_suffix = stringify!($t); 98 | 99 | match exp.lit { 100 | $crate::syn::Lit::Int(n) => { 101 | let suffix = n.suffix(); 102 | 103 | if !suffix.is_empty() && suffix != accept_suffix { 104 | panic!("incorrect element type, index = {}, file: {}", i, path); 105 | } 106 | 107 | result[i] = n.base10_parse().unwrap(); 108 | } 109 | _ => { 110 | panic!("incorrect element type, index = {}, file: {}", i, path); 111 | } 112 | } 113 | } 114 | 115 | result 116 | } else { 117 | panic!("incorrect array, file: {}", path); 118 | } 119 | } 120 | }; 121 | ( @f $name:ident: [$t:ident; $s:expr], $path:expr ) => { 122 | { 123 | let path = $crate::manifest_dir_macros::not_directory_path!($path); 124 | 125 | let text = ::std::fs::read_to_string(path).unwrap(); 126 | 127 | let s = text.trim(); 128 | 129 | let mut result = [0 as $t; $s]; 130 | 131 | if let Ok($crate::syn::Expr::Array(array)) = $crate::syn::parse_str(s) { 132 | for (i, l) in array.elems.into_iter().enumerate() { 133 | if i >= $s { 134 | panic!("incorrect length, bigger than {}, file: {}", $s, path); 135 | } 136 | 137 | let mut neg = false; 138 | 139 | let exp = match l { 140 | $crate::syn::Expr::Lit(exp) => exp, 141 | $crate::syn::Expr::Unary(exp) => { 142 | neg = true; 143 | 144 | match exp.expr.as_ref() { 145 | $crate::syn::Expr::Lit(exp) => exp.clone(), 146 | _ => { 147 | panic!("incorrect element type, index = {}, file: {}", i, path); 148 | } 149 | } 150 | } 151 | _ => { 152 | panic!("incorrect element type, index = {}, file: {}", i, path); 153 | } 154 | }; 155 | 156 | let accept_suffix = stringify!($t); 157 | 158 | match exp.lit { 159 | $crate::syn::Lit::Float(f) => { 160 | let suffix = f.suffix(); 161 | 162 | if !suffix.is_empty() && suffix != accept_suffix { 163 | panic!("incorrect element type, index = {}, file: {}", i, path); 164 | } 165 | 166 | let f: $t = f.base10_parse().unwrap(); 167 | 168 | result[i] = if neg { 169 | -f 170 | } else { 171 | f 172 | }; 173 | } 174 | $crate::syn::Lit::Int(n) => { 175 | let suffix = n.suffix(); 176 | 177 | if suffix != accept_suffix { 178 | panic!("incorrect element type, index = {}, file: {}", i, path); 179 | } 180 | 181 | let n: $t = n.base10_parse().unwrap(); 182 | 183 | result[i] = if neg { 184 | -n 185 | } else { 186 | n 187 | }; 188 | } 189 | _ => { 190 | panic!("incorrect element type, index = {}, file: {}", i, path); 191 | } 192 | } 193 | } 194 | 195 | result 196 | } else { 197 | panic!("incorrect array, file: {}", path); 198 | } 199 | } 200 | }; 201 | ( @c $name:ident: [$t:ident; $s:expr], $path:expr ) => { 202 | { 203 | let path = $crate::manifest_dir_macros::not_directory_path!($path); 204 | 205 | let text = ::std::fs::read_to_string(path).unwrap(); 206 | 207 | let s = text.trim(); 208 | 209 | let mut result = ['\0'; $s]; 210 | 211 | if let Ok($crate::syn::Expr::Array(array)) = $crate::syn::parse_str(s) { 212 | for (i, l) in array.elems.into_iter().enumerate() { 213 | if i >= $s { 214 | panic!("incorrect length, bigger than {}, file: {}", $s, path); 215 | } 216 | 217 | if let $crate::syn::Expr::Lit(exp) = l { 218 | match exp.lit { 219 | $crate::syn::Lit::Char(c) => { 220 | result[i] = c.value(); 221 | } 222 | _ => { 223 | panic!("incorrect element type, index = {}, file: {}", i, path); 224 | } 225 | } 226 | } else { 227 | panic!("incorrect element type, index = {}, file: {}", i, path); 228 | } 229 | } 230 | 231 | result 232 | } else { 233 | panic!("incorrect array, file: {}", path); 234 | } 235 | } 236 | }; 237 | ( @b $name:ident: [$t:ident; $s:expr], $path:expr ) => { 238 | { 239 | let path = $crate::manifest_dir_macros::not_directory_path!($path); 240 | 241 | let text = ::std::fs::read_to_string(path).unwrap(); 242 | 243 | let s = text.trim(); 244 | 245 | let mut result = [false; $s]; 246 | 247 | if let Ok($crate::syn::Expr::Array(array)) = $crate::syn::parse_str(s) { 248 | for (i, l) in array.elems.into_iter().enumerate() { 249 | if i >= $s { 250 | panic!("incorrect length, bigger than {}, file: {}", $s, path); 251 | } 252 | 253 | if let $crate::syn::Expr::Lit(exp) = l { 254 | match exp.lit { 255 | $crate::syn::Lit::Bool(b) => { 256 | result[i] = b.value; 257 | } 258 | _ => { 259 | panic!("incorrect element type, index = {}, file: {}", i, path); 260 | } 261 | } 262 | } else { 263 | panic!("incorrect element type, index = {}, file: {}", i, path); 264 | } 265 | } 266 | 267 | result 268 | } else { 269 | panic!("incorrect array, file: {}", path); 270 | } 271 | } 272 | }; 273 | ( @s $name:ident: [$t:ident; $s:expr], $path:expr ) => { 274 | { 275 | use ::std::mem::{forget, transmute}; 276 | 277 | let path = $crate::manifest_dir_macros::not_directory_path!($path); 278 | 279 | let text = ::std::fs::read_to_string(path).unwrap(); 280 | 281 | let s = text.trim(); 282 | 283 | let mut result = Vec::with_capacity($s); 284 | 285 | if let Ok($crate::syn::Expr::Array(array)) = $crate::syn::parse_str(s) { 286 | for (i, l) in array.elems.into_iter().enumerate() { 287 | if i >= $s { 288 | panic!("incorrect length, bigger than {}, file: {}", $s, path); 289 | } 290 | 291 | if let $crate::syn::Expr::Lit(exp) = l { 292 | match exp.lit { 293 | $crate::syn::Lit::Str(s) => { 294 | result.push(s.value()); 295 | } 296 | _ => { 297 | panic!("incorrect element type, index = {}, file: {}", i, path); 298 | } 299 | } 300 | } else { 301 | panic!("incorrect element type, index = {}, file: {}", i, path); 302 | } 303 | } 304 | 305 | let mut result_str = [""; $s]; 306 | 307 | for (i, s) in result.iter().enumerate() { 308 | result_str[i] = unsafe { 309 | let ret = transmute(s.as_str()); 310 | ret 311 | }; 312 | } 313 | 314 | unsafe { 315 | forget(result); 316 | }; 317 | 318 | result_str 319 | } else { 320 | panic!("incorrect array, file: {}", path); 321 | } 322 | } 323 | }; 324 | ( @type $name:ident: [isize; $s:expr], $path:expr ) => { 325 | $crate::lazy_static_include_array!(@i $name: [isize; $s], $path); 326 | }; 327 | ( @type $name:ident: [i8; $s:expr], $path:expr ) => { 328 | $crate::lazy_static_include_array!(@i $name: [i8; $s], $path); 329 | }; 330 | ( @type $name:ident: [i16; $s:expr], $path:expr ) => { 331 | $crate::lazy_static_include_array!(@i $name: [i16; $s], $path); 332 | }; 333 | ( @type $name:ident: [i32; $s:expr], $path:expr ) => { 334 | $crate::lazy_static_include_array!(@i $name: [i32; $s], $path); 335 | }; 336 | ( @type $name:ident: [i64; $s:expr], $path:expr ) => { 337 | $crate::lazy_static_include_array!(@i $name: [i64; $s], $path); 338 | }; 339 | ( @type $name:ident: [i128; $s:expr], $path:expr ) => { 340 | $crate::lazy_static_include_array!(@i $name: [i128; $s], $path); 341 | }; 342 | ( @type $name:ident: [usize; $s:expr], $path:expr ) => { 343 | $crate::lazy_static_include_array!(@u $name: [usize; $s], $path); 344 | }; 345 | ( @type $name:ident: [u8; $s:expr], $path:expr ) => { 346 | $crate::lazy_static_include_array!(@u $name: [u8; $s], $path); 347 | }; 348 | ( @type $name:ident: [u16; $s:expr], $path:expr ) => { 349 | $crate::lazy_static_include_array!(@u $name: [u16; $s], $path); 350 | }; 351 | ( @type $name:ident: [u32; $s:expr], $path:expr ) => { 352 | $crate::lazy_static_include_array!(@u $name: [u32; $s], $path); 353 | }; 354 | ( @type $name:ident: [u64; $s:expr], $path:expr ) => { 355 | $crate::lazy_static_include_array!(@u $name: [u64; $s], $path); 356 | }; 357 | ( @type $name:ident: [u128; $s:expr], $path:expr ) => { 358 | $crate::lazy_static_include_array!(@u $name: [u128; $s], $path); 359 | }; 360 | ( @type $name:ident: [f32; $s:expr], $path:expr ) => { 361 | $crate::lazy_static_include_array!(@f $name: [f32; $s], $path); 362 | }; 363 | ( @type $name:ident: [f64; $s:expr], $path:expr ) => { 364 | $crate::lazy_static_include_array!(@f $name: [f64; $s], $path); 365 | }; 366 | ( @type $name:ident: [char; $s:expr], $path:expr ) => { 367 | $crate::lazy_static_include_array!(@c $name: [char; $s], $path); 368 | }; 369 | ( @type $name:ident: [bool; $s:expr], $path:expr ) => { 370 | $crate::lazy_static_include_array!(@b $name: [bool; $s], $path); 371 | }; 372 | ( @type $name:ident: [&'static str; $s:expr], $path:expr ) => { 373 | $crate::lazy_static_include_array!(@s $name: [bool; $s], $path); 374 | }; 375 | ( @unit $(#[$attr: meta])* $name:ident: [$(& $lt:lifetime)? $t:ident; $s:expr] => $path:expr ) => { 376 | $crate::lazy_static::lazy_static! { 377 | $(#[$attr])* 378 | static ref $name: [$(& $lt)? $t; $s] = $crate::lazy_static_include_array!(@type $name: [$(& $lt)? $t; $s], $path); 379 | } 380 | }; 381 | ( @unit $(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident: [$(& $lt:lifetime)? $t:ident; $s:expr] => $path:expr ) => { 382 | $crate::lazy_static::lazy_static! { 383 | $(#[$attr])* 384 | pub$(($($v)+))? static ref $name: [$(& $lt)? $t; $s] = $crate::lazy_static_include_array!(@type $name: [$(& $lt)? $t; $s], $path); 385 | } 386 | }; 387 | ( $($(#[$attr: meta])* $name:ident: [$(& $lt:lifetime)? $t:ident; $s:expr] => $path:expr),* $(,)* ) => { 388 | $( 389 | $crate::lazy_static_include_array! { 390 | @unit 391 | $(#[$attr])* 392 | $name: [$(& $lt)? $t; $s] => $path 393 | } 394 | )* 395 | }; 396 | ( $($(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident: [$(& $lt:lifetime)? $t:ident; $s:expr] => $path:expr),* $(,)* ) => { 397 | $( 398 | $crate::lazy_static_include_array! { 399 | @unit 400 | $(#[$attr])* 401 | pub$(($($v)+))? $name: [$(& $lt)? $t; $s] => $path 402 | } 403 | )* 404 | }; 405 | } 406 | 407 | #[cfg(not(debug_assertions))] 408 | /// Includes a file containing a rust array. 409 | /// 410 | /// The file is located relative to the directory containing the manifest of your package. 411 | #[macro_export] 412 | macro_rules! lazy_static_include_array { 413 | ( @unit $(#[$attr: meta])* $name:ident: [$(& $lt:lifetime)? $t:ident; $s:expr] => $path:expr ) => { 414 | $crate::lazy_static::lazy_static! { 415 | $(#[$attr])* 416 | static ref $name: [$(& $lt)? $t; $s] = include!($crate::manifest_dir_macros::path!($path)); 417 | } 418 | }; 419 | ( @unit $(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident: [$(& $lt:lifetime)? $t:ident; $s:expr] => $path:expr ) => { 420 | $crate::lazy_static::lazy_static! { 421 | $(#[$attr])* 422 | pub$(($($v)+))? static ref $name: [$(& $lt)? $t; $s] = include!($crate::manifest_dir_macros::path!($path)); 423 | } 424 | }; 425 | ( $($(#[$attr: meta])* $name:ident: [$(& $lt:lifetime)? $t:ident; $s:expr] => $path:expr),* $(,)* ) => { 426 | $( 427 | $crate::lazy_static_include_array! { 428 | @unit 429 | $(#[$attr])* 430 | $name: [$(& $lt)? $t; $s] => $path 431 | } 432 | )* 433 | }; 434 | ( $($(#[$attr: meta])* pub$(($($v:tt)+))? $name:ident: [$(& $lt:lifetime)? $t:ident; $s:expr] => $path:expr),* $(,)* ) => { 435 | $( 436 | $crate::lazy_static_include_array! { 437 | @unit 438 | $(#[$attr])* 439 | pub$(($($v)+))? $name: [$(& $lt)? $t; $s] => $path 440 | } 441 | )* 442 | }; 443 | } 444 | --------------------------------------------------------------------------------