systemprompt_traits/
storage.rs1use async_trait::async_trait;
16use std::path::Path;
17
18use crate::BoxedSource;
19
20pub type FileStorageResult<T> = Result<T, FileStorageError>;
21
22#[derive(Debug, thiserror::Error)]
23#[non_exhaustive]
24pub enum FileStorageError {
25 #[error("file not found: {0}")]
26 NotFound(String),
27
28 #[error("validation failed: {0}")]
29 Validation(String),
30
31 #[error("io error: {0}")]
32 Io(#[from] std::io::Error),
33
34 #[error("serialization error: {0}")]
35 Serialization(#[from] serde_json::Error),
36
37 #[error("storage backend error: {0}")]
38 Backend(#[source] BoxedSource),
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Hash)]
42pub struct StoredFileId(pub String);
43
44impl StoredFileId {
45 #[must_use]
46 pub fn new(id: impl Into<String>) -> Self {
47 Self(id.into())
48 }
49
50 #[must_use]
51 pub fn as_str(&self) -> &str {
52 &self.0
53 }
54}
55
56impl From<String> for StoredFileId {
57 fn from(s: String) -> Self {
58 Self(s)
59 }
60}
61
62impl From<&str> for StoredFileId {
63 fn from(s: &str) -> Self {
64 Self(s.to_owned())
65 }
66}
67
68impl std::fmt::Display for StoredFileId {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 write!(f, "{}", self.0)
71 }
72}
73
74#[derive(Debug, Clone)]
75pub struct StoredFileMetadata {
76 pub id: StoredFileId,
77 pub path: String,
78 pub mime_type: String,
79 pub size_bytes: Option<i64>,
80 pub created_at: chrono::DateTime<chrono::Utc>,
81 pub updated_at: chrono::DateTime<chrono::Utc>,
82}
83
84#[async_trait]
85pub trait FileStorage: Send + Sync {
86 async fn store(&self, path: &Path, content: &[u8]) -> FileStorageResult<StoredFileId>;
87
88 async fn retrieve(&self, id: &StoredFileId) -> FileStorageResult<Vec<u8>>;
89
90 async fn delete(&self, id: &StoredFileId) -> FileStorageResult<()>;
91
92 async fn metadata(&self, id: &StoredFileId) -> FileStorageResult<StoredFileMetadata>;
93
94 async fn exists(&self, id: &StoredFileId) -> FileStorageResult<bool>;
95
96 fn public_url(&self, _id: &StoredFileId) -> Option<String> {
97 None
98 }
99}