{"id":18406939,"url":"https://github.com/nvzqz/byte-set-rs","last_synced_at":"2025-07-16T09:36:34.623Z","repository":{"id":62438694,"uuid":"268214256","full_name":"nvzqz/byte-set-rs","owner":"nvzqz","description":"Efficient sets of bytes for Rust","archived":false,"fork":false,"pushed_at":"2020-06-23T22:36:02.000Z","size":152,"stargazers_count":19,"open_issues_count":6,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-30T13:49:09.526Z","etag":null,"topics":["bytes","data-structures","maps","rust","sets"],"latest_commit_sha":null,"homepage":"https://docs.rs/byte_set","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nvzqz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["nvzqz"],"patreon":"nvzqz","custom":["https://www.paypal.me/nvzqz"]}},"created_at":"2020-05-31T05:19:50.000Z","updated_at":"2023-01-27T12:05:04.000Z","dependencies_parsed_at":"2022-11-01T22:01:25.662Z","dependency_job_id":null,"html_url":"https://github.com/nvzqz/byte-set-rs","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/nvzqz/byte-set-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2Fbyte-set-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2Fbyte-set-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2Fbyte-set-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2Fbyte-set-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nvzqz","download_url":"https://codeload.github.com/nvzqz/byte-set-rs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2Fbyte-set-rs/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265500312,"owners_count":23777459,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bytes","data-structures","maps","rust","sets"],"created_at":"2024-11-06T03:11:28.079Z","updated_at":"2025-07-16T09:36:34.598Z","avatar_url":"https://github.com/nvzqz.png","language":"Rust","funding_links":["https://github.com/sponsors/nvzqz","https://patreon.com/nvzqz","https://www.paypal.me/nvzqz","https://github.com/sponsors/nvzqz)!"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n    \u003ch1\u003e\n        \u003ca href=\"https://github.com/nvzqz/byte-set-rs\"\u003e\n            ByteSet\n        \u003c/a\u003e\n    \u003c/h1\u003e\n    \u003ca href=\"https://crates.io/crates/byte_set\"\u003e\n        \u003cimg src=\"https://img.shields.io/crates/v/byte_set.svg\" alt=\"Crates.io\"\u003e\n        \u003cimg src=\"https://img.shields.io/crates/d/byte_set.svg\" alt=\"Downloads\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://docs.rs/byte_set\"\u003e\n        \u003cimg src=\"https://docs.rs/byte_set/badge.svg\" alt=\"docs.rs\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/nvzqz/byte-set-rs/actions?query=workflow%3ACI\"\u003e\n        \u003cimg src=\"https://github.com/nvzqz/byte-set-rs/workflows/CI/badge.svg\" alt=\"Build Status\"\u003e\n    \u003c/a\u003e\n    \u003cbr\u003e\u003cbr\u003e\n\u003c/div\u003e\n\nEfficient sets of bytes for Rust, brought to you by [@NikolaiVazquez]!\n\nThe star of the show is [`ByteSet`]: an allocation-free sorted set. It is a\n*much faster* alternative to [`HashSet\u003cu8\u003e`], [`BTreeSet\u003cu8\u003e`], and other types\nfor a variety of scenarios. See [\"Implementation\"](#implementation) for a peek\nunder the hood.\n\nIf you found this library useful, please consider\n[sponsoring me on GitHub](https://github.com/sponsors/nvzqz)!\n\n## Table of Contents\n\n1. [Usage](#usage)\n2. [Examples](#examples)\n   1. [`ByteSet` Type](#byteset-type)\n      1. [Insert](#insert)\n      2. [Extend](#extend)\n      3. [Remove](#remove)\n      4. [Iterate](#iterate)\n      5. [Contains](#contains)\n      6. [Subset](#subset)\n      7. [Min and Max](#min-and-max)\n   2. [`byte_set!` Macro](#byte_set-macro)\n3. [Implementation](#implementation)\n4. [Benchmarks](#benchmarks)\n5. [Ecosystem Integrations](#ecosystem-integrations)\n   1. [`rand`](#rand)\n   2. [`serde`](#serde)\n6. [License](#license)\n\n## Usage\n\nThis library is available [on crates.io][crate] and can be used by adding the\nfollowing to your project's [`Cargo.toml`]:\n\n```toml\n[dependencies]\nbyte_set = \"0.1.3\"\n```\n\nTo import the [`byte_set!`] macro, add this to your crate root (`main.rs` or\n`lib.rs`):\n\n```rust\nuse byte_set::byte_set;\n```\n\nIf you're not using [Rust 2018 edition][2018], it must be imported differently:\n\n```rust\n#[macro_use]\nextern crate byte_set;\n```\n\n## Examples\n\n### `ByteSet` Type\n\nFirst, let's import [`ByteSet`]:\n\n```rust\nuse byte_set::ByteSet;\n```\n\nHere's how you create an empty set:\n\n```rust\nlet bytes = ByteSet::new();\n```\n\nYou can create a set filled with all bytes (0 through 255) just as easily:\n\n```rust\nlet bytes = ByteSet::full();\n```\n\nOk, let's see what we can do with this. Note that this isn't the only available\nfunctionality. See [`ByteSet`] for a complete list.\n\n#### Insert\n\nUse [`insert`] to include a single byte, by mutating the [`ByteSet`] in-place:\n\n```rust\nlet mut bytes = ByteSet::new();\nbytes.insert(255);\n```\n\nUse [`inserting`] as an immutable alternative, by passing the calling\n[`ByteSet`] by value:\n\n```rust\nlet bytes = ByteSet::new().inserting(255);\n```\n\nUse [`insert_all`] to include all bytes of another [`ByteSet`], by mutating the\n[`ByteSet`] in-place:\n\n```rust\nlet mut alphabet = ByteSet::ASCII_UPPERCASE;\nalphabet.insert_all(ByteSet::ASCII_LOWERCASE);\n\nassert_eq!(alphabet, ByteSet::ASCII_ALPHABETIC);\n```\n\nUse [`inserting_all`] as an immutable alternative, by passing the calling\n[`ByteSet`] by value:\n\n```rust\nlet alphabet = ByteSet::ASCII_UPPERCASE.inserting_all(ByteSet::ASCII_LOWERCASE);\n\nassert_eq!(alphabet, ByteSet::ASCII_ALPHABETIC);\n```\n\n#### Extend\n\nRather than call [`insert`] in a loop, [`extend`] simplifies inserting from an\niterator:\n\n```rust\nfn take_string(bytes: \u0026mut ByteSet, s: \u0026str) {\n    bytes.extend(s.as_bytes());\n}\n```\n\nBecause this iterates over the entire input, it is *much* more efficient to use\n[`insert_all`] instead of [`extend`] when inserting another [`ByteSet`].\n\n#### Remove\n\nUse [`remove`] to exclude a single byte by mutating the set in-place:\n\n```rust\nlet mut bytes = ByteSet::full();\nbytes.remove(255);\n```\n\nUse [`removing`] as an immutable alternative, by passing the calling [`ByteSet`]\nby value:\n\n```rust\nlet bytes = ByteSet::full().removing(255);\n```\n\nUse [`remove_all`] to exclude all bytes of another [`ByteSet`], by mutating the\n[`ByteSet`] in-place:\n\n```rust\nlet mut alphabet = ByteSet::ASCII_ALPHANUMERIC;\nalphabet.remove_all(ByteSet::ASCII_DIGIT);\n\nassert_eq!(alphabet, ByteSet::ASCII_ALPHABETIC);\n```\n\nUse [`removing_all`] as an immutable alternative, by passing the calling\n[`ByteSet`] by value:\n\n```rust\nlet alphabet = ByteSet::ASCII_ALPHANUMERIC.removing_all(ByteSet::ASCII_DIGIT);\n\nassert_eq!(alphabet, ByteSet::ASCII_ALPHABETIC);\n```\n\n#### Iterate\n\nIterating can be done with just a `for` loop, and goes in order from least to\ngreatest:\n\n```rust\nfn small_to_big(bytes: ByteSet) {\n    for byte in bytes {\n        do_work(byte);\n    }\n}\n```\n\nIterating in reverse is slightly more verbose, and goes in order from greatest\nto least:\n\n```rust\nfn big_to_small(bytes: ByteSet) {\n    for byte in bytes.into_iter().rev() {\n        do_work(byte);\n    }\n}\n```\n\n#### Contains\n\nIt wouldn't really be a set if you couldn't check if it has specific items.\n\nUse [`contains`] to check a single byte:\n\n```rust\nfn has_null(bytes: \u0026ByteSet) -\u003e bool {\n    bytes.contains(0)\n}\n```\n\nUse [`contains_any`] to check for any matches in another [`ByteSet`]:\n\n```rust\nfn intersects(a: \u0026ByteSet, b: \u0026ByteSet) -\u003e bool {\n    a.contains_any(b)\n}\n```\n\n#### Subset\n\nUse [`is_subset`] to check that all of the bytes in a [`ByteSet`] are contained\nin another:\n\n```rust\nfn test(a: \u0026ByteSet, b: \u0026ByteSet) {\n    assert!(a.is_subset(b));\n\n    // Always passes because every set is a subset of itself.\n    assert!(a.is_subset(a));\n}\n```\n\nUse [`is_strict_subset`] to check [`is_subset`] *and* that the sets are not the\nsame:\n\n```rust\nfn test(a: \u0026ByteSet, b: \u0026ByteSet) {\n    assert!(a.is_strict_subset(b));\n\n    // `a` is equal to itself.\n    assert!(!a.is_strict_subset(a));\n}\n```\n\nFor the sake of completion, there is also [`is_superset`] and\n[`is_strict_superset`], which call these functions with `a` and `b` switched.\n\n#### Min and Max\n\nUse [`first`] to get the smallest byte and [`last`] to get the biggest byte:\n\n```rust\nfn sanity_check(bytes: \u0026ByteSet) {\n    if let (Some(first), Some(last)) = (bytes.first(), bytes.last()) {\n        assert!(first \u003c= last);\n    } else {\n        // `bytes` is empty.\n    }\n}\n```\n\nThese are the first and last bytes returned when iterating.\n\n### `byte_set!` Macro\n\n[`byte_set!`] enables you to create a [`ByteSet`] with the same syntax as [`vec!`]\nor array expressions:\n\n```rust\nlet bytes = byte_set![1, 2, 3, b'x', b'y', b'z'];\n```\n\nIt even works at compile-time in a `const` expression:\n\n```rust\nconst WHOA: ByteSet = byte_set![b'w', b'h', b'o', b'a'];\n\nstatic ABC: ByteSet = byte_set![b'a', b'c', b'c'];\n```\n\n## Implementation\n\n[`ByteSet`] is implemented as a 256-bit mask where each bit corresponds to a\nbyte value. The first (least significant) bit in the mask represents the first\nbyte (0) in the set. Likewise, the last last (most significant) bit represents\nthe last byte (255).\n\nGiven the following [`ByteSet`]:\n\n```rust\nlet bytes = byte_set![0, 1, 4, 5, 244];\n```\n\nThe in-memory representation of `bytes` would look like:\n\n```text\n Byte: 0 1 2 3 4 5 6 7 ... 253 244 255\nValue: 1 1 0 0 1 1 0 0 ...  0   1   0\n```\n\nThis bit mask is composed of either `[u64; 4]` or `[u32; 8]` depending on the\ntarget CPU (see [#3]). Because this comes out to only 32 bytes, [`ByteSet`]\nimplements [`Copy`].\n\n## Benchmarks\n\nI will upload benchmarks run from my machine soon.\n\nIn the meantime, you can benchmark this library by running:\n\n```sh\ncargo bench\n```\n\nBy default, this will benchmark [`ByteSet`] along with various other types to\ncompare performance. Note that this will take **a long time** (about 1 hour and\n30 minutes).\n\nBenchmark only [`ByteSet`] by running:\n\n```sh\ncargo bench ByteSet\n```\n\nThis takes about 15 minutes, so maybe grab a coffee in the meantime.\n\nBenchmark a specific [`ByteSet`] operation by running:\n\n```sh\ncargo bench $operation/ByteSet\n```\n\nSee `/benches/benchmarks` for strings that can be used for `$operation`.\n\nNote that `cargo bench` takes a regular expression, so `Contains (Random)` will\nnot work because the parentheses are treated as a capture group. To match\nparentheses, escape them: `Contains \\(Random\\)`.\n\n## Ecosystem Integrations\n\nThis library has extended functionality for some popular crates.\n\n### `rand`\n\nUse the `rand` (or `rand_core`) feature in your [`Cargo.toml`] to enable random\n[`ByteSet`] generation:\n\n```toml\n[dependencies.byte_set]\nversion = \"0.1.3\"\nfeatures = [\"rand\"]\n```\n\nThis makes the following possible:\n\n```rust\nlet bytes = rand::random::\u003cByteSet\u003e();\n\n// Same as above.\nlet bytes = ByteSet::rand(rand::thread_rng());\n\n// Handle failure instead of panicking.\nmatch ByteSet::try_rand(rand::rngs::OsRng) {\n    Ok(bytes)  =\u003e // ...\n    Err(error) =\u003e // ...\n}\n```\n\n### `serde`\n\nUse the `serde` feature in your [`Cargo.toml`] to enable [`Serialize`] and\n[`Deserialize`] for [`ByteSet`]:\n\n```toml\n[dependencies.byte_set]\nversion = \"0.1.3\"\nfeatures = [\"serde\"]\n```\n\nThis makes the following possible:\n\n```rust\nuse serde::{Serialize, Deserialize};\n\n#[derive(Serialize, Deserialize)]\nstruct MyValue {\n    bytes: ByteSet\n}\n```\n\n[`ByteSet`] can be serialized into a `u8` sequence, and deserialized from\n`\u0026[u8]` or a `u8` sequence.\n\nRead more about using `serde` at [serde.rs](https://serde.rs/).\n\n## License\n\nThis project is released under either:\n\n- [MIT License](https://github.com/nvzqz/byte-set-rs/blob/master/LICENSE-MIT)\n\n- [Apache License (Version 2.0)](https://github.com/nvzqz/byte-set-rs/blob/master/LICENSE-APACHE)\n\nat your choosing.\n\n[@NikolaiVazquez]: https://twitter.com/NikolaiVazquez\n\n[`Cargo.toml`]: https://doc.rust-lang.org/cargo/reference/manifest.html\n[2018]:         https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#rust-2018\n[crate]:        https://crates.io/crates/byte_set\n\n[`BTreeSet\u003cu8\u003e`]:   https://doc.rust-lang.org/std/collections/struct.BTreeSet.html\n[`Copy`]:           https://doc.rust-lang.org/std/marker/trait.Copy.html\n[`HashSet\u003cu8\u003e`]:    https://doc.rust-lang.org/std/collections/struct.HashSet.html\n[`u8`]:             https://doc.rust-lang.org/std/primitive.u8.html\n[`vec!`]:           https://doc.rust-lang.org/std/macro.vec.html\n\n[`Serialize`]:   https://docs.rs/serde/1.*/serde/trait.Serialize.html\n[`Deserialize`]: https://docs.rs/serde/1.*/serde/trait.Deserialize.html\n\n[#3]: https://github.com/nvzqz/byte-set-rs/issues/3\n\n\u003c!-- These links must be replaced with local ones when used in crate docs: --\u003e\n[`byte_set!`]:          https://docs.rs/byte_set/0.1.3/byte_set/macro.byte_set.html\n[`ByteSet`]:            https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html\n[`contains_any`]:       https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.contains_any\n[`contains`]:           https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.contains\n[`extend`]:             https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#impl-Extend%3Cu8%3E\n[`first`]:              https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.first\n[`insert_all`]:         https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.insert_all\n[`insert`]:             https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.insert\n[`inserting_all`]:      https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.inserting_all\n[`inserting`]:          https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.inserting\n[`last`]:               https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.last\n[`remove_all`]:         https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.remove_all\n[`remove`]:             https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.remove\n[`removing_all`]:       https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.removing_all\n[`removing`]:           https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.removing\n[`is_strict_subset`]:   https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.is_strict_subset\n[`is_subset`]:          https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.is_subset\n[`is_strict_superset`]: https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.is_strict_superset\n[`is_superset`]:        https://docs.rs/byte_set/0.1.3/byte_set/struct.ByteSet.html#method.is_superset\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnvzqz%2Fbyte-set-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnvzqz%2Fbyte-set-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnvzqz%2Fbyte-set-rs/lists"}