I've created a struct that has a &Path
and two &str
s. I'm trying to define a method on the struct that, given a Path
-like representing a relative file path, concatenates it to the root, canonicalizes it, validates that the resulting path is contained in the root dir, and returns either a tuple of the relative and absolute paths, or an error (using a Result
):
use std::path::Path;
use std::path::PathBuf;
mod error {
use std::error;
use std::fmt;
use std::path;
#[derive(Debug)]
pub enum MediaLibraryError<'a> {
NonAbsPath(&'a path::Path),
NonRelPath(&'a path::Path),
}
impl<'a> error::Error for MediaLibraryError<'a> {
// This is meant to be a static description of the error, without any computation!
fn description(&self) -> &str {
match self {
&MediaLibraryError::NonAbsPath(_) => "File path was was expected to be absolute",
&MediaLibraryError::NonRelPath(_) => "File path was was expected to be relative",
}
}
}
impl<'a> fmt::Display for MediaLibraryError<'a> {
// This is the place to put formatted/computed error messages!
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&MediaLibraryError::NonAbsPath(x) => {
write!(f, r##"Path "{:?}" is not absolute"##, x)
}
&MediaLibraryError::NonRelPath(x) => {
write!(f, r##"Path "{:?}" is not relative"##, x)
}
}
}
}
}
use error::MediaLibraryError;
struct MediaLibrary<'a> {
root_dir: &'a Path,
item_meta_fn: &'a str,
self_meta_fn: &'a str,
}
impl<'a> MediaLibrary<'a> {
fn co_norm<P: AsRef<Path>>(
&self,
rel_sub_path: P,
) -> Result<(PathBuf, PathBuf), MediaLibraryError> {
let rel_sub_path = rel_sub_path.as_ref().to_path_buf();
if !rel_sub_path.is_relative() {
return Err(MediaLibraryError::NonRelPath(&rel_sub_path));
}
let abs_sub_path = self.root_dir.join(&rel_sub_path);
// Canonicalize.
// Check that created absolute path is a child of root or root itself.
Ok((rel_sub_path.to_path_buf(), abs_sub_path))
}
}
fn main() {}
However, when trying to compile, I get this error:
error[E0597]: `rel_sub_path` does not live long enough
--> src/main.rs:56:55
|
56 | return Err(MediaLibraryError::NonRelPath(&rel_sub_path));
| ^^^^^^^^^^^^ does not live long enough
...
65 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 49:5...
--> src/main.rs:49:5
|
49 | / fn co_norm<P: AsRef<Path>>(
50 | | &self,
51 | | rel_sub_path: P,
52 | | ) -> Result<(PathBuf, PathBuf), MediaLibraryError> {
... |
64 | | Ok((rel_sub_path.to_path_buf(), abs_sub_path))
65 | | }
| |_____^
A common beginner error, I'm sure, but for the life of me, I can't seem to figure out what to do. I've tried messing with lifetimes, trying PathBuf
s instead of Path
s, using as_ref()
/to_owned()
. However, all in vain. I feel like there's a great lesson hidden in here, but I'm stumped.
P.S.: I'm using the P: AsRef<Path>
as found in the docs, my understanding is that it lets one pass in a &str
, Path
, PathBuf
, etc to the method?