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