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};
15
16mod private {
17 pub trait Sealed {}
24}
25
26pub use grouped::{GroupedRow, PagedGroupedExecution, PagedGroupedExecutionWithTrace};
27pub use paged::{PagedLoadExecution, PagedLoadExecutionWithTrace};
28
29pub trait ResponseRow: private::Sealed {}
37
38impl ResponseRow for GroupedRow {}
39
40impl private::Sealed for GroupedRow {}
41
42#[derive(Clone, Debug, Eq, PartialEq)]
49pub struct Row<E: EntityKind> {
50 id: Id<E>,
51 entity: E,
52}
53
54impl<E: EntityKind> Row<E> {
55 #[must_use]
57 pub const fn new(id: Id<E>, entity: E) -> Self {
58 Self { id, entity }
59 }
60
61 #[must_use]
63 pub const fn id(&self) -> Id<E> {
64 self.id
65 }
66
67 #[must_use]
69 pub fn entity(self) -> E {
70 self.entity
71 }
72
73 #[must_use]
75 pub const fn entity_ref(&self) -> &E {
76 &self.entity
77 }
78
79 #[must_use]
81 pub fn into_id_and_entity(self) -> (Id<E>, E) {
82 (self.id, self.entity)
83 }
84}
85
86impl<E: EntityKind> From<(Id<E>, E)> for Row<E> {
87 fn from(value: (Id<E>, E)) -> Self {
88 Self::new(value.0, value.1)
89 }
90}
91
92impl<E: EntityKind> private::Sealed for Row<E> {}
93
94impl<E: EntityKind> ResponseRow for Row<E> {}
95
96#[derive(Clone, Debug, Eq, PartialEq)]
104pub struct ProjectedRow<E: EntityKind> {
105 id: Id<E>,
106 values: Vec<OutputValue>,
107}
108
109impl<E: EntityKind> ProjectedRow<E> {
110 #[must_use]
112 pub const fn new(id: Id<E>, values: Vec<OutputValue>) -> Self {
113 Self { id, values }
114 }
115
116 #[cfg(test)]
118 #[must_use]
119 pub(in crate::db) fn from_runtime_values(id: Id<E>, values: Vec<Value>) -> Self {
120 Self::new(id, values.into_iter().map(OutputValue::from).collect())
121 }
122
123 #[must_use]
125 pub const fn id(&self) -> Id<E> {
126 self.id
127 }
128
129 #[must_use]
131 pub const fn values(&self) -> &[OutputValue] {
132 self.values.as_slice()
133 }
134
135 #[must_use]
137 pub fn into_id_and_values(self) -> (Id<E>, Vec<OutputValue>) {
138 (self.id, self.values)
139 }
140}
141
142impl<E: EntityKind> private::Sealed for ProjectedRow<E> {}
143
144impl<E: EntityKind> ResponseRow for ProjectedRow<E> {}
145
146#[derive(Debug)]
151pub enum ResponseError {
152 NotFound { entity: &'static str },
153
154 NotUnique { entity: &'static str, count: u32 },
155}
156
157impl ResponseError {
158 #[must_use]
160 pub const fn not_found(entity: &'static str) -> Self {
161 Self::NotFound { entity }
162 }
163
164 #[must_use]
166 pub const fn not_unique(entity: &'static str, count: u32) -> Self {
167 Self::NotUnique { entity, count }
168 }
169}
170
171#[derive(Debug)]
178pub struct Response<R: ResponseRow>(Vec<R>);
179
180pub type EntityResponse<E> = Response<Row<E>>;
187
188pub type ProjectionResponse<E> = Response<ProjectedRow<E>>;
195
196impl<R: ResponseRow> Response<R> {
197 #[must_use]
199 pub const fn new(rows: Vec<R>) -> Self {
200 Self(rows)
201 }
202
203 #[must_use]
205 pub const fn len(&self) -> usize {
206 self.0.len()
207 }
208
209 #[must_use]
211 #[expect(clippy::cast_possible_truncation)]
212 pub const fn count(&self) -> u32 {
213 self.0.len() as u32
214 }
215
216 #[must_use]
218 pub const fn is_empty(&self) -> bool {
219 self.0.is_empty()
220 }
221
222 #[must_use]
224 pub fn rows(self) -> Vec<R> {
225 self.0
226 }
227
228 #[must_use]
230 pub const fn as_slice(&self) -> &[R] {
231 self.0.as_slice()
232 }
233
234 pub fn iter(&self) -> std::slice::Iter<'_, R> {
236 self.0.iter()
237 }
238}
239
240impl<E: EntityKind> Response<Row<E>> {
241 #[must_use]
243 pub fn entities(self) -> Vec<E> {
244 self.0.into_iter().map(Row::entity).collect()
245 }
246
247 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_ {
249 self.0.iter().map(Row::id)
250 }
251
252 pub fn contains_id(&self, id: &Id<E>) -> bool {
254 self.0.iter().any(|row| row.id() == *id)
255 }
256}
257
258impl<R: ResponseRow> IntoIterator for Response<R> {
259 type Item = R;
260 type IntoIter = std::vec::IntoIter<Self::Item>;
261
262 fn into_iter(self) -> Self::IntoIter {
263 self.0.into_iter()
264 }
265}
266
267impl<'a, R: ResponseRow> IntoIterator for &'a Response<R> {
268 type Item = &'a R;
269 type IntoIter = std::slice::Iter<'a, R>;
270
271 fn into_iter(self) -> Self::IntoIter {
272 self.iter()
273 }
274}
275
276#[derive(Debug)]
284pub struct WriteBatchResponse<E> {
285 entities: Vec<E>,
286}
287
288impl<E> WriteBatchResponse<E> {
289 #[must_use]
291 pub const fn new(entities: Vec<E>) -> Self {
292 Self { entities }
293 }
294
295 #[must_use]
297 pub const fn len(&self) -> usize {
298 self.entities.len()
299 }
300
301 #[must_use]
303 pub const fn is_empty(&self) -> bool {
304 self.entities.is_empty()
305 }
306
307 #[must_use]
309 pub fn entities(self) -> Vec<E> {
310 self.entities
311 }
312
313 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_
315 where
316 E: EntityValue,
317 {
318 self.entities.iter().map(EntityValue::id)
319 }
320
321 pub fn iter(&self) -> std::slice::Iter<'_, E> {
323 self.entities.iter()
324 }
325}
326
327impl<E> IntoIterator for WriteBatchResponse<E> {
328 type Item = E;
329 type IntoIter = std::vec::IntoIter<E>;
330
331 fn into_iter(self) -> Self::IntoIter {
332 self.entities.into_iter()
333 }
334}
335
336impl<'a, E> IntoIterator for &'a WriteBatchResponse<E> {
337 type Item = &'a E;
338 type IntoIter = std::slice::Iter<'a, E>;
339
340 fn into_iter(self) -> Self::IntoIter {
341 self.iter()
342 }
343}