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