use super::*;
use std::rc::Rc;
#[derive(Debug)]
pub struct Base<T> {
index: Index,
name: String,
gl: Rc<GL>,
value: T,
}
use core::ops::Deref;
impl<T> Deref for Base<T>{
type Target = T;
fn deref(&self) -> &Self::Target{
&self.value
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
GLError(super::super::context::Error),
Type(gltype::Error),
Uniform(String),
Active(String),
}
use core::fmt;
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match self {
Error::GLError(x) => x.fmt(fmt),
Error::Type(x) => x.fmt(fmt),
Error::Uniform(x) => write! {fmt, "Uniform '{}' does not exists.", x},
Error::Active(x) => write! {fmt, "Uniform '{}' is not active.", x},
}
}
}
impl<T> Uniform<T> for Base<T>
where
T: GLType,
{
fn index(&self) -> &Index {
&self.index
}
fn swap(&mut self, mut value: T) -> T {
use core::mem::swap;
value.send(&*self.gl, &self.index);
swap(&mut self.value, &mut value);
value
}
}
impl<T> ToUniform for T
where
T: GLType,
{
type Output = Base<T>;
type Error = Error;
fn to_uniform(
self,
gl: Rc<GL>,
program: &WebGlProgram,
member: Option<Rc<Member>>,
map: &mut HashMap<String, WebGlActiveInfo>,
) -> Result<Self::Output, Self::Error> {
let name = member.map(|x| x.to_string()).unwrap_or_default();
let index = match gl.get_uniform_location(program, &name) {
Some(x) => Ok(x),
_ => {
use crate::context::GLError;
gl.error().map_err(Error::GLError)?;
Err(Error::Uniform(name.clone()))
}
}?;
let info = map.remove(&name).ok_or(Error::Active(name.clone()))?;
T::compatible(&info).map_err(Error::Type)?;
use core::mem::MaybeUninit;
let mut base = Base::<T> {
index,
name,
gl,
value: unsafe { MaybeUninit::uninit().assume_init() },
};
base.swap(self);
Ok(base)
}
}