shapely
shapely provides runtime reflection for Rust.
Any type that implements Shapely
trait returns a Shape
, which describes:
- The memory layout of the type
- Its innards: struct fields, underlying type for newtypes, etc.
- How to drop it in place
The Partial
type is able to allocate (or work from a &mut MaybeUninit<T>
)
any Shapely type, and gradually initialize its fields — until the fully-built
value is moved out of the partial.
It comes with a derive macro that uses unsynn for speed of compilation.
Ecosystem
The main shapely
crate re-exports symbols from:
- shapely-core, which defines the main
Shapely
trait and theShape
struct - shapely-derive, which implements the
Shapely
derive attribute as a fast/light proc macro powered by unsynn
shapely supports deserialization from multiple data formats through dedicated crates:
- shapely-json: JSON deserialization
- shapely-yaml: YAML deserialization
- shapely-msgpack: MessagePack deserialization
- shapely-urlencoded: URL-encoded form data deserialization
Additionally:
- shapely-pretty is able to pretty-print Shapely types.
- shapely-codegen is internal and generates some of the code of
shapely-core
Implementing Your Own Deserializer
To implement a custom deserializer for a new format, you'll need to work with the following key components from shapely:
Key Types
- [
Partial
]: The central type for building shapely values incrementally - [
Shape
]: Describes the memory layout and structure of a type - [
Innards
]: Represents the internal structure (Scalar, Struct, etc.) - [
Scalar
]: Represents primitive types like String, u64, etc.
Implementation Pattern
- Create a function that takes a
&mut
[Partial
] and your format's input (string, bytes, etc.) - Examine the shape of the partial using [
Partial::shape
] - Handle different shapes based on [
Shape::innards
]:- For [
Innards::Scalar
], use [Partial::scalar_slot
] to get and fill the slot - For [
Innards::Struct
], iterate through fields, using [Partial::slot_by_name
] to access each field - [
Innards::Map
] and [Innards::List
] come with vtables, they have helper slots as well - Create nested [
Partial
] instances for complex fields and fill them recursively
- For [
When in doubt, refer to the shapely-json
implementation — it's the most featureful.
Example Implementation Skeleton
use ;
use From;
For more detailed examples, examine the implementation of existing deserializers like shapely-json or shapely-msgpack.
Funding
Thanks to Namespace for providing fast GitHub Actions workers:
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.