key-paths-core
Trait-only keypath contracts for Rust. No proc-macros, no locks, no async runtime — only the interfaces your library can implement so callers share a common read/write surface.
Use this crate when you want to build a custom keypath library (or integrate keypaths into an existing framework) without pulling in rust-key-paths.
For a full reference implementation (derive macros, Kp, sync/async locks, composition), see rust-key-paths in the same repository.
Traits
| Trait | Role |
|---|---|
Readable<Root, Value> |
Getter path: root → optional Value |
Writable<MutRoot, MutValue> |
Setter path: mut root → optional mutable Value |
KeyPath<Root, Value, MutRoot, MutValue> |
Marker: both read and write |
KpTrait<R, V, Root, Value, MutRoot, MutValue> |
Above + TypeId helpers + then |
KeyPathValueTarget |
Maps &T / &mut T → T for generic chaining |
AccessorTrait |
Optional-root and or_else helpers (default methods) |
Architecture: adapting keypaths in your crate
1. Pick root and value types
- Root — what the caller passes into
get(often&MyStructor&mut MyStruct). - Value — what the keypath returns on success (often
&Fieldor&mut Field). - MutRoot / MutValue — usually the same shapes as Root/Value for mutation paths.
Keep logical types R and V in mind when you implement [KpTrait] (for TypeId and documentation).
2. Implement Readable and Writable
use ;
;
3. Optional: AccessorTrait
Blanket-style ergonomics without new methods on your type:
use ;
4. Composition with [KpTrait::then]
Implement then on your keypath type; return type Out is inferred at the call site (see rust-key-paths Kp::then for a reference impl).
Lock traversal and async chaining stay in rust-key-paths (SyncKp, AsyncLockKp, ChainExt).
5. Async keypaths
Define async methods on your type (e.g. async fn get(&self, root: Root) -> Option<Value>), and optionally a blocking adapter that implements Readable/Writable for background threads (see rust-key-paths block_async pattern). The core traits stay synchronous so they stay runtime-agnostic.
6. Lock / shared state
Do not fake &mut T through Arc or lock-free snapshots. Either:
- return owned snapshots / guards from your own API, or
- use
rust-key-pathslock keypaths (SyncKp,AsyncLockKp) that encode the right semantics.
Cargo.toml
[]
= "2"
No default features. #![no_std] with alloc not required.
Migration from 1.x
Version 2.0 is a breaking rewrite: the old dynamic KeyPaths enum and container helpers were removed in favor of these traits. Existing code that used key_paths_core::KeyPaths should stay on 1.x or migrate to rust-key-paths 3.x.
Related crates
| Crate | Purpose |
|---|---|
rust-key-paths |
Reference Kp, derive, sync/async locks, ChainExt, HOF helpers |
key-paths-derive |
#[derive(Kp)] proc-macro (depends on rust-key-paths, not this crate) |