1#![warn(clippy::unwrap_used)]
2#![cfg_attr(not(feature = "std"), no_std)]
3#[cfg_attr(not(feature = "std"), macro_use)]
4#[cfg(not(feature = "std"))]
5extern crate alloc;
6
7#[macro_use]
8extern crate tracing;
9#[macro_use]
10extern crate metrics;
11
12pub use armour_derive::*;
13pub use async_broadcast::RecvError;
14pub use cid::{Cid, KeyScheme, KeyType, key_size};
15#[cfg(feature = "sled")]
16pub use database::{db::Database, raw_tree::RawTree, tree::CollectionTree};
17pub use dyn_types::{Typ, get_type::GetType, value::Value};
18pub use error::{DbError, DbResult};
19#[cfg(feature = "fjall")]
20pub use fjall::{self, Slice};
21pub use indexes::index::{CompositionIndex, HashIndexExtractor};
22pub use rapira;
23pub use record::{Migration, Record};
24#[cfg(feature = "sled")]
25pub use sled::{self, InlineArray};
26#[cfg(feature = "fjall")]
27pub use transactional::{db::TxDb, raw::TxRawTree, tree::TxTree};
28pub use types::{entry::Entry, fuid::Fuid, id64::Id64, record_status::RecordStatus};
29#[cfg(all(feature = "sled", feature = "id32"))]
30pub use types::{ident::ID, low_id::LowId, uid::Uid};
31
32#[cfg(feature = "bytemuck")]
33pub use crate::database::byte_as_slice::BytesAsValSlice;
34
35pub mod cid;
36#[cfg(feature = "sled")]
37pub mod database;
38pub mod dyn_types;
39pub mod error;
40pub mod indexes;
41#[cfg(feature = "fjall")]
42pub mod logdb;
43pub mod record;
44pub mod replication;
45#[cfg(feature = "fjall")]
46pub mod transactional;
47pub mod types;
48pub mod utils;
49
50pub mod migrations {
51 pub use crate::record::{MigrationRes, MigrationType};
52}
53
54pub type KV<K, V> = (K, V);
55
56#[macro_export]
62macro_rules! const_hasher {
63 ($m_name: ident, $key_name: literal) => {
64 pub mod $m_name {
65 use $crate::types::enc::{Cipher, IdHasher};
66
67 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy, Hash)]
68 pub struct Hasher;
69
70 impl IdHasher for Hasher {
71 const HASHER: Cipher = Cipher::new(env!(concat!("APP_ID_KEY_", $key_name)));
72 }
73 }
74 };
75}
76
77#[macro_export]
81macro_rules! hasher {
82 ($m_name: ident, $key: literal) => {
83 pub mod $m_name {
84 use $crate::types::enc::{Cipher, IdHasher};
85
86 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy, Hash)]
87 pub struct Hasher;
88
89 impl IdHasher for Hasher {
90 const HASHER: Cipher = Cipher::new($key);
91 }
92 }
93 };
94}
95
96#[macro_export]
98macro_rules! rapira_record {
99 ($ty: ty, $id_ty: ty, $value_ty: ty, $name: literal) => {
100 impl $crate::Record for $ty {
101 type SelfId = $id_ty;
102 type Value = $value_ty;
103 const NAME: &'static str = $name;
104 fn deser(bytes: &Self::Value) -> Self {
105 rapira::deserialize(bytes.as_ref()).unwrap()
106 }
107 fn ser(&self) -> $value_ty {
108 rapira::serialize(self).into()
109 }
110 }
111 };
112}
113
114#[macro_export]
116macro_rules! zerocopy_record {
117 ($ty: ty, $id_ty: ty, $value_ty: ty, $name: literal) => {
118 const SIZE: usize = std::mem::size_of::<$ty>();
119 impl $crate::Record for $ty {
120 type SelfId = $id_ty;
121 type Value = $value_ty;
122 const NAME: &'static str = $name;
123 fn deser(bytes: &Self::Value) -> Self {
124 let bytes: &[u8] = bytes.as_ref();
125 let bytes: [u8; SIZE] = bytes.try_into().unwrap();
126 zerocopy::transmute!(bytes)
127 }
128 fn ser(&self) -> $value_ty {
129 let bytes: &[u8; SIZE] = zerocopy::transmute_ref!(self);
130 bytes.into()
131 }
132 }
133 };
134}
135
136#[macro_export]
138macro_rules! bytemuck_slice_record {
139 ($ty: ty, $id_ty: ty, $value_ty: ty, $name: literal) => {
140 impl $crate::Record for $ty {
141 type SelfId = $id_ty;
142 type Value = $value_ty;
143 const NAME: &'static str = $name;
144 fn deser(bytes: &Self::Value) -> Self {
145 if bytes.is_empty() {
146 return Default::default();
147 }
148 let vec = bytes.as_ref().to_vec();
149 let vec: Vec<ProfileId> = bytemuck::cast_vec(vec);
150 Self(vec)
151 }
152 fn ser(&self) -> $value_ty {
153 let bytes: &[u8] = bytemuck::cast_slice(self);
154 bytes.to_vec().into()
155 }
156 }
157 };
158}
159
160#[macro_export]
162macro_rules! zerocopy_cid {
163 ($ty: ty, [$($key_type:expr),*], $group_bits:expr, $field:ident) => {
164 impl $crate::Cid for $ty {
165 type B = [u8; size_of::<Self>()];
166 const TY: $crate::KeyScheme = $crate::KeyScheme::Typed(&[$($key_type),*]);
167 const GROUP_BITS: u32 = $group_bits;
168 fn encode(&self) -> Self::B {
169 zerocopy::transmute!(*self)
170 }
171 fn decode(bytes: &Self::B) -> armour::types::Result<Self> {
172 Ok(zerocopy::transmute!(*bytes))
173 }
174 fn group_id(&self) -> u32 {
175 self.$field.group_id()
176 }
177 }
178 };
179}
180
181#[cfg(test)]
182mod tests {
183 use rapira::Rapira;
184
185 use super::*;
186 use crate::types::id64::Id64;
187
188 #[derive(Clone, Rapira)]
189 struct User {
190 name: String,
191 }
192
193 impl GetType for User {
194 const TYPE: Typ = Typ::Custom("unimplemented", &[]);
195 }
196
197 const_hasher!(test_key, "TEST");
198 type UserID = Id64<test_key::Hasher>;
199 rapira_record!(User, UserID, Vec<u8>, "users");
200
201 #[test]
202 fn test_rapira_record() {
203 let _user = User {
204 name: "John Doe".to_string(),
205 };
206 }
207}