Re-organize some systree-related code

This commit is contained in:
Chen Chengjun 2025-06-05 03:06:51 +00:00 committed by Tate, Hongliang Tian
parent a67bd8cdc9
commit c56aee92f4
9 changed files with 125 additions and 273 deletions

1
Cargo.lock generated
View File

@ -268,6 +268,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bitflags 2.9.0", "bitflags 2.9.0",
"component", "component",
"inherit-methods-macro",
"ostd", "ostd",
"spin", "spin",
] ]

View File

@ -9,6 +9,7 @@ edition = "2021"
bitflags = "2.5" bitflags = "2.5"
ostd = { path = "../../../ostd" } ostd = { path = "../../../ostd" }
component = { path = "../../libs/comp-sys/component" } component = { path = "../../libs/comp-sys/component" }
inherit-methods-macro = { git = "https://github.com/asterinas/inherit-methods-macro", rev = "98f7e3e"}
spin = "0.9" spin = "0.9"
[lints] [lints]

View File

@ -37,9 +37,6 @@ pub struct SysAttr {
name: SysStr, name: SysStr,
/// Flags defining the behavior and permissions of the attribute. /// Flags defining the behavior and permissions of the attribute.
flags: SysAttrFlags, flags: SysAttrFlags,
// Potentially add read/write handler functions or trait objects later
// read_handler: fn(...) -> Result<usize>,
// write_handler: fn(...) -> Result<usize>,
} }
impl SysAttr { impl SysAttr {

View File

@ -7,7 +7,7 @@ use core::{
sync::atomic::{AtomicU64, Ordering}, sync::atomic::{AtomicU64, Ordering},
}; };
use ostd::mm::{VmReader, VmWriter}; use ostd::mm::{FallibleVmWrite, VmReader, VmWriter};
use super::{Error, Result, SysAttrSet, SysStr}; use super::{Error, Result, SysAttrSet, SysStr};
@ -16,9 +16,9 @@ pub const MAX_ATTR_SIZE: usize = 4096;
/// The three types of nodes in a `SysTree`. /// The three types of nodes in a `SysTree`.
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SysNodeType { pub enum SysNodeType {
/// A branching node is one that may contain child nodes. /// A branching node is one that can have child nodes.
Branch, Branch,
/// A leaf node is one that may not contain child nodes. /// A leaf node is one that cannot have child nodes.
Leaf, Leaf,
/// A symlink node, /// A symlink node,
/// which ia a special kind of leaf node that points to another node, /// which ia a special kind of leaf node that points to another node,
@ -27,6 +27,7 @@ pub enum SysNodeType {
} }
/// A trait that represents a branching node in a `SysTree`. /// A trait that represents a branching node in a `SysTree`.
#[expect(clippy::type_complexity)]
pub trait SysBranchNode: SysNode { pub trait SysBranchNode: SysNode {
/// Visits a child node with the given name using a closure. /// Visits a child node with the given name using a closure.
/// ///
@ -49,7 +50,7 @@ pub trait SysBranchNode: SysNode {
/// So the caller should do as little as possible inside the closure. /// So the caller should do as little as possible inside the closure.
/// In particular, the caller should _not_ invoke other methods /// In particular, the caller should _not_ invoke other methods
/// on this object as this might cause deadlock. /// on this object as this might cause deadlock.
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&dyn SysNode>)); fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<dyn SysObj>>));
/// Visits child nodes with a minimum ID using a closure. /// Visits child nodes with a minimum ID using a closure.
/// ///
@ -75,7 +76,7 @@ pub trait SysBranchNode: SysNode {
fn visit_children_with( fn visit_children_with(
&self, &self,
min_id: u64, min_id: u64,
f: &mut dyn for<'a> FnMut(&'a Arc<(dyn SysObj + 'static)>) -> Option<()>, f: &mut dyn for<'a> FnMut(&'a Arc<(dyn SysObj)>) -> Option<()>,
); );
/// Returns a child with a specified name. /// Returns a child with a specified name.
@ -182,18 +183,18 @@ pub trait SysObj: Any + Send + Sync + Debug + 'static {
/// Returns a reference to this object as `Any` for downcasting. /// Returns a reference to this object as `Any` for downcasting.
fn as_any(&self) -> &dyn Any; fn as_any(&self) -> &dyn Any;
/// Attempts to get an Arc to this object as a `SysSymlink`. /// Casts this object to a trait object of `SysTree` symlink.
fn arc_as_symlink(&self) -> Option<Arc<dyn SysSymlink>> { fn cast_to_symlink(&self) -> Option<Arc<dyn SysSymlink>> {
None None
} }
/// Attempts to get an Arc to this object as a `SysNode`. /// Casts this object to a trait object of a `SysTree` node.
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> { fn cast_to_node(&self) -> Option<Arc<dyn SysNode>> {
None None
} }
/// Attempts to get an Arc to this object as a `SysBranchNode`. /// Casts this object to a trait object of a `SysTree` branch node.
fn arc_as_branch(&self) -> Option<Arc<dyn SysBranchNode>> { fn cast_to_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
None None
} }
@ -210,7 +211,7 @@ pub trait SysObj: Any + Send + Sync + Debug + 'static {
/// ///
/// The root node of a `SysTree` has an empty name. /// The root node of a `SysTree` has an empty name.
/// All other inodes must have an non-empty name. /// All other inodes must have an non-empty name.
fn name(&self) -> SysStr; fn name(&self) -> &SysStr;
/// Returns whether a node is the root of a `SysTree`. /// Returns whether a node is the root of a `SysTree`.
fn is_root(&self) -> bool { fn is_root(&self) -> bool {

View File

@ -6,22 +6,24 @@ use alloc::{
sync::{Arc, Weak}, sync::{Arc, Weak},
vec::Vec, vec::Vec,
}; };
use core::{any::Any, fmt::Debug}; use core::fmt::Debug;
use inherit_methods_macro::inherit_methods;
use ostd::{ use ostd::{
mm::{FallibleVmRead, FallibleVmWrite, VmReader, VmWriter}, mm::{FallibleVmRead, FallibleVmWrite, VmReader, VmWriter},
prelude::ktest, prelude::ktest,
}; };
use super::{ use super::{
Error, Result, SysAttrFlags, SysAttrSet, SysAttrSetBuilder, SysBranchNode, SysBranchNodeFields, impl_cast_methods_for_branch, impl_cast_methods_for_symlink, Error, Result, SysAttrFlags,
SysNode, SysNodeId, SysNodeType, SysObj, SysStr, SysSymlink, SysTree, SysAttrSet, SysAttrSetBuilder, SysBranchNode, SysBranchNodeFields, SysNode, SysNodeId,
SysNodeType, SysObj, SysStr, SysSymlink, SysTree,
}; };
#[derive(Debug)] #[derive(Debug)]
struct DeviceNode { struct DeviceNode {
fields: SysBranchNodeFields<dyn SysObj>, fields: SysBranchNodeFields<dyn SysObj>,
self_ref: Weak<Self>, weak_self: Weak<Self>,
} }
impl DeviceNode { impl DeviceNode {
@ -41,38 +43,20 @@ impl DeviceNode {
Arc::new_cyclic(|weak_self| DeviceNode { Arc::new_cyclic(|weak_self| DeviceNode {
fields, fields,
self_ref: weak_self.clone(), weak_self: weak_self.clone(),
}) })
} }
} }
impl SysObj for DeviceNode { impl SysObj for DeviceNode {
fn as_any(&self) -> &dyn Any { impl_cast_methods_for_branch!();
self
}
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> {
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysNode>)
}
fn arc_as_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysBranchNode>)
}
fn id(&self) -> &SysNodeId { fn id(&self) -> &SysNodeId {
self.fields.id() self.fields.id()
} }
fn type_(&self) -> SysNodeType { fn name(&self) -> &SysStr {
SysNodeType::Branch self.fields.name()
}
fn name(&self) -> SysStr {
self.fields.name().to_string().into()
} }
} }
@ -129,45 +113,13 @@ impl SysNode for DeviceNode {
} }
} }
#[inherit_methods(from = "self.fields")]
impl SysBranchNode for DeviceNode { impl SysBranchNode for DeviceNode {
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&dyn SysNode>)) { fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<dyn SysObj>>));
let children = self.fields.children.read();
children
.get(name)
.map(|child| {
child
.arc_as_node()
.map(|node| f(Some(node.as_ref())))
.unwrap_or_else(|| f(None))
})
.unwrap_or_else(|| f(None));
}
fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>) { fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>);
let children = self.fields.children.read();
for child in children
.values()
.filter(|child| child.id().as_u64() >= min_id)
{
if f(child).is_none() {
break;
}
}
}
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>> { fn child(&self, name: &str) -> Option<Arc<dyn SysObj>>;
let children = self.fields.children.read();
children.get(name).cloned()
}
fn children(&self) -> Vec<Arc<dyn SysObj>> {
let children = self.fields.children.read();
children.values().cloned().collect()
}
fn count_children(&self) -> usize {
self.fields.children.read().len()
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -175,7 +127,7 @@ struct SymlinkNode {
id: SysNodeId, id: SysNodeId,
name: SysStr, name: SysStr,
target: String, target: String,
self_ref: Weak<Self>, weak_self: Weak<Self>,
} }
impl SymlinkNode { impl SymlinkNode {
@ -184,32 +136,20 @@ impl SymlinkNode {
id: SysNodeId::new(), id: SysNodeId::new(),
name: name.to_string().into(), name: name.to_string().into(),
target: target.to_string(), target: target.to_string(),
self_ref: weak_self.clone(), weak_self: weak_self.clone(),
}) })
} }
} }
impl SysObj for SymlinkNode { impl SysObj for SymlinkNode {
fn as_any(&self) -> &dyn Any { impl_cast_methods_for_symlink!();
self
}
fn arc_as_symlink(&self) -> Option<Arc<dyn SysSymlink>> {
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysSymlink>)
}
fn id(&self) -> &SysNodeId { fn id(&self) -> &SysNodeId {
&self.id &self.id
} }
fn type_(&self) -> SysNodeType { fn name(&self) -> &SysStr {
SysNodeType::Symlink &self.name
}
fn name(&self) -> SysStr {
self.name.clone()
} }
} }
@ -230,7 +170,7 @@ fn systree_singleton() {
// Check if root node exists // Check if root node exists
assert!(root.is_root()); assert!(root.is_root());
assert_eq!(root.name(), ""); assert_eq!(root.name(), "");
assert_eq!(root.type_(), SysNodeType::Leaf); assert_eq!(root.type_(), SysNodeType::Branch);
} }
#[ktest] #[ktest]
@ -309,7 +249,7 @@ fn symlinks() {
// Verify symlink was added correctly // Verify symlink was added correctly
let symlink_obj = device.child("device_link").unwrap(); let symlink_obj = device.child("device_link").unwrap();
let symlink_node = symlink_obj.arc_as_symlink().unwrap(); let symlink_node = symlink_obj.cast_to_symlink().unwrap();
assert_eq!(symlink_node.target_path(), "/sys/devices/device"); assert_eq!(symlink_node.target_path(), "/sys/devices/device");
} }

