diff --git a/README.md b/README.md index f5db68b..270f709 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,10 @@ logic. See Features and How It Works for details. - **Automatic Patch Type Generation**: Derives a companion `Patch` struct for any struct annotated with `#[derive(Patchable)]` - **Recursive Patching**: Use the `#[patchable]` attribute to mark fields that require recursive patching - **Smart Exclusion**: Excludes fields marked with `#[patchable(skip)]` -- **Serde Integration (default)**: Generated patch types automatically implement `serde::Deserialize` and `Clone` +- **Serde Integration (optional, default)**: Generated patch types automatically implement `serde::Deserialize` (exclude + the `serde` feature to opt out) +- **Clone Support (optional, default)**: Generated patch types automatically implement `Clone` (exclude the `cloneable` + feature to opt out) - **Generic Support**: Full support for generic types with automatic trait bound inference - **Optional `From` Derive**: Enable `From` for `StructPatch` with the `impl_from` feature - **`#[patchable_model]` Attribute Macro**: Auto-derives `Patchable` and `Patch`, and (with default `serde`) adds `serde::Serialize` @@ -83,6 +86,13 @@ Enable `From` generation: patchable = { version = "0.5.3", features = ["impl_from"] } ``` +Enable `Clone` derivation for patch types: + +```toml +[dependencies] +patchable = { version = "0.5.3", features = ["cloneable"] } +``` + ## Usage ### Basic Example @@ -244,7 +254,7 @@ impl TryPatch for Config { - Only structs are supported (enums and unions are not). - Lifetime parameters are not supported. - `#[patchable]` currently only supports simple generic types (not complex types like `Vec`). -- Generated patch types derive `Clone` and `Deserialize` but not `Serialize` (by design). +- Generated patch types derive `Deserialize` (default) and `Clone` (optional with `cloneable` feature) but not `Serialize` (by design). ## How It Works @@ -319,7 +329,7 @@ Marks a field for recursive patching. ```rust pub trait Patchable { - type Patch: Clone; + type Patch; } ``` diff --git a/patchable/src/lib.rs b/patchable/src/lib.rs index 11ca72e..970f0c5 100644 --- a/patchable/src/lib.rs +++ b/patchable/src/lib.rs @@ -39,16 +39,15 @@ pub use patchable_macro::{Patch, Patchable, patchable_model}; /// // `impl_from` feature is enabled. For derived implementations, mark non-state fields with /// // `#[patchable(skip)]` (and add `#[serde(skip)]` as needed when using serde). /// -/// #[derive(Clone, PartialEq, Deserialize)] +/// // Derive `Clone` if needed by enabling "cloneable" feature or manually. +/// // "cloneable" is enabled by default. +/// #[derive(PartialEq, Deserialize)] /// pub struct AccumulatorPatch { /// prev_control_signal: T, /// accumulated: u32, /// } /// -/// impl Patchable for Accumulator -/// where -/// T: Clone, -/// { +/// impl Patchable for Accumulator { /// type Patch = AccumulatorPatch; /// } /// @@ -61,10 +60,7 @@ pub use patchable_macro::{Patch, Patchable, patchable_model}; /// } /// } /// -/// impl Patch for Accumulator -/// where -/// T: Clone, -/// { +/// impl Patch for Accumulator { /// #[inline(always)] /// fn patch(&mut self, patch: Self::Patch) { /// self.prev_control_signal = patch.prev_control_signal;