Skip to content

Instantly share code, notes, and snippets.

@metatoaster
Last active February 28, 2026 11:23
Show Gist options
  • Select an option

  • Save metatoaster/6f5ef5ac7f8aa08ed7a598d056bef236 to your computer and use it in GitHub Desktop.

Select an option

Save metatoaster/6f5ef5ac7f8aa08ed7a598d056bef236 to your computer and use it in GitHub Desktop.
mod traits {
use super::*;
// optionally seal this trait, and that this diagnostic message sometimes
// fail to trigger.
#[diagnostic::on_unimplemented(
label = "incomplete `Conf`",
note = "ensure that `.app()`, `.shell()`, and `.state()` are provided \
with the required values"
)]
pub trait Conf {
fn apply(self, consumer: &Consumer);
}
}
/// ```compile_fail
/// # use playground::*;
/// Consumer::default()
/// .configure(Conf::default()
/// .app(|| {})
/// );
/// ```
///
/// ```compile_fail
/// # use playground::*;
/// Consumer::default()
/// .configure(Conf::default()
/// .state(())
/// .app(|| {})
/// .shell(|_s: String| {})
/// );
/// ```
///
/// ```rust
/// # use playground::*;
/// Consumer::default()
/// .configure(Conf::default()
/// .state(())
/// .app(|| {})
/// .shell(|_s: ()| {})
/// );
/// ```
pub struct Conf<APP, SH, S> {
app: Option<APP>,
shell: Option<SH>,
state: Option<S>,
}
impl Default for Conf<(), (), ()> {
fn default() -> Self {
Self {
app: None,
shell: None,
state: None,
}
}
}
impl<APP, SH, S, IV1, IV2> traits::Conf for Conf<APP, SH, S>
where
APP: Fn() -> IV1 + Clone + Send + Sync + 'static,
SH: Fn(S) -> IV2 + Clone + Send + Sync + 'static,
S: Clone + Send + Sync + 'static,
IV1: IntoView + 'static,
IV2: IntoView + 'static,
{
fn apply(self, _consumer: &Consumer) {
// consume the builder
let _app = self.app.expect("an `App` should have been configured");
let _shell = self.shell.expect("a `shell` should have been configured");
let _state = self.state.expect("a `state` should have been configured");
// apply whatever the above to the consumer
}
}
impl<APP, SH, S> Conf<APP, SH, S> {
pub fn app<APP2, IV>(
self,
app: APP2,
) -> Conf<APP2, SH, S>
where
APP2: Fn() -> IV + Clone + Send + Sync + 'static,
IV: IntoView + 'static,
{
Conf {
app: Some(app),
shell: self.shell,
state: self.state,
}
}
pub fn shell<SH2, S2, IV>(
self,
shell: SH2,
) -> Conf<APP, SH2, S>
where
SH2: Fn(S2) -> IV + Clone + Send + Sync + 'static,
IV: IntoView + 'static,
S2: Clone + Send + Sync + 'static,
{
Conf {
app: self.app,
shell: Some(shell),
state: self.state,
}
}
pub fn state<S2>(
self,
state: S2,
) -> Conf<APP, SH, S2>
where
S2: Clone + Send + Sync + 'static,
{
Conf {
app: self.app,
shell: self.shell,
state: Some(state)
}
}
}
pub trait IntoView {}
impl IntoView for () {}
#[derive(Default)]
pub struct Consumer {}
impl Consumer {
pub fn configure(&self, conf: impl traits::Conf) {
conf.apply(&self)
}
}
#[test]
fn compiles() {
Consumer::default()
.configure(Conf::default()
.state(())
.app(|| {})
.shell(|_s: ()| {})
);
Consumer::default()
.configure(Conf::default()
.app(|| {})
.shell(|_s: String| {})
.state(String::from("hello world"))
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment