Skip to main content

yoctui_utils/
validation.rs

1use std::path::{Component, Path};
2
3/// Validate a non-root absolute path whose components never traverse upward or
4/// redundantly refer to the current directory.
5pub fn is_absolute_normal_path(path: &Path) -> bool {
6    path.is_absolute()
7        && path.parent().is_some()
8        && path
9            .components()
10            .all(|component| !matches!(component, Component::ParentDir | Component::CurDir))
11}
12
13pub fn is_absolute_normal_path_within(path: &Path, maximum_bytes: usize) -> bool {
14    path.as_os_str().as_encoded_bytes().len() <= maximum_bytes && is_absolute_normal_path(path)
15}
16
17pub fn is_bounded_plain_text(value: &str, maximum_bytes: usize) -> bool {
18    !value.is_empty() && value.len() <= maximum_bytes && !value.chars().any(char::is_control)
19}
20
21/// Validate the shared BitBake identifier alphabet used by recipe, machine,
22/// distro, image and test selector identities.
23pub fn is_bounded_identifier(value: &str, maximum_bytes: usize) -> bool {
24    !matches!(value, "" | "." | "..")
25        && value.len() <= maximum_bytes
26        && value
27            .bytes()
28            .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.' | b'+'))
29}
30
31pub fn push_unique_bounded<T: PartialEq>(values: &mut Vec<T>, value: T, maximum: usize) -> bool {
32    if values.len() >= maximum || values.contains(&value) {
33        return false;
34    }
35    values.push(value);
36    true
37}
38
39#[cfg(test)]
40#[path = "tests/validation/mod.rs"]
41mod tests;