icydb_core/db/response/
mod.rs1mod grouped;
10mod paged;
11
12use crate::{
13 db::data::{DataRow, PersistedRow, decode_data_rows_into_entity_response},
14 prelude::*,
15 traits::EntityValue,
16 types::Id,
17 value::Value,
18};
19use thiserror::Error as ThisError;
20
21mod private {
22 pub trait Sealed {}
29}
30
31pub(in crate::db) use grouped::GroupedTextCursorPageWithTrace;
32pub use grouped::{GroupedRow, PagedGroupedExecution, PagedGroupedExecutionWithTrace};
33pub use paged::{PagedLoadExecution, PagedLoadExecutionWithTrace};
34
35pub trait ResponseRow: private::Sealed {}
43
44impl ResponseRow for GroupedRow {}
45
46impl private::Sealed for GroupedRow {}
47
48#[derive(Clone, Debug, Eq, PartialEq)]
55pub struct Row<E: EntityKind> {
56 id: Id<E>,
57 entity: E,
58}
59
60impl<E: EntityKind> Row<E> {
61 #[must_use]
63 pub const fn new(id: Id<E>, entity: E) -> Self {
64 Self { id, entity }
65 }
66
67 #[must_use]
69 pub const fn id(&self) -> Id<E> {
70 self.id
71 }
72
73 #[must_use]
75 pub fn entity(self) -> E {
76 self.entity
77 }
78
79 #[must_use]
81 pub const fn entity_ref(&self) -> &E {
82 &self.entity
83 }
84
85 #[must_use]
87 pub fn into_parts(self) -> (Id<E>, E) {
88 (self.id, self.entity)
89 }
90}
91
92impl<E: EntityKind> From<(Id<E>, E)> for Row<E> {
93 fn from(value: (Id<E>, E)) -> Self {
94 Self::new(value.0, value.1)
95 }
96}
97
98impl<E: EntityKind> private::Sealed for Row<E> {}
99
100impl<E: EntityKind> ResponseRow for Row<E> {}
101
102#[derive(Clone, Debug, Eq, PartialEq)]
110pub struct ProjectedRow<E: EntityKind> {
111 id: Id<E>,
112 values: Vec<Value>,
113}
114
115impl<E: EntityKind> ProjectedRow<E> {
116 #[must_use]
118 pub const fn new(id: Id<E>, values: Vec<Value>) -> Self {
119 Self { id, values }
120 }
121
122 #[must_use]
124 pub const fn id(&self) -> Id<E> {
125 self.id
126 }
127
128 #[must_use]
130 pub const fn values(&self) -> &[Value] {
131 self.values.as_slice()
132 }
133
134 #[must_use]
136 pub fn into_parts(self) -> (Id<E>, Vec<Value>) {
137 (self.id, self.values)
138 }
139}
140
141impl<E: EntityKind> private::Sealed for ProjectedRow<E> {}
142
143impl<E: EntityKind> ResponseRow for ProjectedRow<E> {}
144
145#[derive(Debug, ThisError)]
150pub enum ResponseError {
151 #[error("expected exactly one row, found 0 (entity {entity})")]
152 NotFound { entity: &'static str },
153
154 #[error("expected exactly one row, found {count} (entity {entity})")]
155 NotUnique { entity: &'static str, count: u32 },
156}
157
158impl ResponseError {
159 #[must_use]
161 pub const fn not_found(entity: &'static str) -> Self {
162 Self::NotFound { entity }
163 }
164
165 #[must_use]
167 pub const fn not_unique(entity: &'static str, count: u32) -> Self {
168 Self::NotUnique { entity, count }
169 }
170}
171
172#[derive(Debug)]
179pub struct Response<R: ResponseRow>(Vec<R>);
180
181pub type EntityResponse<E> = Response<Row<E>>;
188
189pub type ProjectionResponse<E> = Response<ProjectedRow<E>>;
196
197impl<R: ResponseRow> Response<R> {
198 #[must_use]
200 pub const fn new(rows: Vec<R>) -> Self {
201 Self(rows)
202 }
203
204 #[must_use]
206 pub fn from_rows<T>(rows: Vec<T>) -> Self
207 where
208 T: Into<R>,
209 {
210 Self(rows.into_iter().map(Into::into).collect())
211 }
212
213 #[must_use]
215 pub const fn len(&self) -> usize {
216 self.0.len()
217 }
218
219 #[must_use]
221 #[expect(clippy::cast_possible_truncation)]
222 pub const fn count(&self) -> u32 {
223 self.0.len() as u32
224 }
225
226 #[must_use]
228 pub const fn is_empty(&self) -> bool {
229 self.0.is_empty()
230 }
231
232 #[must_use]
234 pub fn rows(self) -> Vec<R> {
235 self.0
236 }
237
238 pub fn iter(&self) -> std::slice::Iter<'_, R> {
240 self.0.iter()
241 }
242}
243
244impl<R: ResponseRow> AsRef<[R]> for Response<R> {
245 fn as_ref(&self) -> &[R] {
246 self.0.as_slice()
247 }
248}
249
250impl<R: ResponseRow> std::ops::Deref for Response<R> {
251 type Target = [R];
252
253 fn deref(&self) -> &Self::Target {
254 self.0.as_slice()
255 }
256}
257
258impl<E: EntityKind> Response<Row<E>> {
259 pub(in crate::db) fn from_data_rows(
261 rows: Vec<DataRow>,
262 ) -> Result<Self, crate::error::InternalError>
263 where
264 E: PersistedRow + EntityValue,
265 {
266 decode_data_rows_into_entity_response::<E>(rows)
267 }
268
269 #[must_use]
271 pub fn id(&self) -> Option<Id<E>> {
272 self.0.first().map(Row::id)
273 }
274
275 #[must_use]
277 pub fn entities(self) -> Vec<E> {
278 self.0.into_iter().map(Row::entity).collect()
279 }
280
281 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_ {
283 self.0.iter().map(Row::id)
284 }
285
286 pub fn contains_id(&self, id: &Id<E>) -> bool {
288 self.0.iter().any(|row| row.id() == *id)
289 }
290}
291
292impl<R: ResponseRow> IntoIterator for Response<R> {
293 type Item = R;
294 type IntoIter = std::vec::IntoIter<Self::Item>;
295
296 fn into_iter(self) -> Self::IntoIter {
297 self.0.into_iter()
298 }
299}
300
301impl<'a, R: ResponseRow> IntoIterator for &'a Response<R> {
302 type Item = &'a R;
303 type IntoIter = std::slice::Iter<'a, R>;
304
305 fn into_iter(self) -> Self::IntoIter {
306 self.iter()
307 }
308}
309
310#[derive(Debug)]
318pub struct WriteBatchResponse<E> {
319 entities: Vec<E>,
320}
321
322impl<E> WriteBatchResponse<E> {
323 #[must_use]
325 pub const fn new(entities: Vec<E>) -> Self {
326 Self { entities }
327 }
328
329 #[must_use]
331 pub const fn len(&self) -> usize {
332 self.entities.len()
333 }
334
335 #[must_use]
337 pub const fn is_empty(&self) -> bool {
338 self.entities.is_empty()
339 }
340
341 #[must_use]
343 pub fn entities(self) -> Vec<E> {
344 self.entities
345 }
346
347 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_
349 where
350 E: EntityValue,
351 {
352 self.entities.iter().map(EntityValue::id)
353 }
354
355 pub fn iter(&self) -> std::slice::Iter<'_, E> {
357 self.entities.iter()
358 }
359}
360
361impl<E> IntoIterator for WriteBatchResponse<E> {
362 type Item = E;
363 type IntoIter = std::vec::IntoIter<E>;
364
365 fn into_iter(self) -> Self::IntoIter {
366 self.entities.into_iter()
367 }
368}
369
370impl<'a, E> IntoIterator for &'a WriteBatchResponse<E> {
371 type Item = &'a E;
372 type IntoIter = std::slice::Iter<'a, E>;
373
374 fn into_iter(self) -> Self::IntoIter {
375 self.iter()
376 }
377}