use crate::http::HeaderMap;
use crate::model::Object;
use crate::model_ext::ReadRange;
use crate::read_object::ReadObjectResponse;
use crate::storage::bidi::stub::dynamic::ObjectDescriptor as ObjectDescriptorStub;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct ObjectDescriptor {
inner: Arc<dyn ObjectDescriptorStub>,
}
impl ObjectDescriptor {
pub fn object(&self) -> Object {
self.inner.object()
}
pub async fn read_range(&self, range: ReadRange) -> ReadObjectResponse {
self.inner.read_range(range).await
}
pub fn headers(&self) -> HeaderMap {
self.inner.headers()
}
pub fn new<T>(inner: T) -> Self
where
T: crate::stub::ObjectDescriptor + 'static,
{
Self {
inner: Arc::new(inner),
}
}
pub(crate) fn into_parts(self) -> Arc<dyn ObjectDescriptorStub> {
self.inner
}
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::model_ext::ObjectHighlights;
use crate::read_object::ReadObjectResponse;
use http::{HeaderName, HeaderValue};
use mockall::mock;
use static_assertions::assert_impl_all;
#[test]
fn impls() {
assert_impl_all!(ObjectDescriptor: Clone, std::fmt::Debug);
}
#[tokio::test]
async fn can_be_mocked() -> anyhow::Result<()> {
let object = Object::new().set_name("test-object").set_generation(123456);
let headers = HeaderMap::from_iter(
[
("content-type", "application/octet-stream"),
("x-guploader-uploadid", "abc-123"),
]
.map(|(k, v)| (HeaderName::from_static(k), HeaderValue::from_static(v))),
);
let mut mock = MockDescriptor::new();
mock.expect_object().times(1).return_const(object.clone());
mock.expect_read_range()
.times(1)
.withf(|range| range.0 == ReadRange::segment(100, 200).0)
.returning(|_| ReadObjectResponse::new(Box::new(MockResponse::new())));
mock.expect_headers().times(1).return_const(headers.clone());
let descriptor = ObjectDescriptor::new(mock);
assert_eq!(descriptor.object(), object);
assert_eq!(descriptor.headers(), headers);
let _reader = descriptor.read_range(ReadRange::segment(100, 200)).await;
Ok(())
}
mock! {
#[derive(Debug)]
pub Descriptor {}
impl crate::stub::ObjectDescriptor for Descriptor {
fn object(&self) -> Object;
async fn read_range(&self, range: ReadRange) -> ReadObjectResponse;
fn headers(&self) -> HeaderMap;
}
}
mock! {
#[derive(Debug)]
pub Response {}
#[async_trait::async_trait]
impl crate::read_object::dynamic::ReadObjectResponse for Response {
fn object(&self) -> ObjectHighlights;
async fn next(&mut self) -> Option<crate::Result<bytes::Bytes>>;
}
}
}