1use crate::{DatabaseAccess, DatabaseRecord, Error, Record, Validate};
2use serde::{Deserialize, Serialize};
3use std::ops::{Deref, DerefMut};
4
5#[derive(Serialize, Deserialize, Clone)]
15pub struct EdgeRecord<T> {
16 #[serde(rename(serialize = "_from", deserialize = "_from"))]
18 from: String,
19 #[serde(rename(serialize = "_to", deserialize = "_to"))]
21 to: String,
22 #[serde(flatten)]
28 pub data: T,
29}
30
31impl<T: Record> EdgeRecord<T> {
32 pub fn new(id_from: String, id_to: String, data: T) -> Result<Self, Error> {
44 let res = Self {
45 from: id_from,
46 to: id_to,
47 data,
48 };
49 res.validate()?;
50 Ok(res)
51 }
52
53 #[maybe_async::maybe_async]
55 pub async fn from_record<D, R>(&self, db_access: &D) -> Result<DatabaseRecord<R>, Error>
56 where
57 D: DatabaseAccess + ?Sized,
58 R: Record,
59 {
60 DatabaseRecord::find(self.key_from(), db_access).await
61 }
62
63 #[maybe_async::maybe_async]
65 pub async fn to_record<D, R>(&self, db_access: &D) -> Result<DatabaseRecord<R>, Error>
66 where
67 D: DatabaseAccess + ?Sized,
68 R: Record,
69 {
70 DatabaseRecord::find(self.key_to(), db_access).await
71 }
72
73 #[allow(clippy::missing_const_for_fn)] #[must_use]
76 #[inline]
77 pub fn id_from(&self) -> &String {
78 &self.from
79 }
80
81 #[allow(clippy::missing_const_for_fn)] #[must_use]
84 #[inline]
85 pub fn id_to(&self) -> &String {
86 &self.to
87 }
88
89 #[must_use]
95 pub fn key_from(&self) -> &str {
96 self.id_from().split('/').last().unwrap()
97 }
98
99 #[must_use]
105 pub fn key_to(&self) -> &str {
106 self.id_to().split('/').last().unwrap()
107 }
108
109 #[must_use]
115 pub fn to_collection_name(&self) -> String {
116 self.id_to().split('/').next().unwrap().to_string()
117 }
118
119 #[must_use]
125 pub fn from_collection_name(&self) -> &str {
126 self.id_from().split('/').next().unwrap()
127 }
128
129 fn validate_edge_fields(&self, errors: &mut Vec<String>) {
130 let array = [("from", self.id_from()), ("to", self.id_to())];
131 for (name, field) in array {
132 let vec: Vec<&str> = field.split('/').collect();
133 let [left, right]: [_; 2] = if let Ok(v) = vec.try_into() {
134 v
135 } else {
136 errors.push(format!(r#"{} "{}" is not a valid id"#, name, field));
137 continue;
138 };
139 Self::validate_min_len(name, left, 2, errors);
140 Self::validate_min_len(name, right, 2, errors);
141 }
142 }
143}
144
145impl<T: Record> Validate for EdgeRecord<T> {
146 fn validations(&self, errors: &mut Vec<String>) {
147 self.validate_edge_fields(errors);
148 }
149}
150
151#[maybe_async::maybe_async]
152impl<T: Record + Send> Record for EdgeRecord<T> {
153 const COLLECTION_NAME: &'static str = T::COLLECTION_NAME;
154
155 async fn before_create_hook<D>(&mut self, db_accessor: &D) -> Result<(), Error>
156 where
157 D: DatabaseAccess + ?Sized,
158 {
159 self.validate()?;
160 self.data.before_create_hook(db_accessor).await
161 }
162
163 async fn before_save_hook<D>(&mut self, db_accessor: &D) -> Result<(), Error>
164 where
165 D: DatabaseAccess + ?Sized,
166 {
167 self.data.before_save_hook(db_accessor).await
168 }
169
170 async fn before_delete_hook<D>(&mut self, db_accessor: &D) -> Result<(), Error>
171 where
172 D: DatabaseAccess + ?Sized,
173 {
174 self.data.before_delete_hook(db_accessor).await
175 }
176
177 async fn after_create_hook<D>(&mut self, db_accessor: &D) -> Result<(), Error>
178 where
179 D: DatabaseAccess + ?Sized,
180 {
181 self.data.after_create_hook(db_accessor).await
182 }
183
184 async fn after_save_hook<D>(&mut self, db_accessor: &D) -> Result<(), Error>
185 where
186 D: DatabaseAccess + ?Sized,
187 {
188 self.validate()?;
189 self.data.after_save_hook(db_accessor).await
190 }
191
192 async fn after_delete_hook<D>(&mut self, db_accessor: &D) -> Result<(), Error>
193 where
194 D: DatabaseAccess + ?Sized,
195 {
196 self.data.after_delete_hook(db_accessor).await
197 }
198}
199
200impl<T: Record> Deref for EdgeRecord<T> {
201 type Target = T;
202
203 fn deref(&self) -> &Self::Target {
204 &self.data
205 }
206}
207
208impl<T: Record> DerefMut for EdgeRecord<T> {
209 fn deref_mut(&mut self) -> &mut Self::Target {
210 &mut self.data
211 }
212}