aboutsummaryrefslogtreecommitdiffstats
path: root/src/types.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/types.rs')
-rw-r--r--src/types.rs145
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
+ }
+ })
+ }
+ }
+}