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}