1use crate::{LabelId, RelTypeId, Value};
16use std::collections::{BTreeMap, BTreeSet};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct NodeId(pub u64);
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct NodeRecord {
23 pub id: NodeId,
24 pub labels: BTreeSet<LabelId>,
25 pub properties: BTreeMap<String, Value>,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct ProjectedNodeRecord {
35 pub id: NodeId,
36 pub labels: BTreeSet<LabelId>,
37 pub properties: BTreeMap<String, Value>,
38}
39
40#[doc(hidden)]
41pub fn project_node_record(
42 node: NodeRecord,
43 required_properties: &BTreeSet<String>,
44) -> ProjectedNodeRecord {
45 let properties = required_properties
46 .iter()
47 .filter_map(|property| {
48 node.properties
49 .get(property)
50 .cloned()
51 .map(|value| (property.clone(), value))
52 })
53 .collect();
54 ProjectedNodeRecord {
55 id: node.id,
56 labels: node.labels,
57 properties,
58 }
59}
60
61#[doc(hidden)]
64pub fn project_node_record_ref(
65 node: &NodeRecord,
66 required_properties: &BTreeSet<String>,
67) -> ProjectedNodeRecord {
68 ProjectedNodeRecord {
69 id: node.id,
70 labels: node.labels.clone(),
71 properties: required_properties
72 .iter()
73 .filter_map(|name| {
74 node.properties
75 .get(name)
76 .map(|value| (name.clone(), value.clone()))
77 })
78 .collect(),
79 }
80}
81
82#[doc(hidden)]
85pub fn projected_node_allocation_bytes(
86 node: &NodeRecord,
87 required_properties: &BTreeSet<String>,
88) -> usize {
89 std::mem::size_of::<ProjectedNodeRecord>()
90 .saturating_add(node.labels.len().saturating_mul(128))
91 .saturating_add(properties_allocation_bytes(
92 required_properties.iter().filter_map(|name| {
93 node.properties
94 .get(name)
95 .map(|value| (name.as_str(), value))
96 }),
97 ))
98}
99
100#[doc(hidden)]
102pub fn node_allocation_bytes(node: &NodeRecord) -> usize {
103 std::mem::size_of::<NodeRecord>()
104 .saturating_add(node.labels.len().saturating_mul(128))
105 .saturating_add(properties_allocation_bytes(
106 node.properties
107 .iter()
108 .map(|(name, value)| (name.as_str(), value)),
109 ))
110}
111
112fn properties_allocation_bytes<'a>(
113 properties: impl Iterator<Item = (&'a str, &'a Value)>,
114) -> usize {
115 let (count, payload) = properties.fold((0usize, 0usize), |(count, payload), (name, value)| {
116 (
117 count.saturating_add(1),
118 payload
119 .saturating_add(name.len())
120 .saturating_add(projected_value_allocation_bytes(value)),
121 )
122 });
123 if count == 0 {
124 return 0;
125 }
126 payload.saturating_add(property_container_allocation_bytes(count))
127}
128
129#[doc(hidden)]
132pub fn property_container_allocation_bytes(count: usize) -> usize {
133 if count == 0 {
134 return 0;
135 }
136 let pair_bytes = std::mem::size_of::<(String, Value)>();
140 let node_bytes = pair_bytes
141 .saturating_mul(11)
142 .saturating_add(std::mem::size_of::<usize>().saturating_mul(12))
143 .saturating_add(32);
144 let nodes = if count <= 11 {
145 1
146 } else {
147 1usize.saturating_add((count - 1) / 5)
148 };
149 nodes
150 .saturating_mul(node_bytes)
151 .saturating_add(count.saturating_mul(2).max(4).saturating_mul(pair_bytes))
152}
153
154#[doc(hidden)]
156pub fn projected_value_allocation_bytes(value: &Value) -> usize {
157 std::mem::size_of::<Value>().saturating_add(match value {
158 Value::String(value) => value.len(),
159 Value::Binary(value) => value.len(),
160 Value::Vector(value) => value.encoded().len(),
161 Value::List(values) => values.iter().fold(32usize, |total, value| {
162 total.saturating_add(projected_value_allocation_bytes(value).saturating_mul(2))
163 }),
164 Value::Map(values) => {
165 properties_allocation_bytes(values.iter().map(|(key, value)| (key.as_str(), value)))
166 }
167 _ => 0,
168 })
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
172pub struct RelId(pub u64);
173
174#[derive(Debug, Clone, PartialEq, Eq)]
175pub struct RelRecord {
176 pub id: RelId,
177 pub source: NodeId,
178 pub target: NodeId,
179 pub rel_type: RelTypeId,
180 pub properties: BTreeMap<String, Value>,
181}
182
183#[doc(hidden)]
185pub fn relationship_allocation_bytes(relationship: &RelRecord) -> usize {
186 std::mem::size_of::<RelRecord>().saturating_add(properties_allocation_bytes(
187 relationship
188 .properties
189 .iter()
190 .map(|(name, value)| (name.as_str(), value)),
191 ))
192}