Thanks to visit codestin.com
Credit goes to docs.rs

Struct KeyInput

Source
pub struct KeyInput { /* private fields */ }
Expand description

Single key input by pressing a key and modifiers.

This struct is equivalent to a key combination in the syntax document such as “Ctrl+x”.

Implementations§

Source§

impl KeyInput

Source

pub fn new<K, M>(key: K, mods: M) -> Self
where K: Into<Key>, M: Into<Mods>,

Create a new KeyInput instance with checking the Shift modifier restriction described in the syntax document.

use keybinds::{KeyInput, Key, Mods};

let k = KeyInput::new('x', Mods::CTRL);
assert_eq!(k.key(), Key::Char('x'));
assert_eq!(k.mods(), Mods::CTRL);

let k = KeyInput::new(Key::Enter, Mods::MOD);
assert_eq!(k.key(), Key::Enter);
assert_eq!(k.mods(), Mods::MOD);

// Shift modifier is removed when it is not used with named keys following the restriction.
let k = KeyInput::new('x', Mods::SHIFT | Mods::CTRL);
assert_eq!(k.key(), Key::Char('x'));
assert_eq!(k.mods(), Mods::CTRL);

// You need to use the following instead.
let k = KeyInput::new('X', Mods::CTRL);
assert_eq!(k.key(), Key::Char('X'));
assert_eq!(k.mods(), Mods::CTRL);
Source

pub fn key(&self) -> Key

Return the Key of the input.

Examples found in repository?
examples/vim.rs (line 401)
396    fn convert_key_input(&self, input: KeyInput) -> Option<Input> {
397        if self.mode != Mode::Insert {
398            return None;
399        }
400
401        let key = match input.key() {
402            keybinds::Key::Char(c) => Key::Char(c),
403            keybinds::Key::Copy => Key::Copy,
404            keybinds::Key::Cut => Key::Cut,
405            keybinds::Key::Paste => Key::Paste,
406            keybinds::Key::Backspace => Key::Backspace,
407            keybinds::Key::Delete => Key::Delete,
408            keybinds::Key::Enter => Key::Enter,
409            keybinds::Key::Up => Key::Up,
410            keybinds::Key::Right => Key::Right,
411            keybinds::Key::Down => Key::Down,
412            keybinds::Key::Left => Key::Left,
413            keybinds::Key::Home => Key::Home,
414            keybinds::Key::End => Key::End,
415            keybinds::Key::PageUp => Key::PageUp,
416            keybinds::Key::PageDown => Key::PageDown,
417            keybinds::Key::Tab => Key::Tab,
418            _ => return None,
419        };
420
421        let mods = input.mods();
422        Some(Input {
423            key,
424            ctrl: mods.contains(Mods::CTRL),
425            alt: mods.contains(Mods::ALT),
426            shift: mods.contains(Mods::SHIFT),
427        })
428    }
More examples
Hide additional examples
examples/winit.rs (line 52)
49    fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
50        // Convert the window event into key input
51        let input = self.converter.convert(&event);
52        if input.key() != Key::Ignored {
53            println!("Key input: {input:?}");
54        }
55
56        // Check if the converted key input dispatches some action
57        if let Some(action) = self.keybinds.dispatch(input) {
58            println!("Action: {action:?}");
59
60            match action {
61                Action::SayHi => println!("Hi!"),
62                Action::ToggleMaximized => {
63                    let window = self.window.as_ref().unwrap();
64                    window.set_maximized(!window.is_maximized());
65                }
66                Action::ToggleTheme => {
67                    let window = self.window.as_ref().unwrap();
68                    let theme = match window.theme() {
69                        Some(Theme::Dark) => Theme::Light,
70                        _ => Theme::Dark,
71                    };
72                    window.set_theme(Some(theme));
73                }
74                Action::Exit => event_loop.exit(),
75            }
76        }
77
78        if let WindowEvent::CloseRequested = event {
79            event_loop.exit();
80        }
81    }
examples/iced.rs (line 67)
62    fn update(&mut self, message: Message) -> Task<Message> {
63        match message {
64            Message::WindowOpen(id) => self.window_id = id,
65            Message::KeyEvent(event) => {
66                let input = KeyInput::from(&event);
67                if input.key() != Key::Ignored {
68                    println!("Key input: {input:?}");
69                    if !self.keybinds.is_ongoing() {
70                        self.last_action.clear();
71                        self.ongoing_input.clear();
72                    }
73                    if !self.ongoing_input.is_empty() {
74                        self.ongoing_input.push_str(" → ");
75                    }
76                    write!(self.ongoing_input, "{input:}").unwrap();
77                }
78
79                if let Some(action) = self.keybinds.dispatch(event) {
80                    self.last_action = format!("{action:?}");
81
82                    // Handle the dispatched action
83                    match action {
84                        Action::SayHello => println!("Hello!"),
85                        Action::ToggleMaximize => {
86                            self.maximized = !self.maximized;
87                            return window::maximize(self.window_id, self.maximized);
88                        }
89                        Action::ToggleTheme => {
90                            self.theme = match self.theme {
91                                Theme::Dark => Theme::Light,
92                                _ => Theme::Dark,
93                            };
94                        }
95                        Action::Exit => return iced::exit(),
96                    }
97                }
98            }
99            Message::Reset => {
100                self.keybinds.reset();
101                self.ongoing_input.clear();
102                self.last_action.clear();
103            }
104        }
105        Task::none()
106    }
Source

