1use std::ffi::c_void;
2use std::marker::PhantomData;
3use std::ptr;
4
5use crate::db::Db;
6use crate::ffi::*;
7use crate::record::{Record, RecordRef};
8use crate::{Error, ensure_init};
9
10pub struct Rset<'a> {
11 ptr: rec_rset_t,
12 _marker: PhantomData<&'a mut Db>,
13}
14
15impl<'a> Rset<'a> {
16 pub(crate) fn from_raw(ptr: rec_rset_t) -> Self {
17 Rset { ptr, _marker: PhantomData }
18 }
19
20 pub fn num_records(&self) -> usize {
21 unsafe { rec_rset_num_records(self.ptr) }
22 }
23
24 pub fn descriptor(&self) -> Option<RecordRef<'_>> {
28 let p = unsafe { rec_rset_descriptor(self.ptr) };
29 (!p.is_null()).then(|| RecordRef::from_raw(p))
30 }
31
32 pub fn records(&self) -> Records<'_> {
33 let iter = unsafe { rec_mset_iterator(rec_rset_mset(self.ptr)) };
34 Records { iter, done: false, _marker: PhantomData }
35 }
36
37 pub fn remove_matching<F>(&mut self, mut pred: F) -> usize
40 where
41 F: FnMut(&RecordRef<'_>) -> bool,
42 {
43 let mset = unsafe { rec_rset_mset(self.ptr) };
44 let mut to_remove: Vec<usize> = Vec::new();
45 let mut iter = unsafe { rec_mset_iterator(mset) };
46 let mut idx: usize = 0;
47 loop {
48 let mut data: *const c_void = ptr::null();
49 let advanced = unsafe {
50 rec_mset_iterator_next(
51 &mut iter,
52 MSET_RECORD as rec_mset_type_t,
53 &mut data,
54 ptr::null_mut(),
55 )
56 };
57 if !advanced {
58 break;
59 }
60 let r = RecordRef::from_raw(data as rec_record_t);
61 if pred(&r) {
62 to_remove.push(idx);
63 }
64 idx += 1;
65 }
66 unsafe { rec_mset_iterator_free(&mut iter) };
67
68 let n = to_remove.len();
69 for pos in to_remove.into_iter().rev() {
70 unsafe { rec_mset_remove_at(mset, MSET_RECORD as rec_mset_type_t, pos) };
71 }
72 n
73 }
74
75 pub fn append_record(&mut self, record: Record) -> Result<(), Error> {
76 let raw = record.into_raw();
77 let elem = unsafe {
78 rec_mset_append(
79 rec_rset_mset(self.ptr),
80 MSET_RECORD as rec_mset_type_t,
81 raw as *mut c_void,
82 MSET_RECORD as rec_mset_type_t,
83 )
84 };
85 if elem.is_null() {
86 unsafe { rec_record_destroy(raw) };
87 return Err(Error::new("rec_mset_append (record) failed"));
88 }
89 Ok(())
90 }
91}
92
93pub struct Records<'a> {
94 iter: rec_mset_iterator_t,
95 done: bool,
96 _marker: PhantomData<&'a Rset<'a>>,
97}
98
99impl<'a> Iterator for Records<'a> {
100 type Item = RecordRef<'a>;
101
102 fn next(&mut self) -> Option<Self::Item> {
103 if self.done {
104 return None;
105 }
106 let mut data: *const c_void = ptr::null();
107 let advanced = unsafe {
108 rec_mset_iterator_next(
109 &mut self.iter,
110 MSET_RECORD as rec_mset_type_t,
111 &mut data,
112 ptr::null_mut(),
113 )
114 };
115 if !advanced {
116 self.done = true;
117 return None;
118 }
119 Some(RecordRef::from_raw(data as rec_record_t))
120 }
121}
122
123impl<'a> Drop for Records<'a> {
124 fn drop(&mut self) {
125 unsafe { rec_mset_iterator_free(&mut self.iter) }
126 }
127}
128
129pub struct OwnedRset {
133 ptr: rec_rset_t,
134}
135
136impl OwnedRset {
137 pub fn new() -> Self {
138 ensure_init();
139 let ptr = unsafe { rec_rset_new() };
140 assert!(!ptr.is_null(), "rec_rset_new returned NULL");
141 OwnedRset { ptr }
142 }
143
144 pub fn set_descriptor(&mut self, record: Record) {
148 let raw = record.into_raw();
149 unsafe { rec_rset_set_descriptor(self.ptr, raw) };
150 }
151
152 pub fn append_record(&mut self, record: Record) -> Result<(), Error> {
153 let raw = record.into_raw();
154 let elem = unsafe {
155 rec_mset_append(
156 rec_rset_mset(self.ptr),
157 MSET_RECORD as rec_mset_type_t,
158 raw as *mut c_void,
159 MSET_RECORD as rec_mset_type_t,
160 )
161 };
162 if elem.is_null() {
163 unsafe { rec_record_destroy(raw) };
164 return Err(Error::new("rec_mset_append (record) failed"));
165 }
166 Ok(())
167 }
168
169 pub(crate) fn into_raw(self) -> rec_rset_t {
170 let ptr = self.ptr;
171 std::mem::forget(self);
172 ptr
173 }
174}
175
176impl Default for OwnedRset {
177 fn default() -> Self {
178 OwnedRset::new()
179 }
180}
181
182impl Drop for OwnedRset {
183 fn drop(&mut self) {
184 unsafe { rec_rset_destroy(self.ptr) }
185 }
186}