1pub(crate) mod attachment;
2pub(crate) mod autotype;
3pub(crate) mod color;
4pub(crate) mod custom_data;
5pub(crate) mod entry;
6pub(crate) mod group;
7pub(crate) mod history;
8pub(crate) mod icon;
9pub(crate) mod meta;
10pub(crate) mod times;
11pub(crate) mod value;
12
13use std::collections::HashMap;
14
15pub use attachment::{Attachment, AttachmentId, AttachmentMut, AttachmentRef};
16pub use autotype::{AutoType, AutoTypeAssociation, DataTransferObfuscation};
17pub use color::{Color, ParseColorError};
18pub use custom_data::{CustomDataItem, CustomDataValue};
19pub use entry::{DestinationGroupNotFoundError, Entry, EntryId, EntryMut, EntryRef, EntryTrack};
20pub use group::{
21 DuplicateEntryIdError, DuplicateGroupIdError, Group, GroupId, GroupMut, GroupRef, GroupTrack,
22 MoveGroupError,
23};
24pub use history::History;
25pub use icon::{CustomIcon, CustomIconId, CustomIconMut, CustomIconNotFoundError, CustomIconRef, Icon};
26pub use meta::{MemoryProtection, Meta};
27pub use times::Times;
28pub use value::Value;
29
30use crate::config::DatabaseConfig;
31
32use chrono::NaiveDateTime;
33use uuid::Uuid;
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37#[cfg_attr(feature = "serialization", derive(serde::Serialize))]
38pub struct Database {
39 pub config: DatabaseConfig,
41
42 pub meta: Meta,
44
45 pub(crate) root: GroupId,
47
48 pub(crate) attachments: HashMap<AttachmentId, Attachment>,
50
51 pub(crate) custom_icons: HashMap<CustomIconId, CustomIcon>,
53
54 pub(crate) entries: HashMap<EntryId, Entry>,
56
57 pub(crate) groups: HashMap<GroupId, Group>,
59
60 pub deleted_objects: HashMap<Uuid, Option<NaiveDateTime>>,
62}
63
64impl Database {
65 #[allow(clippy::new_without_default)]
69 pub fn new() -> Self {
70 Self::new_with_root_id(GroupId::new())
71 }
72
73 pub fn with_config(config: DatabaseConfig) -> Self {
77 Self::with_data(config, GroupId::new())
78 }
79
80 pub fn new_with_root_id(root_id: GroupId) -> Self {
82 let root = Group::with_id(root_id, None);
83
84 let mut groups = HashMap::new();
85 groups.insert(root_id, root);
86
87 Database {
88 config: DatabaseConfig::default(),
89 meta: Meta::default(),
90 root: root_id,
91 attachments: HashMap::new(),
92 custom_icons: HashMap::new(),
93 entries: HashMap::new(),
94 groups,
95 deleted_objects: HashMap::new(),
96 }
97 }
98
99 pub(crate) fn with_data(config: DatabaseConfig, root_id: GroupId) -> Self {
100 let root = Group::with_id(root_id, None);
101
102 let mut groups = HashMap::new();
103 groups.insert(root_id, root);
104
105 Database {
106 config,
107 meta: Meta::default(),
108 root: root_id,
109 attachments: HashMap::new(),
110 custom_icons: HashMap::new(),
111 entries: HashMap::new(),
112 groups,
113 deleted_objects: HashMap::new(),
114 }
115 }
116
117 pub fn root(&self) -> GroupRef<'_> {
119 GroupRef::new(self, self.root)
120 }
121
122 pub fn root_mut(&mut self) -> GroupMut<'_> {
124 GroupMut::new(self, self.root)
125 }
126
127 pub fn recycle_bin(&self) -> Option<GroupRef<'_>> {
129 let recyclebin_id = self.meta.recyclebin_uuid.map(GroupId::from_uuid)?;
130 self.group(recyclebin_id)
131 }
132
133 pub fn recycle_bin_mut(&mut self) -> Option<GroupMut<'_>> {
135 let recyclebin_id = self.meta.recyclebin_uuid.map(GroupId::from_uuid)?;
136 self.group_mut(recyclebin_id)
137 }
138
139 pub fn num_attachments(&self) -> usize {
141 self.attachments.len()
142 }
143
144 pub fn num_custom_icons(&self) -> usize {
146 self.custom_icons.len()
147 }
148
149 pub fn num_entries(&self) -> usize {
151 self.entries.len()
152 }
153
154 pub fn num_groups(&self) -> usize {
156 self.groups.len()
157 }
158
159 pub fn iter_all_attachments(&self) -> impl Iterator<Item = AttachmentRef<'_>> + '_ {
161 self.attachments
162 .keys()
163 .map(move |id| AttachmentRef::new(self, *id))
164 }
165
166 pub fn foreach_attachment_mut<F>(&mut self, mut f: F)
169 where
170 F: FnMut(AttachmentMut<'_>),
171 {
172 let ids: Vec<AttachmentId> = self.attachments.keys().copied().collect();
173 for id in ids {
174 f(AttachmentMut::new(self, id));
175 }
176 }
177
178 pub fn iter_all_entries(&self) -> impl Iterator<Item = EntryRef<'_>> + '_ {
180 self.entries.keys().map(move |id| EntryRef::new(self, *id))
181 }
182
183 pub fn foreach_entry_mut<F>(&mut self, mut f: F)
186 where
187 F: FnMut(EntryMut<'_>),
188 {
189 let ids: Vec<EntryId> = self.entries.keys().copied().collect();
190 for id in ids {
191 f(EntryMut::new(self, id));
192 }
193 }
194
195 pub fn iter_all_custom_icons(&self) -> impl Iterator<Item = CustomIconRef<'_>> + '_ {
197 self.custom_icons
198 .keys()
199 .map(move |id| CustomIconRef::new(self, *id))
200 }
201
202 pub fn foreach_custom_icon_mut<F>(&mut self, mut f: F)
205 where
206 F: FnMut(CustomIconMut<'_>),
207 {
208 let ids: Vec<CustomIconId> = self.custom_icons.keys().copied().collect();
209 for id in ids {
210 f(CustomIconMut::new(self, id));
211 }
212 }
213
214 pub fn iter_all_groups(&self) -> impl Iterator<Item = GroupRef<'_>> + '_ {
217 self.groups.keys().map(move |id| GroupRef::new(self, *id))
218 }
219
220 pub fn foreach_group_mut<F>(&mut self, mut f: F)
223 where
224 F: FnMut(GroupMut<'_>),
225 {
226 let ids: Vec<GroupId> = self.groups.keys().copied().collect();
227 for id in ids {
228 f(GroupMut::new(self, id));
229 }
230 }
231
232 pub fn attachment(&self, id: AttachmentId) -> Option<AttachmentRef<'_>> {
234 self.attachments
235 .contains_key(&id)
236 .then(move || AttachmentRef::new(self, id))
237 }
238
239 pub fn attachment_mut(&mut self, id: AttachmentId) -> Option<AttachmentMut<'_>> {
241 self.attachments
242 .contains_key(&id)
243 .then(move || AttachmentMut::new(self, id))
244 }
245
246 pub fn custom_icon(&self, id: CustomIconId) -> Option<CustomIconRef<'_>> {
248 self.custom_icons
249 .contains_key(&id)
250 .then(move || CustomIconRef::new(self, id))
251 }
252
253 pub fn custom_icon_mut(&mut self, id: CustomIconId) -> Option<CustomIconMut<'_>> {
255 self.custom_icons
256 .contains_key(&id)
257 .then(move || CustomIconMut::new(self, id))
258 }
259
260 pub fn entry(&self, id: EntryId) -> Option<EntryRef<'_>> {
262 self.entries
263 .contains_key(&id)
264 .then(move || EntryRef::new(self, id))
265 }
266
267 pub fn entry_mut(&mut self, id: EntryId) -> Option<EntryMut<'_>> {
269 self.entries
270 .contains_key(&id)
271 .then(move || EntryMut::new(self, id))
272 }
273
274 pub fn group(&self, id: GroupId) -> Option<GroupRef<'_>> {
276 self.groups
277 .contains_key(&id)
278 .then(move || GroupRef::new(self, id))
279 }
280
281 pub fn group_mut(&mut self, id: GroupId) -> Option<GroupMut<'_>> {
283 self.groups
284 .contains_key(&id)
285 .then(move || GroupMut::new(self, id))
286 }
287}