pub fn mods(&self) -> Mods

Return the Mods of the input.

Examples found in repository?
examples/vim.rs (line 421)
396    fn convert_key_input(&self, input: KeyInput) -> Option<Input> {
397        if self.mode != Mode::Insert {
398            return None;
399        }
400
401        let key = match input.key() {
402            keybinds::Key::Char(c) => Key::Char(c),
403            keybinds::Key::Copy => Key::Copy,
404            keybinds::Key::Cut => Key::Cut,
405            keybinds::Key::Paste => Key::Paste,
406            keybinds::Key::Backspace => Key::Backspace,
407            keybinds::Key::Delete => Key::Delete,
408            keybinds::Key::Enter => Key::Enter,
409            keybinds::Key::Up => Key::Up,
410            keybinds::Key::Right => Key::Right,
411            keybinds::Key::Down => Key::Down,
412            keybinds::Key::Left => Key::Left,
413            keybinds::Key::Home => Key::Home,
414            keybinds::Key::End => Key::End,
415            keybinds::Key::PageUp => Key::PageUp,
416            keybinds::Key::PageDown => Key::PageDown,
417            keybinds::Key::Tab => Key::Tab,
418            _ => return None,
419        };
420
421        let mods = input.mods();
422        Some(Input {
423            key,
424            ctrl: mods.contains(Mods::CTRL),
425            alt: mods.contains(Mods::ALT),
426            shift: mods.contains(Mods::SHIFT),
427        })
428    }

Trait Implementations§

Source§

impl<'arbitrary> Arbitrary<'arbitrary> for KeyInput

Source§

fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the given unstructured data. Read more
Source§

