credence_lib/configuration/port/
loadable_bytes.rs

1use {
2    bytes::*,
3    bytestring::*,
4    compris::resolve::*,
5    kutil_std::error::*,
6    std::{fmt, fs::*, io, path::*},
7};
8
9//
10// LoadableBytes
11//
12
13/// A [Bytes] that be specified either explicitly or as a path from which to read it.
14///
15/// Resolves from:
16/// * A single-key map where the key is either "content" or "path".
17/// * Directly from a [Blob].
18#[derive(Clone, Debug, Resolve)]
19pub enum LoadableBytes {
20    /// Content.
21    #[resolve(single, key = "content")]
22    Content(Bytes),
23
24    /// Path.
25    #[resolve(key = "path")]
26    Path(PathBuf),
27}
28
29impl LoadableBytes {
30    /// If it's [Content](LoadableBytes::Content), returns it.
31    ///
32    /// If it's [Path](LoadableBytes::Path), will attempt to read from it.
33    pub fn to_bytes(&self) -> io::Result<Bytes> {
34        match self {
35            Self::Content(bytes) => Ok(bytes.clone()),
36            Self::Path(path) => read(path).map(|bytes| bytes.into()).with_path(path),
37        }
38    }
39
40    /// If it's already [Content](LoadableBytes::Content), returns self.
41    ///
42    /// If it's [Path](LoadableBytes::Path), will attempt to read from the path and return a new
43    /// [LoadableBytes] with [Content](LoadableBytes::Content).
44    pub fn into_content(self) -> io::Result<Self> {
45        match &self {
46            Self::Content(_) => Ok(self),
47            Self::Path(_) => Ok(Self::Content(self.to_bytes()?)),
48        }
49    }
50}
51
52impl Default for LoadableBytes {
53    fn default() -> Self {
54        Self::Content(Bytes::default())
55    }
56}
57
58impl From<Bytes> for LoadableBytes {
59    fn from(blob: Bytes) -> Self {
60        Self::Content(blob)
61    }
62}
63
64impl From<ByteString> for LoadableBytes {
65    fn from(string: ByteString) -> Self {
66        Self::Content(string.into_bytes())
67    }
68}
69
70impl From<&str> for LoadableBytes {
71    fn from(string: &str) -> Self {
72        Self::Content(Bytes::copy_from_slice(string.as_bytes()))
73    }
74}
75
76impl TryInto<Bytes> for LoadableBytes {
77    type Error = io::Error;
78
79    fn try_into(self) -> Result<Bytes, Self::Error> {
80        match self {
81            Self::Content(bytes) => Ok(bytes),
82            Self::Path(_) => self.to_bytes(),
83        }
84    }
85}
86
87impl fmt::Display for LoadableBytes {
88    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
89        match self {
90            Self::Content(bytes) => write!(formatter, "content: {} bytes", bytes.len()),
91            Self::Path(path) => write!(formatter, "path: {}", path.display()),
92        }
93    }
94}