1use std::{
4 future::Future,
5 path::{Path, PathBuf},
6};
7
8use wadm_types::Manifest;
9
10use crate::{error::ClientError, Result};
11
12pub trait ManifestLoader {
15 fn load_manifest(self) -> impl Future<Output = Result<Manifest>>;
16}
17
18impl ManifestLoader for &Manifest {
19 async fn load_manifest(self) -> Result<Manifest> {
20 Ok(self.clone())
21 }
22}
23
24impl ManifestLoader for Manifest {
25 async fn load_manifest(self) -> Result<Manifest> {
26 Ok(self)
27 }
28}
29
30impl ManifestLoader for Vec<u8> {
31 async fn load_manifest(self) -> Result<Manifest> {
32 parse_yaml_or_json(self).map_err(Into::into)
33 }
34}
35
36impl ManifestLoader for &[u8] {
37 async fn load_manifest(self) -> Result<Manifest> {
38 parse_yaml_or_json(self).map_err(Into::into)
39 }
40}
41
42macro_rules! impl_manifest_loader_for_path {
45 ($($ty:ty),*) => {
46 $(
47 impl ManifestLoader for $ty {
48 async fn load_manifest(self) -> Result<Manifest> {
49 let raw = tokio::fs::read(self).await.map_err(|e| ClientError::ManifestLoad(e.into()))?;
50 parse_yaml_or_json(raw).map_err(Into::into)
51 }
52 }
53 )*
54 };
55}
56
57impl_manifest_loader_for_path!(&Path, &str, &String, String, PathBuf, &PathBuf);
58
59pub fn parse_yaml_or_json(
62 raw: impl AsRef<[u8]>,
63) -> std::result::Result<Manifest, crate::error::SerializationError> {
64 serde_yaml::from_slice(raw.as_ref())
66 .or_else(|_| serde_json::from_slice(raw.as_ref()))
67 .map_err(Into::into)
68}