semilattice_database/
collection.rs1mod row;
2
3pub use row::CollectionRow;
4
5use std::{
6 num::NonZeroI32,
7 ops::{Deref, DerefMut},
8 path::PathBuf,
9};
10
11use versatile_data::{Data, DataOption};
12
13use crate::Database;
14
15pub struct Collection {
16 data: Data,
17 id: NonZeroI32,
18 name: String,
19}
20impl Collection {
21 pub fn new(data: Data, id: NonZeroI32, name: impl Into<String>) -> Self {
22 Self {
23 data,
24 id,
25 name: name.into(),
26 }
27 }
28
29 pub fn id(&self) -> NonZeroI32 {
30 self.id
31 }
32
33 pub fn name(&self) -> &str {
34 &self.name
35 }
36
37 pub fn data(&self) -> &Data {
38 &self.data
39 }
40}
41impl Deref for Collection {
42 type Target = Data;
43 fn deref(&self) -> &Self::Target {
44 &self.data
45 }
46}
47impl DerefMut for Collection {
48 fn deref_mut(&mut self) -> &mut Self::Target {
49 &mut self.data
50 }
51}
52
53impl Database {
54 pub fn collections(&self) -> Vec<String> {
55 self.collections
56 .iter()
57 .map(|(_, x)| x.name().to_owned())
58 .collect()
59 }
60
61 pub fn collection(&self, id: NonZeroI32) -> Option<&Collection> {
62 self.collections.get(&id)
63 }
64
65 pub fn collection_mut(&mut self, id: NonZeroI32) -> Option<&mut Collection> {
66 self.collections.get_mut(&id)
67 }
68
69 pub fn collection_id(&self, name: &str) -> Option<NonZeroI32> {
70 self.collections_map
71 .contains_key(name)
72 .then(|| *self.collections_map.get(name).unwrap())
73 }
74
75 pub fn collection_id_or_create(&mut self, name: &str) -> NonZeroI32 {
76 if self.collections_map.contains_key(name) {
77 *self.collections_map.get(name).unwrap()
78 } else {
79 self.collection_by_name_or_create(name)
80 }
81 }
82
83 pub async fn delete_collection(&mut self, name: &str) {
84 let collection_id = self.collections_map.get(name).map_or(0, |x| x.get());
85 if collection_id > 0 {
86 let collection_id = unsafe { NonZeroI32::new_unchecked(collection_id) };
87 if let Some(collection) = self.collections.get(&collection_id) {
88 for row in collection.data.all().into_iter() {
89 self.delete(&CollectionRow::new(collection_id, row))
90 .await;
91 if let Some(collection) = self.collection_mut(collection_id) {
92 collection.delete(row).await;
93 }
94 }
95 }
96 self.collections_map.remove(name);
97 self.collections.remove(&collection_id);
98
99 let mut dir = self.collections_dir.clone();
100 dir.push(collection_id.to_string() + "_" + name);
101 std::fs::remove_dir_all(&dir).unwrap();
102 }
103 }
104
105 pub(super) fn create_collection(&mut self, id: NonZeroI32, name: &str, dir: PathBuf) {
106 let collection = Collection::new(
107 Data::new(
108 dir,
109 self.collection_settings
110 .get(name)
111 .map_or(DataOption::default(), |f| f.clone()),
112 ),
113 id,
114 name,
115 );
116 self.collections_map.insert(name.to_string(), id);
117 self.collections.insert(id, collection);
118 }
119
120 fn collection_by_name_or_create(&mut self, name: &str) -> NonZeroI32 {
121 let mut max_id = 0;
122 if self.collections_dir.exists() {
123 for d in self.collections_dir.read_dir().unwrap().into_iter() {
124 let d = d.unwrap();
125 if d.file_type().unwrap().is_dir() {
126 if let Some(fname) = d.file_name().to_str() {
127 let s: Vec<_> = fname.split("_").collect();
128 if s.len() > 1 {
129 if let Ok(i) = s[0].parse() {
130 max_id = std::cmp::max(max_id, i);
131 }
132 if s[1] == name {
133 let max_id = NonZeroI32::new(max_id).unwrap();
134 self.create_collection(max_id, name, d.path());
135 return max_id;
136 }
137 }
138 }
139 }
140 }
141 }
142 let collection_id = unsafe { NonZeroI32::new_unchecked(max_id + 1) };
143 self.create_collection(collection_id, name, {
144 let mut collecion_dir = self.collections_dir.clone();
145 collecion_dir.push(&(collection_id.to_string() + "_" + name));
146 collecion_dir
147 });
148 collection_id
149 }
150}