keepass_ng/db/
node.rs

1use crate::{
2    Result,
3    db::{Entry, Group, Times, iconid::IconId},
4};
5use std::collections::VecDeque;
6use uuid::Uuid;
7
8pub type NodePtr = std::rc::Rc<std::cell::RefCell<dyn Node>>;
9
10#[derive(Debug, Clone)]
11pub struct SerializableNodePtr {
12    node_ptr: NodePtr,
13}
14
15impl PartialEq for SerializableNodePtr {
16    fn eq(&self, other: &Self) -> bool {
17        node_is_equals_to(&self.node_ptr, &other.node_ptr)
18    }
19}
20
21impl Eq for SerializableNodePtr {}
22
23#[cfg(feature = "serialization")]
24impl serde::ser::Serialize for SerializableNodePtr {
25    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
26    where
27        S: serde::ser::Serializer,
28    {
29        self.node_ptr.borrow().serialize(serializer)
30    }
31}
32
33impl From<NodePtr> for SerializableNodePtr {
34    fn from(node: NodePtr) -> Self {
35        SerializableNodePtr { node_ptr: node }
36    }
37}
38
39impl From<&NodePtr> for SerializableNodePtr {
40    fn from(node: &NodePtr) -> Self {
41        SerializableNodePtr { node_ptr: node.clone() }
42    }
43}
44
45impl From<SerializableNodePtr> for NodePtr {
46    fn from(serializable: SerializableNodePtr) -> Self {
47        serializable.node_ptr
48    }
49}
50
51impl From<&SerializableNodePtr> for NodePtr {
52    fn from(serializable: &SerializableNodePtr) -> Self {
53        serializable.node_ptr.clone()
54    }
55}
56
57impl AsRef<NodePtr> for SerializableNodePtr {
58    fn as_ref(&self) -> &NodePtr {
59        &self.node_ptr
60    }
61}
62
63impl AsMut<NodePtr> for SerializableNodePtr {
64    fn as_mut(&mut self) -> &mut NodePtr {
65        &mut self.node_ptr
66    }
67}
68
69impl std::ops::Deref for SerializableNodePtr {
70    type Target = NodePtr;
71
72    fn deref(&self) -> &Self::Target {
73        &self.node_ptr
74    }
75}
76
77impl std::ops::DerefMut for SerializableNodePtr {
78    fn deref_mut(&mut self) -> &mut Self::Target {
79        &mut self.node_ptr
80    }
81}
82
83pub fn rc_refcell_node<T: Node>(e: T) -> NodePtr {
84    std::rc::Rc::new(std::cell::RefCell::new(e)) as NodePtr
85}
86
87/// Get a reference to a node if it is of the specified type
88/// and call the closure with the reference.
89/// Usage:
90/// ```no_run
91/// use keepass_ng::db::{with_node, Entry, Group, NodePtr, rc_refcell_node};
92///
93/// let node: NodePtr = rc_refcell_node(Group::new("group"));
94/// with_node::<Group, _, _>(&node, |group| {
95///     // do something with group
96/// });
97///
98/// with_node::<Entry, _, _>(&node, |entry| {
99///     // do something with entry
100/// });
101/// ```
102pub fn with_node<T, F, R>(node: &NodePtr, f: F) -> Option<R>
103where
104    T: 'static,
105    F: FnOnce(&T) -> R,
106{
107    node.borrow().downcast_ref::<T>().map(f)
108}
109
110/// Get a mutable reference to a node if it is of the specified type
111/// and call the closure with the mutable reference.
112/// Usage:
113/// ```no_run
114/// use keepass_ng::db::{with_node_mut, Entry, Group, NodePtr, rc_refcell_node};
115///
116/// let node: NodePtr = rc_refcell_node(Group::new("group"));
117/// with_node_mut::<Group, _, _>(&node, |group| {
118///     // do something with group
119/// });
120///
121/// with_node_mut::<Entry, _, _>(&node, |entry| {
122///     // do something with entry
123/// });
124/// ```
125pub fn with_node_mut<T, F, R>(node: &NodePtr, f: F) -> Option<R>
126where
127    T: 'static,
128    F: FnOnce(&mut T) -> R,
129{
130    node.borrow_mut().downcast_mut::<T>().map(f)
131}
132
133pub fn node_is_entry(entry: &NodePtr) -> bool {
134    with_node::<Entry, _, _>(entry, |_| true).unwrap_or(false)
135}
136
137pub fn node_is_group(group: &NodePtr) -> bool {
138    with_node::<Group, _, _>(group, |_| true).unwrap_or(false)
139}
140
141pub fn group_get_children(group: &NodePtr) -> Option<Vec<NodePtr>> {
142    with_node::<Group, _, _>(group, |g| g.get_children())
143}
144
145pub fn group_add_child(parent: &NodePtr, child: NodePtr, index: usize) -> Result<()> {
146    with_node_mut::<Group, _, _>(parent, |parent| {
147        parent.add_child(child, index);
148        Ok::<_, crate::Error>(())
149    })
150    .unwrap_or(Err("parent is not a group".into()))?;
151    Ok(())
152}
153
154pub fn group_remove_node_by_uuid(root: &NodePtr, uuid: Uuid) -> crate::Result<NodePtr> {
155    let root_uuid = root.borrow().get_uuid();
156    if root_uuid == uuid {
157        return Err("Cannot remove root node".into());
158    }
159
160    let node = search_node_by_uuid(root, uuid).ok_or("Node not found")?;
161    let parent_uuid = node.borrow().get_parent().ok_or("Node has no parent")?;
162    let err = format!("Parent \"{parent_uuid}\" not found");
163    let parent = search_node_by_uuid_with_specific_type::<Group>(root, parent_uuid).ok_or(err)?;
164    with_node_mut::<Group, _, _>(&parent, |parent| {
165        parent.children.retain(|c| c.borrow().get_uuid() != uuid);
166        Ok::<_, crate::Error>(())
167    })
168    .unwrap_or(Err(crate::Error::from("Not a group")))?;
169
170    Ok(node)
171}
172
173pub fn node_is_equals_to(node: &NodePtr, other: &NodePtr) -> bool {
174    if with_node::<Entry, _, _>(node, |e1| with_node::<Entry, _, _>(other, |e2| e1 == e2).unwrap_or(false)).unwrap_or(false) {
175        return true;
176    }
177    with_node::<Group, _, _>(node, |g1| with_node::<Group, _, _>(other, |g2| g1 == g2).unwrap_or(false)).unwrap_or(false)
178}
179
180pub fn search_node_by_uuid(root: &NodePtr, uuid: Uuid) -> Option<NodePtr> {
181    NodeIterator::new(root).find(|n| n.borrow().get_uuid() == uuid)
182}
183
184pub fn search_node_by_uuid_with_specific_type<'a, T>(root: &'a NodePtr, uuid: Uuid) -> Option<NodePtr>
185where
186    T: 'a + 'static,
187{
188    NodeIterator::new(root)
189        .filter(|n| with_node::<T, _, _>(n, |_| true).is_some())
190        .find(|n| n.borrow().get_uuid() == uuid)
191}
192
193#[cfg(feature = "serialization")]
194pub trait Node: std::any::Any + std::fmt::Debug + erased_serde::Serialize {
195    fn duplicate(&self) -> NodePtr;
196    fn get_uuid(&self) -> Uuid;
197    fn set_uuid(&mut self, uuid: Uuid);
198    fn get_title(&self) -> Option<&str>;
199    fn set_title(&mut self, title: Option<&str>);
200    fn get_notes(&self) -> Option<&str>;
201    fn set_notes(&mut self, notes: Option<&str>);
202    fn get_icon_id(&self) -> Option<IconId>;
203    fn set_icon_id(&mut self, icon_id: Option<IconId>);
204    fn get_custom_icon_uuid(&self) -> Option<Uuid>;
205
206    /// Get a timestamp field by name
207    ///
208    /// Returning the `NaiveDateTime` which does not include timezone
209    /// or UTC offset because `KeePass` clients typically store timestamps
210    /// relative to the local time on the machine writing the data without
211    /// including accurate UTC offset or timezone information.
212    fn get_times(&self) -> &Times;
213    fn get_times_mut(&mut self) -> &mut Times;
214
215    fn get_parent(&self) -> Option<Uuid>;
216    fn set_parent(&mut self, parent: Option<Uuid>);
217}
218
219#[cfg(feature = "serialization")]
220erased_serde::serialize_trait_object!(Node);
221
222#[cfg(not(feature = "serialization"))]
223pub trait Node: std::any::Any + std::fmt::Debug {
224    fn duplicate(&self) -> NodePtr;
225    fn get_uuid(&self) -> Uuid;
226    fn set_uuid(&mut self, uuid: Uuid);
227    fn get_title(&self) -> Option<&str>;
228    fn set_title(&mut self, title: Option<&str>);
229    fn get_notes(&self) -> Option<&str>;
230    fn set_notes(&mut self, notes: Option<&str>);
231    fn get_icon_id(&self) -> Option<IconId>;
232    fn set_icon_id(&mut self, icon_id: Option<IconId>);
233    fn get_custom_icon_uuid(&self) -> Option<Uuid>;
234    fn get_times(&self) -> &Times;
235    fn get_times_mut(&mut self) -> &mut Times;
236    fn get_parent(&self) -> Option<Uuid>;
237    fn set_parent(&mut self, parent: Option<Uuid>);
238}
239
240impl dyn Node {
241    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
242        (self as &dyn std::any::Any).downcast_ref()
243    }
244}
245
246impl dyn Node {
247    pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
248        (self as &mut dyn std::any::Any).downcast_mut()
249    }
250}
251
252pub struct NodeIterator {
253    queue: VecDeque<NodePtr>,
254}
255
256impl NodeIterator {
257    pub fn new(root: &NodePtr) -> Self {
258        let mut queue = VecDeque::new();
259        queue.push_back(root.clone());
260        Self { queue }
261    }
262}
263
264impl Iterator for NodeIterator {
265    type Item = NodePtr;
266
267    fn next(&mut self) -> Option<Self::Item> {
268        let next = self.queue.pop_front()?;
269        if let Some(children) = group_get_children(&next) {
270            self.queue.extend(children);
271        }
272        Some(next)
273    }
274}