From 264aed722d34fa9ebc3a210c0c1ffe21f2f6131a Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Fri, 1 Sep 2023 15:13:20 +0300 Subject: [PATCH] refactor: seal `IsMenuItem` trait --- .changes/item-into-id.md | 2 +- src/items/check.rs | 9 +++++++-- src/items/icon.rs | 8 +++++++- src/items/normal.rs | 9 +++++++-- src/items/predefined.rs | 8 +++++++- src/items/submenu.rs | 11 +++++++++-- src/lib.rs | 17 ++++++++++------- 7 files changed, 48 insertions(+), 16 deletions(-) diff --git a/.changes/item-into-id.md b/.changes/item-into-id.md index b98c36f..9a8be20 100644 --- a/.changes/item-into-id.md +++ b/.changes/item-into-id.md @@ -2,4 +2,4 @@ "muda": "patch" --- -Added `into_id` method to `MenuItem`, `CheckMenuItem`, `PredefinedMenuItem`, `Submenu`, and `MenuItemKind`. It moves the menu item into its menu ID. +Added `into_id` method to `MenuItem`, `CheckMenuItem`, `PredefinedMenuItem`, `Submenu`, `MenuItemKind` and `IsMenuItem` trait. It moves the menu item into its id. diff --git a/src/items/check.rs b/src/items/check.rs index a994f16..cc562a4 100644 --- a/src/items/check.rs +++ b/src/items/check.rs @@ -4,7 +4,7 @@ use std::{cell::RefCell, mem, rc::Rc}; -use crate::{accelerator::Accelerator, IsMenuItem, MenuId, MenuItemKind}; +use crate::{accelerator::Accelerator, sealed::IsMenuItemBase, IsMenuItem, MenuId, MenuItemKind}; /// A check menu item inside a [`Menu`] or [`Submenu`] /// and usually contains a text and a check mark or a similar toggle @@ -18,7 +18,8 @@ pub struct CheckMenuItem { pub(crate) inner: Rc>, } -unsafe impl IsMenuItem for CheckMenuItem { +impl IsMenuItemBase for CheckMenuItem {} +impl IsMenuItem for CheckMenuItem { fn kind(&self) -> MenuItemKind { MenuItemKind::Check(self.clone()) } @@ -26,6 +27,10 @@ unsafe impl IsMenuItem for CheckMenuItem { fn id(&self) -> &MenuId { self.id() } + + fn into_id(self) -> MenuId { + self.into_id() + } } impl CheckMenuItem { diff --git a/src/items/icon.rs b/src/items/icon.rs index 6738ec5..5342ad9 100644 --- a/src/items/icon.rs +++ b/src/items/icon.rs @@ -7,6 +7,7 @@ use std::{cell::RefCell, mem, rc::Rc}; use crate::{ accelerator::Accelerator, icon::{Icon, NativeIcon}, + sealed::IsMenuItemBase, IsMenuItem, MenuId, MenuItemKind, }; @@ -21,7 +22,8 @@ pub struct IconMenuItem { pub(crate) inner: Rc>, } -unsafe impl IsMenuItem for IconMenuItem { +impl IsMenuItemBase for IconMenuItem {} +impl IsMenuItem for IconMenuItem { fn kind(&self) -> MenuItemKind { MenuItemKind::Icon(self.clone()) } @@ -29,6 +31,10 @@ unsafe impl IsMenuItem for IconMenuItem { fn id(&self) -> &MenuId { self.id() } + + fn into_id(self) -> MenuId { + self.into_id() + } } impl IconMenuItem { diff --git a/src/items/normal.rs b/src/items/normal.rs index fef0dee..8e1c344 100644 --- a/src/items/normal.rs +++ b/src/items/normal.rs @@ -1,6 +1,6 @@ use std::{cell::RefCell, mem, rc::Rc}; -use crate::{accelerator::Accelerator, IsMenuItem, MenuId, MenuItemKind}; +use crate::{accelerator::Accelerator, sealed::IsMenuItemBase, IsMenuItem, MenuId, MenuItemKind}; /// A menu item inside a [`Menu`] or [`Submenu`] and contains only text. /// @@ -12,7 +12,8 @@ pub struct MenuItem { pub(crate) inner: Rc>, } -unsafe impl IsMenuItem for MenuItem { +impl IsMenuItemBase for MenuItem {} +impl IsMenuItem for MenuItem { fn kind(&self) -> MenuItemKind { MenuItemKind::MenuItem(self.clone()) } @@ -20,6 +21,10 @@ unsafe impl IsMenuItem for MenuItem { fn id(&self) -> &MenuId { self.id() } + + fn into_id(self) -> MenuId { + self.into_id() + } } impl MenuItem { diff --git a/src/items/predefined.rs b/src/items/predefined.rs index a9c80e0..0574bca 100644 --- a/src/items/predefined.rs +++ b/src/items/predefined.rs @@ -6,6 +6,7 @@ use std::{cell::RefCell, mem, rc::Rc}; use crate::{ accelerator::{Accelerator, CMD_OR_CTRL}, + sealed::IsMenuItemBase, AboutMetadata, IsMenuItem, MenuId, MenuItemKind, }; use keyboard_types::{Code, Modifiers}; @@ -17,7 +18,8 @@ pub struct PredefinedMenuItem { pub(crate) inner: Rc>, } -unsafe impl IsMenuItem for PredefinedMenuItem { +impl IsMenuItemBase for PredefinedMenuItem {} +impl IsMenuItem for PredefinedMenuItem { fn kind(&self) -> MenuItemKind { MenuItemKind::Predefined(self.clone()) } @@ -25,6 +27,10 @@ unsafe impl IsMenuItem for PredefinedMenuItem { fn id(&self) -> &MenuId { self.id() } + + fn into_id(self) -> MenuId { + self.into_id() + } } impl PredefinedMenuItem { diff --git a/src/items/submenu.rs b/src/items/submenu.rs index a6f1524..cd3cc87 100644 --- a/src/items/submenu.rs +++ b/src/items/submenu.rs @@ -4,7 +4,9 @@ use std::{cell::RefCell, mem, rc::Rc}; -use crate::{util::AddOp, ContextMenu, IsMenuItem, MenuId, MenuItemKind, Position}; +use crate::{ + sealed::IsMenuItemBase, util::AddOp, ContextMenu, IsMenuItem, MenuId, MenuItemKind, Position, +}; /// A menu that can be added to a [`Menu`] or another [`Submenu`]. /// @@ -15,7 +17,8 @@ pub struct Submenu { pub(crate) inner: Rc>, } -unsafe impl IsMenuItem for Submenu { +impl IsMenuItemBase for Submenu {} +impl IsMenuItem for Submenu { fn kind(&self) -> MenuItemKind { MenuItemKind::Submenu(self.clone()) } @@ -23,6 +26,10 @@ unsafe impl IsMenuItem for Submenu { fn id(&self) -> &MenuId { self.id() } + + fn into_id(self) -> MenuId { + self.into_id() + } } impl Submenu { diff --git a/src/lib.rs b/src/lib.rs index ebefc8c..95be568 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -166,7 +166,7 @@ pub enum MenuItemKind { } impl MenuItemKind { - /// Returns the id associated with this menu item. + /// Returns a unique identifier associated with this menu item. pub fn id(&self) -> &MenuId { match self { MenuItemKind::MenuItem(i) => i.id(), @@ -270,14 +270,17 @@ impl MenuItemKind { } /// A trait that defines a generic item in a menu, which may be one of [`MenuItemKind`] -/// -/// # Safety -/// -/// This trait is ONLY meant to be implemented internally by the crate. -pub unsafe trait IsMenuItem { +pub trait IsMenuItem: sealed::IsMenuItemBase { + /// Returns a [`MenuItemKind`] associated with this item. fn kind(&self) -> MenuItemKind; - + /// Returns a unique identifier associated with this menu item. fn id(&self) -> &MenuId; + /// Convert this menu item into its menu ID. + fn into_id(self) -> MenuId; +} + +mod sealed { + pub trait IsMenuItemBase {} } #[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]