Skip to content

Instantly share code, notes, and snippets.

@jstarry
Created June 28, 2019 13:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jstarry/0c753f4e435a80b118beb52faa1344e6 to your computer and use it in GitHub Desktop.
Save jstarry/0c753f4e435a80b118beb52faa1344e6 to your computer and use it in GitHub Desktop.
Proof of concept for Yew required props
use std::marker::PhantomData;
use yew::Properties;
struct Alpha;
#[derive(Properties)]
struct Props {
#[props(required)]
alpha: Alpha,
beta: Option<bool>,
charlie: String,
#[props(required)]
delta: Option<String>,
}
fn proof_of_concept() {
// `yew_html` GENERATED CODE
// -------------------------
let props: Props = PropsBuilder::<Start>::new()
.alpha(Alpha {})
.charlie(String::from("yo"))
.delta(None)
.build();
// ----------------------------
}
// `yew_props_derive` GENERATED CODE
// ---------------------------------
struct Start;
struct AfterAlpha;
struct AfterDelta;
trait NextProp {}
impl NextProp for Start {}
impl NextProp for AfterAlpha {}
impl NextProp for AfterDelta {}
struct WrappedProps {
alpha_wrapper: Option<Alpha>,
beta: Option<bool>,
charlie: String,
delta_wrapper: Option<Option<String>>,
}
struct PropsBuilder<P: NextProp> {
wrapped: Box<WrappedProps>,
_marker: PhantomData<P>,
}
impl PropsBuilder<Start> {
fn new() -> Self {
PropsBuilder {
wrapped: Box::new(WrappedProps {
alpha_wrapper: Default::default(),
beta: Default::default(),
charlie: Default::default(),
delta_wrapper: Default::default(),
}),
_marker: PhantomData,
}
}
fn alpha(mut self, alpha: Alpha) -> PropsBuilder<AfterAlpha> {
self.wrapped.alpha_wrapper = Some(alpha);
PropsBuilder {
wrapped: self.wrapped,
_marker: PhantomData,
}
}
}
impl PropsBuilder<AfterAlpha> {
fn beta(mut self, beta: Option<bool>) -> PropsBuilder<AfterAlpha> {
self.wrapped.beta = beta;
self
}
fn charlie(mut self, charlie: String) -> PropsBuilder<AfterAlpha> {
self.wrapped.charlie = charlie;
self
}
fn delta(mut self, delta: Option<String>) -> PropsBuilder<AfterDelta> {
self.wrapped.delta_wrapper = Some(delta);
PropsBuilder {
wrapped: self.wrapped,
_marker: PhantomData,
}
}
}
impl PropsBuilder<AfterDelta> {
fn build(self) -> Props {
Props {
alpha: self.wrapped.alpha_wrapper.unwrap(),
beta: self.wrapped.beta,
charlie: self.wrapped.charlie,
delta: self.wrapped.delta_wrapper.unwrap(),
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment