1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! Integration with the armour ecosystem (feature `armour`).
//!
//! Provides multi-tree database management, schema-versioned migrations,
//! and a binary RPC server compatible with armour-rpc clients.
//!
//! # Components
//!
//! - [`Db`] — manages a directory of named collections with persistent
//! metadata ([`DbInfo`]) and sequential ID generation.
//! - [`TreeMeta`] — static descriptor for a collection (name, key scheme, type, version).
//! - [`Db::open_typed_tree`] / [`Db::open_typed_map`] /
//! [`Db::open_zero_tree`] / [`Db::open_zero_map`] —
//! open a tree or map with automatic migration when the stored schema version
//! differs from [`TreeMeta::version`].
//! - [`Db::inspector`] — borrowed in-process read-only diagnostic API over
//! every collection opened through this [`Db`]. Does not require or alter RPC.
//! - [`Inspector`] — discovery, schema, raw key/value reads, counts, and bounded
//! scans. Authentication, redaction, JSON, and audit logging stay with the
//! application.
//! - [`RpcHandler`] — trait for handling binary RPC requests per collection.
//! Every collection opened through [`Db`] (`open_typed_tree`, `open_zero_map`,
//! `open_var_typed_tree`, `open_lsm_tree`, …) is registered on both the RPC
//! and Inspection surfaces automatically — no handler struct to write.
//! `RpcHandler` itself stays public so an application can still hand-write a
//! custom implementation, e.g. for a collection opened outside this `Db`.
//! - [`TreeMap`] — `Arc<HashMap<u64, Arc<dyn RpcHandler>>>` routing table
//! (key = `xxh3(name)`), built from every registered handler via
//! [`Db::build_tree_map`].
//!
//! # Read-only Inspector
//!
//! [`Db::inspector`] returns a borrowed [`Inspector`] tied to the owning `Db`.
//! Only collections opened through that `Db` are visible; directly opened
//! trees and maps are not registered.
//!
//! **Discovery** — [`Inspector::collections`] lists every registered collection
//! sorted by name with [`InspectionCollection`] metadata: [`InspectionSchema`]
//! (version, [`Typ`](armour_core::Typ), [`KeyScheme`](armour_core::KeyScheme),
//! key size, [`InspectionEncoding`](crate::InspectionEncoding)), storage class
//! ([`StorageClass`](armour_core::StorageClass)), optional cheap count,
//! [`ScanCapability`], and [`IterationDirection`] when ordered.
//! [`Inspector::key_group_bits`] reports the collection's key-routing group width.
//!
//! **Value encoding** — [`InspectionEncoding::Rapira`] means value bytes are
//! accepted by generic `DynValue` decoding for the collection [`Typ`](armour_core::Typ).
//! Zero collections may report `Rapira` on little-endian targets when the computed
//! fixed `Typ` width equals the stored value width; otherwise they report
//! [`InspectionEncoding::RawLayout`]. Keys are not part of this contract — they
//! are exposed as raw bytes via each collection's [`KeyScheme`](armour_core::KeyScheme).
//! [`InspectionEncoding::Opaque`] declares no generic decoder contract.
//!
//! ```no_run
//! # use armdb::armour::Inspector;
//! # fn example(inspector: &Inspector<'_>, name: &str, key: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
//! let schema = inspector.schema(name)?;
//! let entry = inspector.get(name, key)?.expect("present");
//! let value = armour_core::dyn_value::decode(&schema.typ, &entry.value)?;
//! let _ = value;
//! # Ok(())
//! # }
//! ```
//!
//! This does **not** promise that `rapira::deserialize::<ConcreteType>` succeeds.
//! Compatible Zero layouts may not implement `Rapira` at all, and DynValue decoding
//! intentionally differs from typed Rapira for some values (for example non-finite floats).
//!
//! **Counts** — [`CountMode::Current`] uses the handler's O(1) live-key counter
//! when available; [`CountMode::Exact`] performs a strict key-only scan that
//! includes unreadable values and fails on storage errors (Var/LSM paths
//! propagate failures instead of returning partial results).
//!
//! **Ordered scans** — [`Inspector::range`] and [`Inspector::prefix`] honor the
//! collection's byte order and configured direction. Pass the previous page's
//! `next_key` as `after` to continue in ascending or reversed order. Pagination
//! uses a one-row lookahead so `next_key` is set only when another row exists.
//! Pages are not a cross-shard or cross-page point-in-time snapshot.
//!
//! **Unordered snapshot** — [`Inspector::snapshot_unordered`] walks a
//! non-iterable Map in per-shard unspecified order; it is not a global snapshot.
//!
//! **Map iterability** — whether an iterable Map supports ordered scans is
//! decided at open time (`iterable(true)`); non-iterable Maps expose
//! [`ScanCapability::UnorderedSnapshot`] instead.
//!
//! Inspector exposes no mutation methods. See [`Db::inspector`] for
//! `compile_fail` boundary examples.
//!
//! # Quick start
//!
//! ```ignore
//! use armdb::armour::Db;
//! use armdb::{Config, NoHook, RapiraCodec};
//!
//! let db = Db::open("data/myapp")?;
//! // Opening a collection through `db` registers it on the RPC and
//! // Inspection surfaces — no handler to write or register by hand.
//! let tree = db.open_typed_tree::<User, RapiraCodec, _>(
//! Config::balanced().build(), NoHook, &[])?;
//!
//! // Start the RPC server. Each `listen_*` call builds its own routing table
//! // from every collection opened so far.
//! db.listen_tcp("127.0.0.1:9000");
//! db.listen_uds("/tmp/myapp.sock");
//! ```
//!
//! # RPC protocol
//!
//! Length-delimited frames over TCP or Unix socket. Each request carries an
//! opcode, a collection hashname (`xxh3` of the collection name), and an
//! operation-specific payload. See [`rpc`] module for codec details.
//!
//! Graceful shutdown: Ctrl-C sends a broadcast via `async_broadcast`;
//! all accept loops and active connections terminate.
pub
pub
pub use crate::;
pub use crate::;
pub use Collection;
pub use ;
pub use RpcHandler;
pub use ;
pub use ;
pub use TreeMap;
pub use SeqGen;
pub use TypedRpcClient;