1use deepsize::DeepSizeOf;
2use serde::{Deserialize, Serialize};
3use zerocopy::{FromBytes, Immutable, IntoBytes};
4
5pub type NodeId = u64;
6pub type EdgeId = u64;
7pub type LabelId = u32;
8pub type TypeId = u32;
9pub type PropKeyId = u32;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13#[repr(u8)]
14pub enum Language {
15 English = 1,
16 Spanish = 2,
17 French = 3,
18 German = 4,
19 Italian = 5,
20 Portuguese = 6,
21}
22
23impl Default for Language {
24 fn default() -> Self {
25 Self::English
26 }
27}
28
29impl Language {
30 pub fn from_u8(val: u8) -> Self {
31 match val {
32 2 => Self::Spanish,
33 3 => Self::French,
34 4 => Self::German,
35 5 => Self::Italian,
36 6 => Self::Portuguese,
37 _ => Self::English,
38 }
39 }
40
41 pub fn to_u8(self) -> u8 {
42 self as u8
43 }
44}
45
46impl std::str::FromStr for Language {
47 type Err = crate::error::Error;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 match s.to_lowercase().as_str() {
54 "english" => Ok(Self::English),
55 "spanish" => Ok(Self::Spanish),
56 "french" => Ok(Self::French),
57 "german" => Ok(Self::German),
58 "italian" => Ok(Self::Italian),
59 "portuguese" => Ok(Self::Portuguese),
60 other => Err(crate::error::Error::InvalidArgument(format!(
61 "unknown language '{other}' (expected one of: english, spanish, french, german, italian, portuguese)"
62 ))),
63 }
64 }
65}
66
67#[derive(Clone, Copy, Debug, IntoBytes, FromBytes, Immutable)]
73#[repr(C, packed)]
74pub struct AdjEntry {
75 pub edge_type: TypeId, pub other: NodeId, pub edge_id: EdgeId, }
79
80impl DeepSizeOf for AdjEntry {
81 fn deep_size_of_children(&self, _context: &mut deepsize::Context) -> usize {
82 0
84 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, DeepSizeOf)]
93pub struct NodeRecord {
94 pub labels: Vec<LabelId>,
95 pub props: Vec<u8>, }
97
98impl NodeRecord {
99 pub fn primary_label(&self) -> Option<LabelId> {
102 self.labels.first().copied()
103 }
104
105 pub fn has_label(&self, id: LabelId) -> bool {
107 self.labels.contains(&id)
108 }
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize, DeepSizeOf)]
113pub struct EdgeRecord {
114 pub src: NodeId,
115 pub dst: NodeId,
116 pub edge_type: TypeId,
117 pub props: Vec<u8>, }
119
120#[derive(Debug, Clone, PartialEq)]
123pub struct NeighborEntry {
124 pub node: NodeId,
125 pub edge: EdgeId,
126 pub edge_type: TypeId,
127}
128
129#[derive(Debug, Clone, PartialEq)]
131pub struct DirectedNeighborEntry {
132 pub node: NodeId,
133 pub edge: EdgeId,
134 pub edge_type: TypeId,
135 pub outgoing: bool,
137}
138
139#[derive(Debug, Clone, PartialEq)]
141pub struct WeightedPath {
142 pub nodes: Vec<NodeId>,
143 pub total_weight: f64,
144}
145
146#[derive(Debug, Clone, PartialEq)]
151pub enum PropValue {
152 Bool(bool),
153 Int(i64),
154 Float(f64),
155 Str(String),
156}
157
158impl PropValue {
159 pub(crate) fn into_json(self) -> serde_json::Value {
162 match self {
163 PropValue::Bool(b) => serde_json::Value::Bool(b),
164 PropValue::Int(i) => serde_json::Value::Number(i.into()),
165 PropValue::Float(f) => serde_json::json!(f),
166 PropValue::Str(s) => serde_json::Value::String(s),
167 }
168 }
169}
170
171impl From<bool> for PropValue {
172 fn from(v: bool) -> Self {
173 PropValue::Bool(v)
174 }
175}
176impl From<i64> for PropValue {
177 fn from(v: i64) -> Self {
178 PropValue::Int(v)
179 }
180}
181impl From<f64> for PropValue {
182 fn from(v: f64) -> Self {
183 PropValue::Float(v)
184 }
185}
186impl From<String> for PropValue {
187 fn from(v: String) -> Self {
188 PropValue::Str(v)
189 }
190}
191impl<'a> From<&'a str> for PropValue {
192 fn from(v: &'a str) -> Self {
193 PropValue::Str(v.to_string())
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200
201 #[test]
202 fn language_from_str_is_case_insensitive_and_rejects_unknown() {
203 assert_eq!("english".parse::<Language>().unwrap(), Language::English);
204 assert_eq!("German".parse::<Language>().unwrap(), Language::German);
205 assert_eq!(
206 "PORTUGUESE".parse::<Language>().unwrap(),
207 Language::Portuguese
208 );
209 assert!("klingon".parse::<Language>().is_err());
210 }
211}