1use crate::error::OrbokError;
9use serde::{Deserialize, Serialize};
10
11macro_rules! catalog_enum {
12 ($(#[$doc:meta])* $name:ident, $column:literal, { $($variant:ident => $s:literal),+ $(,)? }) => {
13 $(#[$doc])*
14 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
15 #[serde(rename_all = "snake_case")]
16 pub enum $name {
17 $($variant),+
18 }
19
20 impl $name {
21 pub fn as_str(&self) -> &'static str {
23 match self {
24 $(Self::$variant => $s),+
25 }
26 }
27
28 pub fn parse(s: &str) -> Result<Self, OrbokError> {
31 match s {
32 $($s => Ok(Self::$variant),)+
33 other => Err(OrbokError::InvalidCatalogValue {
34 column: $column,
35 value: other.to_string(),
36 }),
37 }
38 }
39 }
40 };
41}
42
43catalog_enum!(
44 SourceType,
46 "sources.source_type",
47 { Directory => "directory", File => "file" }
48);
49
50catalog_enum!(
51 PersistenceMode,
53 "sources.persistence_mode",
54 { Persistent => "persistent", Temporary => "temporary" }
55);
56
57catalog_enum!(
58 SourceStatus,
60 "sources.status",
61 {
62 Active => "active",
63 Paused => "paused",
64 Missing => "missing",
65 PermissionDenied => "permission_denied",
66 Removed => "removed",
67 }
68);
69
70impl SourceStatus {
71 pub fn is_searchable(self) -> bool {
81 matches!(self, Self::Active)
82 }
83}
84
85pub const SEARCHABLE_SOURCE_STATUS_SQL: &str = "('active')";
91
92catalog_enum!(
93 IndexMode,
95 "sources.index_mode",
96 {
97 Balanced => "balanced",
98 HighAccuracy => "high_accuracy",
99 SpaceSaving => "space_saving",
100 }
101);
102
103catalog_enum!(
104 HiddenFilePolicy,
106 "sources.hidden_file_policy",
107 { Exclude => "exclude", Include => "include", Warn => "warn" }
108);
109
110catalog_enum!(
111 SymlinkPolicy,
113 "sources.symlink_policy",
114 {
115 Ignore => "ignore",
116 FollowWithinSource => "follow_within_source",
117 FollowAllWithWarning => "follow_all_with_warning",
118 }
119);
120
121catalog_enum!(
122 FileStatus,
124 "files.file_status",
125 {
126 Discovered => "discovered",
127 Indexed => "indexed",
128 Stale => "stale",
129 Missing => "missing",
130 Deleted => "deleted",
131 PermissionDenied => "permission_denied",
132 Unsupported => "unsupported",
133 Failed => "failed",
134 NoTextFound => "no_text_found",
140 }
141);
142
143catalog_enum!(
144 JobType,
146 "index_jobs.job_type",
147 {
148 Scan => "scan",
149 Extract => "extract",
150 Chunk => "chunk",
151 KeywordIndex => "keyword_index",
152 Embedding => "embedding",
153 DeleteStale => "delete_stale",
154 Rebuild => "rebuild",
155 }
156);
157
158catalog_enum!(
159 JobStatus,
161 "index_jobs.status",
162 {
163 Queued => "queued",
164 Running => "running",
165 Succeeded => "succeeded",
166 Failed => "failed",
167 Canceled => "canceled",
168 Blocked => "blocked",
169 Paused => "paused",
170 WaitingForDependency => "waiting_for_dependency",
171 }
172);
173
174#[allow(clippy::derivable_impls)]
175impl Default for HiddenFilePolicy {
176 fn default() -> Self {
177 HiddenFilePolicy::Exclude
178 }
179}
180
181#[allow(clippy::derivable_impls)]
182impl Default for SymlinkPolicy {
183 fn default() -> Self {
184 SymlinkPolicy::Ignore
185 }
186}
187
188#[allow(clippy::derivable_impls)]
189impl Default for IndexMode {
190 fn default() -> Self {
191 IndexMode::Balanced
192 }
193}