From 5316f272cbfb42b9792c7315d15381f44828823d Mon Sep 17 00:00:00 2001 From: Guillaume Binet Date: Mon, 22 Dec 2025 11:08:05 -0600 Subject: [PATCH 1/6] first pass --- .gitignore | 2 + CODE_OF_CONDUCT.md | 128 ----- Cargo.lock | 991 ------------------------------------ Cargo.toml | 214 ++------ Cargo.toml.orig | 73 --- readme.md => README.md | 0 derive/.cargo_vcs_info.json | 6 + derive/.gitignore | 2 + derive/Cargo.toml | 24 + derive/LICENSE.md | 21 + derive/README.md | 28 + derive/src/attribute.rs | 131 +++++ derive/src/derive_enum.rs | 449 ++++++++++++++++ derive/src/derive_struct.rs | 211 ++++++++ derive/src/lib.rs | 105 ++++ src/lib.rs | 4 +- 16 files changed, 1029 insertions(+), 1360 deletions(-) create mode 100644 .gitignore delete mode 100644 CODE_OF_CONDUCT.md delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml.orig rename readme.md => README.md (100%) create mode 100644 derive/.cargo_vcs_info.json create mode 100644 derive/.gitignore create mode 100644 derive/Cargo.toml create mode 100644 derive/LICENSE.md create mode 100644 derive/README.md create mode 100644 derive/src/attribute.rs create mode 100644 derive/src/derive_enum.rs create mode 100644 derive/src/derive_struct.rs create mode 100644 derive/src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54466f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target + diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 5849b62..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,128 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -abuse@dos.cafe. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index cc5084e..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,991 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "aliasable" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bincode" -version = "2.0.1" -dependencies = [ - "bincode 1.3.3", - "bincode_derive", - "bumpalo", - "chrono", - "criterion", - "glam", - "ouroboros", - "rand", - "serde", - "serde_derive", - "serde_json", - "tempfile", - "unty", - "uuid", -] - -[[package]] -name = "bincode_derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" -dependencies = [ - "virtue", -] - -[[package]] -name = "bitflags" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" - -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" -dependencies = [ - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "clap" -version = "4.5.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" -dependencies = [ - "anstyle", - "clap_lex", -] - -[[package]] -name = "clap_lex" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "is-terminal", - "itertools", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - -[[package]] -name = "either" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets", -] - -[[package]] -name = "glam" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" -dependencies = [ - "serde", -] - -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "is-terminal" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "libc" -version = "0.2.170" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "log" -version = "0.4.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" - -[[package]] -name = "oorandom" -version = "11.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" - -[[package]] -name = "ouroboros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59" -dependencies = [ - "aliasable", - "ouroboros_macro", - "static_assertions", -] - -[[package]] -name = "ouroboros_macro" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" -dependencies = [ - "heck", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn", -] - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "version_check", - "yansi", -] - -[[package]] -name = "quote" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "rustversion" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" - -[[package]] -name = "ryu" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "serde" -version = "1.0.218" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.218" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "2.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tempfile" -version = "3.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" -dependencies = [ - "cfg-if", - "fastrand", - "getrandom 0.3.1", - "once_cell", - "rustix", - "windows-sys", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "unicode-ident" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" - -[[package]] -name = "unty" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" - -[[package]] -name = "uuid" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" -dependencies = [ - "serde", -] - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "virtue" -version = "0.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-link" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "wit-bindgen-rt" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" -dependencies = [ - "bitflags", -] - -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml index 0be40d9..0e622a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,192 +1,74 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. +[workspace] +members = ["derive"] [package] -edition = "2021" -rust-version = "1.85.0" -name = "bincode" -version = "2.0.1" +name = "cu-bincode" +version = "2.0.2" authors = [ + "Guillaume Binet ", "Ty Overby ", "Zoey Riordan ", "Victor Koenders ", ] -build = false -exclude = [ - "logo.svg", - "examples/*", - ".gitignore", - ".github/", -] +exclude = ["logo.svg", "examples/*", ".gitignore", ".github/"] +rust-version = "1.92.0" + publish = true -autolib = false -autobins = false -autoexamples = false -autotests = false -autobenches = false -description = "A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!" -documentation = "https://docs.rs/bincode" -readme = "readme.md" -keywords = [ - "binary", - "encode", - "decode", - "serialize", - "deserialize", -] -categories = [ - "encoding", - "network-programming", -] + +repository = "https://github.com/copper-robotics/cu-bincode" +documentation = "https://docs.rs/cu-bincode" +readme = "./readme.md" +categories = ["encoding", "network-programming"] +keywords = ["binary", "encode", "decode", "serialize", "deserialize"] + license = "MIT" -repository = "https://github.com/bincode-org/bincode" +description = "A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!" -[package.metadata.docs.rs] -all-features = true -rustdoc-args = [ - "--cfg", - "docsrs", -] +edition = "2024" [features] +default = ["std", "derive"] +std = ["alloc", "serde?/std"] alloc = ["serde?/alloc"] -default = [ - "std", - "derive", -] -derive = ["bincode_derive"] -std = [ - "alloc", - "serde?/std", -] - -[lib] -name = "bincode" -path = "src/lib.rs" - -[[test]] -name = "alloc" -path = "tests/alloc.rs" - -[[test]] -name = "atomic" -path = "tests/atomic.rs" - -[[test]] -name = "basic_types" -path = "tests/basic_types.rs" - -[[test]] -name = "context" -path = "tests/context.rs" - -[[test]] -name = "derive" -path = "tests/derive.rs" - -[[test]] -name = "derive_rename" -path = "tests/derive_rename.rs" - -[[test]] -name = "error_size" -path = "tests/error_size.rs" - -[[test]] -name = "issues" -path = "tests/issues.rs" - -[[test]] -name = "serde" -path = "tests/serde.rs" - -[[test]] -name = "std" -path = "tests/std.rs" - -[[test]] -name = "utils" -path = "tests/utils.rs" +derive = ["dep:cu_bincode_derive"] + +[dependencies] +cu_bincode_derive = { path = "derive", version = "2.0.2", optional = true } +serde = { version = "1.0", default-features = false, optional = true } +unty = "0.0" + +# Used for tests +[dev-dependencies] +ouroboros = "0.18" +serde_derive = "1.0" +serde_json = { version = "1.0", default-features = false } +tempfile = "3.23" +criterion = "0.8" +rand = "0.9" +uuid = { version = "1.1", features = ["serde"] } +chrono = { version = "0.4", features = ["serde"] } +glam = { version = "0.25", features = ["serde"] } +bincode_1 = { version = "1.3", package = "bincode" } +serde = { version = "1.0", features = ["derive"] } +bumpalo = { version = "3.16.0", features = ["collections"] } [[bench]] -name = "inline" -path = "benches/inline.rs" +name = "varint" harness = false [[bench]] -name = "string" -path = "benches/string.rs" +name = "inline" harness = false [[bench]] -name = "varint" -path = "benches/varint.rs" +name = "string" harness = false -[dependencies.bincode_derive] -version = "2.0.1" -optional = true - -[dependencies.serde] -version = "1.0" -optional = true -default-features = false - -[dependencies.unty] -version = "0.0.4" - -[dev-dependencies.bincode_1] -version = "1.3" -package = "bincode" - -[dev-dependencies.bumpalo] -version = "3.16.0" -features = ["collections"] - -[dev-dependencies.chrono] -version = "0.4" -features = ["serde"] - -[dev-dependencies.criterion] -version = "0.5" - -[dev-dependencies.glam] -version = "0.25" -features = ["serde"] - -[dev-dependencies.ouroboros] -version = "0.18.3" - -[dev-dependencies.rand] -version = "0.8" - -[dev-dependencies.serde] -version = "1.0" -features = ["derive"] - -[dev-dependencies.serde_derive] -version = "1.0" - -[dev-dependencies.serde_json] -version = "1.0" -default-features = false - -[dev-dependencies.tempfile] -version = "3.2" - -[dev-dependencies.uuid] -version = "1.1" -features = ["serde"] - [profile.bench] -lto = true codegen-units = 1 debug = 1 +lto = true + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/Cargo.toml.orig b/Cargo.toml.orig deleted file mode 100644 index 528b904..0000000 --- a/Cargo.toml.orig +++ /dev/null @@ -1,73 +0,0 @@ -[workspace] -members = ["derive", "compatibility"] - -[package] -name = "bincode" -version = "2.0.1" # remember to update html_root_url and bincode_derive -authors = [ - "Ty Overby ", - "Zoey Riordan ", - "Victor Koenders ", -] -exclude = ["logo.svg", "examples/*", ".gitignore", ".github/"] -rust-version = "1.85.0" - -publish = true - -repository = "https://github.com/bincode-org/bincode" -documentation = "https://docs.rs/bincode" -readme = "./readme.md" -categories = ["encoding", "network-programming"] -keywords = ["binary", "encode", "decode", "serialize", "deserialize"] - -license = "MIT" -description = "A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!" - -edition = "2021" - -[features] -default = ["std", "derive"] -std = ["alloc", "serde?/std"] -alloc = ["serde?/alloc"] -derive = ["bincode_derive"] - -[dependencies] -bincode_derive = { path = "derive", version = "2.0.1", optional = true } -serde = { version = "1.0", default-features = false, optional = true } -unty = "0.0.4" - -# Used for tests -[dev-dependencies] -ouroboros = "0.18.3" -serde_derive = "1.0" -serde_json = { version = "1.0", default-features = false } -tempfile = "3.2" -criterion = "0.5" -rand = "0.8" -uuid = { version = "1.1", features = ["serde"] } -chrono = { version = "0.4", features = ["serde"] } -glam = { version = "0.25", features = ["serde"] } -bincode_1 = { version = "1.3", package = "bincode" } -serde = { version = "1.0", features = ["derive"] } -bumpalo = { version = "3.16.0", features = ["collections"] } - -[[bench]] -name = "varint" -harness = false - -[[bench]] -name = "inline" -harness = false - -[[bench]] -name = "string" -harness = false - -[profile.bench] -codegen-units = 1 -debug = 1 -lto = true - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = ["--cfg", "docsrs"] diff --git a/readme.md b/README.md similarity index 100% rename from readme.md rename to README.md diff --git a/derive/.cargo_vcs_info.json b/derive/.cargo_vcs_info.json new file mode 100644 index 0000000..9546ae0 --- /dev/null +++ b/derive/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4673360aa638b2b907dff24538de54f258d157da" + }, + "path_in_vcs": "derive" +} \ No newline at end of file diff --git a/derive/.gitignore b/derive/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/derive/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/derive/Cargo.toml b/derive/Cargo.toml new file mode 100644 index 0000000..d1be464 --- /dev/null +++ b/derive/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "cu_bincode_derive" +version = "2.0.2" +authors = [ + "Guillaume Binet ", + "Zoey Riordan ", + "Victor Koenders ", +] +edition = "2024" +rust-version = "1.92" + +repository = "https://github.com/copper-robotics/cu_bincode" +documentation = "https://docs.rs/cu_bincode_derive" +readme = "./readme.md" +categories = ["encoding", "network-programming"] +keywords = ["binary", "encode", "decode", "serialize", "deserialize"] +license = "MIT" +description = "Implementation of #[derive(Encode, Decode)] for bincode" + +[lib] +proc-macro = true + +[dependencies] +virtue = "0.0" diff --git a/derive/LICENSE.md b/derive/LICENSE.md new file mode 100644 index 0000000..26b1f00 --- /dev/null +++ b/derive/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Ty Overby + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/derive/README.md b/derive/README.md new file mode 100644 index 0000000..0e652ce --- /dev/null +++ b/derive/README.md @@ -0,0 +1,28 @@ +# Bincode-derive + +The derive crate for bincode. Implements `bincode::Encode` and `bincode::Decode`. + +This crate is roughly split into 2 parts: + +# Parsing + +Most of parsing is done in the `src/parse/` folder. This will generate the following types: +- `Attributes`, not being used currently +- `Visibility`, not being used currently +- `DataType` either `Struct` or `Enum`, with the name of the data type being parsed +- `Generics` the generics part of the type, e.g. `struct Foo<'a>` +- `GenericConstraints` the "where" part of the type + +# Generate + +Generating the code implementation is done in either `src/derive_enum.rs` and `src/derive_struct.rs`. + +This is supported by the structs in `src/generate`. The most notable points of this module are: +- `StreamBuilder` is a thin but friendly wrapper around `TokenStream` +- `Generator` is the base type of the code generator. This has helper methods to generate implementations: + - `ImplFor` is a helper struct for a single `impl A for B` construction. In this functions can be defined: + - `GenerateFnBody` is a helper struct for a single function in the above `impl`. This is created with a callback to `FnBuilder` which helps set some properties. `GenerateFnBody` has a `stream()` function which returns ` StreamBuilder` for the function. + +For additional derive testing, see the test cases in `../tests` + +For testing purposes, all generated code is outputted to the current `target/generated/bincode` folder, under file name `_Encode.rs` and `_Decode.rs`. This can help with debugging. diff --git a/derive/src/attribute.rs b/derive/src/attribute.rs new file mode 100644 index 0000000..d6e8042 --- /dev/null +++ b/derive/src/attribute.rs @@ -0,0 +1,131 @@ +use virtue::prelude::*; +use virtue::utils::{parse_tagged_attribute, ParsedAttribute}; + +pub struct ContainerAttributes { + pub crate_name: String, + pub bounds: Option<(String, Literal)>, + pub decode_bounds: Option<(String, Literal)>, + pub decode_context: Option<(String, Literal)>, + pub borrow_decode_bounds: Option<(String, Literal)>, + pub encode_bounds: Option<(String, Literal)>, +} + +impl Default for ContainerAttributes { + fn default() -> Self { + Self { + crate_name: "::bincode".to_string(), + bounds: None, + decode_bounds: None, + decode_context: None, + encode_bounds: None, + borrow_decode_bounds: None, + } + } +} + +impl FromAttribute for ContainerAttributes { + fn parse(group: &Group) -> Result> { + let attributes = match parse_tagged_attribute(group, "bincode")? { + Some(body) => body, + None => return Ok(None), + }; + let mut result = Self::default(); + for attribute in attributes { + match attribute { + ParsedAttribute::Property(key, val) if key.to_string() == "crate" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.crate_name = val_string[1..val_string.len() - 1].to_string(); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) if key.to_string() == "bounds" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.bounds = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) if key.to_string() == "decode_bounds" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.decode_bounds = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) if key.to_string() == "decode_context" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.decode_context = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) if key.to_string() == "encode_bounds" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.encode_bounds = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) + if key.to_string() == "borrow_decode_bounds" => + { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.borrow_decode_bounds = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Tag(i) => { + return Err(Error::custom_at("Unknown field attribute", i.span())) + } + ParsedAttribute::Property(key, _) => { + return Err(Error::custom_at("Unknown field attribute", key.span())) + } + _ => {} + } + } + Ok(Some(result)) + } +} + +#[derive(Default)] +pub struct FieldAttributes { + pub with_serde: bool, +} + +impl FromAttribute for FieldAttributes { + fn parse(group: &Group) -> Result> { + let attributes = match parse_tagged_attribute(group, "bincode")? { + Some(body) => body, + None => return Ok(None), + }; + let mut result = Self::default(); + for attribute in attributes { + match attribute { + ParsedAttribute::Tag(i) if i.to_string() == "with_serde" => { + result.with_serde = true; + } + ParsedAttribute::Tag(i) => { + return Err(Error::custom_at("Unknown field attribute", i.span())) + } + ParsedAttribute::Property(key, _) => { + return Err(Error::custom_at("Unknown field attribute", key.span())) + } + _ => {} + } + } + Ok(Some(result)) + } +} diff --git a/derive/src/derive_enum.rs b/derive/src/derive_enum.rs new file mode 100644 index 0000000..2ba17c5 --- /dev/null +++ b/derive/src/derive_enum.rs @@ -0,0 +1,449 @@ +use crate::attribute::{ContainerAttributes, FieldAttributes}; +use virtue::prelude::*; + +const TUPLE_FIELD_PREFIX: &str = "field_"; + +pub(crate) struct DeriveEnum { + pub variants: Vec, + pub attributes: ContainerAttributes, +} + +impl DeriveEnum { + fn iter_fields(&self) -> EnumVariantIterator { + EnumVariantIterator { + idx: 0, + variants: &self.variants, + } + } + + pub fn generate_encode(self, generator: &mut Generator) -> Result<()> { + let crate_name = self.attributes.crate_name.as_str(); + generator + .impl_for(format!("{}::Encode", crate_name)) + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = + (self.attributes.encode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) + { + where_constraints.clear(); + where_constraints + .push_parsed_constraint(bounds) + .map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints + .push_constraint(g, format!("{}::Encode", crate_name)) + .unwrap(); + } + } + Ok(()) + })? + .generate_fn("encode") + .with_generic_deps("__E", [format!("{}::enc::Encoder", crate_name)]) + .with_self_arg(FnSelfArg::RefSelf) + .with_arg("encoder", "&mut __E") + .with_return_type(format!( + "core::result::Result<(), {}::error::EncodeError>", + crate_name + )) + .body(|fn_body| { + fn_body.ident_str("match"); + fn_body.ident_str("self"); + fn_body.group(Delimiter::Brace, |match_body| { + if self.variants.is_empty() { + self.encode_empty_enum_case(match_body)?; + } + for (variant_index, variant) in self.iter_fields() { + // Self::Variant + match_body.ident_str("Self"); + match_body.puncts("::"); + match_body.ident(variant.name.clone()); + + // if we have any fields, declare them here + // Self::Variant { a, b, c } + if let Some(fields) = variant.fields.as_ref() { + let delimiter = fields.delimiter(); + match_body.group(delimiter, |field_body| { + for (idx, field_name) in fields.names().into_iter().enumerate() { + if idx != 0 { + field_body.punct(','); + } + field_body.push( + field_name.to_token_tree_with_prefix(TUPLE_FIELD_PREFIX), + ); + } + Ok(()) + })?; + } + + // Arrow + // Self::Variant { a, b, c } => + match_body.puncts("=>"); + + // Body of this variant + // Note that the fields are available as locals because of the match destructuring above + // { + // encoder.encode_u32(n)?; + // bincode::Encode::encode(a, encoder)?; + // bincode::Encode::encode(b, encoder)?; + // bincode::Encode::encode(c, encoder)?; + // } + match_body.group(Delimiter::Brace, |body| { + // variant index + body.push_parsed(format!("::encode", crate_name))?; + body.group(Delimiter::Parenthesis, |args| { + args.punct('&'); + args.group(Delimiter::Parenthesis, |num| { + num.extend(variant_index); + Ok(()) + })?; + args.punct(','); + args.push_parsed("encoder")?; + Ok(()) + })?; + body.punct('?'); + body.punct(';'); + // If we have any fields, encode them all one by one + if let Some(fields) = variant.fields.as_ref() { + for field_name in fields.names() { + let attributes = field_name + .attributes() + .get_attribute::()? + .unwrap_or_default(); + if attributes.with_serde { + body.push_parsed(format!( + "{0}::Encode::encode(&{0}::serde::Compat({1}), encoder)?;", + crate_name, + field_name.to_string_with_prefix(TUPLE_FIELD_PREFIX), + ))?; + } else { + body.push_parsed(format!( + "{0}::Encode::encode({1}, encoder)?;", + crate_name, + field_name.to_string_with_prefix(TUPLE_FIELD_PREFIX), + ))?; + } + } + } + body.push_parsed("core::result::Result::Ok(())")?; + Ok(()) + })?; + match_body.punct(','); + } + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + } + + /// If we're encoding an empty enum, we need to add an empty case in the form of: + /// `_ => core::unreachable!(),` + fn encode_empty_enum_case(&self, builder: &mut StreamBuilder) -> Result { + builder.push_parsed("_ => core::unreachable!()").map(|_| ()) + } + + /// Build the catch-all case for an int-to-enum decode implementation + fn invalid_variant_case(&self, enum_name: &str, result: &mut StreamBuilder) -> Result { + let crate_name = self.attributes.crate_name.as_str(); + + // we'll be generating: + // variant => Err( + // bincode::error::DecodeError::UnexpectedVariant { + // found: variant, + // type_name: + // allowed: ..., + // } + // ) + // + // Where allowed is either: + // - bincode::error::AllowedEnumVariants::Range { min: 0, max: } + // if we have no fixed value variants + // - bincode::error::AllowedEnumVariants::Allowed(&[, , ...]) + // if we have fixed value variants + result.ident_str("variant"); + result.puncts("=>"); + result.push_parsed("core::result::Result::Err")?; + result.group(Delimiter::Parenthesis, |err_inner| { + err_inner.push_parsed(format!( + "{}::error::DecodeError::UnexpectedVariant", + crate_name + ))?; + err_inner.group(Delimiter::Brace, |variant_inner| { + variant_inner.ident_str("found"); + variant_inner.punct(':'); + variant_inner.ident_str("variant"); + variant_inner.punct(','); + + variant_inner.ident_str("type_name"); + variant_inner.punct(':'); + variant_inner.lit_str(enum_name); + variant_inner.punct(','); + + variant_inner.ident_str("allowed"); + variant_inner.punct(':'); + + if self.variants.iter().any(|i| i.value.is_some()) { + // we have fixed values, implement AllowedEnumVariants::Allowed + variant_inner.push_parsed(format!( + "&{}::error::AllowedEnumVariants::Allowed", + crate_name + ))?; + variant_inner.group(Delimiter::Parenthesis, |allowed_inner| { + allowed_inner.punct('&'); + allowed_inner.group(Delimiter::Bracket, |allowed_slice| { + for (idx, (ident, _)) in self.iter_fields().enumerate() { + if idx != 0 { + allowed_slice.punct(','); + } + allowed_slice.extend(ident); + } + Ok(()) + })?; + Ok(()) + })?; + } else { + // no fixed values, implement a range + variant_inner.push_parsed(format!( + "&{0}::error::AllowedEnumVariants::Range {{ min: 0, max: {1} }}", + crate_name, + self.variants.len() - 1 + ))?; + } + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + } + + pub fn generate_decode(self, generator: &mut Generator) -> Result<()> { + let crate_name = self.attributes.crate_name.as_str(); + + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + // Remember to keep this mostly in sync with generate_borrow_decode + + let enum_name = generator.target_name().to_string(); + + let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name)); + + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .with_trait_generics([decode_context]) + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { + where_constraints.clear(); + where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints.push_constraint(g, format!("{}::Decode<__Context>", crate_name))?; + } + } + Ok(()) + })? + .generate_fn("decode") + .with_generic_deps("__D", [format!("{}::de::Decoder", crate_name, decode_context)]) + .with_arg("decoder", "&mut __D") + .with_return_type(format!("core::result::Result", crate_name)) + .body(|fn_builder| { + if self.variants.is_empty() { + fn_builder.push_parsed(format!( + "core::result::Result::Err({}::error::DecodeError::EmptyEnum {{ type_name: core::any::type_name::() }})", + crate_name + ))?; + } else { + fn_builder + .push_parsed(format!( + "let variant_index = >::decode(decoder)?;", + crate_name + ))?; + fn_builder.push_parsed("match variant_index")?; + fn_builder.group(Delimiter::Brace, |variant_case| { + for (mut variant_index, variant) in self.iter_fields() { + // idx => Ok(..) + if variant_index.len() > 1 { + variant_case.push_parsed("x if x == ")?; + variant_case.extend(variant_index); + } else { + variant_case.push(variant_index.remove(0)); + } + variant_case.puncts("=>"); + variant_case.push_parsed("core::result::Result::Ok")?; + variant_case.group(Delimiter::Parenthesis, |variant_case_body| { + // Self::Variant { } + // Self::Variant { 0: ..., 1: ... 2: ... }, + // Self::Variant { a: ..., b: ... c: ... }, + variant_case_body.ident_str("Self"); + variant_case_body.puncts("::"); + variant_case_body.ident(variant.name.clone()); + + variant_case_body.group(Delimiter::Brace, |variant_body| { + if let Some(fields) = variant.fields.as_ref() { + let is_tuple = matches!(fields, Fields::Tuple(_)); + for (idx, field) in fields.names().into_iter().enumerate() { + if is_tuple { + variant_body.lit_usize(idx); + } else { + variant_body.ident(field.unwrap_ident().clone()); + } + variant_body.punct(':'); + let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); + if attributes.with_serde { + variant_body + .push_parsed(format!( + "<{0}::serde::Compat<_> as {0}::Decode::<__D::Context>>::decode(decoder)?.0,", + crate_name + ))?; + } else { + variant_body + .push_parsed(format!( + "{}::Decode::<__D::Context>::decode(decoder)?,", + crate_name + ))?; + } + } + } + Ok(()) + })?; + Ok(()) + })?; + variant_case.punct(','); + } + + // invalid idx + self.invalid_variant_case(&enum_name, variant_case) + })?; + } + Ok(()) + })?; + self.generate_borrow_decode(generator)?; + Ok(()) + } + + pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> { + let crate_name = &self.attributes.crate_name; + + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + + // Remember to keep this mostly in sync with generate_decode + let enum_name = generator.target_name().to_string(); + + let mut impl_for = generator + .impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]) + .with_trait_generics([decode_context]); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { + where_constraints.clear(); + where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap(); + } + for lt in generics.iter_lifetimes() { + where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?; + } + } + Ok(()) + })? + .generate_fn("borrow_decode") + .with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Context = {}>", crate_name, decode_context)]) + .with_arg("decoder", "&mut __D") + .with_return_type(format!("core::result::Result", crate_name)) + .body(|fn_builder| { + if self.variants.is_empty() { + fn_builder.push_parsed(format!( + "core::result::Result::Err({}::error::DecodeError::EmptyEnum {{ type_name: core::any::type_name::() }})", + crate_name + ))?; + } else { + fn_builder + .push_parsed(format!("let variant_index = >::decode(decoder)?;", crate_name))?; + fn_builder.push_parsed("match variant_index")?; + fn_builder.group(Delimiter::Brace, |variant_case| { + for (mut variant_index, variant) in self.iter_fields() { + // idx => Ok(..) + if variant_index.len() > 1 { + variant_case.push_parsed("x if x == ")?; + variant_case.extend(variant_index); + } else { + variant_case.push(variant_index.remove(0)); + } + variant_case.puncts("=>"); + variant_case.push_parsed("core::result::Result::Ok")?; + variant_case.group(Delimiter::Parenthesis, |variant_case_body| { + // Self::Variant { } + // Self::Variant { 0: ..., 1: ... 2: ... }, + // Self::Variant { a: ..., b: ... c: ... }, + variant_case_body.ident_str("Self"); + variant_case_body.puncts("::"); + variant_case_body.ident(variant.name.clone()); + + variant_case_body.group(Delimiter::Brace, |variant_body| { + if let Some(fields) = variant.fields.as_ref() { + let is_tuple = matches!(fields, Fields::Tuple(_)); + for (idx, field) in fields.names().into_iter().enumerate() { + if is_tuple { + variant_body.lit_usize(idx); + } else { + variant_body.ident(field.unwrap_ident().clone()); + } + variant_body.punct(':'); + let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); + if attributes.with_serde { + variant_body + .push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<__D::Context>>::borrow_decode(decoder)?.0,", crate_name))?; + } else { + variant_body.push_parsed(format!("{}::BorrowDecode::<__D::Context>::borrow_decode(decoder)?,", crate_name))?; + } + } + } + Ok(()) + })?; + Ok(()) + })?; + variant_case.punct(','); + } + + // invalid idx + self.invalid_variant_case(&enum_name, variant_case) + })?; + } + Ok(()) + })?; + Ok(()) + } +} + +struct EnumVariantIterator<'a> { + variants: &'a [EnumVariant], + idx: usize, +} + +impl<'a> Iterator for EnumVariantIterator<'a> { + type Item = (Vec, &'a EnumVariant); + + fn next(&mut self) -> Option { + let idx = self.idx; + let variant = self.variants.get(self.idx)?; + self.idx += 1; + + let tokens = vec![TokenTree::Literal(Literal::u32_suffixed(idx as u32))]; + + Some((tokens, variant)) + } +} diff --git a/derive/src/derive_struct.rs b/derive/src/derive_struct.rs new file mode 100644 index 0000000..93a63a0 --- /dev/null +++ b/derive/src/derive_struct.rs @@ -0,0 +1,211 @@ +use crate::attribute::{ContainerAttributes, FieldAttributes}; +use virtue::prelude::*; + +pub(crate) struct DeriveStruct { + pub fields: Option, + pub attributes: ContainerAttributes, +} + +impl DeriveStruct { + pub fn generate_encode(self, generator: &mut Generator) -> Result<()> { + let crate_name = &self.attributes.crate_name; + generator + .impl_for(format!("{}::Encode", crate_name)) + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = + (self.attributes.encode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) + { + where_constraints.clear(); + where_constraints + .push_parsed_constraint(bounds) + .map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints + .push_constraint(g, format!("{}::Encode", crate_name)) + .unwrap(); + } + } + Ok(()) + })? + .generate_fn("encode") + .with_generic_deps("__E", [format!("{}::enc::Encoder", crate_name)]) + .with_self_arg(virtue::generate::FnSelfArg::RefSelf) + .with_arg("encoder", "&mut __E") + .with_return_type(format!( + "core::result::Result<(), {}::error::EncodeError>", + crate_name + )) + .body(|fn_body| { + if let Some(fields) = self.fields.as_ref() { + for field in fields.names() { + let attributes = field + .attributes() + .get_attribute::()? + .unwrap_or_default(); + if attributes.with_serde { + fn_body.push_parsed(format!( + "{0}::Encode::encode(&{0}::serde::Compat(&self.{1}), encoder)?;", + crate_name, field + ))?; + } else { + fn_body.push_parsed(format!( + "{}::Encode::encode(&self.{}, encoder)?;", + crate_name, field + ))?; + } + } + } + fn_body.push_parsed("core::result::Result::Ok(())")?; + Ok(()) + })?; + Ok(()) + } + + pub fn generate_decode(self, generator: &mut Generator) -> Result<()> { + // Remember to keep this mostly in sync with generate_borrow_decode + let crate_name = &self.attributes.crate_name; + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + + let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name)); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .with_trait_generics([decode_context]) + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { + where_constraints.clear(); + where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints.push_constraint(g, format!("{}::Decode<{}>", crate_name, decode_context)).unwrap(); + } + } + Ok(()) + })? + .generate_fn("decode") + .with_generic_deps("__D", [format!("{}::de::Decoder", crate_name, decode_context)]) + .with_arg("decoder", "&mut __D") + .with_return_type(format!("core::result::Result", crate_name)) + .body(|fn_body| { + // Ok(Self { + fn_body.push_parsed("core::result::Result::Ok")?; + fn_body.group(Delimiter::Parenthesis, |ok_group| { + ok_group.ident_str("Self"); + ok_group.group(Delimiter::Brace, |struct_body| { + // Fields + // { + // a: bincode::Decode::decode(decoder)?, + // b: bincode::Decode::decode(decoder)?, + // ... + // } + if let Some(fields) = self.fields.as_ref() { + for field in fields.names() { + let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); + if attributes.with_serde { + struct_body + .push_parsed(format!( + "{1}: (<{0}::serde::Compat<_> as {0}::Decode::<{2}>>::decode(decoder)?).0,", + crate_name, + field, + decode_context, + ))?; + } else { + struct_body + .push_parsed(format!( + "{1}: {0}::Decode::decode(decoder)?,", + crate_name, + field + ))?; + } + } + } + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + })?; + self.generate_borrow_decode(generator)?; + Ok(()) + } + + pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> { + // Remember to keep this mostly in sync with generate_decode + let crate_name = self.attributes.crate_name; + + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + + let mut impl_for = generator + .impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]) + .with_trait_generics([decode_context]); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { + where_constraints.clear(); + where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap(); + } + for lt in generics.iter_lifetimes() { + where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?; + } + } + Ok(()) + })? + .generate_fn("borrow_decode") + .with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Context = {}>", crate_name, decode_context)]) + .with_arg("decoder", "&mut __D") + .with_return_type(format!("core::result::Result", crate_name)) + .body(|fn_body| { + // Ok(Self { + fn_body.push_parsed("core::result::Result::Ok")?; + fn_body.group(Delimiter::Parenthesis, |ok_group| { + ok_group.ident_str("Self"); + ok_group.group(Delimiter::Brace, |struct_body| { + if let Some(fields) = self.fields.as_ref() { + for field in fields.names() { + let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); + if attributes.with_serde { + struct_body + .push_parsed(format!( + "{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<'_, {2}>>::borrow_decode(decoder)?).0,", + crate_name, + field, + decode_context, + ))?; + } else { + struct_body + .push_parsed(format!( + "{1}: {0}::BorrowDecode::<'_, {2}>::borrow_decode(decoder)?,", + crate_name, + field, + decode_context, + ))?; + } + } + } + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + } +} diff --git a/derive/src/lib.rs b/derive/src/lib.rs new file mode 100644 index 0000000..166bb2f --- /dev/null +++ b/derive/src/lib.rs @@ -0,0 +1,105 @@ +mod attribute; +mod derive_enum; +mod derive_struct; + +use attribute::ContainerAttributes; +use virtue::prelude::*; + +#[proc_macro_derive(Encode, attributes(bincode))] +pub fn derive_encode(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_encode_inner(input).unwrap_or_else(|e| e.into_token_stream()) +} + +fn derive_encode_inner(input: TokenStream) -> Result { + let parse = Parse::new(input)?; + let (mut generator, attributes, body) = parse.into_generator(); + let attributes = attributes + .get_attribute::()? + .unwrap_or_default(); + + match body { + Body::Struct(body) => { + derive_struct::DeriveStruct { + fields: body.fields, + attributes, + } + .generate_encode(&mut generator)?; + } + Body::Enum(body) => { + derive_enum::DeriveEnum { + variants: body.variants, + attributes, + } + .generate_encode(&mut generator)?; + } + } + + generator.export_to_file("bincode", "Encode"); + generator.finish() +} + +#[proc_macro_derive(Decode, attributes(bincode))] +pub fn derive_decode(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_decode_inner(input).unwrap_or_else(|e| e.into_token_stream()) +} + +fn derive_decode_inner(input: TokenStream) -> Result { + let parse = Parse::new(input)?; + let (mut generator, attributes, body) = parse.into_generator(); + let attributes = attributes + .get_attribute::()? + .unwrap_or_default(); + + match body { + Body::Struct(body) => { + derive_struct::DeriveStruct { + fields: body.fields, + attributes, + } + .generate_decode(&mut generator)?; + } + Body::Enum(body) => { + derive_enum::DeriveEnum { + variants: body.variants, + attributes, + } + .generate_decode(&mut generator)?; + } + } + + generator.export_to_file("bincode", "Decode"); + generator.finish() +} + +#[proc_macro_derive(BorrowDecode, attributes(bincode))] +pub fn derive_borrow_decode(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_borrow_decode_inner(input).unwrap_or_else(|e| e.into_token_stream()) +} + +fn derive_borrow_decode_inner(input: TokenStream) -> Result { + let parse = Parse::new(input)?; + let (mut generator, attributes, body) = parse.into_generator(); + let attributes = attributes + .get_attribute::()? + .unwrap_or_default(); + + match body { + Body::Struct(body) => { + derive_struct::DeriveStruct { + fields: body.fields, + attributes, + } + .generate_borrow_decode(&mut generator)?; + } + Body::Enum(body) => { + derive_enum::DeriveEnum { + variants: body.variants, + attributes, + } + .generate_borrow_decode(&mut generator)?; + } + } + + generator.export_to_file("bincode", "BorrowDecode"); + generator.finish() +} diff --git a/src/lib.rs b/src/lib.rs index 1555c5e..239eb77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,8 +71,8 @@ //! [`net::TcpStream`]: std::net::TcpStream //! -#![doc(html_root_url = "https://docs.rs/bincode/2.0.1")] -#![crate_name = "bincode"] +#![doc(html_root_url = "https://docs.rs/cu-bincode/2.0.1")] +#![crate_name = "cu_bincode"] #![crate_type = "rlib"] #[cfg(feature = "alloc")] From 9ec00029bc911d9c4b255d9d6ce3b19ddb89a64f Mon Sep 17 00:00:00 2001 From: Guillaume Binet Date: Mon, 22 Dec 2025 11:27:50 -0600 Subject: [PATCH 2/6] tests passes again --- Cargo.toml | 2 +- README.md | 1 + benches/inline.rs | 1 + benches/string.rs | 1 + benches/varint.rs | 1 + docs/spec.md | 7 +++++++ src/config.rs | 3 +++ src/de/decoder.rs | 1 + src/de/mod.rs | 5 +++++ src/enc/encoder.rs | 1 + src/enc/mod.rs | 3 +++ src/enc/write.rs | 1 + src/features/derive.rs | 2 ++ src/lib.rs | 3 ++- tests/alloc.rs | 1 + tests/basic_types.rs | 1 + tests/context.rs | 1 + tests/derive.rs | 1 + tests/derive_rename.rs | 2 +- tests/error_size.rs | 2 ++ tests/issues.rs | 2 ++ tests/issues/issue_427.rs | 2 ++ tests/issues/issue_431.rs | 1 + tests/issues/issue_459.rs | 1 + tests/issues/issue_467.rs | 1 + tests/issues/issue_474.rs | 1 + tests/issues/issue_498.rs | 1 + tests/issues/issue_500.rs | 2 ++ tests/issues/issue_523.rs | 1 + tests/issues/issue_537.rs | 1 + tests/issues/issue_547.rs | 1 + tests/issues/issue_570.rs | 2 ++ tests/issues/issue_592.rs | 1 + tests/issues/issue_614.rs | 1 + tests/serde.rs | 1 + tests/std.rs | 1 + tests/utils.rs | 1 + 37 files changed, 58 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0e622a2..92624e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ publish = true repository = "https://github.com/copper-robotics/cu-bincode" documentation = "https://docs.rs/cu-bincode" -readme = "./readme.md" +readme = "./README.md" categories = ["encoding", "network-programming"] keywords = ["binary", "encode", "decode", "serialize", "deserialize"] diff --git a/README.md b/README.md index d04ba09..3c2a3a3 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ library. ## Example ```rust +# extern crate cu_bincode as bincode; use bincode::{config, Decode, Encode}; #[derive(Encode, Decode, PartialEq, Debug)] diff --git a/benches/inline.rs b/benches/inline.rs index 56f5ade..2868895 100644 --- a/benches/inline.rs +++ b/benches/inline.rs @@ -1,3 +1,4 @@ +extern crate cu_bincode as bincode; use bincode::config; use criterion::{black_box, criterion_group, criterion_main, Criterion}; diff --git a/benches/string.rs b/benches/string.rs index f565b4a..a6932b9 100644 --- a/benches/string.rs +++ b/benches/string.rs @@ -1,5 +1,6 @@ // https://github.com/bincode-org/bincode/issues/618 +extern crate cu_bincode as bincode; use bincode::{Decode, Encode}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use serde::{Deserialize, Serialize}; diff --git a/benches/varint.rs b/benches/varint.rs index 248ab0a..565f6de 100644 --- a/benches/varint.rs +++ b/benches/varint.rs @@ -1,3 +1,4 @@ +extern crate cu_bincode as bincode; use bincode::config; use criterion::{criterion_group, criterion_main, Criterion}; use rand::distributions::Distribution; diff --git a/docs/spec.md b/docs/spec.md index 5e29e72..c564e58 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -68,6 +68,7 @@ Endianness can be configured with the following methods, allowing for big-endian All tuples have no additional bytes, and are encoded in their specified order, e.g. ```rust +# extern crate cu_bincode as bincode; let tuple = (u32::min_value(), i32::max_value()); // 8 bytes let encoded = bincode::encode_to_vec(tuple, bincode::config::legacy()).unwrap(); assert_eq!(encoded.as_slice(), &[ @@ -109,6 +110,7 @@ Enums are encoded with their variant first, followed by optionally the variant f Both named and unnamed fields are serialized with their values only, and therefore encode to the same value. ```rust +# extern crate cu_bincode as bincode; #[derive(bincode::Encode)] pub enum SomeEnum { A, @@ -143,6 +145,7 @@ assert_eq!(encoded.as_slice(), &[ `Option` is always serialized using a single byte for the discriminant, even in `Fixint` encoding (which normally uses a `u32` for discriminant). ```rust +# extern crate cu_bincode as bincode; let data: Option = Some(123); let encoded = bincode::encode_to_vec(data, bincode::config::legacy()).unwrap(); assert_eq!(encoded.as_slice(), &[ @@ -180,6 +183,7 @@ Collections are encoded with their length value first, followed by each entry of - Each item serialized sequentially ```rust +# extern crate cu_bincode as bincode; let list = vec![0u8, 1u8, 2u8]; let encoded = bincode::encode_to_vec(list, bincode::config::legacy()).unwrap(); assert_eq!(encoded.as_slice(), &[ @@ -227,6 +231,7 @@ assert_eq!(encoded.as_slice(), &[ - If an invalid UTF-8 sequence is encountered during decoding, an [`DecodeError::Utf8`](https://docs.rs/bincode/2/bincode/error/enum.DecodeError.html#variant.Utf8) error is raised ```rust +# extern crate cu_bincode as bincode; let str = "Hello 🌍"; // Mixed ASCII and Unicode let encoded = bincode::encode_to_vec(str, bincode::config::legacy()).unwrap(); @@ -248,6 +253,7 @@ Array length is never encoded. Note that `&[T]` is encoded as a [Collection](#collections). ```rust +# extern crate cu_bincode as bincode; let arr: [u8; 5] = [10, 20, 30, 40, 50]; let encoded = bincode::encode_to_vec(arr, bincode::config::legacy()).unwrap(); assert_eq!(encoded.as_slice(), &[ @@ -259,6 +265,7 @@ assert_eq!(encoded.as_slice(), &[ This applies to any type `T` that implements `Encode`/`Decode` ```rust +# extern crate cu_bincode as bincode; #[derive(bincode::Encode)] struct Foo { first: u8, diff --git a/src/config.rs b/src/config.rs index 3642677..2ab5045 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,6 +5,7 @@ //! To use a config, first create a type of [Configuration]. This type will implement trait [Config] for use with bincode. //! //! ``` +//! # extern crate cu_bincode as bincode; //! let config = bincode::config::standard() //! // pick one of: //! .with_big_endian() @@ -107,6 +108,7 @@ impl Configuration { /// The zigzag algorithm is defined as follows: /// /// ```rust +/// # extern crate cu_bincode as bincode; /// # type Signed = i32; /// # type Unsigned = u32; /// fn zigzag(v: Signed) -> Unsigned { @@ -125,6 +127,7 @@ impl Configuration { /// And works such that: /// /// ```rust +/// # extern crate cu_bincode as bincode; /// # let zigzag = |n: i64| -> u64 { /// # match n { /// # 0 => 0, diff --git a/src/de/decoder.rs b/src/de/decoder.rs index 8945130..00b7bb0 100644 --- a/src/de/decoder.rs +++ b/src/de/decoder.rs @@ -13,6 +13,7 @@ use crate::{config::Config, error::DecodeError, utils::Sealed}; /// is used to read integers out of the reader. /// /// ``` +/// # extern crate cu_bincode as bincode; /// # let slice: &[u8] = &[0, 0, 0, 0]; /// # let some_reader = bincode::de::read::SliceReader::new(slice); /// use bincode::de::{DecoderImpl, Decode}; diff --git a/src/de/mod.rs b/src/de/mod.rs index 16abcb4..420b537 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -36,6 +36,7 @@ pub use self::decoder::DecoderImpl; /// For this struct: /// /// ``` +/// # extern crate cu_bincode as bincode; /// struct Entity { /// pub x: f32, /// pub y: f32, @@ -45,6 +46,7 @@ pub use self::decoder::DecoderImpl; /// It will look something like: /// /// ``` +/// # extern crate cu_bincode as bincode; /// # struct Entity { /// # pub x: f32, /// # pub y: f32, @@ -75,6 +77,7 @@ pub use self::decoder::DecoderImpl; /// /// To get specific integer types, you can use: /// ``` +/// # extern crate cu_bincode as bincode; /// # struct Foo; /// # impl bincode::Decode for Foo { /// # fn decode>( @@ -90,6 +93,7 @@ pub use self::decoder::DecoderImpl; /// /// You can use `Context` to require contexts for decoding a type: /// ``` +/// # extern crate cu_bincode as bincode; /// # /// # use bumpalo::Bump; /// use bincode::de::Decoder; /// use bincode::error::DecodeError; @@ -202,6 +206,7 @@ pub trait Decoder: Sealed { /// a nested container (e.g. `Vec>`), it does not know how much memory is already claimed, and could easily /// allocate much more than the user intends. /// ``` +/// # extern crate cu_bincode as bincode; /// # use bincode::de::{Decode, Decoder}; /// # use bincode::error::DecodeError; /// # struct Container(Vec); diff --git a/src/enc/encoder.rs b/src/enc/encoder.rs index 7f0bf22..40faf4a 100644 --- a/src/enc/encoder.rs +++ b/src/enc/encoder.rs @@ -10,6 +10,7 @@ use crate::{config::Config, utils::Sealed}; /// is used to write integers to the writer. /// /// ``` +/// # extern crate cu_bincode as bincode; /// # use bincode::enc::{write::SliceWriter, EncoderImpl, Encode}; /// let slice: &mut [u8] = &mut [0, 0, 0, 0]; /// let config = bincode::config::legacy().with_big_endian(); diff --git a/src/enc/mod.rs b/src/enc/mod.rs index c5c37f8..8257870 100644 --- a/src/enc/mod.rs +++ b/src/enc/mod.rs @@ -22,6 +22,7 @@ pub use self::encoder::EncoderImpl; /// For this struct: /// /// ``` +/// # extern crate cu_bincode as bincode; /// struct Entity { /// pub x: f32, /// pub y: f32, @@ -30,6 +31,7 @@ pub use self::encoder::EncoderImpl; /// It will look something like: /// /// ``` +/// # extern crate cu_bincode as bincode; /// # struct Entity { /// # pub x: f32, /// # pub y: f32, @@ -45,6 +47,7 @@ pub use self::encoder::EncoderImpl; /// } /// } /// ``` +/// # extern crate cu_bincode as bincode; /// /// From here you can add/remove fields, or add custom logic. pub trait Encode { diff --git a/src/enc/write.rs b/src/enc/write.rs index 97a4784..a57d1a2 100644 --- a/src/enc/write.rs +++ b/src/enc/write.rs @@ -22,6 +22,7 @@ impl Writer for &mut T { /// A helper struct that implements `Writer` for a `&[u8]` slice. /// /// ``` +/// # extern crate cu_bincode as bincode; /// use bincode::enc::write::{Writer, SliceWriter}; /// /// let destination = &mut [0u8; 100]; diff --git a/src/features/derive.rs b/src/features/derive.rs index 1d07ba1..23cc4e5 100644 --- a/src/features/derive.rs +++ b/src/features/derive.rs @@ -1,2 +1,4 @@ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +use cu_bincode_derive as bincode_derive; +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use bincode_derive::{BorrowDecode, Decode, Encode}; diff --git a/src/lib.rs b/src/lib.rs index 239eb77..bae1117 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,7 @@ //! # Example //! //! ```rust +//! # extern crate cu_bincode as bincode; //! let mut slice = [0u8; 100]; //! //! // You can encode any type that implements `Encode`. @@ -233,5 +234,5 @@ pub mod migration_guide { // Test the examples in readme.md #[cfg(all(feature = "alloc", feature = "derive", doctest))] mod readme { - #![doc = include_str!("../readme.md")] + #![doc = include_str!("../README.md")] } diff --git a/tests/alloc.rs b/tests/alloc.rs index f5bc75e..25c536a 100644 --- a/tests/alloc.rs +++ b/tests/alloc.rs @@ -5,6 +5,7 @@ extern crate alloc; mod utils; +extern crate cu_bincode as bincode; use alloc::borrow::Cow; use alloc::collections::*; #[cfg(not(feature = "serde"))] diff --git a/tests/basic_types.rs b/tests/basic_types.rs index 0aae093..21676f5 100644 --- a/tests/basic_types.rs +++ b/tests/basic_types.rs @@ -1,5 +1,6 @@ mod utils; +extern crate cu_bincode as bincode; use bincode::error::DecodeError; use core::cell::{Cell, RefCell}; use core::cmp::Reverse; diff --git a/tests/context.rs b/tests/context.rs index 5c85147..58f6664 100644 --- a/tests/context.rs +++ b/tests/context.rs @@ -1,5 +1,6 @@ #![cfg(all(feature = "alloc", feature = "derive"))] +extern crate cu_bincode as bincode; use bincode::{ config, de::BorrowDecoder, decode_from_slice, decode_from_slice_with_context, encode_to_vec, error::DecodeError, BorrowDecode, Decode, Encode, diff --git a/tests/derive.rs b/tests/derive.rs index c059c96..b4dd034 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -1,5 +1,6 @@ #![cfg(feature = "derive")] +extern crate cu_bincode as bincode; use bincode::error::DecodeError; #[derive(bincode::Encode, PartialEq, Debug)] diff --git a/tests/derive_rename.rs b/tests/derive_rename.rs index fe2d0cf..d3ea658 100644 --- a/tests/derive_rename.rs +++ b/tests/derive_rename.rs @@ -1,6 +1,6 @@ #![cfg(feature = "derive")] -extern crate bincode as bincode_new; +extern crate cu_bincode as bincode_new; // Make sure that the `bincode` crate exists, just symlink it to `core. extern crate core as bincode; diff --git a/tests/error_size.rs b/tests/error_size.rs index dfc03ea..342ccf9 100644 --- a/tests/error_size.rs +++ b/tests/error_size.rs @@ -1,5 +1,7 @@ #![cfg(target_pointer_width = "64")] +extern crate cu_bincode as bincode; + #[test] fn decode_error_size() { assert_eq!(std::mem::size_of::(), 32); diff --git a/tests/issues.rs b/tests/issues.rs index cd027b1..332316e 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -1,5 +1,7 @@ #![no_std] +extern crate cu_bincode as bincode; + #[path = "issues/issue_431.rs"] mod issue_431; diff --git a/tests/issues/issue_427.rs b/tests/issues/issue_427.rs index 09ea981..7e3d235 100644 --- a/tests/issues/issue_427.rs +++ b/tests/issues/issue_427.rs @@ -1,5 +1,7 @@ #![cfg(feature = "derive")] +extern crate cu_bincode as bincode; + /// HID-IO Packet Buffer Struct /// /// # Remarks diff --git a/tests/issues/issue_431.rs b/tests/issues/issue_431.rs index 03b35d2..0f086f4 100644 --- a/tests/issues/issue_431.rs +++ b/tests/issues/issue_431.rs @@ -2,6 +2,7 @@ extern crate std; +extern crate cu_bincode as bincode; use bincode::{Decode, Encode}; use std::borrow::Cow; use std::string::String; diff --git a/tests/issues/issue_459.rs b/tests/issues/issue_459.rs index 831041f..ce705bc 100644 --- a/tests/issues/issue_459.rs +++ b/tests/issues/issue_459.rs @@ -2,6 +2,7 @@ extern crate std; +extern crate cu_bincode as bincode; use std::collections::BTreeMap; #[derive(bincode::Encode)] diff --git a/tests/issues/issue_467.rs b/tests/issues/issue_467.rs index 0ca0c1f..adb7356 100644 --- a/tests/issues/issue_467.rs +++ b/tests/issues/issue_467.rs @@ -2,6 +2,7 @@ extern crate std; +extern crate cu_bincode as bincode; use std::collections::BTreeMap; #[derive(bincode::Decode, bincode::Encode)] diff --git a/tests/issues/issue_474.rs b/tests/issues/issue_474.rs index 0526ebb..33a863a 100644 --- a/tests/issues/issue_474.rs +++ b/tests/issues/issue_474.rs @@ -2,6 +2,7 @@ extern crate std; +extern crate cu_bincode as bincode; use chrono::{DateTime, Utc}; use serde::de::DeserializeOwned; use std::collections::HashMap; diff --git a/tests/issues/issue_498.rs b/tests/issues/issue_498.rs index f301c4b..28234a7 100644 --- a/tests/issues/issue_498.rs +++ b/tests/issues/issue_498.rs @@ -2,6 +2,7 @@ extern crate std; +extern crate cu_bincode as bincode; use std::ffi::CString; #[test] diff --git a/tests/issues/issue_500.rs b/tests/issues/issue_500.rs index 6c013ba..624493a 100644 --- a/tests/issues/issue_500.rs +++ b/tests/issues/issue_500.rs @@ -2,6 +2,8 @@ extern crate std; +extern crate cu_bincode as bincode; + type NodeId = u64; use std::collections::BTreeSet; diff --git a/tests/issues/issue_523.rs b/tests/issues/issue_523.rs index 2cda3f9..a551e3b 100644 --- a/tests/issues/issue_523.rs +++ b/tests/issues/issue_523.rs @@ -2,6 +2,7 @@ extern crate std; +extern crate cu_bincode as bincode; use bincode::{Decode, Encode}; use std::borrow::Cow; diff --git a/tests/issues/issue_537.rs b/tests/issues/issue_537.rs index 4dd8bbf..61b99c1 100644 --- a/tests/issues/issue_537.rs +++ b/tests/issues/issue_537.rs @@ -1,5 +1,6 @@ #![cfg(all(feature = "derive", feature = "std"))] +extern crate cu_bincode as bincode; use bincode::{Decode, Encode}; #[derive(Encode, Decode)] diff --git a/tests/issues/issue_547.rs b/tests/issues/issue_547.rs index 7c75021..27e0ad9 100644 --- a/tests/issues/issue_547.rs +++ b/tests/issues/issue_547.rs @@ -1,5 +1,6 @@ #![cfg(all(feature = "serde", feature = "std"))] +extern crate cu_bincode as bincode; use glam::vec3; use serde::{Deserialize, Serialize}; diff --git a/tests/issues/issue_570.rs b/tests/issues/issue_570.rs index def9043..2b31d2e 100644 --- a/tests/issues/issue_570.rs +++ b/tests/issues/issue_570.rs @@ -1,5 +1,7 @@ #![cfg(feature = "derive")] +extern crate cu_bincode as bincode; + #[derive(bincode::Encode, bincode::Decode)] pub struct Eg { data: (D, E), diff --git a/tests/issues/issue_592.rs b/tests/issues/issue_592.rs index 995e28e..984e125 100644 --- a/tests/issues/issue_592.rs +++ b/tests/issues/issue_592.rs @@ -1,5 +1,6 @@ #![cfg(all(feature = "derive", feature = "std"))] +extern crate cu_bincode as bincode; use bincode::{Decode, Encode}; #[derive(Encode, Decode)] diff --git a/tests/issues/issue_614.rs b/tests/issues/issue_614.rs index c36b17e..f032b1c 100644 --- a/tests/issues/issue_614.rs +++ b/tests/issues/issue_614.rs @@ -1,5 +1,6 @@ #![cfg(feature = "derive")] +extern crate cu_bincode as bincode; use bincode::{Decode, Encode}; #[derive(Encode, Decode, Clone)] diff --git a/tests/serde.rs b/tests/serde.rs index 7a5ed83..ba5c759 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -2,6 +2,7 @@ extern crate alloc; +extern crate cu_bincode as bincode; use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, bincode::Encode, bincode::Decode)] diff --git a/tests/std.rs b/tests/std.rs index 0c33c6f..eb9b805 100644 --- a/tests/std.rs +++ b/tests/std.rs @@ -3,6 +3,7 @@ mod utils; +extern crate cu_bincode as bincode; use bincode::error::DecodeError; use std::{ ffi::CString, diff --git a/tests/utils.rs b/tests/utils.rs index 22e3533..56bea71 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -1,3 +1,4 @@ +extern crate cu_bincode as bincode; use core::fmt::Debug; fn the_same_with_config(element: &V, config: C, cmp: CMP) From 806b86c56644a9c9f8d60e44f576725597016aad Mon Sep 17 00:00:00 2001 From: Guillaume Binet Date: Mon, 22 Dec 2025 11:36:53 -0600 Subject: [PATCH 3/6] ok all pass cleanly now --- benches/inline.rs | 3 ++- benches/string.rs | 3 ++- benches/varint.rs | 34 +++++++++++++++---------------- derive/src/derive_enum.rs | 2 +- src/de/mod.rs | 2 +- src/features/serde/de_borrowed.rs | 24 +++++++++------------- src/features/serde/de_owned.rs | 24 +++++++++------------- src/features/serde/mod.rs | 1 + src/features/serde/ser.rs | 12 ++++------- tests/derive.rs | 1 + tests/issues.rs | 1 + 11 files changed, 50 insertions(+), 57 deletions(-) diff --git a/benches/inline.rs b/benches/inline.rs index 2868895..8071de3 100644 --- a/benches/inline.rs +++ b/benches/inline.rs @@ -1,6 +1,7 @@ extern crate cu_bincode as bincode; use bincode::config; -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{criterion_group, criterion_main, Criterion}; +use std::hint::black_box; fn inline_decoder_claim_bytes_read(c: &mut Criterion) { let config = config::standard().with_limit::<100000>(); diff --git a/benches/string.rs b/benches/string.rs index a6932b9..fc64a28 100644 --- a/benches/string.rs +++ b/benches/string.rs @@ -2,8 +2,9 @@ extern crate cu_bincode as bincode; use bincode::{Decode, Encode}; -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{criterion_group, criterion_main, Criterion}; use serde::{Deserialize, Serialize}; +use std::hint::black_box; #[derive(Serialize, Deserialize, Default, Encode, Decode)] pub struct MyStruct { diff --git a/benches/varint.rs b/benches/varint.rs index 565f6de..e35c216 100644 --- a/benches/varint.rs +++ b/benches/varint.rs @@ -1,11 +1,11 @@ extern crate cu_bincode as bincode; use bincode::config; use criterion::{criterion_group, criterion_main, Criterion}; -use rand::distributions::Distribution; +use rand::distr::{Distribution, Uniform}; fn slice_varint_u8(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let dist = rand::distributions::Uniform::from(0..u8::MAX); + let mut rng = rand::rng(); + let dist = Uniform::new(0, u8::MAX).expect("valid range"); let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng))) .take(10_000) .collect(); @@ -20,8 +20,8 @@ fn slice_varint_u8(c: &mut Criterion) { } fn slice_varint_u16(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let dist = rand::distributions::Uniform::from(0..u16::MAX); + let mut rng = rand::rng(); + let dist = Uniform::new(0, u16::MAX).expect("valid range"); let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng))) .take(10_000) .collect(); @@ -36,8 +36,8 @@ fn slice_varint_u16(c: &mut Criterion) { } fn slice_varint_u32(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let dist = rand::distributions::Uniform::from(0..u32::MAX); + let mut rng = rand::rng(); + let dist = Uniform::new(0, u32::MAX).expect("valid range"); let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng))) .take(10_000) .collect(); @@ -52,8 +52,8 @@ fn slice_varint_u32(c: &mut Criterion) { } fn slice_varint_u64(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let dist = rand::distributions::Uniform::from(0..u64::MAX); + let mut rng = rand::rng(); + let dist = Uniform::new(0, u64::MAX).expect("valid range"); let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng))) .take(10_000) .collect(); @@ -68,8 +68,8 @@ fn slice_varint_u64(c: &mut Criterion) { } fn bufreader_varint_u8(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let dist = rand::distributions::Uniform::from(0..u8::MAX); + let mut rng = rand::rng(); + let dist = Uniform::new(0, u8::MAX).expect("valid range"); let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng))) .take(10_000) .collect(); @@ -86,8 +86,8 @@ fn bufreader_varint_u8(c: &mut Criterion) { } fn bufreader_varint_u16(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let dist = rand::distributions::Uniform::from(0..u16::MAX); + let mut rng = rand::rng(); + let dist = Uniform::new(0, u16::MAX).expect("valid range"); let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng))) .take(10_000) .collect(); @@ -104,8 +104,8 @@ fn bufreader_varint_u16(c: &mut Criterion) { } fn bufreader_varint_u32(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let dist = rand::distributions::Uniform::from(0..u32::MAX); + let mut rng = rand::rng(); + let dist = Uniform::new(0, u32::MAX).expect("valid range"); let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng))) .take(10_000) .collect(); @@ -122,8 +122,8 @@ fn bufreader_varint_u32(c: &mut Criterion) { } fn bufreader_varint_u64(c: &mut Criterion) { - let mut rng = rand::thread_rng(); - let dist = rand::distributions::Uniform::from(0..u64::MAX); + let mut rng = rand::rng(); + let dist = Uniform::new(0, u64::MAX).expect("valid range"); let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng))) .take(10_000) .collect(); diff --git a/derive/src/derive_enum.rs b/derive/src/derive_enum.rs index 2ba17c5..9b3b318 100644 --- a/derive/src/derive_enum.rs +++ b/derive/src/derive_enum.rs @@ -9,7 +9,7 @@ pub(crate) struct DeriveEnum { } impl DeriveEnum { - fn iter_fields(&self) -> EnumVariantIterator { + fn iter_fields(&self) -> EnumVariantIterator<'_> { EnumVariantIterator { idx: 0, variants: &self.variants, diff --git a/src/de/mod.rs b/src/de/mod.rs index 420b537..246c796 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -164,7 +164,7 @@ pub trait Decoder: Sealed { fn context(&mut self) -> &mut Self::Context; /// Wraps decoder with a context - fn with_context(&mut self, context: C) -> WithContext { + fn with_context(&mut self, context: C) -> WithContext<'_, Self, C> { WithContext { decoder: self, context, diff --git a/src/features/serde/de_borrowed.rs b/src/features/serde/de_borrowed.rs index d0cbefc..af1bb6d 100644 --- a/src/features/serde/de_borrowed.rs +++ b/src/features/serde/de_borrowed.rs @@ -129,13 +129,11 @@ impl<'de, DE: BorrowDecoder<'de>> Deserializer<'de> for SerdeDecoder<'_, 'de, DE visitor.visit_i64(Decode::decode(&mut self.de)?) } - serde::serde_if_integer128! { - fn deserialize_i128(mut self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_i128(Decode::decode(&mut self.de)?) - } + fn deserialize_i128(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i128(Decode::decode(&mut self.de)?) } fn deserialize_u8(mut self, visitor: V) -> Result @@ -166,13 +164,11 @@ impl<'de, DE: BorrowDecoder<'de>> Deserializer<'de> for SerdeDecoder<'_, 'de, DE visitor.visit_u64(Decode::decode(&mut self.de)?) } - serde::serde_if_integer128! { - fn deserialize_u128(mut self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_u128(Decode::decode(&mut self.de)?) - } + fn deserialize_u128(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u128(Decode::decode(&mut self.de)?) } fn deserialize_f32(mut self, visitor: V) -> Result diff --git a/src/features/serde/de_owned.rs b/src/features/serde/de_owned.rs index 9c6e7ba..e5c3476 100644 --- a/src/features/serde/de_owned.rs +++ b/src/features/serde/de_owned.rs @@ -144,13 +144,11 @@ impl<'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'_, DE> { visitor.visit_i64(Decode::decode(&mut self.de)?) } - serde::serde_if_integer128! { - fn deserialize_i128(mut self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_i128(Decode::decode(&mut self.de)?) - } + fn deserialize_i128(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i128(Decode::decode(&mut self.de)?) } fn deserialize_u8(mut self, visitor: V) -> Result @@ -181,13 +179,11 @@ impl<'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'_, DE> { visitor.visit_u64(Decode::decode(&mut self.de)?) } - serde::serde_if_integer128! { - fn deserialize_u128(mut self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_u128(Decode::decode(&mut self.de)?) - } + fn deserialize_u128(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u128(Decode::decode(&mut self.de)?) } fn deserialize_f32(mut self, visitor: V) -> Result diff --git a/src/features/serde/mod.rs b/src/features/serde/mod.rs index 5874cca..bea2f95 100644 --- a/src/features/serde/mod.rs +++ b/src/features/serde/mod.rs @@ -13,6 +13,7 @@ //! For interop with bincode's `derive` feature, you can use the `#[bincode(with_serde)]` attribute on each field that implements serde's traits. //! //! ``` +//! # extern crate cu_bincode as bincode; //! # #[cfg(feature = "derive")] //! # mod foo { //! # use bincode::{Decode, Encode}; diff --git a/src/features/serde/ser.rs b/src/features/serde/ser.rs index 5dbdde3..c9cbe0b 100644 --- a/src/features/serde/ser.rs +++ b/src/features/serde/ser.rs @@ -115,10 +115,8 @@ where v.encode(self.enc) } - serde::serde_if_integer128! { - fn serialize_i128(self, v: i128) -> Result { - v.encode(self.enc) - } + fn serialize_i128(self, v: i128) -> Result { + v.encode(self.enc) } fn serialize_u8(self, v: u8) -> Result { @@ -137,10 +135,8 @@ where v.encode(self.enc) } - serde::serde_if_integer128! { - fn serialize_u128(self, v: u128) -> Result { - v.encode(self.enc) - } + fn serialize_u128(self, v: u128) -> Result { + v.encode(self.enc) } fn serialize_f32(self, v: f32) -> Result { diff --git a/tests/derive.rs b/tests/derive.rs index b4dd034..d7da179 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -1,4 +1,5 @@ #![cfg(feature = "derive")] +#![allow(dead_code)] extern crate cu_bincode as bincode; use bincode::error::DecodeError; diff --git a/tests/issues.rs b/tests/issues.rs index 332316e..40d3ebc 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -1,4 +1,5 @@ #![no_std] +#![allow(dead_code)] extern crate cu_bincode as bincode; From b991938a7f7951b2089848e825e07f7f0236866c Mon Sep 17 00:00:00 2001 From: Guillaume Binet Date: Mon, 22 Dec 2025 11:37:22 -0600 Subject: [PATCH 4/6] don't lock for now --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 54466f5..79034fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target +/Cargo.lock From be38029a4936802f33e4bdfaf7420aeaf7668e6d Mon Sep 17 00:00:00 2001 From: Guillaume Binet Date: Mon, 22 Dec 2025 11:39:42 -0600 Subject: [PATCH 5/6] add clippy to CI --- .github/workflows/rust.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9fd45e0..436dcb9 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -16,7 +16,11 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install clippy + run: rustup component add clippy - name: Build run: cargo build --verbose - name: Run tests run: cargo test --verbose + - name: Run clippy + run: cargo clippy --all-targets --all-features -- -D warnings From 973351c65707124e8ea25a7fbb7ad8f95395d43b Mon Sep 17 00:00:00 2001 From: Guillaume Binet Date: Mon, 22 Dec 2025 11:44:10 -0600 Subject: [PATCH 6/6] updates to READMEs --- README.md | 14 ++++++++------ derive/README.md | 8 +++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3c2a3a3..15464cb 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ -# Bincode +# cu-bincode -[![CI](https://github.com/bincode-org/bincode/workflows/CI/badge.svg)](https://github.com/bincode-org/bincode/actions) -[![](https://img.shields.io/crates/v/bincode.svg)](https://crates.io/crates/bincode) +[![CI](https://github.com/copper-project/cu-bincode/workflows/CI/badge.svg)](https://github.com/copper-project/cu-bincode/actions) +[![](https://img.shields.io/crates/v/cu-bincode.svg)](https://crates.io/crates/cu-bincode) [![](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) -[![Matrix](https://img.shields.io/matrix/bincode:matrix.org?label=Matrix%20Chat)](https://matrix.to/#/#bincode:matrix.org) +[![](https://img.shields.io/badge/discord-join-5865F2?logo=discord&logoColor=white)](https://discord.com/invite/VkCG7Sb9Kw) + +This is a hard fork of bincode 2.0.1 from crates.io (see first verbatim commit). Do not contact the original authors as per their wishes. A compact encoder / decoder pair that uses a binary zero-fluff encoding scheme. The size of the encoded object will be the same or smaller than the size that @@ -18,7 +20,7 @@ perfectly with other stream-based APIs such as Rust files, network streams, and the [flate2-rs](https://github.com/rust-lang/flate2-rs) compression library. -## [API Documentation](https://docs.rs/bincode/) +## [API Documentation](https://docs.rs/cu-bincode/) ## Bincode in the Wild @@ -63,7 +65,7 @@ fn main() { ## Specification -Bincode's format is specified in [docs/spec.md](https://github.com/bincode-org/bincode/blob/trunk/docs/spec.md). +Bincode's format is specified in [docs/spec.md](https://github.com/copper-project/cu-bincode/blob/main/docs/spec.md). ## FAQ diff --git a/derive/README.md b/derive/README.md index 0e652ce..ca3694d 100644 --- a/derive/README.md +++ b/derive/README.md @@ -1,6 +1,8 @@ -# Bincode-derive - -The derive crate for bincode. Implements `bincode::Encode` and `bincode::Decode`. +# cu-bincode-derive + +This is a hard fork of bincode 2.0.1 from crates.io (see first verbatim commit). Do not contact the original authors as per their wishes. + +The derive crate for cu-bincode. Implements `bincode::Encode` and `bincode::Decode`. This crate is roughly split into 2 parts: