Issue 762 (#763)

* Add InvalidRangeSpec error

* Add EntityTooSmall to from_u32

* Add InvalidRangeSpec to from_u32

* Map InvalidRangeSpec to correct S3ErrorCode

* Return Error::InvalidRangeSpec

* Use auto implementation

---------

Co-authored-by: Niklas Mollenhauer <nikeee@outlook.com>
This commit is contained in:
loverustfs
2025-10-31 17:20:18 +08:00
committed by GitHub
parent f0c2ede7a7
commit 325ff62684
7 changed files with 23 additions and 36 deletions
+2 -7
View File
@@ -49,11 +49,12 @@ pub enum HealType {
} }
/// Heal priority /// Heal priority
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum HealPriority { pub enum HealPriority {
/// Low priority /// Low priority
Low = 0, Low = 0,
/// Normal priority /// Normal priority
#[default]
Normal = 1, Normal = 1,
/// High priority /// High priority
High = 2, High = 2,
@@ -61,12 +62,6 @@ pub enum HealPriority {
Urgent = 3, Urgent = 3,
} }
impl Default for HealPriority {
fn default() -> Self {
Self::Normal
}
}
/// Heal options /// Heal options
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealOptions { pub struct HealOptions {
+4 -14
View File
@@ -85,19 +85,14 @@ impl Display for DriveState {
} }
} }
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
pub enum HealScanMode { pub enum HealScanMode {
Unknown, Unknown,
#[default]
Normal, Normal,
Deep, Deep,
} }
impl Default for HealScanMode {
fn default() -> Self {
Self::Normal
}
}
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
pub struct HealOpts { pub struct HealOpts {
pub recursive: bool, pub recursive: bool,
@@ -175,11 +170,12 @@ pub struct HealChannelResponse {
} }
/// Heal priority /// Heal priority
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum HealChannelPriority { pub enum HealChannelPriority {
/// Low priority /// Low priority
Low, Low,
/// Normal priority /// Normal priority
#[default]
Normal, Normal,
/// High priority /// High priority
High, High,
@@ -187,12 +183,6 @@ pub enum HealChannelPriority {
Critical, Critical,
} }
impl Default for HealChannelPriority {
fn default() -> Self {
Self::Normal
}
}
/// Heal channel sender /// Heal channel sender
pub type HealChannelSender = mpsc::UnboundedSender<HealChannelCommand>; pub type HealChannelSender = mpsc::UnboundedSender<HealChannelCommand>;
+7
View File
@@ -193,6 +193,9 @@ pub enum StorageError {
#[error("Precondition failed")] #[error("Precondition failed")]
PreconditionFailed, PreconditionFailed,
#[error("Invalid range specified: {0}")]
InvalidRangeSpec(String),
} }
impl StorageError { impl StorageError {
@@ -424,6 +427,7 @@ impl Clone for StorageError {
StorageError::InsufficientReadQuorum(a, b) => StorageError::InsufficientReadQuorum(a.clone(), b.clone()), StorageError::InsufficientReadQuorum(a, b) => StorageError::InsufficientReadQuorum(a.clone(), b.clone()),
StorageError::InsufficientWriteQuorum(a, b) => StorageError::InsufficientWriteQuorum(a.clone(), b.clone()), StorageError::InsufficientWriteQuorum(a, b) => StorageError::InsufficientWriteQuorum(a.clone(), b.clone()),
StorageError::PreconditionFailed => StorageError::PreconditionFailed, StorageError::PreconditionFailed => StorageError::PreconditionFailed,
StorageError::InvalidRangeSpec(a) => StorageError::InvalidRangeSpec(a.clone()),
} }
} }
} }
@@ -491,6 +495,7 @@ impl StorageError {
StorageError::InsufficientWriteQuorum(_, _) => 0x3A, StorageError::InsufficientWriteQuorum(_, _) => 0x3A,
StorageError::PreconditionFailed => 0x3B, StorageError::PreconditionFailed => 0x3B,
StorageError::EntityTooSmall(_, _, _) => 0x3C, StorageError::EntityTooSmall(_, _, _) => 0x3C,
StorageError::InvalidRangeSpec(_) => 0x3D,
} }
} }
@@ -559,6 +564,8 @@ impl StorageError {
0x39 => Some(StorageError::InsufficientReadQuorum(Default::default(), Default::default())), 0x39 => Some(StorageError::InsufficientReadQuorum(Default::default(), Default::default())),
0x3A => Some(StorageError::InsufficientWriteQuorum(Default::default(), Default::default())), 0x3A => Some(StorageError::InsufficientWriteQuorum(Default::default(), Default::default())),
0x3B => Some(StorageError::PreconditionFailed), 0x3B => Some(StorageError::PreconditionFailed),
0x3C => Some(StorageError::EntityTooSmall(Default::default(), Default::default(), Default::default())),
0x3D => Some(StorageError::InvalidRangeSpec(Default::default())),
_ => None, _ => None,
} }
} }
+6 -6
View File
@@ -291,7 +291,7 @@ impl HTTPRangeSpec {
let suffix_len = if self.start < 0 { let suffix_len = if self.start < 0 {
self.start self.start
.checked_neg() .checked_neg()
.ok_or_else(|| Error::other("range value invalid: suffix length overflow"))? .ok_or_else(|| Error::InvalidRangeSpec("range value invalid: suffix length overflow".to_string()))?
} else { } else {
self.start self.start
}; };
@@ -304,14 +304,14 @@ impl HTTPRangeSpec {
} }
pub fn get_length(&self, res_size: i64) -> Result<i64> { pub fn get_length(&self, res_size: i64) -> Result<i64> {
if res_size < 0 { if res_size < 0 {
return Err(Error::other("The requested range is not satisfiable")); return Err(Error::InvalidRangeSpec("The requested range is not satisfiable".to_string()));
} }
if self.is_suffix_length { if self.is_suffix_length {
let specified_len = if self.start < 0 { let specified_len = if self.start < 0 {
self.start self.start
.checked_neg() .checked_neg()
.ok_or_else(|| Error::other("range value invalid: suffix length overflow"))? .ok_or_else(|| Error::InvalidRangeSpec("range value invalid: suffix length overflow".to_string()))?
} else { } else {
self.start self.start
}; };
@@ -325,7 +325,7 @@ impl HTTPRangeSpec {
} }
if self.start >= res_size { if self.start >= res_size {
return Err(Error::other("The requested range is not satisfiable")); return Err(Error::InvalidRangeSpec("The requested range is not satisfiable".to_string()));
} }
if self.end > -1 { if self.end > -1 {
@@ -343,7 +343,7 @@ impl HTTPRangeSpec {
return Ok(range_length); return Ok(range_length);
} }
Err(Error::other(format!( Err(Error::InvalidRangeSpec(format!(
"range value invalid: start={}, end={}, expected start <= end and end >= -1", "range value invalid: start={}, end={}, expected start <= end and end >= -1",
self.start, self.end self.start, self.end
))) )))
@@ -1361,7 +1361,7 @@ impl<R: AsyncRead + Unpin + Send + Sync> RangedDecompressReader<R> {
// Validate the range request // Validate the range request
if offset >= total_size { if offset >= total_size {
tracing::debug!("Range offset {} exceeds total size {}", offset, total_size); tracing::debug!("Range offset {} exceeds total size {}", offset, total_size);
return Err(Error::other("Range offset exceeds file size")); return Err(Error::InvalidRangeSpec("Range offset exceeds file size".to_string()));
} }
// Adjust length if it extends beyond file end // Adjust length if it extends beyond file end
+2 -8
View File
@@ -21,21 +21,15 @@ use std::time::Duration;
use url::Url; use url::Url;
/// KMS backend types /// KMS backend types
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum KmsBackend { pub enum KmsBackend {
/// Vault backend (recommended for production) /// Vault backend (recommended for production)
Vault, Vault,
/// Local file-based backend for development and testing only /// Local file-based backend for development and testing only
#[default]
Local, Local,
} }
impl Default for KmsBackend {
fn default() -> Self {
// Default to Local backend since Vault requires configuration
Self::Local
}
}
/// Main KMS configuration /// Main KMS configuration
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KmsConfig { pub struct KmsConfig {
+1
View File
@@ -83,6 +83,7 @@ impl From<StorageError> for ApiError {
StorageError::InvalidPart(_, _, _) => S3ErrorCode::InvalidPart, StorageError::InvalidPart(_, _, _) => S3ErrorCode::InvalidPart,
StorageError::EntityTooSmall(_, _, _) => S3ErrorCode::EntityTooSmall, StorageError::EntityTooSmall(_, _, _) => S3ErrorCode::EntityTooSmall,
StorageError::PreconditionFailed => S3ErrorCode::PreconditionFailed, StorageError::PreconditionFailed => S3ErrorCode::PreconditionFailed,
StorageError::InvalidRangeSpec(_) => S3ErrorCode::InvalidRange,
_ => S3ErrorCode::InternalError, _ => S3ErrorCode::InternalError,
}; };
+1 -1
View File
@@ -3202,7 +3202,7 @@ impl S3 for FS {
range_spec range_spec
.get_offset_length(validation_size) .get_offset_length(validation_size)
.map_err(|e| S3Error::with_message(S3ErrorCode::InvalidRange, format!("Invalid range: {e}")))? .map_err(|e| S3Error::with_message(S3ErrorCode::InvalidRange, e.to_string()))?
} else { } else {
(0, src_info.size) (0, src_info.size)
}; };