Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/project-model/src/manifest_path.rs')
-rw-r--r--crates/project-model/src/manifest_path.rs51
1 files changed, 51 insertions, 0 deletions
diff --git a/crates/project-model/src/manifest_path.rs b/crates/project-model/src/manifest_path.rs
new file mode 100644
index 0000000000..4910fd3d11
--- /dev/null
+++ b/crates/project-model/src/manifest_path.rs
@@ -0,0 +1,51 @@
+//! See [`ManifestPath`].
+use std::{ops, path::Path};
+
+use paths::{AbsPath, AbsPathBuf};
+
+/// More or less [`AbsPathBuf`] with non-None parent.
+///
+/// We use it to store path to Cargo.toml, as we frequently use the parent dir
+/// as a working directory to spawn various commands, and its nice to not have
+/// to `.unwrap()` everywhere.
+///
+/// This could have been named `AbsNonRootPathBuf`, as we don't enforce that
+/// this stores manifest files in particular, but we only use this for manifests
+/// at the moment in practice.
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
+pub struct ManifestPath {
+ file: AbsPathBuf,
+}
+
+impl TryFrom<AbsPathBuf> for ManifestPath {
+ type Error = AbsPathBuf;
+
+ fn try_from(file: AbsPathBuf) -> Result<Self, Self::Error> {
+ if file.parent().is_none() {
+ Err(file)
+ } else {
+ Ok(ManifestPath { file })
+ }
+ }
+}
+
+impl ManifestPath {
+ // Shadow `parent` from `Deref`.
+ pub fn parent(&self) -> &AbsPath {
+ self.file.parent().unwrap()
+ }
+}
+
+impl ops::Deref for ManifestPath {
+ type Target = AbsPath;
+
+ fn deref(&self) -> &Self::Target {
+ &*self.file
+ }
+}
+
+impl AsRef<Path> for ManifestPath {
+ fn as_ref(&self) -> &Path {
+ self.file.as_ref()
+ }
+}