icydb_core/db/response/
mod.rs1mod write;
2
3use crate::{
4 prelude::*,
5 types::{Id, Ref},
6 view::View,
7};
8use thiserror::Error as ThisError;
9
10pub use write::*;
12
13pub type Row<E> = (Id<E>, E);
18
19#[derive(Debug, ThisError)]
24pub enum ResponseError {
25 #[error("expected exactly one row, found 0 (entity {entity})")]
26 NotFound { entity: &'static str },
27
28 #[error("expected exactly one row, found {count} (entity {entity})")]
29 NotUnique { entity: &'static str, count: u32 },
30}
31
32impl ResponseError {
33 const fn not_found<E: EntityKind>() -> Self {
34 Self::NotFound { entity: E::PATH }
35 }
36
37 const fn not_unique<E: EntityKind>(count: u32) -> Self {
38 Self::NotUnique {
39 entity: E::PATH,
40 count,
41 }
42 }
43}
44
45#[derive(Debug)]
52pub struct Response<E: EntityKind>(pub Vec<Row<E>>);
53
54impl<E: EntityKind> Response<E> {
55 #[must_use]
60 #[expect(clippy::cast_possible_truncation)]
61 pub const fn count(&self) -> u32 {
62 self.0.len() as u32
63 }
64
65 #[must_use]
66 pub const fn is_empty(&self) -> bool {
67 self.0.is_empty()
68 }
69
70 pub const fn require_one(&self) -> Result<(), ResponseError> {
75 match self.count() {
76 1 => Ok(()),
77 0 => Err(ResponseError::not_found::<E>()),
78 n => Err(ResponseError::not_unique::<E>(n)),
79 }
80 }
81
82 pub const fn require_some(&self) -> Result<(), ResponseError> {
83 if self.is_empty() {
84 Err(ResponseError::not_found::<E>())
85 } else {
86 Ok(())
87 }
88 }
89
90 #[expect(clippy::cast_possible_truncation)]
95 pub fn try_row(self) -> Result<Option<Row<E>>, ResponseError> {
96 match self.0.len() {
97 0 => Ok(None),
98 1 => Ok(Some(self.0.into_iter().next().unwrap())),
99 n => Err(ResponseError::not_unique::<E>(n as u32)),
100 }
101 }
102
103 pub fn row(self) -> Result<Row<E>, ResponseError> {
104 self.try_row()?.ok_or_else(ResponseError::not_found::<E>)
105 }
106
107 #[must_use]
108 pub fn rows(self) -> Vec<Row<E>> {
109 self.0
110 }
111
112 pub fn try_entity(self) -> Result<Option<E>, ResponseError> {
117 Ok(self.try_row()?.map(|(_, e)| e))
118 }
119
120 pub fn entity(self) -> Result<E, ResponseError> {
121 self.row().map(|(_, e)| e)
122 }
123
124 #[must_use]
125 pub fn entities(self) -> Vec<E> {
126 self.0.into_iter().map(|(_, e)| e).collect()
127 }
128
129 #[must_use]
134 pub fn id(&self) -> Option<Id<E>> {
135 self.0.first().map(|(id, _)| *id)
136 }
137
138 pub fn require_id(self) -> Result<Id<E>, ResponseError> {
139 self.row().map(|(id, _)| id)
140 }
141
142 #[must_use]
143 pub fn ids(&self) -> Vec<Id<E>> {
144 self.0.iter().map(|(id, _)| *id).collect()
145 }
146
147 pub fn contains_id(&self, id: &Id<E>) -> bool {
148 self.0.iter().any(|(k, _)| k == id)
149 }
150
151 pub fn reference(self) -> Result<Ref<E>, ResponseError> {
157 self.require_id()
158 .map(|id| Ref::from_storage_key(id.into_key()))
159 }
160
161 pub fn try_reference(self) -> Result<Option<Ref<E>>, ResponseError> {
163 self.try_row()
164 .map(|row| row.map(|(id, _)| Ref::from_storage_key(id.into_key())))
165 }
166
167 #[must_use]
169 pub fn references(&self) -> Vec<Ref<E>> {
170 self.0
171 .iter()
172 .map(|(id, _)| Ref::from_storage_key(id.into_key()))
173 .collect()
174 }
175
176 pub fn view(&self) -> Result<View<E>, ResponseError> {
181 self.require_one()?;
182 Ok(self.0[0].1.to_view())
183 }
184
185 pub fn view_opt(&self) -> Result<Option<View<E>>, ResponseError> {
186 match self.count() {
187 0 => Ok(None),
188 1 => Ok(Some(self.0[0].1.to_view())),
189 n => Err(ResponseError::not_unique::<E>(n)),
190 }
191 }
192
193 #[must_use]
194 pub fn views(&self) -> Vec<View<E>> {
195 self.0.iter().map(|(_, e)| e.to_view()).collect()
196 }
197}
198
199impl<E: EntityKind> IntoIterator for Response<E> {
200 type Item = Row<E>;
201 type IntoIter = std::vec::IntoIter<Self::Item>;
202
203 fn into_iter(self) -> Self::IntoIter {
204 self.0.into_iter()
205 }
206}