basalt_core/obsidian/vault.rs
1use std::{path::PathBuf, result};
2
3use serde::{Deserialize, Deserializer};
4
5use super::vault_entry::VaultEntry;
6
7/// Represents a single Obsidian vault.
8///
9/// A vault is a folder containing notes and other metadata.
10#[derive(Debug, Clone, Default, PartialEq)]
11pub struct Vault {
12 /// The name of the vault, inferred from its directory name.
13 pub name: String,
14
15 /// Filesystem path to the vault's directory.
16 pub path: PathBuf,
17
18 /// Whether the vault is marked 'open' by Obsidian.
19 pub open: bool,
20
21 /// Timestamp of last update or creation.
22 pub ts: u64,
23}
24
25impl Vault {
26 /// Returns a [`Vec`] of Markdown vault entries in this vault as [`VaultEntry`] structs.
27 /// Entries can be either directories or files (notes). If the directory is marked hidden with
28 /// a dot (`.`) prefix it will be filtered out from the resulting [`Vec`].
29 ///
30 /// The returned entries are not sorted.
31 ///
32 /// # Examples
33 ///
34 /// ```
35 /// use basalt_core::obsidian::{Vault, Note};
36 ///
37 /// let vault = Vault {
38 /// name: "MyVault".into(),
39 /// path: "path/to/my_vault".into(),
40 /// ..Default::default()
41 /// };
42 ///
43 /// assert_eq!(vault.entries(), vec![]);
44 /// ```
45 pub fn entries(&self) -> Vec<VaultEntry> {
46 match self.path.as_path().try_into() {
47 Ok(VaultEntry::Directory { entries, .. }) => entries
48 .into_iter()
49 .filter(|entry| !entry.name().starts_with('.'))
50 .collect(),
51 _ => vec![],
52 }
53 }
54}
55
56impl<'de> Deserialize<'de> for Vault {
57 fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
58 where
59 D: Deserializer<'de>,
60 {
61 #[derive(Deserialize)]
62 struct Json {
63 path: PathBuf,
64 open: Option<bool>,
65 ts: u64,
66 }
67
68 impl TryFrom<Json> for Vault {
69 type Error = String;
70 fn try_from(Json { path, open, ts }: Json) -> result::Result<Self, Self::Error> {
71 let name = path
72 .file_name()
73 .map(|file_name| file_name.to_string_lossy().to_string())
74 .ok_or("unable to retrieve vault name")?;
75
76 Ok(Vault {
77 name,
78 path,
79 open: open.unwrap_or(false),
80 ts,
81 })
82 }
83 }
84
85 let deserialized: Json = Deserialize::deserialize(deserializer)?;
86 deserialized.try_into().map_err(serde::de::Error::custom)
87 }
88}