use std::{ fmt::{Debug, Display}, ops::{Add, AddAssign, Div, Mul, Sub, SubAssign}, }; use binrw::{binrw, BinRead, BinWrite}; use diff::{Diff, VecDiff}; use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; use strum::EnumIter; use crate::{array_of::ArrayOfPrimitive, field_of::FieldOf}; /// Generic field with structure of length + data pub type Field = ArrayOfPrimitive; pub type U16 = FieldOf; pub type I16 = FieldOf; pub type U32 = FieldOf; pub type I32 = FieldOf; pub type F64 = FieldOf; pub type Bool = FieldOf; impl From> for bool { fn from(value: FieldOf) -> Self { value.value != 0 } } impl From for FieldOf { fn from(value: bool) -> Self { Self { value: match value { true => 1, false => 0, }, } } } #[binrw] #[derive(Clone, Default, PartialEq)] pub struct WString { // Temporary variable that holds number of elements #[br(temp)] #[bw(try_calc(u32::try_from(value.len() * core::mem::size_of::())))] size: u32, #[br(count = size / core::mem::size_of::() as u32)] pub value: Vec, } impl From<&WString> for String { fn from(value: &WString) -> Self { String::from_utf16_lossy(&value.value) } } impl From for WString { fn from(value: String) -> Self { let value: Vec = value.encode_utf16().collect(); Self { value } } } // Custom Diff implementation to only diff internal value impl Diff for WString { type Repr = VecDiff; fn diff(&self, other: &Self) -> Self::Repr { self.value.diff(&other.value) } fn apply(&mut self, diff: &Self::Repr) { self.value.apply(diff) } fn identity() -> Self { Self { value: vec![] } } } impl Debug for WString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "\"{}\"", String::from(self)) } } impl Display for WString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", String::from(self)) } } #[derive(Clone, Debug, Default, Diff, PartialEq, BinRead, BinWrite)] #[diff(attr( #[derive(Debug, PartialEq)] ))] pub struct Rgba { pub red: u8, pub green: u8, pub blue: u8, pub alpha: u8, } impl From<(u8, u8, u8)> for Rgba { fn from(value: (u8, u8, u8)) -> Self { Self { red: value.0, green: value.1, blue: value.2, alpha: 0, } } } impl Rgba { pub fn random() -> Self { Self { red: thread_rng().gen(), green: thread_rng().gen(), blue: thread_rng().gen(), alpha: 0, } } } #[derive( Copy, Clone, Debug, Default, Diff, PartialEq, BinRead, BinWrite, Serialize, Deserialize, )] #[diff(attr( #[derive(Debug, PartialEq)] ))] #[serde(rename_all = "PascalCase")] pub struct Coordinate { pub x: f64, pub y: f64, } impl Display for Coordinate { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "({}, {})", self.x, self.y) } } impl Sub for Coordinate { type Output = Coordinate; fn sub(self, rhs: Self) -> Self::Output { Coordinate { x: self.x - rhs.x, y: self.y - rhs.y, } } } impl SubAssign for Coordinate { fn sub_assign(&mut self, rhs: Self) { self.x -= rhs.x; self.y -= rhs.y; } } impl Add for Coordinate { type Output = Coordinate; fn add(self, rhs: Self) -> Self::Output { Coordinate { x: self.x + rhs.x, y: self.y + rhs.y, } } } impl AddAssign for Coordinate { fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; } } impl Mul for Coordinate { type Output = Coordinate; fn mul(self, rhs: Self) -> Self::Output { Coordinate { x: self.x * rhs.x, y: self.y * rhs.y, } } } impl Div for Coordinate { type Output = Coordinate; fn div(self, rhs: Self) -> Self::Output { Coordinate { x: self.x / rhs.x, y: self.y / rhs.y, } } } impl From<(f64, f64)> for Coordinate { fn from(value: (f64, f64)) -> Self { Self { x: value.0, y: value.1, } } } #[derive(Clone, Debug, Diff, PartialEq, BinRead, BinWrite, strum::Display)] #[diff(attr( #[derive(Debug, PartialEq)] ))] #[brw(repr(u32))] #[repr(u32)] pub enum WobbleType { Spiral = 0, Sinusoidal = 1, Ellipse = 2, Vert8 = 3, Hori8 = 4, Unknown = 5, } impl Default for WobbleType { fn default() -> Self { WobbleType::Unknown } } #[derive(Clone, Debug, Diff, PartialEq, BinRead, BinWrite, strum::Display)] #[diff(attr( #[derive(Debug, PartialEq)] ))] #[brw(repr(u16))] #[repr(u16)] pub enum ObjectType { Unknown = 0, Curve = 1, Point = 2, Rectangle = 3, Circle = 4, Ellipse = 5, Polygon = 6, HatchLine = 16, Hatch = 32, } impl Default for ObjectType { fn default() -> Self { ObjectType::Unknown } } #[derive(Copy, Clone, Debug, Diff, PartialEq, strum::Display, Serialize, Deserialize, EnumIter)] #[diff(attr( #[derive(Debug, PartialEq)] ))] #[serde(try_from = "u32")] #[serde(into = "u32")] #[repr(u32)] pub enum PulseWidth { Ns2, Ns4, Ns6, Ns8, Ns12, Ns20, Ns30, Ns45, Ns60, Ns80, Ns100, Ns150, Ns200, Ns250, Ns350, Ns500, } impl From for u32 { fn from(value: PulseWidth) -> Self { match value { PulseWidth::Ns2 => 2, PulseWidth::Ns4 => 4, PulseWidth::Ns6 => 6, PulseWidth::Ns8 => 8, PulseWidth::Ns12 => 12, PulseWidth::Ns20 => 20, PulseWidth::Ns30 => 30, PulseWidth::Ns45 => 45, PulseWidth::Ns60 => 60, PulseWidth::Ns80 => 80, PulseWidth::Ns100 => 100, PulseWidth::Ns150 => 150, PulseWidth::Ns200 => 200, PulseWidth::Ns250 => 250, PulseWidth::Ns350 => 350, PulseWidth::Ns500 => 500, } } } pub enum PulseWidthError { Unsupported, } impl Display for PulseWidthError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { PulseWidthError::Unsupported => write!(f, "Unsupported pulse width value"), } } } impl TryFrom for PulseWidth { type Error = PulseWidthError; fn try_from(value: u32) -> Result { match value { 2 => Ok(PulseWidth::Ns2), 4 => Ok(PulseWidth::Ns4), 6 => Ok(PulseWidth::Ns6), 8 => Ok(PulseWidth::Ns8), 12 => Ok(PulseWidth::Ns12), 20 => Ok(PulseWidth::Ns20), 30 => Ok(PulseWidth::Ns30), 45 => Ok(PulseWidth::Ns45), 60 => Ok(PulseWidth::Ns60), 80 => Ok(PulseWidth::Ns80), 100 => Ok(PulseWidth::Ns100), 150 => Ok(PulseWidth::Ns150), 200 => Ok(PulseWidth::Ns200), 250 => Ok(PulseWidth::Ns250), 350 => Ok(PulseWidth::Ns350), 500 => Ok(PulseWidth::Ns500), _ => Err(PulseWidthError::Unsupported), } } }