From db3d5d05a6ad15e521675fdc0040f0811deb9d32 Mon Sep 17 00:00:00 2001 From: chyyran Date: Tue, 20 Aug 2024 22:08:17 -0400 Subject: [PATCH] presets: use crate for extract_if with fully qualified syntax to avoid name collision with unstable std --- Cargo.lock | 7 + librashader-presets/Cargo.toml | 1 + librashader-presets/src/extract_if.rs | 312 ------------------------ librashader-presets/src/lib.rs | 4 - librashader-presets/src/parse/preset.rs | 66 ++--- librashader-presets/src/parse/value.rs | 31 ++- librashader-reflect/src/front/mod.rs | 1 - 7 files changed, 61 insertions(+), 361 deletions(-) delete mode 100644 librashader-presets/src/extract_if.rs diff --git a/Cargo.lock b/Cargo.lock index 2f8a11d..750167c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1706,6 +1706,7 @@ dependencies = [ "once_cell", "regex", "thiserror", + "vec_extract_if_polyfill", ] [[package]] @@ -3418,6 +3419,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "vec_extract_if_polyfill" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c9cb5fb67c2692310b6eb3fce7dd4b6e4c9a75be4f2f46b27f0b2b7799759c" + [[package]] name = "version-compare" version = "0.2.0" diff --git a/librashader-presets/Cargo.toml b/librashader-presets/Cargo.toml index b73e3e1..c6de63a 100644 --- a/librashader-presets/Cargo.toml +++ b/librashader-presets/Cargo.toml @@ -20,6 +20,7 @@ num-traits = "0.2" once_cell = "1" # we don't need unicode regex = { version = "1", default-features = false, features = ["perf"] } +vec_extract_if_polyfill = "0.1.0" [features] parse_legacy_glsl = [] diff --git a/librashader-presets/src/extract_if.rs b/librashader-presets/src/extract_if.rs deleted file mode 100644 index 0901df4..0000000 --- a/librashader-presets/src/extract_if.rs +++ /dev/null @@ -1,312 +0,0 @@ -//! This is a stable polyfill for [`Vec::extract_if`](https://github.com/rust-lang/rust/issues/43244). - -use core::ptr; -use core::slice; - -/// Polyfill trait for [`Vec::extract_if`](https://github.com/rust-lang/rust/issues/43244). -pub(crate) trait MakeExtractIf { - /// Creates an iterator which uses a closure to determine if an element should be removed. - /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the vector and will not be yielded - /// by the iterator. - /// - /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating - /// or the iteration short-circuits, then the remaining elements will be retained. - /// - /// Note that `extract_if` also lets you mutate every element in the filter closure, - /// regardless of whether you choose to keep or remove it. - /// - /// # Examples - /// - /// Splitting an array into evens and odds, reusing the original allocation: - /// - /// ``` - /// use vec_extract_if_polyfill::MakeExtractIf; - /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; - /// - /// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::>(); - /// let odds = numbers; - /// - /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); - /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); - /// ``` - fn extract_if(&mut self, filter: F) -> ExtractIf - where - F: FnMut(&mut T) -> bool; -} - -impl MakeExtractIf for Vec { - fn extract_if(&mut self, filter: F) -> ExtractIf - where - F: FnMut(&mut T) -> bool, - { - let old_len = self.len(); - - // Guard against us getting leaked (leak amplification) - unsafe { - self.set_len(0); - } - - ExtractIf { - vec: self, - idx: 0, - del: 0, - old_len, - pred: filter, - } - } -} -/// An iterator which uses a closure to determine if an element should be removed. -/// -/// This struct is created by [`Vec::extract_if`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// use vec_extract_if_polyfill::MakeExtractIf; -/// -/// let mut v = vec![0, 1, 2]; -/// let iter = v.extract_if(|x| *x % 2 == 0); -/// ``` -#[derive(Debug)] -#[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct ExtractIf<'a, T, F> -where - F: FnMut(&mut T) -> bool, -{ - vec: &'a mut Vec, - /// The index of the item that will be inspected by the next call to `next`. - idx: usize, - /// The number of items that have been drained (removed) thus far. - del: usize, - /// The original length of `vec` prior to draining. - old_len: usize, - /// The filter test predicate. - pred: F, -} - -impl Iterator for ExtractIf<'_, T, F> -where - F: FnMut(&mut T) -> bool, -{ - type Item = T; - - fn next(&mut self) -> Option { - unsafe { - while self.idx < self.old_len { - let i = self.idx; - let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); - let drained = (self.pred)(&mut v[i]); - // Update the index *after* the predicate is called. If the index - // is updated prior and the predicate panics, the element at this - // index would be leaked. - self.idx += 1; - if drained { - self.del += 1; - return Some(ptr::read(&v[i])); - } else if self.del > 0 { - let del = self.del; - let src: *const T = &v[i]; - let dst: *mut T = &mut v[i - del]; - ptr::copy_nonoverlapping(src, dst, 1); - } - } - None - } - } - - fn size_hint(&self) -> (usize, Option) { - (0, Some(self.old_len - self.idx)) - } -} - -impl Drop for ExtractIf<'_, T, F> -where - F: FnMut(&mut T) -> bool, -{ - fn drop(&mut self) { - unsafe { - if self.idx < self.old_len && self.del > 0 { - // This is a pretty messed up state, and there isn't really an - // obviously right thing to do. We don't want to keep trying - // to execute `pred`, so we just backshift all the unprocessed - // elements and tell the vec that they still exist. The backshift - // is required to prevent a double-drop of the last successfully - // drained item prior to a panic in the predicate. - let ptr = self.vec.as_mut_ptr(); - let src = ptr.add(self.idx); - let dst = src.sub(self.del); - let tail_len = self.old_len - self.idx; - src.copy_to(dst, tail_len); - } - self.vec.set_len(self.old_len - self.del); - } - } -} - -#[cfg(test)] -mod test { - use crate::extract_if::MakeExtractIf; - #[test] - fn drain_filter_empty() { - let mut vec: Vec = vec![]; - - { - let mut iter = vec.extract_if(|_| true); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - assert_eq!(vec.len(), 0); - assert_eq!(vec, vec![]); - } - - #[test] - fn drain_filter_zst() { - let mut vec = vec![(), (), (), (), ()]; - let initial_len = vec.len(); - let mut count = 0; - { - let mut iter = vec.extract_if(|_| true); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - while let Some(_) = iter.next() { - count += 1; - assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, initial_len); - assert_eq!(vec.len(), 0); - assert_eq!(vec, vec![]); - } - - #[test] - fn drain_filter_false() { - let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - let initial_len = vec.len(); - let mut count = 0; - { - let mut iter = vec.extract_if(|_| false); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - for _ in iter.by_ref() { - count += 1; - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, 0); - assert_eq!(vec.len(), initial_len); - assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - } - - #[test] - fn drain_filter_true() { - let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - let initial_len = vec.len(); - let mut count = 0; - { - let mut iter = vec.extract_if(|_| true); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - while let Some(_) = iter.next() { - count += 1; - assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, initial_len); - assert_eq!(vec.len(), 0); - assert_eq!(vec, vec![]); - } - - #[test] - fn drain_filter_complex() { - { - // [+xxx++++++xxxxx++++x+x++] - let mut vec = vec![ - 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, - 37, 39, - ]; - - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(vec.len(), 14); - assert_eq!( - vec, - vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] - ); - } - - { - // [xxx++++++xxxxx++++x+x++] - let mut vec = vec![ - 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, - 39, - ]; - - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(vec.len(), 13); - assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); - } - - { - // [xxx++++++xxxxx++++x+x] - let mut vec = vec![ - 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, - ]; - - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(vec.len(), 11); - assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]); - } - - { - // [xxxxxxxxxx+++++++++++] - let mut vec = vec![ - 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, - ]; - - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); - - assert_eq!(vec.len(), 10); - assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); - } - - { - // [+++++++++++xxxxxxxxxx] - let mut vec = vec![ - 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, - ]; - - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); - - assert_eq!(vec.len(), 10); - assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); - } - } -} diff --git a/librashader-presets/src/lib.rs b/librashader-presets/src/lib.rs index 22548ac..4a9e347 100644 --- a/librashader-presets/src/lib.rs +++ b/librashader-presets/src/lib.rs @@ -8,12 +8,8 @@ //! //! Re-exported as [`librashader::presets`](https://docs.rs/librashader/latest/librashader/presets/index.html). -#![allow(stable_features)] -#![allow(unstable_name_collisions)] - pub mod context; mod error; -mod extract_if; mod parse; mod preset; diff --git a/librashader-presets/src/parse/preset.rs b/librashader-presets/src/parse/preset.rs index 58efa21..1bf47c0 100644 --- a/librashader-presets/src/parse/preset.rs +++ b/librashader-presets/src/parse/preset.rs @@ -1,42 +1,42 @@ -use crate::extract_if::MakeExtractIf; use crate::parse::remove_if; use crate::parse::value::Value; use crate::{ParameterConfig, Scale2D, Scaling, ShaderPassConfig, ShaderPreset, TextureConfig}; +use vec_extract_if_polyfill::MakeExtractIf; pub fn resolve_values(mut values: Vec) -> ShaderPreset { - let textures: Vec = values - .extract_if(|f| matches!(*f, Value::Texture { .. })) - .map(|value| { - if let Value::Texture { - name, - filter_mode, - wrap_mode, - mipmap, - path, - } = value - { - TextureConfig { + let textures: Vec = + MakeExtractIf::extract_if(&mut values, |f| matches!(*f, Value::Texture { .. })) + .map(|value| { + if let Value::Texture { name, - path, - wrap_mode, filter_mode, + wrap_mode, mipmap, + path, + } = value + { + TextureConfig { + name, + path, + wrap_mode, + filter_mode, + mipmap, + } + } else { + unreachable!("values should all be of type Texture") } - } else { - unreachable!("values should all be of type Texture") - } - }) - .collect(); - let parameters: Vec = values - .extract_if(|f| matches!(*f, Value::Parameter { .. })) - .map(|value| { - if let Value::Parameter(name, value) = value { - ParameterConfig { name, value } - } else { - unreachable!("values should be all of type parameters") - } - }) - .collect(); + }) + .collect(); + let parameters: Vec = + MakeExtractIf::extract_if(&mut values, |f| matches!(*f, Value::Parameter { .. })) + .map(|value| { + if let Value::Parameter(name, value) = value { + ParameterConfig { name, value } + } else { + unreachable!("values should be all of type parameters") + } + }) + .collect(); let mut shaders = Vec::new(); let shader_count = @@ -64,9 +64,9 @@ pub fn resolve_values(mut values: Vec) -> ShaderPreset { &mut values, |v| matches!(*v, Value::Shader(shader_index, _) if shader_index == shader), ) { - let shader_values: Vec = values - .extract_if(|v| v.shader_index() == Some(shader)) - .collect(); + let shader_values: Vec = + MakeExtractIf::extract_if(&mut values, |v| v.shader_index() == Some(shader)) + .collect(); let scale_type = shader_values.iter().find_map(|f| match f { Value::ScaleType(_, value) => Some(*value), _ => None, diff --git a/librashader-presets/src/parse/value.rs b/librashader-presets/src/parse/value.rs index bc59310..4654b74 100644 --- a/librashader-presets/src/parse/value.rs +++ b/librashader-presets/src/parse/value.rs @@ -18,7 +18,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use crate::context::{apply_context, WildcardContext}; -use crate::extract_if::MakeExtractIf; +use vec_extract_if_polyfill::MakeExtractIf; #[derive(Debug)] pub enum Value { @@ -195,8 +195,10 @@ fn load_child_reference_strings( .map_err(|e| ParsePresetError::IOError(path.clone(), e))?; let mut new_tokens = do_lex(&reference_contents)?; - let new_references: Vec = new_tokens - .extract_if(|token| *token.key.fragment() == "#reference") + let new_references: Vec = + MakeExtractIf::extract_if(&mut new_tokens, |token| { + *token.key.fragment() == "#reference" + }) .map(|value| PathBuf::from(*value.value.fragment())) .collect(); @@ -250,10 +252,10 @@ pub fn parse_values( root_path.pop(); } - let references: Vec = tokens - .extract_if(|token| *token.key.fragment() == "#reference") - .map(|value| PathBuf::from(*value.value.fragment())) - .collect(); + let references: Vec = + MakeExtractIf::extract_if(&mut tokens, |token| *token.key.fragment() == "#reference") + .map(|value| PathBuf::from(*value.value.fragment())) + .collect(); // unfortunately we need to lex twice because there's no way to know the references ahead of time. // the returned references should have context applied @@ -275,7 +277,9 @@ pub fn parse_values( // collect all possible parameter names. let mut parameter_names: Vec<&str> = Vec::new(); for (_, tokens) in all_tokens.iter_mut() { - for token in tokens.extract_if(|token| *token.key.fragment() == "parameters") { + for token in + MakeExtractIf::extract_if(tokens, |token| *token.key.fragment() == "parameters") + { let parameter_name_string: &str = token.value.fragment(); for parameter_name in parameter_name_string.split(';') { parameter_names.push(parameter_name); @@ -286,7 +290,8 @@ pub fn parse_values( // collect all possible texture names. let mut texture_names: Vec<&str> = Vec::new(); for (_, tokens) in all_tokens.iter_mut() { - for token in tokens.extract_if(|token| *token.key.fragment() == "textures") { + for token in MakeExtractIf::extract_if(tokens, |token| *token.key.fragment() == "textures") + { let texture_name_string: &str = token.value.fragment(); for texture_name in texture_name_string.split(';') { texture_names.push(texture_name); @@ -297,7 +302,9 @@ pub fn parse_values( let mut values = Vec::new(); // resolve shader paths. for (path, tokens) in all_tokens.iter_mut() { - for token in tokens.extract_if(|token| parse_indexed_key("shader", token.key).is_ok()) { + for token in MakeExtractIf::extract_if(tokens, |token| { + parse_indexed_key("shader", token.key).is_ok() + }) { let (_, index) = parse_indexed_key("shader", token.key).map_err(|e| match e { nom::Err::Error(e) | nom::Err::Failure(e) => { let input: Span = e.input; @@ -328,7 +335,9 @@ pub fn parse_values( // resolve texture paths let mut textures = Vec::new(); for (path, tokens) in all_tokens.iter_mut() { - for token in tokens.extract_if(|token| texture_names.contains(token.key.fragment())) { + for token in + MakeExtractIf::extract_if(tokens, |token| texture_names.contains(token.key.fragment())) + { let mut relative_path = path.to_path_buf(); relative_path.push(*token.value.fragment()); relative_path diff --git a/librashader-reflect/src/front/mod.rs b/librashader-reflect/src/front/mod.rs index 56c0884..a1a122b 100644 --- a/librashader-reflect/src/front/mod.rs +++ b/librashader-reflect/src/front/mod.rs @@ -32,7 +32,6 @@ pub struct SpirvCompilation { pub(crate) fragment: Vec, } - impl TryFrom<&ShaderSource> for SpirvCompilation { type Error = ShaderCompileError;