icydb_core/db/response/
mod.rs1mod grouped;
10mod paged;
11mod private;
12
13use crate::{
14 db::data::{DataRow, decode_data_rows_into_entity_response},
15 prelude::*,
16 traits::{AsView, EntityValue},
17 types::Id,
18 value::Value,
19};
20use thiserror::Error as ThisError;
21
22pub use grouped::{GroupedRow, PagedGroupedExecution, PagedGroupedExecutionWithTrace};
23pub use paged::{PagedLoadExecution, PagedLoadExecutionWithTrace};
24
25pub trait ResponseRow: private::Sealed {}
33
34impl ResponseRow for GroupedRow {}
35
36impl private::Sealed for GroupedRow {}
37
38#[derive(Clone, Debug, Eq, PartialEq)]
45pub struct Row<E: EntityKind> {
46 id: Id<E>,
47 entity: E,
48}
49
50impl<E: EntityKind> Row<E> {
51 #[must_use]
53 pub const fn new(id: Id<E>, entity: E) -> Self {
54 Self { id, entity }
55 }
56
57 #[must_use]
59 pub const fn id(&self) -> Id<E> {
60 self.id
61 }
62
63 #[must_use]
65 pub fn entity(self) -> E {
66 self.entity
67 }
68
69 #[must_use]
71 pub const fn entity_ref(&self) -> &E {
72 &self.entity
73 }
74
75 #[must_use]
77 pub fn into_parts(self) -> (Id<E>, E) {
78 (self.id, self.entity)
79 }
80}
81
82impl<E: EntityKind> From<(Id<E>, E)> for Row<E> {
83 fn from(value: (Id<E>, E)) -> Self {
84 Self::new(value.0, value.1)
85 }
86}
87
88impl<E: EntityKind> private::Sealed for Row<E> {}
89
90impl<E: EntityKind> ResponseRow for Row<E> {}
91
92#[derive(Clone, Debug, Eq, PartialEq)]
100pub struct ProjectedRow<E: EntityKind> {
101 id: Id<E>,
102 values: Vec<Value>,
103}
104
105impl<E: EntityKind> ProjectedRow<E> {
106 #[must_use]
108 pub const fn new(id: Id<E>, values: Vec<Value>) -> Self {
109 Self { id, values }
110 }
111
112 #[must_use]
114 pub const fn id(&self) -> Id<E> {
115 self.id
116 }
117
118 #[must_use]
120 pub const fn values(&self) -> &[Value] {
121 self.values.as_slice()
122 }
123
124 #[must_use]
126 pub fn into_parts(self) -> (Id<E>, Vec<Value>) {
127 (self.id, self.values)
128 }
129}
130
131impl<E: EntityKind> private::Sealed for ProjectedRow<E> {}
132
133impl<E: EntityKind> ResponseRow for ProjectedRow<E> {}
134
135#[derive(Debug, ThisError)]
140pub enum ResponseError {
141 #[error("expected exactly one row, found 0 (entity {entity})")]
142 NotFound { entity: &'static str },
143
144 #[error("expected exactly one row, found {count} (entity {entity})")]
145 NotUnique { entity: &'static str, count: u32 },
146}
147
148#[derive(Debug)]
155pub struct Response<R: ResponseRow>(Vec<R>);
156
157pub type EntityResponse<E> = Response<Row<E>>;
164
165pub type ProjectionResponse<E> = Response<ProjectedRow<E>>;
172
173impl<R: ResponseRow> Response<R> {
174 #[must_use]
176 pub const fn new(rows: Vec<R>) -> Self {
177 Self(rows)
178 }
179
180 #[must_use]
182 pub fn from_rows<T>(rows: Vec<T>) -> Self
183 where
184 T: Into<R>,
185 {
186 Self(rows.into_iter().map(Into::into).collect())
187 }
188
189 #[must_use]
191 pub const fn len(&self) -> usize {
192 self.0.len()
193 }
194
195 #[must_use]
197 #[expect(clippy::cast_possible_truncation)]
198 pub const fn count(&self) -> u32 {
199 self.0.len() as u32
200 }
201
202 #[must_use]
204 pub const fn is_empty(&self) -> bool {
205 self.0.is_empty()
206 }
207
208 #[must_use]
210 pub fn rows(self) -> Vec<R> {
211 self.0
212 }
213
214 pub fn iter(&self) -> std::slice::Iter<'_, R> {
216 self.0.iter()
217 }
218}
219
220impl<R: ResponseRow> AsRef<[R]> for Response<R> {
221 fn as_ref(&self) -> &[R] {
222 self.0.as_slice()
223 }
224}
225
226impl<R: ResponseRow> std::ops::Deref for Response<R> {
227 type Target = [R];
228
229 fn deref(&self) -> &Self::Target {
230 self.0.as_slice()
231 }
232}
233
234impl<E: EntityKind> Response<Row<E>> {
235 #[inline(never)]
237 pub(in crate::db) fn from_data_rows(
238 rows: Vec<DataRow>,
239 ) -> Result<Self, crate::error::InternalError>
240 where
241 E: EntityValue,
242 {
243 decode_data_rows_into_entity_response::<E>(rows)
244 }
245
246 #[must_use]
248 pub fn id(&self) -> Option<Id<E>> {
249 self.0.first().map(Row::id)
250 }
251
252 #[must_use]
254 pub fn entities(self) -> Vec<E> {
255 self.0.into_iter().map(Row::entity).collect()
256 }
257
258 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_ {
260 self.0.iter().map(Row::id)
261 }
262
263 pub fn contains_id(&self, id: &Id<E>) -> bool {
265 self.0.iter().any(|row| row.id() == *id)
266 }
267
268 pub fn views(&self) -> impl Iterator<Item = <E as AsView>::ViewType> + '_ {
270 self.0.iter().map(|row| row.entity_ref().as_view())
271 }
272}
273
274impl<R: ResponseRow> IntoIterator for Response<R> {
275 type Item = R;
276 type IntoIter = std::vec::IntoIter<Self::Item>;
277
278 fn into_iter(self) -> Self::IntoIter {
279 self.0.into_iter()
280 }
281}
282
283impl<'a, R: ResponseRow> IntoIterator for &'a Response<R> {
284 type Item = &'a R;
285 type IntoIter = std::slice::Iter<'a, R>;
286
287 fn into_iter(self) -> Self::IntoIter {
288 self.iter()
289 }
290}
291
292#[derive(Debug)]
300pub struct WriteBatchResponse<E> {
301 entities: Vec<E>,
302}
303
304impl<E> WriteBatchResponse<E> {
305 #[must_use]
307 pub const fn new(entities: Vec<E>) -> Self {
308 Self { entities }
309 }
310
311 #[must_use]
313 pub const fn len(&self) -> usize {
314 self.entities.len()
315 }
316
317 #[must_use]
319 pub const fn is_empty(&self) -> bool {
320 self.entities.is_empty()
321 }
322
323 #[must_use]
325 pub fn entities(self) -> Vec<E> {
326 self.entities
327 }
328
329 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_
331 where
332 E: EntityValue,
333 {
334 self.entities.iter().map(EntityValue::id)
335 }
336
337 pub fn views(&self) -> impl Iterator<Item = <E as AsView>::ViewType> + '_
339 where
340 E: AsView,
341 {
342 self.entities.iter().map(AsView::as_view)
343 }
344
345 pub fn iter(&self) -> std::slice::Iter<'_, E> {
347 self.entities.iter()
348 }
349}
350
351impl<E> IntoIterator for WriteBatchResponse<E> {
352 type Item = E;
353 type IntoIter = std::vec::IntoIter<E>;
354
355 fn into_iter(self) -> Self::IntoIter {
356 self.entities.into_iter()
357 }
358}
359
360impl<'a, E> IntoIterator for &'a WriteBatchResponse<E> {
361 type Item = &'a E;
362 type IntoIter = std::slice::Iter<'a, E>;
363
364 fn into_iter(self) -> Self::IntoIter {
365 self.iter()
366 }
367}