icydb_core/db/response/
mod.rs1mod grouped;
10mod paged;
11
12#[cfg(test)]
13use crate::value::Value;
14use crate::{prelude::*, traits::EntityValue, types::Id, value::OutputValue};
15use thiserror::Error as ThisError;
16
17mod private {
18 pub trait Sealed {}
25}
26
27pub use grouped::{GroupedRow, PagedGroupedExecution, PagedGroupedExecutionWithTrace};
28pub use paged::{PagedLoadExecution, PagedLoadExecutionWithTrace};
29
30pub trait ResponseRow: private::Sealed {}
38
39impl ResponseRow for GroupedRow {}
40
41impl private::Sealed for GroupedRow {}
42
43#[derive(Clone, Debug, Eq, PartialEq)]
50pub struct Row<E: EntityKind> {
51 id: Id<E>,
52 entity: E,
53}
54
55impl<E: EntityKind> Row<E> {
56 #[must_use]
58 pub const fn new(id: Id<E>, entity: E) -> Self {
59 Self { id, entity }
60 }
61
62 #[must_use]
64 pub const fn id(&self) -> Id<E> {
65 self.id
66 }
67
68 #[must_use]
70 pub fn entity(self) -> E {
71 self.entity
72 }
73
74 #[must_use]
76 pub const fn entity_ref(&self) -> &E {
77 &self.entity
78 }
79
80 #[must_use]
82 pub fn into_id_and_entity(self) -> (Id<E>, E) {
83 (self.id, self.entity)
84 }
85}
86
87impl<E: EntityKind> From<(Id<E>, E)> for Row<E> {
88 fn from(value: (Id<E>, E)) -> Self {
89 Self::new(value.0, value.1)
90 }
91}
92
93impl<E: EntityKind> private::Sealed for Row<E> {}
94
95impl<E: EntityKind> ResponseRow for Row<E> {}
96
97#[derive(Clone, Debug, Eq, PartialEq)]
105pub struct ProjectedRow<E: EntityKind> {
106 id: Id<E>,
107 values: Vec<OutputValue>,
108}
109
110impl<E: EntityKind> ProjectedRow<E> {
111 #[must_use]
113 pub const fn new(id: Id<E>, values: Vec<OutputValue>) -> Self {
114 Self { id, values }
115 }
116
117 #[cfg(test)]
119 #[must_use]
120 pub(in crate::db) fn from_runtime_values(id: Id<E>, values: Vec<Value>) -> Self {
121 Self::new(id, values.into_iter().map(OutputValue::from).collect())
122 }
123
124 #[must_use]
126 pub const fn id(&self) -> Id<E> {
127 self.id
128 }
129
130 #[must_use]
132 pub const fn values(&self) -> &[OutputValue] {
133 self.values.as_slice()
134 }
135
136 #[must_use]
138 pub fn into_id_and_values(self) -> (Id<E>, Vec<OutputValue>) {
139 (self.id, self.values)
140 }
141}
142
143impl<E: EntityKind> private::Sealed for ProjectedRow<E> {}
144
145impl<E: EntityKind> ResponseRow for ProjectedRow<E> {}
146
147#[derive(Debug, ThisError)]
152pub enum ResponseError {
153 #[error("expected exactly one row, found 0 (entity {entity})")]
154 NotFound { entity: &'static str },
155
156 #[error("expected exactly one row, found {count} (entity {entity})")]
157 NotUnique { entity: &'static str, count: u32 },
158}
159
160impl ResponseError {
161 #[must_use]
163 pub const fn not_found(entity: &'static str) -> Self {
164 Self::NotFound { entity }
165 }
166
167 #[must_use]
169 pub const fn not_unique(entity: &'static str, count: u32) -> Self {
170 Self::NotUnique { entity, count }
171 }
172}
173
174#[derive(Debug)]
181pub struct Response<R: ResponseRow>(Vec<R>);
182
183pub type EntityResponse<E> = Response<Row<E>>;
190
191pub type ProjectionResponse<E> = Response<ProjectedRow<E>>;
198
199impl<R: ResponseRow> Response<R> {
200 #[must_use]
202 pub const fn new(rows: Vec<R>) -> Self {
203 Self(rows)
204 }
205
206 #[must_use]
208 pub const fn len(&self) -> usize {
209 self.0.len()
210 }
211
212 #[must_use]
214 #[expect(clippy::cast_possible_truncation)]
215 pub const fn count(&self) -> u32 {
216 self.0.len() as u32
217 }
218
219 #[must_use]
221 pub const fn is_empty(&self) -> bool {
222 self.0.is_empty()
223 }
224
225 #[must_use]
227 pub fn rows(self) -> Vec<R> {
228 self.0
229 }
230
231 #[must_use]
233 pub const fn as_slice(&self) -> &[R] {
234 self.0.as_slice()
235 }
236
237 pub fn iter(&self) -> std::slice::Iter<'_, R> {
239 self.0.iter()
240 }
241}
242
243impl<E: EntityKind> Response<Row<E>> {
244 #[must_use]
246 pub fn entities(self) -> Vec<E> {
247 self.0.into_iter().map(Row::entity).collect()
248 }
249
250 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_ {
252 self.0.iter().map(Row::id)
253 }
254
255 pub fn contains_id(&self, id: &Id<E>) -> bool {
257 self.0.iter().any(|row| row.id() == *id)
258 }
259}
260
261impl<R: ResponseRow> IntoIterator for Response<R> {
262 type Item = R;
263 type IntoIter = std::vec::IntoIter<Self::Item>;
264
265 fn into_iter(self) -> Self::IntoIter {
266 self.0.into_iter()
267 }
268}
269
270impl<'a, R: ResponseRow> IntoIterator for &'a Response<R> {
271 type Item = &'a R;
272 type IntoIter = std::slice::Iter<'a, R>;
273
274 fn into_iter(self) -> Self::IntoIter {
275 self.iter()
276 }
277}
278
279#[derive(Debug)]
287pub struct WriteBatchResponse<E> {
288 entities: Vec<E>,
289}
290
291impl<E> WriteBatchResponse<E> {
292 #[must_use]
294 pub const fn new(entities: Vec<E>) -> Self {
295 Self { entities }
296 }
297
298 #[must_use]
300 pub const fn len(&self) -> usize {
301 self.entities.len()
302 }
303
304 #[must_use]
306 pub const fn is_empty(&self) -> bool {
307 self.entities.is_empty()
308 }
309
310 #[must_use]
312 pub fn entities(self) -> Vec<E> {
313 self.entities
314 }
315
316 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_
318 where
319 E: EntityValue,
320 {
321 self.entities.iter().map(EntityValue::id)
322 }
323
324 pub fn iter(&self) -> std::slice::Iter<'_, E> {
326 self.entities.iter()
327 }
328}
329
330impl<E> IntoIterator for WriteBatchResponse<E> {
331 type Item = E;
332 type IntoIter = std::vec::IntoIter<E>;
333
334 fn into_iter(self) -> Self::IntoIter {
335 self.entities.into_iter()
336 }
337}
338
339impl<'a, E> IntoIterator for &'a WriteBatchResponse<E> {
340 type Item = &'a E;
341 type IntoIter = std::slice::Iter<'a, E>;
342
343 fn into_iter(self) -> Self::IntoIter {
344 self.iter()
345 }
346}