Give a meaningful distinction for format in details

This commit is contained in:
asonix 2023-08-31 16:26:45 -05:00
parent dce0827099
commit 8fb90a6f69
3 changed files with 85 additions and 30 deletions

View file

@ -17,8 +17,30 @@ pub(crate) struct HumanDate {
pub(crate) timestamp: time::OffsetDateTime,
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[derive(Debug, serde::Serialize)]
enum ApiFormat {
Image,
Animation,
Video,
}
#[derive(Debug, serde::Serialize)]
pub(crate) struct ApiDetails {
width: u16,
height: u16,
frames: Option<u32>,
content_type: Serde<mime::Mime>,
created_at: HumanDate,
format: ApiFormat,
}
#[derive(Clone, Debug)]
pub(crate) struct Details {
pub(crate) inner: DetailsInner,
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub(crate) struct DetailsInner {
width: u16,
height: u16,
frames: Option<u32>,
@ -28,12 +50,39 @@ pub(crate) struct Details {
}
impl Details {
pub(crate) fn into_api_details(self) -> ApiDetails {
let Details {
inner:
DetailsInner {
width,
height,
frames,
content_type,
created_at,
format,
},
} = self;
ApiDetails {
width,
height,
frames,
content_type,
created_at,
format: match format {
InternalFormat::Image(_) => ApiFormat::Image,
InternalFormat::Animation(_) => ApiFormat::Animation,
InternalFormat::Video(_) => ApiFormat::Video,
},
}
}
pub(crate) fn is_video(&self) -> bool {
self.content_type.type_() == "video"
self.inner.content_type.type_() == "video"
}
pub(crate) fn created_at(&self) -> time::OffsetDateTime {
self.created_at.timestamp
self.inner.created_at.timestamp
}
pub(crate) async fn from_bytes(timeout: u64, input: web::Bytes) -> Result<Self, Error> {
@ -74,19 +123,19 @@ impl Details {
}
pub(crate) fn internal_format(&self) -> InternalFormat {
self.format
self.inner.format
}
pub(crate) fn media_type(&self) -> mime::Mime {
(*self.content_type).clone()
(*self.inner.content_type).clone()
}
pub(crate) fn system_time(&self) -> std::time::SystemTime {
self.created_at.into()
self.inner.created_at.into()
}
pub(crate) fn video_format(&self) -> Option<InternalVideoFormat> {
match self.format {
match self.inner.format {
InternalFormat::Video(format) => Some(format),
_ => None,
}
@ -100,12 +149,14 @@ impl Details {
created_at: HumanDate,
) -> Self {
Self {
inner: DetailsInner {
width,
height,
frames,
content_type: Serde::new(format.media_type()),
created_at,
format,
},
}
}
@ -116,6 +167,7 @@ impl Details {
frames: Option<u32>,
) -> Self {
Self {
inner: DetailsInner {
width,
height,
frames,
@ -124,6 +176,7 @@ impl Details {
timestamp: OffsetDateTime::now_utc(),
},
format,
},
}
}
}

View file

@ -34,7 +34,7 @@ use actix_web::{
http::header::{CacheControl, CacheDirective, LastModified, Range, ACCEPT_RANGES},
web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer,
};
use details::HumanDate;
use details::{ApiDetails, HumanDate};
use futures_core::Stream;
use metrics_exporter_prometheus::PrometheusBuilder;
use middleware::Metrics;
@ -296,7 +296,7 @@ async fn handle_upload<S: Store + 'static>(
files.push(serde_json::json!({
"file": alias.to_string(),
"delete_token": delete_token.to_string(),
"details": details,
"details": details.into_api_details(),
}));
}
}
@ -446,7 +446,7 @@ async fn claim_upload<S: Store + 'static>(
"files": [{
"file": alias.to_string(),
"delete_token": token.to_string(),
"details": details,
"details": details.into_api_details(),
}]
})))
}
@ -543,7 +543,7 @@ async fn do_download_inline<S: Store + 'static>(
"files": [{
"file": alias.to_string(),
"delete_token": delete_token.to_string(),
"details": details,
"details": details.into_api_details(),
}]
})))
}
@ -603,7 +603,7 @@ struct PageJson {
struct HashJson {
hex: String,
aliases: Vec<String>,
details: Option<Details>,
details: Option<ApiDetails>,
}
/// Get a page of hashes
@ -637,7 +637,9 @@ async fn page(
let identifier = repo.identifier(hash.clone()).await?;
let details = if let Some(identifier) = identifier {
repo.details(&identifier).await?
repo.details(&identifier)
.await?
.map(|d| d.into_api_details())
} else {
None
};
@ -769,7 +771,7 @@ async fn process_details<S: Store>(
let details = details.ok_or(UploadError::NoFiles)?;
Ok(HttpResponse::Ok().json(&details))
Ok(HttpResponse::Ok().json(&details.into_api_details()))
}
async fn not_found_hash(repo: &ArcRepo) -> Result<Option<(Alias, Hash)>, Error> {
@ -1105,7 +1107,7 @@ async fn do_details<S: Store + 'static>(
) -> Result<HttpResponse, Error> {
let details = ensure_details(&repo, &store, &config, &alias).await?;
Ok(HttpResponse::Ok().json(&details))
Ok(HttpResponse::Ok().json(&details.into_api_details()))
}
/// Serve files based on alias query

View file

@ -932,7 +932,7 @@ impl DetailsRepo for SledRepo {
details: &Details,
) -> Result<(), StoreError> {
let key = identifier.to_bytes()?;
let details = serde_json::to_vec(&details)
let details = serde_json::to_vec(&details.inner)
.map_err(SledError::from)
.map_err(RepoError::from)?;
@ -950,7 +950,7 @@ impl DetailsRepo for SledRepo {
let opt = b!(self.identifier_details, identifier_details.get(key));
opt.map(|ivec| serde_json::from_slice(&ivec))
opt.map(|ivec| serde_json::from_slice(&ivec).map(|inner| Details { inner }))
.transpose()
.map_err(SledError::from)
.map_err(RepoError::from)