structfs_serde_store/lib.rs
1//! Serde Integration for StructFS
2//!
3//! This layer provides typed access to StructFS stores via serde. It adds:
4//! - `TypedReader`: Read directly into Rust types
5//! - `TypedWriter`: Write Rust types directly
6//! - `JsonCodec`: A codec for JSON format
7//! - Value <-> serde conversions
8//!
9//! # Lossless values
10//!
11//! ```rust
12//! use structfs_serde_store::{Codec, Format, Value, ValueJsonCodec};
13//! let value = Value::Array(vec![Value::from(u64::MAX), Value::Bytes(vec![0, 255])]);
14//! let bytes = ValueJsonCodec.encode(&value, &Format::VALUE_JSON)?;
15//! let decoded = ValueJsonCodec.decode(&bytes, &Format::VALUE_JSON)?;
16//! assert!(value.semantic_eq(&decoded));
17//! # Ok::<(), structfs_serde_store::Error>(())
18//! ```
19//!
20//! Plain JSON rejects bytes and non-finite floats. Use [`ValueCodec`] to select
21//! a profile and [`Limits`] explicitly. [`to_value`] and [`from_value`] use the
22//! structural Serde mapping directly; ambiguous null-valued options require
23//! [`ExplicitOption`]. All codecs validate complete documents. Raw record
24//! forwarding does not imply validation; use [`transcode`] for that contract.
25//!
26//! # Example
27//!
28//! ```rust,ignore
29//! use structfs_serde_store::{TypedReader, TypedWriter, JsonCodec};
30//! use serde::{Serialize, Deserialize};
31//!
32//! #[derive(Serialize, Deserialize)]
33//! struct User {
34//! name: String,
35//! age: u32,
36//! }
37//!
38//! fn read_user(store: &mut dyn Reader) -> Result<Option<User>, Error> {
39//! let codec = JsonCodec;
40//! store.read_as(&path!("users/123"), &codec)
41//! }
42//! ```
43//!
44//! # Async Support
45//!
46//! Enable the `async` feature for async trait variants:
47//!
48//! ```toml
49//! [dependencies]
50//! structfs-serde-store = { version = "0.3", features = ["async"] }
51//! ```
52//!
53//! Use `AsyncTypedReader`/`AsyncTypedWriter` for borrowing futures, or
54//! `DetachedTypedReader`/`DetachedTypedWriter` for independent operations.
55
56pub use bytes::Bytes;
57
58mod cbor_profile;
59mod codec;
60mod convert;
61mod flex_profile;
62mod json_profile;
63mod limits;
64mod typed;
65mod value_serde;
66
67pub use codec::{
68 transcode, CborCodec, FlexbuffersCodec, JsonCodec, MultiCodec, Profile, ValueCodec,
69 ValueJsonCodec,
70};
71pub use convert::{from_value, json_to_value, to_value, value_to_json};
72pub use limits::{validate_value, Limits};
73pub use typed::{TypedReader, TypedWriter};
74pub use value_serde::{from_value_with_limits, to_value_with_limits, ExplicitOption};
75
76// Re-export core types for convenience
77pub use structfs_core_store::{
78 Codec, Error, Format, Path, PathError, Reader, Record, Store, Value, Writer,
79};
80
81// Async support
82#[cfg(feature = "async")]
83mod async_typed;
84
85#[cfg(feature = "async")]
86pub use async_typed::{AsyncTypedReader, AsyncTypedWriter};
87
88// Re-export async core types when async feature is enabled
89#[cfg(feature = "async")]
90pub use structfs_core_store::{
91 AsyncCoreToLL, AsyncLLReader, AsyncLLStore, AsyncLLToCore, AsyncLLWriter, AsyncReader,
92 AsyncStore, AsyncWriter, DetachedFuture, DetachedReader, DetachedStore, DetachedWriter,
93 SyncToAsync, SyncToAsyncLL,
94};
95
96#[cfg(feature = "async")]
97mod detached_typed;
98#[cfg(feature = "async")]
99pub use detached_typed::{DetachedTypedReader, DetachedTypedWriter};