mirror of
https://codeberg.org/Toasterson/ips.git
synced 2026-04-10 21:30:41 +00:00
Add default derive
Add Fast path parsing which catches the case of unescaped values with spaces.
This commit is contained in:
parent
f33df3d0ab
commit
441a47d384
2 changed files with 77 additions and 5 deletions
|
|
@ -3,7 +3,7 @@
|
|||
// MPL was not distributed with this file, You can
|
||||
// obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
use regex::Regex;
|
||||
use regex::{Regex, Captures};
|
||||
use std::collections::HashSet;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
|
|
@ -11,6 +11,7 @@ use std::fs::File;
|
|||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Dir {
|
||||
pub path: String,
|
||||
pub group: String,
|
||||
|
|
@ -18,6 +19,7 @@ pub struct Dir {
|
|||
pub mode: String, //TODO implement as bitmask
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Attr {
|
||||
pub key: String,
|
||||
pub values: Vec<String>,
|
||||
|
|
@ -30,6 +32,7 @@ pub struct Property {
|
|||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Manifest {
|
||||
pub attributes: Vec<Attr>,
|
||||
}
|
||||
|
|
@ -130,6 +133,49 @@ fn is_attr_action(line: &String) -> bool {
|
|||
}
|
||||
|
||||
pub fn parse_attr_action(line: String) -> Result<Attr, ManifestError> {
|
||||
// Do a full line match to see if we can fast path this.
|
||||
// This also catches values with spaces, that have not been properly escaped.
|
||||
// Note: values with spaces must be properly escaped or the rest here will fail. Strings with
|
||||
// unescaped spaces are never valid but sadly present in the wild.
|
||||
// Fast path will fail if a value has multiple values or a '=' sign in the values
|
||||
let full_line_regex = match Regex::new(r"^set name=([^ ]+) value=(.+)$") {
|
||||
Ok(re) => re,
|
||||
Err(e) => return Err(ManifestError::Regex(e)),
|
||||
};
|
||||
|
||||
if full_line_regex.is_match(line.trim_start()) {
|
||||
match full_line_regex.captures(line.trim_start()) {
|
||||
Some(captures) => {
|
||||
let mut fast_path_fail = false;
|
||||
let mut val = String::from(&captures[2]);
|
||||
|
||||
if val.contains("=") {
|
||||
fast_path_fail = true;
|
||||
}
|
||||
|
||||
if val.contains("value=") {
|
||||
fast_path_fail = true;
|
||||
}
|
||||
|
||||
if val.contains("name=") {
|
||||
fast_path_fail = true;
|
||||
}
|
||||
|
||||
val = val.replace(&['"', '\\'][..], "");
|
||||
|
||||
if !fast_path_fail{
|
||||
return Ok(Attr{
|
||||
key: String::from(&captures[1]),
|
||||
values: vec![val],
|
||||
..Attr::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//Todo move regex initialisation out of for loop into static area
|
||||
let name_regex = match Regex::new(r"name=([^ ]+) value=") {
|
||||
Ok(re) => re,
|
||||
|
|
|
|||
34
src/lib.rs
34
src/lib.rs
|
|
@ -8,7 +8,7 @@ mod actions;
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use crate::actions::Manifest;
|
||||
use crate::actions::{Manifest, Property};
|
||||
use crate::actions::{parse_manifest_string, Attr};
|
||||
use std::collections::HashSet;
|
||||
|
||||
|
|
@ -25,7 +25,15 @@ mod tests {
|
|||
set name=info.source-url value=http://nginx.org/download/nginx-1.18.0.tar.gz
|
||||
set name=org.opensolaris.consolidation value=userland
|
||||
set name=com.oracle.info.version value=1.18.0
|
||||
set name=variant.arch value=i386");
|
||||
set name=pkg.summary value=\\\"provided mouse accessibility enhancements\\\"
|
||||
set name=info.upstream value=X.Org Foundation
|
||||
set name=pkg.description value=Latvian language support's extra files
|
||||
set name=variant.arch value=i386 optional=testing optionalWithString=\"test ing\"");
|
||||
|
||||
let mut optional_hash = HashSet::new();
|
||||
optional_hash.insert(Property{key: String::from("optional"), value:String::from("testing")});
|
||||
optional_hash.insert(Property{key: String::from("optionalWithString"), value:String::from("test ing")});
|
||||
|
||||
let test_results = vec![
|
||||
Attr{
|
||||
key: String::from("pkg.fmri"),
|
||||
|
|
@ -82,10 +90,25 @@ mod tests {
|
|||
values: vec![String::from("1.18.0")],
|
||||
properties: HashSet::new(),
|
||||
},
|
||||
Attr{
|
||||
key: String::from("pkg.summary"),
|
||||
values: vec![String::from("provided mouse accessibility enhancements")],
|
||||
properties: HashSet::new(),
|
||||
},
|
||||
Attr{
|
||||
key: String::from("info.upstream"),
|
||||
values: vec![String::from("X.Org Foundation")],
|
||||
properties: HashSet::new(),
|
||||
},
|
||||
Attr{
|
||||
key: String::from("pkg.description"),
|
||||
values: vec![String::from("Latvian language support's extra files")],
|
||||
properties: HashSet::new(),
|
||||
},
|
||||
Attr{
|
||||
key: String::from("variant.arch"),
|
||||
values: vec![String::from("i386")],
|
||||
properties: HashSet::new(),
|
||||
properties: optional_hash,
|
||||
}
|
||||
];
|
||||
|
||||
|
|
@ -94,9 +117,12 @@ mod tests {
|
|||
Ok(m) => manifest = m,
|
||||
Err(_) => assert!(false, "caught error"),
|
||||
};
|
||||
assert_eq!(manifest.attributes.len(), 12);
|
||||
|
||||
assert_eq!(manifest.attributes.len(), 15);
|
||||
|
||||
for (pos, attr) in manifest.attributes.iter().enumerate() {
|
||||
assert_eq!(attr.key, test_results[pos].key);
|
||||
|
||||
for (vpos, val) in attr.values.iter().enumerate() {
|
||||
assert_eq!(val, &test_results[pos].values[vpos]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue