From 2d6c0a6291bc37d8ee655c3c37be105bb9ee64bc Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Tue, 1 Jun 2021 00:19:32 +0800 Subject: [PATCH] feat: add search --- Cargo.lock | 8 ++++---- Cargo.toml | 6 +++--- src/args.rs | 3 +++ src/find.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 11 +++++++++++ 5 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 src/find.rs diff --git a/Cargo.lock b/Cargo.lock index 3273d6d..58bab78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,9 +134,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.94" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" +checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" [[package]] name = "line-wrap" @@ -210,9 +210,9 @@ dependencies = [ [[package]] name = "rust_util" -version = "0.6.33" +version = "0.6.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f06fc6f605c69092884583efb526f0db6d8e81a9fa8f0ec574a5560c02fd8a07" +checksum = "21b1ebfe593930e71805e37c914bf2dc48c2194b9dff7f0f1af8c59f92c5cff5" dependencies = [ "lazy_static", "libc", diff --git a/Cargo.toml b/Cargo.toml index 62d9ace..574c219 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -plist = "1.1.0" -clap = "2.33.3" -rust_util = "0.6.33" +plist = "1.1" +clap = "2.33" +rust_util = "0.6" diff --git a/src/args.rs b/src/args.rs index 236464a..816def7 100644 --- a/src/args.rs +++ b/src/args.rs @@ -9,6 +9,7 @@ pub struct ParsedArgs { pub in_file: String, pub format: PlistFormat, pub out_file: Option, + pub search: Option, } pub fn parse_args(matches: ArgMatches<'static>) -> ParsedArgs { @@ -20,6 +21,7 @@ pub fn parse_args(matches: ArgMatches<'static>) -> ParsedArgs { _ => failure_and_exit!("Plist format error."), }, out_file: matches.value_of("out").map(ToString::to_string), + search: matches.value_of("search").map(ToString::to_string), } } @@ -33,6 +35,7 @@ pub fn get_args_matches() -> ArgMatches<'static> { .possible_values(&["xml", "binary", "bin"]) .help("Output plist format") ) + .arg(Arg::with_name("search").long("search").takes_value(true).help("Search plist value")) .arg(Arg::with_name("out").short("o").long("out").takes_value(true).help("Output plist file")) .arg(Arg::with_name("FILE").required(true).index(1).help("Input plist file name")) .get_matches() diff --git a/src/find.rs b/src/find.rs new file mode 100644 index 0000000..ef023fa --- /dev/null +++ b/src/find.rs @@ -0,0 +1,55 @@ +use plist::Value; +use rust_util::util_msg::MessageType; + +pub fn find(value: &Value, find_val: &str) -> Vec<(String, String)> { + let mut path = vec![]; + find_value(value, &mut path, find_val) +} + +fn find_value(value: &Value, path: &mut Vec, find_val: &str) -> Vec<(String, String)> { + rust_util::util_msg::when(MessageType::DEBUG, || { + debugging!("Matching key: {}, value: {:?}", make_path(path), value.clone().into_string()); + }); + let mut ret = vec![]; + match value { + Value::String(str) => if str.contains(find_val) { + ret.push((make_path(path), str.to_string())); + } + Value::Array(arr) => { + for (i, val) in arr.iter().enumerate() { + path.push(i.to_string()); + ret.extend_from_slice(&find_value(val, path, find_val)); + path.pop(); + } + } + Value::Boolean(b) => if b.to_string().eq_ignore_ascii_case(find_val) { + ret.push((make_path(path), b.to_string())); + } + Value::Data(_data) => { + warning!("Ignored key: {}", make_path(path)); + } + Value::Date(_date) => { /* IGNORE */ } + Value::Dictionary(dict) => { + for (k, v) in dict { + path.push(k.to_string()); + ret.extend_from_slice(&find_value(v, path, find_val)); + path.pop(); + } + } + Value::Integer(int) => if int.to_string().contains(find_val) { + ret.push((make_path(path), int.to_string())); + } + Value::Real(f) => if f.to_string().contains(find_val) { + ret.push((make_path(path), f.to_string())); + } + Value::Uid(uid) => if uid.get().to_string().contains(find_val) { + ret.push((make_path(path), uid.get().to_string())); + } + Value::__Nonexhaustive => { /* IGNORE */ } + } + ret +} + +fn make_path(path: &[String]) -> String { + ":".to_owned() + &path.join(":") +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 2c880dc..35f30a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate rust_util; mod utils; mod args; +mod find; use std::fs::File; use plist::Value; @@ -17,6 +18,16 @@ fn main() { let plist_value = Value::from_file(&parsed_args.in_file).unwrap_or_else(|e| { failure_and_exit!("Read plist file: {}, failed: {}", parsed_args.in_file, e); }); + + if let Some(search) = parsed_args.search { + let matched = find::find(&plist_value, &search); + for (k, v) in &matched { + information!("Matched: {} -> {}", k, v); + } + success!("Found {} values(s)", matched.len()); + return; + } + // write plist to file or stdout if let Some(out_file) = parsed_args.out_file { if File::open(&out_file).is_ok() {