extern crate proc_macro;
use proc_macro::TokenStream;
use std::collections::HashMap;
use naga::FastHashMap;
use serde::Deserialize;
#[cfg(feature = "to-glsl")]
mod glsl;
#[cfg(feature = "to-hlsl")]
mod hlsl;
#[cfg(feature = "to-msl")]
mod msl;
#[cfg(feature = "to-spv")]
mod spv;
mod util;
#[cfg(feature = "to-wgsl")]
mod wgsl;
#[derive(Deserialize)]
struct Transpile<'a> {
_entry_point: Option<&'a str>,
stage: &'a str,
source: &'a str,
from: &'a str,
to: &'a str,
defines: Option<HashMap<String, String>>,
}
#[proc_macro]
pub fn transpile(input: TokenStream) -> TokenStream {
let mut input = input.to_string();
input.insert(0, '(');
input.push(')');
let input: Transpile =
ron::from_str(input.as_str()).expect("Failed to parse input as RON struct");
let stage = util::parse_stage(input.stage);
#[allow(clippy::redundant_closure)]
let _from = util::parse_from(
input.source,
stage,
input.defines.map(|some| FastHashMap::from_iter(some)),
input.from,
);
match input.to {
#[cfg(feature = "to-hlsl")]
"hlsl" => TokenStream::from(proc_macro::TokenTree::Literal(proc_macro::Literal::string(
hlsl::to_hlsl(_from).as_str(),
))),
#[cfg(feature = "to-wgsl")]
"wgsl" => TokenStream::from(proc_macro::TokenTree::Literal(proc_macro::Literal::string(
wgsl::to_wgsl(_from).as_str(),
))),
#[cfg(feature = "to-spv")]
"spv" => format!("{:?}", spv::to_spv(_from)).parse().unwrap(),
#[cfg(feature = "to-glsl")]
"glsl" => TokenStream::from(proc_macro::TokenTree::Literal(proc_macro::Literal::string(
glsl::to_glsl(
_from,
stage,
input._entry_point.expect("GLSL requires an entry point"),
)
.as_str(),
))),
#[cfg(feature = "to-msl")]
"msl" => TokenStream::from(proc_macro::TokenTree::Literal(proc_macro::Literal::string(
msl::to_msl(_from).as_str(),
))),
_ => panic!("Unsupported output language: {}", input.to),
}
}
#[proc_macro]
pub fn transpile_file(input: TokenStream) -> TokenStream {
let mut input = input.to_string();
input.insert(0, '(');
input.push(')');
let mut input: Transpile =
ron::from_str(input.as_str()).expect("Failed to parse input as RON struct");
let stage = util::parse_stage(input.stage);
let file = std::fs::read_to_string(input.source).expect("Failed to read source file");
input.source = file.as_str();
#[allow(clippy::redundant_closure)]
let _from = util::parse_from(
input.source,
stage,
input.defines.map(|some| FastHashMap::from_iter(some)),
input.from,
);
match input.to {
#[cfg(feature = "to-hlsl")]
"hlsl" => TokenStream::from(proc_macro::TokenTree::Literal(proc_macro::Literal::string(
hlsl::to_hlsl(_from).as_str(),
))),
#[cfg(feature = "to-wgsl")]
"wgsl" => TokenStream::from(proc_macro::TokenTree::Literal(proc_macro::Literal::string(
wgsl::to_wgsl(_from).as_str(),
))),
#[cfg(feature = "to-spv")]
"spv" => format!("{:?}", spv::to_spv(_from)).parse().unwrap(),
#[cfg(feature = "to-glsl")]
"glsl" => TokenStream::from(proc_macro::TokenTree::Literal(proc_macro::Literal::string(
glsl::to_glsl(
_from,
stage,
input._entry_point.expect("GLSL requires an entry point"),
)
.as_str(),
))),
#[cfg(feature = "to-msl")]
"msl" => TokenStream::from(proc_macro::TokenTree::Literal(proc_macro::Literal::string(
msl::to_msl(_from).as_str(),
))),
_ => panic!("Unsupported output language: {}", input.to),
}
}