use concinnity_core::platform::Platform;
pub(crate) fn stage_source_path(args: &serde_json::Value, platform: Platform) -> Option<String> {
if let Some(obj) = args.get("sources").and_then(|v| v.as_object())
&& let Some(src) = obj.get(platform.key()).and_then(|v| v.as_str())
{
return Some(src.to_string());
}
let src = args
.get("source")
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())?;
let ext = std::path::Path::new(src)
.extension()
.and_then(|e| e.to_str())
.unwrap_or("");
if platform.accepts_ext(ext) {
Some(src.to_string())
} else {
None
}
}
pub(crate) fn resolve_source_from_args(args: &serde_json::Value) -> Option<String> {
stage_source_path(args, Platform::current())
}
pub(crate) fn sdf_volume_source_path(
args: &serde_json::Value,
platform: Platform,
) -> Option<String> {
if let Some(obj) = args.get("fragment_shaders").and_then(|v| v.as_object())
&& let Some(src) = obj
.get(platform.key())
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())
{
return Some(src.to_string());
}
let src = args
.get("fragment_shader")
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())?;
let ext = std::path::Path::new(src)
.extension()
.and_then(|e| e.to_str())
.unwrap_or("");
if platform.accepts_ext(ext) {
Some(src.to_string())
} else {
None
}
}
pub(crate) fn current_platform_source_arg(args: &serde_json::Value) -> Option<String> {
sdf_volume_source_path(args, Platform::current())
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn shader_source_path_selects_per_platform() {
let args = json!({"sources": {"metal": "a.metal", "hlsl": "a.hlsl", "glsl": "a.glsl"}});
assert_eq!(
stage_source_path(&args, Platform::Metal),
Some("a.metal".to_string())
);
assert_eq!(
stage_source_path(&args, Platform::Hlsl),
Some("a.hlsl".to_string())
);
assert_eq!(
stage_source_path(&args, Platform::Glsl),
Some("a.glsl".to_string())
);
let metal_only = json!({"source": "s.metal"});
assert_eq!(
stage_source_path(&metal_only, Platform::Metal),
Some("s.metal".to_string())
);
assert_eq!(stage_source_path(&metal_only, Platform::Hlsl), None);
assert_eq!(
stage_source_path(&json!({"kind": "vertex"}), Platform::Metal),
None
);
}
#[test]
fn sdf_source_path_prefers_map_over_single() {
let args = json!({
"fragment_shader": "shaders/single.metal",
"fragment_shaders": { "metal": "shaders/from_map.metal" },
});
assert_eq!(
sdf_volume_source_path(&args, Platform::Metal).as_deref(),
Some("shaders/from_map.metal")
);
}
}