surrealml_core/storage/header/
origin.rs1use std::fmt;
3
4use super::string_value::StringValue;
5use crate::errors::error::{SurrealError, SurrealErrorStatus};
6use crate::safe_eject_option;
7
8const LOCAL: &str = "local";
9const SURREAL_DB: &str = "surreal_db";
10const NONE: &str = "";
11
12#[derive(Debug, PartialEq)]
19pub enum OriginValue {
20 Local(StringValue),
21 SurrealDb(StringValue),
22 None(StringValue),
23}
24
25impl OriginValue {
26 pub fn fresh() -> Self {
31 OriginValue::None(StringValue::fresh())
32 }
33
34 pub fn from_string(origin: String) -> Result<Self, SurrealError> {
42 match origin.to_lowercase().as_str() {
43 LOCAL => Ok(OriginValue::Local(StringValue::from_string(origin))),
44 SURREAL_DB => Ok(OriginValue::SurrealDb(StringValue::from_string(origin))),
45 NONE => Ok(OriginValue::None(StringValue::from_string(origin))),
46 _ => Err(SurrealError::new(
47 format!("invalid origin: {}", origin),
48 SurrealErrorStatus::BadRequest,
49 )),
50 }
51 }
52}
53
54impl fmt::Display for OriginValue {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 match self {
57 OriginValue::Local(val) | OriginValue::SurrealDb(val) | OriginValue::None(val) => {
58 write!(f, "{}", val)
59 }
60 }
61 }
62}
63
64#[derive(Debug, PartialEq)]
70pub struct Origin {
71 pub origin: OriginValue,
72 pub author: StringValue,
73}
74
75impl Origin {
76 pub fn fresh() -> Self {
81 Origin {
82 origin: OriginValue::fresh(),
83 author: StringValue::fresh(),
84 }
85 }
86
87 pub fn add_author(&mut self, author: String) {
92 self.author = StringValue::from_string(author);
93 }
94
95 pub fn add_origin(&mut self, origin: String) -> Result<(), SurrealError> {
99 self.origin = OriginValue::from_string(origin)?;
100 Ok(())
101 }
102
103 pub fn from_string(origin: String) -> Result<Self, SurrealError> {
111 if origin == *"" {
112 return Ok(Origin::fresh());
113 }
114 let mut split = origin.split("=>");
115 let author = safe_eject_option!(split.next()).to_string();
118 let origin = safe_eject_option!(split.next()).to_string();
119 Ok(Origin {
120 origin: OriginValue::from_string(origin)?,
121 author: StringValue::from_string(author),
122 })
123 }
124}
125
126impl fmt::Display for Origin {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 let is_empty_author = self.author.value.is_none();
129 let is_empty_origin = matches!(self.origin, OriginValue::None(ref s) if s.value.is_none());
130
131 if is_empty_author && is_empty_origin {
132 write!(f, "")
133 } else {
134 write!(f, "{}=>{}", self.author, self.origin)
135 }
136 }
137}
138
139#[cfg(test)]
140mod tests {
141
142 use super::*;
143
144 #[test]
145 fn test_fresh() {
146 let origin = Origin::fresh();
147 assert_eq!(
148 origin,
149 Origin {
150 origin: OriginValue::fresh(),
151 author: StringValue::fresh(),
152 }
153 );
154 }
155
156 #[test]
157 fn test_to_string() {
158 let origin = Origin {
159 origin: OriginValue::from_string("local".to_string()).unwrap(),
160 author: StringValue::from_string("author".to_string()),
161 };
162 assert_eq!(origin.to_string(), "author=>local".to_string());
163
164 let origin = Origin::fresh();
165 assert_eq!(origin.to_string(), "".to_string());
166 }
167
168 #[test]
169 fn test_from_string() {
170 let origin = Origin::from_string("author=>local".to_string()).unwrap();
171 assert_eq!(
172 origin,
173 Origin {
174 origin: OriginValue::from_string("local".to_string()).unwrap(),
175 author: StringValue::from_string("author".to_string()),
176 }
177 );
178
179 let origin = Origin::from_string("=>local".to_string()).unwrap();
180
181 assert_eq!(None, origin.author.value);
182 assert_eq!("local".to_string(), origin.origin.to_string());
183 }
184
185 #[test]
188 fn test_from_string_missing_delimiter_errors() {
189 assert!(Origin::from_string("no-delimiter".to_string()).is_err());
190 }
191}