fn arbitrary_take_rest(u: Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the entirety of the given unstructured data. Read more
Source§

fn size_hint(depth: usize) -> (usize, Option<usize>)

Get a size hint for how many bytes out of an Unstructured this type needs to construct itself. Read more
Source§

fn try_size_hint( depth: usize, ) -> Result<(usize, Option<usize>), MaxRecursionReached>

Get a size hint for how many bytes out of an Unstructured this type needs to construct itself. Read more
Source§

impl Clone for KeyInput

Source§

fn clone(&self) -> KeyInput

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for KeyInput

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for KeyInput

Available on crate feature serde only.
Source§

fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for KeyInput

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Generate a string representation of the key input following the syntax.

use keybinds::{Key, Mods, KeyInput};

assert_eq!(format!("{}", KeyInput::new('x', Mods::CTRL)), "Ctrl+x");
assert_eq!(
    format!("{}", KeyInput::new(Key::Enter, Mods::SHIFT | Mods::ALT)),
    "Alt+Shift+Enter",
);
Source§

impl From<&Event> for KeyInput

Available on crate feature crossterm only.
Source§

fn from(event: &Event) -> Self

Convert crossterm’s events to KeyInput. Events unrelated to key presses are converted into Key::Ignored with no modifiers.

Source§

impl From<&Event> for KeyInput

Available on crate feature iced only.
Source§

fn from(event: &KeyEvent) -> Self

Convert iced’s key events to KeyInput. Events except for key presses are converted into Key::Ignored with no modifiers. Note that Shift modifier is removed when the pressed key is unnamed following the syntax.

use keybinds::{KeyInput, Mods};
use iced::keyboard::{Event, Modifiers, Key};

// Key event for Ctrl+Shift+X
let event = Event::KeyPressed {
    key: Key::Character("x".into()),
    modified_key: Key::Character("X".into()),
    modifiers: Modifiers::CTRL | Modifiers::SHIFT,
    // ...
};
// `Mods::SHIFT` is removed because 'X' is already modified by Shift key
assert_eq!(KeyInput::from(event), KeyInput::new('X', Mods::CTRL));

// Events other than key presses are ignored
let event = Event::KeyReleased {
    // ...
};
assert_eq!(KeyInput::from(event), KeyInput::from(keybinds::Key::Ignored));
Source§

impl From<&Event> for KeyInput

Available on crate feature iced only.
Source§

fn from(event: &Event) -> Self

Convert iced’s events to KeyInput. Events unrelated to key presses are converted into Key::Ignored with no modifiers.

Source§

impl From<&InputEvent> for KeyInput

Available on crate feature termwiz only.
Source§

fn from(event: &InputEvent) -> Self

Converts to this type from the input type.
Source§

impl From<&KeyEvent> for KeyInput

Available on crate feature crossterm only.
Source§

fn from(event: &KeyEvent) -> Self

Convert crossterm’s key events to KeyInput. The key release events are converted into Key::Ignored with no modifiers.

Source§

impl From<&KeyEvent> for KeyInput

Available on crate feature termwiz only.
Source§

fn from(event: &KeyEvent) -> Self

Converts to this type from the input type.
Source§

impl From<Event> for KeyInput

Available on crate feature crossterm only.
Source§

fn from(event: Event) -> Self

Converts to this type from the input type.
Source§

impl From<Event> for KeyInput

Available on crate feature iced only.
Source§

fn from(event: KeyEvent) -> Self

Converts to this type from the input type.
Source§

impl From<Event> for KeyInput

Available on crate feature iced only.
Source§

fn from(event: Event) -> Self

Converts to this type from the input type.
Source§

impl From<InputEvent> for KeyInput

Available on crate feature termwiz only.
Source§

fn from(event: InputEvent) -> Self

Converts to this type from the input type.
Source§

impl<K: Into<Key>> From<K> for KeyInput

Source§

fn from(k: K) -> Self

Convert a single key with no modifiers into KeyInput.

use keybinds::{KeyInput, Mods};

assert_eq!(KeyInput::from('x'), KeyInput::new('x', Mods::NONE));
Source§

impl From<KeyEvent> for KeyInput

Available on crate feature crossterm only.
Source§

fn from(event: KeyEvent) -> Self

Converts to this type from the input type.
Source§

impl From<KeyEvent> for KeyInput

Available on crate feature termwiz only.
Source§

fn from(event: KeyEvent) -> Self

Converts to this type from the input type.
Source§

impl FromStr for KeyInput

Source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parse the key input from str following the syntax.

use keybinds::{Key, Mods, KeyInput};

assert_eq!("a".parse(), Ok(KeyInput::new('a', Mods::NONE)));
assert_eq!("Ctrl+x".parse(), Ok(KeyInput::new('x', Mods::CTRL)));
assert_eq!("Alt+Shift+Enter".parse(), Ok(KeyInput::new(Key::Enter, Mods::ALT | Mods::SHIFT)));

assert!("".parse::<KeyInput>().is_err());
assert!("Foooo".parse::<KeyInput>().is_err());
assert!("Shift+x".parse::<KeyInput>().is_err()); // Violates Shift modifier invariant
Source§

type Err = Error

The associated error which can be returned from parsing.
Source§

impl Hash for KeyInput

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for KeyInput

Source§

fn eq(&self, other: &KeyInput) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for KeyInput

Available on crate feature serde only.
Source§

fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>

Serialize this value into the given Serde serializer. Read more
Source§

impl Copy for KeyInput

Source§

impl Eq for KeyInput

Source§

impl StructuralPartialEq for KeyInput

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

Convert the source color to the destination color using the bradford method by default.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CallHasher for T
where T: Hash + ?Sized,

Source§

default fn get_hash<H, B>(value: &H, build_hasher: &B) -> u64
where H: Hash + ?Sized, B: BuildHasher,

Source§

impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToSmolStr for T
where T: Display + ?Sized,

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> MaybeSend for T
where T: Send,

Source§

impl<T> MaybeSync for T
where T: Sync,

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,