rust_rocksdb/
db_pinnable_batch.rs1use crate::{Error, ffi};
2use std::{
3 marker::PhantomData,
4 ptr::{self, NonNull},
5 slice,
6};
7
8pub struct DBPinnableBatch<'db> {
15 inner: NonNull<ffi::rust_rocksdb_pinnable_batch_t>,
16 len: usize,
17 db: PhantomData<&'db ()>,
18}
19
20pub struct DBPinnableBatchIter<'batch, 'db> {
22 batch: &'batch DBPinnableBatch<'db>,
23 index: usize,
24}
25
26unsafe impl Send for DBPinnableBatch<'_> {}
27unsafe impl Sync for DBPinnableBatch<'_> {}
28
29impl<'db> DBPinnableBatch<'db> {
30 #[inline]
32 pub fn len(&self) -> usize {
33 self.len
34 }
35
36 #[inline]
38 pub fn is_empty(&self) -> bool {
39 self.len() == 0
40 }
41
42 pub fn get(&self, index: usize) -> Option<Result<Option<&[u8]>, Error>> {
44 if index >= self.len() {
45 return None;
46 }
47
48 let mut value = ptr::null();
49 let mut value_len = 0;
50 let mut error = ptr::null();
51 let mut error_len = 0;
52 let state = unsafe {
53 ffi::rust_rocksdb_pinnable_batch_get(
54 self.inner.as_ptr(),
55 index,
56 &raw mut value,
57 &raw mut value_len,
58 &raw mut error,
59 &raw mut error_len,
60 )
61 };
62
63 Some(match state {
64 state if state == ffi::rust_rocksdb_pinnable_batch_not_found as u8 => Ok(None),
65 state if state == ffi::rust_rocksdb_pinnable_batch_found as u8 => {
66 let value = if value_len == 0 {
67 &[]
68 } else {
69 unsafe { slice::from_raw_parts(value.cast::<u8>(), value_len) }
71 };
72 Ok(Some(value))
73 }
74 state if state == ffi::rust_rocksdb_pinnable_batch_error as u8 => {
75 let message = if error_len == 0 {
76 String::new()
77 } else {
78 let bytes = unsafe { slice::from_raw_parts(error.cast::<u8>(), error_len) };
80 String::from_utf8_lossy(bytes).into_owned()
81 };
82 Err(Error::new(message))
83 }
84 unexpected => Err(Error::new(format!(
90 "unexpected pinned batch result state {unexpected} at index {index}"
91 ))),
92 })
93 }
94
95 pub fn iter(&self) -> DBPinnableBatchIter<'_, 'db> {
97 DBPinnableBatchIter {
98 batch: self,
99 index: 0,
100 }
101 }
102
103 pub(crate) unsafe fn from_c(inner: *mut ffi::rust_rocksdb_pinnable_batch_t) -> Self {
104 let inner = NonNull::new(inner).expect("RocksDB returned a null pinned batch");
105 Self {
106 len: unsafe { ffi::rust_rocksdb_pinnable_batch_len(inner.as_ptr()) },
107 inner,
108 db: PhantomData,
109 }
110 }
111}
112
113impl Drop for DBPinnableBatch<'_> {
114 fn drop(&mut self) {
115 unsafe {
116 ffi::rust_rocksdb_pinnable_batch_destroy(self.inner.as_ptr());
117 }
118 }
119}
120
121impl<'batch> IntoIterator for &'batch DBPinnableBatch<'_> {
122 type Item = Result<Option<&'batch [u8]>, Error>;
123 type IntoIter = DBPinnableBatchIter<'batch, 'batch>;
124
125 fn into_iter(self) -> Self::IntoIter {
126 self.iter()
127 }
128}
129
130impl<'batch> Iterator for DBPinnableBatchIter<'batch, '_> {
131 type Item = Result<Option<&'batch [u8]>, Error>;
132
133 fn next(&mut self) -> Option<Self::Item> {
134 let result = self.batch.get(self.index)?;
135 self.index += 1;
136 Some(result)
137 }
138
139 fn size_hint(&self) -> (usize, Option<usize>) {
140 let remaining = self.batch.len() - self.index;
141 (remaining, Some(remaining))
142 }
143}
144
145impl ExactSizeIterator for DBPinnableBatchIter<'_, '_> {}
146impl std::iter::FusedIterator for DBPinnableBatchIter<'_, '_> {}