View File

@ -4,22 +4,18 @@
use alloc::{ use alloc::{
borrow::Cow, borrow::Cow,
collections::BTreeMap,
sync::{Arc, Weak}, sync::{Arc, Weak},
vec::Vec,
}; };
use core::any::Any;
use ostd::{ use inherit_methods_macro::inherit_methods;
mm::{VmReader, VmWriter}, use ostd::mm::{VmReader, VmWriter};
sync::RwLock,
};
use super::{ use super::{
attr::SysAttrSet, attr::SysAttrSet,
node::{SysBranchNode, SysNode, SysNodeId, SysNodeType, SysObj, SysSymlink}, node::{SysBranchNode, SysNode, SysNodeId, SysNodeType, SysObj},
Error, Result, SysStr, Error, Result, SysStr,
}; };
use crate::{impl_cast_methods_for_branch, SysBranchNodeFields};
#[derive(Debug)] #[derive(Debug)]
pub struct SysTree { pub struct SysTree {
@ -32,12 +28,13 @@ impl SysTree {
/// and standard subdirectories like "devices", "block", "kernel". /// and standard subdirectories like "devices", "block", "kernel".
/// This is intended to be called once for the singleton. /// This is intended to be called once for the singleton.
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
let name = ""; // Only the root has an empty name
let attr_set = SysAttrSet::new_empty(); // The root has no attributes
let fields = SysBranchNodeFields::new(SysStr::from(name), attr_set);
let root_node = Arc::new_cyclic(|weak_self| RootNode { let root_node = Arc::new_cyclic(|weak_self| RootNode {
id: SysNodeId::new(), fields,
name: "".into(), weak_self: weak_self.clone(),
attrs: SysAttrSet::new_empty(),
children: RwLock::new(BTreeMap::new()),
self_ref: weak_self.clone(),
}); });
Self { root: root_node } Self { root: root_node }
@ -49,22 +46,22 @@ impl SysTree {
} }
} }
/// The root node in the `SysTree`.
///
/// A `RootNode` can work like a branching node, allowing to add additional nodes
/// as its children.
#[derive(Debug)] #[derive(Debug)]
pub struct RootNode { pub struct RootNode {
id: SysNodeId, fields: SysBranchNodeFields<dyn SysObj>,
name: SysStr, weak_self: Weak<Self>,
attrs: SysAttrSet,
children: RwLock<BTreeMap<SysStr, Arc<dyn SysObj>>>,
self_ref: Weak<Self>,
} }
impl RootNode { impl RootNode {
/// Adds a child node. This was part of the concrete RootNode impl in lib.rs. /// Adds a child node to this `RootNode`.
/// It's not part of the SysBranchNode trait definition.
pub fn add_child(&self, new_child: Arc<dyn SysObj>) -> Result<()> { pub fn add_child(&self, new_child: Arc<dyn SysObj>) -> Result<()> {
let name = new_child.name(); let name = new_child.name();
let mut children_guard = self.children.write(); let mut children_guard = self.fields.children.write();
if children_guard.contains_key(&name) { if children_guard.contains_key(name) {
return Err(Error::PermissionDenied); return Err(Error::PermissionDenied);
} }
children_guard.insert(name.clone(), new_child); children_guard.insert(name.clone(), new_child);
@ -72,41 +69,13 @@ impl RootNode {
} }
} }
#[inherit_methods(from = "self.fields")]
impl SysObj for RootNode { impl SysObj for RootNode {
fn as_any(&self) -> &dyn Any { impl_cast_methods_for_branch!();
self
}
fn arc_as_symlink(&self) -> Option<Arc<dyn SysSymlink>> { fn id(&self) -> &SysNodeId;
None
}
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> { fn name(&self) -> &SysStr;
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysNode>)
}
fn arc_as_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysBranchNode>)
}
fn id(&self) -> &SysNodeId {
&self.id
}
fn type_(&self) -> SysNodeType {
if self.children.read().is_empty() {
return SysNodeType::Leaf;
}
SysNodeType::Branch
}
fn name(&self) -> SysStr {
self.name.clone()
}
fn is_root(&self) -> bool { fn is_root(&self) -> bool {
true true
@ -119,7 +88,7 @@ impl SysObj for RootNode {
impl SysNode for RootNode { impl SysNode for RootNode {
fn node_attrs(&self) -> &SysAttrSet { fn node_attrs(&self) -> &SysAttrSet {
&self.attrs self.fields.attr_set()
} }
fn read_attr(&self, _name: &str, _writer: &mut VmWriter) -> Result<usize> { fn read_attr(&self, _name: &str, _writer: &mut VmWriter) -> Result<usize> {
@ -131,35 +100,11 @@ impl SysNode for RootNode {
} }
} }
#[inherit_methods(from = "self.fields")]
impl SysBranchNode for RootNode { impl SysBranchNode for RootNode {
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&dyn SysNode>)) { fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<dyn SysObj>>));
let children_guard = self.children.read();
children_guard
.get(name)
.map(|child| {
if let Some(node_ref) = child.arc_as_node().as_deref() {
f(Some(node_ref));
} else {
f(None);
}
})
.unwrap_or_else(|| f(None));
}
fn visit_children_with(&self, _min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>) { fn visit_children_with(&self, _min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>);
let children_guard = self.children.read();
for child_arc in children_guard.values() {
if f(child_arc).is_none() {
break;
}
}
}
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>> { fn child(&self, name: &str) -> Option<Arc<dyn SysObj>>;
self.children.read().get(name).cloned()
}
fn children(&self) -> Vec<Arc<dyn SysObj>> {
self.children.read().values().cloned().collect()
}
} }

