pub struct Mask<T, const N: usize>(/* private fields */)
where
T: MaskElement;portable_simd)Expand description
A SIMD vector mask for N elements of width specified by Element.
Masks represent boolean inclusion/exclusion on a per-element basis.
The layout of this type is unspecified, and may change between platforms
and/or Rust versions, and code should not assume that it is equivalent to
[T; N].
N cannot be 0 and may be at most 64. This limit may be increased in
the future.
Implementationsยง
Sourceยงimpl<T, const N: usize> Mask<T, N>where
T: MaskElement,
impl<T, const N: usize> Mask<T, N>where
T: MaskElement,
Sourcepub fn reverse(self) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn reverse(self) -> Mask<T, N>
portable_simd)Reverse the order of the elements in the mask.
Sourcepub fn rotate_elements_left<const OFFSET: usize>(self) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn rotate_elements_left<const OFFSET: usize>(self) -> Mask<T, N>
portable_simd)Rotates the mask such that the first OFFSET elements of the slice move to the end
while the last self.len() - OFFSET elements move to the front. After calling rotate_elements_left,
the element previously at index OFFSET will become the first element in the slice.
Sourcepub fn rotate_elements_right<const OFFSET: usize>(self) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn rotate_elements_right<const OFFSET: usize>(self) -> Mask<T, N>
portable_simd)Rotates the mask such that the first self.len() - OFFSET elements of the mask move to
the end while the last OFFSET elements move to the front. After calling rotate_elements_right,
the element previously at index self.len() - OFFSET will become the first element in the slice.
Sourcepub fn shift_elements_left<const OFFSET: usize>(
self,
padding: bool,
) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn shift_elements_left<const OFFSET: usize>( self, padding: bool, ) -> Mask<T, N>
portable_simd)Shifts the mask elements to the left by OFFSET, filling in with
padding from the right.
Sourcepub fn shift_elements_right<const OFFSET: usize>(
self,
padding: bool,
) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn shift_elements_right<const OFFSET: usize>( self, padding: bool, ) -> Mask<T, N>
portable_simd)Shifts the mask elements to the right by OFFSET, filling in with
padding from the left.
Sourcepub fn interleave(self, other: Mask<T, N>) -> (Mask<T, N>, Mask<T, N>)
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn interleave(self, other: Mask<T, N>) -> (Mask<T, N>, Mask<T, N>)
portable_simd)Interleave two masks.
The resulting masks contain elements taken alternatively from self and other, first
filling the first result, and then the second.
The reverse of this operation is Mask::deinterleave.
let a = mask32x4::from_array([false, true, false, true]);
let b = mask32x4::from_array([false, false, true, true]);
let (x, y) = a.interleave(b);
assert_eq!(x.to_array(), [false, false, true, false]);
assert_eq!(y.to_array(), [false, true, true, true]);Sourcepub fn deinterleave(self, other: Mask<T, N>) -> (Mask<T, N>, Mask<T, N>)
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn deinterleave(self, other: Mask<T, N>) -> (Mask<T, N>, Mask<T, N>)
portable_simd)Deinterleave two masks.
The first result takes every other element of self and then other, starting with
the first element.
The second result takes every other element of self and then other, starting with
the second element.
The reverse of this operation is Mask::interleave.
let a = mask32x4::from_array([false, true, false, true]);
let b = mask32x4::from_array([false, false, true, true]);
let (x, y) = a.deinterleave(b);
assert_eq!(x.to_array(), [false, false, false, true]);
assert_eq!(y.to_array(), [true, true, false, true]);Sourcepub fn resize<const M: usize>(self, value: bool) -> Mask<T, M>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn resize<const M: usize>(self, value: bool) -> Mask<T, M>
portable_simd)Resize a mask.
If M > N, extends the length of a mask, setting the new elements to value.
If M < N, truncates the mask to the first M elements.
let x = mask32x4::from_array([false, true, true, false]);
assert_eq!(x.resize::<8>(true).to_array(), [false, true, true, false, true, true, true, true]);
assert_eq!(x.resize::<2>(true).to_array(), [false, true]);Sourceยงimpl<T, const N: usize> Mask<T, N>where
T: MaskElement,
impl<T, const N: usize> Mask<T, N>where
T: MaskElement,
Sourcepub const fn splat(value: bool) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub const fn splat(value: bool) -> Mask<T, N>
portable_simd)Constructs a mask by setting all elements to the given value.
Sourcepub fn from_array(array: [bool; N]) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn from_array(array: [bool; N]) -> Mask<T, N>
portable_simd)Converts an array of bools to a SIMD mask.
Sourcepub fn to_array(self) -> [bool; N]
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn to_array(self) -> [bool; N]
portable_simd)Converts a SIMD mask to an array of bools.
Sourcepub unsafe fn from_simd_unchecked(value: Simd<T, N>) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub unsafe fn from_simd_unchecked(value: Simd<T, N>) -> Mask<T, N>
portable_simd)Converts a vector of integers to a mask, where 0 represents false and -1
represents true.
ยงSafety
All elements must be either 0 or -1.
Sourcepub fn from_simd(value: Simd<T, N>) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn from_simd(value: Simd<T, N>) -> Mask<T, N>
portable_simd)Converts a vector of integers to a mask, where 0 represents false and -1
represents true.
ยงPanics
Panics if any element is not 0 or -1.
Sourcepub fn to_simd(self) -> Simd<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn to_simd(self) -> Simd<T, N>
portable_simd)Converts the mask to a vector of integers, where 0 represents false and -1
represents true.
Sourcepub fn cast<U>(self) -> Mask<U, N>where
U: MaskElement,
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn cast<U>(self) -> Mask<U, N>where
U: MaskElement,
portable_simd)Converts the mask to a mask of any other element size.
Sourcepub unsafe fn test_unchecked(&self, index: usize) -> bool
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub unsafe fn test_unchecked(&self, index: usize) -> bool
portable_simd)Sourcepub fn test(&self, index: usize) -> bool
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn test(&self, index: usize) -> bool
portable_simd)Tests the value of the specified element.
ยงPanics
Panics if index is greater than or equal to the number of elements in the vector.
Sourcepub unsafe fn set_unchecked(&mut self, index: usize, value: bool)
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub unsafe fn set_unchecked(&mut self, index: usize, value: bool)
portable_simd)Sourcepub fn set(&mut self, index: usize, value: bool)
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn set(&mut self, index: usize, value: bool)
portable_simd)Sets the value of the specified element.
ยงPanics
Panics if index is greater than or equal to the number of elements in the vector.
Sourcepub fn any(self) -> bool
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn any(self) -> bool
portable_simd)Returns true if any element is set, or false otherwise.
Sourcepub fn all(self) -> bool
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn all(self) -> bool
portable_simd)Returns true if all elements are set, or false otherwise.
Sourcepub fn to_bitmask(self) -> u64
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn to_bitmask(self) -> u64
portable_simd)Creates a bitmask from a mask.
Each bit is set if the corresponding element in the mask is true.
Sourcepub fn from_bitmask(bitmask: u64) -> Mask<T, N>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn from_bitmask(bitmask: u64) -> Mask<T, N>
portable_simd)Creates a mask from a bitmask.
For each bit, if it is set, the corresponding element in the mask is set to true.
If the mask contains more than 64 elements, the remainder are set to false.
Sourcepub fn first_set(self) -> Option<usize>
๐ฌThis is a nightly-only experimental API. (portable_simd)
pub fn first_set(self) -> Option<usize>
portable_simd)Finds the index of the first set element.
assert_eq!(mask32x8::splat(false).first_set(), None);
assert_eq!(mask32x8::splat(true).first_set(), Some(0));
let mask = mask32x8::from_array([false, true, false, false, true, false, false, true]);
assert_eq!(mask.first_set(), Some(1));Trait Implementationsยง
Sourceยงimpl<T, const N: usize> BitAndAssign<bool> for Mask<T, N>where
T: MaskElement,
impl<T, const N: usize> BitAndAssign<bool> for Mask<T, N>where
T: MaskElement,
Sourceยงfn bitand_assign(&mut self, rhs: bool)
fn bitand_assign(&mut self, rhs: bool)
&= operation. Read moreSourceยงimpl<T, const N: usize> BitAndAssign for Mask<T, N>where
T: MaskElement,
impl<T, const N: usize> BitAndAssign for Mask<T, N>where
T: MaskElement,
Sourceยงfn bitand_assign(&mut self, rhs: Mask<T, N>)
fn bitand_assign(&mut self, rhs: Mask<T, N>)
&= operation. Read moreSourceยงimpl<T, const N: usize> BitOrAssign<bool> for Mask<T, N>where
T: MaskElement,
impl<T, const N: usize> BitOrAssign<bool> for Mask<T, N>where
T: MaskElement,
Sourceยงfn bitor_assign(&mut self, rhs: bool)
fn bitor_assign(&mut self, rhs: bool)
|= operation. Read moreSourceยงimpl<T, const N: usize> BitOrAssign for Mask<T, N>where
T: MaskElement,
impl<T, const N: usize> BitOrAssign for Mask<T, N>where
T: MaskElement,
Sourceยงfn bitor_assign(&mut self, rhs: Mask<T, N>)
fn bitor_assign(&mut self, rhs: Mask<T, N>)
|= operation. Read moreSourceยงimpl<T, const N: usize> BitXorAssign<bool> for Mask<T, N>where
T: MaskElement,
impl<T, const N: usize> BitXorAssign<bool> for Mask<T, N>where
T: MaskElement,
Sourceยงfn bitxor_assign(&mut self, rhs: bool)
fn bitxor_assign(&mut self, rhs: bool)
^= operation. Read moreSourceยงimpl<T, const N: usize> BitXorAssign for Mask<T, N>where
T: MaskElement,
impl<T, const N: usize> BitXorAssign for Mask<T, N>where
T: MaskElement,
Sourceยงfn bitxor_assign(&mut self, rhs: Mask<T, N>)
fn bitxor_assign(&mut self, rhs: Mask<T, N>)
^= operation. Read moreSourceยงimpl<T, const N: usize> PartialEq for Mask<T, N>where
T: MaskElement + PartialEq,
impl<T, const N: usize> PartialEq for Mask<T, N>where
T: MaskElement + PartialEq,
Sourceยงimpl<T, const N: usize> PartialOrd for Mask<T, N>where
T: MaskElement + PartialOrd,
impl<T, const N: usize> PartialOrd for Mask<T, N>where
T: MaskElement + PartialOrd,
Sourceยงimpl<T, U, const N: usize> Select<Mask<T, N>> for Mask<U, N>where
T: MaskElement,
U: MaskElement,
impl<T, U, const N: usize> Select<Mask<T, N>> for Mask<U, N>where
T: MaskElement,
U: MaskElement,
Sourceยงimpl<T, U, const N: usize> Select<Simd<T, N>> for Mask<U, N>where
T: SimdElement,
U: MaskElement,
impl<T, U, const N: usize> Select<Simd<T, N>> for Mask<U, N>where
T: SimdElement,
U: MaskElement,
Sourceยงimpl<const N: usize> SimdOrd for Mask<i16, N>
impl<const N: usize> SimdOrd for Mask<i16, N>
Sourceยงfn simd_max(self, other: Mask<i16, N>) -> Mask<i16, N>
fn simd_max(self, other: Mask<i16, N>) -> Mask<i16, N>
portable_simd)other.Sourceยงimpl<const N: usize> SimdOrd for Mask<i32, N>
impl<const N: usize> SimdOrd for Mask<i32, N>
Sourceยงfn simd_max(self, other: Mask<i32, N>) -> Mask<i32, N>
fn simd_max(self, other: Mask<i32, N>) -> Mask<i32, N>
portable_simd)other.Sourceยงimpl<const N: usize> SimdOrd for Mask<i64, N>
impl<const N: usize> SimdOrd for Mask<i64, N>
Sourceยงfn simd_max(self, other: Mask<i64, N>) -> Mask<i64, N>
fn simd_max(self, other: Mask<i64, N>) -> Mask<i64, N>
portable_simd)other.Sourceยงimpl<const N: usize> SimdOrd for Mask<i8, N>
impl<const N: usize> SimdOrd for Mask<i8, N>
Sourceยงfn simd_max(self, other: Mask<i8, N>) -> Mask<i8, N>
fn simd_max(self, other: Mask<i8, N>) -> Mask<i8, N>
portable_simd)other.Sourceยงimpl<const N: usize> SimdOrd for Mask<isize, N>
impl<const N: usize> SimdOrd for Mask<isize, N>
Sourceยงfn simd_max(self, other: Mask<isize, N>) -> Mask<isize, N>
fn simd_max(self, other: Mask<isize, N>) -> Mask<isize, N>
portable_simd)other.Sourceยงimpl<const N: usize> SimdPartialEq for Mask<i16, N>
impl<const N: usize> SimdPartialEq for Mask<i16, N>
Sourceยงtype Mask = Mask<i16, N>
type Mask = Mask<i16, N>
portable_simd)Sourceยงimpl<const N: usize> SimdPartialEq for Mask<i32, N>
impl<const N: usize> SimdPartialEq for Mask<i32, N>
Sourceยงtype Mask = Mask<i32, N>
type Mask = Mask<i32, N>
portable_simd)Sourceยงimpl<const N: usize> SimdPartialEq for Mask<i64, N>
impl<const N: usize> SimdPartialEq for Mask<i64, N>
Sourceยงtype Mask = Mask<i64, N>
type Mask = Mask<i64, N>
portable_simd)Sourceยงimpl<const N: usize> SimdPartialEq for Mask<i8, N>
impl<const N: usize> SimdPartialEq for Mask<i8, N>
Sourceยงtype Mask = Mask<i8, N>
type Mask = Mask<i8, N>
portable_simd)Sourceยงimpl<const N: usize> SimdPartialEq for Mask<isize, N>
impl<const N: usize> SimdPartialEq for Mask<isize, N>
Sourceยงtype Mask = Mask<isize, N>
type Mask = Mask<isize, N>
portable_simd)Sourceยงimpl<const N: usize> SimdPartialOrd for Mask<i16, N>
impl<const N: usize> SimdPartialOrd for Mask<i16, N>
Sourceยงfn simd_lt(self, other: Mask<i16, N>) -> <Mask<i16, N> as SimdPartialEq>::Mask
fn simd_lt(self, other: Mask<i16, N>) -> <Mask<i16, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงfn simd_le(self, other: Mask<i16, N>) -> <Mask<i16, N> as SimdPartialEq>::Mask
fn simd_le(self, other: Mask<i16, N>) -> <Mask<i16, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงimpl<const N: usize> SimdPartialOrd for Mask<i32, N>
impl<const N: usize> SimdPartialOrd for Mask<i32, N>
Sourceยงfn simd_lt(self, other: Mask<i32, N>) -> <Mask<i32, N> as SimdPartialEq>::Mask
fn simd_lt(self, other: Mask<i32, N>) -> <Mask<i32, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงfn simd_le(self, other: Mask<i32, N>) -> <Mask<i32, N> as SimdPartialEq>::Mask
fn simd_le(self, other: Mask<i32, N>) -> <Mask<i32, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงimpl<const N: usize> SimdPartialOrd for Mask<i64, N>
impl<const N: usize> SimdPartialOrd for Mask<i64, N>
Sourceยงfn simd_lt(self, other: Mask<i64, N>) -> <Mask<i64, N> as SimdPartialEq>::Mask
fn simd_lt(self, other: Mask<i64, N>) -> <Mask<i64, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงfn simd_le(self, other: Mask<i64, N>) -> <Mask<i64, N> as SimdPartialEq>::Mask
fn simd_le(self, other: Mask<i64, N>) -> <Mask<i64, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงimpl<const N: usize> SimdPartialOrd for Mask<i8, N>
impl<const N: usize> SimdPartialOrd for Mask<i8, N>
Sourceยงfn simd_lt(self, other: Mask<i8, N>) -> <Mask<i8, N> as SimdPartialEq>::Mask
fn simd_lt(self, other: Mask<i8, N>) -> <Mask<i8, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงfn simd_le(self, other: Mask<i8, N>) -> <Mask<i8, N> as SimdPartialEq>::Mask
fn simd_le(self, other: Mask<i8, N>) -> <Mask<i8, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงimpl<const N: usize> SimdPartialOrd for Mask<isize, N>
impl<const N: usize> SimdPartialOrd for Mask<isize, N>
Sourceยงfn simd_lt(
self,
other: Mask<isize, N>,
) -> <Mask<isize, N> as SimdPartialEq>::Mask
fn simd_lt( self, other: Mask<isize, N>, ) -> <Mask<isize, N> as SimdPartialEq>::Mask
portable_simd)other.Sourceยงfn simd_le(
self,
other: Mask<isize, N>,
) -> <Mask<isize, N> as SimdPartialEq>::Mask
fn simd_le( self, other: Mask<isize, N>, ) -> <Mask<isize, N> as SimdPartialEq>::Mask
portable_simd)other.impl<T, const N: usize> Copy for Mask<T, N>where
T: MaskElement,
Auto Trait Implementationsยง
impl<T, const N: usize> Freeze for Mask<T, N>where
T: Freeze,
impl<T, const N: usize> RefUnwindSafe for Mask<T, N>where
T: RefUnwindSafe,
impl<T, const N: usize> Send for Mask<T, N>where
T: Send,
impl<T, const N: usize> Sync for Mask<T, N>where
T: Sync,
impl<T, const N: usize> Unpin for Mask<T, N>where
T: Unpin,
impl<T, const N: usize> UnsafeUnpin for Mask<T, N>where
T: UnsafeUnpin,
impl<T, const N: usize> UnwindSafe for Mask<T, N>where
T: UnwindSafe,
Blanket Implementationsยง
Sourceยงimpl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Sourceยงfn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Sourceยงimpl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Sourceยงimpl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Sourceยงfn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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
impl<T> DowncastSync for T
Sourceยงimpl<A> DynCastExt for A
impl<A> DynCastExt for A
Sourceยงfn dyn_cast<T>(
self,
) -> Result<<A as DynCastExtHelper<T>>::Target, <A as DynCastExtHelper<T>>::Source>where
A: DynCastExtHelper<T>,
T: ?Sized,
fn dyn_cast<T>(
self,
) -> Result<<A as DynCastExtHelper<T>>::Target, <A as DynCastExtHelper<T>>::Source>where
A: DynCastExtHelper<T>,
T: ?Sized,
Sourceยงfn dyn_upcast<T>(self) -> <A as DynCastExtAdvHelper<T, T>>::Target
fn dyn_upcast<T>(self) -> <A as DynCastExtAdvHelper<T, T>>::Target
Sourceยงfn dyn_cast_adv<F, T>(
self,
) -> Result<<A as DynCastExtAdvHelper<F, T>>::Target, <A as DynCastExtAdvHelper<F, T>>::Source>
fn dyn_cast_adv<F, T>( self, ) -> Result<<A as DynCastExtAdvHelper<F, T>>::Target, <A as DynCastExtAdvHelper<F, T>>::Source>
Sourceยงfn dyn_cast_with_config<C>(
self,
) -> Result<<A as DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>>::Target, <A as DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>>::Source>where
C: DynCastConfig,
A: DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>,
fn dyn_cast_with_config<C>(
self,
) -> Result<<A as DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>>::Target, <A as DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>>::Source>where
C: DynCastConfig,
A: DynCastExtAdvHelper<<C as DynCastConfig>::Source, <C as DynCastConfig>::Target>,
Sourceยงimpl<T> Instrument for T
impl<T> Instrument for T
Sourceยงfn instrument(self, span: Span) -> Instrumented<Self> โ
fn instrument(self, span: Span) -> Instrumented<Self> โ
Sourceยงfn in_current_span(self) -> Instrumented<Self> โ
fn in_current_span(self) -> Instrumented<Self> โ
Sourceยงimpl<T> IntoEither for T
impl<T> IntoEither for T
Sourceยงfn into_either(self, into_left: bool) -> Either<Self, Self> โ
fn into_either(self, into_left: bool) -> Either<Self, Self> โ
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 moreSourceยงfn into_either_with<F>(self, into_left: F) -> Either<Self, Self> โ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> โ
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