Created
October 18, 2023 18:34
-
-
Save absolutejam/373744541525ab7774f65acfd2a22809 to your computer and use it in GitHub Desktop.
Not quite Scala, but close enough
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use async_trait::async_trait; | |
use dyn_clone::DynClone; | |
use serde::{Deserialize, Serialize}; | |
//------------------------------------------------------------------------------ | |
trait SpecLoaderContract<Value, Spec> { | |
fn load(&self, value: Value) -> Result<Spec, anyhow::Error>; | |
} | |
trait HasSpecLoader<Value, Spec> { | |
fn get_loader() -> Box<dyn SpecLoaderContract<Value, Spec>>; | |
} | |
//------------------------------------------------------------------------------ | |
trait SpecLoader<Value, Spec> { | |
fn register_spec(&mut self, loader: Box<dyn SpecLoaderContract<Value, Spec> + 'static>); | |
} | |
trait SpecLoaderExt<Value, Spec> | |
where | |
Self: SpecLoader<Value, Spec>, | |
{ | |
fn register_spec_via_loader<T>(&mut self) | |
where | |
T: Default + SpecLoaderContract<Value, Spec> + 'static, | |
{ | |
let loader = <T as Default>::default(); | |
self.register_spec(Box::new(loader)) | |
} | |
fn register_spec_with_loader<T>(&mut self) | |
where | |
T: HasSpecLoader<Value, Spec> + 'static, | |
{ | |
let loader = T::get_loader(); | |
self.register_spec(loader) | |
} | |
} | |
impl<A: SpecLoader<Value, Spec>, Value, Spec> SpecLoaderExt<Value, Spec> for A {} | |
//------------------------------------------------------------------------------ | |
struct YamlSpecLoader<Spec> { | |
loaders: Vec<Box<dyn SpecLoaderContract<serde_yaml::Value, Spec>>>, | |
} | |
impl<Spec> YamlSpecLoader<Spec> { | |
pub fn new() -> Self { | |
Self { | |
loaders: Vec::new(), | |
} | |
} | |
} | |
impl<Spec> SpecLoader<serde_yaml::Value, Spec> for YamlSpecLoader<Spec> { | |
fn register_spec( | |
&mut self, | |
loader: Box<dyn SpecLoaderContract<serde_yaml::Value, Spec> + 'static>, | |
) { | |
self.loaders.push(loader) | |
} | |
} | |
//------------------------------------------------------------------------------ | |
struct JsonSpecLoader<Spec> { | |
loaders: Vec<Box<dyn SpecLoaderContract<serde_json::Value, Spec>>>, | |
} | |
impl<Spec> JsonSpecLoader<Spec> { | |
pub fn new() -> Self { | |
Self { | |
loaders: Vec::new(), | |
} | |
} | |
} | |
impl<Spec> SpecLoader<serde_json::Value, Spec> for JsonSpecLoader<Spec> { | |
fn register_spec( | |
&mut self, | |
loader: Box<dyn SpecLoaderContract<serde_json::Value, Spec> + 'static>, | |
) { | |
self.loaders.push(loader) | |
} | |
} | |
//------------------------------------------------------------------------------ | |
#[async_trait] | |
pub trait Initialiser: Sync + Send + DynClone { | |
async fn initialise(&self) -> Result<(), anyhow::Error>; | |
} | |
dyn_clone::clone_trait_object!(Initialiser); | |
//------------------------------------------------------------------------------ | |
#[derive(Debug, Clone, Serialize, Deserialize)] | |
pub struct HelmInitialiser { | |
pub chart: String, | |
} | |
//------------------------------------------------------------------------------ | |
impl HasSpecLoader<serde_yaml::Value, Box<dyn Initialiser>> for HelmInitialiser { | |
fn get_loader() -> Box<dyn SpecLoaderContract<serde_yaml::Value, Box<dyn Initialiser>>> { | |
Box::new(HelmInitialiserLoader) | |
} | |
} | |
impl HasSpecLoader<serde_json::Value, Box<dyn Initialiser>> for HelmInitialiser { | |
fn get_loader() -> Box<dyn SpecLoaderContract<serde_json::Value, Box<dyn Initialiser>>> { | |
Box::new(HelmInitialiserLoader) | |
} | |
} | |
//------------------------------------------------------------------------------ | |
#[derive(Default)] | |
struct HelmInitialiserLoader; | |
impl SpecLoaderContract<serde_yaml::Value, Box<dyn Initialiser>> for HelmInitialiserLoader { | |
fn load(&self, value: serde_yaml::Value) -> Result<Box<dyn Initialiser>, anyhow::Error> { | |
// if value == whatever | |
Ok(Box::new(HelmInitialiser { | |
chart: "".to_owned(), | |
})) | |
} | |
} | |
impl SpecLoaderContract<serde_json::Value, Box<dyn Initialiser>> for HelmInitialiserLoader { | |
fn load(&self, value: serde_json::Value) -> Result<Box<dyn Initialiser>, anyhow::Error> { | |
// if value == whatever | |
Ok(Box::new(HelmInitialiser { | |
chart: "".to_owned(), | |
})) | |
} | |
} | |
#[async_trait] | |
impl Initialiser for HelmInitialiser { | |
async fn initialise(&self) -> Result<(), anyhow::Error> { | |
Ok(()) | |
} | |
} | |
//------------------------------------------------------------------------------ | |
fn main() { | |
let mut yaml_spec_loader = YamlSpecLoader::new(); | |
yaml_spec_loader.register_spec_via_loader::<HelmInitialiserLoader>(); | |
yaml_spec_loader.register_spec_with_loader::<HelmInitialiser>(); | |
let mut json_spec_loader = JsonSpecLoader::new(); | |
json_spec_loader.register_spec_via_loader::<HelmInitialiserLoader>(); | |
json_spec_loader.register_spec_with_loader::<HelmInitialiser>(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment