diff options
Diffstat (limited to 'src/types.rs')
| -rw-r--r-- | src/types.rs | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..b1ed2fb --- /dev/null +++ b/src/types.rs @@ -0,0 +1,145 @@ +use std::fmt; + +#[derive(Copy, Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum FloatPrecision { + Single, + Double, +} + +#[derive(Copy, Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum ScalarType { + Float(FloatPrecision), + Int, + UInt, + Bool, +} + +#[derive(Copy, Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] +#[repr(u8)] +pub enum Dimension { + D2 = 2, + D3 = 3, + D4 = 4, +} +impl fmt::Display for Dimension { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", *self as u8) + } +} +impl Dimension { + pub const fn from(v: usize) -> Dimension { + match v { + 2 => Self::D2, + 3 => Self::D3, + 4 => Self::D4, + _ => panic!("invalid dimension value"), + } + } +} + +/// a GLSL type +#[derive(Copy, Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum Type { + Scalar(ScalarType), + Vector(ScalarType, Dimension), + Matrix(FloatPrecision, Dimension, Dimension), +} + +impl From<ScalarType> for Type { + fn from(val: ScalarType) -> Self { + Self::Scalar(val) + } +} + +impl Type { + pub fn scalar(&self) -> ScalarType { + match self { + Type::Scalar(s) => *s, + Type::Vector(s, _) => *s, + Type::Matrix(p, _, _) => ScalarType::Float(*p), + } + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Type::Scalar(s) => write!( + f, + "{}", + match s { + ScalarType::Float(FloatPrecision::Single) => "float", + ScalarType::Float(FloatPrecision::Double) => "double", + ScalarType::Int => "int", + ScalarType::UInt => "uint", + ScalarType::Bool => "bool", + } + ), + Type::Vector(s, d) => write!( + f, + "{}vec{d}", + match s { + ScalarType::Float(FloatPrecision::Single) => "", + ScalarType::Float(FloatPrecision::Double) => "d", + ScalarType::Int => "i", + ScalarType::UInt => "u", + ScalarType::Bool => "b", + } + ), + Type::Matrix(p, r, c) => { + let pr = match p { + FloatPrecision::Single => "", + FloatPrecision::Double => "d", + }; + if r == c { + write!(f, "{pr}mat{r}") + } else { + write!(f, "{pr}mat{r}{c}") + } + } + } + } +} + +/// a single concrete type signature for a function +#[derive(PartialEq, Debug)] +pub struct TypeSignature { + pub inputs: Box<[Type]>, + pub outputs: Box<[Type]>, +} + +impl TypeSignature { + pub fn new<const NI: usize, const NO: usize>(inputs: [Type; NI], outputs: [Type; NO]) -> Self { + Self { + inputs: Box::new(inputs), + outputs: Box::new(outputs), + } + } +} + +impl TypeSignature { + pub fn matches_inputs(&self, connected: &[Option<Type>]) -> bool { + let have_inputs = connected + .iter() + .enumerate() + .filter(|(_, t)| matches!(t, Some(_))) + .map(|(i, _)| i + 1) + .max() + .unwrap_or(0); + + if have_inputs > self.inputs.len() { + false + } else { + connected + .iter() + .zip(self.inputs.iter()) + .all(|(connected_input, expected)| { + if let Some(input) = connected_input { + *input == *expected + } else { + true + } + }) + } + } +} |
