json_db/
lib.rs

1use serde::{Deserialize, Serialize};
2use std::{env, fs, path::Path};
3
4mod test;
5
6/// Database struct (does not use `::new` instead uses `::init`)
7///
8/// # Examples
9/// ```
10/// let db = JsonDB::init("your db name")?;
11/// ```
12///
13/// ### Note:
14/// Does not handle errors in version "0.1.0" just passes on to user
15///
16pub struct JsonDB {
17    path: String,
18}
19
20impl JsonDB {
21    /// Init function (takes the place of `::new`)
22    ///
23    /// # Examples
24    /// ```
25    /// let db = JsonDB::init("your db name")?;
26    /// ```
27    ///
28    pub fn init(path: &str) -> Result<JsonDB, Box<dyn std::error::Error>> {
29        let db_path = format!("{}/.JsonDB/{}/", env::var("HOME")?, path);
30        if !Path::new(&*format!("{}/.JsonDB/{}/", env::var("HOME")?, path)).is_dir() {
31            fs::create_dir_all(format!("{}/.JsonDB/{}/", env::var("HOME")?, path))?;
32        }
33        Ok(JsonDB { path: db_path })
34    }
35
36    /// Creates a new collection either in your database or in another collection
37    ///
38    /// # Examples
39    /// ```
40    /// db.create_collection("your collection path")?;
41    /// ```
42    ///
43    pub fn create_collection<S>(
44        self,
45        collection_path: S,
46    ) -> Result<JsonDB, Box<dyn std::error::Error>>
47    where
48        S: Into<String>,
49    {
50        fs::create_dir(format!("{}/{}", self.path, collection_path.into()))?;
51        Ok(self)
52    }
53
54    /// Writes (or rewrites) data to document in collection
55    ///
56    /// # Examples
57    /// ```
58    /// db.write("your collection path", "your document", "struct that derives serde::serialize")?;
59    /// ```
60    ///
61    pub fn write<J, S>(
62        self,
63        collection_path: S,
64        document: S,
65        data: J,
66    ) -> Result<JsonDB, Box<dyn std::error::Error>>
67    where
68        J: Serialize,
69        S: Into<String>,
70    {
71        let serialized = serde_json::to_string(&data)?;
72        fs::write(
73            format!(
74                "{}/{}/{}.data.json",
75                self.path,
76                collection_path.into(),
77                document.into()
78            ),
79            serialized,
80        )?;
81        Ok(self)
82    }
83
84    /// Reads data from document in collection
85    ///
86    /// ```
87    /// let data: impl serde::Deserialize = db.read("your collection path", "your document")?;
88    /// ```
89    ///
90    pub fn read<D, S>(
91        self,
92        collection_path: S,
93        document: S,
94    ) -> Result<D, Box<dyn std::error::Error>>
95    where
96        for<'a> D: Deserialize<'a>,
97        S: Into<String>,
98    {
99        let data = serde_json::from_str::<D>(
100            fs::read_to_string(format!(
101                "{}/{}/{}.data.json",
102                self.path,
103                collection_path.into(),
104                document.into()
105            ))?
106            .as_str(),
107        )?;
108        Ok(data)
109    }
110
111    /// Deletes document in collection
112    ///
113    /// # Examples
114    /// ```
115    /// db.delete("your collection path", "your document")?;
116    /// ```
117    ///
118    pub fn delete<S>(
119        self,
120        collection_path: S,
121        document: S,
122    ) -> Result<JsonDB, Box<dyn std::error::Error>>
123    where
124        S: Into<String>,
125    {
126        fs::remove_file(format!(
127            "{}/{}/{}.data.json",
128            self.path,
129            collection_path.into(),
130            document.into()
131        ))?;
132        Ok(self)
133    }
134
135    /// List all document in a collection
136    ///
137    /// # Examples
138    /// ```
139    /// let list: Vec<String> = db.list("your collection path")?;
140    /// ```
141    ///
142    pub fn list<S>(self, collection_path: S) -> Result<Vec<String>, Box<dyn std::error::Error>>
143    where
144        S: Into<String>,
145    {
146        let mut list: Vec<String> = Vec::new();
147        for file in fs::read_dir(format!("{}/{}/", self.path, collection_path.into()))? {
148            let mut value = file?.file_name().into_string().unwrap();
149            let len = value.chars().count() - 10;
150            let string = String::from(value.drain(0..len).as_str());
151
152            list.push(string);
153        }
154        Ok(list)
155    }
156}