use crate::imp::history::file_name::file_name_props::FileNameProps;
use std::str::FromStr;
pub(crate) fn analyze_file_name(s : &str, hint_max_phase : Option<usize>) -> Option<FileNameProps>{
if s.ends_with(".his") == false{
return None;
}
let tag = get_tag(s);
let s = if let Some(tag) = tag{
&s[(tag.len() + 2)..]
} else{
s
};
let prev_ctl = get_prev_ctl(s);
let mut s = if let Some(prev_ctl) = prev_ctl{
&s[(prev_ctl.len() + 2)..]
} else{
s
};
let n = if let Some((num, read)) = get_num(s.as_bytes()){
s = &s[read..];
num
} else{
return None;
};
let prev_ctl = prev_ctl.and_then(|s| u32::from_str(s).ok()).unwrap_or(n);
let capacity = hint_max_phase.unwrap_or(0) + 1;
let mut order : Vec<u32> = Vec::with_capacity(capacity);
loop{
if let Some((num, read)) = get_num(s.as_bytes()){
order.push(num);
s = &s[read..];
} else{
if s == ".his" && order.len() != 0{
if let Ok(props) = FileNameProps::new(n, prev_ctl,
order, tag.map(|t| t.to_string())){
return Some(props);
}
}
return None;
}
}
}
fn get_tag(s : &str) -> Option<&str>{
let bytes = s.as_bytes();
if bytes.len() <= 1{ return None; }
let first = bytes[0];
if first != '#' as u8{
return None;
}
for (i,c) in bytes.iter().skip(1).enumerate(){
if *c == '#' as u8{
return Some(&s[1..i])
}
}
return None;
}
fn get_prev_ctl(s : &str) -> Option<&str>{
let bytes = s.as_bytes();
if bytes.len() <= 1{ return None; }
let first = bytes[0];
if first != '(' as u8{
return None;
}
for (i,c) in bytes.iter().skip(1).enumerate(){
if *c == ')' as u8{
return Some(&s[1..i+1])
}
}
return None;
}
fn get_num(s : &[u8]) -> Option<(u32, usize)>{
if s.len() == 0 { return None; }
if s[0] != '_' as u8{ return None; }
let mut i = 1;
let mut result : u32 = 0;
loop{
if s.len() <= i{ return None; }
let b = s[i];
if '0' as u8 <= b && b <= '9' as u8{
result *= 10;
result += (b - '0' as u8) as u32;
} else{
return Some((result, i));
}
i += 1;
if i == 10{ return None; } }
}