rpfm_extensions/search/
unknown.rs1use getset::{Getters, MutGetters, Setters};
12use regex::bytes::RegexBuilder;
13use serde_derive::{Deserialize, Serialize};
14
15use rpfm_lib::files::unknown::Unknown;
16
17use super::{find_in_bytes, MatchingMode, Replaceable, SearchSource, Searchable, replace_match_bytes};
18
19#[derive(Debug, Clone, Getters, MutGetters, Setters, Serialize, Deserialize)]
25#[getset(get = "pub", get_mut = "pub", set = "pub")]
26pub struct UnknownMatches {
27
28 path: String,
30
31 #[serde(default)]
33 source: SearchSource,
34
35 #[serde(default)]
37 container_name: String,
38
39 matches: Vec<UnknownMatch>,
41}
42
43#[derive(Debug, Clone, Eq, PartialEq, Getters, MutGetters, Serialize, Deserialize)]
45#[getset(get = "pub", get_mut = "pub")]
46pub struct UnknownMatch {
47
48 pos: usize,
50
51 len: usize,
53}
54
55impl Searchable for Unknown {
60 type SearchMatches = UnknownMatches;
61
62 fn search(&self, file_path: &str, pattern: &str, case_sensitive: bool, matching_mode: &MatchingMode) -> UnknownMatches {
63 let mut matches = UnknownMatches::new(file_path);
64
65 match matching_mode {
66 MatchingMode::Regex(regex) => {
67
68 let regex = RegexBuilder::new(regex.as_str()).case_insensitive(!case_sensitive).build().unwrap();
70 for match_data in regex.find_iter(self.data()) {
71 matches.matches.push(
72 UnknownMatch::new(
73 match_data.start(),
74 match_data.end() - match_data.start(),
75 )
76 );
77 }
78 }
79
80 MatchingMode::Pattern(regex) => {
81 let regex = regex.as_ref().map(|regex| RegexBuilder::new(regex.as_str()).case_insensitive(!case_sensitive).build().unwrap());
82
83 if self.data().len() > pattern.len() {
84 for (start, length) in &find_in_bytes(self.data(), pattern, case_sensitive, ®ex) {
85 matches.matches.push(UnknownMatch::new(*start, *length));
86 }
87 }
88 }
89 }
90
91 matches
92 }
93}
94
95impl Replaceable for Unknown {
96
97 fn replace(&mut self, _pattern: &str, replace_pattern: &str, _case_sensitive: bool, _matching_mode: &MatchingMode, search_matches: &UnknownMatches) -> bool {
98 let mut edited = false;
99
100 for search_match in search_matches.matches().iter().rev() {
103 edited |= search_match.replace(replace_pattern, self.data_mut());
104 }
105
106 edited
107 }
108}
109
110impl UnknownMatches {
111
112 pub fn new(path: &str) -> Self {
114 Self {
115 path: path.to_owned(),
116 matches: vec![],
117 source: SearchSource::default(),
118 container_name: String::new(),
119 }
120 }
121}
122
123impl UnknownMatch {
124
125 pub fn new(pos: usize, len: usize) -> Self {
127 Self {
128 pos,
129 len,
130 }
131 }
132
133 fn replace(&self, replace_pattern: &str, data: &mut Vec<u8>) -> bool {
135 replace_match_bytes(replace_pattern, self.pos, self.len, data)
136 }
137}