///|
fn wgsl_template_const_skip_whitespace(source : String, start : Int) -> Int {
let mut index = start
while index < source.length() {
match source.code_unit_at(index).to_int() {
9 | 10 | 11 | 12 | 13 | 32 => index = index + 1
_ => break
}
}
index
}
///|
fn wgsl_template_const_source_has_prefix_at(
source : String,
start : Int,
prefix : String,
) -> Bool {
guard prefix != "" && start + prefix.length() <= source.length() else {
return false
}
for i in 0.. Bool {
if !source.contains("#") {
return false
}
let mut has_value_define = false
for _ in value_defines.iter() {
has_value_define = true
break
}
if !has_value_define {
return false
}
let mut index = 0
while index < source.length() {
guard source.code_unit_at(index).to_int() == 35 else {
index = index + 1
continue
}
let body_start = wgsl_template_const_skip_whitespace(source, index + 1)
guard body_start < source.length() else {
index = index + 1
continue
}
match source.code_unit_at(body_start).to_int() {
35 | 123 => return true
_ => ()
}
for entry in value_defines.iter() {
let (name, _) = entry
if wgsl_template_const_source_has_prefix_at(source, body_start, name) {
return true
}
}
index = index + 1
}
false
}
///|
fn wgsl_source_needs_ifdef_directive_scan(source : String) -> Bool {
if !source.contains("#") {
return false
}
let mut index = 0
while index < source.length() {
guard source.code_unit_at(index).to_int() == 35 else {
index = index + 1
continue
}
let body_start = wgsl_template_const_skip_whitespace(source, index + 1)
if wgsl_template_const_source_has_prefix_at(source, body_start, "if") ||
wgsl_template_const_source_has_prefix_at(source, body_start, "ifdef") ||
wgsl_template_const_source_has_prefix_at(source, body_start, "ifndef") ||
wgsl_template_const_source_has_prefix_at(source, body_start, "else") ||
wgsl_template_const_source_has_prefix_at(source, body_start, "endif") ||
wgsl_template_const_source_has_prefix_at(source, body_start, "version") {
return true
}
index = index + 1
}
false
}
///|
pub fn apply_wgsl_template_consts(
source : String,
value_defines : Map[String, ShaderDefValue],
) -> String {
if !wgsl_source_may_contain_template_const_reference(source, value_defines) {
return source
}
let out = StringBuilder::new()
let mut copy_start = 0
for reference in parse_wgsl_template_const_references(source, value_defines) {
if value_defines.get(reference.name()) is Some(value) {
out.write_string(source[copy_start:reference.start()].to_owned())
out.write_string(value.value_as_string())
copy_start = reference.end()
}
}
if copy_start < source.length() {
out.write_string(source[copy_start:source.length()].to_owned())
}
out.to_string()
}
///|
pub fn apply_wgsl_ifdefs_strict(
source : String,
shader_defs : Map[String, ShaderDefValue],
) -> String raise PreprocessError {
if !wgsl_source_needs_ifdef_directive_scan(source) {
return source
}
let out = StringBuilder::new()
let scope = Scope()
let import_state = WgslImportSubstitutionState::default()
for item in parse_wgsl_directive_scan_items(source) {
let offset = item.start()
match item.kind() {
GlslVersion(version) =>
if version != "440" && version != "450" {
raise GlslInvalidVersion(offset)
}
Directive(directive) => {
let (is_scope, _) = preprocess_check_scope_directive(
shader_defs,
directive,
Some(scope),
offset,
)
if !is_scope && scope.active() {
out.write_string(
preprocess_emit_scanned_item(
KeepTrivia,
item,
shader_defs,
import_state,
[],
),
)
}
}
Source =>
if scope.active() {
out.write_string(
preprocess_emit_scanned_item(
KeepTrivia,
item,
shader_defs,
import_state,
[],
),
)
}
}
}
scope.finish(utf8_byte_length(source))
out.to_string()
}