from_path/
lib.rs

1//! Loading values from paths.
2//!
3//! This crate provides the [`FromPath`] trait for types that can have values loaded from paths.
4//!
5//! There are also the [`load`] convenience function and the [`Load`] extension trait for
6//! when the types can be inferred.
7//!
8//! # Example
9//!
10//! Firstly, we need to implement the [`FromPath`] trait, and then use it via [`load`] or [`Load`]:
11//!
12//! ```rust
13//! use std::{fs::read_to_string, io::Error, path::Path};
14//!
15//! use from_path::{load, FromPath, Load};
16//!
17//! #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
18//! pub struct Content {
19//!     pub string: String,
20//! }
21//!
22//! impl Content {
23//!     pub fn new(string: String) -> Self {
24//!         Self { string }
25//!     }
26//! }
27//!
28//! impl FromPath for Content {
29//!     type Error = Error;
30//!
31//!     fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, Self::Error> {
32//!         read_to_string(path).map(Self::new)
33//!     }
34//! }
35//!
36//! let path = "hello-world";
37//!
38//! let content: Content = load(path).unwrap();
39//!
40//! assert_eq!(content.string.trim(), "Hello, world!");
41//!
42//! let extended: Content = path.load().unwrap();
43//!
44//! assert_eq!(content, extended);
45//! ```
46
47#![forbid(unsafe_code)]
48#![deny(missing_docs)]
49
50use std::path::Path;
51
52/// Loading values from paths.
53pub trait FromPath: Sized {
54    /// The associated error type returned from [`from_path`] on failure.
55    ///
56    /// [`from_path`]: Self::from_path
57    type Error;
58
59    /// Loads the value of this type from the given path.
60    ///
61    /// # Errors
62    ///
63    /// Returns [`Error`] when loading fails.
64    ///
65    /// [`Error`]: Self::Error
66    fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, Self::Error>;
67}
68
69/// Loads the value of the given type from the given path.
70///
71/// # Errors
72///
73/// Returns [`Error`] when loading fails.
74///
75/// [`Error`]: FromPath::Error
76pub fn load<F: FromPath, P: AsRef<Path>>(path: P) -> Result<F, F::Error> {
77    F::from_path(path)
78}
79
80mod sealed {
81    pub trait Sealed {}
82}
83
84/// Loading values from paths (sealed extension trait).
85pub trait Load: sealed::Sealed {
86    /// Loads the value of type [`F`] from the path.
87    ///
88    /// # Errors
89    ///
90    /// Returns [`F::Error`] when loading fails.
91    ///
92    /// [`F`]: FromPath
93    /// [`F::Error`]: FromPath::Error
94    fn load<F: FromPath>(&self) -> Result<F, F::Error>;
95}
96
97impl<P: AsRef<Path> + ?Sized> sealed::Sealed for P {}
98
99impl<P: AsRef<Path> + ?Sized> Load for P {
100    fn load<F: FromPath>(&self) -> Result<F, F::Error> {
101        load(self)
102    }
103}