wp_model_core/model/data/
storage.rs1use crate::model::Value;
2use crate::model::DataType;
3use crate::model::{FNameStr, FValueStr};
4use crate::model::format::LevelFormatAble;
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use std::fmt::{Display, Formatter};
7use std::net::IpAddr;
8use std::sync::Arc;
9
10use super::field::Field;
11use super::record::{RecordItem, RecordItemFactory};
12
13#[derive(Clone, Debug)]
41pub enum FieldStorage {
42 Shared(Arc<Field<Value>>),
47
48 Owned(Field<Value>),
53}
54
55impl FieldStorage {
56 #[inline]
73 pub fn as_field(&self) -> &Field<Value> {
74 match self {
75 FieldStorage::Shared(arc) => arc.as_ref(),
76 FieldStorage::Owned(field) => field,
77 }
78 }
79
80 pub fn into_owned(self) -> Field<Value> {
99 match self {
100 FieldStorage::Shared(arc) => {
101 Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())
103 }
104 FieldStorage::Owned(field) => field,
105 }
106 }
107
108 pub fn from_shared(field: Field<Value>) -> Self {
121 FieldStorage::Shared(Arc::new(field))
122 }
123
124 pub fn from_owned(field: Field<Value>) -> Self {
137 FieldStorage::Owned(field)
138 }
139
140 #[inline]
155 pub fn is_shared(&self) -> bool {
156 matches!(self, FieldStorage::Shared(_))
157 }
158
159 pub fn shared_count(&self) -> Option<usize> {
177 match self {
178 FieldStorage::Shared(arc) => Some(Arc::strong_count(arc)),
179 FieldStorage::Owned(_) => None,
180 }
181 }
182}
183
184impl Display for FieldStorage {
186 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
187 self.as_field().fmt(f)
188 }
189}
190
191impl PartialEq for FieldStorage {
193 fn eq(&self, other: &Self) -> bool {
194 self.as_field().eq(other.as_field())
195 }
196}
197
198impl Eq for FieldStorage {}
199
200impl Serialize for FieldStorage {
202 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
203 where
204 S: Serializer,
205 {
206 self.as_field().serialize(serializer)
208 }
209}
210
211impl<'de> Deserialize<'de> for FieldStorage {
213 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
214 where
215 D: Deserializer<'de>,
216 {
217 Field::<Value>::deserialize(deserializer).map(FieldStorage::Owned)
219 }
220}
221
222impl RecordItem for FieldStorage {
224 fn get_name(&self) -> &str {
225 self.as_field().get_name()
226 }
227
228 fn get_meta(&self) -> &DataType {
229 self.as_field().get_meta()
230 }
231
232 fn get_value(&self) -> &Value {
233 self.as_field().get_value()
234 }
235
236 fn get_value_mut(&mut self) -> &mut Value {
237 match self {
238 FieldStorage::Shared(arc) => {
239 let field = Arc::try_unwrap(std::mem::replace(arc, Arc::new(Field::new(DataType::Ignore, "", Value::from(false)))))
242 .unwrap_or_else(|arc| (*arc).clone());
243 *self = FieldStorage::Owned(field);
244 match self {
245 FieldStorage::Owned(f) => f.get_value_mut(),
246 _ => unreachable!(),
247 }
248 }
249 FieldStorage::Owned(field) => field.get_value_mut(),
250 }
251 }
252}
253
254impl RecordItemFactory for FieldStorage {
256 fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self {
257 FieldStorage::Owned(Field::from_digit(name, val))
258 }
259
260 fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self {
261 FieldStorage::Owned(Field::from_ip(name, ip))
262 }
263
264 fn from_chars<N: Into<FNameStr>, Val: Into<FValueStr>>(name: N, val: Val) -> Self {
265 FieldStorage::Owned(Field::from_chars(name, val))
266 }
267}
268
269impl LevelFormatAble for FieldStorage {
271 fn level_fmt(&self, f: &mut Formatter<'_>, level: usize) -> std::fmt::Result {
272 self.as_field().level_fmt(f, level)
273 }
274}
275
276#[cfg(test)]
277mod tests {
278 use super::*;
279 use crate::model::DataType;
280
281 #[test]
282 fn test_field_storage_shared_variant() {
283 let field = Field::new(DataType::Chars, "test", Value::from("hello"));
284 let storage = FieldStorage::Shared(Arc::new(field.clone()));
285
286 assert_eq!(storage.as_field().get_name(), "test");
288 assert!(storage.is_shared());
289 assert_eq!(storage.shared_count(), Some(1));
290
291 let storage2 = storage.clone();
293 assert_eq!(storage.shared_count(), Some(2));
294 assert_eq!(storage2.shared_count(), Some(2));
295 }
296
297 #[test]
298 fn test_field_storage_owned_variant() {
299 let field = Field::new(DataType::Digit, "test", Value::from(42));
300 let storage = FieldStorage::Owned(field);
301
302 assert_eq!(storage.as_field().get_name(), "test");
303 assert!(!storage.is_shared());
304 assert_eq!(storage.shared_count(), None);
305 }
306
307 #[test]
308 fn test_into_owned() {
309 let field1 = Field::new(DataType::Chars, "shared_field", Value::from("value"));
311 let storage1 = FieldStorage::Shared(Arc::new(field1));
312 let owned1 = storage1.into_owned();
313 assert_eq!(owned1.get_name(), "shared_field");
314
315 let field2 = Field::new(DataType::Digit, "owned_field", Value::from(123));
317 let storage2 = FieldStorage::Owned(field2);
318 let owned2 = storage2.into_owned();
319 assert_eq!(owned2.get_name(), "owned_field");
320 }
321
322 #[test]
323 fn test_from_shared() {
324 let field = Field::new(DataType::Chars, "name", Value::from("Alice"));
325 let storage = FieldStorage::from_shared(field);
326
327 assert!(storage.is_shared());
328 assert_eq!(storage.as_field().get_name(), "name");
329 }
330
331 #[test]
332 fn test_from_owned() {
333 let field = Field::new(DataType::Digit, "count", Value::from(10));
334 let storage = FieldStorage::from_owned(field);
335
336 assert!(!storage.is_shared());
337 assert_eq!(storage.as_field().get_name(), "count");
338 }
339
340 #[test]
341 fn test_display() {
342 let field = Field::new(DataType::Digit, "num", Value::from(42));
343 let storage = FieldStorage::from_owned(field);
344
345 let display = format!("{}", storage);
346 assert!(display.contains("42"));
347 }
348
349 #[test]
350 fn test_equality() {
351 let field1 = Field::new(DataType::Chars, "test", Value::from("value"));
352 let field2 = Field::new(DataType::Chars, "test", Value::from("value"));
353 let field3 = Field::new(DataType::Chars, "test", Value::from("different"));
354
355 let shared1 = FieldStorage::from_shared(field1.clone());
356 let owned1 = FieldStorage::from_owned(field1);
357 let shared2 = FieldStorage::from_shared(field2);
358 let owned3 = FieldStorage::from_owned(field3);
359
360 assert_eq!(shared1, owned1);
362 assert_eq!(shared1, shared2);
363
364 assert_ne!(shared1, owned3);
366 }
367
368 #[test]
369 fn test_serde_serialization() {
370 let field1 = Field::new(DataType::Chars, "f1", Value::from("shared"));
371 let field2 = Field::new(DataType::Digit, "f2", Value::from(99));
372
373 let shared = FieldStorage::from_shared(field1);
374 let owned = FieldStorage::from_owned(field2);
375
376 let json_shared = serde_json::to_string(&shared).unwrap();
378 let json_owned = serde_json::to_string(&owned).unwrap();
379
380 let deserialized_shared: FieldStorage = serde_json::from_str(&json_shared).unwrap();
382 let deserialized_owned: FieldStorage = serde_json::from_str(&json_owned).unwrap();
383
384 assert_eq!(deserialized_shared.as_field().get_name(), "f1");
386 assert_eq!(deserialized_owned.as_field().get_name(), "f2");
387
388 assert!(!deserialized_shared.is_shared());
390 assert!(!deserialized_owned.is_shared());
391 }
392
393 #[test]
394 fn test_clone_performance_difference() {
395 use crate::model::FValueStr;
397 let large_str = FValueStr::from("x".repeat(1000));
398 let field = Field::new(DataType::Chars, "large", Value::from(large_str));
399
400 let shared = FieldStorage::from_shared(field.clone());
402 let _shared2 = shared.clone();
403 assert_eq!(shared.shared_count(), Some(2));
404
405 let owned = FieldStorage::from_owned(field);
407 let _owned2 = owned.clone();
408 assert!(owned.shared_count().is_none());
409 }
410}