feat: add search

This commit is contained in:
2021-06-01 00:19:32 +08:00
parent c7bd4a5b61
commit 2d6c0a6291
5 changed files with 76 additions and 7 deletions

8
Cargo.lock generated
View File

@@ -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",

View File

@@ -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"

View File

@@ -9,6 +9,7 @@ pub struct ParsedArgs {
pub in_file: String,
pub format: PlistFormat,
pub out_file: Option<String>,
pub search: Option<String>,
}
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()

55
src/find.rs Normal file
View File

@@ -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<String>, 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(":")
}

View File

@@ -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() {