1use doublets::data::LinkReference;
17
18use crate::error::LinkError;
19use crate::link::{GenericLink, Link};
20use crate::link_storage::LinkStorage;
21use crate::named_types::NamedTypesDecorator;
22use crate::pinned_types::PinnedTypesDecorator;
23use crate::storage::traits::{LinksStorage, LinksStorageRef, StorageRevision};
24
25fn storage_error(error: anyhow::Error) -> LinkError {
26 LinkError::StorageError(format!("{error:#}"))
27}
28
29macro_rules! impl_in_memory_links_storage {
33 ($type:ty, $create:expr, $flush:expr, $external:expr, $reload:expr) => {
34 impl LinksStorage<u32> for $type {
35 fn create_link(&mut self, source: u32, target: u32) -> Result<u32, LinkError> {
36 #[allow(clippy::redundant_closure_call)]
37 Ok($create(self, source, target))
38 }
39
40 fn ensure_link_created(&mut self, index: u32) -> Result<u32, LinkError> {
41 Ok(self.ensure_created(index))
42 }
43
44 fn get_link(&self, index: u32) -> Option<GenericLink<u32>> {
45 self.get(index).copied()
46 }
47
48 fn link_exists(&self, index: u32) -> bool {
49 self.exists(index)
50 }
51
52 fn update_link(
53 &mut self,
54 index: u32,
55 source: u32,
56 target: u32,
57 ) -> Result<GenericLink<u32>, LinkError> {
58 self.update(index, source, target).map_err(storage_error)
59 }
60
61 fn delete_link(&mut self, index: u32) -> Result<GenericLink<u32>, LinkError> {
62 self.delete(index).map_err(storage_error)
63 }
64
65 fn update_link_observed(
66 &mut self,
67 index: u32,
68 source: u32,
69 target: u32,
70 observer: &mut dyn FnMut(GenericLink<u32>, GenericLink<u32>),
71 ) -> Result<GenericLink<u32>, LinkError> {
72 self.update_observed(index, source, target, observer)
73 .map_err(storage_error)
74 }
75
76 fn delete_link_observed(
77 &mut self,
78 index: u32,
79 observer: &mut dyn FnMut(GenericLink<u32>, GenericLink<u32>),
80 ) -> Result<GenericLink<u32>, LinkError> {
81 self.delete_observed(index, observer).map_err(storage_error)
82 }
83
84 fn all_links(&self) -> Vec<GenericLink<u32>> {
85 self.all().into_iter().copied().collect()
86 }
87
88 fn query_links(
89 &self,
90 index: Option<u32>,
91 source: Option<u32>,
92 target: Option<u32>,
93 ) -> Vec<GenericLink<u32>> {
94 self.query(index, source, target)
95 .into_iter()
96 .copied()
97 .collect()
98 }
99
100 fn search_link(&self, source: u32, target: u32) -> Option<u32> {
101 self.search(source, target)
102 }
103
104 fn get_or_create_link(&mut self, source: u32, target: u32) -> Result<u32, LinkError> {
105 Ok(self.get_or_create(source, target))
106 }
107
108 fn flush(&mut self) -> Result<(), LinkError> {
109 #[allow(clippy::redundant_closure_call)]
110 $flush(self)
111 }
112
113 fn has_external_changes(&self) -> Result<bool, LinkError> {
114 #[allow(clippy::redundant_closure_call)]
115 $external(self)
116 }
117
118 fn reload(&mut self) -> Result<(), LinkError> {
119 #[allow(clippy::redundant_closure_call)]
120 $reload(self)
121 }
122 }
123
124 impl LinksStorageRef<u32> for $type {
125 fn get_link_ref(&self, index: u32) -> Option<&Link> {
126 self.get(index)
127 }
128
129 fn all_link_refs(&self) -> Vec<&Link> {
130 self.all()
131 }
132
133 fn query_link_refs(
134 &self,
135 index: Option<u32>,
136 source: Option<u32>,
137 target: Option<u32>,
138 ) -> Vec<&Link> {
139 self.query(index, source, target)
140 }
141 }
142 };
143}
144
145impl_in_memory_links_storage!(
146 LinkStorage,
147 |storage: &mut LinkStorage, source, target| storage.create(source, target),
148 |storage: &mut LinkStorage| {
149 storage.save().map_err(storage_error)?;
150 storage.refresh_observed_revision()
151 },
152 |storage: &LinkStorage| {
153 Ok(StorageRevision::of(storage.database_path())? != storage.observed_revision())
154 },
155 |storage: &mut LinkStorage| storage.reload_from_disk().map_err(storage_error)
156);
157
158impl_in_memory_links_storage!(
159 PinnedTypesDecorator,
160 |storage: &mut PinnedTypesDecorator, source, target| storage.create(source, target),
161 |storage: &mut PinnedTypesDecorator| {
162 storage.save().map_err(storage_error)?;
163 storage.links_mut().refresh_observed_revision()
164 },
165 |storage: &PinnedTypesDecorator| storage.links().has_external_changes(),
166 |storage: &mut PinnedTypesDecorator| storage.links_mut().reload()
167);
168
169impl_in_memory_links_storage!(
170 NamedTypesDecorator,
171 |storage: &mut NamedTypesDecorator, source, target| storage.create(source, target),
172 |storage: &mut NamedTypesDecorator| {
173 storage.save().map_err(storage_error)?;
174 storage.links_mut().refresh_observed_revision()?;
175 storage.names_links_mut().refresh_observed_revision()
176 },
177 |storage: &NamedTypesDecorator| {
178 Ok(storage.links().has_external_changes()?
179 || storage.names_links().has_external_changes()?)
180 },
181 |storage: &mut NamedTypesDecorator| {
182 storage.links_mut().reload()?;
183 storage.names_links_mut().reload()
184 }
185);
186
187#[allow(dead_code)]
190fn assert_generic_over_address<T: LinkReference, S: LinksStorage<T>>(_storage: &S) {}