credence_lib/configuration/port/
loadable_bytes.rs

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