Skip to main content

greentic_distributor_dev/
lib.rs

1use std::fs;
2use std::io::ErrorKind;
3use std::path::{Path, PathBuf};
4
5use greentic_distributor_client::{
6    ComponentId, DistributorError, DistributorSource, PackId, Version,
7};
8
9/// Filesystem layout strategies for the dev distributor source.
10#[derive(Clone, Debug)]
11pub enum DevLayout {
12    Flat,
13    ByIdAndVersion,
14}
15
16/// Configuration for [`DevDistributorSource`].
17#[derive(Clone, Debug)]
18pub struct DevConfig {
19    pub root_dir: PathBuf,
20    pub packs_dir: String,
21    pub components_dir: String,
22    pub layout: DevLayout,
23}
24
25impl Default for DevConfig {
26    fn default() -> Self {
27        DevConfig {
28            root_dir: PathBuf::from(".greentic/dev"),
29            packs_dir: "packs".into(),
30            components_dir: "components".into(),
31            layout: DevLayout::Flat,
32        }
33    }
34}
35
36/// Serves packs/components directly from a local directory tree.
37pub struct DevDistributorSource {
38    cfg: DevConfig,
39}
40
41impl DevDistributorSource {
42    pub fn new(cfg: DevConfig) -> Self {
43        Self { cfg }
44    }
45
46    fn pack_path(&self, pack_id: &PackId, version: &Version) -> PathBuf {
47        match self.cfg.layout {
48            DevLayout::Flat => self
49                .root()
50                .join(&self.cfg.packs_dir)
51                .join(format!("{pack_id}-{version}.gtpack")),
52            DevLayout::ByIdAndVersion => self
53                .root()
54                .join(&self.cfg.packs_dir)
55                .join(pack_id.as_str())
56                .join(version.to_string())
57                .join("pack.gtpack"),
58        }
59    }
60
61    fn component_path(&self, component_id: &ComponentId, version: &Version) -> PathBuf {
62        match self.cfg.layout {
63            DevLayout::Flat => self
64                .root()
65                .join(&self.cfg.components_dir)
66                .join(format!("{component_id}-{version}.wasm")),
67            DevLayout::ByIdAndVersion => self
68                .root()
69                .join(&self.cfg.components_dir)
70                .join(component_id.as_str())
71                .join(version.to_string())
72                .join("component.wasm"),
73        }
74    }
75
76    fn read_file(&self, path: &Path) -> Result<Vec<u8>, DistributorError> {
77        match fs::read(path) {
78            Ok(bytes) => Ok(bytes),
79            Err(err) if err.kind() == ErrorKind::NotFound => Err(DistributorError::NotFound),
80            Err(err) => Err(DistributorError::Io(err)),
81        }
82    }
83
84    fn root(&self) -> &Path {
85        &self.cfg.root_dir
86    }
87}
88
89impl DistributorSource for DevDistributorSource {
90    fn fetch_pack(&self, pack_id: &PackId, version: &Version) -> Result<Vec<u8>, DistributorError> {
91        let path = self.pack_path(pack_id, version);
92        self.read_file(&path)
93    }
94
95    fn fetch_component(
96        &self,
97        component_id: &ComponentId,
98        version: &Version,
99    ) -> Result<Vec<u8>, DistributorError> {
100        let path = self.component_path(component_id, version);
101        self.read_file(&path)
102    }
103}