1use crate::{data::Object, Value, Variable};
2use dashmap::DashMap;
3
4#[derive(Clone, Debug)]
5pub enum FieldType {
6 Node(Field),
7 Leaf(String),
8}
9
10#[derive(Debug, Clone)]
11pub struct Field {
12 pub(crate) name: String,
13 pub(crate) alias: Option<String>,
14 pub(crate) arguments: Object,
15 pub(crate) fields: Vec<FieldType>,
16 pub(crate) paginate: bool,
17 pub(crate) paginate_name: bool,
18}
19
20impl Field {
21 pub fn set_name(mut self, name: String) -> Self {
22 self.name = name;
23 self
24 }
25
26 pub fn set_alias(mut self, alias: String) -> Self {
27 self.alias = Some(alias);
28 self
29 }
30
31 pub fn set_argument(self, name: String, value: Value) -> Self {
32 self.arguments.insert(name, value);
33 self
34 }
35
36 pub fn add_field(mut self, field: FieldType) -> Self {
37 self.fields.push(field);
38 self
39 }
40
41 pub fn add_field_node(mut self, field: Field) -> Self {
42 self.fields.push(FieldType::Node(field));
43 self
44 }
45
46 pub fn add_field_leaf(mut self, field: &str) -> Self {
47 self.fields.push(FieldType::Leaf(field.into()));
48 self
49 }
50
51 pub fn will_paginate(mut self) -> Self {
52 self.paginate = true;
53 self.paginate_name = true;
54 self
55 }
56
57 pub fn is_paginated(mut self) -> Self {
58 self.paginate = true;
59 self
60 }
61
62 pub(crate) fn get_variables(&self) -> Vec<Variable> {
63 let mut vars = Vec::new();
64 for i in self.arguments.iter() {
65 if let Value::Variable(variable) = i.value() {
66 vars.push(variable.clone());
67 }
68 }
69 for field in &self.fields {
70 match field {
71 FieldType::Node(field) => vars.extend(field.get_variables()),
72 FieldType::Leaf(_) => {},
73 }
74 }
75 vars
76 }
77
78 pub(crate) fn tree_will_paginate(&self) -> bool {
79 if self.paginate {
80 return true;
81 }
82 for field in &self.fields {
83 match field {
84 FieldType::Node(field) => {
85 if field.tree_will_paginate() {
86 return true;
87 }
88 },
89 FieldType::Leaf(_) => {},
90 }
91 }
92 false
93 }
94
95 pub(crate) fn valid(&self) -> Result<(), String> {
96 if self.name.is_empty() {
97 return Err("Field name cannot be empty".into());
98 }
99 Ok(())
100 }
101}
102
103impl Default for Field {
104 fn default() -> Self {
105 Self {
106 name: String::new(),
107 alias: None,
108 arguments: DashMap::new(),
109 fields: Vec::new(),
110 paginate: false,
111 paginate_name: false,
112 }
113 }
114}
115
116pub fn field(name: &str) -> Field {
117 Field::default().set_name(name.into())
118}
119
120pub fn field_as(name: &str, alias: &str) -> Field {
121 Field::default()
122 .set_name(name.into())
123 .set_alias(alias.into())
124}