use rand::Rng;
use serde::de::Error;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Eq, Hash, Clone, Copy, PartialEq, PartialOrd, Ord)]
pub struct RenderTargetId(u128);
impl RenderTargetId {
pub fn gen() -> RenderTargetId {
RenderTargetId(rand::thread_rng().gen())
}
}
impl fmt::Display for RenderTargetId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "rt_{}", &base64::encode(self.0.to_be_bytes())[0..22])
}
}
impl fmt::Debug for RenderTargetId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self)
}
}
impl Serialize for RenderTargetId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for RenderTargetId {
fn deserialize<D>(deserializer: D) -> Result<RenderTargetId, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
if let Some(suffix) = s.strip_prefix("rt_") {
let decoded_bytes: Vec<u8> = base64::decode(suffix).map_err(D::Error::custom)?;
let decoded_value = <u128>::from_be_bytes(
decoded_bytes
.try_into()
.map_err(|_| D::Error::custom("render target id is wrong length"))?,
);
Ok(RenderTargetId(decoded_value))
} else {
Err(D::Error::custom(
"not a valid render target id (must start with rt_)",
))
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RenderTarget {
width: u32,
height: u32,
dt: f32,
}
impl RenderTarget {
pub fn new(width: u32, height: u32, dt: f32) -> Self {
Self { width, height, dt }
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
pub fn dt(&self) -> f32 {
self.dt
}
}