mirror of
https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation.git
synced 2026-08-28 02:10:39 +02:00
refactor(adb): rm regex dependency from PackageId::new by adding some utils.
and: - refactor `adb` `version` assertions to call `next` explicitly, rather than matching on iteration count. - re-add debug-assertions for `pm list packages`
This commit is contained in:
parent
b34492e98c
commit
5633b077c2
2 changed files with 72 additions and 30 deletions
|
|
@ -38,13 +38,14 @@
|
|||
//! For comprehensive info about ADB,
|
||||
//! [see this](https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/master/docs/)
|
||||
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
||||
use crate::core::utils::is_all_w_c;
|
||||
|
||||
pub fn to_trimmed_utf8(v: Vec<u8>) -> String {
|
||||
String::from_utf8(v)
|
||||
.expect("ADB should always output valid ASCII (or UTF-8, at least)")
|
||||
|
|
@ -133,33 +134,32 @@ impl ACommand {
|
|||
/// ```
|
||||
#[expect(clippy::panic_in_result_fn, reason = "Assertions are fine")]
|
||||
pub fn version(mut self) -> Result<String, String> {
|
||||
#[cfg(debug_assertions)]
|
||||
static TRIPLE: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"^Android Debug Bridge version \d+.\d+.\d+$")
|
||||
.unwrap_or_else(|_| unreachable!())
|
||||
});
|
||||
#[cfg(debug_assertions)]
|
||||
static DISTRO: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"^Version \d+.\d+.\d+-\S+$").unwrap_or_else(|_| unreachable!())
|
||||
});
|
||||
|
||||
self.0.arg("version");
|
||||
|
||||
let out = self.run()?;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
for (i, ln) in out.lines().enumerate() {
|
||||
assert!(match i {
|
||||
0 => TRIPLE.is_match(ln),
|
||||
1 => DISTRO.is_match(ln),
|
||||
2 =>
|
||||
// missing test for valid path
|
||||
ln.starts_with("Installed as ")
|
||||
&& (ln.ends_with("adb") || ln.ends_with("adb.exe")),
|
||||
// missing test for x86/ARM (both 64b)
|
||||
3 => ln.starts_with("Running on "),
|
||||
_ => unreachable!("Expected < 5 lines"),
|
||||
{
|
||||
use regex::Regex;
|
||||
|
||||
static TRIPLE: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"^Android Debug Bridge version \d+.\d+.\d+$")
|
||||
.unwrap_or_else(|_| unreachable!())
|
||||
});
|
||||
static DISTRO: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"^Version \d+.\d+.\d+-\S+$").unwrap_or_else(|_| unreachable!())
|
||||
});
|
||||
|
||||
let mut lns = out.lines();
|
||||
assert!(lns.next().is_some_and(|ln| TRIPLE.is_match(ln)));
|
||||
assert!(lns.next().is_some_and(|ln| DISTRO.is_match(ln)));
|
||||
// missing test for valid path
|
||||
assert!(lns.next().is_some_and(|ln| ln.starts_with("Installed as ")
|
||||
&& (ln.ends_with("adb") || ln.ends_with("adb.exe"))));
|
||||
// missing test for x86/ARM (both 64b)
|
||||
assert!(lns.next().is_some_and(|ln| ln.starts_with("Running on ")));
|
||||
if lns.next().is_some() {
|
||||
unreachable!("Expected < 5 lines")
|
||||
}
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
|
|
@ -230,6 +230,19 @@ impl ShellCommand {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn is_pkg_component(s: &[u8]) -> bool {
|
||||
if s.is_empty() {
|
||||
return false;
|
||||
}
|
||||
s[0].is_ascii_alphabetic()
|
||||
&& if s.len() > 1 {
|
||||
is_all_w_c(s.split_at(1).1)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// String with the invariant of being a valid package-name.
|
||||
/// See its `new` constructor for more info.
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
|
||||
|
|
@ -238,12 +251,16 @@ impl PackageId {
|
|||
/// Creates a package-ID if it's valid according to
|
||||
/// [this](https://developer.android.com/build/configure-app-module#set-application-id)
|
||||
pub fn new(p_id: Box<str>) -> Option<Self> {
|
||||
static RE: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"^[a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)+$")
|
||||
.unwrap_or_else(|_| unreachable!())
|
||||
});
|
||||
|
||||
if RE.is_match(p_id.as_ref()) {
|
||||
let mut components = p_id.split('.');
|
||||
for _ in 0..2 {
|
||||
if !components
|
||||
.next()
|
||||
.is_some_and(|comp| is_pkg_component(comp.as_bytes()))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if components.all(|comp| is_pkg_component(comp.as_bytes())) {
|
||||
Some(Self(p_id))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -316,7 +333,10 @@ impl PmCommand {
|
|||
.lines()
|
||||
.map(|p_ln| {
|
||||
debug_assert!(p_ln.starts_with(PACK_PREFIX));
|
||||
String::from(&p_ln[PACK_PREFIX.len()..])
|
||||
let p = &p_ln[PACK_PREFIX.len()..];
|
||||
#[cfg(debug_assertions)]
|
||||
assert!(PackageId::new(p.into()).is_some() || p == "android");
|
||||
String::from(p)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -19,6 +19,28 @@ use std::{
|
|||
pub const NAME: &str = "UAD-ng";
|
||||
pub const EXPORT_FILE_NAME: &str = "selection_export.txt";
|
||||
|
||||
/// Returns `true` if `c` matches the regex `\w`
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn is_w(c: u8) -> bool {
|
||||
// https://github.com/rust-lang/rust/issues/93279
|
||||
// https://github.com/rust-lang/rust/issues/83623
|
||||
(c == b'_') | c.is_ascii_alphanumeric()
|
||||
}
|
||||
|
||||
/// Returns `true` if `s` matches the regex `^\w+$`
|
||||
#[must_use]
|
||||
pub const fn is_all_w_c(s: &[u8]) -> bool {
|
||||
let mut i = 0;
|
||||
while i < s.len() {
|
||||
if !is_w(s[i]) {
|
||||
return false;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
// Takes a time-stamp parameter,
|
||||
// for purity and testability.
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue