├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── static-events ├── Cargo.toml ├── src │ ├── events.rs │ ├── events_types.rs │ ├── handlers.rs │ ├── lib.rs │ └── private.rs └── tests │ ├── async_events.rs │ └── type_params.rs ├── static-events_derive ├── Cargo.toml └── src │ └── lib.rs └── static-events_internals ├── Cargo.toml └── src ├── common.rs ├── derive.rs ├── errors.rs ├── handlers.rs ├── lib.rs └── utils.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.idea 3 | /*.iml 4 | /Cargo.lock 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | "static-events", 5 | "static-events_derive", 6 | "static-events_internals", 7 | ] 8 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Lymia Aluysia 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A generic zero-cost event handler system. Event dispatches should get compiled down to a 2 | plain function that executes all handlers involved with no dynamic dispatches. 3 | 4 | This library is nightly-only as it relies on specialization. 5 | 6 | [See the documentation for more information.](https://docs.rs/static-events/) 7 | 8 | This library is dual licenced under the MIT and Apache 2.0 licenses. 9 | -------------------------------------------------------------------------------- /static-events/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "static-events" 3 | version = "0.2.0" 4 | authors = ["Lymia Aluysia "] 5 | edition = "2018" 6 | 7 | description = "A library for creating zero-cost event systems." 8 | keywords = ["events", "static"] 9 | categories = ["rust-patterns"] 10 | 11 | documentation = "https://docs.rs/static-events/" 12 | repository = "https://github.com/Lymia/static-events" 13 | readme = "../README.md" 14 | 15 | license = "MIT/Apache-2.0" 16 | 17 | [features] 18 | std = ["parking_lot"] 19 | default = ["std"] 20 | 21 | [dependencies] 22 | parking_lot = { version = "0.10.0", optional = true } 23 | static-events_derive = { version = "0.1.0", path = "../static-events_derive" } 24 | 25 | [dev-dependencies] 26 | futures = "0.3" 27 | -------------------------------------------------------------------------------- /static-events/src/events.rs: -------------------------------------------------------------------------------- 1 | //! The underlying traits used to define events. 2 | //! 3 | //! # Defining events 4 | //! 5 | //! An hierarchy of helper traits exists for defining event types: 6 | //! * [`Event`] exposes the full power of the events system, and is required for events that 7 | //! only pass part of the dispatch state into handlers, or expect handlers to return a different 8 | //! type than usual. 9 | //! * [`SimpleInterfaceEvent`] is required for events for event that return a different type from 10 | //! their internal state. 11 | //! * [`SimpleEvent`] is the most general common type of event. It directly returns its internal 12 | //! state to the caller. 13 | //! * [`VoidEvent`] is the simplest type of event, that maintains no state and returns no value. 14 | //! 15 | //! In addition, helper macros exist to help define specific types of common events; 16 | //! * [`simple_event!`] for events that directly return their state to the caller, or do not 17 | //! use state at all. 18 | //! * [`failable_event!`] for events that can fail and return [`Result`]s. 19 | 20 | /// The result of a stage of a event handler. 21 | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] 22 | pub enum EventResult { 23 | /// Continues normally. 24 | EvOk, 25 | /// Cancels further event handlers from processing the current phase of the current event. 26 | /// (i.e. `init`, `check`, `before_event`, `on_event`, and `after_event`) 27 | EvCancelStage, 28 | /// Cancels further event handlers from processing the current event. 29 | EvCancel, 30 | } 31 | impl Default for EventResult { 32 | fn default() -> Self { 33 | EventResult::EvOk 34 | } 35 | } 36 | impl From<()> for EventResult { 37 | fn from(_: ()) -> Self { 38 | EventResult::EvOk 39 | } 40 | } 41 | #[allow(unused_imports)] use self::EventResult::EvOk; // for documentation 42 | 43 | /// The generic trait that defines an event. 44 | pub trait Event: Sized { 45 | /// The type of state stored on the stack during event dispatch. 46 | /// 47 | /// A value of this type is constructed at the start of event dispatch by calling the 48 | /// `starting_state` method. 49 | type State: Send; 50 | /// The type of the state that event handlers receive. This can be distinct from `State`, 51 | /// allowing a part of the state to be hidden from event handlers. 52 | /// 53 | /// This is derived from `State` by calling the `borrow_state` method. 54 | /// 55 | /// Note that the full `State` value is still exposed to [`Events`]. 56 | type StateArg; 57 | /// The return value of an event handler's methods. 58 | /// 59 | /// After an event handler is called, whether default or not, `to_event_result` is called 60 | /// to decide how to proceed with event dispatch and update the state according to its 61 | /// return value. 62 | type MethodRetVal; 63 | /// The type returned to the method that originally started the event dispatch. 64 | /// 65 | /// This is derived from the internal state by calling `to_return_value` 66 | type RetVal; 67 | 68 | /// Constructs the state maintained during an event dispatch. 69 | fn starting_state(&self) -> Self::State; 70 | /// Borrows the part of the state that is passed to event dispatches. 71 | fn borrow_state<'a>(&self, _: &'a mut Self::State) -> &'a mut Self::StateArg; 72 | /// Extracts an [`EventResult`] and updates state based on an event handler's return value. 73 | fn to_event_result(&self, _: &mut Self::State, _: Self::MethodRetVal) -> EventResult; 74 | /// Derives the output of the event dispatch from the current state. 75 | fn to_return_value(self, _: Self::State) -> Self::RetVal; 76 | } 77 | 78 | /// A trait for events that can be used asynchronously. 79 | pub trait AsyncEvent: Event + Send + Sized { } 80 | impl AsyncEvent for T { } 81 | 82 | /// An [`Event`] that does not use the `MethodRetVal` or `StateArg` mechanisms. 83 | pub trait SimpleInterfaceEvent: Sized { 84 | /// The type of state stored on the stack during event dispatch, and passed to event handlers. 85 | /// 86 | /// A value of this type is constructed at the start of event dispatch by calling the 87 | /// `starting_state` method. 88 | type State: Send; 89 | /// The ultimate return type of a call to this event. 90 | type RetVal; 91 | 92 | /// Constructs the state maintained during an event dispatch. 93 | fn starting_state(&self) -> Self::State; 94 | /// Derives the output of the event dispatch from the current state. 95 | fn to_return_value(self, _: Self::State) -> Self::RetVal; 96 | } 97 | impl Event for T { 98 | type State = T::State; 99 | type StateArg = T::State; 100 | type MethodRetVal = EventResult; 101 | type RetVal = T::RetVal; 102 | 103 | fn starting_state(&self) -> T::State { 104 | SimpleInterfaceEvent::starting_state(self) 105 | } 106 | fn borrow_state<'a>(&self, state: &'a mut T::State) -> &'a mut T::State { 107 | state 108 | } 109 | fn to_event_result(&self, _: &mut T::State, result: EventResult) -> EventResult { 110 | result 111 | } 112 | fn to_return_value(self, state: T::State) -> T::RetVal { 113 | SimpleInterfaceEvent::to_return_value(self, state) 114 | } 115 | } 116 | 117 | /// An [`Event`] that returns `State` directly when called. 118 | pub trait SimpleEvent: Sized { 119 | /// The type of the state maintained between event handler calls and returned from this event. 120 | /// 121 | /// A value of this type is constructed at the start of event dispatch by calling the 122 | /// `starting_state` method. 123 | type State: Send; 124 | /// Constructs the state maintained during an event dispatch. 125 | fn starting_state(&self) -> Self::State; 126 | } 127 | impl SimpleInterfaceEvent for T { 128 | type State = T::State; 129 | type RetVal = T::State; 130 | 131 | fn starting_state(&self) -> T::State { 132 | SimpleEvent::starting_state(self) 133 | } 134 | fn to_return_value(self, state: T::State) -> T::State { 135 | state 136 | } 137 | } 138 | 139 | /// An [`Event`] that returns no value and stores no state. 140 | pub trait VoidEvent: Sized { } 141 | impl SimpleEvent for T { 142 | type State = (); 143 | fn starting_state(&self) { } 144 | } 145 | -------------------------------------------------------------------------------- /static-events/src/events_types.rs: -------------------------------------------------------------------------------- 1 | // TODO: Document `[T: Bounds]` syntax. 2 | 3 | // for documentation 4 | #[allow(unused_imports)] use crate::*; 5 | 6 | /// A helper macro to define events that directly return their state with no further processing. 7 | /// 8 | /// The first argument is the event type, the second is the type of the event state, and the 9 | /// third is the starting value of the event state. 10 | /// 11 | /// If the third argument is omitted, it is assumed to be [`Default::default`]. If the second 12 | /// argument is omitted, it assumed to be `()`. 13 | /// 14 | /// Event handlers for events defined using this macro should return either an [`EventResult`] 15 | /// or `()`. 16 | /// 17 | /// # Example 18 | /// 19 | /// Declaration: 20 | /// 21 | /// ``` 22 | /// use static_events::prelude_sync::*; 23 | /// 24 | /// pub struct MyEventA(u32); 25 | /// simple_event!(MyEventA); 26 | /// 27 | /// pub struct MyEventB(u32); 28 | /// simple_event!(MyEventB, u32); 29 | /// 30 | /// pub struct MyEventC(T); 31 | /// simple_event!([T: Send] MyEventC, u32, 42); 32 | /// ``` 33 | /// 34 | /// Usage: 35 | /// ``` 36 | /// use static_events::prelude_sync::*; 37 | /// 38 | /// # pub struct MyEventB(u32); simple_event!(MyEventB, u32); 39 | /// #[derive(Events)] 40 | /// struct MyEventHandler; 41 | /// 42 | /// #[events_impl] 43 | /// impl MyEventHandler { 44 | /// #[event_handler] 45 | /// fn handle_event(ev: &MyEventB, state: &mut u32) { 46 | /// *state = ev.0 * ev.0; 47 | /// } 48 | /// } 49 | /// 50 | /// let handler = Handler::new(MyEventHandler); 51 | /// assert_eq!(handler.dispatch(MyEventB(12)), 144); 52 | /// ``` 53 | #[macro_export] 54 | macro_rules! simple_event { 55 | ([$($bounds:tt)*] $ev:ty $(,)?) => { 56 | simple_event!([$($bounds)*] $ev, (), ()); 57 | }; 58 | ([$($bounds:tt)*] $ev:ty, $state:ty $(,)?) => { 59 | simple_event!([$($bounds)*] $ev, $state, Default::default()); 60 | }; 61 | ([$($bounds:tt)*] $ev:ty, $state:ty, $starting_val:expr $(,)?) => { 62 | impl <$($bounds)*> $crate::events::SimpleEvent for $ev { 63 | type State = $state; 64 | fn starting_state(&self) -> $state { 65 | $starting_val 66 | } 67 | } 68 | }; 69 | ($ev:ty $(,)?) => { 70 | simple_event!([] $ev); 71 | }; 72 | ($ev:ty, $state:ty $(,)?) => { 73 | simple_event!([] $ev, $state); 74 | }; 75 | ($ev:ty, $state:ty, $starting_val:expr $(,)?) => { 76 | simple_event!([] $ev, $state, $starting_val); 77 | }; 78 | } 79 | 80 | /// A helper macro to define events that return themselves as output. 81 | /// 82 | /// Event handlers for events defined using this macro should return either an [`EventResult`] 83 | /// or `()`. 84 | /// 85 | /// # Example 86 | /// 87 | /// Declaration: 88 | /// 89 | /// ``` 90 | /// use static_events::prelude_sync::*; 91 | /// pub struct MyEvent(u32); 92 | /// self_event!(MyEvent); 93 | /// ``` 94 | /// 95 | /// Usage: 96 | /// 97 | /// ``` 98 | /// use static_events::prelude_sync::*; 99 | /// 100 | /// # #[derive(PartialEq, Debug)] pub struct MyEvent(u32); 101 | /// # self_event!(MyEvent); 102 | /// #[derive(Events)] 103 | /// struct MyEventHandler; 104 | /// 105 | /// #[events_impl] 106 | /// impl MyEventHandler { 107 | /// #[event_handler] 108 | /// fn handle_event(ev: &mut MyEvent) { 109 | /// ev.0 *= 10; 110 | /// } 111 | /// } 112 | /// 113 | /// let handler = Handler::new(MyEventHandler); 114 | /// assert_eq!(handler.dispatch(MyEvent(10)), MyEvent(100)); 115 | /// ``` 116 | #[macro_export] 117 | macro_rules! self_event { 118 | ([$($bounds:tt)*] $ev:ty $(,)?) => { 119 | impl <$($bounds)*> $crate::events::SimpleInterfaceEvent for $ev { 120 | type State = (); 121 | type RetVal = $ev; 122 | fn starting_state(&self) { } 123 | fn to_return_value(self, _: ()) -> $ev { 124 | self 125 | } 126 | } 127 | }; 128 | ($ev:ty $(,)?) => { 129 | self_event!([] $ev); 130 | }; 131 | } 132 | 133 | /// A helper macro to define events that can fail. 134 | /// 135 | /// The first argument is the event type, the second is the type of the event state, and the 136 | /// third is the type of the error type, and the fourth is the starting value of the initial 137 | /// state. 138 | /// 139 | /// If the fourth argument is omitted, it is assumed to be [`Default::default`]. 140 | /// 141 | /// Handlers for events defined with this macro return a `Result` or a 142 | /// `Result<(), E>`, and return errors to the caller of the event, cancelling all further handlers. 143 | /// 144 | /// # Example 145 | /// 146 | /// Declaration: 147 | /// 148 | /// ``` 149 | /// use static_events::prelude_sync::*; 150 | /// # use std::io; 151 | /// 152 | /// pub struct MyEvent(u32); 153 | /// failable_event!(MyEvent, u32, io::Error); 154 | /// 155 | /// pub struct MyEvent2(T); 156 | /// failable_event!([T: Send] MyEvent2, u32, io::Error); 157 | /// ``` 158 | /// 159 | /// Usage: 160 | /// 161 | /// ``` 162 | /// use static_events::prelude_sync::*; 163 | /// # use std::io; 164 | /// # pub struct MyEvent(u32); failable_event!(MyEvent, u32, io::Error); 165 | /// 166 | /// #[derive(Events)] 167 | /// struct MyEventHandler; 168 | /// 169 | /// #[events_impl] 170 | /// impl MyEventHandler { 171 | /// #[event_handler] 172 | /// fn handle_event(ev: &MyEvent, state: &mut u32) -> io::Result<()> { 173 | /// if ev.0 > 50 { Err(io::Error::new(io::ErrorKind::Other, "too large!"))? } 174 | /// *state = ev.0 * ev.0; 175 | /// Ok(()) 176 | /// } 177 | /// } 178 | /// 179 | /// let handler = Handler::new(MyEventHandler); 180 | /// assert_eq!(handler.dispatch(MyEvent(12)).ok(), Some(144)); 181 | /// assert!(handler.dispatch(MyEvent(100)).is_err()); 182 | /// ``` 183 | #[macro_export] 184 | macro_rules! failable_event { 185 | ([$($bounds:tt)*] $ev:ty, $state:ty, $error:ty $(,)?) => { 186 | failable_event!([$($bounds)*] $ev, $state, $error, Default::default()); 187 | }; 188 | ([$($bounds:tt)*] $ev:ty, $state:ty, $error:ty, $starting_val:expr $(,)?) => { 189 | impl <$($bounds)*> $crate::events::Event for $ev { 190 | type State = $crate::private::Result<$state, $error>; 191 | type StateArg = $state; 192 | type MethodRetVal = $crate::private::FailableReturn<$error>; 193 | type RetVal = $crate::private::Result<$state, $error>; 194 | fn starting_state(&self) -> $crate::private::Result<$state, $error> { 195 | Ok($starting_val) 196 | } 197 | fn borrow_state<'__state>( 198 | &self, state: &'__state mut $crate::private::Result<$state, $error>, 199 | ) -> &'__state mut $state { 200 | state.as_mut().expect("Continuing already failed event?") 201 | } 202 | fn to_event_result( 203 | &self, state: &mut $crate::private::Result<$state, $error>, 204 | result: $crate::private::FailableReturn<$error>, 205 | ) -> $crate::events::EventResult { 206 | match result.0 { 207 | Ok(result) => result, 208 | Err(err) => { 209 | *state = Err(err); 210 | $crate::events::EventResult::EvCancel 211 | } 212 | } 213 | } 214 | fn to_return_value( 215 | self, state: $crate::private::Result<$state, $error>, 216 | ) -> $crate::private::Result<$state, $error> { 217 | state 218 | } 219 | } 220 | }; 221 | ($ev:ty, $state:ty, $error:ty $(,)?) => { 222 | failable_event!([] $ev, $state, $error, Default::default()); 223 | }; 224 | ($ev:ty, $state:ty, $error:ty, $starting_val:expr $(,)?) => { 225 | failable_event!([] $ev, $state, $error, $starting_val); 226 | }; 227 | } 228 | 229 | /// A helper macro to define events that return themselves as output and can fail. 230 | /// 231 | /// The first argument is the event type, the second is the type of error type. 232 | /// 233 | /// Event handlers for events defined using this macro should return either a 234 | /// `Result` or `Result<()>`. 235 | /// 236 | /// # Example 237 | /// 238 | /// Declaration: 239 | /// 240 | /// ``` 241 | /// # use std::io; 242 | /// use static_events::prelude_sync::*; 243 | /// pub struct MyEvent(u32); 244 | /// failable_self_event!(MyEvent, io::Error); 245 | /// ``` 246 | /// 247 | /// Usage: 248 | /// 249 | /// ``` 250 | /// use static_events::prelude_sync::*; 251 | /// 252 | /// # use std::io; 253 | /// # #[derive(PartialEq, Debug)] pub struct MyEvent(u32); 254 | /// # failable_self_event!(MyEvent, io::Error); 255 | /// #[derive(Events)] 256 | /// struct MyEventHandler; 257 | /// 258 | /// #[events_impl] 259 | /// impl MyEventHandler { 260 | /// #[event_handler] 261 | /// fn handle_event(ev: &mut MyEvent) -> io::Result<()> { 262 | /// if ev.0 > 50 { Err(io::Error::new(io::ErrorKind::Other, "too large!"))? } 263 | /// ev.0 *= ev.0; 264 | /// Ok(()) 265 | /// } 266 | /// } 267 | /// 268 | /// let handler = Handler::new(MyEventHandler); 269 | /// assert_eq!(handler.dispatch(MyEvent(12)).ok(), Some(MyEvent(144))); 270 | /// assert!(handler.dispatch(MyEvent(100)).is_err()); 271 | /// ``` 272 | #[macro_export] 273 | macro_rules! failable_self_event { 274 | ([$($bounds:tt)*] $ev:ty, $error:ty $(,)?) => { 275 | impl <$($bounds)*> $crate::events::Event for $ev { 276 | type State = ((), $crate::private::Option<$error>); 277 | type StateArg = (); 278 | type MethodRetVal = $crate::private::FailableReturn<$error>; 279 | type RetVal = $crate::private::Result<$ev, $error>; 280 | fn starting_state(&self) -> ((), $crate::private::Option<$error>) { 281 | ((), $crate::private::None) 282 | } 283 | fn borrow_state<'__state>( 284 | &self, state: &'__state mut ((), $crate::private::Option<$error>), 285 | ) -> &'__state mut () { 286 | &mut state.0 287 | } 288 | fn to_event_result( 289 | &self, state: &mut ((), $crate::private::Option<$error>), 290 | result: $crate::private::FailableReturn<$error>, 291 | ) -> $crate::events::EventResult { 292 | match result.0 { 293 | Ok(result) => result, 294 | Err(err) => { 295 | state.1 = $crate::private::Some(err); 296 | $crate::events::EventResult::EvCancel 297 | } 298 | } 299 | } 300 | fn to_return_value( 301 | self, state: ((), $crate::private::Option<$error>), 302 | ) -> $crate::private::Result<$ev, $error> { 303 | match state.1 { 304 | $crate::private::Some(v) => Err(v), 305 | $crate::private::None => Ok(self), 306 | } 307 | } 308 | } 309 | }; 310 | ($ev:ty, $error:ty $(,)?) => { 311 | failable_self_event!([] $ev, $error); 312 | }; 313 | } 314 | -------------------------------------------------------------------------------- /static-events/src/handlers.rs: -------------------------------------------------------------------------------- 1 | //! The underlying traits used to define event handlers. 2 | 3 | use crate::events::*; 4 | use std::fmt; 5 | use std::future::Future; 6 | use std::sync::Arc; 7 | use std::fmt::{Debug, Formatter}; 8 | 9 | pub(crate) mod private { 10 | pub trait Sealed { } 11 | } 12 | 13 | /// A sealed trait that marks the phases of an event. 14 | pub trait EventPhase: private::Sealed { } 15 | macro_rules! phases { 16 | ($(($name:ident, $doc:literal))*) => {$( 17 | #[doc = $doc] 18 | pub enum $name { } 19 | impl private::Sealed for $name { } 20 | impl EventPhase for $name { } 21 | )*} 22 | } 23 | phases! { 24 | (EvInit , "The first phase of event execution. Intended to be used to set up an event.") 25 | (EvCheck , "The second phase of event execution. Intended to be used to check \ 26 | conditions required for the execution of the event.") 27 | (EvBeforeEvent, "The third phase of event execution. Intended to be used for hooks that \ 28 | execute before the main actions of an event.") 29 | (EvOnEvent , "The fourth phase of event execution. Intended to be used for the main \ 30 | actions of an event.") 31 | (EvAfterEvent , "The fifth phase of event execution. Intended to be used for hooks that \ 32 | execute after the main actions of an event.") 33 | } 34 | 35 | /// Distinguisher for the actual default handler invoked by [`Handler`] 36 | pub enum DefaultHandler { } 37 | 38 | /// The base trait used to mark event dispatchers. 39 | pub trait Events: Sized + 'static { 40 | /// Gets a service from this event dispatch. 41 | fn get_service(&self) -> Option<&S>; 42 | } 43 | impl Events for Arc { 44 | fn get_service(&self) -> Option<&S> { 45 | (**self).get_service() 46 | } 47 | } 48 | 49 | /// The base trait used to mark asynchronous event dispatchers. 50 | pub trait AsyncEvents: Events + Sync + Send { } 51 | impl AsyncEvents for Arc { } 52 | 53 | pub use static_events_derive::*; 54 | 55 | /// A trait that defines a phase of handling a particular event. 56 | /// 57 | /// # Type parameters 58 | /// * `'a`: The lifetime this event handler is for. 59 | /// * `E`: The type of event handler this event is being dispatched into. 60 | /// * `Ev`: The event this handler is for. 61 | /// * `P`: The event phase this handler is for. 62 | /// * `D`: A phantom type used internally by the `#[events_impl]` macro to allow overlapping event 63 | /// handler implementations. This defaults to [`DefaultHandler`], which is what [`Handler`] 64 | /// actually invokes events with. 65 | pub trait EventHandler<'a, E: Events, Ev: Event + 'a, P: EventPhase, D = DefaultHandler>: Events { 66 | /// `true` if this `EventHandler` actually does anything. This is used for optimizations. 67 | const IS_IMPLEMENTED: bool = true; 68 | 69 | /// `true` if this `EventHandler` contains asynchronous handlers. This is used for 70 | /// optimizations and early panicking. 71 | const IS_ASYNC: bool = false; 72 | 73 | /// Runs a phase of this event. 74 | fn on_phase( 75 | &'a self, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 76 | ) -> EventResult; 77 | } 78 | impl < 79 | 'a, E: Events, Ev: Event + 'a, P: EventPhase, D, T: EventHandler<'a, E, Ev, P, D> 80 | > EventHandler<'a, E, Ev, P, D> for Arc { 81 | const IS_IMPLEMENTED: bool = T::IS_IMPLEMENTED; 82 | const IS_ASYNC: bool = T::IS_ASYNC; 83 | fn on_phase( 84 | &'a self, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 85 | ) -> EventResult { 86 | (**self).on_phase(target, ev, state) 87 | } 88 | } 89 | 90 | /// A trait that defines a phase of handling a particular event asynchronously. 91 | pub trait AsyncEventHandler< 92 | 'a, E: AsyncEvents, Ev: Event + 'a, P: EventPhase, D = DefaultHandler, 93 | > : AsyncEvents + EventHandler<'a, E, Ev, P, D> { 94 | /// The type of the future returned by `on_phase_async`. 95 | type FutureType: Future + Send + 'a; 96 | 97 | /// Runs a phase of this event asynchronously. 98 | /// 99 | /// This function should only be called if `IS_IMPLEMENTED` and `IS_ASYNC` are `true`. 100 | fn on_phase_async( 101 | &'a self, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 102 | ) -> Self::FutureType; 103 | } 104 | impl < 105 | 'a, E: AsyncEvents, Ev: Event + 'a, P: EventPhase, D, T: AsyncEventHandler<'a, E, Ev, P, D>, 106 | > AsyncEventHandler<'a, E, Ev, P, D> for Arc { 107 | type FutureType = T::FutureType; 108 | fn on_phase_async( 109 | &'a self, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 110 | ) -> Self::FutureType { 111 | (**self).on_phase_async(target, ev, state) 112 | } 113 | } 114 | 115 | 116 | /// A wrapper for [`Events`] that allows dispatching events into them. 117 | #[derive(Default)] 118 | pub struct Handler(Arc>); 119 | #[derive(Default)] 120 | struct HandlerData { 121 | events: E, 122 | } 123 | impl Handler { 124 | /// Wraps an [`Events`] to allow dispatching events into it. 125 | pub fn new(e: E) -> Self { 126 | Handler(Arc::new(HandlerData { 127 | events: e, 128 | })) 129 | } 130 | 131 | /// Retrieves a service from an [`Events`]. 132 | /// 133 | /// # Panics 134 | /// 135 | /// This function will panic if the service does not exist. 136 | /// 137 | /// # Example 138 | /// ```rust 139 | /// use static_events::prelude_sync::*; 140 | /// 141 | /// #[derive(Eq, PartialEq, Debug)] 142 | /// struct TestService; 143 | /// 144 | /// #[derive(Events)] 145 | /// struct EventHandler(#[service] TestService); 146 | /// 147 | /// let handler = Handler::new(EventHandler(TestService)); 148 | /// assert_eq!(handler.get_service::(), &TestService); 149 | /// ``` 150 | pub fn get_service(&self) -> &S { 151 | match self.0.events.get_service() { 152 | Some(v) => v, 153 | None => missing_service::(), 154 | } 155 | } 156 | 157 | /// Retrieves a service that may or may not exist from an [`Events`]. 158 | /// 159 | /// # Example 160 | /// ```rust 161 | /// use static_events::prelude_sync::*; 162 | /// 163 | /// #[derive(Eq, PartialEq, Debug)] 164 | /// struct TestService; 165 | /// 166 | /// #[derive(Events)] 167 | /// struct EventHandler(#[service] TestService); 168 | /// 169 | /// let handler = Handler::new(EventHandler(TestService)); 170 | /// assert_eq!(handler.get_service_opt::(), Some(&TestService)); 171 | /// ``` 172 | pub fn get_service_opt(&self) -> Option<&S> { 173 | self.0.events.get_service() 174 | } 175 | 176 | /// Downcasts this handler into a particular concrete handler type. 177 | pub fn downcast_ref(&self) -> Option<&Handler> { 178 | crate::private::CheckDowncast::>::downcast_ref(self) 179 | } 180 | 181 | /// Dispatches an event synchronously. 182 | /// 183 | /// Any asynchronous event handlers will cause this function to panic. 184 | pub fn dispatch_sync(&self, mut ev: Ev) -> Ev::RetVal { 185 | if crate::private::is_any_async::() { 186 | crate::private::async_in_sync(); 187 | } 188 | 189 | let mut state = ev.starting_state(); 190 | 'outer: loop { 191 | macro_rules! do_phase { 192 | ($phase:ident) => { 193 | if crate::private::is_implemented::() { 194 | match crate::private::on_phase::( 195 | &self.0.events, self, &mut ev, &mut state 196 | ) { 197 | EventResult::EvOk | EventResult::EvCancelStage => { } 198 | EventResult::EvCancel => break 'outer, 199 | } 200 | } 201 | } 202 | } 203 | do_phase!(EvInit); 204 | do_phase!(EvCheck); 205 | do_phase!(EvBeforeEvent); 206 | do_phase!(EvOnEvent); 207 | do_phase!(EvAfterEvent); 208 | break 'outer 209 | } 210 | ev.to_return_value(state) 211 | } 212 | 213 | /// Returns the number of active references to this `Handler`. 214 | pub fn refcount(&self) -> usize { 215 | Arc::strong_count(&self.0) 216 | } 217 | } 218 | impl Handler { 219 | /// Dispatches an event asynchronously. This future is bounded by the lifetime of `&self` 220 | /// and the event. 221 | /// 222 | /// Any synchronous events are run immediately as part of the [`Future::poll`] execution. 223 | /// 224 | /// This method requires that the [`Events`] type parameter is [`Sync`]. 225 | pub fn dispatch_async<'a, Ev: AsyncEvent + 'a>( 226 | &'a self, mut ev: Ev, 227 | ) -> impl Future + 'a { 228 | async move { 229 | let mut state = ev.starting_state(); 230 | 'outer: loop { 231 | macro_rules! do_phase { 232 | ($phase:ident) => { 233 | if crate::private::is_implemented::() { 234 | let result = 235 | if crate::private::is_async::() { 236 | crate::private::on_phase_async::< 237 | E, E, Ev, $phase, DefaultHandler, 238 | >( 239 | &self.0.events, self, &mut ev, &mut state 240 | ).await 241 | } else { 242 | crate::private::on_phase::( 243 | &self.0.events, self, &mut ev, &mut state 244 | ) 245 | }; 246 | match result { 247 | EventResult::EvOk | EventResult::EvCancelStage => { } 248 | EventResult::EvCancel => break 'outer, 249 | } 250 | } 251 | } 252 | } 253 | do_phase!(EvInit); 254 | do_phase!(EvCheck); 255 | do_phase!(EvBeforeEvent); 256 | do_phase!(EvOnEvent); 257 | do_phase!(EvAfterEvent); 258 | break 'outer 259 | } 260 | ev.to_return_value(state) 261 | } 262 | } 263 | 264 | /// Dispatches an event asynchronously. 265 | /// 266 | /// Any synchronous events are run immediately as part of the [`Future::poll`] execution. 267 | /// 268 | /// This method requires that the [`Events`] type parameter is [`Sync`]. 269 | pub fn dispatch_async_static( 270 | &self, ev: Ev, 271 | ) -> impl Future + 'static { 272 | let this = self.clone(); 273 | async move { 274 | this.dispatch_async(ev).await 275 | } 276 | } 277 | } 278 | impl Clone for Handler { 279 | fn clone(&self) -> Self { 280 | Handler(self.0.clone()) 281 | } 282 | } 283 | impl Debug for Handler { 284 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 285 | f.debug_struct("Handler") 286 | .field("events", &self.0.events) 287 | .finish() 288 | } 289 | } 290 | 291 | #[inline(never)] 292 | #[cold] 293 | fn missing_service() -> ! { 294 | panic!("Missing service: {}", std::any::type_name::()) 295 | } 296 | -------------------------------------------------------------------------------- /static-events/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(const_fn, specialization, type_alias_impl_trait, allow_internal_unstable, decl_macro)] 2 | 3 | // TODO: Implement filtering of some kind on events, and state between phases. 4 | // TODO: Document how to set the phase of an event handler. 5 | 6 | //! A generic zero-cost asynchronous event handler system built on compile-time magic. 7 | //! 8 | //! Synchronous event dispatches should get compiled down to a plain function that executes all 9 | //! handlers involved with no dynamic dispatches. Asynchrnous event dispatches should be 10 | //! similarily compile down to a relatively optimized future 11 | //! 12 | //! This crate relies on many unstable features, and can only be used on nightly versions of Rust. 13 | //! 14 | //! # Basic model 15 | //! 16 | //! Events handlers can be any type that implements [`Event`], and the type of the event itself 17 | //! is used to distinguish different kinds of events. For detailed information on defining events, 18 | //! see the [`events`] module. These handlers are wrapped in a [`Handler`] to allow events to be 19 | //! dispatched into them. 20 | //! 21 | //! [`Events`] is implemented using `#[derive(Events)]`. This can be paired with an `impl` block 22 | //! marked with an `#[events_impl]` annotation, which is used to actually defined the handlers 23 | //! used by the event handler. 24 | //! 25 | //! # Event dispatch 26 | //! 27 | //! Events dispatches behave like functions built up from individual event handlers called in 28 | //! sequence. They take an event, and return a value (which may simply be `()`). 29 | //! 30 | //! Event dispatch proceeds in multiple phases, each of which can have its own each event handlers 31 | //! attached to them: 32 | //! [`EvInit`], [`EvCheck`], [`EvBeforeEvent`], [`EvOnEvent`], and [`EvAfterEvent`] 33 | //! 34 | //! The exact signature of the functions event handlers are built up of are defined by the 35 | //! particular [`Event`] trait implementation for the event in question. 36 | //! 37 | //! # Defining event handlers 38 | //! 39 | //! Event handlers are defined by adding an `#[derive(Events)]` annotation. The event handlers's 40 | //! response to various events is defined inside an impl block marked with `#[events_impl]`. 41 | //! Any function in such an impl block marked with `#[event_handler]` will be called when an 42 | //! event of an approprate type is passed into the corresponding [`Events`]. 43 | //! 44 | //! These methods have parameters in the following order: a `&self` parameter, an 45 | //! `&Handler` parameter, a mutable borrow of the event value, and a mutable 46 | //! borrow of the event dispatch state. 47 | //! 48 | //! (e.g. `&self, target: &impl EventDispatch, ev: &mut MyEvent, state: &mut MyEventState`) 49 | //! 50 | //! Each parameter except the event value itself are optional, and the method may accept `ev` 51 | //! or `state` by immutable borrows instead. 52 | //! 53 | //! Example: 54 | //! ``` 55 | //! use static_events::prelude_sync::*; 56 | //! 57 | //! struct MyEvent(u32); 58 | //! simple_event!(MyEvent, u32, 0); 59 | //! 60 | //! #[derive(Events, Default)] 61 | //! struct MyEventHandler; 62 | //! 63 | //! #[events_impl] 64 | //! impl MyEventHandler { 65 | //! #[event_handler] 66 | //! fn handle_event(ev: &MyEvent, i: &mut u32) { 67 | //! *i += ev.0; 68 | //! } 69 | //! } 70 | //! 71 | //! let handler = Handler::new(MyEventHandler); 72 | //! assert_eq!(handler.dispatch(MyEvent(42)), 42); 73 | //! ``` 74 | //! 75 | //! Fields inside the [`Events`] can be marked with `#[subhandler]` to cause any events to be 76 | //! passed on to another event handler: 77 | //! ``` 78 | //! use static_events::prelude_sync::*; 79 | //! 80 | //! # struct MyEvent(u32); simple_event!(MyEvent, u32, 0); 81 | //! # #[derive(Default)] struct MyEventHandler; 82 | //! # #[derive(Events)] #[events(impl_on_external = "MyEventHandler")] struct MyEventHandler2; 83 | //! # #[events_impl] impl MyEventHandler { 84 | //! # #[event_handler] fn handle_event(ev: &MyEvent, i: &mut u32) { 85 | //! # *i += ev.0; 86 | //! # } 87 | //! # } 88 | //! // events are defined as in the previous example 89 | //! 90 | //! #[derive(Events, Default)] 91 | //! struct MyOtherEventHandler; 92 | //! 93 | //! #[events_impl] 94 | //! impl MyOtherEventHandler { 95 | //! #[event_handler] 96 | //! fn handle_event(ev: &MyEvent, i: &mut u32) { 97 | //! *i *= ev.0; 98 | //! } 99 | //! } 100 | //! 101 | //! #[derive(Events, Default)] 102 | //! struct SquaringEventHandler { 103 | //! #[subhandler] evh_a: MyEventHandler, 104 | //! #[subhandler] evh_b: MyOtherEventHandler, 105 | //! } 106 | //! 107 | //! let handler = Handler::new(SquaringEventHandler::default()); 108 | //! assert_eq!(handler.dispatch(MyEvent(9)), 81); 109 | //! ``` 110 | //! 111 | //! # Async Handlers 112 | //! 113 | //! Asynchronous handlers can be defined much the same as synchronous event handlers. The interface 114 | //! is the same, simply import `static_events::prelude_async` instead of 115 | //! `static_events::prelude_sync`. 116 | //! 117 | //! Example: 118 | //! ``` 119 | //! use static_events::prelude_async::*; 120 | //! 121 | //! struct MyEvent(u32); 122 | //! simple_event!(MyEvent, u32, 0); 123 | //! 124 | //! #[derive(Events, Default)] 125 | //! struct MyEventHandler; 126 | //! 127 | //! #[events_impl] 128 | //! impl MyEventHandler { 129 | //! #[event_handler] 130 | //! fn handle_event(ev: &MyEvent, i: &mut u32) { 131 | //! *i += ev.0; 132 | //! } 133 | //! } 134 | //! 135 | //! let handler = Handler::new(MyEventHandler); 136 | //! assert_eq!(futures::executor::block_on(handler.dispatch_async(MyEvent(42))), 42); 137 | //! ``` 138 | //! 139 | //! # Limitations 140 | //! 141 | //! A fundamental limitation to this approach is that event handlers cannot be dynamically added 142 | //! or removed at runtime, and sets of handlers can only be defined at compile-time. 143 | //! 144 | //! As event handlers are passed around using immutable pointers, locking or cells must be used to 145 | //! store state. 146 | 147 | mod events_types; 148 | pub use crate::events_types::*; 149 | 150 | pub mod events; 151 | pub mod handlers; 152 | 153 | // Fixes for documentation. 154 | #[allow(unused_imports)] use std::fmt::Debug; 155 | #[allow(unused_imports)] use events::*; 156 | 157 | #[doc(hidden)] 158 | /// This module is used by static-events_derive, and is not stable API. 159 | pub mod private; 160 | 161 | mod prelude_common { 162 | pub use crate::events::{Event, EventResult}; 163 | pub use crate::events::EventResult::*; 164 | pub use crate::handlers::{Handler, event_handler}; 165 | pub use crate::handlers::{EvInit, EvCheck, EvBeforeEvent, EvOnEvent, EvAfterEvent}; 166 | pub use crate::{simple_event, self_event, failable_event, failable_self_event}; 167 | } 168 | mod prelude_private { 169 | use crate::handlers::*; 170 | pub trait Sealed { } 171 | impl Sealed for Handler { } 172 | } 173 | 174 | /// A module containing useful imports for synchronous applications. 175 | pub mod prelude_sync { 176 | pub use crate::prelude_common::*; 177 | pub use crate::handlers::{Events, events_impl}; 178 | 179 | /// A helper extension trait for allowing `Handler::dispatch` as an alias to `dispatch_sync`. 180 | pub trait HandlerDispatchExt: crate::prelude_private::Sealed { 181 | fn dispatch(&self, ev: Ev) -> Ev::RetVal; 182 | } 183 | impl HandlerDispatchExt for Handler { 184 | fn dispatch(&self, ev: Ev) -> Ev::RetVal { 185 | self.dispatch_sync(ev) 186 | } 187 | } 188 | } 189 | 190 | /// A module containing useful imports for asynchronous applications. 191 | #[allow(non_camel_case_types)] 192 | pub mod prelude_async { 193 | pub use crate::prelude_common::*; 194 | pub use crate::events::AsyncEvent; 195 | pub use crate::handlers::{Events as SyncEvents, events_impl as sync_events_impl}; 196 | pub use crate::handlers::{AsyncEvents as Events, async_events_impl as events_impl}; 197 | } 198 | -------------------------------------------------------------------------------- /static-events/src/private.rs: -------------------------------------------------------------------------------- 1 | //! This module is used by static-events_derive, and is not stable API. 2 | 3 | use crate::events::*; 4 | use crate::handlers::*; 5 | use std::future::Future; 6 | use std::pin::Pin; 7 | use std::task::{Poll, Context}; 8 | 9 | #[doc(hidden)] pub use std::option::{Option, Option::{Some, None}}; 10 | #[doc(hidden)] pub use std::result::Result; 11 | 12 | /// A hack to allow the `type_alias_impl_trait` feature flag to be contained to this crate. 13 | #[allow_internal_unstable(type_alias_impl_trait)] 14 | pub macro allow_existentials(($($head:tt)*) ($($tail:tt)*)) { 15 | type $($head)* = impl $($tail)*; 16 | } 17 | 18 | #[inline(never)] 19 | #[cold] 20 | pub fn event_error() -> ! { 21 | panic!("internal static-events error, this is likely a bug") 22 | } 23 | 24 | #[inline(never)] 25 | #[cold] 26 | pub fn async_in_sync() -> ! { 27 | panic!("events containing asynchronous handlers cannot be called in \ 28 | synchronous dispatches or contexts.") 29 | } 30 | 31 | /// Casts a `Handler` to a `Handler` 32 | pub fn handler_as_sync_handler(handler: &Handler) -> &Handler { 33 | DowncastEvents::as_async_events(handler) 34 | } 35 | #[inline(never)] 36 | #[cold] 37 | fn async_handler_in_sync() -> ! { 38 | panic!("this event handler requires an asynchronous event dispatch") 39 | } 40 | trait DowncastEvents: Events { 41 | type AsAsyncEvents: AsyncEvents; 42 | fn as_async_events(handler: &Handler) -> &Handler; 43 | } 44 | impl DowncastEvents for E { 45 | default type AsAsyncEvents = NullAsyncEvents; 46 | default fn as_async_events(_: &Handler) -> &Handler { 47 | async_handler_in_sync() 48 | } 49 | } 50 | impl DowncastEvents for E { 51 | type AsAsyncEvents = E; 52 | fn as_async_events(handler: &Handler) -> &Handler { 53 | handler 54 | } 55 | } 56 | 57 | /// An `AsyncEvents` of which no instances should exist. 58 | pub enum NullAsyncEvents { } 59 | impl Events for NullAsyncEvents { 60 | fn get_service(&self) -> Option<&S> { 61 | event_error() 62 | } 63 | } 64 | impl AsyncEvents for NullAsyncEvents { } 65 | 66 | /// A future of which no instances should exist. Used as a the future type when no async future 67 | /// is defined. 68 | pub enum NullFuture { } 69 | impl Future for NullFuture { 70 | type Output = EventResult; 71 | 72 | #[inline(always)] 73 | fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll { 74 | event_error() 75 | } 76 | } 77 | 78 | pub trait UniversalEventHandler< 79 | 'a, E: Events, Ev: Event + 'a, P: EventPhase, D = DefaultHandler, 80 | >: Events { 81 | const IS_IMPLEMENTED: bool; 82 | const IS_ASYNC: bool; 83 | fn on_phase( 84 | &'a self, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 85 | ) -> EventResult; 86 | } 87 | impl < 88 | 'a, E: Events, Ev: Event + 'a, P: EventPhase, D, T: Events, 89 | > UniversalEventHandler<'a, E, Ev, P, D> for T { 90 | default const IS_IMPLEMENTED: bool = false; 91 | default const IS_ASYNC: bool = false; 92 | #[inline(always)] 93 | default fn on_phase( 94 | &'a self, _: &'a Handler, _: &'a mut Ev, _: &'a mut Ev::State, 95 | ) -> EventResult { 96 | event_error() 97 | } 98 | } 99 | impl < 100 | 'a, E: Events, Ev: Event + 'a, P: EventPhase, D, T: Events + EventHandler<'a, E, Ev, P, D>, 101 | > UniversalEventHandler<'a, E, Ev, P, D> for T { 102 | const IS_IMPLEMENTED: bool = >::IS_IMPLEMENTED; 103 | const IS_ASYNC: bool = >::IS_ASYNC; 104 | #[inline(always)] 105 | fn on_phase( 106 | &'a self, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 107 | ) -> EventResult { 108 | self.on_phase(target, ev, state) 109 | } 110 | } 111 | 112 | pub trait UniversalAsyncEventHandler< 113 | 'a, E: AsyncEvents, Ev: AsyncEvent + 'a, P: EventPhase, D = DefaultHandler, 114 | >: AsyncEvents { 115 | type FutureType: Future + Send; 116 | fn on_phase_async( 117 | &'a self, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 118 | ) -> Self::FutureType; 119 | } 120 | impl < 121 | 'a, E: AsyncEvents, Ev: AsyncEvent + 'a, P: EventPhase, D, T: AsyncEvents, 122 | > UniversalAsyncEventHandler<'a, E, Ev, P, D> for T { 123 | default type FutureType = NullFuture; 124 | default fn on_phase_async( 125 | &'a self, _: &'a Handler, _: &'a mut Ev, _: &'a mut ::State, 126 | ) -> Self::FutureType { 127 | event_error() 128 | } 129 | } 130 | impl < 131 | 'a, E: AsyncEvents, Ev: AsyncEvent + 'a, P: EventPhase, D, 132 | T: AsyncEvents + AsyncEventHandler<'a, E, Ev, P, D>, 133 | > UniversalAsyncEventHandler<'a, E, Ev, P, D> for T { 134 | type FutureType = >::FutureType; 135 | #[inline(always)] 136 | fn on_phase_async( 137 | &'a self, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 138 | ) -> Self::FutureType { 139 | >::on_phase_async(self, target, ev, state) 140 | } 141 | 142 | } 143 | 144 | #[inline(always)] 145 | pub const fn is_implemented<'a, T: Events, E: Events, Ev: Event + 'a, P: EventPhase, D>() -> bool { 146 | >::IS_IMPLEMENTED 147 | } 148 | 149 | #[inline(always)] 150 | pub const fn is_async<'a, T: Events, E: Events, Ev: Event + 'a, P: EventPhase, D>() -> bool { 151 | >::IS_ASYNC 152 | } 153 | 154 | #[inline(always)] 155 | pub const fn is_any_async<'a, E: Events, Ev: Event + 'a>() -> bool { 156 | is_async::<'a, E, E, Ev, EvInit, DefaultHandler>() || 157 | is_async::<'a, E, E, Ev, EvCheck, DefaultHandler>() || 158 | is_async::<'a, E, E, Ev, EvBeforeEvent, DefaultHandler>() || 159 | is_async::<'a, E, E, Ev, EvOnEvent, DefaultHandler>() || 160 | is_async::<'a, E, E, Ev, EvAfterEvent, DefaultHandler>() 161 | } 162 | 163 | #[inline(always)] 164 | pub fn on_phase< 165 | 'a, 'b: 'a, 'c: 'a, 'd: 'a, 'e: 'a, T: Events, E: Events, Ev: Event + 'a, P: EventPhase, D, 166 | >( 167 | this: &'b T, target: &'c Handler, ev: &'d mut Ev, state: &'e mut Ev::State, 168 | ) -> EventResult { 169 | if is_implemented::<'a, T, E, Ev, P, D>() { 170 | UniversalEventHandler::<'a, E, Ev, P, D>::on_phase(this, target, ev, state) 171 | } else { 172 | EventResult::EvOk 173 | } 174 | } 175 | 176 | #[inline(always)] 177 | pub fn on_phase_async< 178 | 'a, T: AsyncEvents, E: AsyncEvents, Ev: AsyncEvent + 'a, P: EventPhase + 'a, D: 'a, 179 | >( 180 | this: &'a T, target: &'a Handler, ev: &'a mut Ev, state: &'a mut Ev::State, 181 | ) -> >::FutureType { 182 | if is_implemented::<'a, T, E, Ev, P, D>() && is_async::<'a, T, E, Ev, P, D>() { 183 | >::on_phase_async(this, target, ev, state) 184 | } else { 185 | event_error() 186 | } 187 | } 188 | 189 | /// Distinguisher for the handler generated by `#[events_impl]` 190 | pub enum HandlerImplBlock { } 191 | 192 | /// Helper trait for statically checking if types are equal. Similar to `Any`, kinda. 193 | pub trait CheckDowncast { 194 | fn downcast_ref(&self) -> Option<&A>; 195 | } 196 | impl CheckDowncast for A { 197 | default fn downcast_ref(&self) -> Option<&A> { 198 | Some(unsafe { &*(self as *const Self as *const A) }) 199 | } 200 | } 201 | impl CheckDowncast for A { 202 | default fn downcast_ref(&self) -> Option<&B> { 203 | None 204 | } 205 | } 206 | 207 | /// A helper type for `failable_event!`. 208 | pub struct FailableReturn(pub Result); 209 | impl Default for FailableReturn { 210 | fn default() -> Self { 211 | FailableReturn(Ok(EventResult::EvOk)) 212 | } 213 | } 214 | impl From> for FailableReturn { 215 | fn from(res: Result<(), E>) -> Self { 216 | FailableReturn(res.map(|_| EventResult::EvOk)) 217 | } 218 | } 219 | impl From> for FailableReturn { 220 | fn from(res: Result) -> Self { 221 | FailableReturn(res) 222 | } 223 | } 224 | impl From<()> for FailableReturn { 225 | fn from(_: ()) -> Self { 226 | FailableReturn(Ok(EventResult::EvOk)) 227 | } 228 | } 229 | impl From for FailableReturn { 230 | fn from(res: EventResult) -> Self { 231 | FailableReturn(Ok(res)) 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /static-events/tests/async_events.rs: -------------------------------------------------------------------------------- 1 | use static_events::prelude_async::*; 2 | use std::sync::Arc; 3 | 4 | struct MyEvent(u32); 5 | simple_event!(MyEvent, u32, 0); 6 | 7 | struct AsyncNonStatic<'a>(&'a u32); 8 | simple_event!(['a] AsyncNonStatic<'a>, u32, 0); 9 | 10 | #[derive(Events, Default)] 11 | struct MyEventHandler; 12 | 13 | #[events_impl] 14 | impl MyEventHandler { 15 | #[event_handler] 16 | fn handle_event(_target: &Handler, ev: &MyEvent, i: &mut u32) { 17 | *i += ev.0; 18 | } 19 | 20 | #[event_handler] 21 | async fn handle_event_async(_target: &Handler, ev: &MyEvent, i: &mut u32) { 22 | *i += ev.0; 23 | } 24 | 25 | #[event_handler] 26 | async fn handle_event_async_nonstatic<'a>( 27 | _target: &Handler, ev: &AsyncNonStatic<'a>, i: &mut u32, 28 | ) { 29 | *i += *ev.0; 30 | } 31 | } 32 | 33 | #[test] 34 | fn sync_in_async_event_test() { 35 | let handler = Handler::new(MyEventHandler); 36 | assert_eq!(futures::executor::block_on(handler.dispatch_async(MyEvent(20))), 40); 37 | } 38 | 39 | #[test] 40 | fn async_nonstatic_test() { 41 | let handler = Handler::new(MyEventHandler); 42 | assert_eq!(futures::executor::block_on(handler.dispatch_async(AsyncNonStatic(&20))), 20); 43 | } 44 | 45 | #[test] 46 | fn arc_sync_in_async_event_test() { 47 | let handler = Handler::new(Arc::new(MyEventHandler)); 48 | assert_eq!(futures::executor::block_on(handler.dispatch_async(MyEvent(20))), 40); 49 | } 50 | 51 | #[test] 52 | fn arc_async_nonstatic_test() { 53 | let handler = Handler::new(Arc::new(MyEventHandler)); 54 | assert_eq!(futures::executor::block_on(handler.dispatch_async(AsyncNonStatic(&20))), 20); 55 | } -------------------------------------------------------------------------------- /static-events/tests/type_params.rs: -------------------------------------------------------------------------------- 1 | use static_events::prelude_sync::*; 2 | 3 | #[derive(Events)] 4 | pub struct HasParameter(T); -------------------------------------------------------------------------------- /static-events_derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "static-events_derive" 3 | version = "0.1.0" 4 | authors = ["Lymia Aluysia "] 5 | edition = "2018" 6 | 7 | description = "An internal helper crate for static-events. Not public API." 8 | 9 | documentation = "https://docs.rs/static-events/" 10 | repository = "https://github.com/Lymia/static-events" 11 | 12 | license = "MIT/Apache-2.0" 13 | 14 | [lib] 15 | proc-macro = true 16 | 17 | [dependencies] 18 | static-events_internals = { version = "0.1.0", path = "../static-events_internals" } -------------------------------------------------------------------------------- /static-events_derive/src/lib.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | use static_events_internals::*; 3 | 4 | #[proc_macro_derive(Events, attributes(subhandler, service, events))] 5 | pub fn derive_events(input: TokenStream) -> TokenStream { 6 | try_syn!(DeriveStaticEvents::from_tokens_raw(input, false)).generate().into() 7 | } 8 | 9 | #[proc_macro_derive(AsyncEvents, attributes(subhandler, service, events))] 10 | pub fn derive_sync_events(input: TokenStream) -> TokenStream { 11 | try_syn!(DeriveStaticEvents::from_tokens_raw(input, true)).generate().into() 12 | } 13 | 14 | #[proc_macro_attribute] 15 | pub fn events_impl(_: TokenStream, item: TokenStream) -> TokenStream { 16 | try_syn!(EventsImplAttr::from_tokens_raw(item, false)).generate().into() 17 | } 18 | 19 | #[proc_macro_attribute] 20 | pub fn async_events_impl(_: TokenStream, item: TokenStream) -> TokenStream { 21 | try_syn!(EventsImplAttr::from_tokens_raw(item, true)).generate().into() 22 | } 23 | 24 | derived_attr!(event_handler, events_impl); 25 | -------------------------------------------------------------------------------- /static-events_internals/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "static-events_internals" 3 | version = "0.1.0" 4 | authors = ["Lymia Aluysia "] 5 | edition = "2018" 6 | 7 | description = "An helper crate for procedural derives based off static-events. Public API but not particularly stable." 8 | 9 | documentation = "https://docs.rs/static-events/" 10 | repository = "https://github.com/Lymia/static-events" 11 | 12 | license = "MIT/Apache-2.0" 13 | 14 | [dependencies] 15 | darling = "0.10.2" 16 | quote = "1.0" 17 | syn = { version = "1.0", features = ["extra-traits", "full"] } 18 | proc-macro2 = "1.0" 19 | -------------------------------------------------------------------------------- /static-events_internals/src/common.rs: -------------------------------------------------------------------------------- 1 | use crate::utils::*; 2 | use proc_macro2::{TokenStream as SynTokenStream}; 3 | use syn::*; 4 | use quote::*; 5 | 6 | fn unwrap_distinguisher( 7 | crate_name: &SynTokenStream, distinguisher: Option, 8 | ) -> SynTokenStream { 9 | match distinguisher { 10 | Some(x) => x.into_token_stream(), 11 | None => quote! { #crate_name::handlers::DefaultHandler }, 12 | } 13 | } 14 | fn bool_val( 15 | crate_name: &SynTokenStream, 16 | tp: impl ToTokens, distinguisher: impl ToTokens, call: impl ToTokens, 17 | ) -> SynTokenStream { 18 | quote! { 19 | #crate_name::private::#call::< 20 | '__EventLifetime, #tp, __EventDispatch, __EventType, __EventPhase, #distinguisher, 21 | >() 22 | } 23 | } 24 | 25 | /// Generates `|| (...)::IS_IMPLEMENTED` 26 | pub fn is_implemented( 27 | crate_name: &SynTokenStream, tp: impl ToTokens, distinguisher: impl ToTokens, 28 | ) -> SynTokenStream { 29 | bool_val(crate_name, tp, distinguisher, quote! { is_implemented }) 30 | } 31 | /// Generates `|| (...)::IS_ASYNC` 32 | pub fn is_async( 33 | crate_name: &SynTokenStream, tp: impl ToTokens, distinguisher: impl ToTokens, 34 | ) -> SynTokenStream { 35 | bool_val(crate_name, tp, distinguisher, quote! { is_async }) 36 | } 37 | 38 | /// A particular call to make during an event dispatch. 39 | pub struct CallStage { 40 | extract_field: SynTokenStream, field_tp: SynTokenStream, distinguisher: SynTokenStream, 41 | } 42 | impl CallStage { 43 | pub fn new( 44 | crate_name: &SynTokenStream, 45 | extract_field: impl ToTokens, field_tp: impl ToTokens, 46 | distinguisher: Option, 47 | ) -> CallStage { 48 | CallStage { 49 | extract_field: extract_field.into_token_stream(), 50 | field_tp: field_tp.into_token_stream(), 51 | distinguisher: unwrap_distinguisher(crate_name, distinguisher), 52 | } 53 | } 54 | } 55 | 56 | /// A particular arm of an event dispatch (e.g. if the Events is implemented on an enum). 57 | pub struct CallGroup { 58 | is_common_group: bool, matcher: SynTokenStream, stages: Vec, 59 | } 60 | impl CallGroup { 61 | pub fn new(matcher: impl ToTokens, stages: Vec) -> CallGroup { 62 | CallGroup { is_common_group: false, matcher: matcher.into_token_stream(), stages } 63 | } 64 | } 65 | 66 | pub enum EventHandlerTarget<'a> { 67 | Ident(&'a Ident), Type(&'a Type), 68 | } 69 | fn make_call( 70 | crate_name: &SynTokenStream, 71 | field: impl ToTokens, tp: impl ToTokens, is_async: bool, distinguisher: impl ToTokens, 72 | ) -> SynTokenStream { 73 | let call_fn = if is_async { quote! { on_phase_async } } else { quote! { on_phase } }; 74 | quote! { 75 | #crate_name::private::#call_fn::< 76 | #tp, __EventDispatch, __EventType, __EventPhase, #distinguisher, 77 | >(#field, _target, _ev, _state) 78 | } 79 | } 80 | pub fn make_merge_event_handler( 81 | crate_name: &SynTokenStream, is_async_handler: bool, 82 | name: EventHandlerTarget, item_generics: &Generics, 83 | distinguisher: Option, mut groups: Vec, common: Vec, 84 | ) -> SynTokenStream { 85 | let distinguisher = unwrap_distinguisher(crate_name, distinguisher); 86 | 87 | let event_generics = generics("e! { 88 | '__EventLifetime, 89 | __EventDispatch: #crate_name::handlers::Events, 90 | __EventType: #crate_name::events::Event + '__EventLifetime, 91 | __EventPhase: #crate_name::handlers::EventPhase + '__EventLifetime, 92 | }); 93 | 94 | let handler_generics = merge_generics(&event_generics, item_generics); 95 | 96 | let (handler_impl_bounds, _, handler_where_bounds) = 97 | handler_generics.split_for_impl(); 98 | let (_, self_ty_param, _) = item_generics.split_for_impl(); 99 | 100 | let name = match name { 101 | EventHandlerTarget::Ident(id) => quote! { #id #self_ty_param }, 102 | EventHandlerTarget::Type(tp) => quote! { #tp }, 103 | }; 104 | 105 | let handler_ty = quote! { #crate_name::handlers::EventHandler< 106 | '__EventLifetime, __EventDispatch, __EventType, __EventPhase, #distinguisher, 107 | > }; 108 | 109 | let mut is_implemented_expr = quote! { false }; 110 | let mut is_async_expr = quote! { false }; 111 | let mut sync_actions = SynTokenStream::new(); 112 | let mut async_actions = SynTokenStream::new(); 113 | let mut sync_match = SynTokenStream::new(); 114 | let mut async_match = SynTokenStream::new(); 115 | 116 | let mut common_group = CallGroup::new(quote! { }, common); 117 | common_group.is_common_group = true; 118 | let mut all_groups = Vec::new(); 119 | all_groups.push(common_group); 120 | all_groups.append(&mut groups); 121 | for group in all_groups { 122 | let mut sync_stage = SynTokenStream::new(); 123 | let mut async_stage = SynTokenStream::new(); 124 | 125 | for stage in group.stages { 126 | let extract_field = &stage.extract_field; 127 | let field_tp = &stage.field_tp; 128 | let distinguisher = &stage.distinguisher; 129 | 130 | let is_implemented = is_implemented(crate_name, field_tp, distinguisher); 131 | let is_async = is_async(crate_name, field_tp, distinguisher); 132 | let call_sync = make_call( 133 | crate_name, quote!(#extract_field), field_tp, false, distinguisher, 134 | ); 135 | let call_async = make_call( 136 | crate_name, quote!(#extract_field), field_tp, true , distinguisher, 137 | ); 138 | 139 | is_implemented_expr.extend(quote! { || #is_implemented }); 140 | is_async_expr.extend(quote! { || #is_async }); 141 | sync_stage.extend(quote! {{ 142 | match #call_sync { 143 | #crate_name::events::EventResult::EvOk => { } 144 | e => return e, 145 | } 146 | }}); 147 | async_stage.extend(quote! {{ 148 | let result = if #is_async { 149 | #call_async.await 150 | } else { 151 | #call_sync 152 | }; 153 | match result { 154 | #crate_name::events::EventResult::EvOk => { } 155 | e => return e, 156 | } 157 | }}); 158 | } 159 | 160 | if group.is_common_group { 161 | sync_actions.extend(sync_stage); 162 | async_actions.extend(async_stage); 163 | } else { 164 | let matcher = &group.matcher; 165 | sync_match.extend(quote! { #matcher => { #sync_stage } }); 166 | async_match.extend(quote! { #matcher => { #async_stage } }); 167 | } 168 | } 169 | let async_events = if is_async_handler { 170 | let async_event_generics = generics("e! { 171 | '__EventLifetime, 172 | __EventDispatch: #crate_name::handlers::AsyncEvents, 173 | __EventType: #crate_name::events::AsyncEvent + '__EventLifetime, 174 | __EventPhase: #crate_name::handlers::EventPhase + '__EventLifetime, 175 | }); 176 | 177 | let async_handler_ty = quote! { #crate_name::handlers::AsyncEventHandler< 178 | '__EventLifetime, __EventDispatch, __EventType, __EventPhase, #distinguisher, 179 | > }; 180 | 181 | let async_handler_generics = merge_generics(&async_event_generics, item_generics); 182 | let no_lt_generics = strip_lifetimes(&async_handler_generics); 183 | 184 | let (async_handler_impl_bounds, async_handler_ty_param, async_handler_where_bounds) = 185 | async_handler_generics.split_for_impl(); 186 | 187 | let (_, no_lt_ty_param, _) = no_lt_generics.split_for_impl(); 188 | let no_lt_turbofish = no_lt_ty_param.as_turbofish(); 189 | 190 | quote! { 191 | async fn __merge_events_async_wrapper #async_handler_impl_bounds ( 192 | _this: &#name, 193 | _target: &'__EventLifetime #crate_name::handlers::Handler<__EventDispatch>, 194 | _ev: &'__EventLifetime mut __EventType, 195 | _state: &'__EventLifetime mut __EventType::State, 196 | ) -> #crate_name::events::EventResult #async_handler_where_bounds { 197 | #async_actions 198 | match _this { 199 | #async_match 200 | } 201 | #crate_name::events::EventResult::EvOk 202 | } 203 | 204 | #crate_name::private::allow_existentials! { 205 | (__MergeEventsWrapperFut #async_handler_impl_bounds #async_handler_where_bounds) 206 | (::std::future::Future + 207 | '__EventLifetime) 208 | } 209 | 210 | impl #async_handler_impl_bounds #async_handler_ty 211 | for #name #async_handler_where_bounds 212 | { 213 | type FutureType = __MergeEventsWrapperFut #async_handler_ty_param; 214 | 215 | #[inline] 216 | fn on_phase_async( 217 | &'__EventLifetime self, 218 | target: &'__EventLifetime #crate_name::handlers::Handler<__EventDispatch>, 219 | ev: &'__EventLifetime mut __EventType, 220 | state: &'__EventLifetime mut __EventType::State, 221 | ) -> __MergeEventsWrapperFut #async_handler_ty_param { 222 | __merge_events_async_wrapper #no_lt_turbofish (self, target, ev, state) 223 | } 224 | } 225 | } 226 | } else { 227 | SynTokenStream::new() 228 | }; 229 | 230 | quote! { 231 | impl #handler_impl_bounds #handler_ty for #name #handler_where_bounds { 232 | const IS_IMPLEMENTED: bool = #is_implemented_expr; 233 | const IS_ASYNC: bool = #is_async_expr; 234 | 235 | #[inline] 236 | fn on_phase( 237 | &'__EventLifetime self, 238 | _target: &'__EventLifetime #crate_name::handlers::Handler<__EventDispatch>, 239 | _ev: &'__EventLifetime mut __EventType, 240 | _state: &'__EventLifetime mut __EventType::State, 241 | ) -> #crate_name::events::EventResult { 242 | let _this = self; 243 | #sync_actions 244 | match _this { 245 | #sync_match 246 | } 247 | #crate_name::events::EventResult::EvOk 248 | } 249 | } 250 | 251 | #async_events 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /static-events_internals/src/derive.rs: -------------------------------------------------------------------------------- 1 | use crate::common::*; 2 | use crate::errors::Result; 3 | use crate::utils::*; 4 | use darling::*; 5 | use proc_macro2::{TokenStream as SynTokenStream}; 6 | use syn::*; 7 | use syn::export::Span; 8 | use syn::punctuated::Punctuated; 9 | use syn::spanned::Spanned; 10 | use quote::*; 11 | 12 | fn dispatch_get_service(crate_name: &SynTokenStream, field: impl ToTokens) -> SynTokenStream { 13 | quote! { 14 | match #crate_name::handlers::Events::get_service::<__DowncastTarget>(#field) { 15 | Some(t) => return Some(t), 16 | None => { } 17 | } 18 | } 19 | } 20 | fn check_get_service_type(crate_name: &SynTokenStream, field: impl ToTokens) -> SynTokenStream { 21 | quote! { 22 | match #crate_name::private::CheckDowncast::<__DowncastTarget>::downcast_ref(#field) { 23 | Some(t) => return Some(t), 24 | None => { } 25 | } 26 | } 27 | } 28 | 29 | #[derive(Default)] 30 | struct FieldAttrs { 31 | is_subhandler: bool, 32 | is_service: bool, 33 | } 34 | impl FieldAttrs { 35 | fn from_attrs(attrs: &[Attribute]) -> FieldAttrs { 36 | let mut tp = FieldAttrs::default(); 37 | for attr in attrs { 38 | match last_path_segment(&attr.path).as_str() { 39 | "subhandler" => tp.is_subhandler = true, 40 | "service" => tp.is_service = true, 41 | _ => { } 42 | } 43 | } 44 | tp 45 | } 46 | } 47 | 48 | #[derive(FromDeriveInput)] 49 | #[darling(attributes(events))] 50 | struct EventsAttrs { 51 | ident: Ident, 52 | 53 | #[darling(default)] 54 | impl_on_external: Option, 55 | } 56 | 57 | fn i_ident(i: usize) -> Ident { 58 | Ident::new(&format!("_field_{}", i), Span::call_site()) 59 | } 60 | 61 | #[derive(Copy, Clone)] 62 | enum Style { 63 | Unit, Struct, Tuple, 64 | } 65 | fn to_vec(punctuated: &Punctuated) -> Vec<&T> { 66 | punctuated.iter().collect() 67 | } 68 | 69 | /// A type for including the effect of `#[derive(Events)]` in a procedural macro. 70 | pub struct DeriveStaticEvents { 71 | arms: Vec, 72 | crate_name: SynTokenStream, 73 | subhandlers_exist: bool, 74 | get_service_body: SynTokenStream, 75 | discriminator: Vec, 76 | name: Ident, 77 | input: DeriveInput, 78 | is_async_handler: bool, 79 | } 80 | impl DeriveStaticEvents { 81 | /// Parses a derive input block. 82 | pub fn new( 83 | input: &DeriveInput, crate_name: Option, is_async_handler: bool, 84 | ) -> Result { 85 | let crate_name = crate_name.unwrap_or(quote! { ::static_events }); 86 | 87 | let attrs: EventsAttrs = EventsAttrs::from_derive_input(input)?; 88 | let name = attrs.impl_on_external.as_ref().unwrap_or(&attrs.ident); 89 | let name = name.clone(); 90 | 91 | let mut data = DeriveStaticEvents { 92 | arms: Vec::new(), 93 | crate_name, 94 | subhandlers_exist: false, 95 | get_service_body: Default::default(), 96 | discriminator: Vec::new(), 97 | name: name.clone(), 98 | input: input.clone(), 99 | is_async_handler, 100 | }; 101 | match &input.data { 102 | Data::Struct(input_data) => data.generate_struct(&name, input_data), 103 | Data::Enum(input_data) => data.generate_enum(&name, input_data), 104 | Data::Union(_) => 105 | error(input.span(), "EventDispatch can only be derived on a struct or enum.")?, 106 | } 107 | Ok(data) 108 | } 109 | 110 | /// Sets the crate name to use. Overrides any manual tags on the derive. 111 | pub fn set_crate_name(&mut self, name: impl ToTokens) { 112 | self.crate_name = name.to_token_stream(); 113 | } 114 | 115 | /// Parses a token stream. 116 | pub fn from_tokens(toks: impl ToTokens, is_async_handler: bool) -> Result { 117 | Self::new(&mut parse2(toks.into_token_stream())?, None, is_async_handler) 118 | } 119 | 120 | /// Parses a token stream. 121 | pub fn from_tokens_raw(toks: proc_macro::TokenStream, is_async_handler: bool) -> Result { 122 | Self::new(&mut parse(toks)?, None, is_async_handler) 123 | } 124 | 125 | fn generate_arm( 126 | &mut self, self_path: SynTokenStream, tp: Style, fields: &[&Field], 127 | is_struct: bool, 128 | ) { 129 | let crate_name = &self.crate_name; 130 | 131 | let mut matches = SynTokenStream::new(); 132 | for (i, field) in fields.iter().enumerate() { 133 | let field_ident = i_ident(i); 134 | let field_name = &field.ident; 135 | matches.extend(match tp { 136 | Style::Unit => unimplemented!(), 137 | Style::Struct => quote!(#field_name: #field_ident,), 138 | Style::Tuple => quote!(#field_ident,), 139 | }); 140 | } 141 | let matches = match tp { 142 | Style::Unit => matches, 143 | Style::Struct => quote! { { #matches } }, 144 | Style::Tuple => quote! { ( #matches ) }, 145 | }; 146 | 147 | let mut get_service = SynTokenStream::new(); 148 | let mut stages = Vec::new(); 149 | for (i, field) in fields.iter().enumerate() { 150 | let name = match tp { 151 | Style::Unit => unimplemented!(), 152 | Style::Struct => { 153 | let ident = &field.ident; 154 | quote! { #ident } 155 | } 156 | Style::Tuple => { 157 | let i = syn::Index::from(i); 158 | quote! { #i } 159 | } 160 | }; 161 | let attr = FieldAttrs::from_attrs(&field.attrs); 162 | let field_ident = i_ident(i); 163 | 164 | if attr.is_service { 165 | get_service.extend(check_get_service_type(&self.crate_name, &field_ident)); 166 | } 167 | if attr.is_subhandler { 168 | get_service.extend(dispatch_get_service(&self.crate_name, &field_ident)); 169 | stages.push(CallStage::new(crate_name, if is_struct { 170 | quote! { &_this.#name } 171 | } else { 172 | quote! { 173 | if let #self_path #matches = _this { 174 | #field_ident 175 | } else { 176 | #crate_name::private::event_error() 177 | } 178 | } 179 | }, &field.ty, None)); 180 | self.subhandlers_exist = true; 181 | } 182 | } 183 | self.arms.push(CallGroup::new(match tp { 184 | Style::Unit => quote! { #self_path }, 185 | Style::Struct => quote! { #self_path {..} }, 186 | Style::Tuple => quote! { #self_path(..) }, 187 | }, stages)); 188 | self.get_service_body.extend(quote!(#self_path #matches => { #get_service })); 189 | } 190 | fn generate_arm_fields( 191 | &mut self, self_path: SynTokenStream, fields: &Fields, is_struct: bool, 192 | ) { 193 | match fields { 194 | Fields::Unit => 195 | self.generate_arm(self_path, Style::Unit, &[], is_struct), 196 | Fields::Named(named) => 197 | self.generate_arm(self_path, Style::Struct, &to_vec(&named.named), is_struct), 198 | Fields::Unnamed(unnamed) => 199 | self.generate_arm(self_path, Style::Tuple, &to_vec(&unnamed.unnamed), is_struct), 200 | } 201 | } 202 | 203 | fn generate_struct( 204 | &mut self, ident: &Ident, fields: &DataStruct, 205 | ) { 206 | self.generate_arm_fields(quote! { #ident }, &fields.fields, true); 207 | } 208 | fn generate_enum( 209 | &mut self, ident: &Ident, variants: &DataEnum, 210 | ) { 211 | for variant in &variants.variants { 212 | let variant_ident = &variant.ident; 213 | self.generate_arm_fields(quote! { #ident::#variant_ident }, &variant.fields, false); 214 | } 215 | } 216 | 217 | /// Adds a discriminator to the events handler. 218 | pub fn add_discriminator(&mut self, discriminator: Type) { 219 | self.discriminator.push(discriminator); 220 | } 221 | 222 | /// Generates an impl block for the events handler. 223 | pub fn generate(self) -> SynTokenStream { 224 | let crate_name = &self.crate_name; 225 | 226 | let name = self.name; 227 | let input = self.input; 228 | 229 | let get_service_self = if FieldAttrs::from_attrs(&input.attrs).is_service { 230 | check_get_service_type(crate_name, quote!(self)) 231 | } else { 232 | quote! { } 233 | }; 234 | let get_service_body = self.get_service_body; 235 | 236 | let (impl_bounds, ty_param, where_bounds) = input.generics.split_for_impl(); 237 | let dist = Some(quote! { #crate_name::private::HandlerImplBlock }); 238 | 239 | let mut common = Vec::new(); 240 | common.push(CallStage::new( 241 | crate_name, quote! { _this }, quote! { #name #ty_param }, dist, 242 | )); 243 | for dist in self.discriminator { 244 | common.push(CallStage::new( 245 | crate_name, 246 | quote! { _this }, quote! { #name #ty_param }, Some(quote! { #dist }), 247 | )); 248 | } 249 | 250 | let event_handler = make_merge_event_handler( 251 | crate_name, self.is_async_handler, 252 | EventHandlerTarget::Ident(&name), &input.generics, None, self.arms, common, 253 | ); 254 | let sync_event_impl = if self.is_async_handler { 255 | quote! { 256 | impl #impl_bounds #crate_name::handlers::AsyncEvents 257 | for #name #ty_param #where_bounds { } 258 | } 259 | } else { 260 | SynTokenStream::new() 261 | }; 262 | 263 | quote! { 264 | #[allow(non_snake_case)] 265 | const _: () = { 266 | impl #impl_bounds #crate_name::handlers::Events for #name #ty_param #where_bounds { 267 | fn get_service<__DowncastTarget>(&self) -> Option<&__DowncastTarget> { 268 | #get_service_self 269 | match self { #get_service_body } 270 | None 271 | } 272 | } 273 | #sync_event_impl 274 | #event_handler 275 | }; 276 | } 277 | } 278 | } -------------------------------------------------------------------------------- /static-events_internals/src/errors.rs: -------------------------------------------------------------------------------- 1 | enum ErrorData { 2 | SynError(syn::Error), 3 | DarlingError(darling::Error), 4 | Combined(Vec), 5 | Empty, 6 | } 7 | 8 | /// A error type used by this crate. 9 | pub struct Error(ErrorData); 10 | 11 | impl Error { 12 | /// Creates a new error from a span and an message 13 | pub fn new(span: impl Into, message: T) -> Self { 14 | Error(ErrorData::SynError(syn::Error::new(span.into(), message))) 15 | } 16 | 17 | /// Creates an error empty data for collecting errors. 18 | pub fn empty() -> Self { 19 | Error(ErrorData::Empty) 20 | } 21 | 22 | /// Returns whether this error data is empty. 23 | pub fn is_empty(&self) -> bool { 24 | match &self.0 { 25 | ErrorData::Empty => true, 26 | _ => false, 27 | } 28 | } 29 | 30 | /// Combines two errors into one so they can be emitted at one time. 31 | pub fn combine(self, other: impl Into) -> Self { 32 | let mut list = match self.0 { 33 | ErrorData::Combined(vec) => vec, 34 | ErrorData::Empty => Vec::new(), 35 | x => vec![Error(x)], 36 | }; 37 | match other.into().0 { 38 | ErrorData::Combined(vec) => list.extend(vec), 39 | ErrorData::Empty => { } 40 | x => list.push(Error(x)), 41 | } 42 | Error(ErrorData::Combined(list)) 43 | } 44 | 45 | /// Emits the error as a token stream. 46 | pub fn emit(self) -> proc_macro::TokenStream { 47 | match self.0 { 48 | ErrorData::SynError(e) => e.to_compile_error().into(), 49 | ErrorData::DarlingError(e) => e.write_errors().into(), 50 | ErrorData::Combined(e) => { 51 | let mut stream = proc_macro::TokenStream::new(); 52 | for e in e { 53 | stream.extend(e.emit()); 54 | } 55 | stream 56 | } 57 | ErrorData::Empty => { 58 | Error::new( 59 | proc_macro2::Span::call_site(), 60 | "internal error: Error::empty() emitted?", 61 | ).emit() 62 | } 63 | } 64 | } 65 | } 66 | 67 | impl From for Error { 68 | fn from(e: syn::Error) -> Self { 69 | Error(ErrorData::SynError(e)) 70 | } 71 | } 72 | 73 | impl From for Error { 74 | fn from(e: darling::Error) -> Self { 75 | Error(ErrorData::DarlingError(e)) 76 | } 77 | } 78 | 79 | /// An error type specialized for this crate. 80 | pub type Result = std::result::Result; 81 | 82 | #[macro_export] 83 | macro_rules! try_syn { 84 | ($err:expr) => { 85 | match $err { 86 | Ok(v) => v, 87 | Err(e) => return e.emit().into(), 88 | } 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /static-events_internals/src/handlers.rs: -------------------------------------------------------------------------------- 1 | use crate::common::*; 2 | use crate::errors::{Error, Result}; 3 | use crate::utils::*; 4 | use proc_macro2::{TokenStream as SynTokenStream, Span as SynSpan}; 5 | use syn::*; 6 | use syn::spanned::Spanned; 7 | use quote::{quote, ToTokens}; 8 | 9 | // TODO: Figure out what to do with elided type parameters in function arguments. 10 | // TODO: Properly handle lifetimes in general for method arguments. 11 | 12 | #[derive(Debug)] 13 | enum HandlerArg { 14 | SelfParam, 15 | TargetParam, 16 | OtherParam(Type), 17 | } 18 | impl HandlerArg { 19 | fn generic_argument_contains_impl(arg: &GenericArgument) -> bool { 20 | match arg { 21 | GenericArgument::Type(tp) => Self::type_contains_impl(tp), 22 | _ => false, 23 | } 24 | } 25 | fn path_segment_contains_impl(seg: &PathSegment) -> bool { 26 | match &seg.arguments { 27 | PathArguments::None => false, 28 | PathArguments::AngleBracketed(paren) => 29 | paren.args.iter().any(|x| Self::generic_argument_contains_impl(x)), 30 | PathArguments::Parenthesized(_) => false, 31 | } 32 | } 33 | fn type_contains_impl(tp: &Type) -> bool { 34 | match tp { 35 | Type::Paren(paren) => Self::type_contains_impl(&paren.elem), 36 | Type::Group(group) => Self::type_contains_impl(&group.elem), 37 | Type::Path(path) => 38 | path.path.segments.iter().any(|x| Self::path_segment_contains_impl(x)), 39 | Type::ImplTrait(_) => true, 40 | _ => false, 41 | } 42 | } 43 | 44 | fn check_reference_type(tp: &Type) -> Result { 45 | match tp { 46 | Type::Paren(paren) => Self::check_reference_type(&paren.elem), 47 | Type::Group(group) => Self::check_reference_type(&group.elem), 48 | Type::Path(_) => Ok(if Self::type_contains_impl(tp) { 49 | HandlerArg::TargetParam 50 | } else { 51 | HandlerArg::OtherParam((*tp).clone()) 52 | }), 53 | _ => Ok(HandlerArg::OtherParam((*tp).clone())), 54 | } 55 | } 56 | fn check_any_type(tp: &Type) -> Result { 57 | match tp { 58 | Type::Reference(ref_tp) => Self::check_reference_type(&ref_tp.elem), 59 | Type::Paren(paren) => Self::check_any_type(&paren.elem), 60 | Type::Group(group) => Self::check_any_type(&group.elem), 61 | _ => error(tp.span(), "Event handlers must take parameters by reference."), 62 | } 63 | } 64 | 65 | fn from_param(param: &FnArg) -> Result { 66 | match param { 67 | FnArg::Receiver(receiver) => if receiver.reference.is_none() { 68 | error(param.span(), "Event handlers may not take `self` by value.") 69 | } else if receiver.mutability.is_some() { 70 | error(param.span(), "Event handlers may not take `self` by mutable reference.") 71 | } else { 72 | Ok(HandlerArg::SelfParam) 73 | }, 74 | FnArg::Typed(ty) => Self::check_any_type(&ty.ty), 75 | } 76 | } 77 | } 78 | 79 | enum EventHandlerBody { 80 | Sync(SynTokenStream), Async(SynTokenStream), 81 | } 82 | 83 | struct HandlerSig { 84 | fn_name: Ident, 85 | method_generics: Generics, 86 | self_param: Option, 87 | target_param: Option, 88 | event_ty: Type, 89 | state_param: Option, 90 | is_unsafe: bool, 91 | is_async: bool, 92 | } 93 | impl HandlerSig { 94 | fn find_signature(method: &ImplItemMethod, is_handler_async: bool) -> Result { 95 | let sig = &method.sig; 96 | if sig.variadic.is_some() { 97 | error(sig.span(), "Event handlers cannot be variadic.")?; 98 | } 99 | if sig.asyncness.is_some() && !is_handler_async { 100 | error( 101 | sig.asyncness.span(), 102 | "`async` handlers cannot be included in synchronous event handlers.", 103 | )?; 104 | } 105 | 106 | let mut parsed_params = Vec::new(); 107 | for arg in &sig.inputs { 108 | parsed_params.push((HandlerArg::from_param(arg)?, arg.span())); 109 | } 110 | let mut params = parsed_params.into_iter().peekable(); 111 | 112 | let mut handler_sig = HandlerSig { 113 | fn_name: sig.ident.clone(), 114 | method_generics: sig.generics.clone(), 115 | self_param: None, 116 | target_param: None, 117 | event_ty: Type::Verbatim(SynTokenStream::new()), 118 | state_param: None, 119 | is_unsafe: sig.unsafety.is_some(), 120 | is_async: sig.asyncness.is_some(), 121 | }; 122 | 123 | if let Some((HandlerArg::SelfParam, _)) = params.peek() { 124 | handler_sig.self_param = Some(params.next().unwrap().1); 125 | } 126 | if let Some((HandlerArg::TargetParam, _)) = params.peek() { 127 | handler_sig.target_param = Some(params.next().unwrap().1); 128 | } 129 | if let Some((HandlerArg::OtherParam(ty), _)) = params.next() { 130 | handler_sig.event_ty = ty; 131 | } else { 132 | error(sig.span(), "No event parameter found for event handler.")?; 133 | } 134 | if let Some((HandlerArg::OtherParam(_), _)) = params.peek() { 135 | handler_sig.state_param = Some(params.next().unwrap().1); 136 | } 137 | if let Some((_, span)) = params.next() { 138 | error(span, "Unexpected parameter in event handler signature.")?; 139 | } 140 | 141 | Ok(handler_sig) 142 | } 143 | 144 | fn make_body( 145 | &self, crate_name: &SynTokenStream, self_ty: &Type, is_async_handler: bool, 146 | ) -> EventHandlerBody { 147 | let name = &self.fn_name; 148 | let call = match self.self_param { 149 | Some(_) => quote! { _self.#name }, 150 | None => quote! { <#self_ty>::#name }, 151 | }; 152 | let target = match self.target_param { 153 | Some(_) => if is_async_handler { 154 | // this is a hack to allow the (slightly sloppy) `AsyncEvents` bound in sync 155 | // handlers defined in async events. 156 | quote! { #crate_name::private::handler_as_sync_handler(_target), } 157 | } else { 158 | quote! { _target, } 159 | }, 160 | None => quote! {}, 161 | }; 162 | let state = match self.state_param { 163 | Some(_) => quote! { _ev.borrow_state(_state), }, 164 | None => quote! {}, 165 | }; 166 | let call = quote! { #call (#target _ev, #state) }; 167 | let call = if !self.is_unsafe { 168 | call 169 | } else { 170 | quote! { unsafe { #call } } 171 | }; 172 | if self.is_async { 173 | EventHandlerBody::Async(quote! { (#call).await }) 174 | } else { 175 | EventHandlerBody::Sync(call) 176 | } 177 | } 178 | } 179 | 180 | enum HandlerType { 181 | EventHandler(SynTokenStream), 182 | } 183 | impl HandlerType { 184 | fn is_attr(attr: &Attribute) -> bool { 185 | match last_path_segment(&attr.path).as_str() { 186 | "event_handler" => true, 187 | _ => false, 188 | } 189 | } 190 | fn for_attr(crate_name: &SynTokenStream, attr: &Attribute) -> Result> { 191 | match last_path_segment(&attr.path).as_str() { 192 | "event_handler" => { 193 | Ok(Some(HandlerType::EventHandler(if !attr.tokens.is_empty() { 194 | match parse2::(attr.tokens.clone()) { 195 | Ok(tp) => tp.elem.into_token_stream(), 196 | Err(_) => error(attr.span(), "Error parsing #[event_handler] attribute.")?, 197 | } 198 | } else { 199 | quote! { #crate_name::handlers::EvOnEvent } 200 | }))) 201 | }, 202 | _ => Ok(None), 203 | } 204 | } 205 | fn name(&self) -> &'static str { 206 | match self { 207 | HandlerType::EventHandler(_) => "#[event_handler]", 208 | } 209 | } 210 | } 211 | 212 | enum MethodInfo { 213 | EventHandler { phase: SynTokenStream, sig: HandlerSig }, 214 | } 215 | impl MethodInfo { 216 | fn for_method( 217 | crate_name: &SynTokenStream, method: &ImplItemMethod, is_async_handler: bool, 218 | ) -> Result> { 219 | let mut handler_type: Option = None; 220 | for attr in &method.attrs { 221 | if let Some(tp) = HandlerType::for_attr(crate_name, attr)? { 222 | if let Some(e_tp) = &handler_type { 223 | error( 224 | attr.span(), 225 | if e_tp.name() == tp.name() { 226 | format!("{} can only be used once.", tp.name()) 227 | } else { 228 | format!("{} cannot be used with {}.", tp.name(), e_tp.name()) 229 | } 230 | )?; 231 | } 232 | handler_type = Some(tp); 233 | } 234 | } 235 | match handler_type { 236 | Some(HandlerType::EventHandler(phase)) => { 237 | let sig = HandlerSig::find_signature(method, is_async_handler)?; 238 | Ok(Some(MethodInfo::EventHandler { phase, sig })) 239 | } 240 | None => Ok(None), 241 | } 242 | } 243 | } 244 | 245 | fn create_normal_handler( 246 | crate_name: &SynTokenStream, discriminator: &SynTokenStream, is_async_handler: bool, 247 | id: usize, count: usize, 248 | self_ty: &Type, impl_generics: &Generics, phase: &SynTokenStream, sig: &HandlerSig, 249 | ) -> (Ident, SynTokenStream) { 250 | let phantom = ident!("__DistinguisherPhantom_{}", id); 251 | let async_fn = ident!("__events_async_handler_wrapper_{}", id); 252 | let existential = ident!("__RootEventFut_{}", id); 253 | 254 | let event_ty = &sig.event_ty; 255 | let event_ty_event = quote! { <#event_ty as #crate_name::events::Event> }; 256 | 257 | let method_generics = reparent_lifetimes(&sig.method_generics, quote!('__EventLifetime)); 258 | let merged_generics = merge_generics(impl_generics, &method_generics); 259 | 260 | let sync_generics = generics("e! { 261 | '__EventLifetime, 262 | __EventDispatch: #crate_name::handlers::Events, 263 | }); 264 | let sync_generics = merge_generics(&merged_generics, &sync_generics); 265 | let (sync_bounds, _, sync_where_bounds) = sync_generics.split_for_impl(); 266 | 267 | let async_generics = generics("e! { 268 | '__EventLifetime, 269 | __EventDispatch: #crate_name::handlers::AsyncEvents, 270 | }); 271 | let async_generics = merge_generics(&merged_generics, &async_generics); 272 | let (async_bounds, async_ty, async_where_bounds) = async_generics.split_for_impl(); 273 | 274 | let body = sig.make_body(crate_name, self_ty, is_async_handler); 275 | let (is_async, sync_body, future_ty, async_defs, async_body) = match body { 276 | EventHandlerBody::Sync(sync_body) => ( 277 | false, 278 | quote! { 279 | use #crate_name::events::Event; 280 | let _self = self; 281 | let ev_result = (#sync_body).into(); 282 | _ev.to_event_result(_state, ev_result) 283 | }, 284 | quote! { #crate_name::private::NullFuture }, 285 | quote! { }, 286 | quote! { #crate_name::private::event_error() }, 287 | ), 288 | EventHandlerBody::Async(async_body) => ( 289 | true, 290 | quote! { #crate_name::private::async_in_sync() }, 291 | quote! { #existential #async_ty }, 292 | quote! { 293 | async fn #async_fn #async_bounds ( 294 | _self: &'__EventLifetime #self_ty, 295 | _target: &'__EventLifetime #crate_name::handlers::Handler<__EventDispatch>, 296 | _ev: &'__EventLifetime mut #event_ty, 297 | _state: &'__EventLifetime mut #event_ty_event::State, 298 | ) -> #crate_name::events::EventResult #async_where_bounds { 299 | use #crate_name::events::Event; 300 | let ev_result = (#async_body).into(); 301 | _ev.to_event_result(_state, ev_result) 302 | } 303 | 304 | #crate_name::private::allow_existentials! { 305 | (#existential #async_generics) 306 | (::std::future::Future + 307 | '__EventLifetime) 308 | } 309 | }, 310 | quote! { 311 | #async_fn(self, target, ev, state) 312 | }, 313 | ), 314 | }; 315 | 316 | let phantom_impl = if count == 1 { 317 | quote! { pub type #phantom = #discriminator; } 318 | } else { 319 | quote! { pub enum #phantom { } } 320 | }; 321 | let async_impl = if is_async_handler { 322 | quote! { 323 | impl #async_bounds #crate_name::handlers::AsyncEventHandler< 324 | '__EventLifetime, __EventDispatch, #event_ty, #phase, #phantom, 325 | > for #self_ty #async_where_bounds { 326 | type FutureType = #future_ty; 327 | 328 | #[inline] 329 | fn on_phase_async ( 330 | &'__EventLifetime self, 331 | target: &'__EventLifetime #crate_name::handlers::Handler<__EventDispatch>, 332 | ev: &'__EventLifetime mut #event_ty, 333 | state: &'__EventLifetime mut #event_ty_event::State, 334 | ) -> #future_ty { 335 | use #crate_name::events::Event; 336 | #async_body 337 | } 338 | } 339 | } 340 | } else { 341 | SynTokenStream::new() 342 | }; 343 | 344 | (phantom.clone(), quote! { 345 | #phantom_impl 346 | #async_defs 347 | impl #sync_bounds #crate_name::handlers::EventHandler< 348 | '__EventLifetime, __EventDispatch, #event_ty, #phase, #phantom, 349 | > for #self_ty #sync_where_bounds { 350 | const IS_IMPLEMENTED: bool = true; 351 | const IS_ASYNC: bool = #is_async; 352 | 353 | #[inline] 354 | fn on_phase( 355 | &'__EventLifetime self, 356 | _target: &'__EventLifetime #crate_name::handlers::Handler<__EventDispatch>, 357 | _ev: &'__EventLifetime mut #event_ty, 358 | _state: &'__EventLifetime mut #event_ty_event::State, 359 | ) -> #crate_name::events::EventResult { 360 | #sync_body 361 | } 362 | } 363 | #async_impl 364 | }) 365 | } 366 | fn create_impls( 367 | crate_name: &SynTokenStream, discriminator: &SynTokenStream, is_async_handler: bool, 368 | self_ty: &Type, impl_generics: &Generics, methods: &[MethodInfo], 369 | synthetic_methods: &[ImplItemMethod], extra_items: &[SynTokenStream], 370 | ) -> SynTokenStream { 371 | let mut impls = SynTokenStream::new(); 372 | let mut stages = Vec::new(); 373 | 374 | for (i, info) in methods.iter().enumerate() { 375 | match info { 376 | MethodInfo::EventHandler { phase, sig } => { 377 | let (phantom, tts) = create_normal_handler( 378 | crate_name, discriminator, is_async_handler, 379 | i, methods.len(), self_ty, impl_generics, phase, sig, 380 | ); 381 | impls.extend(tts); 382 | stages.push(CallStage::new( 383 | crate_name, quote!(_this), self_ty, Some(quote!(#phantom)), 384 | )); 385 | } 386 | } 387 | } 388 | 389 | let (impl_bounds, _, impl_where_bounds) = impl_generics.split_for_impl(); 390 | let synthetic_methods = if synthetic_methods.is_empty() { 391 | quote! { } 392 | } else { 393 | quote! { 394 | impl #impl_bounds #self_ty #impl_where_bounds { 395 | #(#synthetic_methods)* 396 | } 397 | } 398 | }; 399 | 400 | let group = CallGroup::new(quote!(_), stages); 401 | if methods.len() > 1 { 402 | impls.extend( 403 | make_merge_event_handler( 404 | crate_name, is_async_handler, 405 | EventHandlerTarget::Type(self_ty), impl_generics, 406 | Some(discriminator.clone()), 407 | vec![group], Vec::new(), 408 | ) 409 | ); 410 | } 411 | 412 | quote! { 413 | #[allow(non_snake_case)] 414 | const _: () = { 415 | #impls 416 | #(#extra_items)* 417 | #synthetic_methods 418 | }; 419 | } 420 | } 421 | 422 | fn mark_attrs_processed(method: &mut ImplItemMethod) { 423 | for attr in &mut method.attrs { 424 | if HandlerType::is_attr(attr) { 425 | mark_attribute_processed(attr); 426 | } 427 | } 428 | } 429 | 430 | /// Contains the implementation for `#[events_impl]`. 431 | pub struct EventsImplAttr { 432 | self_ty: Type, 433 | impl_generics: Generics, 434 | methods: Vec, 435 | synthetic_methods: Vec, 436 | extra_items: Vec, 437 | emit_input: bool, 438 | impl_input: ItemImpl, 439 | crate_name: SynTokenStream, 440 | discriminator: SynTokenStream, 441 | is_async_handler: bool, 442 | } 443 | impl EventsImplAttr { 444 | /// Parses an impl block. 445 | /// 446 | /// It takes a mutable reference to the impl block, as it may mark some attributes processed. 447 | pub fn new( 448 | impl_block: &mut ItemImpl, crate_name: Option, is_async_handler: bool, 449 | ) -> Result { 450 | let crate_name = crate_name.unwrap_or(quote! { ::static_events }); 451 | 452 | let mut handlers = Vec::new(); 453 | let mut errors = Error::empty(); 454 | 455 | for item in &mut impl_block.items { 456 | match item { 457 | ImplItem::Method(method) => { 458 | match MethodInfo::for_method(&crate_name, method, is_async_handler) { 459 | Ok(Some(handler)) => handlers.push(handler), 460 | Ok(None) => { } 461 | Err(e) => errors = errors.combine(e), 462 | } 463 | mark_attrs_processed(method); 464 | }, 465 | _ => { } 466 | } 467 | } 468 | if !errors.is_empty() { 469 | Err(errors) 470 | } else { 471 | Ok(EventsImplAttr { 472 | self_ty: (*impl_block.self_ty).clone(), 473 | impl_generics: impl_block.generics.clone(), 474 | methods: handlers, 475 | synthetic_methods: Vec::new(), 476 | extra_items: Vec::new(), 477 | emit_input: false, 478 | impl_input: impl_block.clone(), 479 | crate_name: crate_name.clone(), 480 | discriminator: quote!(#crate_name::private::HandlerImplBlock), 481 | is_async_handler, 482 | }) 483 | } 484 | } 485 | 486 | fn mark_emit_input(mut self) -> Self { 487 | self.emit_input = true; 488 | self 489 | } 490 | 491 | /// Parses a token stream. 492 | pub fn from_tokens(toks: impl ToTokens, is_async_handler: bool) -> Result { 493 | Ok(Self::new( 494 | &mut parse2(toks.into_token_stream())?, None, is_async_handler, 495 | )?.mark_emit_input()) 496 | } 497 | 498 | /// Parses a token stream. 499 | pub fn from_tokens_raw(toks: proc_macro::TokenStream, is_async_handler: bool) -> Result { 500 | Ok(Self::new( 501 | &mut parse(toks)?, None, is_async_handler, 502 | )?.mark_emit_input()) 503 | } 504 | 505 | /// Sets the discriminator of the generated impl block. 506 | pub fn set_discriminator(&mut self, toks: impl ToTokens) { 507 | self.discriminator = toks.into_token_stream(); 508 | } 509 | 510 | /// Processes an synthetic method, emitting it alongside the method's other impls. 511 | pub fn process_synthetic_method(&mut self, method: impl ToTokens) -> Result<()> { 512 | let mut method: ImplItemMethod = parse2(method.into_token_stream())?; 513 | match MethodInfo::for_method(&self.crate_name, &mut method, self.is_async_handler) { 514 | Ok(Some(handler)) => self.methods.push(handler), 515 | Ok(None) => { } 516 | Err(e) => return Err(e), 517 | } 518 | mark_attrs_processed(&mut method); 519 | self.synthetic_methods.push(method); 520 | Ok(()) 521 | } 522 | 523 | /// Adds an extra item into the const block. 524 | pub fn add_extra_item(&mut self, item: impl ToTokens) { 525 | self.extra_items.push(item.into_token_stream()); 526 | } 527 | 528 | /// Generates an impl block for the event handler implementation. 529 | pub fn generate(self) -> SynTokenStream { 530 | let impls = create_impls( 531 | &self.crate_name, &self.discriminator, self.is_async_handler, 532 | &self.self_ty, &self.impl_generics, &self.methods, 533 | &self.synthetic_methods, &self.extra_items, 534 | ); 535 | if self.emit_input { 536 | let input = self.impl_input; 537 | quote! { 538 | #input 539 | #impls 540 | } 541 | } else { 542 | impls 543 | } 544 | } 545 | } -------------------------------------------------------------------------------- /static-events_internals/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![recursion_limit="256"] 2 | 3 | extern crate proc_macro; 4 | 5 | #[macro_use] pub mod utils; 6 | 7 | mod common; 8 | mod derive; 9 | mod errors; 10 | mod handlers; 11 | 12 | pub use crate::errors::*; 13 | pub use crate::derive::DeriveStaticEvents; 14 | pub use crate::handlers::EventsImplAttr; -------------------------------------------------------------------------------- /static-events_internals/src/utils.rs: -------------------------------------------------------------------------------- 1 | //! Various helper methods that may help with static-events based procedural derives. 2 | 3 | use crate::errors::{Error, Result}; 4 | use proc_macro::TokenStream; 5 | use proc_macro2::{Span, TokenStream as SynTokenStream}; 6 | use std::fmt::Display; 7 | use syn::*; 8 | use quote::*; 9 | 10 | /// Creates an identifier with a format-like syntax. 11 | #[macro_export] 12 | macro_rules! ident { 13 | ($($tts:tt)*) => { Ident::new(&format!($($tts)*), ::proc_macro2::Span::call_site()) } 14 | } 15 | 16 | /// Emits a `syn` based compile error. 17 | pub fn error(span: Span, message: impl Display) -> Result { 18 | Err(Error::new(span, &message.to_string())) 19 | } 20 | 21 | /// Returns the actual type name of a path as a string. 22 | pub fn last_path_segment(path: &Path) -> String { 23 | (&path.segments).into_iter().last().expect("Empty path?").ident.to_string() 24 | } 25 | 26 | /// Helpers for parsing interior attributes in the outer block. 27 | const ATTR_OK_STR: &str = concat!( 28 | "(If you include this string in your crate, you are doing a bad, unstable thing.) ", 29 | "__", 30 | env!("CARGO_PKG_NAME"), 31 | "_attr_ok_2e72dd274be94c5e85063900550c326d_", 32 | env!("CARGO_PKG_VERSION"), 33 | ); 34 | 35 | fn smart_err_attr(attr: SynTokenStream, item: SynTokenStream, error: &str) -> SynTokenStream { 36 | syn::Error::new( 37 | stream_span(if attr.is_empty() { item } else { attr }), error, 38 | ).to_compile_error() 39 | } 40 | fn is_handler_valid(attr: SynTokenStream) -> bool { 41 | if attr.clone().into_iter().count() != 1 { return false } 42 | parse2::(attr).ok() 43 | .map(|x| match x { 44 | Lit::Str(s) => s.value() == ATTR_OK_STR, 45 | _ => false, 46 | }) 47 | .unwrap_or(false) 48 | } 49 | fn err_helper_attribute( 50 | error_str: &str, attr: SynTokenStream, item: SynTokenStream, 51 | ) -> SynTokenStream { 52 | if !is_handler_valid(attr.clone()) { 53 | smart_err_attr(attr, item, error_str) 54 | } else { 55 | SynTokenStream::new() 56 | } 57 | } 58 | 59 | /// Checks if an attribute has been processed via `mark_attribute_processed`. 60 | /// 61 | /// Not public API, use [`derived_attr!`] instead. 62 | #[doc(hidden)] 63 | pub fn check_attr(error_str: &str, attr: TokenStream, item: TokenStream) -> TokenStream { 64 | let item: SynTokenStream = item.into(); 65 | let error = err_helper_attribute(error_str, attr.into(), item.clone()); 66 | (quote! { 67 | #error 68 | #item 69 | }).into() 70 | } 71 | 72 | /// Creates a macro attribute that exists only to be processed by another macro attribute. 73 | /// 74 | /// The macro will result in an error if it's used outside the macro. The macro must be 75 | /// marked with [`mark_attribute_processed`] once processed to suppress this error. 76 | #[macro_export] 77 | macro_rules! derived_attr { 78 | (@error_str $attr:ident ($($head:tt)*) $inside:ident,) => { 79 | concat!( 80 | "#[", stringify!($attr), "] may only be used in a ", 81 | $($head)* "#[", stringify!($inside), "]", 82 | " block.", 83 | ) 84 | }; 85 | (@error_str $attr:ident ($($head:tt)*) $first:ident, $last:ident) => { 86 | concat!( 87 | "#[", stringify!($attr), "] may only be used in a ", 88 | $($head)* "#[", stringify!($first), "], or #[", stringify!($last), "]", 89 | " block.", 90 | ) 91 | }; 92 | (@error_str $attr:ident ($($head:tt)*) $inside:ident, $($rest:ident,)*) => { 93 | derived_attr!(@error_str ("#[", stringify!($inside), "], ",) $($rest,)*) 94 | }; 95 | ($event_name:ident, $($inside:ident),* $(,)?) => { 96 | #[proc_macro_attribute] 97 | pub fn $event_name(attr: TokenStream, item: TokenStream) -> TokenStream { 98 | const ERROR_STR: &str = derived_attr!(@error_str $event_name () $($inside,)*); 99 | crate::utils::check_attr(ERROR_STR, attr, item) 100 | } 101 | }; 102 | } 103 | 104 | /// Marks an attribute as having been successfully processed. 105 | /// 106 | /// See [`derived_attr!`]. 107 | pub fn mark_attribute_processed(attr: &mut Attribute) { 108 | attr.tokens = quote! { (#ATTR_OK_STR) }.into(); 109 | } 110 | 111 | /// Creates generics from a token stream. 112 | /// 113 | /// # Example 114 | /// 115 | /// ```rust 116 | /// # use static_events_internals::utils::generics; 117 | /// # use syn::Generics; 118 | /// # use quote::*; 119 | /// let generics: Generics = generics(quote! { 120 | /// A, B: Copy, 121 | /// }); 122 | /// # drop(generics); 123 | /// ``` 124 | pub fn generics(a: impl ToTokens) -> Generics { 125 | parse2::(quote! { < #a > }).unwrap() 126 | } 127 | 128 | /// Common function for processing generics. 129 | fn process_generics( 130 | list: &[&Generics], skip_lifetimes: bool, reparent_lifetimes: Option, 131 | ) -> Generics { 132 | let mut toks = SynTokenStream::new(); 133 | if !skip_lifetimes { 134 | for g in list { 135 | for lifetime in g.lifetimes() { 136 | let mut lifetime = (*lifetime).clone(); 137 | if let Some(lt) = &reparent_lifetimes { 138 | lifetime.bounds.push(lt.clone()); 139 | } 140 | toks.extend(quote! { #lifetime, }) 141 | } 142 | } 143 | } 144 | for g in list { 145 | for bound in g.type_params() { 146 | toks.extend(quote! { #bound, }) 147 | } 148 | for const_bound in g.const_params() { 149 | toks.extend(quote! { #const_bound, }) 150 | } 151 | } 152 | 153 | let mut generics = generics(toks); 154 | if list.iter().any(|x| x.where_clause.is_some()) { 155 | let mut toks = SynTokenStream::new(); 156 | toks.extend(quote! { where }); 157 | for g in list { 158 | for where_element in &(*g).clone().make_where_clause().predicates { 159 | toks.extend(quote! { #where_element, }) 160 | } 161 | } 162 | generics.where_clause = Some(parse2(toks).unwrap()); 163 | } 164 | generics 165 | } 166 | 167 | /// Merges two sets of generics into one. 168 | pub fn merge_generics(a: &Generics, b: &Generics) -> Generics { 169 | process_generics(&[a, b], false, None) 170 | } 171 | 172 | /// Strips lifetimes from a set of generics. 173 | pub fn strip_lifetimes(a: &Generics) -> Generics { 174 | process_generics(&[a], true, None) 175 | } 176 | 177 | /// Reparents the lifetimes in a set of generics. 178 | pub fn reparent_lifetimes(a: &Generics, lt: SynTokenStream) -> Generics { 179 | process_generics(&[a], false, Some(parse2(lt).unwrap())) 180 | } 181 | 182 | /// Creates a span for an entire TokenStream. 183 | pub fn stream_span(attr: SynTokenStream) -> Span { 184 | let head_span = attr.clone().into_iter().next().unwrap().span(); 185 | let tail_span = attr.into_iter().last().unwrap().span(); 186 | head_span.join(tail_span).unwrap() 187 | } 188 | --------------------------------------------------------------------------------