Skip to content

Commit

Permalink
Move MaybeDyn to new file and add some impls (#693)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukechu10 authored Sep 12, 2024
1 parent 2fa36a6 commit 96a756b
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 71 deletions.
3 changes: 0 additions & 3 deletions packages/sycamore-reactive/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ use crate::*;

/// A trait that is implemented for reactive data that can be accessed and tracked, such as
/// [`Signal`].
///
/// You can make your components/functions take this instead of a concrete reactive type so that it
/// can work with any reactive type.
pub trait Accessor<T> {
/// Get the reactive value. For example, with [`Signal`], this just calls
/// [`get`](ReadSignal::get).
Expand Down
2 changes: 2 additions & 0 deletions packages/sycamore-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub mod events;
mod components;
mod elements;
mod iter;
mod maybe_dyn;
mod node;
mod noderef;
mod portal;
Expand All @@ -50,6 +51,7 @@ mod view;
pub use self::components::*;
pub use self::elements::*;
pub use self::iter::*;
pub use self::maybe_dyn::*;
pub use self::node::*;
pub use self::noderef::*;
pub use self::portal::*;
Expand Down
87 changes: 87 additions & 0 deletions packages/sycamore-web/src/maybe_dyn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use std::borrow::Cow;

use wasm_bindgen::JsValue;

/// Represents a value that can be either static or dynamic.
///
/// This is useful for cases where you want to accept a value that can be either static or dynamic,
/// such as in component props.
///
/// A [`MaybeDyn`] value can be created from a static value or a closure that returns the value by
/// using the [`From`] trait.
pub enum MaybeDyn<T: Into<Self>> {
Static(T),
Dynamic(Box<dyn FnMut() -> T>),
}

impl<T: Into<Self>> MaybeDyn<T> {
/// Evaluate the value by consuming itself.
pub fn evaluate(self) -> T {
match self {
Self::Static(value) => value,
Self::Dynamic(mut f) => f(),
}
}
}

impl<T: Into<Self>, F: FnMut() -> U + 'static, U: Into<T>> From<F> for MaybeDyn<T> {
fn from(mut f: F) -> Self {
Self::Dynamic(Box::new(move || f().into()))
}
}

macro_rules! impl_from_maybe_dyn {
($struct:ty => $($ty:ty),*) => {
$(
impl From<$ty> for $struct {
fn from(value: $ty) -> Self {
Self::Static(value.into())
}
}
)*
};
}

macro_rules! impl_into_self {
($($ty:ty),*) => {
$(
impl From<$ty> for MaybeDyn<$ty> {
fn from(value: $ty) -> Self {
Self::Static(value)
}
}
)*
};
}

/// A possibly dynamic string value.
pub type MaybeDynString = MaybeDyn<Cow<'static, str>>;
impl_from_maybe_dyn!(MaybeDynString => &'static str, String);

/// A possibly dynamic boolean value.
pub type MaybeDynBool = MaybeDyn<bool>;

/// A possibly dynamic [`JsValue`].
pub type MaybeDynJsValue = MaybeDyn<JsValue>;
impl_from_maybe_dyn!(
MaybeDynJsValue =>
String,
bool,
i8,
i16,
i32,
i64,
i128,
isize,
u8,
u16,
u32,
u64,
u128,
usize,
f32,
f64
);
impl_into_self!(Cow<'static, str>, bool, JsValue);

impl_into_self!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64);
68 changes: 0 additions & 68 deletions packages/sycamore-web/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,74 +99,6 @@ impl AttributeValue for MaybeDynJsValue {
}
}

/// Represents a value that can be either static or dynamic.
pub enum MaybeDyn<T> {
Static(T),
Dynamic(Box<dyn FnMut() -> T>),
}

impl<T> MaybeDyn<T> {
/// Evaluate the value by consuming itself.
pub fn evaluate(self) -> T {
match self {
Self::Static(value) => value,
Self::Dynamic(mut f) => f(),
}
}
}

impl<T, F: FnMut() -> U + 'static, U: Into<T>> From<F> for MaybeDyn<T> {
fn from(mut f: F) -> Self {
Self::Dynamic(Box::new(move || f().into()))
}
}

/// A possibly dynamic string value.
pub type MaybeDynString = MaybeDyn<Cow<'static, str>>;

/// A possibly dynamic boolean value.
pub type MaybeDynBool = MaybeDyn<bool>;

/// A possibly dynamic [`JsValue`].
pub type MaybeDynJsValue = MaybeDyn<JsValue>;

macro_rules! impl_from_maybe_dyn {
($struct:ty => $($ty:ty),*) => {
$(
impl From<$ty> for $struct {
fn from(value: $ty) -> Self {
Self::Static(value.into())
}
}
)*
};
}

impl_from_maybe_dyn!(MaybeDynString => &'static str, String, Cow<'static, str>);

impl_from_maybe_dyn!(MaybeDynBool => bool);

impl_from_maybe_dyn!(
MaybeDynJsValue =>
JsValue,
String,
bool,
i8,
i16,
i32,
i64,
i128,
isize,
u8,
u16,
u32,
u64,
u128,
usize,
f32,
f64
);

thread_local! {
/// Whether we are in hydration mode or not.
pub(crate) static IS_HYDRATING: Cell<bool> = const { Cell::new(false) };
Expand Down

0 comments on commit 96a756b

Please sign in to comment.