refactor(core): more bounds for better errors from #1623 (#1632)

This commit is contained in:
chip 2021-04-27 16:14:51 -07:00 committed by GitHub
parent 181e132aee
commit a755d23e1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 33 deletions

View File

@ -2,4 +2,22 @@
"tauri": patch
---
Simplify usage of app event and window label types.
Simplify usage of app event and window label types. The following functions now
accept references the `Tag` can be borrowed as. This means an `&str` can now be
accepted for functions like `Window::emit`. This is a breaking change for the
following items, which now need to take a reference. Additionally, type inference
for `&"event".into()` will no longer work, but `&"event".to_string()` will. The
solution for this is to now just pass `"event"` because `Borrow<str>` is implemented
for the default event type `String`.
* **Breaking:** `Window::emit` now accepts `Borrow` for the event.
* **Breaking:** `Window::emit_others` now accepts `Borrow` for the event
* **Breaking:** `Window::trigger` now accepts `Borrow` for the event.
* **Breaking:** `Manager::emit_all` now accepts `Borrow` for the event.
* **Breaking:** `Manager::emit_to` now accepts `Borrow` for both the event and window label.
* **Breaking:** `Manager::trigger_global` now accepts `Borrow` for the event.
* **Breaking:** `Manager::get_window` now accepts `Borrow` for the window label.
* _(internal):_ `trait tauri::runtime::tag::TagRef` helper for accepting tag references.
Any time you want to accept a tag reference, that trait will handle requiring the reference
to have all the necessary bounds, and generate errors when the exposed function doesn't
set a bound like `P::Event: Borrow<E>`.

View File

@ -192,10 +192,14 @@ impl<Event: Tag, Window: Tag> Listeners<Event, Window> {
}
/// Triggers the given global event with its payload.
pub(crate) fn trigger<E>(&self, event: &E, window: Option<Window>, payload: Option<String>)
where
E: TagRef<Event> + ?Sized,
pub(crate) fn trigger<E: ?Sized>(
&self,
event: &E,
window: Option<Window>,
payload: Option<String>,
) where
Event: Borrow<E>,
E: TagRef<Event>,
{
let mut maybe_pending = false;
match self.inner.handlers.try_lock() {

View File

@ -139,24 +139,27 @@ pub trait Manager<P: Params>: sealed::ManagerBase<P> {
}
/// Emits a event to all windows.
fn emit_all<E, S>(&self, event: &E, payload: Option<S>) -> Result<()>
fn emit_all<E: ?Sized, S>(&self, event: &E, payload: Option<S>) -> Result<()>
where
E: TagRef<P::Event> + ?Sized,
P::Event: Borrow<E>,
E: TagRef<P::Event>,
S: Serialize + Clone,
{
self.manager().emit_filter(event, payload, |_| true)
}
/// Emits an event to a window with the specified label.
fn emit_to<E, L, S: Serialize + Clone>(
fn emit_to<E: ?Sized, L: ?Sized, S: Serialize + Clone>(
&self,
label: &L,
event: &E,
payload: Option<S>,
) -> Result<()>
where
L: TagRef<P::Label> + ?Sized,
E: TagRef<P::Event> + ?Sized,
P::Label: Borrow<L>,
P::Event: Borrow<E>,
L: TagRef<P::Label>,
E: TagRef<P::Event>,
{
self
.manager()
@ -193,10 +196,10 @@ pub trait Manager<P: Params>: sealed::ManagerBase<P> {
}
/// Trigger a global event.
fn trigger_global<E>(&self, event: &E, data: Option<String>)
fn trigger_global<E: ?Sized>(&self, event: &E, data: Option<String>)
where
E: TagRef<P::Event> + ?Sized,
P::Event: Borrow<E>,
E: TagRef<P::Event>,
{
self.manager().trigger(event, None, data)
}
@ -207,10 +210,10 @@ pub trait Manager<P: Params>: sealed::ManagerBase<P> {
}
/// Fetch a single window from the manager.
fn get_window<L>(&self, label: &L) -> Option<Window<P>>
fn get_window<L: ?Sized>(&self, label: &L) -> Option<Window<P>>
where
L: TagRef<P::Label> + ?Sized,
P::Label: Borrow<L>,
L: TagRef<P::Label>,
{
self.manager().get_window(label)
}

View File

@ -493,9 +493,15 @@ impl<P: Params> WindowManager<P> {
window
}
pub fn emit_filter<E, S, F>(&self, event: &E, payload: Option<S>, filter: F) -> crate::Result<()>
pub fn emit_filter<E: ?Sized, S, F>(
&self,
event: &E,
payload: Option<S>,
filter: F,
) -> crate::Result<()>
where
E: TagRef<P::Event> + ?Sized,
P::Event: Borrow<E>,
E: TagRef<P::Event>,
S: Serialize + Clone,
F: Fn(&Window<P>) -> bool,
{
@ -519,10 +525,10 @@ impl<P: Params> WindowManager<P> {
self.inner.listeners.unlisten(handler_id)
}
pub fn trigger<E>(&self, event: &E, window: Option<P::Label>, data: Option<String>)
pub fn trigger<E: ?Sized>(&self, event: &E, window: Option<P::Label>, data: Option<String>)
where
E: TagRef<P::Event> + ?Sized,
P::Event: Borrow<E>,
E: TagRef<P::Event>,
{
self.inner.listeners.trigger(event, window, data)
}
@ -578,10 +584,10 @@ impl<P: Params> WindowManager<P> {
.remove(&uuid)
}
pub fn get_window<L>(&self, label: &L) -> Option<Window<P>>
pub fn get_window<L: ?Sized>(&self, label: &L) -> Option<Window<P>>
where
L: TagRef<P::Label> + ?Sized,
P::Label: Borrow<L>,
L: TagRef<P::Label>,
{
self.windows_lock().get(label).cloned()
}

View File

@ -91,11 +91,17 @@ impl<T, E: Debug> Tag for T where
/// * [`ToOwned`] to make sure we can clone it into the owned tag in specific cases.
/// * [`PartialEq`] so that we can compare refs to the owned tags easily.
/// * [`Hash`] + [`Eq`] because we want to be able to use a ref as a key to internal hashmaps.
pub trait TagRef<T: Tag>: Display + ToOwned<Owned = T> + PartialEq<T> + Eq + Hash {}
pub trait TagRef<T: Tag>: Display + ToOwned<Owned = T> + PartialEq<T> + Eq + Hash
where
T: std::borrow::Borrow<Self>,
{
}
/// Automatically implement [`TagRef`] for all types that fit the requirements.
impl<T: Tag, R> TagRef<T> for R where
R: Display + ToOwned<Owned = T> + PartialEq<T> + Eq + Hash + ?Sized
impl<T: Tag, R> TagRef<T> for R
where
T: std::borrow::Borrow<R>,
R: Display + ToOwned<Owned = T> + PartialEq<T> + Eq + Hash + ?Sized,
{
}

View File

@ -196,9 +196,14 @@ pub(crate) mod export {
&self.window.label
}
pub(crate) fn emit_internal<E, S>(&self, event: &E, payload: Option<S>) -> crate::Result<()>
pub(crate) fn emit_internal<E: ?Sized, S>(
&self,
event: &E,
payload: Option<S>,
) -> crate::Result<()>
where
E: TagRef<P::Event> + ?Sized,
P::Event: Borrow<E>,
E: TagRef<P::Event>,
S: Serialize,
{
let js_payload = match payload {
@ -218,20 +223,22 @@ pub(crate) mod export {
}
/// Emits an event to the current window.
pub fn emit<E, S>(&self, event: &E, payload: Option<S>) -> crate::Result<()>
pub fn emit<E: ?Sized, S>(&self, event: &E, payload: Option<S>) -> crate::Result<()>
where
E: TagRef<P::Event> + ?Sized,
P::Event: Borrow<E>,
E: TagRef<P::Event>,
S: Serialize,
{
self.emit_internal(event, payload)
}
/// Emits an event on all windows except this one.
pub fn emit_others<E: TagRef<P::Event> + ?Sized, S: Serialize + Clone>(
&self,
event: &E,
payload: Option<S>,
) -> crate::Result<()> {
pub fn emit_others<E: ?Sized, S>(&self, event: &E, payload: Option<S>) -> crate::Result<()>
where
P::Event: Borrow<E>,
E: TagRef<P::Event>,
S: Serialize + Clone,
{
self.manager.emit_filter(event, payload, |w| w != self)
}
@ -254,10 +261,10 @@ pub(crate) mod export {
}
/// Triggers an event on this window.
pub fn trigger<E>(&self, event: &E, data: Option<String>)
pub fn trigger<E: ?Sized>(&self, event: &E, data: Option<String>)
where
E: TagRef<P::Event> + ?Sized,
P::Event: Borrow<E>,
E: TagRef<P::Event>,
{
let label = self.window.label.clone();
self.manager.trigger(event, Some(label), data)