diman_unit_system 0.5.1

Internal procedural macros for diman.
Documentation
use quote::quote;

use proc_macro2::TokenStream;

use super::storage_types::FloatType;
use super::Codegen;

impl Codegen {
    pub fn gen_rand_impl(&self) -> TokenStream {
        let float_impls: TokenStream = self
            .float_types()
            .iter()
            .map(|float_type| self.rand_impl_float(float_type))
            .collect();
        let dimension_type = &self.defs.dimension_type;
        quote! {
            use ::rand::distributions::uniform::SampleBorrow;
            use ::rand::distributions::uniform::SampleUniform;
            use ::rand::distributions::uniform::UniformFloat;
            use ::rand::distributions::uniform::UniformSampler;
            use ::rand::prelude::*;

            #[derive(Clone, Copy, Debug)]
            pub struct UniformQuantity<S, const D: #dimension_type>(UniformFloat<S>);

            #float_impls
        }
    }

    fn rand_impl_float(&self, float_type: &FloatType) -> TokenStream {
        let dimension_type = &self.defs.dimension_type;
        let quantity_type = &self.defs.quantity_type;
        let float_type = &float_type.name;
        quote! {
            impl<const D: #dimension_type> UniformSampler for UniformQuantity<#float_type, D> {
                type X = #quantity_type::<#float_type, D>;
                fn new<B1, B2>(low: B1, high: B2) -> Self
                where
                    B1: SampleBorrow<Self::X> + Sized,
                    B2: SampleBorrow<Self::X> + Sized,
                {
                    UniformQuantity::<#float_type, D>(UniformFloat::<#float_type>::new(
                        low.borrow().0,
                        high.borrow().0,
                    ))
                }
                fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
                where
                    B1: SampleBorrow<Self::X> + Sized,
                    B2: SampleBorrow<Self::X> + Sized,
                {
                    UniformQuantity::<#float_type, D>(UniformFloat::<#float_type>::new_inclusive(
                        low.borrow().0,
                        high.borrow().0,
                    ))
                }

                fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
                    #quantity_type::<#float_type, D>(self.0.sample(rng))
                }
            }

            impl<const D: #dimension_type> SampleUniform for #quantity_type<#float_type, D> {
                type Sampler = UniformQuantity<#float_type, D>;
            }
        }
    }
}