1use bstr::ByteSlice;
2use thiserror::Error;
3use tokio::task::JoinError;
4use tonic::Status;
5
6use crate::{
7 SymlinkTargetError,
8 path::{PathComponent, PathComponentError},
9};
10
11#[derive(Debug, Error, PartialEq)]
13pub enum Error {
14 #[error("invalid request: {0}")]
15 InvalidRequest(String),
16
17 #[error("internal storage error: {0}")]
18 StorageError(String),
19}
20
21#[derive(Debug, thiserror::Error, PartialEq)]
23pub enum ValidateNodeError {
24 #[error("invalid digest length: {0}")]
26 InvalidDigestLen(usize),
27 #[error("Invalid symlink target: {0}")]
29 InvalidSymlinkTarget(SymlinkTargetError),
30 #[error("invalid hash type: expected a 'blake3-' prefixed digest")]
32 InvalidHashType,
33}
34
35impl From<crate::digests::Error> for ValidateNodeError {
36 fn from(e: crate::digests::Error) -> Self {
37 match e {
38 crate::digests::Error::InvalidDigestLen(n) => ValidateNodeError::InvalidDigestLen(n),
39 crate::digests::Error::InvalidHashType => ValidateNodeError::InvalidHashType,
40 }
41 }
42}
43
44#[derive(Debug, thiserror::Error, PartialEq)]
47pub enum DirectoryError {
48 #[error("{:?} is a duplicate name", .0)]
50 DuplicateName(PathComponent),
51 #[error("invalid node with name {}: {:?}", .0.as_bstr(), .1.to_string())]
53 InvalidNode(bytes::Bytes, ValidateNodeError),
54 #[error("Total size exceeds u64::MAX")]
55 SizeOverflow,
56 #[error("Invalid name: {0}")]
58 InvalidName(PathComponentError),
59 #[error("Name is set when it shouldn't")]
62 NameInAnonymousNode,
63 #[error("{:?} is not sorted", .0.as_bstr())]
65 WrongSorting(bytes::Bytes),
66 #[error("No entry set")]
68 NoEntrySet,
69}
70
71impl From<JoinError> for Error {
72 fn from(value: JoinError) -> Self {
73 Error::StorageError(value.to_string())
74 }
75}
76
77impl From<Error> for Status {
78 fn from(value: Error) -> Self {
79 match value {
80 Error::InvalidRequest(msg) => Status::invalid_argument(msg),
81 Error::StorageError(msg) => Status::data_loss(format!("storage error: {}", msg)),
82 }
83 }
84}
85
86impl From<crate::tonic::Error> for Error {
87 fn from(value: crate::tonic::Error) -> Self {
88 Self::StorageError(value.to_string())
89 }
90}
91
92impl From<redb::Error> for Error {
93 fn from(value: redb::Error) -> Self {
94 Error::StorageError(value.to_string())
95 }
96}
97
98impl From<redb::DatabaseError> for Error {
99 fn from(value: redb::DatabaseError) -> Self {
100 Error::StorageError(value.to_string())
101 }
102}
103
104impl From<redb::TableError> for Error {
105 fn from(value: redb::TableError) -> Self {
106 Error::StorageError(value.to_string())
107 }
108}
109
110impl From<redb::TransactionError> for Error {
111 fn from(value: redb::TransactionError) -> Self {
112 Error::StorageError(value.to_string())
113 }
114}
115
116impl From<redb::StorageError> for Error {
117 fn from(value: redb::StorageError) -> Self {
118 Error::StorageError(value.to_string())
119 }
120}
121
122impl From<redb::CommitError> for Error {
123 fn from(value: redb::CommitError) -> Self {
124 Error::StorageError(value.to_string())
125 }
126}
127
128impl From<std::io::Error> for Error {
129 fn from(value: std::io::Error) -> Self {
130 if value.kind() == std::io::ErrorKind::InvalidInput {
131 Error::InvalidRequest(value.to_string())
132 } else {
133 Error::StorageError(value.to_string())
134 }
135 }
136}
137
138impl From<Error> for std::io::Error {
140 fn from(value: Error) -> Self {
141 match value {
142 Error::InvalidRequest(msg) => Self::new(std::io::ErrorKind::InvalidInput, msg),
143 Error::StorageError(msg) => Self::new(std::io::ErrorKind::Other, msg),
144 }
145 }
146}