1#![doc = include_str!("../README.md")]
2
3use std::{convert::Infallible, marker::PhantomData};
4
5pub mod codec;
6mod database;
7mod error;
8mod keyspace;
9pub(crate) mod txn;
10
11pub use database::Database;
12pub use error::Error;
13pub use fjall::KeyspaceCreateOptions;
14pub use keyspace::Keyspace;
15pub use txn::{Readable, Rtxn, Wtxn};
16
17pub use byteorder;
18
19pub struct Guard<Key, Value>(fjall::Guard, PhantomData<(Key, Value)>);
21
22impl<Key, Value> Guard<Key, Value> {
23 #[inline]
24 pub(crate) fn new(guard: fjall::Guard) -> Self {
25 Self(guard, PhantomData)
26 }
27
28 #[inline]
30 #[must_use]
31 pub fn remap_key_type<NKey>(self) -> Guard<NKey, Value> {
32 Guard(self.0, PhantomData)
33 }
34
35 #[inline]
37 #[must_use]
38 pub fn remap_value_type<NValue>(self) -> Guard<Key, NValue> {
39 Guard(self.0, PhantomData)
40 }
41
42 #[inline]
44 #[must_use]
45 pub fn remap_types<NKey, NValue>(self) -> Guard<NKey, NValue> {
46 Guard(self.0, PhantomData)
47 }
48
49 #[inline]
51 #[must_use]
52 pub fn size(self) -> Result<u32, fjall::Error> {
53 self.0.size()
54 }
55}
56
57impl<Key: codec::Decode, Value> Guard<Key, Value> {
58 #[inline]
60 #[must_use]
61 pub fn key(self) -> Result<Key::Item, Error<Key::Error, Infallible>> {
62 let key = self.0.key().map_err(Error::Fjall)?;
63 Key::decode(key).map_err(Error::Key)
64 }
65}
66
67impl<Key, Value: codec::Decode> Guard<Key, Value> {
68 #[inline]
70 #[must_use]
71 pub fn value(self) -> Result<Value::Item, Error<Infallible, Value::Error>> {
72 let value = self.0.value().map_err(Error::Fjall)?;
73 Value::decode(value).map_err(Error::Value)
74 }
75}
76
77impl<Key: codec::Decode, Value: codec::Decode> Guard<Key, Value> {
78 #[inline]
80 #[must_use]
81 pub fn into_inner(self) -> Result<(Key::Item, Value::Item), Error<Key::Error, Value::Error>> {
82 let (k, v) = self.0.into_inner().map_err(Error::Fjall)?;
83 Ok((
84 Key::decode(k).map_err(Error::Key)?,
85 Value::decode(v).map_err(Error::Value)?,
86 ))
87 }
88}
89
90pub struct Iter<Key, Value>(fjall::Iter, PhantomData<(Key, Value)>);
92
93impl<Key, Value> Iter<Key, Value> {
94 #[inline]
95 pub(crate) fn new(iter: fjall::Iter) -> Self {
96 Self(iter, PhantomData)
97 }
98
99 #[inline]
101 pub fn remap_key_type<NKey>(self) -> Iter<NKey, Value> {
102 Iter(self.0, PhantomData)
103 }
104
105 #[inline]
107 pub fn remap_value_type<NValue>(self) -> Iter<Key, NValue> {
108 Iter(self.0, PhantomData)
109 }
110
111 #[inline]
113 pub fn remap_types<NKey, NValue>(self) -> Iter<NKey, NValue> {
114 Iter(self.0, PhantomData)
115 }
116}
117
118impl<Key, Value> Iterator for Iter<Key, Value> {
119 type Item = Guard<Key, Value>;
120
121 #[inline]
122 fn next(&mut self) -> Option<Self::Item> {
123 self.0.next().map(Guard::new)
124 }
125}
126
127impl<Key, Value> DoubleEndedIterator for Iter<Key, Value> {
128 #[inline]
129 fn next_back(&mut self) -> Option<Self::Item> {
130 self.0.next_back().map(Guard::new)
131 }
132}
133
134#[cfg(test)]
135mod test {
136 use fjall::KeyspaceCreateOptions;
137
138 use crate::{codec::Str, Database};
139
140 #[test]
141 fn get_from_wtxn() {
142 let dir = tempfile::tempdir().unwrap();
143 let database = Database::builder(&dir.path()).unwrap();
144 let ks = database
145 .keyspace::<Str, Str>("hello", || KeyspaceCreateOptions::default())
146 .unwrap();
147
148 let rtxn = database.read_tx();
150 ks.get(&rtxn, "hello").unwrap();
151 let wtxn = database.write_tx().unwrap();
152 ks.get(&wtxn, "hello").unwrap();
153 drop(wtxn);
154 }
155}