2021-10-23 04:48:56 +00:00
|
|
|
use crate::{
|
|
|
|
error::{Error, UploadError},
|
|
|
|
store::Store,
|
|
|
|
};
|
2021-01-18 23:11:32 +00:00
|
|
|
use actix_web::{
|
2022-03-01 17:23:15 +00:00
|
|
|
http::header::{ByteRangeSpec, ContentRange, ContentRangeSpec, Range},
|
2021-01-18 23:11:32 +00:00
|
|
|
web::Bytes,
|
|
|
|
};
|
2021-10-14 00:06:53 +00:00
|
|
|
use futures_util::stream::{once, Stream};
|
|
|
|
use std::future::ready;
|
2021-01-18 23:11:32 +00:00
|
|
|
|
2022-03-01 17:23:15 +00:00
|
|
|
pub(crate) fn chop_bytes(
|
|
|
|
byte_range: &ByteRangeSpec,
|
|
|
|
bytes: Bytes,
|
|
|
|
length: u64,
|
|
|
|
) -> Result<impl Stream<Item = Result<Bytes, Error>>, Error> {
|
|
|
|
if let Some((start, end)) = byte_range.to_satisfiable_range(length) {
|
2022-03-27 01:45:12 +00:00
|
|
|
// END IS INCLUSIVE
|
|
|
|
let end = end as usize + 1;
|
|
|
|
return Ok(once(ready(Ok(bytes.slice(start as usize..end)))));
|
2021-01-18 23:11:32 +00:00
|
|
|
}
|
|
|
|
|
2022-03-01 17:23:15 +00:00
|
|
|
Err(UploadError::Range.into())
|
2021-01-18 23:11:32 +00:00
|
|
|
}
|
|
|
|
|
2022-03-01 17:23:15 +00:00
|
|
|
pub(crate) async fn chop_store<S: Store>(
|
|
|
|
byte_range: &ByteRangeSpec,
|
|
|
|
store: &S,
|
|
|
|
identifier: &S::Identifier,
|
|
|
|
length: u64,
|
2022-03-27 01:45:12 +00:00
|
|
|
) -> Result<impl Stream<Item = std::io::Result<Bytes>>, Error> {
|
2022-03-01 17:23:15 +00:00
|
|
|
if let Some((start, end)) = byte_range.to_satisfiable_range(length) {
|
2022-03-27 01:45:12 +00:00
|
|
|
// END IS INCLUSIVE
|
|
|
|
let end = end + 1;
|
|
|
|
return store
|
2022-03-01 17:23:15 +00:00
|
|
|
.to_stream(identifier, Some(start), Some(end.saturating_sub(start)))
|
2023-06-20 20:59:08 +00:00
|
|
|
.await
|
|
|
|
.map_err(Error::from);
|
2021-01-18 23:11:32 +00:00
|
|
|
}
|
|
|
|
|
2022-03-01 17:23:15 +00:00
|
|
|
Err(UploadError::Range.into())
|
|
|
|
}
|
2021-01-18 23:11:32 +00:00
|
|
|
|
2022-03-01 17:23:15 +00:00
|
|
|
pub(crate) fn single_bytes_range(range: &Range) -> Option<&ByteRangeSpec> {
|
|
|
|
if let Range::Bytes(ranges) = range {
|
|
|
|
if ranges.len() == 1 {
|
|
|
|
return ranges.get(0);
|
2021-01-18 23:11:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-01 17:23:15 +00:00
|
|
|
None
|
2021-01-18 23:11:32 +00:00
|
|
|
}
|
|
|
|
|
2022-03-01 17:23:15 +00:00
|
|
|
pub(crate) fn to_content_range(
|
|
|
|
byte_range: &ByteRangeSpec,
|
|
|
|
instance_length: u64,
|
|
|
|
) -> Option<ContentRange> {
|
|
|
|
byte_range
|
|
|
|
.to_satisfiable_range(instance_length)
|
|
|
|
.map(|range| {
|
|
|
|
ContentRange(ContentRangeSpec::Bytes {
|
|
|
|
range: Some(range),
|
|
|
|
instance_length: Some(instance_length),
|
|
|
|
})
|
|
|
|
})
|
2021-01-18 23:11:32 +00:00
|
|
|
}
|