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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//! **--> /!\ Important Update: This crate `struct_db` has been renamed to [`native_db`](https://crates.io/crates/native_db) to better reflect its functionality and purpose. Please update your dependencies to use [`native_db`](https://crates.io/crates/native_db) for the latest features and updates. <--**
//!
//! Struct DB is a Rust library that provides a simple, fast, and embedded database solution,
//! focusing on maintaining coherence between Rust types and stored data with minimal boilerplate.
//! It supports multiple indexes, real-time watch with filters, schema migration.
//!
//! Use macro `struct_db`:
//!
//! - required: `fn_primary_key(<function name>)` associates a function of the struct that generates the **primary key** of the struct. Allows **only one** `fn_primary_key` declaration.
//! - optional: `fn_secondary_key(<function name>)` associates a function of the struct that generates a **secondary key** of the struct. Allows **multiple** `fn_secondary_key` declarations.
//!
//! `struct_db` generates an enum `<your_type>` with the suffix `Key` that contains all the secondary keys like: E.g. `<your_type>Key::<your_secondary_key>` more details [`here`](crate::ReadableTable::secondary_get).
//!
//! ## API
//! - Initialize a database:
//! - [`Db::init_tmp(<database name>)`](crate::Db::create_tmp) initializes a database at a temporary path.
//! - [`Db::init(<path>)`](crate::Db::create) initializes a database at a given path.
//! - Define schema
//! - [`db.define::<your_type>()`](crate::Db::define) initializes a schema.
//! - Transactions
//! - [`db.transaction()`](crate::Db::transaction) starts a [`read-write transaction`](crate::Transaction).
//! - [`db.read_transaction()`](crate::Db::read_transaction) starts a [`read-only transaction`](crate::ReadOnlyTransaction).
//! - Tables (`txn` is a [`Transaction`](crate::Transaction) and `read_only_txn` a [`ReadOnlyTransaction`](crate::ReadOnlyTransaction))
//! - [`txn.tables()`](crate::Transaction::tables) returns a [`Tables`](crate::Tables)
//! - [`read_only_txn.tables()`](crate::ReadOnlyTransaction::tables) returns a [`ReadOnlyTables`](crate::ReadOnlyTables).
//! - Write operations
//! - [`tables.insert(&txn,<item>)`](crate::Tables::insert) inserts an item into the database.
//! - [`tables.update(&txn,<old_item>, <new_item>)`](crate::Tables::update) updates an item in the database.
//! - [`tables.remove(&txn,<item>)`](crate::Tables::remove) removes an item from the database.
//! - [`tables.migrate::<old_type, new_type>(&txn)`](crate::Tables::migrate) migrates the schema from `old_type` to `new_type`.
//! - Read operations
//! - Primary key
//! - [`tables.primary_get(&txn,<key>)`](crate::ReadableTable::primary_get) get an item.
//! - [`tables.primary_iter(&txn)`](crate::ReadableTable::primary_iter) iterate all items.
//! - [`tables.primary_iter_range(&txn,<start_key>..<end_key>)`](crate::ReadableTable::primary_iter_range) all items in range.
//! - [`tables.primary_iter_start_with(&txn,<key_prefix>)`](crate::ReadableTable::primary_iter_start_with) all items with prefix.
//! - Secondary key
//! - [`tables.secondary_get(&txn,<key_def>,<key>)`](crate::ReadableTable::secondary_get) get an item.
//! - [`tables.secondary_iter(&txn,<key_def>,<key_def>)`](crate::ReadableTable::secondary_iter) iterate all items.
//! - [`tables.secondary_iter_range(&txn,<key_def>,<start_key>..<end_key>)`](crate::ReadableTable::secondary_iter_range) all items in range.
//! - [`tables.secondary_iter_start_with(&txn,<key_def>,<key_prefix>)`](crate::ReadableTable::secondary_iter_start_with) all items with prefix.
//! - Global
//! - [`tables.len::<your_type>()`](crate::ReadableTable::len)
//! - Watch (details [`here`](crate::Db::primary_watch))
//! - Primary key
//! - [`db.primary_watch(Option<key>)`](crate::Db::primary_watch) watch all or a specific item.
//! - [`db.primary_watch_start_with(<key_prefix>)`](crate::Db::primary_watch_start_with) watch all items with prefix.
//! - Secondary key
//! - [`db.secondary_watch(<key_def>,Option<key>)`](crate::Db::secondary_watch) watch all or a specific item.
//! - [`db.secondary_watch_start_with(<key_def>,<key_prefix>)`](crate::Db::secondary_watch_start_with) watch all items with prefix.
//! - Global
//! - [`db.unwatch(<watcher_id>)`](crate::Db::unwatch) stop watching a specific watcher.
//! # Example
//! ```
//! use serde::{Deserialize, Serialize};
//! use struct_db::*;
//!
//! #[derive(Serialize, Deserialize, PartialEq, Debug)]
//! #[struct_db(
//! fn_primary_key(p_key), // required
//! fn_secondary_key(s_key), // optional
//! // ... other fn_secondary_key ...
//! )]
//! struct Data(u32, String);
//!
//! impl Data {
//! // Returns primary key as big-endian bytes for consistent lexicographical ordering.
//! pub fn p_key(&self) -> Vec<u8> {
//! self.0.to_be_bytes().to_vec()
//! }
//!
//! // Generates a secondary key combining the String field and the big-endian bytes of
//! // the primary key for versatile queries.
//! pub fn s_key(&self) -> Vec<u8> {
//! let mut s_key = self.1.as_bytes().to_vec();
//! s_key.extend_from_slice(&self.p_key().as_slice());
//! s_key
//! }
//! }
//!
//! fn main() {
//! let mut db = Db::create_tmp("my_db_example").unwrap();
//! // Initialize the schema
//! db.define::<Data>();
//!
//! // Insert data
//! let txn = db.transaction().unwrap();
//! {
//! let mut tables = txn.tables();
//! tables.insert(&txn, Data(1,"red".to_string())).unwrap();
//! tables.insert(&txn, Data(2,"red".to_string())).unwrap();
//! tables.insert(&txn, Data(3,"blue".to_string())).unwrap();
//! }
//! txn.commit().unwrap();
//!
//! let txn_read = db.read_transaction().unwrap();
//! let mut tables = txn_read.tables();
//!
//! // Retrieve data with p_key=3
//! let retrieve_data: Data = tables.primary_get(&txn_read, &3_u32.to_be_bytes()).unwrap().unwrap();
//! println!("data p_key='3' : {:?}", retrieve_data);
//!
//! // Iterate data with s_key="red" String
//! for item in tables.secondary_iter_start_with::<Data>(&txn_read, DataKey::s_key, "red".as_bytes()).unwrap() {
//! println!("data s_key='1': {:?}", item);
//! }
//!
//! // Remove data
//! let txn = db.transaction().unwrap();
//! {
//! let mut tables = txn.tables();
//! tables.remove(&txn, retrieve_data).unwrap();
//! }
//! txn.commit().unwrap();
//! }
//! ```
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
use Error;
pub type Result<T> = Result;