raw
1use petgraph::graph::NodeIndex;
2
3use crate::{
4 ItemPathBuf,
5 note::{Note, NoteError},
6};
7
8static AUDIO_EXTS: &[&str] = &["3gp", "flac", "m4a", "mp3", "ogg", "opus", "wav"];
9static DATA_EXTS: &[&str] = &["json", "toml", "yaml"];
10static IMAGE_EXTS: &[&str] = &["bmp", "gif", "png", "jpeg", "jpg", "svg", "webp"];
11static VIDEO_EXTS: &[&str] = &["avi", "mkv", "mov", "mp4", "ogv", "webm"];
12
13static BASE_EXTS: &[&str] = &["base"];
14static CANVAS_EXTS: &[&str] = &["canvas"];
15static NOTE_EXTS: &[&str] = &["adoc", "gem", "md", "org"];
16
17static HTML_EXTS: &[&str] = &["html", "htm"];
18
19#[derive(Debug, Clone, Hash, PartialEq, Eq)]
21pub enum FileKind {
22 Audio,
26 Data,
30 Image,
34 Video,
38
39 Base,
41 Canvas,
43 Note,
45
46 Html,
50
51 Unknown(Option<String>),
53}
54
55impl FileKind {
56 #[must_use]
58 pub const fn is_asset(&self) -> bool {
59 self.is_audio() || self.is_image() || self.is_video()
60 }
61
62 #[must_use]
64 pub const fn is_audio(&self) -> bool {
65 matches!(self, Self::Audio)
66 }
67
68 #[must_use]
70 pub const fn is_data(&self) -> bool {
71 matches!(self, Self::Data)
72 }
73
74 #[must_use]
76 pub const fn is_image(&self) -> bool {
77 matches!(self, Self::Image)
78 }
79
80 #[must_use]
82 pub const fn is_video(&self) -> bool {
83 matches!(self, Self::Video)
84 }
85
86 #[must_use]
88 pub const fn is_base(&self) -> bool {
89 matches!(self, Self::Base)
90 }
91
92 #[must_use]
94 pub const fn is_canvas(&self) -> bool {
95 matches!(self, Self::Canvas)
96 }
97
98 #[must_use]
100 pub const fn is_note(&self) -> bool {
101 matches!(self, Self::Note)
102 }
103
104 #[must_use]
106 pub const fn is_html(&self) -> bool {
107 matches!(self, Self::Html)
108 }
109}
110
111#[derive(Debug, Clone, Hash, PartialEq, Eq)]
116pub struct File {
117 pub path: ItemPathBuf,
119
120 pub kind: FileKind,
125}
126
127impl File {
128 #[must_use]
130 pub fn from_path(path: ItemPathBuf) -> Self {
131 let kind = path
132 .extension()
133 .map_or(FileKind::Unknown(None), |ext| match ext {
134 _ if AUDIO_EXTS.contains(&ext) => FileKind::Audio,
135 _ if DATA_EXTS.contains(&ext) => FileKind::Data,
136 _ if IMAGE_EXTS.contains(&ext) => FileKind::Image,
137 _ if VIDEO_EXTS.contains(&ext) => FileKind::Video,
138
139 _ if BASE_EXTS.contains(&ext) => FileKind::Base,
140 _ if CANVAS_EXTS.contains(&ext) => FileKind::Canvas,
141 _ if NOTE_EXTS.contains(&ext) => FileKind::Note,
142
143 _ if HTML_EXTS.contains(&ext) => FileKind::Html,
144
145 _ => FileKind::Unknown(Some(ext.to_string())),
146 });
147
148 if matches!(&kind, FileKind::Unknown(_)) {
149 tracing::warn!(path=%path.relative, "unknown file type");
150 }
151
152 Self { path, kind }
153 }
154
155 pub fn into_note(self, index: NodeIndex) -> Result<Note, NoteError> {
163 Note::from_path(self.path, index)
164 }
165}
166