icydb_schema/node/
item.rs1use crate::prelude::*;
2use std::ops::Not;
3
4#[derive(Clone, Debug, Serialize)]
9pub struct Item {
10 pub target: ItemTarget,
11
12 #[serde(default, skip_serializing_if = "Option::is_none")]
13 pub relation: Option<&'static str>,
14
15 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub scale: Option<u32>,
17
18 #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
19 pub validators: &'static [TypeValidator],
20
21 #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
22 pub sanitizers: &'static [TypeSanitizer],
23
24 #[serde(default, skip_serializing_if = "Not::not")]
25 pub indirect: bool,
26}
27
28impl Item {
29 #[must_use]
30 pub const fn is_relation(&self) -> bool {
31 self.relation.is_some()
32 }
33}
34
35impl ValidateNode for Item {
36 fn validate(&self) -> Result<(), ErrorTree> {
37 let mut errs = ErrorTree::new();
38 let schema = schema_read();
39
40 match &self.target {
42 ItemTarget::Is(path) => {
43 if schema.check_node_as::<Entity>(path).is_ok() {
45 err!(errs, "a non-relation Item cannot reference an Entity");
46 }
47 }
48
49 ItemTarget::Primitive(_) => {}
50 }
51
52 if let Some(relation) = &self.relation {
54 match schema.cast_node::<Entity>(relation) {
56 Ok(entity) => {
57 if let Some(primary_field) = entity.get_pk_field() {
59 let relation_target = &primary_field.value.item.target;
60
61 let relation_scale = primary_field.value.item.scale;
63 if &self.target != relation_target || self.scale != relation_scale {
64 err!(
65 errs,
66 "relation target type mismatch: expected ({:?}, scale={:?}), found ({:?}, scale={:?})",
67 relation_target,
68 relation_scale,
69 self.target,
70 self.scale
71 );
72 }
73 } else {
74 err!(
75 errs,
76 "relation entity '{relation}' missing primary key field '{0}'",
77 entity.primary_key.field
78 );
79 }
80 }
81 Err(_) => {
82 err!(errs, "relation entity '{relation}' not found");
83 }
84 }
85 }
86
87 errs.result()
88 }
89}
90
91impl VisitableNode for Item {
92 fn drive<V: Visitor>(&self, v: &mut V) {
93 for node in self.validators {
94 node.accept(v);
95 }
96 }
97}
98
99#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
104pub enum ItemTarget {
105 Is(&'static str),
106 Primitive(Primitive),
107}