Last active
February 28, 2026 11:23
-
-
Save metatoaster/6f5ef5ac7f8aa08ed7a598d056bef236 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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