diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b14e5af..672145d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -17,10 +17,18 @@ updates: schedule: interval: "weekly" - package-ecosystem: "cargo" - directory: "/no-std-examples" + directory: "/examples/no-std-examples" schedule: interval: "weekly" - package-ecosystem: "cargo" - directory: "/complex-example" + directory: "/examples/complex-examples" + schedule: + interval: "weekly" + - package-ecosystem: "cargo" + directory: "/examples/patch-examples" + schedule: + interval: "weekly" + - package-ecosystem: "cargo" + directory: "/examples/filler-examples" schedule: interval: "weekly" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8f994a1..7103cee 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,6 +17,9 @@ jobs: with: github_access_token: ${{ secrets.GITHUB_TOKEN }} + - name: Nix flake check + run: nix flake check + - name: fmt run: nix develop .#ci -c cargo fmt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9bf0e4d..410a754 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,69 +17,33 @@ jobs: with: github_access_token: ${{ secrets.GITHUB_TOKEN }} - - name: Test no default features + - name: Build devshells run: | - nix develop .#ci -c cargo run --quiet --no-default-features --example instance - nix develop .#ci -c cargo run --quiet --no-default-features --example filler - nix develop .#ci -c cargo run --quiet --no-default-features --example diff - nix develop .#ci -c cargo run --quiet --no-default-features --example json - nix develop .#ci -c cargo run --quiet --no-default-features --example rename-patch-struct - nix develop .#ci -c cargo run --quiet --no-default-features --example patch-attr - nix develop .#ci -c cargo run --quiet --no-default-features --example time - nix develop .#ci -c cargo run --quiet --no-default-features --example clap - nix develop .#ci -c cargo run --quiet --no-default-features --features=nesting --example nesting - nix develop .#ci -c cargo run --quiet --no-default-features --features=option --example option - nix develop .#ci -c cargo run --quiet --no-default-features --example=log - nix develop .#ci -c cargo run --quiet --no-default-features --example apply-by - nix develop .#ci -c cargo run --quiet --no-default-features --features=box --example box - nix develop .#ci -c cargo test --quiet --no-default-features + nix develop .#ci -c echo Build ci devshell + nix develop .#no-std -c echo Build no-std devshell - - name: Test with std features + - name: Test lib run: | - nix develop .#ci -c cargo run --quiet --features=std --example instance - nix develop .#ci -c cargo run --quiet --features=std --example filler - nix develop .#ci -c cargo run --quiet --features=std --example filler-op - nix develop .#ci -c cargo run --quiet --features=std --example diff - nix develop .#ci -c cargo run --quiet --features=std --example json - nix develop .#ci -c cargo run --quiet --features=std --example rename-patch-struct - nix develop .#ci -c cargo run --quiet --features=std --example patch-attr - nix develop .#ci -c cargo run --quiet --features=std --example option - nix develop .#ci -c cargo run --quiet --features=std --example box - nix develop .#ci -c cargo run --quiet --features=std,nesting --example nesting - nix develop .#ci -c cargo test --quiet --features=std + nix develop .#ci -c test no-default + nix develop .#ci -c test std + nix develop .#ci -c test merge + nix develop .#ci -c test default - - name: Test with merge features + - name: Test patch examples run: | - nix develop .#ci -c cargo run --quiet --features=option,merge --example option - nix develop .#ci -c cargo run --quiet --features=merge --example op - nix develop .#ci -c cargo run --quiet --features=merge,nesting --example nesting - nix develop .#ci -c cargo test --quiet --features=merge --no-default-features - nix develop .#ci -c cargo test --quiet --features=merge + nix develop .#ci -c check-patch no-default + nix develop .#ci -c check-patch std + nix develop .#ci -c check-patch merge + nix develop .#ci -c check-patch option + nix develop .#ci -c check-patch default - - name: Test with option features + - name: Test filler examples run: | - nix develop .#ci -c cargo run --quiet --features=none_as_default --example option - nix develop .#ci -c cargo run --quiet --features=none_as_default,nesting --example nesting - nix develop .#ci -c cargo run --quiet --features=keep_none --example option - nix develop .#ci -c cargo run --quiet --features=keep_none,nesting --example nesting - - - name: Test with default features - run: | - nix develop .#ci -c cargo run --quiet --example status - nix develop .#ci -c cargo run --quiet --example op - nix develop .#ci -c cargo run --quiet --example clap - nix develop .#ci -c cargo run --quiet --features=nesting --example nesting - nix develop .#ci -c cargo run --quiet --features=nesting --example clap - nix develop .#ci -c cargo run --quiet --example=log - nix develop .#ci -c cargo run --quiet --example apply-by - nix develop .#ci -c cargo run --quiet --features=box --example box - nix develop .#ci -c cargo test --quiet + nix develop .#ci -c check-filler no-default + nix develop .#ci -c check-filler default - name: Test in no std - run: | - cd no-std-examples - nix develop .#no-std -c cargo run --quiet --features=box --bin no-std-box - nix develop .#no-std -c cargo run --quiet --features=option --bin no-std-option + run: nix develop .#no-std -c check-no-std - - name: Test with catalyst - run: nix develop .#ci -c check-catalyst + - name: Test complex examples + run: nix develop .#ci -c check-complex diff --git a/.gitignore b/.gitignore index 1fa5e3d..3ed6912 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ Cargo.lock .envrc .direnv/ struct-patch/examples -no-std-examples/target -complex-example/target +examples/no-std-examples/target +examples/complex-examples/target +examples/patch-examples/target diff --git a/Cargo.toml b/Cargo.toml index f013e96..915ff03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,10 @@ members = [ "derive", ] exclude = [ - "no-std-examples", - "complex-example", + "examples/no-std-examples", + "examples/complex-examples", + "examples/patch-examples", + "examples/filler-examples", ] [workspace.package] diff --git a/README.md b/README.md index 29a65b9..8762a68 100644 --- a/README.md +++ b/README.md @@ -17,15 +17,15 @@ This crate provides the `Patch`, `Filler`, `Substrate`, `Catalyst` and `Complex` - If any field in the instance is empty (`None` or an empty collection), `Filler` will try to fill it. It supports `Option`, `Vec`, `VecDeque`, `LinkedList`, `HashMap`, `BTreeMap`, `HashSet`, `BTreeSet`, `BinaryHeap` fields, as well as custom types via `#[filler(extendable)]` and any type via `#[filler(empty_value = ...)]`. - With the `substrate` feature, the `Substrate` derive macro exposes field information so that other crates can access it. With the `catalyst` feature (which implies `substrate`), `Catalyst` and `Complex` derive macros help you extend a struct with extra fields from another crate. -This crate supports `no_std` — check the [no-std-examples](./no-std-examples). +This crate supports `no_std` — check the [no-std-examples](./examples/no-std-examples). The following are more specific scenarios to help you learn the details: - A project with config from environments, files, and command line: you can use `Patch` to keep your config organized. Please check this [template](https://github.com/yanganto/ConfigTemplate). -- A project extended from another project, where only some fields of the config differ. You can use the `catalyst` feature to expose the base struct in a build script with `Substrate`, then a `Catalyst` struct can bind to it and produce a complex struct. Check the [complex-example](./complex-example) and [Quick Example: case 3](#case-3---extend-a-struct-from-a-crate). +- A project extended from another project, where only some fields of the config differ. You can use the `catalyst` feature to expose the base struct in a build script with `Substrate`, then a `Catalyst` struct can bind to it and produce a complex struct. Check the [complex-examples](./examples/complex-examples) and [Quick Example: case 3](#case-3---extend-a-struct-from-a-crate). ## Quick Example -#### Case 1 - Patch on a Config +#### Case 1 (Patch) - Patch on a Config Deriving `Patch` on a struct generates a struct similar to the original one, but with all fields wrapped in an `Option`. An instance of such a patch struct can be applied onto the original struct, replacing values only if they are set to `Some`, leaving them unchanged otherwise. See also Case Studies: @@ -82,7 +82,7 @@ fn patch_json() { } ``` -#### Case 2 - Fill up on a Config +#### Case 2 (Filler) - Fill up on a Config Deriving `Filler` on a struct generates a struct similar to the original one, keeping only the fields that can be filled (`Option`, collections, `extendable`, or `empty_value` fields). Unlike `Patch`, the `Filler` only works on empty fields of the instance. See also Case Studies: - [Log which fields were patched or filled](docs/logs.md) @@ -119,11 +119,11 @@ assert_eq!(item.maybe_field_int, Some(7)); assert_eq!(item.list, vec![7]); ``` -#### Case 3 - Extend a struct from a crate +#### Case 3 (Complex) - Extend a struct from a crate Deriving `Substrate` on a struct exposes the field information so that other crates can access it. Deriving `Catalyst` reads the field information of a `Substrate` and generates a new complex struct. In the other words, the catalyst is a struct with extra fields that the developer writes down in the downstream crate. The complex is a generated struct that combines the substrate's fields with the catalyst's extra fields. The overall behavior is like [chemical catalysts](https://en.wikipedia.org/wiki/Enzyme_catalysis): a catalyst **binds** onto a substrate to form a complex struct, which has all fields from both. -A complex can also **decouple** without cloning, returning the original catalyst and substrate. Check the [complex-example](./complex-example/catalyst/src/lib.rs). +A complex can also **decouple** without cloning, returning the original catalyst and substrate. Check the [complex-examples](./examples/complex-examples/catalyst/src/lib.rs). With the `unsafe` feature, `bind` and `decouple` use `ManuallyDrop` + `ptr::read` to avoid memory moves, and `__substrate_new` uses `MaybeUninit` + `ptr::write` while `__substrate_unpack` uses `ManuallyDrop` + `ptr::read`, such that the copy will be less. In terms of crate dependencies, the crate using `Substrate` is **upstream** (a dependency), and the crate using `Catalyst` is **downstream** (it depends on the substrate crate). There are two ways for the downstream crate to read the substrate's field layout: @@ -165,7 +165,7 @@ struct Amyloid { // } ``` -**Option B: via source code with `src` attribute**: point the `Catalyst` macro directly at the substrate crate's source file using `#[catalyst(src = "crate_name:/path/to/file.rs")]`. The macro uses `cargo_metadata` to locate the package and `syn` to parse the file, so no `build.rs` or `expose()` call is required. Check the [catalyst-src example](./complex-example/catalyst-src/src/lib.rs). +**Option B: via source code with `src` attribute**: point the `Catalyst` macro directly at the substrate crate's source file using `#[catalyst(src = "crate_name:/path/to/file.rs")]`. The macro uses `cargo_metadata` to locate the package and `syn` to parse the file, so no `build.rs` or `expose()` call is required. Check the [catalyst-src example](./examples/complex-examples/catalyst-src/src/lib.rs). ```rust /// In the substrate crate (src/lib.rs) @@ -231,7 +231,9 @@ Please check the [traits documentation][doc-traits] to learn more. ## Examples -The [examples][examples] demonstrate the following scenarios: +Examples are organised into focused sub-projects under [`examples/`](./examples): + +**[patch-examples](./examples/patch-examples)** — `Patch` derive macro scenarios: - diff two instances for a patch (`diff.rs`) - create a patch from a JSON string (`json.rs`) - rename the patch structure (`rename-patch-struct.rs`) @@ -241,14 +243,20 @@ The [examples][examples] demonstrate the following scenarios: - show operators on patches (`op.rs`) - show example with serde crates, e.g. `humantime_serde` for durations (`time.rs`) - show a patch nesting another patch (`nesting.rs`) -- show filler with all possible types (`filler.rs`) -- show operators on fillers (`filler-op.rs`) - show `skip_wrap` field behavior (`instance.rs`) - use `Patch` with `clap` for command-line config (`clap.rs`) - demonstrate `default_log` and `apply_with_log` for both `Patch` and `Filler` (`log.rs`) - apply a heap-allocated (boxed) patch and produce a boxed diff (`box.rs`) - demonstrate `apply_by` for custom field-level apply logic, e.g. list concatenation (`apply-by.rs`) +**[filler-examples](./examples/filler-examples)** — `Filler` derive macro scenarios: +- show filler with all possible types (`filler.rs`) +- show operators on fillers (`filler-op.rs`) + +**[no-std-examples](./examples/no-std-examples)** — `no_std` usage with a bare-metal target. + +**[complex-examples](./examples/complex-examples)** — `Substrate` / `Catalyst` / `Complex` derive macros for extending a struct across crates. + ## Features This crate includes the following optional features: @@ -275,4 +283,4 @@ This crate includes the following optional features: [doc-badge]: https://img.shields.io/badge/docs-rs-orange.svg [doc-url]: https://docs.rs/struct-patch/ [doc-traits]: https://docs.rs/struct-patch/latest/struct_patch/traits/trait.Patch.html#container-attributes -[examples]: /lib/examples +[examples]: /examples diff --git a/complex-example/Cargo.toml b/examples/complex-examples/Cargo.toml similarity index 93% rename from complex-example/Cargo.toml rename to examples/complex-examples/Cargo.toml index 52cfb06..caa1747 100644 --- a/complex-example/Cargo.toml +++ b/examples/complex-examples/Cargo.toml @@ -6,7 +6,7 @@ members = [ "catalyst-src", ] [workspace.dependencies] -struct-patch = { path = "../lib" } +struct-patch = { path = "../../lib" } [workspace.package] authors = ["Antonio Yang "] diff --git a/complex-example/catalyst-src/Cargo.toml b/examples/complex-examples/catalyst-src/Cargo.toml similarity index 100% rename from complex-example/catalyst-src/Cargo.toml rename to examples/complex-examples/catalyst-src/Cargo.toml diff --git a/complex-example/catalyst-src/src/lib.rs b/examples/complex-examples/catalyst-src/src/lib.rs similarity index 100% rename from complex-example/catalyst-src/src/lib.rs rename to examples/complex-examples/catalyst-src/src/lib.rs diff --git a/complex-example/catalyst/Cargo.toml b/examples/complex-examples/catalyst/Cargo.toml similarity index 100% rename from complex-example/catalyst/Cargo.toml rename to examples/complex-examples/catalyst/Cargo.toml diff --git a/complex-example/catalyst/build.rs b/examples/complex-examples/catalyst/build.rs similarity index 100% rename from complex-example/catalyst/build.rs rename to examples/complex-examples/catalyst/build.rs diff --git a/complex-example/catalyst/src/lib.rs b/examples/complex-examples/catalyst/src/lib.rs similarity index 100% rename from complex-example/catalyst/src/lib.rs rename to examples/complex-examples/catalyst/src/lib.rs diff --git a/complex-example/substrate/Cargo.toml b/examples/complex-examples/substrate/Cargo.toml similarity index 100% rename from complex-example/substrate/Cargo.toml rename to examples/complex-examples/substrate/Cargo.toml diff --git a/complex-example/substrate/src/lib.rs b/examples/complex-examples/substrate/src/lib.rs similarity index 100% rename from complex-example/substrate/src/lib.rs rename to examples/complex-examples/substrate/src/lib.rs diff --git a/examples/filler-examples/Cargo.toml b/examples/filler-examples/Cargo.toml new file mode 100644 index 0000000..07ae398 --- /dev/null +++ b/examples/filler-examples/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "filler-examples" +authors = ["Antonio Yang "] +version = "0.14.1" +edition = "2021" +license = "MIT" + +[dependencies] +struct-patch = { path = "../../lib" } + +[features] +default = ["status", "op"] +status = ["struct-patch/status"] +op = ["struct-patch/op"] diff --git a/lib/examples/filler-op.rs b/examples/filler-examples/examples/filler-op.rs similarity index 100% rename from lib/examples/filler-op.rs rename to examples/filler-examples/examples/filler-op.rs diff --git a/lib/examples/filler.rs b/examples/filler-examples/examples/filler.rs similarity index 100% rename from lib/examples/filler.rs rename to examples/filler-examples/examples/filler.rs diff --git a/no-std-examples/.cargo/config.toml b/examples/no-std-examples/.cargo/config.toml similarity index 100% rename from no-std-examples/.cargo/config.toml rename to examples/no-std-examples/.cargo/config.toml diff --git a/no-std-examples/Cargo.toml b/examples/no-std-examples/Cargo.toml similarity index 92% rename from no-std-examples/Cargo.toml rename to examples/no-std-examples/Cargo.toml index ddaaf9f..3a5f0d7 100644 --- a/no-std-examples/Cargo.toml +++ b/examples/no-std-examples/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "MIT" [dependencies] -struct-patch = { path = "../lib" } +struct-patch = { path = "../../lib" } linked_list_allocator = "0.10" cortex-m-rt = "0.7" cortex-m-semihosting = "0.5" diff --git a/no-std-examples/build.rs b/examples/no-std-examples/build.rs similarity index 100% rename from no-std-examples/build.rs rename to examples/no-std-examples/build.rs diff --git a/no-std-examples/memory.x b/examples/no-std-examples/memory.x similarity index 100% rename from no-std-examples/memory.x rename to examples/no-std-examples/memory.x diff --git a/no-std-examples/src/box.rs b/examples/no-std-examples/src/box.rs similarity index 100% rename from no-std-examples/src/box.rs rename to examples/no-std-examples/src/box.rs diff --git a/no-std-examples/src/option.rs b/examples/no-std-examples/src/option.rs similarity index 100% rename from no-std-examples/src/option.rs rename to examples/no-std-examples/src/option.rs diff --git a/examples/patch-examples/Cargo.toml b/examples/patch-examples/Cargo.toml new file mode 100644 index 0000000..7b47aa8 --- /dev/null +++ b/examples/patch-examples/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "patch-examples" +authors = ["Antonio Yang "] +version = "0.14.1" +edition = "2021" +license = "MIT" + +[dependencies] +struct-patch = { path = "../../lib" } +serde_json = "1.0" +serde = { version = "1", features = ["derive"] } +serde_with = "3.9.0" +toml = "1.1.2" +humantime-serde = "1.1.1" +clap = { version = "4.4.7", features = ["derive"] } + +[features] +default = ["status", "op"] +status = ["struct-patch/status"] +op = ["struct-patch/op"] +merge = ["struct-patch/merge"] +alloc = ["struct-patch/alloc"] +std = ["box", "option"] +box = ["alloc", "struct-patch/box"] +option = ["struct-patch/option"] +nesting = ["struct-patch/nesting"] +none_as_default = ["option", "struct-patch/none_as_default"] +keep_none = ["option", "struct-patch/keep_none"] + +[[example]] +name = "box" +required-features = ["box"] diff --git a/lib/examples/apply-by.rs b/examples/patch-examples/examples/apply-by.rs similarity index 100% rename from lib/examples/apply-by.rs rename to examples/patch-examples/examples/apply-by.rs diff --git a/lib/examples/box.rs b/examples/patch-examples/examples/box.rs similarity index 100% rename from lib/examples/box.rs rename to examples/patch-examples/examples/box.rs diff --git a/lib/examples/clap.rs b/examples/patch-examples/examples/clap.rs similarity index 100% rename from lib/examples/clap.rs rename to examples/patch-examples/examples/clap.rs diff --git a/lib/examples/diff.rs b/examples/patch-examples/examples/diff.rs similarity index 100% rename from lib/examples/diff.rs rename to examples/patch-examples/examples/diff.rs diff --git a/lib/examples/instance.rs b/examples/patch-examples/examples/instance.rs similarity index 100% rename from lib/examples/instance.rs rename to examples/patch-examples/examples/instance.rs diff --git a/lib/examples/json.rs b/examples/patch-examples/examples/json.rs similarity index 100% rename from lib/examples/json.rs rename to examples/patch-examples/examples/json.rs diff --git a/lib/examples/log.rs b/examples/patch-examples/examples/log.rs similarity index 100% rename from lib/examples/log.rs rename to examples/patch-examples/examples/log.rs diff --git a/lib/examples/nesting.rs b/examples/patch-examples/examples/nesting.rs similarity index 100% rename from lib/examples/nesting.rs rename to examples/patch-examples/examples/nesting.rs diff --git a/lib/examples/op.rs b/examples/patch-examples/examples/op.rs similarity index 100% rename from lib/examples/op.rs rename to examples/patch-examples/examples/op.rs diff --git a/lib/examples/option.rs b/examples/patch-examples/examples/option.rs similarity index 100% rename from lib/examples/option.rs rename to examples/patch-examples/examples/option.rs diff --git a/lib/examples/patch-attr.rs b/examples/patch-examples/examples/patch-attr.rs similarity index 100% rename from lib/examples/patch-attr.rs rename to examples/patch-examples/examples/patch-attr.rs diff --git a/lib/examples/rename-patch-struct.rs b/examples/patch-examples/examples/rename-patch-struct.rs similarity index 100% rename from lib/examples/rename-patch-struct.rs rename to examples/patch-examples/examples/rename-patch-struct.rs diff --git a/lib/examples/status.rs b/examples/patch-examples/examples/status.rs similarity index 100% rename from lib/examples/status.rs rename to examples/patch-examples/examples/status.rs diff --git a/lib/examples/time.rs b/examples/patch-examples/examples/time.rs similarity index 100% rename from lib/examples/time.rs rename to examples/patch-examples/examples/time.rs diff --git a/flake.nix b/flake.nix index 438c6d5..fb330d7 100644 --- a/flake.nix +++ b/flake.nix @@ -13,64 +13,35 @@ pkgs = import nixpkgs { inherit system overlays; }; - publishScript = pkgs.writeShellScriptBin "crate-publish" '' - cargo login $1 - cargo publish -p struct-patch-derive || echo "publish struct-patch-derive fail" - sleep 10 - cargo publish -p struct-patch - ''; - checkCatalystScript = pkgs.writeShellScriptBin "check-catalyst" '' - set -ex - cd $(git rev-parse --show-toplevel 2>/dev/null) - cd complex-example - cargo test --quiet -p substrate - cargo test --quiet -p catalyst - cargo test --quiet -p catalyst-src - echo "Run catatyst test with unsafe features" - cargo test --quiet -p catalyst --features unsafe - cargo test --quiet -p catalyst-src --features unsafe + publishScript = pkgs.writeShellScriptBin "crate-publish" + (builtins.readFile ./nix/scripts/crate-publish.sh); + checkNoStdScript = pkgs.writeShellScriptBin "check-no-std" + (builtins.readFile ./nix/scripts/check-no-std.sh); + checkComplexScript = pkgs.writeShellScriptBin "check-complex" + (builtins.readFile ./nix/scripts/check-complex.sh); + checkFillerScript = pkgs.writeShellScriptBin "check-filler" + (builtins.readFile ./nix/scripts/check-filler.sh); + checkPatchScript = pkgs.writeShellScriptBin "check-patch" + (builtins.readFile ./nix/scripts/check-patch.sh); + testScript = pkgs.writeShellScriptBin "test" + (builtins.readFile ./nix/scripts/test.sh); + PROMPT = '' + _git_ps1() { + git rev-parse --is-inside-work-tree &>/dev/null || return + local branch dirty + branch=$(git symbolic-ref --short HEAD 2>/dev/null) + [[ -n $(git status --porcelain) ]] && dirty='*' + echo "<$branch$dirty>" + } + PS1='\[\e[33m\][$DEVSHELL] \w $(_git_ps1) \$\[\e[0m\] ' ''; in - with pkgs; { - devShells = let - noStdRust = rust-bin.stable.latest.default.override { - targets = [ - "thumbv7m-none-eabi" - ]; - extensions = [ "rust-src" "llvm-tools-preview" ]; - }; - in - { - default = mkShell { - buildInputs = [ - rust-bin.stable.latest.minimal - openssl - pkg-config - - checkCatalystScript - ]; - }; - - ci = mkShell { - buildInputs = [ - rust-bin.stable.latest.default - openssl - pkg-config - - publishScript - - checkCatalystScript - ]; - }; - - no-std = mkShell { - buildInputs = [ - noStdRust - qemu - ]; - }; + devShells = { + default = import ./nix/shells/default.nix { inherit pkgs PROMPT; checkScripts = [ checkComplexScript checkFillerScript checkPatchScript testScript ]; }; + ci = import ./nix/shells/ci.nix { inherit pkgs publishScript PROMPT; checkScripts = [ checkComplexScript checkFillerScript checkPatchScript testScript ]; }; + no-std = import ./nix/shells/no-std.nix { inherit pkgs PROMPT; checkScripts = [ checkNoStdScript ]; }; }; } ); diff --git a/lib/Cargo.toml b/lib/Cargo.toml index b9e9822..2f3b61b 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -15,12 +15,8 @@ rust-version.workspace = true struct-patch-derive = { version = "=0.14.1", path = "../derive" } [dev-dependencies] -serde_json = "1.0" serde = { version = "1", features = ["derive"] } -serde_with = "3.9.0" -toml = "1.1.2" -humantime-serde = "1.1.1" -clap = { version = "4.4.7", features = ["derive"] } +serde_json = "1.0" [features] default = ["status", "op"] @@ -54,7 +50,3 @@ unsafe = [ "struct-patch-derive/unsafe" ] - -[[example]] -name = "box" -required-features = ["box"] diff --git a/nix/scripts/check-complex.sh b/nix/scripts/check-complex.sh new file mode 100644 index 0000000..6ff60bf --- /dev/null +++ b/nix/scripts/check-complex.sh @@ -0,0 +1,10 @@ +set -ex +cd $(git rev-parse --show-toplevel 2>/dev/null) +cd examples/complex-examples +cargo test --quiet -p substrate +cargo test --quiet -p catalyst +cargo test --quiet -p catalyst-src + +echo "Run catalyst test with unsafe features" +cargo test --quiet -p catalyst --features unsafe +cargo test --quiet -p catalyst-src --features unsafe diff --git a/nix/scripts/check-filler.sh b/nix/scripts/check-filler.sh new file mode 100644 index 0000000..9b56287 --- /dev/null +++ b/nix/scripts/check-filler.sh @@ -0,0 +1,25 @@ +set -ex +cd $(git rev-parse --show-toplevel 2>/dev/null) +cd examples/filler-examples + +run_no_default() { + cargo run --quiet --no-default-features --example filler +} + +run_default() { + cargo run --quiet --example filler + cargo run --quiet --example filler-op +} + +case "${1:-}" in + no-default) + run_no_default + ;; + default) + run_default + ;; + *) + run_no_default + run_default + ;; +esac diff --git a/nix/scripts/check-no-std.sh b/nix/scripts/check-no-std.sh new file mode 100644 index 0000000..68210f8 --- /dev/null +++ b/nix/scripts/check-no-std.sh @@ -0,0 +1,5 @@ +set -ex +cd $(git rev-parse --show-toplevel 2>/dev/null) +cd examples/no-std-examples +cargo run --quiet --features=box --bin no-std-box +cargo run --quiet --features=option --bin no-std-option diff --git a/nix/scripts/check-patch.sh b/nix/scripts/check-patch.sh new file mode 100644 index 0000000..c1bf126 --- /dev/null +++ b/nix/scripts/check-patch.sh @@ -0,0 +1,78 @@ +set -ex +cd $(git rev-parse --show-toplevel 2>/dev/null) +cd examples/patch-examples + +run_no_default() { + cargo run --quiet --no-default-features --example instance + cargo run --quiet --no-default-features --example diff + cargo run --quiet --no-default-features --example json + cargo run --quiet --no-default-features --example rename-patch-struct + cargo run --quiet --no-default-features --example patch-attr + cargo run --quiet --no-default-features --example time + cargo run --quiet --no-default-features --example clap + cargo run --quiet --no-default-features --features=nesting --example nesting + cargo run --quiet --no-default-features --features=option --example option + cargo run --quiet --no-default-features --example log + cargo run --quiet --no-default-features --example apply-by + cargo run --quiet --no-default-features --features=box --example box +} + +run_std() { + cargo run --quiet --features=std --example instance + cargo run --quiet --features=std --example diff + cargo run --quiet --features=std --example json + cargo run --quiet --features=std --example rename-patch-struct + cargo run --quiet --features=std --example patch-attr + cargo run --quiet --features=std --example option + cargo run --quiet --features=std --example box + cargo run --quiet --features=std,nesting --example nesting +} + +run_merge() { + cargo run --quiet --features=option,merge --example option + cargo run --quiet --features=merge --example op + cargo run --quiet --features=merge,nesting --example nesting +} + +run_option() { + cargo run --quiet --features=none_as_default --example option + cargo run --quiet --features=none_as_default,nesting --example nesting + cargo run --quiet --features=keep_none --example option + cargo run --quiet --features=keep_none,nesting --example nesting +} + +run_default() { + cargo run --quiet --example status + cargo run --quiet --example op + cargo run --quiet --example clap + cargo run --quiet --features=nesting --example nesting + cargo run --quiet --features=nesting --example clap + cargo run --quiet --example log + cargo run --quiet --example apply-by + cargo run --quiet --features=box --example box +} + +case "${1:-}" in + no-default) + run_no_default + ;; + std) + run_std + ;; + merge) + run_merge + ;; + option) + run_option + ;; + default) + run_default + ;; + *) + run_no_default + run_std + run_merge + run_option + run_default + ;; +esac diff --git a/nix/scripts/crate-publish.sh b/nix/scripts/crate-publish.sh new file mode 100644 index 0000000..b579d4b --- /dev/null +++ b/nix/scripts/crate-publish.sh @@ -0,0 +1,4 @@ +cargo login $1 +cargo publish -p struct-patch-derive || echo "publish struct-patch-derive fail" +sleep 10 +cargo publish -p struct-patch diff --git a/nix/scripts/test.sh b/nix/scripts/test.sh new file mode 100644 index 0000000..5ec58ff --- /dev/null +++ b/nix/scripts/test.sh @@ -0,0 +1,40 @@ +set -ex +cd $(git rev-parse --show-toplevel 2>/dev/null) + +run_no_default() { + cargo test --quiet --no-default-features +} + +run_std() { + cargo test --quiet --features=std +} + +run_merge() { + cargo test --quiet --features=merge --no-default-features + cargo test --quiet --features=merge +} + +run_default() { + cargo test --quiet +} + +case "${1:-}" in + no-default) + run_no_default + ;; + std) + run_std + ;; + merge) + run_merge + ;; + default) + run_default + ;; + *) + run_no_default + run_std + run_merge + run_default + ;; +esac diff --git a/nix/shells/ci.nix b/nix/shells/ci.nix new file mode 100644 index 0000000..d919d7b --- /dev/null +++ b/nix/shells/ci.nix @@ -0,0 +1,14 @@ +{ pkgs, publishScript, checkScripts, PROMPT ? "" }: +pkgs.mkShell { + name = "ci"; + shellHook = '' + export DEVSHELL=ci + ${PROMPT} + ''; + buildInputs = [ + pkgs.rust-bin.stable.latest.default + pkgs.openssl + pkgs.pkg-config + publishScript + ] ++ checkScripts; +} diff --git a/nix/shells/default.nix b/nix/shells/default.nix new file mode 100644 index 0000000..9a5a91f --- /dev/null +++ b/nix/shells/default.nix @@ -0,0 +1,15 @@ +{ pkgs, checkScripts, PROMPT ? "" }: +pkgs.mkShell { + name = "default"; + shellHook = '' + export DEVSHELL=default + ${PROMPT} + echo "Scripts:" + ${builtins.concatStringsSep "\n" (map (s: "echo \" ${s.name}\"") checkScripts)} + ''; + buildInputs = [ + pkgs.rust-bin.stable.latest.minimal + pkgs.openssl + pkgs.pkg-config + ] ++ checkScripts; +} diff --git a/nix/shells/no-std.nix b/nix/shells/no-std.nix new file mode 100644 index 0000000..3a6a235 --- /dev/null +++ b/nix/shells/no-std.nix @@ -0,0 +1,20 @@ +{ pkgs, checkScripts, PROMPT ? "" }: +let + noStdRust = pkgs.rust-bin.stable.latest.default.override { + targets = [ "thumbv7m-none-eabi" ]; + extensions = [ "rust-src" "llvm-tools-preview" ]; + }; +in +pkgs.mkShell { + name = "no-std"; + shellHook = '' + export DEVSHELL=no-std + ${PROMPT} + echo "Scripts:" + ${builtins.concatStringsSep "\n" (map (s: "echo \" ${s.name}\"") checkScripts)} + ''; + buildInputs = [ + noStdRust + pkgs.qemu + ] ++ checkScripts; +}