|
@@ -8,7 +8,7 @@ use alloc::{
|
|
|
string::{String, ToString},
|
|
|
vec::Vec,
|
|
|
};
|
|
|
-use core::{fmt, str};
|
|
|
+use core::{fmt, ops::Add, str};
|
|
|
|
|
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
|
|
pub struct AmlName(pub(crate) Vec<NameComponent>);
|
|
@@ -68,6 +68,57 @@ impl AmlName {
|
|
|
pub fn is_absolute(&self) -> bool {
|
|
|
self.0.first() == Some(&NameComponent::Root)
|
|
|
}
|
|
|
+
|
|
|
+ /// Returns `true` if this path is at the root of the namespace (`\`).
|
|
|
+ pub fn is_at_root(&self) -> bool {
|
|
|
+ self.0 == &[NameComponent::Root]
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Special rules apply when searching for certain paths (specifically, those that are made up
|
|
|
+ /// of a single name segment). Returns `true` if those rules apply.
|
|
|
+ pub fn search_rules_apply(&self) -> bool {
|
|
|
+ if self.0.len() != 1 {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ match self.0[0] {
|
|
|
+ NameComponent::Segment(_) => true,
|
|
|
+ _ => false,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Normalize an AML path, resolving prefix chars. Returns `None` if the path normalizes to an
|
|
|
+ /// invalid path (e.g. `\^_FOO`)
|
|
|
+ pub fn normalize(self) -> Option<AmlName> {
|
|
|
+ // TODO: currently, this doesn't do anything. Work out a nice way of handling prefix chars.
|
|
|
+ Some(self)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Get the parent of this `AmlName`. For example, the parent of `\_SB.PCI0._PRT` is `\_SB.PCI0`. The root
|
|
|
+ /// path has no parent, and so returns `None`.
|
|
|
+ pub fn parent(&self) -> Option<AmlName> {
|
|
|
+ // Firstly, normalize the path so we don't have to deal with prefix chars
|
|
|
+ let mut normalized_self = self.clone().normalize()?;
|
|
|
+
|
|
|
+ match normalized_self.0.last() {
|
|
|
+ None => None,
|
|
|
+ Some(NameComponent::Root) => None,
|
|
|
+ Some(NameComponent::Segment(_)) => {
|
|
|
+ normalized_self.0.pop();
|
|
|
+ Some(normalized_self)
|
|
|
+ }
|
|
|
+ Some(NameComponent::Prefix) => unreachable!(), // Prefix chars are removed by normalization
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Add for AmlName {
|
|
|
+ type Output = AmlName;
|
|
|
+
|
|
|
+ fn add(mut self, other: Self) -> Self {
|
|
|
+ self.0.extend_from_slice(&(other.0));
|
|
|
+ self
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
impl fmt::Display for AmlName {
|
|
@@ -323,4 +374,35 @@ mod tests {
|
|
|
]))
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_is_at_root() {
|
|
|
+ assert_eq!(AmlName::root().is_at_root(), true);
|
|
|
+ assert_eq!(AmlName::from_str("\\_SB").unwrap().is_at_root(), false);
|
|
|
+ assert_eq!(AmlName::from_str("\\_SB.PCI0.^VGA").unwrap().is_at_root(), false);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_search_rules_apply() {
|
|
|
+ assert_eq!(AmlName::root().search_rules_apply(), false);
|
|
|
+ assert_eq!(AmlName::from_str("\\_SB").unwrap().search_rules_apply(), false);
|
|
|
+ assert_eq!(AmlName::from_str("^VGA").unwrap().search_rules_apply(), false);
|
|
|
+ assert_eq!(AmlName::from_str("_SB.PCI0.VGA").unwrap().search_rules_apply(), false);
|
|
|
+ assert_eq!(AmlName::from_str("VGA").unwrap().search_rules_apply(), true);
|
|
|
+ assert_eq!(AmlName::from_str("_SB").unwrap().search_rules_apply(), true);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_aml_name_parent() {
|
|
|
+ assert_eq!(AmlName::from_str("\\").unwrap().parent(), None);
|
|
|
+ assert_eq!(AmlName::from_str("\\_SB").unwrap().parent(), Some(AmlName::root()));
|
|
|
+ assert_eq!(
|
|
|
+ AmlName::from_str("\\_SB.PCI0").unwrap().parent(),
|
|
|
+ Some(AmlName::from_str("\\_SB").unwrap())
|
|
|
+ );
|
|
|
+ assert_eq!(
|
|
|
+ AmlName::from_str("\\_SB.PCI0").unwrap().parent().unwrap().parent(),
|
|
|
+ Some(AmlName::root())
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|