diff --git a/.gitignore b/.gitignore index ea8c4bf7..212de442 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +.DS_Store \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 02491fda..38a14fc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -334,6 +334,7 @@ dependencies = [ "thiserror", "time", "tokio", + "tokio-stream", "tokio-util", "tracing", "tracing-error", @@ -1409,6 +1410,17 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.11" diff --git a/ecstore/Cargo.toml b/ecstore/Cargo.toml index 082fea7e..29dc282b 100644 --- a/ecstore/Cargo.toml +++ b/ecstore/Cargo.toml @@ -38,6 +38,7 @@ sha2 = "0.10.8" hex-simd = "0.8.0" path-clean = "1.0.1" http.workspace = true +tokio-stream = "0.1.15" [dev-dependencies] tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } diff --git a/ecstore/src/store_api.rs b/ecstore/src/store_api.rs index deb7af4e..077f5632 100644 --- a/ecstore/src/store_api.rs +++ b/ecstore/src/store_api.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{Error, Result}; use http::HeaderMap; use rmp_serde::Serializer; use s3s::dto::StreamingBlob; @@ -242,7 +242,100 @@ pub struct GetObjectReader { pub object_info: ObjectInfo, } -pub struct HTTPRangeSpec {} +impl GetObjectReader { + pub fn new(stream: StreamingBlob, object_info: ObjectInfo) -> Self { + GetObjectReader { stream, object_info } + } +} + +pub struct HTTPRangeSpec { + pub is_shuffix_length: bool, + pub start: i64, + pub end: i64, +} + +impl HTTPRangeSpec { + pub fn nil() -> Self { + Self { + is_shuffix_length: false, + start: -1, + end: -1, + } + } + + pub fn is_nil(&self) -> bool { + self.start == -1 && self.end == -1 + } + pub fn from_object_info(oi: &ObjectInfo, part_number: usize) -> Self { + let mut l = oi.parts.len(); + if part_number < l { + l = part_number; + } + + let mut start = 0; + let mut end = -1; + for i in 0..l { + start = end + 1; + end = start + oi.parts[i].size as i64 - 1 + } + + HTTPRangeSpec { + is_shuffix_length: false, + start: start, + end: end, + } + } + + pub fn get_offset_length(&self, res_size: i64) -> Result<(i64, i64)> { + if self.start == 0 && self.end == 0 { + return Ok((0, res_size)); + } + + let len = self.get_length(res_size)?; + let mut start = self.start; + if self.is_shuffix_length { + start = self.start + res_size + } + Ok((start, len)) + } + pub fn get_length(&self, res_size: i64) -> Result { + if self.is_nil() { + return Ok(res_size); + } + + if self.is_shuffix_length { + let specified_len = -self.start; // 假设 h.start 是一个 i64 类型 + let mut range_length = specified_len; + + if specified_len > res_size { + range_length = res_size; + } + + return Ok(range_length); + } + + if self.start > res_size { + return Err(Error::msg("The requested range is not satisfiable")); + } + + if self.end > -1 { + let mut end = self.end; + if res_size <= end { + end = res_size - 1; + } + + let range_length = end - self.start - 1; + return Ok(range_length); + } + + if self.end == -1 { + let range_length = res_size - self.start; + return Ok(range_length); + } + + Err(Error::msg("range value invaild")) + } +} #[derive(Debug)] pub struct ObjectOptions {