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