View File

@ -3,7 +3,6 @@
//! Utility definitions and helper structs for implementing `SysTree` nodes. //! Utility definitions and helper structs for implementing `SysTree` nodes.
use alloc::{collections::BTreeMap, string::String, sync::Arc}; use alloc::{collections::BTreeMap, string::String, sync::Arc};
use core::ops::Deref;
use ostd::sync::RwLock; use ostd::sync::RwLock;
@ -31,8 +30,8 @@ impl SysObjFields {
&self.id &self.id
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &SysStr {
self.name.deref() &self.name
} }
} }
@ -54,7 +53,7 @@ impl SysNormalNodeFields {
self.base.id() self.base.id()
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &SysStr {
self.base.name() self.base.name()
} }
@ -81,7 +80,7 @@ impl<C: SysObj + ?Sized> SysBranchNodeFields<C> {
self.base.id() self.base.id()
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &SysStr {
self.base.name() self.base.name()
} }
@ -97,7 +96,7 @@ impl<C: SysObj + ?Sized> SysBranchNodeFields<C> {
pub fn add_child(&self, new_child: Arc<C>) -> Result<()> { pub fn add_child(&self, new_child: Arc<C>) -> Result<()> {
let mut children = self.children.write(); let mut children = self.children.write();
let name = new_child.name(); let name = new_child.name();
if children.contains_key(name.deref()) { if children.contains_key(name) {
return Err(Error::PermissionDenied); return Err(Error::PermissionDenied);
} }
children.insert(name.clone(), new_child); children.insert(name.clone(), new_child);
@ -108,6 +107,29 @@ impl<C: SysObj + ?Sized> SysBranchNodeFields<C> {
let mut children = self.children.write(); let mut children = self.children.write();
children.remove(child_name) children.remove(child_name)
} }
pub fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<C>>)) {
let children_guard = self.children.read();
f(children_guard.get(name))
}
pub fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<C>) -> Option<()>) {
let children_guard = self.children.read();
for child_arc in children_guard.values() {
if child_arc.id().as_u64() < min_id {
continue;
}
if f(child_arc).is_none() {
break;
}
}
}
pub fn child(&self, name: &str) -> Option<Arc<C>> {
let children = self.children.read();
children.get(name).cloned()
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -128,7 +150,7 @@ impl SymlinkNodeFields {
self.base.id() self.base.id()
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &SysStr {
self.base.name() self.base.name()
} }

View File

@ -191,7 +191,7 @@ impl SysFsInode {
match child_type { match child_type {
SysNodeType::Branch => { SysNodeType::Branch => {
let child_branch = child_sysnode let child_branch = child_sysnode
.arc_as_branch() .cast_to_branch()
.ok_or(Error::new(Errno::EIO))?; .ok_or(Error::new(Errno::EIO))?;
let inode = Self::new_branch_dir( let inode = Self::new_branch_dir(
self.systree, self.systree,
@ -202,7 +202,7 @@ impl SysFsInode {
} }
SysNodeType::Leaf => { SysNodeType::Leaf => {
let child_leaf_node = let child_leaf_node =
child_sysnode.arc_as_node().ok_or(Error::new(Errno::EIO))?; child_sysnode.cast_to_node().ok_or(Error::new(Errno::EIO))?;
let inode = Self::new_leaf_dir( let inode = Self::new_leaf_dir(
self.systree, self.systree,
InnerNode::Leaf(child_leaf_node), InnerNode::Leaf(child_leaf_node),
@ -212,7 +212,7 @@ impl SysFsInode {
} }
SysNodeType::Symlink => { SysNodeType::Symlink => {
let child_symlink = child_sysnode let child_symlink = child_sysnode
.arc_as_symlink() .cast_to_symlink()
.ok_or(Error::new(Errno::EIO))?; .ok_or(Error::new(Errno::EIO))?;
let inode = Self::new_symlink( let inode = Self::new_symlink(
self.systree, self.systree,
@ -646,7 +646,7 @@ impl Iterator for NodeDentryIter {
}; };
return Some(Dentry { return Some(Dentry {
ino: obj_ino, ino: obj_ino,
name: obj.name(), name: obj.name().clone(),
type_, type_,
}); });
} }

View File

@ -9,13 +9,15 @@ use alloc::{
vec, vec,
vec::Vec, vec::Vec,
}; };
use core::{any::Any, fmt::Debug}; use core::fmt::Debug;
use aster_systree::{ use aster_systree::{
impl_cast_methods_for_branch, impl_cast_methods_for_node, impl_cast_methods_for_symlink,
init_for_ktest, singleton as systree_singleton, Error as SysTreeError, Result as SysTreeResult, init_for_ktest, singleton as systree_singleton, Error as SysTreeError, Result as SysTreeResult,
SysAttrFlags, SysAttrSet, SysAttrSetBuilder, SysBranchNode, SysBranchNodeFields, SysNode, SysAttrFlags, SysAttrSet, SysAttrSetBuilder, SysBranchNode, SysBranchNodeFields, SysNode,
SysNodeId, SysNodeType, SysNormalNodeFields, SysObj, SysStr, SysSymlink, SysTree, SysNodeId, SysNodeType, SysNormalNodeFields, SysObj, SysStr, SysSymlink, SysTree,
}; };
use inherit_methods_macro::inherit_methods;
use ostd::{ use ostd::{
mm::{FallibleVmRead, FallibleVmWrite, VmReader, VmWriter}, mm::{FallibleVmRead, FallibleVmWrite, VmReader, VmWriter},
prelude::ktest, prelude::ktest,
@ -40,7 +42,7 @@ use crate::{
struct MockLeafNode { struct MockLeafNode {
fields: SysNormalNodeFields, fields: SysNormalNodeFields,
data: RwLock<BTreeMap<String, String>>, // Store attribute data data: RwLock<BTreeMap<String, String>>, // Store attribute data
self_ref: Weak<Self>, weak_self: Weak<Self>,
} }
impl MockLeafNode { impl MockLeafNode {
@ -67,28 +69,20 @@ impl MockLeafNode {
Arc::new_cyclic(|weak_self| MockLeafNode { Arc::new_cyclic(|weak_self| MockLeafNode {
fields, fields,
data: RwLock::new(data), data: RwLock::new(data),
self_ref: weak_self.clone(), weak_self: weak_self.clone(),
}) })
} }
} }
impl SysObj for MockLeafNode { impl SysObj for MockLeafNode {
fn as_any(&self) -> &dyn Any { impl_cast_methods_for_node!();
self
}
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> {
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysNode>)
}
fn id(&self) -> &SysNodeId { fn id(&self) -> &SysNodeId {
self.fields.id() self.fields.id()
} }
fn type_(&self) -> SysNodeType {
SysNodeType::Leaf fn name(&self) -> &SysStr {
} self.fields.name()
fn name(&self) -> SysStr {
Cow::Owned(self.fields.name().to_string()) // Convert to Cow::Owned
} }
} }
@ -143,7 +137,7 @@ impl SysNode for MockLeafNode {
#[derive(Debug)] #[derive(Debug)]
struct MockBranchNode { struct MockBranchNode {
fields: SysBranchNodeFields<dyn SysObj>, fields: SysBranchNodeFields<dyn SysObj>,
self_ref: Weak<Self>, weak_self: Weak<Self>,
} }
impl MockBranchNode { impl MockBranchNode {
@ -160,7 +154,7 @@ impl MockBranchNode {
Arc::new_cyclic(|weak_self| MockBranchNode { Arc::new_cyclic(|weak_self| MockBranchNode {
fields, fields,
self_ref: weak_self.clone(), weak_self: weak_self.clone(),
}) })
} }
@ -170,27 +164,14 @@ impl MockBranchNode {
} }
impl SysObj for MockBranchNode { impl SysObj for MockBranchNode {
fn as_any(&self) -> &dyn Any { impl_cast_methods_for_branch!();
self
}
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> {
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysNode>)
}
fn arc_as_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysBranchNode>)
}
fn id(&self) -> &SysNodeId { fn id(&self) -> &SysNodeId {
self.fields.id() self.fields.id()
} }
fn type_(&self) -> SysNodeType {
SysNodeType::Branch fn name(&self) -> &SysStr {
} self.fields.name()
fn name(&self) -> SysStr {
Cow::Owned(self.fields.name().to_string()) // Convert to Cow::Owned
} }
} }
@ -232,41 +213,13 @@ impl SysNode for MockBranchNode {
} }
} }
#[inherit_methods(from = "self.fields")]
impl SysBranchNode for MockBranchNode { impl SysBranchNode for MockBranchNode {
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&dyn SysNode>)) { fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<dyn SysObj>>));
self.fields
.children
.read()
.get(name)
.map(|child| {
child
.arc_as_node()
.map(|node| f(Some(node.as_ref())))
.unwrap_or_else(|| f(None));
})
.unwrap_or_else(|| f(None));
}
fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>) { fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>);
let children = self.fields.children.read();
for child in children
.values()
.filter(|child| child.id().as_u64() >= min_id)
{
if f(child).is_none() {
break;
}
}
}
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>> { fn child(&self, name: &str) -> Option<Arc<dyn SysObj>>;
let children = self.fields.children.read();
children.get(name).cloned()
}
fn children(&self) -> Vec<Arc<dyn SysObj>> {
self.fields.children.read().values().cloned().collect()
}
} }
// Mock Symlink // Mock Symlink
@ -275,7 +228,7 @@ struct MockSymlinkNode {
id: SysNodeId, id: SysNodeId,
name: SysStr, name: SysStr,
target: String, target: String,
self_ref: Weak<Self>, weak_self: Weak<Self>,
} }
impl MockSymlinkNode { impl MockSymlinkNode {
@ -284,28 +237,20 @@ impl MockSymlinkNode {
id: SysNodeId::new(), id: SysNodeId::new(),
name: name.to_string().into(), name: name.to_string().into(),
target: target.to_string(), target: target.to_string(),
self_ref: weak_self.clone(), weak_self: weak_self.clone(),
}) })
} }
} }
impl SysObj for MockSymlinkNode { impl SysObj for MockSymlinkNode {
fn as_any(&self) -> &dyn Any { impl_cast_methods_for_symlink!();
self
}
fn arc_as_symlink(&self) -> Option<Arc<dyn SysSymlink>> {
self.self_ref
.upgrade()
.map(|arc_self| arc_self as Arc<dyn SysSymlink>)
}
fn id(&self) -> &SysNodeId { fn id(&self) -> &SysNodeId {
&self.id &self.id
} }
fn type_(&self) -> SysNodeType {
SysNodeType::Symlink fn name(&self) -> &SysStr {
} &self.name
fn name(&self) -> SysStr {
self.name.clone()
} }
} }