icydb_core/db/response/
mod.rs1use crate::{Error, Key, ThisError, db::DbError, traits::EntityKind};
2
3#[derive(Debug, ThisError)]
9pub enum ResponseError {
10 #[error("expected exactly one row, found 0 (entity {entity})")]
11 NotFound { entity: &'static str },
12
13 #[error("expected exactly one row, found {count} (entity {entity})")]
14 NotUnique { entity: &'static str, count: u32 },
15}
16
17impl From<ResponseError> for Error {
18 fn from(err: ResponseError) -> Self {
19 DbError::from(err).into()
20 }
21}
22
23#[derive(Debug)]
29pub struct Response<E: EntityKind>(pub Vec<(Key, E)>);
30
31impl<E: EntityKind> Response<E> {
32 #[must_use]
38 #[allow(clippy::cast_possible_truncation)]
39 pub const fn count(&self) -> u32 {
40 self.0.len() as u32
41 }
42
43 #[must_use]
45 pub const fn is_empty(&self) -> bool {
46 self.0.is_empty()
47 }
48
49 pub fn require_one(&self) -> Result<(), Error> {
55 match self.count() {
56 1 => Ok(()),
57 0 => Err(ResponseError::NotFound { entity: E::PATH }.into()),
58 n => Err(ResponseError::NotUnique {
59 entity: E::PATH,
60 count: n,
61 }
62 .into()),
63 }
64 }
65
66 pub fn one(self) -> Result<(Key, E), Error> {
72 self.require_one()?;
73 Ok(self.0.into_iter().next().unwrap())
74 }
75
76 pub fn one_opt(self) -> Result<Option<(Key, E)>, Error> {
78 match self.count() {
79 0 => Ok(None),
80 1 => Ok(Some(self.0.into_iter().next().unwrap())),
81 n => Err(ResponseError::NotUnique {
82 entity: E::PATH,
83 count: n,
84 }
85 .into()),
86 }
87 }
88
89 #[must_use]
95 pub fn key(&self) -> Option<Key> {
96 self.0.first().map(|(k, _)| *k)
97 }
98
99 #[must_use]
101 pub fn keys(&self) -> Vec<Key> {
102 self.0.iter().map(|(k, _)| *k).collect()
103 }
104
105 pub fn one_key(self) -> Result<Key, Error> {
107 self.one().map(|(k, _)| k)
108 }
109
110 pub fn one_opt_key(self) -> Result<Option<Key>, Error> {
112 Ok(self.one_opt()?.map(|(k, _)| k))
113 }
114
115 #[must_use]
116 pub fn contains_key(&self, key: &Key) -> bool {
117 self.0.iter().any(|(k, _)| k == key)
118 }
119
120 #[must_use]
126 pub fn entity(self) -> Option<E> {
127 self.0.into_iter().next().map(|(_, e)| e)
128 }
129
130 #[must_use]
132 pub fn entities(self) -> Vec<E> {
133 self.0.into_iter().map(|(_, e)| e).collect()
134 }
135
136 pub fn one_entity(self) -> Result<E, Error> {
138 self.one().map(|(_, e)| e)
139 }
140
141 pub fn one_opt_entity(self) -> Result<Option<E>, Error> {
143 Ok(self.one_opt()?.map(|(_, e)| e))
144 }
145
146 #[must_use]
152 pub fn pk(&self) -> Option<E::PrimaryKey> {
153 self.0.first().map(|(_, e)| e.primary_key())
154 }
155
156 #[must_use]
158 pub fn pks(&self) -> Vec<E::PrimaryKey> {
159 self.0.iter().map(|(_, e)| e.primary_key()).collect()
160 }
161
162 pub fn one_pk(self) -> Result<E::PrimaryKey, Error> {
164 self.one_entity().map(|e| e.primary_key())
165 }
166
167 pub fn one_opt_pk(self) -> Result<Option<E::PrimaryKey>, Error> {
169 Ok(self.one_opt_entity()?.map(|e| e.primary_key()))
170 }
171
172 #[must_use]
178 pub fn view(self) -> Option<E::ViewType> {
179 self.entity().map(|e| e.to_view())
180 }
181
182 pub fn one_view(self) -> Result<E::ViewType, Error> {
184 self.one_entity().map(|e| e.to_view())
185 }
186
187 pub fn one_opt_view(self) -> Result<Option<E::ViewType>, Error> {
189 Ok(self.one_opt_entity()?.map(|e| e.to_view()))
190 }
191
192 #[must_use]
194 pub fn views(self) -> Vec<E::ViewType> {
195 self.entities().into_iter().map(|e| e.to_view()).collect()
196 }
197}
198
199impl<E: EntityKind> IntoIterator for Response<E> {
200 type Item = (Key, E);
201 type IntoIter = std::vec::IntoIter<Self::Item>;
202
203 fn into_iter(self) -> Self::IntoIter {
204 self.0.into_iter()
205 }
206}