Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace get regex by a lazystatic #199

Merged
merged 3 commits into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ lto = true
clap = { version = "4.4.6", features = ["derive"] }
exr = "1.71.0"
jwalk = "0.8.1"
lazy_static = "1.4.0"
rayon = "1.8.0"

[dependencies.regex]
Expand Down
46 changes: 18 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ mod exr_metadata;
pub mod paths;
use crate::exr_metadata::read_meta;
use jwalk::WalkDir;
use lazy_static::lazy_static;
use paths::{Paths, PathsPacked};
use rayon::prelude::*;
use regex::{Captures, Regex};
Expand Down Expand Up @@ -73,26 +74,16 @@ pub fn recursive_dir(input_path: &str) -> Paths {
)
}

/// This function compile the main regular expression used to extract the
/// frames from the file name.
/// (?x) match the remainder of the pattern with the following effective flags:
/// gmx x modifier: extended. Spaces and text after a # in the pattern are ignored
/// The frames group should contain between **2** and **9** digit, the extension
/// group should contains only letters between 2 and 5 characters.
fn get_regex() -> Regex {
let re = Regex::new(r"(?x)(.*)(\.|_)(?P<frames>\d{2,9})\.(\w{2,5})$");
match re {
Ok(succes_value) => succes_value,
Err(err) => panic!("Can't compile regex with error {}", err),
}
}

/// This function extract the matching group based on regex already compile to
/// a tuple of string. For exemple toto.458.jpg should return
/// (toto.***.jpg, 458)
#[inline(always)]
fn extract_regex(re: &Regex, x: &str) -> (String, String) {
let result_caps: Option<Captures> = re.captures(&x);
fn extract_regex(x: &str) -> (String, String) {
lazy_static! {
static ref RE_FLS: Regex = Regex::new(r"(?x)(.*)(\.|_)(?P<frames>\d{2,9})\.(\w{2,5})$")
.expect("Can't compile regex");
}
let result_caps: Option<Captures> = RE_FLS.captures(&x);
match result_caps {
None => (x.to_string(), "None".to_string()),
caps_wrap => {
Expand All @@ -108,20 +99,19 @@ fn extract_regex(re: &Regex, x: &str) -> (String, String) {
/// Parse the result of a vector of string. This function use HashMap to pack
/// filename removed from the frame value.
fn parse_result(dir_scan: Paths) -> HashMap<String, Vec<String>> {
let re = get_regex();
// Optimisation over PAR_THRESHOLD value, the parsing of the frame list
// used rayon lib to paralelize the work. Result depends a lot from the
// cpu number of thread may be put in a config file
const PAR_THRESHOLD: usize = 100000;
let extracted: Vec<(String, String)> = if dir_scan.len() < PAR_THRESHOLD {
dir_scan
.iter()
.map(|path| extract_regex(&re, path.to_str().unwrap()))
.map(|path| extract_regex(path.to_str().unwrap()))
.collect()
} else {
dir_scan
.par_iter()
.map(|path| extract_regex(&re, path.to_str().unwrap()))
.map(|path| extract_regex(path.to_str().unwrap()))
.collect()
};
let mut paths_dict: HashMap<String, Vec<String>> = HashMap::with_capacity(extracted.len());
Expand Down Expand Up @@ -218,8 +208,11 @@ pub fn basic_listing(frames: Paths) -> PathsPacked {

/// This function is intented to check if a file is an exr to call exr module
/// and print the exr metadata of the file
fn get_exr_metada(re: &Regex, root_path: &String, path: &String) -> String {
if re.is_match(&path) {
fn get_exr_metada(root_path: &String, path: &String) -> String {
lazy_static! {
static ref RE_EXR: Regex = Regex::new(r".*.exr$").expect("Can't compile regex");
}
if RE_EXR.is_match(&path) {
let path = format!("{}{}", root_path, path);
read_meta(path)
} else {
Expand Down Expand Up @@ -247,18 +240,17 @@ fn get_exr_metada(re: &Regex, root_path: &String, path: &String) -> String {
/// ./samples/small/foo.exr Not an exr
/// ```
pub fn extended_listing(root_path: String, frames: Paths) -> PathsPacked {
let re: Regex = Regex::new(r".*.exr$").unwrap();
let frames_dict: HashMap<String, Vec<String>> = parse_result(frames);
let mut out_frames: PathsPacked = PathsPacked::new_empty();
for (key, value) in frames_dict {
if value[0] == "None" && value.len() == 1 {
out_frames.push_metadata(get_exr_metada(&re, &root_path, &key));
out_frames.push_metadata(get_exr_metada(&root_path, &key));
out_frames.push_paths(key.into());
} else {
let to = value.first().unwrap();
let from = String::from_utf8(vec![b'*'; to.len()]).unwrap();
let new_path = &key.replace(&from, to);
out_frames.push_metadata(get_exr_metada(&re, &root_path, &new_path));
out_frames.push_metadata(get_exr_metada(&root_path, &new_path));
out_frames.push_paths(format!("{}@{}", key, create_frame_string(value)).into());
}
}
Expand All @@ -273,21 +265,19 @@ fn test_parse_dir() {
}
#[test]
fn test_handle_none() {
let re = get_regex();
let source: &str = "foobar.exr";
let expected: (String, String) = (source.to_string(), "None".to_string());
assert_eq!(expected, extract_regex(&re, source))
assert_eq!(expected, extract_regex(source))
}

#[test]
fn test_regex_simple() {
let re = get_regex();
let source: &str = "RenderPass_Beauty_1_00000.exr";
let expected: (String, String) = (
"RenderPass_Beauty_1_*****.exr".to_string(),
"00000".to_string(),
);
assert_eq!(expected, extract_regex(&re, source))
assert_eq!(expected, extract_regex(source))
}
#[test]
fn test_parse_string() {
Expand Down