pict-rs/src/details.rs

206 lines
4.9 KiB
Rust
Raw Permalink Normal View History

use crate::{
2024-02-22 22:02:33 +00:00
bytes_stream::BytesStream,
discover::Discovery,
error::Error,
formats::{InternalFormat, InternalVideoFormat},
serde_str::Serde,
2024-02-04 00:18:13 +00:00
state::State,
};
2024-02-22 22:03:49 +00:00
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
2022-03-24 22:09:15 +00:00
#[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize)]
2023-08-29 17:59:36 +00:00
#[serde(transparent)]
pub(crate) struct HumanDate {
#[serde(with = "time::serde::rfc3339")]
pub(crate) timestamp: time::OffsetDateTime,
}
#[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)]
2022-03-24 22:09:15 +00:00
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>,
2022-03-24 22:09:15 +00:00
content_type: Serde<mime::Mime>,
2023-08-29 17:59:36 +00:00
created_at: HumanDate,
2023-08-16 17:36:18 +00:00
format: InternalFormat,
2022-03-24 22:09:15 +00:00
}
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 created_at(&self) -> time::OffsetDateTime {
self.inner.created_at.timestamp
}
2023-12-16 04:34:45 +00:00
#[tracing::instrument(level = "debug", skip_all)]
2024-02-22 22:02:33 +00:00
pub(crate) async fn from_bytes_stream<S>(
state: &State<S>,
input: BytesStream,
) -> Result<Self, Error> {
let Discovery {
input,
width,
height,
frames,
2024-02-22 22:02:33 +00:00
} = crate::discover::discover_bytes_stream(state, input).await?;
Ok(Details::from_parts(
input.internal_format(),
width,
height,
frames,
))
2022-03-24 22:09:15 +00:00
}
2024-02-24 04:12:19 +00:00
pub(crate) fn width(&self) -> u16 {
self.inner.width
}
pub(crate) fn height(&self) -> u16 {
self.inner.height
}
2023-08-16 17:36:18 +00:00
pub(crate) fn internal_format(&self) -> InternalFormat {
self.inner.format
2022-03-24 22:09:15 +00:00
}
pub(crate) fn media_type(&self) -> mime::Mime {
(*self.inner.content_type).clone()
2022-03-24 22:09:15 +00:00
}
2024-02-28 02:41:25 +00:00
pub(crate) fn file_extension(&self) -> &'static str {
self.inner.format.file_extension()
}
2022-03-24 22:09:15 +00:00
pub(crate) fn system_time(&self) -> std::time::SystemTime {
self.inner.created_at.into()
2022-03-24 22:09:15 +00:00
}
2024-02-24 04:12:19 +00:00
pub(crate) fn is_video(&self) -> bool {
matches!(self.inner.format, InternalFormat::Video(_))
}
pub(crate) fn video_format(&self) -> Option<InternalVideoFormat> {
match self.inner.format {
2023-08-16 17:36:18 +00:00
InternalFormat::Video(format) => Some(format),
_ => None,
}
2023-08-16 17:36:18 +00:00
}
2023-11-11 20:22:12 +00:00
pub(crate) fn danger_dummy(format: InternalFormat) -> Self {
Self::from_parts_full(
format,
0,
0,
None,
HumanDate {
timestamp: time::OffsetDateTime::now_utc(),
},
)
}
2023-08-16 17:36:18 +00:00
pub(crate) fn from_parts_full(
format: InternalFormat,
width: u16,
height: u16,
frames: Option<u32>,
2023-08-29 17:59:36 +00:00
created_at: HumanDate,
2023-08-16 17:36:18 +00:00
) -> Self {
Self {
inner: DetailsInner {
width,
height,
frames,
content_type: Serde::new(format.media_type()),
created_at,
format,
},
}
}
pub(crate) fn from_parts(
format: InternalFormat,
width: u16,
height: u16,
frames: Option<u32>,
) -> Self {
Self {
inner: DetailsInner {
width,
height,
frames,
content_type: Serde::new(format.media_type()),
created_at: HumanDate {
timestamp: OffsetDateTime::now_utc(),
},
format,
2023-08-29 17:59:36 +00:00
},
}
}
2022-03-24 22:09:15 +00:00
}
2023-08-29 17:59:36 +00:00
impl From<HumanDate> for std::time::SystemTime {
fn from(HumanDate { timestamp }: HumanDate) -> Self {
timestamp.into()
}
}
2023-08-29 17:59:36 +00:00
impl std::fmt::Display for HumanDate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2023-08-29 17:59:36 +00:00
let s = self
.timestamp
.format(&Rfc3339)
.map_err(|_| std::fmt::Error)?;
2023-08-29 17:59:36 +00:00
f.write_str(&s)
}
}