Skip to main content

fuchsia_fatfs/
node.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::directory::FatDirectory;
6use crate::file::FatFile;
7use std::ops::Deref;
8use std::sync::{Arc, Weak};
9use zx::Status;
10
11pub trait Node {
12    /// Attach this FatNode to the given FatDirectory, with the given name.
13    fn attach(&self, parent: Arc<FatDirectory>, name: &str) -> Result<(), Status>;
14
15    /// Detach this FatNode from its parent.
16    fn detach(&self);
17
18    /// Takes an open count and opens the underlying node if not already open.
19    fn open_ref(&self) -> Result<(), Status>;
20
21    /// Releases an open count.
22    fn close_ref(&self);
23
24    /// Close the underlying node and all of its children, regardless of the number of open
25    /// connections.
26    fn shut_down(&self) -> Result<(), Status>;
27
28    /// Flushes the directory entry for this node.
29    fn flush_dir_entry(&self) -> Result<(), Status>;
30
31    /// Called when the node has been successfully deleted.
32    fn did_delete(&self);
33}
34
35#[derive(Clone, Debug)]
36/// This enum is used to represent values which could be either a FatDirectory
37/// or a FatFile. This holds a strong reference to the contained file/directory.
38pub enum FatNode {
39    Dir(Arc<FatDirectory>),
40    File(Arc<FatFile>),
41}
42
43impl FatNode {
44    /// Downgrade this FatNode into a WeakFatNode.
45    pub fn downgrade(&self) -> WeakFatNode {
46        match self {
47            FatNode::Dir(a) => WeakFatNode::Dir(Arc::downgrade(a)),
48            FatNode::File(b) => WeakFatNode::File(Arc::downgrade(b)),
49        }
50    }
51
52    pub fn as_node(&self) -> &(dyn Node + 'static) {
53        match self {
54            FatNode::Dir(a) => a.as_ref() as &dyn Node,
55            FatNode::File(b) => b.as_ref() as &dyn Node,
56        }
57    }
58}
59
60impl<'a> Deref for FatNode {
61    type Target = dyn Node;
62
63    fn deref(&self) -> &Self::Target {
64        self.as_node()
65    }
66}
67
68/// The same as FatNode, but using a weak reference.
69#[derive(Debug)]
70pub enum WeakFatNode {
71    Dir(Weak<FatDirectory>),
72    File(Weak<FatFile>),
73}
74
75impl WeakFatNode {
76    /// Try and upgrade this WeakFatNode to a FatNode. Returns None
77    /// if the referenced object has been destroyed.
78    pub fn upgrade(&self) -> Option<FatNode> {
79        match self {
80            WeakFatNode::Dir(a) => a.upgrade().map(|val| FatNode::Dir(val)),
81            WeakFatNode::File(b) => b.upgrade().map(|val| FatNode::File(val)),
82        }
83    }
84}
85
86/// RAII class that will close nodes when dropped.  This class is useful
87/// for instances where temporary open counts are required.
88pub struct Closer {
89    nodes: std::vec::Vec<FatNode>,
90}
91
92impl Closer {
93    pub fn new() -> Self {
94        Closer { nodes: Vec::new() }
95    }
96
97    pub fn add(&mut self, node: FatNode) -> FatNode {
98        self.nodes.push(node.clone());
99        node
100    }
101}
102
103impl Drop for Closer {
104    fn drop(&mut self) {
105        self.nodes.drain(..).for_each(|n: FatNode| n.close_ref());
106    }
107}