icydb_core/db/response/
mod.rs1mod grouped;
10mod paged;
11
12use crate::{entity::EntityValue, prelude::*, types::Id};
13
14mod private {
15 pub trait Sealed {}
22}
23
24pub use grouped::{GroupedRow, PagedGroupedExecution, PagedGroupedExecutionWithTrace};
25pub use paged::{PagedLoadExecution, PagedLoadExecutionWithTrace};
26
27pub trait ResponseRow: private::Sealed {}
35
36impl ResponseRow for GroupedRow {}
37
38impl private::Sealed for GroupedRow {}
39
40#[derive(Clone, Debug, Eq, PartialEq)]
47pub struct Row<E: EntityKind> {
48 id: Id<E>,
49 entity: E,
50}
51
52impl<E: EntityKind> Row<E> {
53 #[must_use]
55 pub const fn new(id: Id<E>, entity: E) -> Self {
56 Self { id, entity }
57 }
58
59 #[must_use]
61 pub const fn id(&self) -> Id<E> {
62 self.id
63 }
64
65 #[must_use]
67 pub fn entity(self) -> E {
68 self.entity
69 }
70
71 #[must_use]
73 pub const fn entity_ref(&self) -> &E {
74 &self.entity
75 }
76
77 #[must_use]
79 pub fn into_id_and_entity(self) -> (Id<E>, E) {
80 (self.id, self.entity)
81 }
82}
83
84impl<E: EntityKind> From<(Id<E>, E)> for Row<E> {
85 fn from(value: (Id<E>, E)) -> Self {
86 Self::new(value.0, value.1)
87 }
88}
89
90impl<E: EntityKind> private::Sealed for Row<E> {}
91
92impl<E: EntityKind> ResponseRow for Row<E> {}
93
94#[derive(Debug)]
99pub enum ResponseError {
100 NotFound { entity: &'static str },
101
102 NotUnique { entity: &'static str, count: u32 },
103}
104
105impl ResponseError {
106 #[must_use]
108 pub const fn not_found(entity: &'static str) -> Self {
109 Self::NotFound { entity }
110 }
111
112 #[must_use]
114 pub const fn not_unique(entity: &'static str, count: u32) -> Self {
115 Self::NotUnique { entity, count }
116 }
117}
118
119#[derive(Debug)]
126pub struct Response<R: ResponseRow>(Vec<R>);
127
128pub type EntityResponse<E> = Response<Row<E>>;
135
136impl<R: ResponseRow> Response<R> {
137 #[must_use]
139 pub const fn new(rows: Vec<R>) -> Self {
140 Self(rows)
141 }
142
143 #[must_use]
145 pub const fn len(&self) -> usize {
146 self.0.len()
147 }
148
149 #[must_use]
151 #[expect(clippy::cast_possible_truncation)]
152 pub const fn count(&self) -> u32 {
153 self.0.len() as u32
154 }
155
156 #[must_use]
158 pub const fn is_empty(&self) -> bool {
159 self.0.is_empty()
160 }
161
162 #[must_use]
164 pub fn rows(self) -> Vec<R> {
165 self.0
166 }
167
168 #[must_use]
170 pub const fn as_slice(&self) -> &[R] {
171 self.0.as_slice()
172 }
173
174 pub fn iter(&self) -> std::slice::Iter<'_, R> {
176 self.0.iter()
177 }
178}
179
180impl<E: EntityKind> Response<Row<E>> {
181 #[must_use]
183 pub fn entities(self) -> Vec<E> {
184 self.0.into_iter().map(Row::entity).collect()
185 }
186
187 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_ {
189 self.0.iter().map(Row::id)
190 }
191
192 pub fn contains_id(&self, id: &Id<E>) -> bool {
194 self.0.iter().any(|row| row.id() == *id)
195 }
196}
197
198impl<R: ResponseRow> IntoIterator for Response<R> {
199 type Item = R;
200 type IntoIter = std::vec::IntoIter<Self::Item>;
201
202 fn into_iter(self) -> Self::IntoIter {
203 self.0.into_iter()
204 }
205}
206
207impl<'a, R: ResponseRow> IntoIterator for &'a Response<R> {
208 type Item = &'a R;
209 type IntoIter = std::slice::Iter<'a, R>;
210
211 fn into_iter(self) -> Self::IntoIter {
212 self.iter()
213 }
214}
215
216#[derive(Debug)]
224pub struct WriteBatchResponse<E> {
225 entities: Vec<E>,
226}
227
228impl<E> WriteBatchResponse<E> {
229 #[must_use]
231 pub(in crate::db) const fn new(entities: Vec<E>) -> Self {
232 Self { entities }
233 }
234
235 #[must_use]
237 pub const fn len(&self) -> usize {
238 self.entities.len()
239 }
240
241 #[must_use]
243 pub const fn is_empty(&self) -> bool {
244 self.entities.is_empty()
245 }
246
247 #[must_use]
249 pub fn entities(self) -> Vec<E> {
250 self.entities
251 }
252
253 pub fn ids(&self) -> impl Iterator<Item = Id<E>> + '_
255 where
256 E: EntityValue,
257 {
258 self.entities.iter().map(EntityValue::id)
259 }
260
261 pub fn iter(&self) -> std::slice::Iter<'_, E> {
263 self.entities.iter()
264 }
265}
266
267impl<E> IntoIterator for WriteBatchResponse<E> {
268 type Item = E;
269 type IntoIter = std::vec::IntoIter<E>;
270
271 fn into_iter(self) -> Self::IntoIter {
272 self.entities.into_iter()
273 }
274}
275
276impl<'a, E> IntoIterator for &'a WriteBatchResponse<E> {
277 type Item = &'a E;
278 type IntoIter = std::slice::Iter<'a, E>;
279
280 fn into_iter(self) -> Self::IntoIter {
281 self.iter()
282 }
283}