1use chrono::{DateTime, FixedOffset, Utc};
2
3use crate::{format_query_fields, StampMode};
4
5#[derive(Debug, Clone, Copy, PartialEq)]
7pub enum Stamps {
8 None,
9 Created(&'static str),
10 Updated(&'static str),
11 Both(&'static str, &'static str),
12}
13impl Stamps {
14 pub fn from_fields(fields: &[&'static str]) -> (Stamps, Vec<&'static str>) {
19 let mut has_created_at = false;
20 let mut has_updated_at = false;
21 let mut has_created = false;
22 let mut has_updated = false;
23 let mut non_stamp_fields = Vec::new();
24 for field in fields {
25 match field.as_ref() {
26 "created_at" => has_created_at = true,
27 "updated_at" => has_updated_at = true,
28 "created" => has_created = true,
29 "updated" => has_updated = true,
30 _ => non_stamp_fields.push(*field),
31 }
32 }
33 let created_field = if has_created_at {
34 if has_created {
35 non_stamp_fields.push("created")
36 }
37 Some("created_at")
38 } else if has_created {
39 Some("created")
40 } else {
41 None
42 };
43 let updated_field = if has_updated_at {
44 if has_updated {
45 non_stamp_fields.push("updated")
46 }
47 Some("updated_at")
48 } else if has_updated {
49 Some("updated")
50 } else {
51 None
52 };
53 let stamps = match (created_field, updated_field) {
54 (Some(created), Some(updated)) => Stamps::Both(created, updated),
55 (Some(created), None) => Stamps::Created(created),
56 (None, Some(updated)) => Stamps::Updated(updated),
57 (None, None) => Stamps::None,
58 };
59 (stamps, non_stamp_fields)
60 }
61
62 pub fn as_query_fields(&self, prefix: Option<&str>, mode: StampMode) -> String {
64 if self == &Stamps::None {
65 return "".to_owned();
66 }
67 match mode {
68 StampMode::Read => {
70 let (created, updated) = self.field_names();
71 format_query_fields([created, updated], prefix)
72 }
73 StampMode::Create => match self {
75 Stamps::None => "".to_owned(),
76 Stamps::Created(name) => format!("{}: datetime()", name),
77 Stamps::Updated(name) => format!("{}: datetime()", name),
78 Stamps::Both(created, updated) => {
79 format!("{}: datetime(), {}: datetime()", created, updated)
80 }
81 },
82 StampMode::Update => match self {
84 Stamps::None => "".to_owned(),
85 Stamps::Created(name) => format_query_fields([name], prefix),
86 Stamps::Updated(name) => format!("{}: datetime()", name),
87 Stamps::Both(created, updated) => {
88 format!(
89 "{}, {}: datetime()",
90 format_query_fields([created], prefix),
91 updated
92 )
93 }
94 },
95 }
96 }
97
98 fn field_names(&self) -> (&'static str, &'static str) {
102 match self {
103 Stamps::None => ("", ""),
104 Stamps::Created(name) => (*name, ""),
105 Stamps::Updated(name) => ("", *name),
106 Stamps::Both(created, updated) => (*created, *updated),
107 }
108 }
109}
110
111pub enum Neo4jMap<'a> {
113 Row(&'a neo4rs::Row),
114 Node(&'a neo4rs::Node),
115 Relation(&'a neo4rs::Relation),
116 UnboundedRelation(&'a neo4rs::UnboundedRelation),
117}
118impl<'a> Neo4jMap<'a> {
119 pub fn get_timestamp(&self, name: &str) -> Result<DateTime<Utc>, crate::Error> {
120 match self {
121 Neo4jMap::Row(value) => value
122 .get::<DateTime<FixedOffset>>(name)
123 .map(|dt| dt.into())
124 .map_err(|_e| crate::Error::MissingField(name.to_owned())),
125 Neo4jMap::Node(value) => value
126 .get::<DateTime<FixedOffset>>(name)
127 .map(|dt| dt.into())
128 .map_err(|_e| crate::Error::MissingField(name.to_owned())),
129 Neo4jMap::Relation(value) => value
130 .get::<DateTime<FixedOffset>>(name)
131 .map(|dt| dt.into())
132 .map_err(|_e| crate::Error::MissingField(name.to_owned())),
133 Neo4jMap::UnboundedRelation(value) => value
134 .get::<DateTime<FixedOffset>>(name)
135 .map(|dt| dt.into())
136 .map_err(|_e| crate::Error::MissingField(name.to_owned())),
137 }
138 }
139}