wick-component-codegen 0.6.0

Code generator for wick components
Documentation
use proc_macro2::TokenStream;
use quote::quote;
use wick_interface_types::{Field, StructDefinition, TypeDefinition};

use crate::generate::config;
use crate::generate::dependency::Dependency;
use crate::generate::ids::id;
use crate::generate::templates::TypeOptions;

pub(crate) fn component_config(config: &mut config::Config, fields: Option<Vec<Field>>) -> TokenStream {
  let config_name = "RootConfig";
  let config_id = id(config_name);

  let config_def = fields.map_or_else(
    || {
      quote! {
        #[derive(Debug, ::serde::Deserialize, ::serde::Serialize, Clone, Copy, Default)]
        pub(crate) struct RootConfig {}
      }
    },
    |fields| {
      let (_, config_def) = super::type_def(
        config,
        &TypeDefinition::Struct(StructDefinition::new(config_name, fields, None)),
        TypeOptions::Defaults,
      );
      config_def
    },
  );

  config.add_dep(Dependency::WickPacket);
  config.add_dep(Dependency::WasmRsRx);
  config.add_dep(Dependency::WasmRs);

  quote! {
    #[cfg(target_family = "wasm")]
    thread_local! {
      static __CONFIG: std::cell::UnsafeCell<Option<SetupPayload>> = std::cell::UnsafeCell::new(None);
    }

    #config_def

    #[cfg(target_family = "wasm")]
    #[derive(Debug, ::serde::Deserialize)]
    pub(crate) struct SetupPayload {
      #[allow(unused)]
      pub(crate) provided: std::collections::HashMap<String,wick_packet::ComponentReference>,
      #[allow(unused)]
      pub(crate) imported: std::collections::HashMap<String,wick_packet::ComponentReference>,
      #[allow(unused)]
      pub(crate) config: #config_id,
    }

    #[cfg(target_family = "wasm")]
    fn __setup(input: wasmrs_rx::BoxMono<wasmrs::Payload, wasmrs::PayloadError>) -> Result<wasmrs_rx::BoxMono<wasmrs::RawPayload, wasmrs::PayloadError>, wick_component::BoxError> {
      Ok(Box::pin(async move {
        let payload = input.await?;
        match wasmrs_codec::messagepack::deserialize::<SetupPayload>(&payload.data) {
          Ok(input) => {
            __CONFIG.with(|cell| {
              #[allow(unsafe_code)]
              unsafe { &mut *cell.get() }.replace(input);
            });
            Ok(wasmrs::RawPayload::new_data(None, None))
          }
          Err(e) => Err(wasmrs::PayloadError::application_error(e.to_string(), None)),
        }
      }))
    }

    #[allow(unused)]
    #[cfg(target_family = "wasm")]
    pub(crate) fn get_config() -> &'static SetupPayload {
      __CONFIG.with(|cell| {
        #[allow(unsafe_code)]
        unsafe { & *cell.get() }.as_ref().unwrap()
      })
    }

    #[allow(unused)]
    #[cfg(target_family = "wasm")]
    pub(crate) fn get_root_config() -> &'static #config_id {
      __CONFIG.with(|cell| {
        #[allow(unsafe_code)]
        &unsafe { & *cell.get() }.as_ref().unwrap().config
      })
    }

    pub(crate) trait RootConfigContext {
      fn root_config(&self) -> &'static #config_id;
    }

    impl<T> RootConfigContext for Context<T> where T:std::fmt::Debug + wick_component::flow_component::LocalAwareSend {
      fn root_config(&self) -> &'static #config_id {
        #[cfg(target_family = "wasm")]
        {get_root_config()}
        #[cfg(not(target_family = "wasm"))]
        {unimplemented!("root_config is only available in wasm builds")}
      }
    }


  }
}