Skip to content

Instantly share code, notes, and snippets.

@absolutejam
Created October 18, 2023 18:34
Show Gist options
  • Save absolutejam/373744541525ab7774f65acfd2a22809 to your computer and use it in GitHub Desktop.
Save absolutejam/373744541525ab7774f65acfd2a22809 to your computer and use it in GitHub Desktop.
Not quite Scala, but close enough
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