rs2glsl 0.3.4

Conversion from Rust code to GLSL
Documentation
//!
//! Automatic code convertion from Rust to GLSL.
//!
//! ```
//! # fn main() {
//! use rs2glsl::prelude::*;
//!
//! #[glsl]
//! fn smooth_min(a: f32, b: f32, k: f32) -> f32 {
//!     let mut h: f32 = a - b;
//!
//!     h = 0.5 + 0.5 * h;
//!
//!     if h < 0.0 {
//!         h = 0.0;
//!     }
//!     if h > 1.0 {
//!         h = 1.0;
//!     }
//!
//!     return interpolation(a, b, h) - k * h * (1.0 - h);
//! }
//!
//! #[glsl]
//! fn interpolation(a: f32, b: f32, t: f32) -> f32 {
//!     return a * (1.0 - t) + b * t;
//! }
//!
//! let expected = r#"
//! float smooth_min(float a, float b, float k) {
//!     float h = a - b;
//!     h = 0.5 + 0.5 * h;
//!     if (h < 0.0) {
//!         h = 0.0;
//!     }
//!     if (h > 1.0) {
//!         h = 1.0;
//!     }
//!     return interpolation(a, b, h) - k * h * (1.0 - h);
//! }
//! "#;
//!
//! assert_eq!(expected.trim(), GLSL_SMOOTH_MIN.definition());
//! # }
//! ```
//!
//!
//!
//!

use std::collections::HashSet;

/// An abstract Item representing an entity in GLSL code.
/// May be implemented by GLSL constants, types, and functions.
pub trait GlslItem: core::fmt::Debug {
    /// the name of the item with which it is referred in GLSL
    fn name(&self) -> &'static str;

    /// List of dependencies which this item uses.
    ///
    /// Only contains something for a function which is annotated with `#[glsl]`, namely all the functions, constants, and types it uses.
    fn dependencies(&self) -> Vec<Box<dyn GlslItem>>;

    /// GLSL definition
    fn definition(&self) -> &'static str;

    /// the definition of this item, prepended with all the definitions of the items it depends on.
    ///
    /// do not implement manually
    fn with_dependencies(&self) -> String {
        let mut items = HashSet::new();
        let mut code = String::new();
        self.with_dependencies_impl(&mut items, &mut code);
        code
    }

    /// Recursive implementation of [`with_dependencies`](T::with_dependencies) such that [`with_dependencies`](T::with_dependencies) can have fewer parameters.
    ///
    /// You will probably never need to call this function manually.
    fn with_dependencies_impl(&self, items: &mut HashSet<&'static str>, code: &mut String) {
        if items.contains(self.name()) {
            return;
        }
        items.insert(self.name());

        for dep in self.dependencies() {
            dep.with_dependencies_impl(items, code);
        }

        if code.len() > 0 && self.definition().len() > 0 {
            *code += "\n\n";
        }
        *code += self.definition();
    }
}

/// All types, traits, and functions for use with GLSL
///
/// just `use rs2glsl::prelude::*` and never worry about imports again.
pub mod prelude {
    pub use crate::macros::*;
    pub use crate::traits::*;
    pub use crate::types::*;
}

/// All traits defined in rs2glsl.
pub mod traits {
    pub use super::GlslItem;
    ::rs2glsl_macros::make_traits!();
}

/// Macro implementations
pub mod macros {
    // for doc comment hyperlink
    #[allow(unused_imports)]
    use super::prelude::*;

    /// Generates a corresponding GLSL implementation of a Rust item.
    ///
    /// # Example
    /// ```
    /// # fn main() {
    /// use rs2glsl::prelude::*;
    ///
    /// #[glsl]
    /// fn choose(choice: bool, a: f32, b: f32) -> f32 {
    ///     if choice {
    ///         return a;
    ///     }
    ///     return b;
    /// }
    ///
    /// assert!(GLSL_CHOOSE.definition().starts_with("float choose(bool choice, float a, float b)"));
    /// # }
    /// ```
    ///
    /// The generated item always has the form `GLSL_{NAME_IN_UPPERCASE}`.
    /// If you use call some glsl function from another, be sure to import that constant.
    ///
    /// The generated constant implements [`GlslItem`], so check it out.
    ///
    pub use ::rs2glsl_macros::glsl;

    /// Defines the Rust implementation of an item that natively exists in GLSL
    ///
    /// Its primary use case should be to implement missing functions from the GLSL standard library.
    ///
    /// However, it can also be used to implement a function in Rust with all its syntax, while providing an own implementation in GLSL at some other place.
    pub use ::rs2glsl_macros::glsl_native;
}

/// GLSL types in Rust
pub mod types {
    use core::ops::*;
    use crate::traits::*;

    ::rs2glsl_macros::make_types!();

    fn dist_squared<T: Add<Output=T> + Sub<Output=T> + Mul<Output=T> + Div<Output=T> + Copy>(a: T, b: T) -> T {
        let d = a - b;
        d * d
    }
    fn lerp<T: Add<Output=T> + Sub<Output=T> + Mul<Output=T> + Div<Output=T> + Copy>(x: T, y: T, a: T) -> T {
        x - x * a + y * a
    }
}