light_clone 0.4.1

Compile-time enforcement for O(1) clone operations
Documentation
# LightClone

Compile-time enforcement for O(1) clone operations in Rust.

## Overview

LightClone is for codebases that embrace immutable data structures. It provides a marker trait and derive macro that guarantees cloning is cheap by only allowing types where cloning involves:

- **Atomic refcount increments** (`Arc`)
- **Non-atomic refcount increments** (`Rc`)
- **Bitwise copies** (`Copy` types)
- **Persistent data structures** (im, imbl, rpds with structural sharing)

Types like `String`, `Vec`, or `HashMap` that perform deep copies are rejected at compile time.

[crates.io](https://crates.io/crates/light_clone) | [docs.rs](https://docs.rs/light_clone)

## Usage

```rust
use light_clone::LightClone;
use std::sync::Arc;

#[derive(Clone, LightClone)]
struct Config {
    name: Arc<str>,
    max_connections: u32,
    timeout_ms: u64,
}

let config = Config {
    name: "production".into(),
    max_connections: 100,
    timeout_ms: 5000,
};

// .light_clone() or .lc() for short
let clone = config.lc();
```

### Compile-Time Safety

Add `#[derive(Clone, LightClone)]` to your structs and enums. All fields must implement `LightClone`:

```rust
use light_clone::LightClone;
use std::sync::Arc;

#[derive(Clone, LightClone)]
struct MyType {
    id: u64,                    // Copy types work
    name: Arc<str>,             // Arc works
    metadata: Option<Arc<str>>, // Containers of LightClone work
}
```

If any field doesn't implement `LightClone`, you get a compile error:

```rust
#[derive(Clone, LightClone)]
struct Invalid {
    data: String,  // Error: String does not implement LightClone
}
```

This ensures your types remain O(1) to clone as they evolve.

### Ergonomic Strings

Use `LightStr` as a cheap-to-clone string type:

```rust
use light_clone::{LightStr, IntoLightStr};

let s: LightStr = "hello".into_light_str();
let clone = s.lc();  // O(1) - just increments refcount
```

## Supported Types

### Primitives
All primitive types: `i8`-`i128`, `u8`-`u128`, `f32`, `f64`, `bool`, `char`, `()`

### Smart Pointers
- `Arc<T>` where `T: ?Sized`
- `Rc<T>` where `T: ?Sized`
- `std::sync::Weak<T>` where `T: ?Sized`
- `std::rc::Weak<T>` where `T: ?Sized`

### Containers
- `Option<T>` where `T: LightClone`
- `Result<T, E>` where `T: LightClone, E: LightClone`
- `PhantomData<T>`
- Tuples up to 12 elements
- `[T; N]` arrays where `T: LightClone + Copy`

### Wrapper Types
- `Pin<T>` where `T: LightClone`
- `Bound<T>` where `T: LightClone`
- `Poll<T>` where `T: LightClone`
- `ManuallyDrop<T>` where `T: LightClone`
- `Cell<T>` where `T: LightClone + Copy`
- `NonNull<T>` where `T: ?Sized`

### Function Pointers
- `fn(...) -> R` with up to 12 arguments

### Enums

```rust
#[derive(Clone, LightClone)]
enum State {
    Idle,
    Loading { progress: u8 },
    Ready(Arc<Data>),
}
```

### Implementing for Custom Types

Since `LightClone` is a marker trait, you can implement it for your own types or third-party types that are O(1) to clone:

```rust
use light_clone::LightClone;
use std::sync::Arc;

// For a type you know is O(1) to clone
struct MyArcWrapper(Arc<str>);

impl Clone for MyArcWrapper {
    fn clone(&self) -> Self {
        MyArcWrapper(self.0.clone())
    }
}

impl LightClone for MyArcWrapper {}
```

The trait provides default implementations for `light_clone()` and `lc()` that delegate to `clone()`, so an empty impl is all you need.

This is useful for:
- Third-party types that are O(1) to clone but don't have built-in LightClone support
- Newtypes wrapping LightClone types
- Types from external crates where you can't use the derive macro

## Features

Enable integrations with popular crates via feature flags:

```toml
[dependencies]
light_clone = { version = "0.3", features = ["bytes", "smol_str"] }
```

### Persistent Collections

| Feature | Crate | Types |
|---------|-------|-------|
| `im` | [im]https://crates.io/crates/im | `Vector`, `HashMap`, `HashSet`, `OrdMap`, `OrdSet` |
| `imbl` | [imbl]https://crates.io/crates/imbl | `Vector`, `HashMap`, `HashSet`, `OrdMap`, `OrdSet` |
| `rpds` | [rpds]https://crates.io/crates/rpds | `Vector`, `List`, `Queue`, `Stack`, `HashTrieMap`, `HashTrieSet`, `RedBlackTreeMap`, `RedBlackTreeSet` |

### Common Types

| Feature | Crate | Types | Clone Mechanism |
|---------|-------|-------|-----------------|
| `bytes` | [bytes]https://crates.io/crates/bytes | `Bytes` | Arc-based ref counting |
| `smol_str` | [smol_str]https://crates.io/crates/smol_str | `SmolStr` | Inline or Arc |
| `uuid` | [uuid]https://crates.io/crates/uuid | `Uuid` | Copy (128-bit) |
| `rust_decimal` | [rust_decimal]https://crates.io/crates/rust_decimal | `Decimal` | Copy (128-bit) |
| `ordered-float` | [ordered-float]https://crates.io/crates/ordered-float | `OrderedFloat<T>`, `NotNan<T>` | Copy wrapper |
| `chrono` | [chrono]https://crates.io/crates/chrono | `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Tz>`, `Month`, `Weekday`, `TimeDelta`, `Utc`, `FixedOffset` | Copy |
| `time` | [time]https://crates.io/crates/time | `Date`, `Time`, `PrimitiveDateTime`, `OffsetDateTime`, `UtcOffset`, `Duration`, `Month`, `Weekday` | Copy |

### Meta Features

| Feature | Description |
|---------|-------------|
| `full` | Enable all optional integrations |

## When to Use Immutable Data Structures

LightClone enforces that your types use immutable data structures (`Arc`, `Rc`, persistent collections) which enable O(1) cloning through structural sharing. This approach shines when:

- **Clone-heavy workloads** - Sharing state across threads, event sourcing, undo/redo systems, functional pipelines with pure transforms
- **Cloning large or nested data** - A 10KB string clone copies 10KB; an `Arc<str>` clone increments a counter
- **Concurrent code** - Clone and send freely without worrying about data races or locks
- **Structural sharing matters** - Persistent collections share unchanged portions between versions

The trade-offs to consider:

- **Mutation is still faster than cloning** - LightClone enforces cloning is cheap, not free. In-place mutation avoids refcount operations entirely, so prefer mutation for hot paths
- **Memory overhead** - Arc/Rc add pointer indirection and allocation overhead. Persistent collections trade memory for structural sharing

**Where LightClone fits:** Once you've committed to immutable data structures, LightClone provides compile-time enforcement that cloning is cheap. It catches accidental `String` or `Vec` fields that would silently introduce expensive deep clones.

## Performance

LightClone has zero runtime overhead—`.light_clone()` compiles to identical code as `.clone()`.

The real performance benefit comes from using immutable data structures:

| Scenario | Immutable | Standard | Difference |
|----------|-----------|----------|------------|
| Clone 10KB string | 11 ns | 83 ns | 7x faster |
| Clone struct with 50 levels of nesting | 15 ns | 1.9 µs | 128x faster |
| Clone 10K element vector | 41 ns | 622 ns | 15x faster |
| Clone 10K element hashmap | 15 ns | 2.2 µs | 148x faster |

Mutation has trade-offs—persistent collections are slower for small, mutation-heavy workloads but catch up as data grows. See [BENCHMARKS.md](BENCHMARKS.md) for detailed comparisons.

## Minimum Supported Rust Version

Rust 1.70.0. The `rpds` feature requires Rust 1.85+ due to upstream dependencies.

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

## Created By

[Hamilton Greene](https://hamy.xyz)