Skip to main content

cat_dev/fsemul/filesystem/
mod.rs

1//! All of the code related to filesystems.
2
3pub mod host;
4#[cfg_attr(docsrs, doc(cfg(feature = "nus")))]
5#[cfg(feature = "nus")]
6pub mod nus_fuse;
7
8use std::path::PathBuf;
9use valuable::{Fields, NamedField, NamedValues, StructDef, Structable, Valuable, Value, Visit};
10
11#[cfg(feature = "nus")]
12use sachet::{common::CafeContentFileInformation, title::TitleID};
13
14/// A resolved location given an arbitrary path.
15#[derive(Clone, Debug, PartialEq, Eq, Valuable)]
16pub enum ResolvedLocation {
17	/// A location on a particular filesystem.
18	///
19	/// This location _may not exist_. There is a boolean in this struct that
20	/// tells you the final resolved location, the closest resolved location for
21	/// permission checks, and if the path exists and is the same between
22	/// resolution, and what actually exists.
23	Filesystem(FilesystemLocation),
24	/// A network location to fetch.
25	///
26	/// TODO(mythra): figure out type.
27	Network(()),
28	/// The location of this file is somewhere within NUS.
29	#[cfg_attr(docsrs, doc(cfg(feature = "nus")))]
30	#[cfg(feature = "nus")]
31	NUSLocation(TitleID, PathBuf, PathBuf),
32}
33
34/// A pointer to a particular item within a folder.
35#[derive(Clone, Debug, PartialEq, Eq, Valuable)]
36pub enum ItemInFolder {
37	/// An item that is 'local' within a folder.
38	///
39	/// The path that exists on disk, and the amount of components to strip.
40	Local(PathBuf, usize),
41	#[cfg(feature = "nus")]
42	/// An item that is stored remotely in 'NUS', and doesn't actually exist on
43	/// disk.
44	///
45	/// Items are:
46	/// - Title ID
47	/// - Relative path within NUS
48	/// - Actual File on Disk.
49	/// - File information (none on folder).
50	Nus(
51		Option<TitleID>,
52		PathBuf,
53		PathBuf,
54		Option<CafeContentFileInformation>,
55	),
56}
57
58/// A location that's been resolved, and is guaranteed to be in one of our
59/// mounted paths.
60#[derive(Clone, Debug, PartialEq, Eq)]
61pub struct FilesystemLocation {
62	/// The final resolved path (may not exist).
63	resolved_path: PathBuf,
64	/// The resolved path that may not be the same as the final path, but is
65	/// enough to confirm we're in the same directory.
66	closest_resolved_path: PathBuf,
67	/// If the canonicalized path is the same as the resolved path.
68	canonicalized_is_exact: bool,
69}
70impl FilesystemLocation {
71	#[must_use]
72	pub const fn new(
73		resolved_path: PathBuf,
74		closest_resolved_path: PathBuf,
75		canonicalized_is_exact: bool,
76	) -> Self {
77		Self {
78			resolved_path,
79			closest_resolved_path,
80			canonicalized_is_exact,
81		}
82	}
83
84	#[must_use]
85	pub const fn resolved_path(&self) -> &PathBuf {
86		&self.resolved_path
87	}
88	#[must_use]
89	pub const fn closest_resolved_path(&self) -> &PathBuf {
90		&self.closest_resolved_path
91	}
92	#[must_use]
93	pub const fn canonicalized_is_exact(&self) -> bool {
94		self.canonicalized_is_exact
95	}
96}
97
98const FILESYSTEM_LOCATION_FIELDS: &[NamedField<'static>] = &[
99	NamedField::new("resolved_path"),
100	NamedField::new("closest_resolved_path"),
101	NamedField::new("canonicalized_is_exact"),
102];
103
104impl Structable for FilesystemLocation {
105	fn definition(&self) -> StructDef<'_> {
106		StructDef::new_static(
107			"FilesystemLocation",
108			Fields::Named(FILESYSTEM_LOCATION_FIELDS),
109		)
110	}
111}
112
113impl Valuable for FilesystemLocation {
114	fn as_value(&self) -> Value<'_> {
115		Value::Structable(self)
116	}
117
118	fn visit(&self, visitor: &mut dyn Visit) {
119		visitor.visit_named_fields(&NamedValues::new(
120			FILESYSTEM_LOCATION_FIELDS,
121			&[
122				Valuable::as_value(&self.resolved_path),
123				Valuable::as_value(&self.closest_resolved_path),
124				Valuable::as_value(&self.canonicalized_is_exact),
125			],
126		));
127	}
128}