solomon_gremlin/structure/
map.rs1use crate::error::GremlinError;
2use crate::structure::{Edge, GValue, Vertex};
3use crate::GremlinResult;
4use crate::Token;
5use std::collections::hash_map::IntoIter;
6use std::collections::{BTreeMap, HashMap};
7use std::convert::{TryFrom, TryInto};
8
9#[derive(Debug, PartialEq, Clone)]
12pub struct Map(HashMap<GKey, GValue>);
13
14impl Map {
15 pub fn empty() -> Map {
16 Map(HashMap::default())
17 }
18}
19
20impl From<HashMap<GKey, GValue>> for Map {
21 fn from(val: HashMap<GKey, GValue>) -> Self {
22 Map(val)
23 }
24}
25
26impl From<Map> for HashMap<GKey, GValue> {
27 fn from(map: Map) -> Self {
28 map.0
29 }
30}
31
32impl From<HashMap<String, GValue>> for Map {
33 fn from(val: HashMap<String, GValue>) -> Self {
34 let map = val.into_iter().map(|(k, v)| (GKey::String(k), v)).collect();
35 Map(map)
36 }
37}
38
39impl TryFrom<Map> for HashMap<String, GValue> {
40 type Error = GremlinError;
41
42 fn try_from(map: Map) -> Result<Self, Self::Error> {
43 map.into_iter().map(|(k, v)| Ok((k.try_into()?, v))).collect()
44 }
45}
46
47impl From<BTreeMap<String, GValue>> for Map {
48 fn from(val: BTreeMap<String, GValue>) -> Self {
49 let map = val.into_iter().map(|(k, v)| (GKey::String(k), v)).collect();
50 Map(map)
51 }
52}
53
54impl TryFrom<Map> for BTreeMap<String, GValue> {
55 type Error = GremlinError;
56
57 fn try_from(map: Map) -> Result<Self, Self::Error> {
58 map.into_iter().map(|(k, v)| Ok((k.try_into()?, v))).collect()
59 }
60}
61
62impl Map {
63 pub fn remove<T>(&mut self, key: T) -> Option<GValue>
64 where
65 T: Into<GKey>,
66 {
67 self.0.remove(&key.into())
68 }
69 pub fn iter(&self) -> impl Iterator<Item = (&GKey, &GValue)> {
71 self.0.iter()
72 }
73
74 pub fn get<T>(&self, key: T) -> Option<&GValue>
76 where
77 T: Into<GKey>,
78 {
79 self.0.get(&key.into())
80 }
81
82 pub fn try_get<K, V>(&self, key: K) -> GremlinResult<V>
84 where
85 K: Into<GKey>,
86 V: std::convert::TryFrom<GValue, Error = GremlinError>,
87 {
88 self.0
89 .get(&key.into())
90 .cloned()
91 .or(Some(GValue::Null))
92 .map(V::try_from)
93 .ok_or_else(|| GremlinError::Cast(String::from("field not found")))?
94 }
95
96 pub fn len(&self) -> usize {
98 self.0.len()
99 }
100
101 pub fn is_empty(&self) -> bool {
103 self.0.is_empty()
104 }
105}
106
107impl<T: Into<GKey>> std::ops::Index<T> for Map {
108 type Output = GValue;
109
110 fn index(&self, key: T) -> &GValue {
111 self.0.get(&key.into()).expect("no entry found for key")
112 }
113}
114
115impl IntoIterator for Map {
116 type Item = (GKey, GValue);
117 type IntoIter = IntoIter<GKey, GValue>;
118 fn into_iter(self) -> Self::IntoIter {
119 self.0.into_iter()
120 }
121}
122
123impl std::iter::FromIterator<(String, GValue)> for Map {
124 fn from_iter<I: IntoIterator<Item = (String, GValue)>>(iter: I) -> Self {
125 Map(iter.into_iter().map(|(k, v)| (GKey::String(k), v)).collect())
126 }
127}
128
129#[allow(clippy::large_enum_variant)]
131#[derive(Debug, PartialEq, Clone, Eq, Hash)]
132pub enum GKey {
133 String(String),
134 Token(Token),
135 Vertex(Vertex),
136 Edge(Edge),
137}
138
139impl From<&str> for GKey {
140 fn from(val: &str) -> Self {
141 GKey::String(String::from(val))
142 }
143}
144
145impl From<String> for GKey {
146 fn from(val: String) -> Self {
147 GKey::String(val)
148 }
149}
150
151impl TryFrom<GKey> for String {
152 type Error = GremlinError;
153
154 fn try_from(k: GKey) -> Result<Self, Self::Error> {
155 if let GKey::String(s) = k {
156 Ok(s)
157 } else {
158 Err(GremlinError::Cast(format!("Cannot cast from {:?} to String", k)))
159 }
160 }
161}
162
163impl From<&Vertex> for GKey {
164 fn from(val: &Vertex) -> Self {
165 GKey::Vertex(val.clone())
166 }
167}
168
169impl From<&Edge> for GKey {
170 fn from(val: &Edge) -> Self {
171 GKey::Edge(val.clone())
172 }
173}