use serde::Serialize;
use super::types::ProtectedGroup;
#[derive(Debug, Clone)]
pub(super) enum Protection {
Unconditional,
Guarded(Vec<String>),
}
impl Protection {
pub fn new_guarded() -> Self {
Self::Guarded(Vec::new())
}
pub fn add_extension(&mut self, ext_protect: &[String]) {
match self {
Self::Unconditional => {} Self::Guarded(guards) => {
if ext_protect.is_empty() {
*self = Self::Unconditional;
} else {
for p in ext_protect {
if !guards.contains(p) {
guards.push(p.clone());
}
}
}
}
}
}
pub fn into_vec(self) -> Vec<String> {
match self {
Self::Unconditional => Vec::new(),
Self::Guarded(v) if v.is_empty() => Vec::new(),
Self::Guarded(mut v) => {
v.sort();
v
}
}
}
#[allow(dead_code)]
pub fn is_unconditional(&self) -> bool {
matches!(self, Self::Unconditional)
}
}
pub(super) fn group_by_protection_pairs<T>(
items: impl IntoIterator<Item = (Vec<String>, T)>,
) -> Vec<ProtectedGroup<T>>
where
T: std::fmt::Debug + Serialize,
{
let mut groups: Vec<ProtectedGroup<T>> = Vec::new();
for (protect, item) in items {
if let Some(last) = groups.last_mut()
&& last.protect == protect
{
last.items.push(item);
continue;
}
groups.push(ProtectedGroup {
protect,
items: vec![item],
});
}
groups
}
pub(super) fn group_by_protection<T, F>(
items: impl IntoIterator<Item = T>,
get_protect: F,
) -> Vec<ProtectedGroup<T>>
where
T: std::fmt::Debug + Serialize,
F: Fn(&T) -> Vec<String>,
{
let mut groups: Vec<ProtectedGroup<T>> = Vec::new();
for item in items {
let protect = get_protect(&item);
if let Some(last) = groups.last_mut()
&& last.protect == protect
{
last.items.push(item);
continue;
}
groups.push(ProtectedGroup {
protect,
items: vec![item],
});
}
groups
}
const GL_AUTO_EXCLUDE: &[&str] = &["stddef", "khrplatform", "inttypes"];
pub(super) fn is_gl_auto_excluded(name: &str) -> bool {
GL_AUTO_EXCLUDE.contains(&name)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn protection_guarded_absorbs_unconditional() {
let mut p = Protection::Guarded(vec!["VK_USE_PLATFORM_WIN32_KHR".to_string()]);
p.add_extension(&[]); assert!(p.is_unconditional());
}
#[test]
fn protection_unconditional_stays_unconditional() {
let mut p = Protection::Unconditional;
p.add_extension(&["VK_USE_PLATFORM_XLIB_KHR".to_string()]);
assert!(p.is_unconditional());
}
#[test]
fn protection_guarded_unions_guards() {
let mut p = Protection::new_guarded();
p.add_extension(&["VK_USE_PLATFORM_WIN32_KHR".to_string()]);
p.add_extension(&["VK_USE_PLATFORM_XLIB_KHR".to_string()]);
let v = p.into_vec();
assert_eq!(v.len(), 2);
assert_eq!(v[0], "VK_USE_PLATFORM_WIN32_KHR");
assert_eq!(v[1], "VK_USE_PLATFORM_XLIB_KHR");
}
#[test]
fn protection_guarded_deduplicates() {
let mut p = Protection::new_guarded();
p.add_extension(&["VK_USE_PLATFORM_WIN32_KHR".to_string()]);
p.add_extension(&["VK_USE_PLATFORM_WIN32_KHR".to_string()]);
let v = p.into_vec();
assert_eq!(v.len(), 1);
}
#[test]
fn protection_empty_guarded_into_vec_is_empty() {
let p = Protection::new_guarded();
assert!(p.into_vec().is_empty());
}
#[test]
fn protection_unconditional_into_vec_is_empty() {
let p = Protection::Unconditional;
assert!(p.into_vec().is_empty());
}
#[test]
fn gl_auto_excluded_known_names() {
assert!(is_gl_auto_excluded("stddef"));
assert!(is_gl_auto_excluded("khrplatform"));
assert!(is_gl_auto_excluded("inttypes"));
}
#[test]
fn gl_auto_excluded_other_names() {
assert!(!is_gl_auto_excluded("GLuint"));
assert!(!is_gl_auto_excluded("GLenum"));
}
}