parse_rust_storage/
schema.rs1use indexmap::IndexMap;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum FieldType {
16 String,
17 Number,
18 Boolean,
19 Date,
20 Object,
21 Array,
22 GeoPoint,
23 File,
24 Bytes,
25 Polygon,
26 Pointer {
27 target_class: String,
28 },
29 Relation {
30 target_class: String,
31 },
32 Acl,
35}
36
37impl FieldType {
38 pub fn to_wire_string(&self) -> String {
45 match self {
46 FieldType::String => "String".into(),
47 FieldType::Number => "Number".into(),
48 FieldType::Boolean => "Boolean".into(),
49 FieldType::Date => "Date".into(),
50 FieldType::Object => "Object".into(),
51 FieldType::Array => "Array".into(),
52 FieldType::GeoPoint => "GeoPoint".into(),
53 FieldType::File => "File".into(),
54 FieldType::Bytes => "Bytes".into(),
55 FieldType::Polygon => "Polygon".into(),
56 FieldType::Acl => "ACL".into(),
57 FieldType::Pointer { target_class } => format!("Pointer<{target_class}>"),
58 FieldType::Relation { target_class } => format!("Relation<{target_class}>"),
59 }
60 }
61
62 pub fn is_pointer(&self) -> bool {
63 matches!(self, FieldType::Pointer { .. })
64 }
65}
66
67#[derive(Debug, Clone, Default)]
72pub struct ClassSchema {
73 pub class_name: String,
74 pub fields: IndexMap<String, FieldType>,
75}
76
77impl ClassSchema {
78 pub fn new(class_name: impl Into<String>) -> Self {
79 Self {
80 class_name: class_name.into(),
81 fields: IndexMap::new(),
82 }
83 }
84
85 pub fn with_field(mut self, name: impl Into<String>, ty: FieldType) -> Self {
86 self.fields.insert(name.into(), ty);
87 self
88 }
89
90 pub fn field(&self, name: &str) -> Option<&FieldType> {
91 self.fields.get(name)
92 }
93
94 pub fn is_pointer_field(&self, name: &str) -> bool {
100 self.field(name).is_some_and(FieldType::is_pointer)
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn parametric_types_render_with_angle_brackets() {
110 assert_eq!(
111 FieldType::Pointer {
112 target_class: "_User".into()
113 }
114 .to_wire_string(),
115 "Pointer<_User>"
116 );
117 assert_eq!(
118 FieldType::Relation {
119 target_class: "Post".into()
120 }
121 .to_wire_string(),
122 "Relation<Post>"
123 );
124 assert_eq!(FieldType::String.to_wire_string(), "String");
125 }
126
127 #[test]
128 fn only_declared_pointer_fields_are_prefixed() {
129 let s = ClassSchema::new("Post").with_field(
130 "author",
131 FieldType::Pointer {
132 target_class: "_User".into(),
133 },
134 );
135 assert!(s.is_pointer_field("author"));
136 assert!(!s.is_pointer_field("undeclared"));
137 }
138}