diff --git a/main/funnybones/all.html b/main/funnybones/all.html index 17703a5..f61cdbe 100644 --- a/main/funnybones/all.html +++ b/main/funnybones/all.html @@ -1 +1 @@ -
pub enum ChangeKind {
+ Bone {
+ bone: BoneId,
+ position: Vector,
+ },
+ Joint {
+ joint: JointId,
+ rotation: Rotation,
+ },
+}
source
. Read moreparameters
when converting.self
into C
, using the provided parameters.clone_to_uninit
)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
.Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
+further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &Any
’s vtable from &Trait
’s.&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &mut Any
’s vtable from &mut Trait
’s.angle
.other
into Self
, while performing the appropriate scaling,
+rounding and clamping.T
.parameters
when converting.self
into C
, using the provided parameters.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 moreself
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 moreself
as a ReadOnly
.self
into T
, while performing the appropriate scaling,
+rounding and clamping.Value
].Value
].try_into_colors
fails to cast.OutOfBounds
error is returned which contains
+the unclamped color. Read moreSubscriber
to this type, returning a
+[WithDispatch
] wrapper. Read morepub struct Animation(/* private fields */);
ascii_char
)Views this slice of ASCII characters as a UTF-8 str
.
ascii_char
)Views this slice of ASCII characters as a slice of u8
bytes.
Checks if all bytes in this slice are within the ASCII range.
+ascii_char
)If this slice is_ascii
, returns it as a slice of
+ASCII characters, otherwise returns None
.
ascii_char
)Converts this slice of bytes into a slice of ASCII characters, +without checking whether they’re valid.
+Every byte in the slice must be in 0..=127
, or else this is UB.
Checks that two slices are an ASCII case-insensitive match.
+Same as to_ascii_lowercase(a) == to_ascii_lowercase(b)
,
+but without allocating and copying temporaries.
Converts this slice to its ASCII upper case equivalent in-place.
+ASCII letters ‘a’ to ‘z’ are mapped to ‘A’ to ‘Z’, +but non-ASCII letters are unchanged.
+To return a new uppercased value without modifying the existing one, use
+to_ascii_uppercase
.
Converts this slice to its ASCII lower case equivalent in-place.
+ASCII letters ‘A’ to ‘Z’ are mapped to ‘a’ to ‘z’, +but non-ASCII letters are unchanged.
+To return a new lowercased value without modifying the existing one, use
+to_ascii_lowercase
.
Returns an iterator that produces an escaped version of this slice, +treating it as an ASCII string.
+
+let s = b"0\t\r\n'\"\\\x9d";
+let escaped = s.escape_ascii().to_string();
+assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d");
Returns a byte slice with leading ASCII whitespace bytes removed.
+‘Whitespace’ refers to the definition used by
+u8::is_ascii_whitespace
.
assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n");
+assert_eq!(b" ".trim_ascii_start(), b"");
+assert_eq!(b"".trim_ascii_start(), b"");
Returns a byte slice with trailing ASCII whitespace bytes removed.
+‘Whitespace’ refers to the definition used by
+u8::is_ascii_whitespace
.
assert_eq!(b"\r hello world\n ".trim_ascii_end(), b"\r hello world");
+assert_eq!(b" ".trim_ascii_end(), b"");
+assert_eq!(b"".trim_ascii_end(), b"");
Returns a byte slice with leading and trailing ASCII whitespace bytes +removed.
+‘Whitespace’ refers to the definition used by
+u8::is_ascii_whitespace
.
assert_eq!(b"\r hello world\n ".trim_ascii(), b"hello world");
+assert_eq!(b" ".trim_ascii(), b"");
+assert_eq!(b"".trim_ascii(), b"");
Returns the number of elements in the slice.
+let a = [1, 2, 3];
+assert_eq!(a.len(), 3);
Returns true
if the slice has a length of 0.
let a = [1, 2, 3];
+assert!(!a.is_empty());
+
+let b: &[i32] = &[];
+assert!(b.is_empty());
Returns the first element of the slice, or None
if it is empty.
let v = [10, 40, 30];
+assert_eq!(Some(&10), v.first());
+
+let w: &[i32] = &[];
+assert_eq!(None, w.first());
Returns a mutable pointer to the first element of the slice, or None
if it is empty.
let x = &mut [0, 1, 2];
+
+if let Some(first) = x.first_mut() {
+ *first = 5;
+}
+assert_eq!(x, &[5, 1, 2]);
+
+let y: &mut [i32] = &mut [];
+assert_eq!(None, y.first_mut());
Returns the first and all the rest of the elements of the slice, or None
if it is empty.
let x = &[0, 1, 2];
+
+if let Some((first, elements)) = x.split_first() {
+ assert_eq!(first, &0);
+ assert_eq!(elements, &[1, 2]);
+}
Returns the first and all the rest of the elements of the slice, or None
if it is empty.
let x = &mut [0, 1, 2];
+
+if let Some((first, elements)) = x.split_first_mut() {
+ *first = 3;
+ elements[0] = 4;
+ elements[1] = 5;
+}
+assert_eq!(x, &[3, 4, 5]);
Returns the last and all the rest of the elements of the slice, or None
if it is empty.
let x = &[0, 1, 2];
+
+if let Some((last, elements)) = x.split_last() {
+ assert_eq!(last, &2);
+ assert_eq!(elements, &[0, 1]);
+}
Returns the last and all the rest of the elements of the slice, or None
if it is empty.
let x = &mut [0, 1, 2];
+
+if let Some((last, elements)) = x.split_last_mut() {
+ *last = 3;
+ elements[0] = 4;
+ elements[1] = 5;
+}
+assert_eq!(x, &[4, 5, 3]);
Returns the last element of the slice, or None
if it is empty.
let v = [10, 40, 30];
+assert_eq!(Some(&30), v.last());
+
+let w: &[i32] = &[];
+assert_eq!(None, w.last());
Returns a mutable reference to the last item in the slice, or None
if it is empty.
let x = &mut [0, 1, 2];
+
+if let Some(last) = x.last_mut() {
+ *last = 10;
+}
+assert_eq!(x, &[0, 1, 10]);
+
+let y: &mut [i32] = &mut [];
+assert_eq!(None, y.last_mut());
Returns an array reference to the first N
items in the slice.
If the slice is not at least N
in length, this will return None
.
let u = [10, 40, 30];
+assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
+
+let v: &[i32] = &[10];
+assert_eq!(None, v.first_chunk::<2>());
+
+let w: &[i32] = &[];
+assert_eq!(Some(&[]), w.first_chunk::<0>());
Returns a mutable array reference to the first N
items in the slice.
If the slice is not at least N
in length, this will return None
.
let x = &mut [0, 1, 2];
+
+if let Some(first) = x.first_chunk_mut::<2>() {
+ first[0] = 5;
+ first[1] = 4;
+}
+assert_eq!(x, &[5, 4, 2]);
+
+assert_eq!(None, x.first_chunk_mut::<4>());
Returns an array reference to the first N
items in the slice and the remaining slice.
If the slice is not at least N
in length, this will return None
.
let x = &[0, 1, 2];
+
+if let Some((first, elements)) = x.split_first_chunk::<2>() {
+ assert_eq!(first, &[0, 1]);
+ assert_eq!(elements, &[2]);
+}
+
+assert_eq!(None, x.split_first_chunk::<4>());
Returns a mutable array reference to the first N
items in the slice and the remaining
+slice.
If the slice is not at least N
in length, this will return None
.
let x = &mut [0, 1, 2];
+
+if let Some((first, elements)) = x.split_first_chunk_mut::<2>() {
+ first[0] = 3;
+ first[1] = 4;
+ elements[0] = 5;
+}
+assert_eq!(x, &[3, 4, 5]);
+
+assert_eq!(None, x.split_first_chunk_mut::<4>());
Returns an array reference to the last N
items in the slice and the remaining slice.
If the slice is not at least N
in length, this will return None
.
let x = &[0, 1, 2];
+
+if let Some((elements, last)) = x.split_last_chunk::<2>() {
+ assert_eq!(elements, &[0]);
+ assert_eq!(last, &[1, 2]);
+}
+
+assert_eq!(None, x.split_last_chunk::<4>());
Returns a mutable array reference to the last N
items in the slice and the remaining
+slice.
If the slice is not at least N
in length, this will return None
.
let x = &mut [0, 1, 2];
+
+if let Some((elements, last)) = x.split_last_chunk_mut::<2>() {
+ last[0] = 3;
+ last[1] = 4;
+ elements[0] = 5;
+}
+assert_eq!(x, &[5, 3, 4]);
+
+assert_eq!(None, x.split_last_chunk_mut::<4>());
Returns an array reference to the last N
items in the slice.
If the slice is not at least N
in length, this will return None
.
let u = [10, 40, 30];
+assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
+
+let v: &[i32] = &[10];
+assert_eq!(None, v.last_chunk::<2>());
+
+let w: &[i32] = &[];
+assert_eq!(Some(&[]), w.last_chunk::<0>());
Returns a mutable array reference to the last N
items in the slice.
If the slice is not at least N
in length, this will return None
.
let x = &mut [0, 1, 2];
+
+if let Some(last) = x.last_chunk_mut::<2>() {
+ last[0] = 10;
+ last[1] = 20;
+}
+assert_eq!(x, &[0, 10, 20]);
+
+assert_eq!(None, x.last_chunk_mut::<4>());
Returns a reference to an element or subslice depending on the type of +index.
+None
if out of bounds.None
if out of bounds.let v = [10, 40, 30];
+assert_eq!(Some(&40), v.get(1));
+assert_eq!(Some(&[10, 40][..]), v.get(0..2));
+assert_eq!(None, v.get(3));
+assert_eq!(None, v.get(0..4));
Returns a reference to an element or subslice, without doing bounds +checking.
+For a safe alternative see get
.
Calling this method with an out-of-bounds index is undefined behavior +even if the resulting reference is not used.
+You can think of this like .get(index).unwrap_unchecked()
. It’s UB
+to call .get_unchecked(len)
, even if you immediately convert to a
+pointer. And it’s UB to call .get_unchecked(..len + 1)
,
+.get_unchecked(..=len)
, or similar.
let x = &[1, 2, 4];
+
+unsafe {
+ assert_eq!(x.get_unchecked(1), &2);
+}
Returns a mutable reference to an element or subslice, without doing +bounds checking.
+For a safe alternative see get_mut
.
Calling this method with an out-of-bounds index is undefined behavior +even if the resulting reference is not used.
+You can think of this like .get_mut(index).unwrap_unchecked()
. It’s
+UB to call .get_unchecked_mut(len)
, even if you immediately convert
+to a pointer. And it’s UB to call .get_unchecked_mut(..len + 1)
,
+.get_unchecked_mut(..=len)
, or similar.
let x = &mut [1, 2, 4];
+
+unsafe {
+ let elem = x.get_unchecked_mut(1);
+ *elem = 13;
+}
+assert_eq!(x, &[1, 13, 4]);
Returns a raw pointer to the slice’s buffer.
+The caller must ensure that the slice outlives the pointer this +function returns, or else it will end up dangling.
+The caller must also ensure that the memory the pointer (non-transitively) points to
+is never written to (except inside an UnsafeCell
) using this pointer or any pointer
+derived from it. If you need to mutate the contents of the slice, use as_mut_ptr
.
Modifying the container referenced by this slice may cause its buffer +to be reallocated, which would also make any pointers to it invalid.
+let x = &[1, 2, 4];
+let x_ptr = x.as_ptr();
+
+unsafe {
+ for i in 0..x.len() {
+ assert_eq!(x.get_unchecked(i), &*x_ptr.add(i));
+ }
+}
Returns an unsafe mutable pointer to the slice’s buffer.
+The caller must ensure that the slice outlives the pointer this +function returns, or else it will end up dangling.
+Modifying the container referenced by this slice may cause its buffer +to be reallocated, which would also make any pointers to it invalid.
+let x = &mut [1, 2, 4];
+let x_ptr = x.as_mut_ptr();
+
+unsafe {
+ for i in 0..x.len() {
+ *x_ptr.add(i) += 2;
+ }
+}
+assert_eq!(x, &[3, 4, 6]);
Returns the two raw pointers spanning the slice.
+The returned range is half-open, which means that the end pointer +points one past the last element of the slice. This way, an empty +slice is represented by two equal pointers, and the difference between +the two pointers represents the size of the slice.
+See as_ptr
for warnings on using these pointers. The end pointer
+requires extra caution, as it does not point to a valid element in the
+slice.
This function is useful for interacting with foreign interfaces which +use two pointers to refer to a range of elements in memory, as is +common in C++.
+It can also be useful to check if a pointer to an element refers to an +element of this slice:
+ +let a = [1, 2, 3];
+let x = &a[1] as *const _;
+let y = &5 as *const _;
+
+assert!(a.as_ptr_range().contains(&x));
+assert!(!a.as_ptr_range().contains(&y));
Returns the two unsafe mutable pointers spanning the slice.
+The returned range is half-open, which means that the end pointer +points one past the last element of the slice. This way, an empty +slice is represented by two equal pointers, and the difference between +the two pointers represents the size of the slice.
+See as_mut_ptr
for warnings on using these pointers. The end
+pointer requires extra caution, as it does not point to a valid element
+in the slice.
This function is useful for interacting with foreign interfaces which +use two pointers to refer to a range of elements in memory, as is +common in C++.
+Swaps two elements in the slice.
+If a
equals to b
, it’s guaranteed that elements won’t change value.
Panics if a
or b
are out of bounds.
let mut v = ["a", "b", "c", "d", "e"];
+v.swap(2, 4);
+assert!(v == ["a", "b", "e", "d", "c"]);
slice_swap_unchecked
)Swaps two elements in the slice, without doing bounds checking.
+For a safe alternative see swap
.
Calling this method with an out-of-bounds index is undefined behavior.
+The caller has to ensure that a < self.len()
and b < self.len()
.
#![feature(slice_swap_unchecked)]
+
+let mut v = ["a", "b", "c", "d"];
+// SAFETY: we know that 1 and 3 are both indices of the slice
+unsafe { v.swap_unchecked(1, 3) };
+assert!(v == ["a", "d", "c", "b"]);
Reverses the order of elements in the slice, in place.
+let mut v = [1, 2, 3];
+v.reverse();
+assert!(v == [3, 2, 1]);
Returns an iterator over the slice.
+The iterator yields all items from start to end.
+let x = &[1, 2, 4];
+let mut iterator = x.iter();
+
+assert_eq!(iterator.next(), Some(&1));
+assert_eq!(iterator.next(), Some(&2));
+assert_eq!(iterator.next(), Some(&4));
+assert_eq!(iterator.next(), None);
Returns an iterator that allows modifying each value.
+The iterator yields all items from start to end.
+let x = &mut [1, 2, 4];
+for elem in x.iter_mut() {
+ *elem += 2;
+}
+assert_eq!(x, &[3, 4, 6]);
Returns an iterator over all contiguous windows of length
+size
. The windows overlap. If the slice is shorter than
+size
, the iterator returns no values.
Panics if size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.windows(3);
+assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']);
+assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']);
+assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']);
+assert!(iter.next().is_none());
If the slice is shorter than size
:
let slice = ['f', 'o', 'o'];
+let mut iter = slice.windows(4);
+assert!(iter.next().is_none());
There’s no windows_mut
, as that existing would let safe code violate the
+“only one &mut
at a time to the same thing” rule. However, you can sometimes
+use Cell::as_slice_of_cells
in
+conjunction with windows
to accomplish something similar:
use std::cell::Cell;
+
+let mut array = ['R', 'u', 's', 't', ' ', '2', '0', '1', '5'];
+let slice = &mut array[..];
+let slice_of_cells: &[Cell<char>] = Cell::from_mut(slice).as_slice_of_cells();
+for w in slice_of_cells.windows(3) {
+ Cell::swap(&w[0], &w[2]);
+}
+assert_eq!(array, ['s', 't', ' ', '2', '0', '1', '5', 'u', 'R']);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide the length of the
+slice, then the last chunk will not have length chunk_size
.
See chunks_exact
for a variant of this iterator that returns chunks of always exactly
+chunk_size
elements, and rchunks
for the same iterator but starting at the end of the
+slice.
Panics if chunk_size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.chunks(2);
+assert_eq!(iter.next().unwrap(), &['l', 'o']);
+assert_eq!(iter.next().unwrap(), &['r', 'e']);
+assert_eq!(iter.next().unwrap(), &['m']);
+assert!(iter.next().is_none());
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are mutable slices, and do not overlap. If chunk_size
does not divide the
+length of the slice, then the last chunk will not have length chunk_size
.
See chunks_exact_mut
for a variant of this iterator that returns chunks of always
+exactly chunk_size
elements, and rchunks_mut
for the same iterator but starting at
+the end of the slice.
Panics if chunk_size
is 0.
let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.chunks_mut(2) {
+ for elem in chunk.iter_mut() {
+ *elem += count;
+ }
+ count += 1;
+}
+assert_eq!(v, &[1, 1, 2, 2, 3]);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide the length of the
+slice, then the last up to chunk_size-1
elements will be omitted and can be retrieved
+from the remainder
function of the iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can often optimize the
+resulting code better than in the case of chunks
.
See chunks
for a variant of this iterator that also returns the remainder as a smaller
+chunk, and rchunks_exact
for the same iterator but starting at the end of the slice.
Panics if chunk_size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.chunks_exact(2);
+assert_eq!(iter.next().unwrap(), &['l', 'o']);
+assert_eq!(iter.next().unwrap(), &['r', 'e']);
+assert!(iter.next().is_none());
+assert_eq!(iter.remainder(), &['m']);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are mutable slices, and do not overlap. If chunk_size
does not divide the
+length of the slice, then the last up to chunk_size-1
elements will be omitted and can be
+retrieved from the into_remainder
function of the iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can often optimize the
+resulting code better than in the case of chunks_mut
.
See chunks_mut
for a variant of this iterator that also returns the remainder as a
+smaller chunk, and rchunks_exact_mut
for the same iterator but starting at the end of
+the slice.
Panics if chunk_size
is 0.
let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.chunks_exact_mut(2) {
+ for elem in chunk.iter_mut() {
+ *elem += count;
+ }
+ count += 1;
+}
+assert_eq!(v, &[1, 1, 2, 2, 0]);
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+assuming that there’s no remainder.
This may only be called when
+N
-element chunks (aka self.len() % N == 0
).N != 0
.#![feature(slice_as_chunks)]
+let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
+let chunks: &[[char; 1]] =
+ // SAFETY: 1-element chunks never have remainder
+ unsafe { slice.as_chunks_unchecked() };
+assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
+let chunks: &[[char; 3]] =
+ // SAFETY: The slice length (6) is a multiple of 3
+ unsafe { slice.as_chunks_unchecked() };
+assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
+
+// These would be unsound:
+// let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5
+// let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+starting at the beginning of the slice,
+and a remainder slice with length strictly less than N
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(slice_as_chunks)]
+let slice = ['l', 'o', 'r', 'e', 'm'];
+let (chunks, remainder) = slice.as_chunks();
+assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
+assert_eq!(remainder, &['m']);
If you expect the slice to be an exact multiple, you can combine
+let
-else
with an empty slice pattern:
#![feature(slice_as_chunks)]
+let slice = ['R', 'u', 's', 't'];
+let (chunks, []) = slice.as_chunks::<2>() else {
+ panic!("slice didn't have even length")
+};
+assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+starting at the end of the slice,
+and a remainder slice with length strictly less than N
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(slice_as_chunks)]
+let slice = ['l', 'o', 'r', 'e', 'm'];
+let (remainder, chunks) = slice.as_rchunks();
+assert_eq!(remainder, &['l']);
+assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
array_chunks
)Returns an iterator over N
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are array references and do not overlap. If N
does not divide the
+length of the slice, then the last up to N-1
elements will be omitted and can be
+retrieved from the remainder
function of the iterator.
This method is the const generic equivalent of chunks_exact
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(array_chunks)]
+let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.array_chunks();
+assert_eq!(iter.next().unwrap(), &['l', 'o']);
+assert_eq!(iter.next().unwrap(), &['r', 'e']);
+assert!(iter.next().is_none());
+assert_eq!(iter.remainder(), &['m']);
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+assuming that there’s no remainder.
This may only be called when
+N
-element chunks (aka self.len() % N == 0
).N != 0
.#![feature(slice_as_chunks)]
+let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
+let chunks: &mut [[char; 1]] =
+ // SAFETY: 1-element chunks never have remainder
+ unsafe { slice.as_chunks_unchecked_mut() };
+chunks[0] = ['L'];
+assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]);
+let chunks: &mut [[char; 3]] =
+ // SAFETY: The slice length (6) is a multiple of 3
+ unsafe { slice.as_chunks_unchecked_mut() };
+chunks[1] = ['a', 'x', '?'];
+assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']);
+
+// These would be unsound:
+// let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut() // The slice length is not a multiple of 5
+// let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+starting at the beginning of the slice,
+and a remainder slice with length strictly less than N
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(slice_as_chunks)]
+let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+let (chunks, remainder) = v.as_chunks_mut();
+remainder[0] = 9;
+for chunk in chunks {
+ *chunk = [count; 2];
+ count += 1;
+}
+assert_eq!(v, &[1, 1, 2, 2, 9]);
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+starting at the end of the slice,
+and a remainder slice with length strictly less than N
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(slice_as_chunks)]
+let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+let (remainder, chunks) = v.as_rchunks_mut();
+remainder[0] = 9;
+for chunk in chunks {
+ *chunk = [count; 2];
+ count += 1;
+}
+assert_eq!(v, &[9, 1, 1, 2, 2]);
array_chunks
)Returns an iterator over N
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are mutable array references and do not overlap. If N
does not divide
+the length of the slice, then the last up to N-1
elements will be omitted and
+can be retrieved from the into_remainder
function of the iterator.
This method is the const generic equivalent of chunks_exact_mut
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(array_chunks)]
+let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.array_chunks_mut() {
+ *chunk = [count; 2];
+ count += 1;
+}
+assert_eq!(v, &[1, 1, 2, 2, 0]);
array_windows
)Returns an iterator over overlapping windows of N
elements of a slice,
+starting at the beginning of the slice.
This is the const generic equivalent of windows
.
If N
is greater than the size of the slice, it will return no windows.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(array_windows)]
+let slice = [0, 1, 2, 3];
+let mut iter = slice.array_windows();
+assert_eq!(iter.next().unwrap(), &[0, 1]);
+assert_eq!(iter.next().unwrap(), &[1, 2]);
+assert_eq!(iter.next().unwrap(), &[2, 3]);
+assert!(iter.next().is_none());
Returns an iterator over chunk_size
elements of the slice at a time, starting at the end
+of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide the length of the
+slice, then the last chunk will not have length chunk_size
.
See rchunks_exact
for a variant of this iterator that returns chunks of always exactly
+chunk_size
elements, and chunks
for the same iterator but starting at the beginning
+of the slice.
Panics if chunk_size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.rchunks(2);
+assert_eq!(iter.next().unwrap(), &['e', 'm']);
+assert_eq!(iter.next().unwrap(), &['o', 'r']);
+assert_eq!(iter.next().unwrap(), &['l']);
+assert!(iter.next().is_none());
Returns an iterator over chunk_size
elements of the slice at a time, starting at the end
+of the slice.
The chunks are mutable slices, and do not overlap. If chunk_size
does not divide the
+length of the slice, then the last chunk will not have length chunk_size
.
See rchunks_exact_mut
for a variant of this iterator that returns chunks of always
+exactly chunk_size
elements, and chunks_mut
for the same iterator but starting at the
+beginning of the slice.
Panics if chunk_size
is 0.
let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.rchunks_mut(2) {
+ for elem in chunk.iter_mut() {
+ *elem += count;
+ }
+ count += 1;
+}
+assert_eq!(v, &[3, 2, 2, 1, 1]);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+end of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide the length of the
+slice, then the last up to chunk_size-1
elements will be omitted and can be retrieved
+from the remainder
function of the iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can often optimize the
+resulting code better than in the case of rchunks
.
See rchunks
for a variant of this iterator that also returns the remainder as a smaller
+chunk, and chunks_exact
for the same iterator but starting at the beginning of the
+slice.
Panics if chunk_size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.rchunks_exact(2);
+assert_eq!(iter.next().unwrap(), &['e', 'm']);
+assert_eq!(iter.next().unwrap(), &['o', 'r']);
+assert!(iter.next().is_none());
+assert_eq!(iter.remainder(), &['l']);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the end
+of the slice.
The chunks are mutable slices, and do not overlap. If chunk_size
does not divide the
+length of the slice, then the last up to chunk_size-1
elements will be omitted and can be
+retrieved from the into_remainder
function of the iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can often optimize the
+resulting code better than in the case of chunks_mut
.
See rchunks_mut
for a variant of this iterator that also returns the remainder as a
+smaller chunk, and chunks_exact_mut
for the same iterator but starting at the beginning
+of the slice.
Panics if chunk_size
is 0.
let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.rchunks_exact_mut(2) {
+ for elem in chunk.iter_mut() {
+ *elem += count;
+ }
+ count += 1;
+}
+assert_eq!(v, &[0, 2, 2, 1, 1]);
Returns an iterator over the slice producing non-overlapping runs +of elements using the predicate to separate them.
+The predicate is called for every pair of consecutive elements,
+meaning that it is called on slice[0]
and slice[1]
,
+followed by slice[1]
and slice[2]
, and so on.
let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
+
+let mut iter = slice.chunk_by(|a, b| a == b);
+
+assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
+assert_eq!(iter.next(), Some(&[3, 3][..]));
+assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
+assert_eq!(iter.next(), None);
This method can be used to extract the sorted subslices:
+ +let slice = &[1, 1, 2, 3, 2, 3, 2, 3, 4];
+
+let mut iter = slice.chunk_by(|a, b| a <= b);
+
+assert_eq!(iter.next(), Some(&[1, 1, 2, 3][..]));
+assert_eq!(iter.next(), Some(&[2, 3][..]));
+assert_eq!(iter.next(), Some(&[2, 3, 4][..]));
+assert_eq!(iter.next(), None);
Returns an iterator over the slice producing non-overlapping mutable +runs of elements using the predicate to separate them.
+The predicate is called for every pair of consecutive elements,
+meaning that it is called on slice[0]
and slice[1]
,
+followed by slice[1]
and slice[2]
, and so on.
let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2];
+
+let mut iter = slice.chunk_by_mut(|a, b| a == b);
+
+assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
+assert_eq!(iter.next(), Some(&mut [3, 3][..]));
+assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
+assert_eq!(iter.next(), None);
This method can be used to extract the sorted subslices:
+ +let slice = &mut [1, 1, 2, 3, 2, 3, 2, 3, 4];
+
+let mut iter = slice.chunk_by_mut(|a, b| a <= b);
+
+assert_eq!(iter.next(), Some(&mut [1, 1, 2, 3][..]));
+assert_eq!(iter.next(), Some(&mut [2, 3][..]));
+assert_eq!(iter.next(), Some(&mut [2, 3, 4][..]));
+assert_eq!(iter.next(), None);
Divides one slice into two at an index.
+The first will contain all indices from [0, mid)
(excluding
+the index mid
itself) and the second will contain all
+indices from [mid, len)
(excluding the index len
itself).
Panics if mid > len
. For a non-panicking alternative see
+split_at_checked
.
let v = [1, 2, 3, 4, 5, 6];
+
+{
+ let (left, right) = v.split_at(0);
+ assert_eq!(left, []);
+ assert_eq!(right, [1, 2, 3, 4, 5, 6]);
+}
+
+{
+ let (left, right) = v.split_at(2);
+ assert_eq!(left, [1, 2]);
+ assert_eq!(right, [3, 4, 5, 6]);
+}
+
+{
+ let (left, right) = v.split_at(6);
+ assert_eq!(left, [1, 2, 3, 4, 5, 6]);
+ assert_eq!(right, []);
+}
Divides one mutable slice into two at an index.
+The first will contain all indices from [0, mid)
(excluding
+the index mid
itself) and the second will contain all
+indices from [mid, len)
(excluding the index len
itself).
Panics if mid > len
. For a non-panicking alternative see
+split_at_mut_checked
.
let mut v = [1, 0, 3, 0, 5, 6];
+let (left, right) = v.split_at_mut(2);
+assert_eq!(left, [1, 0]);
+assert_eq!(right, [3, 0, 5, 6]);
+left[1] = 2;
+right[1] = 4;
+assert_eq!(v, [1, 2, 3, 4, 5, 6]);
Divides one slice into two at an index, without doing bounds checking.
+The first will contain all indices from [0, mid)
(excluding
+the index mid
itself) and the second will contain all
+indices from [mid, len)
(excluding the index len
itself).
For a safe alternative see split_at
.
Calling this method with an out-of-bounds index is undefined behavior
+even if the resulting reference is not used. The caller has to ensure that
+0 <= mid <= self.len()
.
let v = [1, 2, 3, 4, 5, 6];
+
+unsafe {
+ let (left, right) = v.split_at_unchecked(0);
+ assert_eq!(left, []);
+ assert_eq!(right, [1, 2, 3, 4, 5, 6]);
+}
+
+unsafe {
+ let (left, right) = v.split_at_unchecked(2);
+ assert_eq!(left, [1, 2]);
+ assert_eq!(right, [3, 4, 5, 6]);
+}
+
+unsafe {
+ let (left, right) = v.split_at_unchecked(6);
+ assert_eq!(left, [1, 2, 3, 4, 5, 6]);
+ assert_eq!(right, []);
+}
Divides one mutable slice into two at an index, without doing bounds checking.
+The first will contain all indices from [0, mid)
(excluding
+the index mid
itself) and the second will contain all
+indices from [mid, len)
(excluding the index len
itself).
For a safe alternative see split_at_mut
.
Calling this method with an out-of-bounds index is undefined behavior
+even if the resulting reference is not used. The caller has to ensure that
+0 <= mid <= self.len()
.
let mut v = [1, 0, 3, 0, 5, 6];
+// scoped to restrict the lifetime of the borrows
+unsafe {
+ let (left, right) = v.split_at_mut_unchecked(2);
+ assert_eq!(left, [1, 0]);
+ assert_eq!(right, [3, 0, 5, 6]);
+ left[1] = 2;
+ right[1] = 4;
+}
+assert_eq!(v, [1, 2, 3, 4, 5, 6]);
Divides one slice into two at an index, returning None
if the slice is
+too short.
If mid ≤ len
returns a pair of slices where the first will contain all
+indices from [0, mid)
(excluding the index mid
itself) and the
+second will contain all indices from [mid, len)
(excluding the index
+len
itself).
Otherwise, if mid > len
, returns None
.
let v = [1, -2, 3, -4, 5, -6];
+
+{
+ let (left, right) = v.split_at_checked(0).unwrap();
+ assert_eq!(left, []);
+ assert_eq!(right, [1, -2, 3, -4, 5, -6]);
+}
+
+{
+ let (left, right) = v.split_at_checked(2).unwrap();
+ assert_eq!(left, [1, -2]);
+ assert_eq!(right, [3, -4, 5, -6]);
+}
+
+{
+ let (left, right) = v.split_at_checked(6).unwrap();
+ assert_eq!(left, [1, -2, 3, -4, 5, -6]);
+ assert_eq!(right, []);
+}
+
+assert_eq!(None, v.split_at_checked(7));
Divides one mutable slice into two at an index, returning None
if the
+slice is too short.
If mid ≤ len
returns a pair of slices where the first will contain all
+indices from [0, mid)
(excluding the index mid
itself) and the
+second will contain all indices from [mid, len)
(excluding the index
+len
itself).
Otherwise, if mid > len
, returns None
.
let mut v = [1, 0, 3, 0, 5, 6];
+
+if let Some((left, right)) = v.split_at_mut_checked(2) {
+ assert_eq!(left, [1, 0]);
+ assert_eq!(right, [3, 0, 5, 6]);
+ left[1] = 2;
+ right[1] = 4;
+}
+assert_eq!(v, [1, 2, 3, 4, 5, 6]);
+
+assert_eq!(None, v.split_at_mut_checked(7));
Returns an iterator over subslices separated by elements that match
+pred
. The matched element is not contained in the subslices.
let slice = [10, 40, 33, 20];
+let mut iter = slice.split(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[10, 40]);
+assert_eq!(iter.next().unwrap(), &[20]);
+assert!(iter.next().is_none());
If the first element is matched, an empty slice will be the first item +returned by the iterator. Similarly, if the last element in the slice +is matched, an empty slice will be the last item returned by the +iterator:
+ +let slice = [10, 40, 33];
+let mut iter = slice.split(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[10, 40]);
+assert_eq!(iter.next().unwrap(), &[]);
+assert!(iter.next().is_none());
If two matched elements are directly adjacent, an empty slice will be +present between them:
+ +let slice = [10, 6, 33, 20];
+let mut iter = slice.split(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[10]);
+assert_eq!(iter.next().unwrap(), &[]);
+assert_eq!(iter.next().unwrap(), &[20]);
+assert!(iter.next().is_none());
Returns an iterator over mutable subslices separated by elements that
+match pred
. The matched element is not contained in the subslices.
let mut v = [10, 40, 30, 20, 60, 50];
+
+for group in v.split_mut(|num| *num % 3 == 0) {
+ group[0] = 1;
+}
+assert_eq!(v, [1, 40, 30, 1, 60, 1]);
Returns an iterator over subslices separated by elements that match
+pred
. The matched element is contained in the end of the previous
+subslice as a terminator.
let slice = [10, 40, 33, 20];
+let mut iter = slice.split_inclusive(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
+assert_eq!(iter.next().unwrap(), &[20]);
+assert!(iter.next().is_none());
If the last element of the slice is matched, +that element will be considered the terminator of the preceding slice. +That slice will be the last item returned by the iterator.
+ +let slice = [3, 10, 40, 33];
+let mut iter = slice.split_inclusive(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[3]);
+assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
+assert!(iter.next().is_none());
Returns an iterator over mutable subslices separated by elements that
+match pred
. The matched element is contained in the previous
+subslice as a terminator.
let mut v = [10, 40, 30, 20, 60, 50];
+
+for group in v.split_inclusive_mut(|num| *num % 3 == 0) {
+ let terminator_idx = group.len()-1;
+ group[terminator_idx] = 1;
+}
+assert_eq!(v, [10, 40, 1, 20, 1, 1]);
Returns an iterator over subslices separated by elements that match
+pred
, starting at the end of the slice and working backwards.
+The matched element is not contained in the subslices.
let slice = [11, 22, 33, 0, 44, 55];
+let mut iter = slice.rsplit(|num| *num == 0);
+
+assert_eq!(iter.next().unwrap(), &[44, 55]);
+assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
+assert_eq!(iter.next(), None);
As with split()
, if the first or last element is matched, an empty
+slice will be the first (or last) item returned by the iterator.
let v = &[0, 1, 1, 2, 3, 5, 8];
+let mut it = v.rsplit(|n| *n % 2 == 0);
+assert_eq!(it.next().unwrap(), &[]);
+assert_eq!(it.next().unwrap(), &[3, 5]);
+assert_eq!(it.next().unwrap(), &[1, 1]);
+assert_eq!(it.next().unwrap(), &[]);
+assert_eq!(it.next(), None);
Returns an iterator over mutable subslices separated by elements that
+match pred
, starting at the end of the slice and working
+backwards. The matched element is not contained in the subslices.
let mut v = [100, 400, 300, 200, 600, 500];
+
+let mut count = 0;
+for group in v.rsplit_mut(|num| *num % 3 == 0) {
+ count += 1;
+ group[0] = count;
+}
+assert_eq!(v, [3, 400, 300, 2, 600, 1]);
Returns an iterator over subslices separated by elements that match
+pred
, limited to returning at most n
items. The matched element is
+not contained in the subslices.
The last element returned, if any, will contain the remainder of the +slice.
+Print the slice split once by numbers divisible by 3 (i.e., [10, 40]
,
+[20, 60, 50]
):
let v = [10, 40, 30, 20, 60, 50];
+
+for group in v.splitn(2, |num| *num % 3 == 0) {
+ println!("{group:?}");
+}
Returns an iterator over mutable subslices separated by elements that match
+pred
, limited to returning at most n
items. The matched element is
+not contained in the subslices.
The last element returned, if any, will contain the remainder of the +slice.
+let mut v = [10, 40, 30, 20, 60, 50];
+
+for group in v.splitn_mut(2, |num| *num % 3 == 0) {
+ group[0] = 1;
+}
+assert_eq!(v, [1, 40, 30, 1, 60, 50]);
Returns an iterator over subslices separated by elements that match
+pred
limited to returning at most n
items. This starts at the end of
+the slice and works backwards. The matched element is not contained in
+the subslices.
The last element returned, if any, will contain the remainder of the +slice.
+Print the slice split once, starting from the end, by numbers divisible
+by 3 (i.e., [50]
, [10, 40, 30, 20]
):
let v = [10, 40, 30, 20, 60, 50];
+
+for group in v.rsplitn(2, |num| *num % 3 == 0) {
+ println!("{group:?}");
+}
Returns an iterator over subslices separated by elements that match
+pred
limited to returning at most n
items. This starts at the end of
+the slice and works backwards. The matched element is not contained in
+the subslices.
The last element returned, if any, will contain the remainder of the +slice.
+let mut s = [10, 40, 30, 20, 60, 50];
+
+for group in s.rsplitn_mut(2, |num| *num % 3 == 0) {
+ group[0] = 1;
+}
+assert_eq!(s, [1, 40, 30, 20, 60, 1]);
slice_split_once
)Splits the slice on the first element that matches the specified +predicate.
+If any matching elements are present in the slice, returns the prefix
+before the match and suffix after. The matching element itself is not
+included. If no elements match, returns None
.
#![feature(slice_split_once)]
+let s = [1, 2, 3, 2, 4];
+assert_eq!(s.split_once(|&x| x == 2), Some((
+ &[1][..],
+ &[3, 2, 4][..]
+)));
+assert_eq!(s.split_once(|&x| x == 0), None);
slice_split_once
)Splits the slice on the last element that matches the specified +predicate.
+If any matching elements are present in the slice, returns the prefix
+before the match and suffix after. The matching element itself is not
+included. If no elements match, returns None
.
#![feature(slice_split_once)]
+let s = [1, 2, 3, 2, 4];
+assert_eq!(s.rsplit_once(|&x| x == 2), Some((
+ &[1, 2, 3][..],
+ &[4][..]
+)));
+assert_eq!(s.rsplit_once(|&x| x == 0), None);
Returns true
if the slice contains an element with the given value.
This operation is O(n).
+Note that if you have a sorted slice, binary_search
may be faster.
let v = [10, 40, 30];
+assert!(v.contains(&30));
+assert!(!v.contains(&50));
If you do not have a &T
, but some other value that you can compare
+with one (for example, String
implements PartialEq<str>
), you can
+use iter().any
:
let v = [String::from("hello"), String::from("world")]; // slice of `String`
+assert!(v.iter().any(|e| e == "hello")); // search with `&str`
+assert!(!v.iter().any(|e| e == "hi"));
Returns true
if needle
is a prefix of the slice or equal to the slice.
let v = [10, 40, 30];
+assert!(v.starts_with(&[10]));
+assert!(v.starts_with(&[10, 40]));
+assert!(v.starts_with(&v));
+assert!(!v.starts_with(&[50]));
+assert!(!v.starts_with(&[10, 50]));
Always returns true
if needle
is an empty slice:
let v = &[10, 40, 30];
+assert!(v.starts_with(&[]));
+let v: &[u8] = &[];
+assert!(v.starts_with(&[]));
Returns true
if needle
is a suffix of the slice or equal to the slice.
let v = [10, 40, 30];
+assert!(v.ends_with(&[30]));
+assert!(v.ends_with(&[40, 30]));
+assert!(v.ends_with(&v));
+assert!(!v.ends_with(&[50]));
+assert!(!v.ends_with(&[50, 30]));
Always returns true
if needle
is an empty slice:
let v = &[10, 40, 30];
+assert!(v.ends_with(&[]));
+let v: &[u8] = &[];
+assert!(v.ends_with(&[]));
Returns a subslice with the prefix removed.
+If the slice starts with prefix
, returns the subslice after the prefix, wrapped in Some
.
+If prefix
is empty, simply returns the original slice. If prefix
is equal to the
+original slice, returns an empty slice.
If the slice does not start with prefix
, returns None
.
let v = &[10, 40, 30];
+assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..]));
+assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..]));
+assert_eq!(v.strip_prefix(&[10, 40, 30]), Some(&[][..]));
+assert_eq!(v.strip_prefix(&[50]), None);
+assert_eq!(v.strip_prefix(&[10, 50]), None);
+
+let prefix : &str = "he";
+assert_eq!(b"hello".strip_prefix(prefix.as_bytes()),
+ Some(b"llo".as_ref()));
Returns a subslice with the suffix removed.
+If the slice ends with suffix
, returns the subslice before the suffix, wrapped in Some
.
+If suffix
is empty, simply returns the original slice. If suffix
is equal to the
+original slice, returns an empty slice.
If the slice does not end with suffix
, returns None
.
let v = &[10, 40, 30];
+assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
+assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
+assert_eq!(v.strip_suffix(&[10, 40, 30]), Some(&[][..]));
+assert_eq!(v.strip_suffix(&[50]), None);
+assert_eq!(v.strip_suffix(&[50, 30]), None);
Binary searches this slice for a given element. +If the slice is not sorted, the returned result is unspecified and +meaningless.
+If the value is found then Result::Ok
is returned, containing the
+index of the matching element. If there are multiple matches, then any
+one of the matches could be returned. The index is chosen
+deterministically, but is subject to change in future versions of Rust.
+If the value is not found then Result::Err
is returned, containing
+the index where a matching element could be inserted while maintaining
+sorted order.
See also binary_search_by
, binary_search_by_key
, and partition_point
.
Looks up a series of four elements. The first is found, with a
+uniquely determined position; the second and third are not
+found; the fourth could match any position in [1, 4]
.
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+
+assert_eq!(s.binary_search(&13), Ok(9));
+assert_eq!(s.binary_search(&4), Err(7));
+assert_eq!(s.binary_search(&100), Err(13));
+let r = s.binary_search(&1);
+assert!(match r { Ok(1..=4) => true, _ => false, });
If you want to find that whole range of matching items, rather than
+an arbitrary matching one, that can be done using partition_point
:
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+
+let low = s.partition_point(|x| x < &1);
+assert_eq!(low, 1);
+let high = s.partition_point(|x| x <= &1);
+assert_eq!(high, 5);
+let r = s.binary_search(&1);
+assert!((low..high).contains(&r.unwrap()));
+
+assert!(s[..low].iter().all(|&x| x < 1));
+assert!(s[low..high].iter().all(|&x| x == 1));
+assert!(s[high..].iter().all(|&x| x > 1));
+
+// For something not found, the "range" of equal items is empty
+assert_eq!(s.partition_point(|x| x < &11), 9);
+assert_eq!(s.partition_point(|x| x <= &11), 9);
+assert_eq!(s.binary_search(&11), Err(9));
If you want to insert an item to a sorted vector, while maintaining
+sort order, consider using partition_point
:
let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+let num = 42;
+let idx = s.partition_point(|&x| x <= num);
+// If `num` is unique, `s.partition_point(|&x| x < num)` (with `<`) is equivalent to
+// `s.binary_search(&num).unwrap_or_else(|x| x)`, but using `<=` will allow `insert`
+// to shift less elements.
+s.insert(idx, num);
+assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
Binary searches this slice with a comparator function.
+The comparator function should return an order code that indicates
+whether its argument is Less
, Equal
or Greater
the desired
+target.
+If the slice is not sorted or if the comparator function does not
+implement an order consistent with the sort order of the underlying
+slice, the returned result is unspecified and meaningless.
If the value is found then Result::Ok
is returned, containing the
+index of the matching element. If there are multiple matches, then any
+one of the matches could be returned. The index is chosen
+deterministically, but is subject to change in future versions of Rust.
+If the value is not found then Result::Err
is returned, containing
+the index where a matching element could be inserted while maintaining
+sorted order.
See also binary_search
, binary_search_by_key
, and partition_point
.
Looks up a series of four elements. The first is found, with a
+uniquely determined position; the second and third are not
+found; the fourth could match any position in [1, 4]
.
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+
+let seek = 13;
+assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
+let seek = 4;
+assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
+let seek = 100;
+assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
+let seek = 1;
+let r = s.binary_search_by(|probe| probe.cmp(&seek));
+assert!(match r { Ok(1..=4) => true, _ => false, });
Binary searches this slice with a key extraction function.
+Assumes that the slice is sorted by the key, for instance with
+sort_by_key
using the same key extraction function.
+If the slice is not sorted by the key, the returned result is
+unspecified and meaningless.
If the value is found then Result::Ok
is returned, containing the
+index of the matching element. If there are multiple matches, then any
+one of the matches could be returned. The index is chosen
+deterministically, but is subject to change in future versions of Rust.
+If the value is not found then Result::Err
is returned, containing
+the index where a matching element could be inserted while maintaining
+sorted order.
See also binary_search
, binary_search_by
, and partition_point
.
Looks up a series of four elements in a slice of pairs sorted by
+their second elements. The first is found, with a uniquely
+determined position; the second and third are not found; the
+fourth could match any position in [1, 4]
.
let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
+ (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
+ (1, 21), (2, 34), (4, 55)];
+
+assert_eq!(s.binary_search_by_key(&13, |&(a, b)| b), Ok(9));
+assert_eq!(s.binary_search_by_key(&4, |&(a, b)| b), Err(7));
+assert_eq!(s.binary_search_by_key(&100, |&(a, b)| b), Err(13));
+let r = s.binary_search_by_key(&1, |&(a, b)| b);
+assert!(match r { Ok(1..=4) => true, _ => false, });
Sorts the slice without preserving the initial order of equal elements.
+This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not +allocate), and O(n * log(n)) worst-case.
+If the implementation of Ord
for T
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for T
panics.
Sorting types that only implement PartialOrd
such as f32
and f64
require
+additional precautions. For example, f32::NAN != f32::NAN
, which doesn’t fulfill the
+reflexivity requirement of Ord
. By using an alternative comparison function with
+slice::sort_unstable_by
such as f32::total_cmp
or f64::total_cmp
that defines a
+total order users can sort slices containing floating-point values. Alternatively, if all
+values in the slice are guaranteed to be in a subset for which PartialOrd::partial_cmp
+forms a total order, it’s possible to sort the slice with sort_unstable_by(|a, b| a.partial_cmp(b).unwrap())
.
The current implementation is based on ipnsort by Lukas Bergdoll and Orson Peters, which +combines the fast average case of quicksort with the fast worst case of heapsort, achieving +linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the +expected time to sort the data is O(n * log(k)).
+It is typically faster than stable sorting, except in a few special cases, e.g., when the +slice is partially sorted.
+May panic if the implementation of Ord
for T
does not implement a total order.
let mut v = [4, -5, 1, -3, 2];
+
+v.sort_unstable();
+assert_eq!(v, [-5, -3, 1, 2, 4]);
Sorts the slice with a comparison function, without preserving the initial order of +equal elements.
+This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not +allocate), and O(n * log(n)) worst-case.
+If the comparison function compare
does not implement a total order the resulting order
+of elements in the slice is unspecified. All original elements will remain in the slice and
+any possible modifications via interior mutability are observed in the input. Same is true
+if compare
panics.
For example |a, b| (a - b).cmp(a)
is a comparison function that is neither transitive nor
+reflexive nor total, a < b < c < a
with a = 1, b = 2, c = 3
. For more information and
+examples see the Ord
documentation.
The current implementation is based on ipnsort by Lukas Bergdoll and Orson Peters, which +combines the fast average case of quicksort with the fast worst case of heapsort, achieving +linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the +expected time to sort the data is O(n * log(k)).
+It is typically faster than stable sorting, except in a few special cases, e.g., when the +slice is partially sorted.
+May panic if compare
does not implement a total order.
let mut v = [4, -5, 1, -3, 2];
+v.sort_unstable_by(|a, b| a.cmp(b));
+assert_eq!(v, [-5, -3, 1, 2, 4]);
+
+// reverse sorting
+v.sort_unstable_by(|a, b| b.cmp(a));
+assert_eq!(v, [4, 2, 1, -3, -5]);
Sorts the slice with a key extraction function, without preserving the initial order of +equal elements.
+This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not +allocate), and O(n * log(n)) worst-case.
+If the implementation of Ord
for K
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for K
panics.
The current implementation is based on ipnsort by Lukas Bergdoll and Orson Peters, which +combines the fast average case of quicksort with the fast worst case of heapsort, achieving +linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the +expected time to sort the data is O(n * log(k)).
+It is typically faster than stable sorting, except in a few special cases, e.g., when the +slice is partially sorted.
+May panic if the implementation of Ord
for K
does not implement a total order.
let mut v = [4i32, -5, 1, -3, 2];
+
+v.sort_unstable_by_key(|k| k.abs());
+assert_eq!(v, [1, 2, -3, 4, -5]);
Reorders the slice such that the element at index
after the reordering is at its final
+sorted position.
This reordering has the additional property that any value at position i < index
will be
+less than or equal to any value at a position j > index
. Additionally, this reordering is
+unstable (i.e. any number of equal elements may end up at position index
), in-place (i.e.
+does not allocate), and runs in O(n) time. This function is also known as “kth element”
+in other libraries.
It returns a triplet of the following from the reordered slice: the subslice prior to
+index
, the element at index
, and the subslice after index
; accordingly, the values in
+those two subslices will respectively all be less-than-or-equal-to and
+greater-than-or-equal-to the value of the element at index
.
The current algorithm is an introselect implementation based on ipnsort by Lukas Bergdoll
+and Orson Peters, which is also the basis for sort_unstable
. The fallback algorithm is
+Median of Medians using Tukey’s Ninther for pivot selection, which guarantees linear runtime
+for all inputs.
Panics when index >= len()
, meaning it always panics on empty slices.
May panic if the implementation of Ord
for T
does not implement a total order.
let mut v = [-5i32, 4, 2, -3, 1];
+
+// Find the items less than or equal to the median, the median, and greater than or equal to
+// the median.
+let (lesser, median, greater) = v.select_nth_unstable(2);
+
+assert!(lesser == [-3, -5] || lesser == [-5, -3]);
+assert_eq!(median, &mut 1);
+assert!(greater == [4, 2] || greater == [2, 4]);
+
+// We are only guaranteed the slice will be one of the following, based on the way we sort
+// about the specified index.
+assert!(v == [-3, -5, 1, 2, 4] ||
+ v == [-5, -3, 1, 2, 4] ||
+ v == [-3, -5, 1, 4, 2] ||
+ v == [-5, -3, 1, 4, 2]);
Reorders the slice with a comparator function such that the element at index
after the
+reordering is at its final sorted position.
This reordering has the additional property that any value at position i < index
will be
+less than or equal to any value at a position j > index
using the comparator function.
+Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
+position index
), in-place (i.e. does not allocate), and runs in O(n) time. This
+function is also known as “kth element” in other libraries.
It returns a triplet of the following from the slice reordered according to the provided
+comparator function: the subslice prior to index
, the element at index
, and the subslice
+after index
; accordingly, the values in those two subslices will respectively all be
+less-than-or-equal-to and greater-than-or-equal-to the value of the element at index
.
The current algorithm is an introselect implementation based on ipnsort by Lukas Bergdoll
+and Orson Peters, which is also the basis for sort_unstable
. The fallback algorithm is
+Median of Medians using Tukey’s Ninther for pivot selection, which guarantees linear runtime
+for all inputs.
Panics when index >= len()
, meaning it always panics on empty slices.
May panic if compare
does not implement a total order.
let mut v = [-5i32, 4, 2, -3, 1];
+
+// Find the items less than or equal to the median, the median, and greater than or equal to
+// the median as if the slice were sorted in descending order.
+let (lesser, median, greater) = v.select_nth_unstable_by(2, |a, b| b.cmp(a));
+
+assert!(lesser == [4, 2] || lesser == [2, 4]);
+assert_eq!(median, &mut 1);
+assert!(greater == [-3, -5] || greater == [-5, -3]);
+
+// We are only guaranteed the slice will be one of the following, based on the way we sort
+// about the specified index.
+assert!(v == [2, 4, 1, -5, -3] ||
+ v == [2, 4, 1, -3, -5] ||
+ v == [4, 2, 1, -5, -3] ||
+ v == [4, 2, 1, -3, -5]);
Reorders the slice with a key extraction function such that the element at index
after the
+reordering is at its final sorted position.
This reordering has the additional property that any value at position i < index
will be
+less than or equal to any value at a position j > index
using the key extraction function.
+Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
+position index
), in-place (i.e. does not allocate), and runs in O(n) time. This
+function is also known as “kth element” in other libraries.
It returns a triplet of the following from the slice reordered according to the provided key
+extraction function: the subslice prior to index
, the element at index
, and the subslice
+after index
; accordingly, the values in those two subslices will respectively all be
+less-than-or-equal-to and greater-than-or-equal-to the value of the element at index
.
The current algorithm is an introselect implementation based on ipnsort by Lukas Bergdoll
+and Orson Peters, which is also the basis for sort_unstable
. The fallback algorithm is
+Median of Medians using Tukey’s Ninther for pivot selection, which guarantees linear runtime
+for all inputs.
Panics when index >= len()
, meaning it always panics on empty slices.
May panic if K: Ord
does not implement a total order.
let mut v = [-5i32, 4, 1, -3, 2];
+
+// Find the items less than or equal to the median, the median, and greater than or equal to
+// the median as if the slice were sorted according to absolute value.
+let (lesser, median, greater) = v.select_nth_unstable_by_key(2, |a| a.abs());
+
+assert!(lesser == [1, 2] || lesser == [2, 1]);
+assert_eq!(median, &mut -3);
+assert!(greater == [4, -5] || greater == [-5, 4]);
+
+// We are only guaranteed the slice will be one of the following, based on the way we sort
+// about the specified index.
+assert!(v == [1, 2, -3, 4, -5] ||
+ v == [1, 2, -3, -5, 4] ||
+ v == [2, 1, -3, 4, -5] ||
+ v == [2, 1, -3, -5, 4]);
slice_partition_dedup
)Moves all consecutive repeated elements to the end of the slice according to the
+PartialEq
trait implementation.
Returns two slices. The first contains no consecutive repeated elements. +The second contains all the duplicates in no specified order.
+If the slice is sorted, the first returned slice contains no duplicates.
+#![feature(slice_partition_dedup)]
+
+let mut slice = [1, 2, 2, 3, 3, 2, 1, 1];
+
+let (dedup, duplicates) = slice.partition_dedup();
+
+assert_eq!(dedup, [1, 2, 3, 2, 1]);
+assert_eq!(duplicates, [2, 3, 1]);
slice_partition_dedup
)Moves all but the first of consecutive elements to the end of the slice satisfying +a given equality relation.
+Returns two slices. The first contains no consecutive repeated elements. +The second contains all the duplicates in no specified order.
+The same_bucket
function is passed references to two elements from the slice and
+must determine if the elements compare equal. The elements are passed in opposite order
+from their order in the slice, so if same_bucket(a, b)
returns true
, a
is moved
+at the end of the slice.
If the slice is sorted, the first returned slice contains no duplicates.
+#![feature(slice_partition_dedup)]
+
+let mut slice = ["foo", "Foo", "BAZ", "Bar", "bar", "baz", "BAZ"];
+
+let (dedup, duplicates) = slice.partition_dedup_by(|a, b| a.eq_ignore_ascii_case(b));
+
+assert_eq!(dedup, ["foo", "BAZ", "Bar", "baz"]);
+assert_eq!(duplicates, ["bar", "Foo", "BAZ"]);
slice_partition_dedup
)Moves all but the first of consecutive elements to the end of the slice that resolve +to the same key.
+Returns two slices. The first contains no consecutive repeated elements. +The second contains all the duplicates in no specified order.
+If the slice is sorted, the first returned slice contains no duplicates.
+#![feature(slice_partition_dedup)]
+
+let mut slice = [10, 20, 21, 30, 30, 20, 11, 13];
+
+let (dedup, duplicates) = slice.partition_dedup_by_key(|i| *i / 10);
+
+assert_eq!(dedup, [10, 20, 30, 20, 11]);
+assert_eq!(duplicates, [21, 30, 13]);
Rotates the slice in-place such that the first mid
elements of the
+slice move to the end while the last self.len() - mid
elements move to
+the front.
After calling rotate_left
, the element previously at index mid
will
+become the first element in the slice.
This function will panic if mid
is greater than the length of the
+slice. Note that mid == self.len()
does not panic and is a no-op
+rotation.
Takes linear (in self.len()
) time.
let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+a.rotate_left(2);
+assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
Rotating a subslice:
+ +let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+a[1..5].rotate_left(1);
+assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
Rotates the slice in-place such that the first self.len() - k
+elements of the slice move to the end while the last k
elements move
+to the front.
After calling rotate_right
, the element previously at index
+self.len() - k
will become the first element in the slice.
This function will panic if k
is greater than the length of the
+slice. Note that k == self.len()
does not panic and is a no-op
+rotation.
Takes linear (in self.len()
) time.
let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+a.rotate_right(2);
+assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
Rotating a subslice:
+ +let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+a[1..5].rotate_right(1);
+assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
Fills self
with elements by cloning value
.
let mut buf = vec![0; 10];
+buf.fill(1);
+assert_eq!(buf, vec![1; 10]);
Fills self
with elements returned by calling a closure repeatedly.
This method uses a closure to create new values. If you’d rather
+Clone
a given value, use fill
. If you want to use the Default
+trait to generate values, you can pass Default::default
as the
+argument.
let mut buf = vec![1; 10];
+buf.fill_with(Default::default);
+assert_eq!(buf, vec![0; 10]);
Copies the elements from src
into self
.
The length of src
must be the same as self
.
This function will panic if the two slices have different lengths.
+Cloning two elements from a slice into another:
+ +let src = [1, 2, 3, 4];
+let mut dst = [0, 0];
+
+// Because the slices have to be the same length,
+// we slice the source slice from four elements
+// to two. It will panic if we don't do this.
+dst.clone_from_slice(&src[2..]);
+
+assert_eq!(src, [1, 2, 3, 4]);
+assert_eq!(dst, [3, 4]);
Rust enforces that there can only be one mutable reference with no
+immutable references to a particular piece of data in a particular
+scope. Because of this, attempting to use clone_from_slice
on a
+single slice will result in a compile failure:
let mut slice = [1, 2, 3, 4, 5];
+
+slice[..2].clone_from_slice(&slice[3..]); // compile fail!
To work around this, we can use split_at_mut
to create two distinct
+sub-slices from a slice:
let mut slice = [1, 2, 3, 4, 5];
+
+{
+ let (left, right) = slice.split_at_mut(2);
+ left.clone_from_slice(&right[1..]);
+}
+
+assert_eq!(slice, [4, 5, 3, 4, 5]);
Copies all elements from src
into self
, using a memcpy.
The length of src
must be the same as self
.
If T
does not implement Copy
, use clone_from_slice
.
This function will panic if the two slices have different lengths.
+Copying two elements from a slice into another:
+ +let src = [1, 2, 3, 4];
+let mut dst = [0, 0];
+
+// Because the slices have to be the same length,
+// we slice the source slice from four elements
+// to two. It will panic if we don't do this.
+dst.copy_from_slice(&src[2..]);
+
+assert_eq!(src, [1, 2, 3, 4]);
+assert_eq!(dst, [3, 4]);
Rust enforces that there can only be one mutable reference with no
+immutable references to a particular piece of data in a particular
+scope. Because of this, attempting to use copy_from_slice
on a
+single slice will result in a compile failure:
let mut slice = [1, 2, 3, 4, 5];
+
+slice[..2].copy_from_slice(&slice[3..]); // compile fail!
To work around this, we can use split_at_mut
to create two distinct
+sub-slices from a slice:
let mut slice = [1, 2, 3, 4, 5];
+
+{
+ let (left, right) = slice.split_at_mut(2);
+ left.copy_from_slice(&right[1..]);
+}
+
+assert_eq!(slice, [4, 5, 3, 4, 5]);
Copies elements from one part of the slice to another part of itself, +using a memmove.
+src
is the range within self
to copy from. dest
is the starting
+index of the range within self
to copy to, which will have the same
+length as src
. The two ranges may overlap. The ends of the two ranges
+must be less than or equal to self.len()
.
This function will panic if either range exceeds the end of the slice,
+or if the end of src
is before the start.
Copying four bytes within a slice:
+ +let mut bytes = *b"Hello, World!";
+
+bytes.copy_within(1..5, 8);
+
+assert_eq!(&bytes, b"Hello, Wello!");
Swaps all elements in self
with those in other
.
The length of other
must be the same as self
.
This function will panic if the two slices have different lengths.
+Swapping two elements across slices:
+ +let mut slice1 = [0, 0];
+let mut slice2 = [1, 2, 3, 4];
+
+slice1.swap_with_slice(&mut slice2[2..]);
+
+assert_eq!(slice1, [3, 4]);
+assert_eq!(slice2, [1, 2, 0, 0]);
Rust enforces that there can only be one mutable reference to a
+particular piece of data in a particular scope. Because of this,
+attempting to use swap_with_slice
on a single slice will result in
+a compile failure:
let mut slice = [1, 2, 3, 4, 5];
+slice[..2].swap_with_slice(&mut slice[3..]); // compile fail!
To work around this, we can use split_at_mut
to create two distinct
+mutable sub-slices from a slice:
let mut slice = [1, 2, 3, 4, 5];
+
+{
+ let (left, right) = slice.split_at_mut(2);
+ left.swap_with_slice(&mut right[1..]);
+}
+
+assert_eq!(slice, [4, 5, 3, 1, 2]);
Transmutes the slice to a slice of another type, ensuring alignment of the types is +maintained.
+This method splits the slice into three distinct slices: prefix, correctly aligned middle +slice of a new type, and the suffix slice. The middle part will be as big as possible under +the given alignment constraint and element size.
+This method has no purpose when either input element T
or output element U
are
+zero-sized and will return the original slice without splitting anything.
This method is essentially a transmute
with respect to the elements in the returned
+middle slice, so all the usual caveats pertaining to transmute::<T, U>
also apply here.
Basic usage:
+ +unsafe {
+ let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
+ let (prefix, shorts, suffix) = bytes.align_to::<u16>();
+ // less_efficient_algorithm_for_bytes(prefix);
+ // more_efficient_algorithm_for_aligned_shorts(shorts);
+ // less_efficient_algorithm_for_bytes(suffix);
+}
Transmutes the mutable slice to a mutable slice of another type, ensuring alignment of the +types is maintained.
+This method splits the slice into three distinct slices: prefix, correctly aligned middle +slice of a new type, and the suffix slice. The middle part will be as big as possible under +the given alignment constraint and element size.
+This method has no purpose when either input element T
or output element U
are
+zero-sized and will return the original slice without splitting anything.
This method is essentially a transmute
with respect to the elements in the returned
+middle slice, so all the usual caveats pertaining to transmute::<T, U>
also apply here.
Basic usage:
+ +unsafe {
+ let mut bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
+ let (prefix, shorts, suffix) = bytes.align_to_mut::<u16>();
+ // less_efficient_algorithm_for_bytes(prefix);
+ // more_efficient_algorithm_for_aligned_shorts(shorts);
+ // less_efficient_algorithm_for_bytes(suffix);
+}
portable_simd
)Splits a slice into a prefix, a middle of aligned SIMD types, and a suffix.
+This is a safe wrapper around slice::align_to
, so inherits the same
+guarantees as that method.
This will panic if the size of the SIMD type is different from
+LANES
times that of the scalar.
At the time of writing, the trait restrictions on Simd<T, LANES>
keeps
+that from ever happening, as only power-of-two numbers of lanes are
+supported. It’s possible that, in the future, those restrictions might
+be lifted in a way that would make it possible to see panics from this
+method for something like LANES == 3
.
#![feature(portable_simd)]
+use core::simd::prelude::*;
+
+let short = &[1, 2, 3];
+let (prefix, middle, suffix) = short.as_simd::<4>();
+assert_eq!(middle, []); // Not enough elements for anything in the middle
+
+// They might be split in any possible way between prefix and suffix
+let it = prefix.iter().chain(suffix).copied();
+assert_eq!(it.collect::<Vec<_>>(), vec![1, 2, 3]);
+
+fn basic_simd_sum(x: &[f32]) -> f32 {
+ use std::ops::Add;
+ let (prefix, middle, suffix) = x.as_simd();
+ let sums = f32x4::from_array([
+ prefix.iter().copied().sum(),
+ 0.0,
+ 0.0,
+ suffix.iter().copied().sum(),
+ ]);
+ let sums = middle.iter().copied().fold(sums, f32x4::add);
+ sums.reduce_sum()
+}
+
+let numbers: Vec<f32> = (1..101).map(|x| x as _).collect();
+assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0);
portable_simd
)Splits a mutable slice into a mutable prefix, a middle of aligned SIMD types, +and a mutable suffix.
+This is a safe wrapper around slice::align_to_mut
, so inherits the same
+guarantees as that method.
This is the mutable version of slice::as_simd
; see that for examples.
This will panic if the size of the SIMD type is different from
+LANES
times that of the scalar.
At the time of writing, the trait restrictions on Simd<T, LANES>
keeps
+that from ever happening, as only power-of-two numbers of lanes are
+supported. It’s possible that, in the future, those restrictions might
+be lifted in a way that would make it possible to see panics from this
+method for something like LANES == 3
.
Checks if the elements of this slice are sorted.
+That is, for each element a
and its following element b
, a <= b
must hold. If the
+slice yields exactly zero or one element, true
is returned.
Note that if Self::Item
is only PartialOrd
, but not Ord
, the above definition
+implies that this function returns false
if any two consecutive items are not
+comparable.
let empty: [i32; 0] = [];
+
+assert!([1, 2, 2, 9].is_sorted());
+assert!(![1, 3, 2, 4].is_sorted());
+assert!([0].is_sorted());
+assert!(empty.is_sorted());
+assert!(![0.0, 1.0, f32::NAN].is_sorted());
Checks if the elements of this slice are sorted using the given comparator function.
+Instead of using PartialOrd::partial_cmp
, this function uses the given compare
+function to determine whether two elements are to be considered in sorted order.
assert!([1, 2, 2, 9].is_sorted_by(|a, b| a <= b));
+assert!(![1, 2, 2, 9].is_sorted_by(|a, b| a < b));
+
+assert!([0].is_sorted_by(|a, b| true));
+assert!([0].is_sorted_by(|a, b| false));
+
+let empty: [i32; 0] = [];
+assert!(empty.is_sorted_by(|a, b| false));
+assert!(empty.is_sorted_by(|a, b| true));
Checks if the elements of this slice are sorted using the given key extraction function.
+Instead of comparing the slice’s elements directly, this function compares the keys of the
+elements, as determined by f
. Apart from that, it’s equivalent to is_sorted
; see its
+documentation for more information.
assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
Returns the index of the partition point according to the given predicate +(the index of the first element of the second partition).
+The slice is assumed to be partitioned according to the given predicate.
+This means that all elements for which the predicate returns true are at the start of the slice
+and all elements for which the predicate returns false are at the end.
+For example, [7, 15, 3, 5, 4, 12, 6]
is partitioned under the predicate x % 2 != 0
+(all odd numbers are at the start, all even at the end).
If this slice is not partitioned, the returned result is unspecified and meaningless, +as this method performs a kind of binary search.
+See also binary_search
, binary_search_by
, and binary_search_by_key
.
let v = [1, 2, 3, 3, 5, 6, 7];
+let i = v.partition_point(|&x| x < 5);
+
+assert_eq!(i, 4);
+assert!(v[..i].iter().all(|&x| x < 5));
+assert!(v[i..].iter().all(|&x| !(x < 5)));
If all elements of the slice match the predicate, including if the slice +is empty, then the length of the slice will be returned:
+ +let a = [2, 4, 8];
+assert_eq!(a.partition_point(|x| x < &100), a.len());
+let a: [i32; 0] = [];
+assert_eq!(a.partition_point(|x| x < &100), 0);
If you want to insert an item to a sorted vector, while maintaining +sort order:
+ +let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+let num = 42;
+let idx = s.partition_point(|&x| x <= num);
+s.insert(idx, num);
+assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
slice_take
)Removes the subslice corresponding to the given range +and returns a reference to it.
+Returns None
and does not modify the slice if the given
+range is out of bounds.
Note that this method only accepts one-sided ranges such as
+2..
or ..6
, but not 2..6
.
Taking the first three elements of a slice:
+ +#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+let mut first_three = slice.take(..3).unwrap();
+
+assert_eq!(slice, &['d']);
+assert_eq!(first_three, &['a', 'b', 'c']);
Taking the last two elements of a slice:
+ +#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+let mut tail = slice.take(2..).unwrap();
+
+assert_eq!(slice, &['a', 'b']);
+assert_eq!(tail, &['c', 'd']);
Getting None
when range
is out of bounds:
#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+
+assert_eq!(None, slice.take(5..));
+assert_eq!(None, slice.take(..5));
+assert_eq!(None, slice.take(..=4));
+let expected: &[char] = &['a', 'b', 'c', 'd'];
+assert_eq!(Some(expected), slice.take(..4));
slice_take
)Removes the subslice corresponding to the given range +and returns a mutable reference to it.
+Returns None
and does not modify the slice if the given
+range is out of bounds.
Note that this method only accepts one-sided ranges such as
+2..
or ..6
, but not 2..6
.
Taking the first three elements of a slice:
+ +#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+let mut first_three = slice.take_mut(..3).unwrap();
+
+assert_eq!(slice, &mut ['d']);
+assert_eq!(first_three, &mut ['a', 'b', 'c']);
Taking the last two elements of a slice:
+ +#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+let mut tail = slice.take_mut(2..).unwrap();
+
+assert_eq!(slice, &mut ['a', 'b']);
+assert_eq!(tail, &mut ['c', 'd']);
Getting None
when range
is out of bounds:
#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+
+assert_eq!(None, slice.take_mut(5..));
+assert_eq!(None, slice.take_mut(..5));
+assert_eq!(None, slice.take_mut(..=4));
+let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+assert_eq!(Some(expected), slice.take_mut(..4));
slice_take
)Removes the first element of the slice and returns a reference +to it.
+Returns None
if the slice is empty.
#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c'];
+let first = slice.take_first().unwrap();
+
+assert_eq!(slice, &['b', 'c']);
+assert_eq!(first, &'a');
slice_take
)Removes the first element of the slice and returns a mutable +reference to it.
+Returns None
if the slice is empty.
#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
+let first = slice.take_first_mut().unwrap();
+*first = 'd';
+
+assert_eq!(slice, &['b', 'c']);
+assert_eq!(first, &'d');
slice_take
)Removes the last element of the slice and returns a reference +to it.
+Returns None
if the slice is empty.
#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c'];
+let last = slice.take_last().unwrap();
+
+assert_eq!(slice, &['a', 'b']);
+assert_eq!(last, &'c');
slice_take
)Removes the last element of the slice and returns a mutable +reference to it.
+Returns None
if the slice is empty.
#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
+let last = slice.take_last_mut().unwrap();
+*last = 'd';
+
+assert_eq!(slice, &['a', 'b']);
+assert_eq!(last, &'d');
get_many_mut
)Returns mutable references to many indices at once, without doing any checks.
+For a safe alternative see get_many_mut
.
Calling this method with overlapping or out-of-bounds indices is undefined behavior +even if the resulting references are not used.
+#![feature(get_many_mut)]
+
+let x = &mut [1, 2, 4];
+
+unsafe {
+ let [a, b] = x.get_many_unchecked_mut([0, 2]);
+ *a *= 10;
+ *b *= 100;
+}
+assert_eq!(x, &[10, 2, 400]);
get_many_mut
)Returns mutable references to many indices at once.
+Returns an error if any index is out-of-bounds, or if the same index was +passed more than once.
+#![feature(get_many_mut)]
+
+let v = &mut [1, 2, 3];
+if let Ok([a, b]) = v.get_many_mut([0, 2]) {
+ *a = 413;
+ *b = 612;
+}
+assert_eq!(v, &[413, 2, 612]);
substr_range
)Returns the index that an element reference points to.
+Returns None
if element
does not point within the slice or if it points between elements.
This method is useful for extending slice iterators like slice::split
.
Note that this uses pointer arithmetic and does not compare elements.
+To find the index of an element via comparison, use
+.iter().position()
instead.
Panics if T
is zero-sized.
Basic usage:
+ +#![feature(substr_range)]
+
+let nums: &[u32] = &[1, 7, 1, 1];
+let num = &nums[2];
+
+assert_eq!(num, &1);
+assert_eq!(nums.elem_offset(num), Some(2));
Returning None
with an in-between element:
#![feature(substr_range)]
+
+let arr: &[[u32; 2]] = &[[0, 1], [2, 3]];
+let flat_arr: &[u32] = arr.as_flattened();
+
+let ok_elm: &[u32; 2] = flat_arr[0..2].try_into().unwrap();
+let weird_elm: &[u32; 2] = flat_arr[1..3].try_into().unwrap();
+
+assert_eq!(ok_elm, &[0, 1]);
+assert_eq!(weird_elm, &[1, 2]);
+
+assert_eq!(arr.elem_offset(ok_elm), Some(0)); // Points to element 0
+assert_eq!(arr.elem_offset(weird_elm), None); // Points between element 0 and 1
substr_range
)Returns the range of indices that a subslice points to.
+Returns None
if subslice
does not point within the slice or if it points between elements.
This method does not compare elements. Instead, this method finds the location in the slice that
+subslice
was obtained from. To find the index of a subslice via comparison, instead use
+.windows()
.position()
.
This method is useful for extending slice iterators like slice::split
.
Note that this may return a false positive (either Some(0..0)
or Some(self.len()..self.len())
)
+if subslice
has a length of zero and points to the beginning or end of another, separate, slice.
Panics if T
is zero-sized.
Basic usage:
+ +#![feature(substr_range)]
+
+let nums = &[0, 5, 10, 0, 0, 5];
+
+let mut iter = nums
+ .split(|t| *t == 0)
+ .map(|n| nums.subslice_range(n).unwrap());
+
+assert_eq!(iter.next(), Some(0..0));
+assert_eq!(iter.next(), Some(1..3));
+assert_eq!(iter.next(), Some(4..4));
+assert_eq!(iter.next(), Some(5..6));
Takes a &[[T; N]]
, and flattens it to a &[T]
.
This panics if the length of the resulting slice would overflow a usize
.
This is only possible when flattening a slice of arrays of zero-sized
+types, and thus tends to be irrelevant in practice. If
+size_of::<T>() > 0
, this will never panic.
assert_eq!([[1, 2, 3], [4, 5, 6]].as_flattened(), &[1, 2, 3, 4, 5, 6]);
+
+assert_eq!(
+ [[1, 2, 3], [4, 5, 6]].as_flattened(),
+ [[1, 2], [3, 4], [5, 6]].as_flattened(),
+);
+
+let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []];
+assert!(slice_of_empty_arrays.as_flattened().is_empty());
+
+let empty_slice_of_arrays: &[[u32; 10]] = &[];
+assert!(empty_slice_of_arrays.as_flattened().is_empty());
Takes a &mut [[T; N]]
, and flattens it to a &mut [T]
.
This panics if the length of the resulting slice would overflow a usize
.
This is only possible when flattening a slice of arrays of zero-sized
+types, and thus tends to be irrelevant in practice. If
+size_of::<T>() > 0
, this will never panic.
fn add_5_to_all(slice: &mut [i32]) {
+ for i in slice {
+ *i += 5;
+ }
+}
+
+let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
+add_5_to_all(array.as_flattened_mut());
+assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
sort_floats
)Sorts the slice of floats.
+This sort is in-place (i.e. does not allocate), O(n * log(n)) worst-case, and uses
+the ordering defined by f32::total_cmp
.
This uses the same sorting algorithm as sort_unstable_by
.
#![feature(sort_floats)]
+let mut v = [2.6, -5e-8, f32::NAN, 8.29, f32::INFINITY, -1.0, 0.0, -f32::INFINITY, -0.0];
+
+v.sort_floats();
+let sorted = [-f32::INFINITY, -1.0, -5e-8, -0.0, 0.0, 2.6, 8.29, f32::INFINITY, f32::NAN];
+assert_eq!(&v[..8], &sorted[..8]);
+assert!(v[8].is_nan());
sort_floats
)Sorts the slice of floats.
+This sort is in-place (i.e. does not allocate), O(n * log(n)) worst-case, and uses
+the ordering defined by f64::total_cmp
.
This uses the same sorting algorithm as sort_unstable_by
.
#![feature(sort_floats)]
+let mut v = [2.6, -5e-8, f64::NAN, 8.29, f64::INFINITY, -1.0, 0.0, -f64::INFINITY, -0.0];
+
+v.sort_floats();
+let sorted = [-f64::INFINITY, -1.0, -5e-8, -0.0, 0.0, 2.6, 8.29, f64::INFINITY, f64::NAN];
+assert_eq!(&v[..8], &sorted[..8]);
+assert!(v[8].is_nan());
Creates an iterator over the contiguous valid UTF-8 ranges of this +slice, and the non-UTF-8 fragments in between.
+This function formats arbitrary but mostly-UTF-8 bytes into Rust source
+code in the form of a C-string literal (c"..."
).
use std::fmt::Write as _;
+
+pub fn cstr_literal(bytes: &[u8]) -> String {
+ let mut repr = String::new();
+ repr.push_str("c\"");
+ for chunk in bytes.utf8_chunks() {
+ for ch in chunk.valid().chars() {
+ // Escapes \0, \t, \r, \n, \\, \', \", and uses \u{...} for non-printable characters.
+ write!(repr, "{}", ch.escape_debug()).unwrap();
+ }
+ for byte in chunk.invalid() {
+ write!(repr, "\\x{:02X}", byte).unwrap();
+ }
+ }
+ repr.push('"');
+ repr
+}
+
+fn main() {
+ let lit = cstr_literal(b"\xferris the \xf0\x9f\xa6\x80\x07");
+ let expected = stringify!(c"\xFErris the 🦀\u{7}");
+ assert_eq!(lit, expected);
+}
Sorts the slice, preserving initial order of equal elements.
+This sort is stable (i.e., does not reorder equal elements) and O(n * log(n)) +worst-case.
+If the implementation of Ord
for T
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for T
panics.
When applicable, unstable sorting is preferred because it is generally faster than stable
+sorting and it doesn’t allocate auxiliary memory. See
+sort_unstable
. The exception are partially sorted slices, which
+may be better served with slice::sort
.
Sorting types that only implement PartialOrd
such as f32
and f64
require
+additional precautions. For example, f32::NAN != f32::NAN
, which doesn’t fulfill the
+reflexivity requirement of Ord
. By using an alternative comparison function with
+slice::sort_by
such as f32::total_cmp
or f64::total_cmp
that defines a total
+order users can sort slices containing floating-point values. Alternatively, if all values
+in the slice are guaranteed to be in a subset for which PartialOrd::partial_cmp
forms a
+total order, it’s possible to sort the slice with sort_by(|a, b| a.partial_cmp(b).unwrap())
.
The current implementation is based on driftsort by Orson Peters and Lukas Bergdoll, which +combines the fast average case of quicksort with the fast worst case and partial run +detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs +with k distinct elements, the expected time to sort the data is O(n * log(k)).
+The auxiliary memory allocation behavior depends on the input length. Short slices are
+handled without allocation, medium sized slices allocate self.len()
and beyond that it
+clamps at self.len() / 2
.
May panic if the implementation of Ord
for T
does not implement a total order.
let mut v = [4, -5, 1, -3, 2];
+
+v.sort();
+assert_eq!(v, [-5, -3, 1, 2, 4]);
Sorts the slice with a comparison function, preserving initial order of equal elements.
+This sort is stable (i.e., does not reorder equal elements) and O(n * log(n)) +worst-case.
+If the comparison function compare
does not implement a total order the resulting order
+of elements in the slice is unspecified. All original elements will remain in the slice and
+any possible modifications via interior mutability are observed in the input. Same is true
+if compare
panics.
For example |a, b| (a - b).cmp(a)
is a comparison function that is neither transitive nor
+reflexive nor total, a < b < c < a
with a = 1, b = 2, c = 3
. For more information and
+examples see the Ord
documentation.
The current implementation is based on driftsort by Orson Peters and Lukas Bergdoll, which +combines the fast average case of quicksort with the fast worst case and partial run +detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs +with k distinct elements, the expected time to sort the data is O(n * log(k)).
+The auxiliary memory allocation behavior depends on the input length. Short slices are
+handled without allocation, medium sized slices allocate self.len()
and beyond that it
+clamps at self.len() / 2
.
May panic if compare
does not implement a total order.
let mut v = [4, -5, 1, -3, 2];
+v.sort_by(|a, b| a.cmp(b));
+assert_eq!(v, [-5, -3, 1, 2, 4]);
+
+// reverse sorting
+v.sort_by(|a, b| b.cmp(a));
+assert_eq!(v, [4, 2, 1, -3, -5]);
Sorts the slice with a key extraction function, preserving initial order of equal elements.
+This sort is stable (i.e., does not reorder equal elements) and O(m * n * log(n)) +worst-case, where the key function is O(m).
+If the implementation of Ord
for K
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for K
panics.
The current implementation is based on driftsort by Orson Peters and Lukas Bergdoll, which +combines the fast average case of quicksort with the fast worst case and partial run +detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs +with k distinct elements, the expected time to sort the data is O(n * log(k)).
+The auxiliary memory allocation behavior depends on the input length. Short slices are
+handled without allocation, medium sized slices allocate self.len()
and beyond that it
+clamps at self.len() / 2
.
May panic if the implementation of Ord
for K
does not implement a total order.
let mut v = [4i32, -5, 1, -3, 2];
+
+v.sort_by_key(|k| k.abs());
+assert_eq!(v, [1, 2, -3, 4, -5]);
Sorts the slice with a key extraction function, preserving initial order of equal elements.
+This sort is stable (i.e., does not reorder equal elements) and O(m * n + n * +log(n)) worst-case, where the key function is O(m).
+During sorting, the key function is called at most once per element, by using temporary +storage to remember the results of key evaluation. The order of calls to the key function is +unspecified and may change in future versions of the standard library.
+If the implementation of Ord
for K
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for K
panics.
For simple key functions (e.g., functions that are property accesses or basic operations),
+sort_by_key
is likely to be faster.
The current implementation is based on instruction-parallel-network sort by Lukas +Bergdoll, which combines the fast average case of randomized quicksort with the fast worst +case of heapsort, while achieving linear time on fully sorted and reversed inputs. And +O(k * log(n)) where k is the number of distinct elements in the input. It leverages +superscalar out-of-order execution capabilities commonly found in CPUs, to efficiently +perform the operation.
+In the worst case, the algorithm allocates temporary storage in a Vec<(K, usize)>
the
+length of the slice.
May panic if the implementation of Ord
for K
does not implement a total order.
let mut v = [4i32, -5, 1, -3, 2, 10];
+
+// Strings are sorted by lexicographical order.
+v.sort_by_cached_key(|k| k.to_string());
+assert_eq!(v, [-3, -5, 1, 10, 2, 4]);
Copies self
into a new Vec
.
let s = [10, 40, 30];
+let x = s.to_vec();
+// Here, `s` and `x` can be modified independently.
allocator_api
)Copies self
into a new Vec
with an allocator.
#![feature(allocator_api)]
+
+use std::alloc::System;
+
+let s = [10, 40, 30];
+let x = s.to_vec_in(System);
+// Here, `s` and `x` can be modified independently.
Flattens a slice of T
into a single value Self::Output
.
assert_eq!(["hello", "world"].concat(), "helloworld");
+assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
Flattens a slice of T
into a single value Self::Output
, placing a
+given separator between each.
assert_eq!(["hello", "world"].join(" "), "hello world");
+assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
+assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]);
Flattens a slice of T
into a single value Self::Output
, placing a
+given separator between each.
assert_eq!(["hello", "world"].connect(" "), "hello world");
+assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
Returns a vector containing a copy of this slice where each byte +is mapped to its ASCII upper case equivalent.
+ASCII letters ‘a’ to ‘z’ are mapped to ‘A’ to ‘Z’, +but non-ASCII letters are unchanged.
+To uppercase the value in-place, use make_ascii_uppercase
.
Returns a vector containing a copy of this slice where each byte +is mapped to its ASCII lower case equivalent.
+ASCII letters ‘A’ to ‘Z’ are mapped to ‘a’ to ‘z’, +but non-ASCII letters are unchanged.
+To lowercase the value in-place, use make_ascii_lowercase
.
parameters
when converting.self
into C
, using the provided parameters.clone_to_uninit
)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
.Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
+further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &Any
’s vtable from &Trait
’s.&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &mut Any
’s vtable from &mut Trait
’s.angle
.other
into Self
, while performing the appropriate scaling,
+rounding and clamping.T
.parameters
when converting.self
into C
, using the provided parameters.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 moreself
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 moreself
as a ReadOnly
.self
into T
, while performing the appropriate scaling,
+rounding and clamping.Value
].Value
].ReadEndian::read_from_little_endian()
.try_into_colors
fails to cast.OutOfBounds
error is returned which contains
+the unclamped color. Read moreSubscriber
to this type, returning a
+[WithDispatch
] wrapper. Read morepub struct Change { /* private fields */ }
parameters
when converting.self
into C
, using the provided parameters.clone_to_uninit
)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
.Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
+further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &Any
’s vtable from &Trait
’s.&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &mut Any
’s vtable from &mut Trait
’s.angle
.other
into Self
, while performing the appropriate scaling,
+rounding and clamping.T
.parameters
when converting.self
into C
, using the provided parameters.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 moreself
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 moreself
as a ReadOnly
.self
into T
, while performing the appropriate scaling,
+rounding and clamping.Value
].Value
].try_into_colors
fails to cast.OutOfBounds
error is returned which contains
+the unclamped color. Read moreSubscriber
to this type, returning a
+[WithDispatch
] wrapper. Read morepub struct Frame { /* private fields */ }
ascii_char
)Views this slice of ASCII characters as a UTF-8 str
.
ascii_char
)Views this slice of ASCII characters as a slice of u8
bytes.
Checks if all bytes in this slice are within the ASCII range.
+ascii_char
)If this slice is_ascii
, returns it as a slice of
+ASCII characters, otherwise returns None
.
ascii_char
)Converts this slice of bytes into a slice of ASCII characters, +without checking whether they’re valid.
+Every byte in the slice must be in 0..=127
, or else this is UB.
Checks that two slices are an ASCII case-insensitive match.
+Same as to_ascii_lowercase(a) == to_ascii_lowercase(b)
,
+but without allocating and copying temporaries.
Converts this slice to its ASCII upper case equivalent in-place.
+ASCII letters ‘a’ to ‘z’ are mapped to ‘A’ to ‘Z’, +but non-ASCII letters are unchanged.
+To return a new uppercased value without modifying the existing one, use
+to_ascii_uppercase
.
Converts this slice to its ASCII lower case equivalent in-place.
+ASCII letters ‘A’ to ‘Z’ are mapped to ‘a’ to ‘z’, +but non-ASCII letters are unchanged.
+To return a new lowercased value without modifying the existing one, use
+to_ascii_lowercase
.
Returns an iterator that produces an escaped version of this slice, +treating it as an ASCII string.
+
+let s = b"0\t\r\n'\"\\\x9d";
+let escaped = s.escape_ascii().to_string();
+assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d");
Returns a byte slice with leading ASCII whitespace bytes removed.
+‘Whitespace’ refers to the definition used by
+u8::is_ascii_whitespace
.
assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n");
+assert_eq!(b" ".trim_ascii_start(), b"");
+assert_eq!(b"".trim_ascii_start(), b"");
Returns a byte slice with trailing ASCII whitespace bytes removed.
+‘Whitespace’ refers to the definition used by
+u8::is_ascii_whitespace
.
assert_eq!(b"\r hello world\n ".trim_ascii_end(), b"\r hello world");
+assert_eq!(b" ".trim_ascii_end(), b"");
+assert_eq!(b"".trim_ascii_end(), b"");
Returns a byte slice with leading and trailing ASCII whitespace bytes +removed.
+‘Whitespace’ refers to the definition used by
+u8::is_ascii_whitespace
.
assert_eq!(b"\r hello world\n ".trim_ascii(), b"hello world");
+assert_eq!(b" ".trim_ascii(), b"");
+assert_eq!(b"".trim_ascii(), b"");
Returns the number of elements in the slice.
+let a = [1, 2, 3];
+assert_eq!(a.len(), 3);
Returns true
if the slice has a length of 0.
let a = [1, 2, 3];
+assert!(!a.is_empty());
+
+let b: &[i32] = &[];
+assert!(b.is_empty());
Returns the first element of the slice, or None
if it is empty.
let v = [10, 40, 30];
+assert_eq!(Some(&10), v.first());
+
+let w: &[i32] = &[];
+assert_eq!(None, w.first());
Returns a mutable pointer to the first element of the slice, or None
if it is empty.
let x = &mut [0, 1, 2];
+
+if let Some(first) = x.first_mut() {
+ *first = 5;
+}
+assert_eq!(x, &[5, 1, 2]);
+
+let y: &mut [i32] = &mut [];
+assert_eq!(None, y.first_mut());
Returns the first and all the rest of the elements of the slice, or None
if it is empty.
let x = &[0, 1, 2];
+
+if let Some((first, elements)) = x.split_first() {
+ assert_eq!(first, &0);
+ assert_eq!(elements, &[1, 2]);
+}
Returns the first and all the rest of the elements of the slice, or None
if it is empty.
let x = &mut [0, 1, 2];
+
+if let Some((first, elements)) = x.split_first_mut() {
+ *first = 3;
+ elements[0] = 4;
+ elements[1] = 5;
+}
+assert_eq!(x, &[3, 4, 5]);
Returns the last and all the rest of the elements of the slice, or None
if it is empty.
let x = &[0, 1, 2];
+
+if let Some((last, elements)) = x.split_last() {
+ assert_eq!(last, &2);
+ assert_eq!(elements, &[0, 1]);
+}
Returns the last and all the rest of the elements of the slice, or None
if it is empty.
let x = &mut [0, 1, 2];
+
+if let Some((last, elements)) = x.split_last_mut() {
+ *last = 3;
+ elements[0] = 4;
+ elements[1] = 5;
+}
+assert_eq!(x, &[4, 5, 3]);
Returns the last element of the slice, or None
if it is empty.
let v = [10, 40, 30];
+assert_eq!(Some(&30), v.last());
+
+let w: &[i32] = &[];
+assert_eq!(None, w.last());
Returns a mutable reference to the last item in the slice, or None
if it is empty.
let x = &mut [0, 1, 2];
+
+if let Some(last) = x.last_mut() {
+ *last = 10;
+}
+assert_eq!(x, &[0, 1, 10]);
+
+let y: &mut [i32] = &mut [];
+assert_eq!(None, y.last_mut());
Returns an array reference to the first N
items in the slice.
If the slice is not at least N
in length, this will return None
.
let u = [10, 40, 30];
+assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
+
+let v: &[i32] = &[10];
+assert_eq!(None, v.first_chunk::<2>());
+
+let w: &[i32] = &[];
+assert_eq!(Some(&[]), w.first_chunk::<0>());
Returns a mutable array reference to the first N
items in the slice.
If the slice is not at least N
in length, this will return None
.
let x = &mut [0, 1, 2];
+
+if let Some(first) = x.first_chunk_mut::<2>() {
+ first[0] = 5;
+ first[1] = 4;
+}
+assert_eq!(x, &[5, 4, 2]);
+
+assert_eq!(None, x.first_chunk_mut::<4>());
Returns an array reference to the first N
items in the slice and the remaining slice.
If the slice is not at least N
in length, this will return None
.
let x = &[0, 1, 2];
+
+if let Some((first, elements)) = x.split_first_chunk::<2>() {
+ assert_eq!(first, &[0, 1]);
+ assert_eq!(elements, &[2]);
+}
+
+assert_eq!(None, x.split_first_chunk::<4>());
Returns a mutable array reference to the first N
items in the slice and the remaining
+slice.
If the slice is not at least N
in length, this will return None
.
let x = &mut [0, 1, 2];
+
+if let Some((first, elements)) = x.split_first_chunk_mut::<2>() {
+ first[0] = 3;
+ first[1] = 4;
+ elements[0] = 5;
+}
+assert_eq!(x, &[3, 4, 5]);
+
+assert_eq!(None, x.split_first_chunk_mut::<4>());
Returns an array reference to the last N
items in the slice and the remaining slice.
If the slice is not at least N
in length, this will return None
.
let x = &[0, 1, 2];
+
+if let Some((elements, last)) = x.split_last_chunk::<2>() {
+ assert_eq!(elements, &[0]);
+ assert_eq!(last, &[1, 2]);
+}
+
+assert_eq!(None, x.split_last_chunk::<4>());
Returns a mutable array reference to the last N
items in the slice and the remaining
+slice.
If the slice is not at least N
in length, this will return None
.
let x = &mut [0, 1, 2];
+
+if let Some((elements, last)) = x.split_last_chunk_mut::<2>() {
+ last[0] = 3;
+ last[1] = 4;
+ elements[0] = 5;
+}
+assert_eq!(x, &[5, 3, 4]);
+
+assert_eq!(None, x.split_last_chunk_mut::<4>());
Returns an array reference to the last N
items in the slice.
If the slice is not at least N
in length, this will return None
.
let u = [10, 40, 30];
+assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
+
+let v: &[i32] = &[10];
+assert_eq!(None, v.last_chunk::<2>());
+
+let w: &[i32] = &[];
+assert_eq!(Some(&[]), w.last_chunk::<0>());
Returns a mutable array reference to the last N
items in the slice.
If the slice is not at least N
in length, this will return None
.
let x = &mut [0, 1, 2];
+
+if let Some(last) = x.last_chunk_mut::<2>() {
+ last[0] = 10;
+ last[1] = 20;
+}
+assert_eq!(x, &[0, 10, 20]);
+
+assert_eq!(None, x.last_chunk_mut::<4>());
Returns a reference to an element or subslice depending on the type of +index.
+None
if out of bounds.None
if out of bounds.let v = [10, 40, 30];
+assert_eq!(Some(&40), v.get(1));
+assert_eq!(Some(&[10, 40][..]), v.get(0..2));
+assert_eq!(None, v.get(3));
+assert_eq!(None, v.get(0..4));
Returns a reference to an element or subslice, without doing bounds +checking.
+For a safe alternative see get
.
Calling this method with an out-of-bounds index is undefined behavior +even if the resulting reference is not used.
+You can think of this like .get(index).unwrap_unchecked()
. It’s UB
+to call .get_unchecked(len)
, even if you immediately convert to a
+pointer. And it’s UB to call .get_unchecked(..len + 1)
,
+.get_unchecked(..=len)
, or similar.
let x = &[1, 2, 4];
+
+unsafe {
+ assert_eq!(x.get_unchecked(1), &2);
+}
Returns a mutable reference to an element or subslice, without doing +bounds checking.
+For a safe alternative see get_mut
.
Calling this method with an out-of-bounds index is undefined behavior +even if the resulting reference is not used.
+You can think of this like .get_mut(index).unwrap_unchecked()
. It’s
+UB to call .get_unchecked_mut(len)
, even if you immediately convert
+to a pointer. And it’s UB to call .get_unchecked_mut(..len + 1)
,
+.get_unchecked_mut(..=len)
, or similar.
let x = &mut [1, 2, 4];
+
+unsafe {
+ let elem = x.get_unchecked_mut(1);
+ *elem = 13;
+}
+assert_eq!(x, &[1, 13, 4]);
Returns a raw pointer to the slice’s buffer.
+The caller must ensure that the slice outlives the pointer this +function returns, or else it will end up dangling.
+The caller must also ensure that the memory the pointer (non-transitively) points to
+is never written to (except inside an UnsafeCell
) using this pointer or any pointer
+derived from it. If you need to mutate the contents of the slice, use as_mut_ptr
.
Modifying the container referenced by this slice may cause its buffer +to be reallocated, which would also make any pointers to it invalid.
+let x = &[1, 2, 4];
+let x_ptr = x.as_ptr();
+
+unsafe {
+ for i in 0..x.len() {
+ assert_eq!(x.get_unchecked(i), &*x_ptr.add(i));
+ }
+}
Returns an unsafe mutable pointer to the slice’s buffer.
+The caller must ensure that the slice outlives the pointer this +function returns, or else it will end up dangling.
+Modifying the container referenced by this slice may cause its buffer +to be reallocated, which would also make any pointers to it invalid.
+let x = &mut [1, 2, 4];
+let x_ptr = x.as_mut_ptr();
+
+unsafe {
+ for i in 0..x.len() {
+ *x_ptr.add(i) += 2;
+ }
+}
+assert_eq!(x, &[3, 4, 6]);
Returns the two raw pointers spanning the slice.
+The returned range is half-open, which means that the end pointer +points one past the last element of the slice. This way, an empty +slice is represented by two equal pointers, and the difference between +the two pointers represents the size of the slice.
+See as_ptr
for warnings on using these pointers. The end pointer
+requires extra caution, as it does not point to a valid element in the
+slice.
This function is useful for interacting with foreign interfaces which +use two pointers to refer to a range of elements in memory, as is +common in C++.
+It can also be useful to check if a pointer to an element refers to an +element of this slice:
+ +let a = [1, 2, 3];
+let x = &a[1] as *const _;
+let y = &5 as *const _;
+
+assert!(a.as_ptr_range().contains(&x));
+assert!(!a.as_ptr_range().contains(&y));
Returns the two unsafe mutable pointers spanning the slice.
+The returned range is half-open, which means that the end pointer +points one past the last element of the slice. This way, an empty +slice is represented by two equal pointers, and the difference between +the two pointers represents the size of the slice.
+See as_mut_ptr
for warnings on using these pointers. The end
+pointer requires extra caution, as it does not point to a valid element
+in the slice.
This function is useful for interacting with foreign interfaces which +use two pointers to refer to a range of elements in memory, as is +common in C++.
+Swaps two elements in the slice.
+If a
equals to b
, it’s guaranteed that elements won’t change value.
Panics if a
or b
are out of bounds.
let mut v = ["a", "b", "c", "d", "e"];
+v.swap(2, 4);
+assert!(v == ["a", "b", "e", "d", "c"]);
slice_swap_unchecked
)Swaps two elements in the slice, without doing bounds checking.
+For a safe alternative see swap
.
Calling this method with an out-of-bounds index is undefined behavior.
+The caller has to ensure that a < self.len()
and b < self.len()
.
#![feature(slice_swap_unchecked)]
+
+let mut v = ["a", "b", "c", "d"];
+// SAFETY: we know that 1 and 3 are both indices of the slice
+unsafe { v.swap_unchecked(1, 3) };
+assert!(v == ["a", "d", "c", "b"]);
Reverses the order of elements in the slice, in place.
+let mut v = [1, 2, 3];
+v.reverse();
+assert!(v == [3, 2, 1]);
Returns an iterator over the slice.
+The iterator yields all items from start to end.
+let x = &[1, 2, 4];
+let mut iterator = x.iter();
+
+assert_eq!(iterator.next(), Some(&1));
+assert_eq!(iterator.next(), Some(&2));
+assert_eq!(iterator.next(), Some(&4));
+assert_eq!(iterator.next(), None);
Returns an iterator that allows modifying each value.
+The iterator yields all items from start to end.
+let x = &mut [1, 2, 4];
+for elem in x.iter_mut() {
+ *elem += 2;
+}
+assert_eq!(x, &[3, 4, 6]);
Returns an iterator over all contiguous windows of length
+size
. The windows overlap. If the slice is shorter than
+size
, the iterator returns no values.
Panics if size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.windows(3);
+assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']);
+assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']);
+assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']);
+assert!(iter.next().is_none());
If the slice is shorter than size
:
let slice = ['f', 'o', 'o'];
+let mut iter = slice.windows(4);
+assert!(iter.next().is_none());
There’s no windows_mut
, as that existing would let safe code violate the
+“only one &mut
at a time to the same thing” rule. However, you can sometimes
+use Cell::as_slice_of_cells
in
+conjunction with windows
to accomplish something similar:
use std::cell::Cell;
+
+let mut array = ['R', 'u', 's', 't', ' ', '2', '0', '1', '5'];
+let slice = &mut array[..];
+let slice_of_cells: &[Cell<char>] = Cell::from_mut(slice).as_slice_of_cells();
+for w in slice_of_cells.windows(3) {
+ Cell::swap(&w[0], &w[2]);
+}
+assert_eq!(array, ['s', 't', ' ', '2', '0', '1', '5', 'u', 'R']);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide the length of the
+slice, then the last chunk will not have length chunk_size
.
See chunks_exact
for a variant of this iterator that returns chunks of always exactly
+chunk_size
elements, and rchunks
for the same iterator but starting at the end of the
+slice.
Panics if chunk_size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.chunks(2);
+assert_eq!(iter.next().unwrap(), &['l', 'o']);
+assert_eq!(iter.next().unwrap(), &['r', 'e']);
+assert_eq!(iter.next().unwrap(), &['m']);
+assert!(iter.next().is_none());
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are mutable slices, and do not overlap. If chunk_size
does not divide the
+length of the slice, then the last chunk will not have length chunk_size
.
See chunks_exact_mut
for a variant of this iterator that returns chunks of always
+exactly chunk_size
elements, and rchunks_mut
for the same iterator but starting at
+the end of the slice.
Panics if chunk_size
is 0.
let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.chunks_mut(2) {
+ for elem in chunk.iter_mut() {
+ *elem += count;
+ }
+ count += 1;
+}
+assert_eq!(v, &[1, 1, 2, 2, 3]);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide the length of the
+slice, then the last up to chunk_size-1
elements will be omitted and can be retrieved
+from the remainder
function of the iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can often optimize the
+resulting code better than in the case of chunks
.
See chunks
for a variant of this iterator that also returns the remainder as a smaller
+chunk, and rchunks_exact
for the same iterator but starting at the end of the slice.
Panics if chunk_size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.chunks_exact(2);
+assert_eq!(iter.next().unwrap(), &['l', 'o']);
+assert_eq!(iter.next().unwrap(), &['r', 'e']);
+assert!(iter.next().is_none());
+assert_eq!(iter.remainder(), &['m']);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are mutable slices, and do not overlap. If chunk_size
does not divide the
+length of the slice, then the last up to chunk_size-1
elements will be omitted and can be
+retrieved from the into_remainder
function of the iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can often optimize the
+resulting code better than in the case of chunks_mut
.
See chunks_mut
for a variant of this iterator that also returns the remainder as a
+smaller chunk, and rchunks_exact_mut
for the same iterator but starting at the end of
+the slice.
Panics if chunk_size
is 0.
let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.chunks_exact_mut(2) {
+ for elem in chunk.iter_mut() {
+ *elem += count;
+ }
+ count += 1;
+}
+assert_eq!(v, &[1, 1, 2, 2, 0]);
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+assuming that there’s no remainder.
This may only be called when
+N
-element chunks (aka self.len() % N == 0
).N != 0
.#![feature(slice_as_chunks)]
+let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
+let chunks: &[[char; 1]] =
+ // SAFETY: 1-element chunks never have remainder
+ unsafe { slice.as_chunks_unchecked() };
+assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
+let chunks: &[[char; 3]] =
+ // SAFETY: The slice length (6) is a multiple of 3
+ unsafe { slice.as_chunks_unchecked() };
+assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
+
+// These would be unsound:
+// let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5
+// let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+starting at the beginning of the slice,
+and a remainder slice with length strictly less than N
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(slice_as_chunks)]
+let slice = ['l', 'o', 'r', 'e', 'm'];
+let (chunks, remainder) = slice.as_chunks();
+assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
+assert_eq!(remainder, &['m']);
If you expect the slice to be an exact multiple, you can combine
+let
-else
with an empty slice pattern:
#![feature(slice_as_chunks)]
+let slice = ['R', 'u', 's', 't'];
+let (chunks, []) = slice.as_chunks::<2>() else {
+ panic!("slice didn't have even length")
+};
+assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+starting at the end of the slice,
+and a remainder slice with length strictly less than N
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(slice_as_chunks)]
+let slice = ['l', 'o', 'r', 'e', 'm'];
+let (remainder, chunks) = slice.as_rchunks();
+assert_eq!(remainder, &['l']);
+assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
array_chunks
)Returns an iterator over N
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are array references and do not overlap. If N
does not divide the
+length of the slice, then the last up to N-1
elements will be omitted and can be
+retrieved from the remainder
function of the iterator.
This method is the const generic equivalent of chunks_exact
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(array_chunks)]
+let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.array_chunks();
+assert_eq!(iter.next().unwrap(), &['l', 'o']);
+assert_eq!(iter.next().unwrap(), &['r', 'e']);
+assert!(iter.next().is_none());
+assert_eq!(iter.remainder(), &['m']);
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+assuming that there’s no remainder.
This may only be called when
+N
-element chunks (aka self.len() % N == 0
).N != 0
.#![feature(slice_as_chunks)]
+let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
+let chunks: &mut [[char; 1]] =
+ // SAFETY: 1-element chunks never have remainder
+ unsafe { slice.as_chunks_unchecked_mut() };
+chunks[0] = ['L'];
+assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]);
+let chunks: &mut [[char; 3]] =
+ // SAFETY: The slice length (6) is a multiple of 3
+ unsafe { slice.as_chunks_unchecked_mut() };
+chunks[1] = ['a', 'x', '?'];
+assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']);
+
+// These would be unsound:
+// let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut() // The slice length is not a multiple of 5
+// let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+starting at the beginning of the slice,
+and a remainder slice with length strictly less than N
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(slice_as_chunks)]
+let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+let (chunks, remainder) = v.as_chunks_mut();
+remainder[0] = 9;
+for chunk in chunks {
+ *chunk = [count; 2];
+ count += 1;
+}
+assert_eq!(v, &[1, 1, 2, 2, 9]);
slice_as_chunks
)Splits the slice into a slice of N
-element arrays,
+starting at the end of the slice,
+and a remainder slice with length strictly less than N
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(slice_as_chunks)]
+let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+let (remainder, chunks) = v.as_rchunks_mut();
+remainder[0] = 9;
+for chunk in chunks {
+ *chunk = [count; 2];
+ count += 1;
+}
+assert_eq!(v, &[9, 1, 1, 2, 2]);
array_chunks
)Returns an iterator over N
elements of the slice at a time, starting at the
+beginning of the slice.
The chunks are mutable array references and do not overlap. If N
does not divide
+the length of the slice, then the last up to N-1
elements will be omitted and
+can be retrieved from the into_remainder
function of the iterator.
This method is the const generic equivalent of chunks_exact_mut
.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(array_chunks)]
+let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.array_chunks_mut() {
+ *chunk = [count; 2];
+ count += 1;
+}
+assert_eq!(v, &[1, 1, 2, 2, 0]);
array_windows
)Returns an iterator over overlapping windows of N
elements of a slice,
+starting at the beginning of the slice.
This is the const generic equivalent of windows
.
If N
is greater than the size of the slice, it will return no windows.
Panics if N
is 0. This check will most probably get changed to a compile time
+error before this method gets stabilized.
#![feature(array_windows)]
+let slice = [0, 1, 2, 3];
+let mut iter = slice.array_windows();
+assert_eq!(iter.next().unwrap(), &[0, 1]);
+assert_eq!(iter.next().unwrap(), &[1, 2]);
+assert_eq!(iter.next().unwrap(), &[2, 3]);
+assert!(iter.next().is_none());
Returns an iterator over chunk_size
elements of the slice at a time, starting at the end
+of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide the length of the
+slice, then the last chunk will not have length chunk_size
.
See rchunks_exact
for a variant of this iterator that returns chunks of always exactly
+chunk_size
elements, and chunks
for the same iterator but starting at the beginning
+of the slice.
Panics if chunk_size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.rchunks(2);
+assert_eq!(iter.next().unwrap(), &['e', 'm']);
+assert_eq!(iter.next().unwrap(), &['o', 'r']);
+assert_eq!(iter.next().unwrap(), &['l']);
+assert!(iter.next().is_none());
Returns an iterator over chunk_size
elements of the slice at a time, starting at the end
+of the slice.
The chunks are mutable slices, and do not overlap. If chunk_size
does not divide the
+length of the slice, then the last chunk will not have length chunk_size
.
See rchunks_exact_mut
for a variant of this iterator that returns chunks of always
+exactly chunk_size
elements, and chunks_mut
for the same iterator but starting at the
+beginning of the slice.
Panics if chunk_size
is 0.
let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.rchunks_mut(2) {
+ for elem in chunk.iter_mut() {
+ *elem += count;
+ }
+ count += 1;
+}
+assert_eq!(v, &[3, 2, 2, 1, 1]);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the
+end of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide the length of the
+slice, then the last up to chunk_size-1
elements will be omitted and can be retrieved
+from the remainder
function of the iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can often optimize the
+resulting code better than in the case of rchunks
.
See rchunks
for a variant of this iterator that also returns the remainder as a smaller
+chunk, and chunks_exact
for the same iterator but starting at the beginning of the
+slice.
Panics if chunk_size
is 0.
let slice = ['l', 'o', 'r', 'e', 'm'];
+let mut iter = slice.rchunks_exact(2);
+assert_eq!(iter.next().unwrap(), &['e', 'm']);
+assert_eq!(iter.next().unwrap(), &['o', 'r']);
+assert!(iter.next().is_none());
+assert_eq!(iter.remainder(), &['l']);
Returns an iterator over chunk_size
elements of the slice at a time, starting at the end
+of the slice.
The chunks are mutable slices, and do not overlap. If chunk_size
does not divide the
+length of the slice, then the last up to chunk_size-1
elements will be omitted and can be
+retrieved from the into_remainder
function of the iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can often optimize the
+resulting code better than in the case of chunks_mut
.
See rchunks_mut
for a variant of this iterator that also returns the remainder as a
+smaller chunk, and chunks_exact_mut
for the same iterator but starting at the beginning
+of the slice.
Panics if chunk_size
is 0.
let v = &mut [0, 0, 0, 0, 0];
+let mut count = 1;
+
+for chunk in v.rchunks_exact_mut(2) {
+ for elem in chunk.iter_mut() {
+ *elem += count;
+ }
+ count += 1;
+}
+assert_eq!(v, &[0, 2, 2, 1, 1]);
Returns an iterator over the slice producing non-overlapping runs +of elements using the predicate to separate them.
+The predicate is called for every pair of consecutive elements,
+meaning that it is called on slice[0]
and slice[1]
,
+followed by slice[1]
and slice[2]
, and so on.
let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
+
+let mut iter = slice.chunk_by(|a, b| a == b);
+
+assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
+assert_eq!(iter.next(), Some(&[3, 3][..]));
+assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
+assert_eq!(iter.next(), None);
This method can be used to extract the sorted subslices:
+ +let slice = &[1, 1, 2, 3, 2, 3, 2, 3, 4];
+
+let mut iter = slice.chunk_by(|a, b| a <= b);
+
+assert_eq!(iter.next(), Some(&[1, 1, 2, 3][..]));
+assert_eq!(iter.next(), Some(&[2, 3][..]));
+assert_eq!(iter.next(), Some(&[2, 3, 4][..]));
+assert_eq!(iter.next(), None);
Returns an iterator over the slice producing non-overlapping mutable +runs of elements using the predicate to separate them.
+The predicate is called for every pair of consecutive elements,
+meaning that it is called on slice[0]
and slice[1]
,
+followed by slice[1]
and slice[2]
, and so on.
let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2];
+
+let mut iter = slice.chunk_by_mut(|a, b| a == b);
+
+assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
+assert_eq!(iter.next(), Some(&mut [3, 3][..]));
+assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
+assert_eq!(iter.next(), None);
This method can be used to extract the sorted subslices:
+ +let slice = &mut [1, 1, 2, 3, 2, 3, 2, 3, 4];
+
+let mut iter = slice.chunk_by_mut(|a, b| a <= b);
+
+assert_eq!(iter.next(), Some(&mut [1, 1, 2, 3][..]));
+assert_eq!(iter.next(), Some(&mut [2, 3][..]));
+assert_eq!(iter.next(), Some(&mut [2, 3, 4][..]));
+assert_eq!(iter.next(), None);
Divides one slice into two at an index.
+The first will contain all indices from [0, mid)
(excluding
+the index mid
itself) and the second will contain all
+indices from [mid, len)
(excluding the index len
itself).
Panics if mid > len
. For a non-panicking alternative see
+split_at_checked
.
let v = [1, 2, 3, 4, 5, 6];
+
+{
+ let (left, right) = v.split_at(0);
+ assert_eq!(left, []);
+ assert_eq!(right, [1, 2, 3, 4, 5, 6]);
+}
+
+{
+ let (left, right) = v.split_at(2);
+ assert_eq!(left, [1, 2]);
+ assert_eq!(right, [3, 4, 5, 6]);
+}
+
+{
+ let (left, right) = v.split_at(6);
+ assert_eq!(left, [1, 2, 3, 4, 5, 6]);
+ assert_eq!(right, []);
+}
Divides one mutable slice into two at an index.
+The first will contain all indices from [0, mid)
(excluding
+the index mid
itself) and the second will contain all
+indices from [mid, len)
(excluding the index len
itself).
Panics if mid > len
. For a non-panicking alternative see
+split_at_mut_checked
.
let mut v = [1, 0, 3, 0, 5, 6];
+let (left, right) = v.split_at_mut(2);
+assert_eq!(left, [1, 0]);
+assert_eq!(right, [3, 0, 5, 6]);
+left[1] = 2;
+right[1] = 4;
+assert_eq!(v, [1, 2, 3, 4, 5, 6]);
Divides one slice into two at an index, without doing bounds checking.
+The first will contain all indices from [0, mid)
(excluding
+the index mid
itself) and the second will contain all
+indices from [mid, len)
(excluding the index len
itself).
For a safe alternative see split_at
.
Calling this method with an out-of-bounds index is undefined behavior
+even if the resulting reference is not used. The caller has to ensure that
+0 <= mid <= self.len()
.
let v = [1, 2, 3, 4, 5, 6];
+
+unsafe {
+ let (left, right) = v.split_at_unchecked(0);
+ assert_eq!(left, []);
+ assert_eq!(right, [1, 2, 3, 4, 5, 6]);
+}
+
+unsafe {
+ let (left, right) = v.split_at_unchecked(2);
+ assert_eq!(left, [1, 2]);
+ assert_eq!(right, [3, 4, 5, 6]);
+}
+
+unsafe {
+ let (left, right) = v.split_at_unchecked(6);
+ assert_eq!(left, [1, 2, 3, 4, 5, 6]);
+ assert_eq!(right, []);
+}
Divides one mutable slice into two at an index, without doing bounds checking.
+The first will contain all indices from [0, mid)
(excluding
+the index mid
itself) and the second will contain all
+indices from [mid, len)
(excluding the index len
itself).
For a safe alternative see split_at_mut
.
Calling this method with an out-of-bounds index is undefined behavior
+even if the resulting reference is not used. The caller has to ensure that
+0 <= mid <= self.len()
.
let mut v = [1, 0, 3, 0, 5, 6];
+// scoped to restrict the lifetime of the borrows
+unsafe {
+ let (left, right) = v.split_at_mut_unchecked(2);
+ assert_eq!(left, [1, 0]);
+ assert_eq!(right, [3, 0, 5, 6]);
+ left[1] = 2;
+ right[1] = 4;
+}
+assert_eq!(v, [1, 2, 3, 4, 5, 6]);
Divides one slice into two at an index, returning None
if the slice is
+too short.
If mid ≤ len
returns a pair of slices where the first will contain all
+indices from [0, mid)
(excluding the index mid
itself) and the
+second will contain all indices from [mid, len)
(excluding the index
+len
itself).
Otherwise, if mid > len
, returns None
.
let v = [1, -2, 3, -4, 5, -6];
+
+{
+ let (left, right) = v.split_at_checked(0).unwrap();
+ assert_eq!(left, []);
+ assert_eq!(right, [1, -2, 3, -4, 5, -6]);
+}
+
+{
+ let (left, right) = v.split_at_checked(2).unwrap();
+ assert_eq!(left, [1, -2]);
+ assert_eq!(right, [3, -4, 5, -6]);
+}
+
+{
+ let (left, right) = v.split_at_checked(6).unwrap();
+ assert_eq!(left, [1, -2, 3, -4, 5, -6]);
+ assert_eq!(right, []);
+}
+
+assert_eq!(None, v.split_at_checked(7));
Divides one mutable slice into two at an index, returning None
if the
+slice is too short.
If mid ≤ len
returns a pair of slices where the first will contain all
+indices from [0, mid)
(excluding the index mid
itself) and the
+second will contain all indices from [mid, len)
(excluding the index
+len
itself).
Otherwise, if mid > len
, returns None
.
let mut v = [1, 0, 3, 0, 5, 6];
+
+if let Some((left, right)) = v.split_at_mut_checked(2) {
+ assert_eq!(left, [1, 0]);
+ assert_eq!(right, [3, 0, 5, 6]);
+ left[1] = 2;
+ right[1] = 4;
+}
+assert_eq!(v, [1, 2, 3, 4, 5, 6]);
+
+assert_eq!(None, v.split_at_mut_checked(7));
Returns an iterator over subslices separated by elements that match
+pred
. The matched element is not contained in the subslices.
let slice = [10, 40, 33, 20];
+let mut iter = slice.split(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[10, 40]);
+assert_eq!(iter.next().unwrap(), &[20]);
+assert!(iter.next().is_none());
If the first element is matched, an empty slice will be the first item +returned by the iterator. Similarly, if the last element in the slice +is matched, an empty slice will be the last item returned by the +iterator:
+ +let slice = [10, 40, 33];
+let mut iter = slice.split(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[10, 40]);
+assert_eq!(iter.next().unwrap(), &[]);
+assert!(iter.next().is_none());
If two matched elements are directly adjacent, an empty slice will be +present between them:
+ +let slice = [10, 6, 33, 20];
+let mut iter = slice.split(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[10]);
+assert_eq!(iter.next().unwrap(), &[]);
+assert_eq!(iter.next().unwrap(), &[20]);
+assert!(iter.next().is_none());
Returns an iterator over mutable subslices separated by elements that
+match pred
. The matched element is not contained in the subslices.
let mut v = [10, 40, 30, 20, 60, 50];
+
+for group in v.split_mut(|num| *num % 3 == 0) {
+ group[0] = 1;
+}
+assert_eq!(v, [1, 40, 30, 1, 60, 1]);
Returns an iterator over subslices separated by elements that match
+pred
. The matched element is contained in the end of the previous
+subslice as a terminator.
let slice = [10, 40, 33, 20];
+let mut iter = slice.split_inclusive(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
+assert_eq!(iter.next().unwrap(), &[20]);
+assert!(iter.next().is_none());
If the last element of the slice is matched, +that element will be considered the terminator of the preceding slice. +That slice will be the last item returned by the iterator.
+ +let slice = [3, 10, 40, 33];
+let mut iter = slice.split_inclusive(|num| num % 3 == 0);
+
+assert_eq!(iter.next().unwrap(), &[3]);
+assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
+assert!(iter.next().is_none());
Returns an iterator over mutable subslices separated by elements that
+match pred
. The matched element is contained in the previous
+subslice as a terminator.
let mut v = [10, 40, 30, 20, 60, 50];
+
+for group in v.split_inclusive_mut(|num| *num % 3 == 0) {
+ let terminator_idx = group.len()-1;
+ group[terminator_idx] = 1;
+}
+assert_eq!(v, [10, 40, 1, 20, 1, 1]);
Returns an iterator over subslices separated by elements that match
+pred
, starting at the end of the slice and working backwards.
+The matched element is not contained in the subslices.
let slice = [11, 22, 33, 0, 44, 55];
+let mut iter = slice.rsplit(|num| *num == 0);
+
+assert_eq!(iter.next().unwrap(), &[44, 55]);
+assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
+assert_eq!(iter.next(), None);
As with split()
, if the first or last element is matched, an empty
+slice will be the first (or last) item returned by the iterator.
let v = &[0, 1, 1, 2, 3, 5, 8];
+let mut it = v.rsplit(|n| *n % 2 == 0);
+assert_eq!(it.next().unwrap(), &[]);
+assert_eq!(it.next().unwrap(), &[3, 5]);
+assert_eq!(it.next().unwrap(), &[1, 1]);
+assert_eq!(it.next().unwrap(), &[]);
+assert_eq!(it.next(), None);
Returns an iterator over mutable subslices separated by elements that
+match pred
, starting at the end of the slice and working
+backwards. The matched element is not contained in the subslices.
let mut v = [100, 400, 300, 200, 600, 500];
+
+let mut count = 0;
+for group in v.rsplit_mut(|num| *num % 3 == 0) {
+ count += 1;
+ group[0] = count;
+}
+assert_eq!(v, [3, 400, 300, 2, 600, 1]);
Returns an iterator over subslices separated by elements that match
+pred
, limited to returning at most n
items. The matched element is
+not contained in the subslices.
The last element returned, if any, will contain the remainder of the +slice.
+Print the slice split once by numbers divisible by 3 (i.e., [10, 40]
,
+[20, 60, 50]
):
let v = [10, 40, 30, 20, 60, 50];
+
+for group in v.splitn(2, |num| *num % 3 == 0) {
+ println!("{group:?}");
+}
Returns an iterator over mutable subslices separated by elements that match
+pred
, limited to returning at most n
items. The matched element is
+not contained in the subslices.
The last element returned, if any, will contain the remainder of the +slice.
+let mut v = [10, 40, 30, 20, 60, 50];
+
+for group in v.splitn_mut(2, |num| *num % 3 == 0) {
+ group[0] = 1;
+}
+assert_eq!(v, [1, 40, 30, 1, 60, 50]);
Returns an iterator over subslices separated by elements that match
+pred
limited to returning at most n
items. This starts at the end of
+the slice and works backwards. The matched element is not contained in
+the subslices.
The last element returned, if any, will contain the remainder of the +slice.
+Print the slice split once, starting from the end, by numbers divisible
+by 3 (i.e., [50]
, [10, 40, 30, 20]
):
let v = [10, 40, 30, 20, 60, 50];
+
+for group in v.rsplitn(2, |num| *num % 3 == 0) {
+ println!("{group:?}");
+}
Returns an iterator over subslices separated by elements that match
+pred
limited to returning at most n
items. This starts at the end of
+the slice and works backwards. The matched element is not contained in
+the subslices.
The last element returned, if any, will contain the remainder of the +slice.
+let mut s = [10, 40, 30, 20, 60, 50];
+
+for group in s.rsplitn_mut(2, |num| *num % 3 == 0) {
+ group[0] = 1;
+}
+assert_eq!(s, [1, 40, 30, 20, 60, 1]);
slice_split_once
)Splits the slice on the first element that matches the specified +predicate.
+If any matching elements are present in the slice, returns the prefix
+before the match and suffix after. The matching element itself is not
+included. If no elements match, returns None
.
#![feature(slice_split_once)]
+let s = [1, 2, 3, 2, 4];
+assert_eq!(s.split_once(|&x| x == 2), Some((
+ &[1][..],
+ &[3, 2, 4][..]
+)));
+assert_eq!(s.split_once(|&x| x == 0), None);
slice_split_once
)Splits the slice on the last element that matches the specified +predicate.
+If any matching elements are present in the slice, returns the prefix
+before the match and suffix after. The matching element itself is not
+included. If no elements match, returns None
.
#![feature(slice_split_once)]
+let s = [1, 2, 3, 2, 4];
+assert_eq!(s.rsplit_once(|&x| x == 2), Some((
+ &[1, 2, 3][..],
+ &[4][..]
+)));
+assert_eq!(s.rsplit_once(|&x| x == 0), None);
Returns true
if the slice contains an element with the given value.
This operation is O(n).
+Note that if you have a sorted slice, binary_search
may be faster.
let v = [10, 40, 30];
+assert!(v.contains(&30));
+assert!(!v.contains(&50));
If you do not have a &T
, but some other value that you can compare
+with one (for example, String
implements PartialEq<str>
), you can
+use iter().any
:
let v = [String::from("hello"), String::from("world")]; // slice of `String`
+assert!(v.iter().any(|e| e == "hello")); // search with `&str`
+assert!(!v.iter().any(|e| e == "hi"));
Returns true
if needle
is a prefix of the slice or equal to the slice.
let v = [10, 40, 30];
+assert!(v.starts_with(&[10]));
+assert!(v.starts_with(&[10, 40]));
+assert!(v.starts_with(&v));
+assert!(!v.starts_with(&[50]));
+assert!(!v.starts_with(&[10, 50]));
Always returns true
if needle
is an empty slice:
let v = &[10, 40, 30];
+assert!(v.starts_with(&[]));
+let v: &[u8] = &[];
+assert!(v.starts_with(&[]));
Returns true
if needle
is a suffix of the slice or equal to the slice.
let v = [10, 40, 30];
+assert!(v.ends_with(&[30]));
+assert!(v.ends_with(&[40, 30]));
+assert!(v.ends_with(&v));
+assert!(!v.ends_with(&[50]));
+assert!(!v.ends_with(&[50, 30]));
Always returns true
if needle
is an empty slice:
let v = &[10, 40, 30];
+assert!(v.ends_with(&[]));
+let v: &[u8] = &[];
+assert!(v.ends_with(&[]));
Returns a subslice with the prefix removed.
+If the slice starts with prefix
, returns the subslice after the prefix, wrapped in Some
.
+If prefix
is empty, simply returns the original slice. If prefix
is equal to the
+original slice, returns an empty slice.
If the slice does not start with prefix
, returns None
.
let v = &[10, 40, 30];
+assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..]));
+assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..]));
+assert_eq!(v.strip_prefix(&[10, 40, 30]), Some(&[][..]));
+assert_eq!(v.strip_prefix(&[50]), None);
+assert_eq!(v.strip_prefix(&[10, 50]), None);
+
+let prefix : &str = "he";
+assert_eq!(b"hello".strip_prefix(prefix.as_bytes()),
+ Some(b"llo".as_ref()));
Returns a subslice with the suffix removed.
+If the slice ends with suffix
, returns the subslice before the suffix, wrapped in Some
.
+If suffix
is empty, simply returns the original slice. If suffix
is equal to the
+original slice, returns an empty slice.
If the slice does not end with suffix
, returns None
.
let v = &[10, 40, 30];
+assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
+assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
+assert_eq!(v.strip_suffix(&[10, 40, 30]), Some(&[][..]));
+assert_eq!(v.strip_suffix(&[50]), None);
+assert_eq!(v.strip_suffix(&[50, 30]), None);
Binary searches this slice for a given element. +If the slice is not sorted, the returned result is unspecified and +meaningless.
+If the value is found then Result::Ok
is returned, containing the
+index of the matching element. If there are multiple matches, then any
+one of the matches could be returned. The index is chosen
+deterministically, but is subject to change in future versions of Rust.
+If the value is not found then Result::Err
is returned, containing
+the index where a matching element could be inserted while maintaining
+sorted order.
See also binary_search_by
, binary_search_by_key
, and partition_point
.
Looks up a series of four elements. The first is found, with a
+uniquely determined position; the second and third are not
+found; the fourth could match any position in [1, 4]
.
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+
+assert_eq!(s.binary_search(&13), Ok(9));
+assert_eq!(s.binary_search(&4), Err(7));
+assert_eq!(s.binary_search(&100), Err(13));
+let r = s.binary_search(&1);
+assert!(match r { Ok(1..=4) => true, _ => false, });
If you want to find that whole range of matching items, rather than
+an arbitrary matching one, that can be done using partition_point
:
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+
+let low = s.partition_point(|x| x < &1);
+assert_eq!(low, 1);
+let high = s.partition_point(|x| x <= &1);
+assert_eq!(high, 5);
+let r = s.binary_search(&1);
+assert!((low..high).contains(&r.unwrap()));
+
+assert!(s[..low].iter().all(|&x| x < 1));
+assert!(s[low..high].iter().all(|&x| x == 1));
+assert!(s[high..].iter().all(|&x| x > 1));
+
+// For something not found, the "range" of equal items is empty
+assert_eq!(s.partition_point(|x| x < &11), 9);
+assert_eq!(s.partition_point(|x| x <= &11), 9);
+assert_eq!(s.binary_search(&11), Err(9));
If you want to insert an item to a sorted vector, while maintaining
+sort order, consider using partition_point
:
let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+let num = 42;
+let idx = s.partition_point(|&x| x <= num);
+// If `num` is unique, `s.partition_point(|&x| x < num)` (with `<`) is equivalent to
+// `s.binary_search(&num).unwrap_or_else(|x| x)`, but using `<=` will allow `insert`
+// to shift less elements.
+s.insert(idx, num);
+assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
Binary searches this slice with a comparator function.
+The comparator function should return an order code that indicates
+whether its argument is Less
, Equal
or Greater
the desired
+target.
+If the slice is not sorted or if the comparator function does not
+implement an order consistent with the sort order of the underlying
+slice, the returned result is unspecified and meaningless.
If the value is found then Result::Ok
is returned, containing the
+index of the matching element. If there are multiple matches, then any
+one of the matches could be returned. The index is chosen
+deterministically, but is subject to change in future versions of Rust.
+If the value is not found then Result::Err
is returned, containing
+the index where a matching element could be inserted while maintaining
+sorted order.
See also binary_search
, binary_search_by_key
, and partition_point
.
Looks up a series of four elements. The first is found, with a
+uniquely determined position; the second and third are not
+found; the fourth could match any position in [1, 4]
.
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+
+let seek = 13;
+assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
+let seek = 4;
+assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
+let seek = 100;
+assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
+let seek = 1;
+let r = s.binary_search_by(|probe| probe.cmp(&seek));
+assert!(match r { Ok(1..=4) => true, _ => false, });
Binary searches this slice with a key extraction function.
+Assumes that the slice is sorted by the key, for instance with
+sort_by_key
using the same key extraction function.
+If the slice is not sorted by the key, the returned result is
+unspecified and meaningless.
If the value is found then Result::Ok
is returned, containing the
+index of the matching element. If there are multiple matches, then any
+one of the matches could be returned. The index is chosen
+deterministically, but is subject to change in future versions of Rust.
+If the value is not found then Result::Err
is returned, containing
+the index where a matching element could be inserted while maintaining
+sorted order.
See also binary_search
, binary_search_by
, and partition_point
.
Looks up a series of four elements in a slice of pairs sorted by
+their second elements. The first is found, with a uniquely
+determined position; the second and third are not found; the
+fourth could match any position in [1, 4]
.
let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
+ (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
+ (1, 21), (2, 34), (4, 55)];
+
+assert_eq!(s.binary_search_by_key(&13, |&(a, b)| b), Ok(9));
+assert_eq!(s.binary_search_by_key(&4, |&(a, b)| b), Err(7));
+assert_eq!(s.binary_search_by_key(&100, |&(a, b)| b), Err(13));
+let r = s.binary_search_by_key(&1, |&(a, b)| b);
+assert!(match r { Ok(1..=4) => true, _ => false, });
Sorts the slice without preserving the initial order of equal elements.
+This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not +allocate), and O(n * log(n)) worst-case.
+If the implementation of Ord
for T
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for T
panics.
Sorting types that only implement PartialOrd
such as f32
and f64
require
+additional precautions. For example, f32::NAN != f32::NAN
, which doesn’t fulfill the
+reflexivity requirement of Ord
. By using an alternative comparison function with
+slice::sort_unstable_by
such as f32::total_cmp
or f64::total_cmp
that defines a
+total order users can sort slices containing floating-point values. Alternatively, if all
+values in the slice are guaranteed to be in a subset for which PartialOrd::partial_cmp
+forms a total order, it’s possible to sort the slice with sort_unstable_by(|a, b| a.partial_cmp(b).unwrap())
.
The current implementation is based on ipnsort by Lukas Bergdoll and Orson Peters, which +combines the fast average case of quicksort with the fast worst case of heapsort, achieving +linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the +expected time to sort the data is O(n * log(k)).
+It is typically faster than stable sorting, except in a few special cases, e.g., when the +slice is partially sorted.
+May panic if the implementation of Ord
for T
does not implement a total order.
let mut v = [4, -5, 1, -3, 2];
+
+v.sort_unstable();
+assert_eq!(v, [-5, -3, 1, 2, 4]);
Sorts the slice with a comparison function, without preserving the initial order of +equal elements.
+This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not +allocate), and O(n * log(n)) worst-case.
+If the comparison function compare
does not implement a total order the resulting order
+of elements in the slice is unspecified. All original elements will remain in the slice and
+any possible modifications via interior mutability are observed in the input. Same is true
+if compare
panics.
For example |a, b| (a - b).cmp(a)
is a comparison function that is neither transitive nor
+reflexive nor total, a < b < c < a
with a = 1, b = 2, c = 3
. For more information and
+examples see the Ord
documentation.
The current implementation is based on ipnsort by Lukas Bergdoll and Orson Peters, which +combines the fast average case of quicksort with the fast worst case of heapsort, achieving +linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the +expected time to sort the data is O(n * log(k)).
+It is typically faster than stable sorting, except in a few special cases, e.g., when the +slice is partially sorted.
+May panic if compare
does not implement a total order.
let mut v = [4, -5, 1, -3, 2];
+v.sort_unstable_by(|a, b| a.cmp(b));
+assert_eq!(v, [-5, -3, 1, 2, 4]);
+
+// reverse sorting
+v.sort_unstable_by(|a, b| b.cmp(a));
+assert_eq!(v, [4, 2, 1, -3, -5]);
Sorts the slice with a key extraction function, without preserving the initial order of +equal elements.
+This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not +allocate), and O(n * log(n)) worst-case.
+If the implementation of Ord
for K
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for K
panics.
The current implementation is based on ipnsort by Lukas Bergdoll and Orson Peters, which +combines the fast average case of quicksort with the fast worst case of heapsort, achieving +linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the +expected time to sort the data is O(n * log(k)).
+It is typically faster than stable sorting, except in a few special cases, e.g., when the +slice is partially sorted.
+May panic if the implementation of Ord
for K
does not implement a total order.
let mut v = [4i32, -5, 1, -3, 2];
+
+v.sort_unstable_by_key(|k| k.abs());
+assert_eq!(v, [1, 2, -3, 4, -5]);
Reorders the slice such that the element at index
after the reordering is at its final
+sorted position.
This reordering has the additional property that any value at position i < index
will be
+less than or equal to any value at a position j > index
. Additionally, this reordering is
+unstable (i.e. any number of equal elements may end up at position index
), in-place (i.e.
+does not allocate), and runs in O(n) time. This function is also known as “kth element”
+in other libraries.
It returns a triplet of the following from the reordered slice: the subslice prior to
+index
, the element at index
, and the subslice after index
; accordingly, the values in
+those two subslices will respectively all be less-than-or-equal-to and
+greater-than-or-equal-to the value of the element at index
.
The current algorithm is an introselect implementation based on ipnsort by Lukas Bergdoll
+and Orson Peters, which is also the basis for sort_unstable
. The fallback algorithm is
+Median of Medians using Tukey’s Ninther for pivot selection, which guarantees linear runtime
+for all inputs.
Panics when index >= len()
, meaning it always panics on empty slices.
May panic if the implementation of Ord
for T
does not implement a total order.
let mut v = [-5i32, 4, 2, -3, 1];
+
+// Find the items less than or equal to the median, the median, and greater than or equal to
+// the median.
+let (lesser, median, greater) = v.select_nth_unstable(2);
+
+assert!(lesser == [-3, -5] || lesser == [-5, -3]);
+assert_eq!(median, &mut 1);
+assert!(greater == [4, 2] || greater == [2, 4]);
+
+// We are only guaranteed the slice will be one of the following, based on the way we sort
+// about the specified index.
+assert!(v == [-3, -5, 1, 2, 4] ||
+ v == [-5, -3, 1, 2, 4] ||
+ v == [-3, -5, 1, 4, 2] ||
+ v == [-5, -3, 1, 4, 2]);
Reorders the slice with a comparator function such that the element at index
after the
+reordering is at its final sorted position.
This reordering has the additional property that any value at position i < index
will be
+less than or equal to any value at a position j > index
using the comparator function.
+Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
+position index
), in-place (i.e. does not allocate), and runs in O(n) time. This
+function is also known as “kth element” in other libraries.
It returns a triplet of the following from the slice reordered according to the provided
+comparator function: the subslice prior to index
, the element at index
, and the subslice
+after index
; accordingly, the values in those two subslices will respectively all be
+less-than-or-equal-to and greater-than-or-equal-to the value of the element at index
.
The current algorithm is an introselect implementation based on ipnsort by Lukas Bergdoll
+and Orson Peters, which is also the basis for sort_unstable
. The fallback algorithm is
+Median of Medians using Tukey’s Ninther for pivot selection, which guarantees linear runtime
+for all inputs.
Panics when index >= len()
, meaning it always panics on empty slices.
May panic if compare
does not implement a total order.
let mut v = [-5i32, 4, 2, -3, 1];
+
+// Find the items less than or equal to the median, the median, and greater than or equal to
+// the median as if the slice were sorted in descending order.
+let (lesser, median, greater) = v.select_nth_unstable_by(2, |a, b| b.cmp(a));
+
+assert!(lesser == [4, 2] || lesser == [2, 4]);
+assert_eq!(median, &mut 1);
+assert!(greater == [-3, -5] || greater == [-5, -3]);
+
+// We are only guaranteed the slice will be one of the following, based on the way we sort
+// about the specified index.
+assert!(v == [2, 4, 1, -5, -3] ||
+ v == [2, 4, 1, -3, -5] ||
+ v == [4, 2, 1, -5, -3] ||
+ v == [4, 2, 1, -3, -5]);
Reorders the slice with a key extraction function such that the element at index
after the
+reordering is at its final sorted position.
This reordering has the additional property that any value at position i < index
will be
+less than or equal to any value at a position j > index
using the key extraction function.
+Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
+position index
), in-place (i.e. does not allocate), and runs in O(n) time. This
+function is also known as “kth element” in other libraries.
It returns a triplet of the following from the slice reordered according to the provided key
+extraction function: the subslice prior to index
, the element at index
, and the subslice
+after index
; accordingly, the values in those two subslices will respectively all be
+less-than-or-equal-to and greater-than-or-equal-to the value of the element at index
.
The current algorithm is an introselect implementation based on ipnsort by Lukas Bergdoll
+and Orson Peters, which is also the basis for sort_unstable
. The fallback algorithm is
+Median of Medians using Tukey’s Ninther for pivot selection, which guarantees linear runtime
+for all inputs.
Panics when index >= len()
, meaning it always panics on empty slices.
May panic if K: Ord
does not implement a total order.
let mut v = [-5i32, 4, 1, -3, 2];
+
+// Find the items less than or equal to the median, the median, and greater than or equal to
+// the median as if the slice were sorted according to absolute value.
+let (lesser, median, greater) = v.select_nth_unstable_by_key(2, |a| a.abs());
+
+assert!(lesser == [1, 2] || lesser == [2, 1]);
+assert_eq!(median, &mut -3);
+assert!(greater == [4, -5] || greater == [-5, 4]);
+
+// We are only guaranteed the slice will be one of the following, based on the way we sort
+// about the specified index.
+assert!(v == [1, 2, -3, 4, -5] ||
+ v == [1, 2, -3, -5, 4] ||
+ v == [2, 1, -3, 4, -5] ||
+ v == [2, 1, -3, -5, 4]);
slice_partition_dedup
)Moves all consecutive repeated elements to the end of the slice according to the
+PartialEq
trait implementation.
Returns two slices. The first contains no consecutive repeated elements. +The second contains all the duplicates in no specified order.
+If the slice is sorted, the first returned slice contains no duplicates.
+#![feature(slice_partition_dedup)]
+
+let mut slice = [1, 2, 2, 3, 3, 2, 1, 1];
+
+let (dedup, duplicates) = slice.partition_dedup();
+
+assert_eq!(dedup, [1, 2, 3, 2, 1]);
+assert_eq!(duplicates, [2, 3, 1]);
slice_partition_dedup
)Moves all but the first of consecutive elements to the end of the slice satisfying +a given equality relation.
+Returns two slices. The first contains no consecutive repeated elements. +The second contains all the duplicates in no specified order.
+The same_bucket
function is passed references to two elements from the slice and
+must determine if the elements compare equal. The elements are passed in opposite order
+from their order in the slice, so if same_bucket(a, b)
returns true
, a
is moved
+at the end of the slice.
If the slice is sorted, the first returned slice contains no duplicates.
+#![feature(slice_partition_dedup)]
+
+let mut slice = ["foo", "Foo", "BAZ", "Bar", "bar", "baz", "BAZ"];
+
+let (dedup, duplicates) = slice.partition_dedup_by(|a, b| a.eq_ignore_ascii_case(b));
+
+assert_eq!(dedup, ["foo", "BAZ", "Bar", "baz"]);
+assert_eq!(duplicates, ["bar", "Foo", "BAZ"]);
slice_partition_dedup
)Moves all but the first of consecutive elements to the end of the slice that resolve +to the same key.
+Returns two slices. The first contains no consecutive repeated elements. +The second contains all the duplicates in no specified order.
+If the slice is sorted, the first returned slice contains no duplicates.
+#![feature(slice_partition_dedup)]
+
+let mut slice = [10, 20, 21, 30, 30, 20, 11, 13];
+
+let (dedup, duplicates) = slice.partition_dedup_by_key(|i| *i / 10);
+
+assert_eq!(dedup, [10, 20, 30, 20, 11]);
+assert_eq!(duplicates, [21, 30, 13]);
Rotates the slice in-place such that the first mid
elements of the
+slice move to the end while the last self.len() - mid
elements move to
+the front.
After calling rotate_left
, the element previously at index mid
will
+become the first element in the slice.
This function will panic if mid
is greater than the length of the
+slice. Note that mid == self.len()
does not panic and is a no-op
+rotation.
Takes linear (in self.len()
) time.
let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+a.rotate_left(2);
+assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
Rotating a subslice:
+ +let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+a[1..5].rotate_left(1);
+assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
Rotates the slice in-place such that the first self.len() - k
+elements of the slice move to the end while the last k
elements move
+to the front.
After calling rotate_right
, the element previously at index
+self.len() - k
will become the first element in the slice.
This function will panic if k
is greater than the length of the
+slice. Note that k == self.len()
does not panic and is a no-op
+rotation.
Takes linear (in self.len()
) time.
let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+a.rotate_right(2);
+assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
Rotating a subslice:
+ +let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+a[1..5].rotate_right(1);
+assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
Fills self
with elements by cloning value
.
let mut buf = vec![0; 10];
+buf.fill(1);
+assert_eq!(buf, vec![1; 10]);
Fills self
with elements returned by calling a closure repeatedly.
This method uses a closure to create new values. If you’d rather
+Clone
a given value, use fill
. If you want to use the Default
+trait to generate values, you can pass Default::default
as the
+argument.
let mut buf = vec![1; 10];
+buf.fill_with(Default::default);
+assert_eq!(buf, vec![0; 10]);
Copies the elements from src
into self
.
The length of src
must be the same as self
.
This function will panic if the two slices have different lengths.
+Cloning two elements from a slice into another:
+ +let src = [1, 2, 3, 4];
+let mut dst = [0, 0];
+
+// Because the slices have to be the same length,
+// we slice the source slice from four elements
+// to two. It will panic if we don't do this.
+dst.clone_from_slice(&src[2..]);
+
+assert_eq!(src, [1, 2, 3, 4]);
+assert_eq!(dst, [3, 4]);
Rust enforces that there can only be one mutable reference with no
+immutable references to a particular piece of data in a particular
+scope. Because of this, attempting to use clone_from_slice
on a
+single slice will result in a compile failure:
let mut slice = [1, 2, 3, 4, 5];
+
+slice[..2].clone_from_slice(&slice[3..]); // compile fail!
To work around this, we can use split_at_mut
to create two distinct
+sub-slices from a slice:
let mut slice = [1, 2, 3, 4, 5];
+
+{
+ let (left, right) = slice.split_at_mut(2);
+ left.clone_from_slice(&right[1..]);
+}
+
+assert_eq!(slice, [4, 5, 3, 4, 5]);
Copies all elements from src
into self
, using a memcpy.
The length of src
must be the same as self
.
If T
does not implement Copy
, use clone_from_slice
.
This function will panic if the two slices have different lengths.
+Copying two elements from a slice into another:
+ +let src = [1, 2, 3, 4];
+let mut dst = [0, 0];
+
+// Because the slices have to be the same length,
+// we slice the source slice from four elements
+// to two. It will panic if we don't do this.
+dst.copy_from_slice(&src[2..]);
+
+assert_eq!(src, [1, 2, 3, 4]);
+assert_eq!(dst, [3, 4]);
Rust enforces that there can only be one mutable reference with no
+immutable references to a particular piece of data in a particular
+scope. Because of this, attempting to use copy_from_slice
on a
+single slice will result in a compile failure:
let mut slice = [1, 2, 3, 4, 5];
+
+slice[..2].copy_from_slice(&slice[3..]); // compile fail!
To work around this, we can use split_at_mut
to create two distinct
+sub-slices from a slice:
let mut slice = [1, 2, 3, 4, 5];
+
+{
+ let (left, right) = slice.split_at_mut(2);
+ left.copy_from_slice(&right[1..]);
+}
+
+assert_eq!(slice, [4, 5, 3, 4, 5]);
Copies elements from one part of the slice to another part of itself, +using a memmove.
+src
is the range within self
to copy from. dest
is the starting
+index of the range within self
to copy to, which will have the same
+length as src
. The two ranges may overlap. The ends of the two ranges
+must be less than or equal to self.len()
.
This function will panic if either range exceeds the end of the slice,
+or if the end of src
is before the start.
Copying four bytes within a slice:
+ +let mut bytes = *b"Hello, World!";
+
+bytes.copy_within(1..5, 8);
+
+assert_eq!(&bytes, b"Hello, Wello!");
Swaps all elements in self
with those in other
.
The length of other
must be the same as self
.
This function will panic if the two slices have different lengths.
+Swapping two elements across slices:
+ +let mut slice1 = [0, 0];
+let mut slice2 = [1, 2, 3, 4];
+
+slice1.swap_with_slice(&mut slice2[2..]);
+
+assert_eq!(slice1, [3, 4]);
+assert_eq!(slice2, [1, 2, 0, 0]);
Rust enforces that there can only be one mutable reference to a
+particular piece of data in a particular scope. Because of this,
+attempting to use swap_with_slice
on a single slice will result in
+a compile failure:
let mut slice = [1, 2, 3, 4, 5];
+slice[..2].swap_with_slice(&mut slice[3..]); // compile fail!
To work around this, we can use split_at_mut
to create two distinct
+mutable sub-slices from a slice:
let mut slice = [1, 2, 3, 4, 5];
+
+{
+ let (left, right) = slice.split_at_mut(2);
+ left.swap_with_slice(&mut right[1..]);
+}
+
+assert_eq!(slice, [4, 5, 3, 1, 2]);
Transmutes the slice to a slice of another type, ensuring alignment of the types is +maintained.
+This method splits the slice into three distinct slices: prefix, correctly aligned middle +slice of a new type, and the suffix slice. The middle part will be as big as possible under +the given alignment constraint and element size.
+This method has no purpose when either input element T
or output element U
are
+zero-sized and will return the original slice without splitting anything.
This method is essentially a transmute
with respect to the elements in the returned
+middle slice, so all the usual caveats pertaining to transmute::<T, U>
also apply here.
Basic usage:
+ +unsafe {
+ let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
+ let (prefix, shorts, suffix) = bytes.align_to::<u16>();
+ // less_efficient_algorithm_for_bytes(prefix);
+ // more_efficient_algorithm_for_aligned_shorts(shorts);
+ // less_efficient_algorithm_for_bytes(suffix);
+}
Transmutes the mutable slice to a mutable slice of another type, ensuring alignment of the +types is maintained.
+This method splits the slice into three distinct slices: prefix, correctly aligned middle +slice of a new type, and the suffix slice. The middle part will be as big as possible under +the given alignment constraint and element size.
+This method has no purpose when either input element T
or output element U
are
+zero-sized and will return the original slice without splitting anything.
This method is essentially a transmute
with respect to the elements in the returned
+middle slice, so all the usual caveats pertaining to transmute::<T, U>
also apply here.
Basic usage:
+ +unsafe {
+ let mut bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
+ let (prefix, shorts, suffix) = bytes.align_to_mut::<u16>();
+ // less_efficient_algorithm_for_bytes(prefix);
+ // more_efficient_algorithm_for_aligned_shorts(shorts);
+ // less_efficient_algorithm_for_bytes(suffix);
+}
portable_simd
)Splits a slice into a prefix, a middle of aligned SIMD types, and a suffix.
+This is a safe wrapper around slice::align_to
, so inherits the same
+guarantees as that method.
This will panic if the size of the SIMD type is different from
+LANES
times that of the scalar.
At the time of writing, the trait restrictions on Simd<T, LANES>
keeps
+that from ever happening, as only power-of-two numbers of lanes are
+supported. It’s possible that, in the future, those restrictions might
+be lifted in a way that would make it possible to see panics from this
+method for something like LANES == 3
.
#![feature(portable_simd)]
+use core::simd::prelude::*;
+
+let short = &[1, 2, 3];
+let (prefix, middle, suffix) = short.as_simd::<4>();
+assert_eq!(middle, []); // Not enough elements for anything in the middle
+
+// They might be split in any possible way between prefix and suffix
+let it = prefix.iter().chain(suffix).copied();
+assert_eq!(it.collect::<Vec<_>>(), vec![1, 2, 3]);
+
+fn basic_simd_sum(x: &[f32]) -> f32 {
+ use std::ops::Add;
+ let (prefix, middle, suffix) = x.as_simd();
+ let sums = f32x4::from_array([
+ prefix.iter().copied().sum(),
+ 0.0,
+ 0.0,
+ suffix.iter().copied().sum(),
+ ]);
+ let sums = middle.iter().copied().fold(sums, f32x4::add);
+ sums.reduce_sum()
+}
+
+let numbers: Vec<f32> = (1..101).map(|x| x as _).collect();
+assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0);
portable_simd
)Splits a mutable slice into a mutable prefix, a middle of aligned SIMD types, +and a mutable suffix.
+This is a safe wrapper around slice::align_to_mut
, so inherits the same
+guarantees as that method.
This is the mutable version of slice::as_simd
; see that for examples.
This will panic if the size of the SIMD type is different from
+LANES
times that of the scalar.
At the time of writing, the trait restrictions on Simd<T, LANES>
keeps
+that from ever happening, as only power-of-two numbers of lanes are
+supported. It’s possible that, in the future, those restrictions might
+be lifted in a way that would make it possible to see panics from this
+method for something like LANES == 3
.
Checks if the elements of this slice are sorted.
+That is, for each element a
and its following element b
, a <= b
must hold. If the
+slice yields exactly zero or one element, true
is returned.
Note that if Self::Item
is only PartialOrd
, but not Ord
, the above definition
+implies that this function returns false
if any two consecutive items are not
+comparable.
let empty: [i32; 0] = [];
+
+assert!([1, 2, 2, 9].is_sorted());
+assert!(![1, 3, 2, 4].is_sorted());
+assert!([0].is_sorted());
+assert!(empty.is_sorted());
+assert!(![0.0, 1.0, f32::NAN].is_sorted());
Checks if the elements of this slice are sorted using the given comparator function.
+Instead of using PartialOrd::partial_cmp
, this function uses the given compare
+function to determine whether two elements are to be considered in sorted order.
assert!([1, 2, 2, 9].is_sorted_by(|a, b| a <= b));
+assert!(![1, 2, 2, 9].is_sorted_by(|a, b| a < b));
+
+assert!([0].is_sorted_by(|a, b| true));
+assert!([0].is_sorted_by(|a, b| false));
+
+let empty: [i32; 0] = [];
+assert!(empty.is_sorted_by(|a, b| false));
+assert!(empty.is_sorted_by(|a, b| true));
Checks if the elements of this slice are sorted using the given key extraction function.
+Instead of comparing the slice’s elements directly, this function compares the keys of the
+elements, as determined by f
. Apart from that, it’s equivalent to is_sorted
; see its
+documentation for more information.
assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
Returns the index of the partition point according to the given predicate +(the index of the first element of the second partition).
+The slice is assumed to be partitioned according to the given predicate.
+This means that all elements for which the predicate returns true are at the start of the slice
+and all elements for which the predicate returns false are at the end.
+For example, [7, 15, 3, 5, 4, 12, 6]
is partitioned under the predicate x % 2 != 0
+(all odd numbers are at the start, all even at the end).
If this slice is not partitioned, the returned result is unspecified and meaningless, +as this method performs a kind of binary search.
+See also binary_search
, binary_search_by
, and binary_search_by_key
.
let v = [1, 2, 3, 3, 5, 6, 7];
+let i = v.partition_point(|&x| x < 5);
+
+assert_eq!(i, 4);
+assert!(v[..i].iter().all(|&x| x < 5));
+assert!(v[i..].iter().all(|&x| !(x < 5)));
If all elements of the slice match the predicate, including if the slice +is empty, then the length of the slice will be returned:
+ +let a = [2, 4, 8];
+assert_eq!(a.partition_point(|x| x < &100), a.len());
+let a: [i32; 0] = [];
+assert_eq!(a.partition_point(|x| x < &100), 0);
If you want to insert an item to a sorted vector, while maintaining +sort order:
+ +let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+let num = 42;
+let idx = s.partition_point(|&x| x <= num);
+s.insert(idx, num);
+assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
slice_take
)Removes the subslice corresponding to the given range +and returns a reference to it.
+Returns None
and does not modify the slice if the given
+range is out of bounds.
Note that this method only accepts one-sided ranges such as
+2..
or ..6
, but not 2..6
.
Taking the first three elements of a slice:
+ +#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+let mut first_three = slice.take(..3).unwrap();
+
+assert_eq!(slice, &['d']);
+assert_eq!(first_three, &['a', 'b', 'c']);
Taking the last two elements of a slice:
+ +#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+let mut tail = slice.take(2..).unwrap();
+
+assert_eq!(slice, &['a', 'b']);
+assert_eq!(tail, &['c', 'd']);
Getting None
when range
is out of bounds:
#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c', 'd'];
+
+assert_eq!(None, slice.take(5..));
+assert_eq!(None, slice.take(..5));
+assert_eq!(None, slice.take(..=4));
+let expected: &[char] = &['a', 'b', 'c', 'd'];
+assert_eq!(Some(expected), slice.take(..4));
slice_take
)Removes the subslice corresponding to the given range +and returns a mutable reference to it.
+Returns None
and does not modify the slice if the given
+range is out of bounds.
Note that this method only accepts one-sided ranges such as
+2..
or ..6
, but not 2..6
.
Taking the first three elements of a slice:
+ +#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+let mut first_three = slice.take_mut(..3).unwrap();
+
+assert_eq!(slice, &mut ['d']);
+assert_eq!(first_three, &mut ['a', 'b', 'c']);
Taking the last two elements of a slice:
+ +#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+let mut tail = slice.take_mut(2..).unwrap();
+
+assert_eq!(slice, &mut ['a', 'b']);
+assert_eq!(tail, &mut ['c', 'd']);
Getting None
when range
is out of bounds:
#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+
+assert_eq!(None, slice.take_mut(5..));
+assert_eq!(None, slice.take_mut(..5));
+assert_eq!(None, slice.take_mut(..=4));
+let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
+assert_eq!(Some(expected), slice.take_mut(..4));
slice_take
)Removes the first element of the slice and returns a reference +to it.
+Returns None
if the slice is empty.
#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c'];
+let first = slice.take_first().unwrap();
+
+assert_eq!(slice, &['b', 'c']);
+assert_eq!(first, &'a');
slice_take
)Removes the first element of the slice and returns a mutable +reference to it.
+Returns None
if the slice is empty.
#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
+let first = slice.take_first_mut().unwrap();
+*first = 'd';
+
+assert_eq!(slice, &['b', 'c']);
+assert_eq!(first, &'d');
slice_take
)Removes the last element of the slice and returns a reference +to it.
+Returns None
if the slice is empty.
#![feature(slice_take)]
+
+let mut slice: &[_] = &['a', 'b', 'c'];
+let last = slice.take_last().unwrap();
+
+assert_eq!(slice, &['a', 'b']);
+assert_eq!(last, &'c');
slice_take
)Removes the last element of the slice and returns a mutable +reference to it.
+Returns None
if the slice is empty.
#![feature(slice_take)]
+
+let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
+let last = slice.take_last_mut().unwrap();
+*last = 'd';
+
+assert_eq!(slice, &['a', 'b']);
+assert_eq!(last, &'d');
get_many_mut
)Returns mutable references to many indices at once, without doing any checks.
+For a safe alternative see get_many_mut
.
Calling this method with overlapping or out-of-bounds indices is undefined behavior +even if the resulting references are not used.
+#![feature(get_many_mut)]
+
+let x = &mut [1, 2, 4];
+
+unsafe {
+ let [a, b] = x.get_many_unchecked_mut([0, 2]);
+ *a *= 10;
+ *b *= 100;
+}
+assert_eq!(x, &[10, 2, 400]);
get_many_mut
)Returns mutable references to many indices at once.
+Returns an error if any index is out-of-bounds, or if the same index was +passed more than once.
+#![feature(get_many_mut)]
+
+let v = &mut [1, 2, 3];
+if let Ok([a, b]) = v.get_many_mut([0, 2]) {
+ *a = 413;
+ *b = 612;
+}
+assert_eq!(v, &[413, 2, 612]);
substr_range
)Returns the index that an element reference points to.
+Returns None
if element
does not point within the slice or if it points between elements.
This method is useful for extending slice iterators like slice::split
.
Note that this uses pointer arithmetic and does not compare elements.
+To find the index of an element via comparison, use
+.iter().position()
instead.
Panics if T
is zero-sized.
Basic usage:
+ +#![feature(substr_range)]
+
+let nums: &[u32] = &[1, 7, 1, 1];
+let num = &nums[2];
+
+assert_eq!(num, &1);
+assert_eq!(nums.elem_offset(num), Some(2));
Returning None
with an in-between element:
#![feature(substr_range)]
+
+let arr: &[[u32; 2]] = &[[0, 1], [2, 3]];
+let flat_arr: &[u32] = arr.as_flattened();
+
+let ok_elm: &[u32; 2] = flat_arr[0..2].try_into().unwrap();
+let weird_elm: &[u32; 2] = flat_arr[1..3].try_into().unwrap();
+
+assert_eq!(ok_elm, &[0, 1]);
+assert_eq!(weird_elm, &[1, 2]);
+
+assert_eq!(arr.elem_offset(ok_elm), Some(0)); // Points to element 0
+assert_eq!(arr.elem_offset(weird_elm), None); // Points between element 0 and 1
substr_range
)Returns the range of indices that a subslice points to.
+Returns None
if subslice
does not point within the slice or if it points between elements.
This method does not compare elements. Instead, this method finds the location in the slice that
+subslice
was obtained from. To find the index of a subslice via comparison, instead use
+.windows()
.position()
.
This method is useful for extending slice iterators like slice::split
.
Note that this may return a false positive (either Some(0..0)
or Some(self.len()..self.len())
)
+if subslice
has a length of zero and points to the beginning or end of another, separate, slice.
Panics if T
is zero-sized.
Basic usage:
+ +#![feature(substr_range)]
+
+let nums = &[0, 5, 10, 0, 0, 5];
+
+let mut iter = nums
+ .split(|t| *t == 0)
+ .map(|n| nums.subslice_range(n).unwrap());
+
+assert_eq!(iter.next(), Some(0..0));
+assert_eq!(iter.next(), Some(1..3));
+assert_eq!(iter.next(), Some(4..4));
+assert_eq!(iter.next(), Some(5..6));
Takes a &[[T; N]]
, and flattens it to a &[T]
.
This panics if the length of the resulting slice would overflow a usize
.
This is only possible when flattening a slice of arrays of zero-sized
+types, and thus tends to be irrelevant in practice. If
+size_of::<T>() > 0
, this will never panic.
assert_eq!([[1, 2, 3], [4, 5, 6]].as_flattened(), &[1, 2, 3, 4, 5, 6]);
+
+assert_eq!(
+ [[1, 2, 3], [4, 5, 6]].as_flattened(),
+ [[1, 2], [3, 4], [5, 6]].as_flattened(),
+);
+
+let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []];
+assert!(slice_of_empty_arrays.as_flattened().is_empty());
+
+let empty_slice_of_arrays: &[[u32; 10]] = &[];
+assert!(empty_slice_of_arrays.as_flattened().is_empty());
Takes a &mut [[T; N]]
, and flattens it to a &mut [T]
.
This panics if the length of the resulting slice would overflow a usize
.
This is only possible when flattening a slice of arrays of zero-sized
+types, and thus tends to be irrelevant in practice. If
+size_of::<T>() > 0
, this will never panic.
fn add_5_to_all(slice: &mut [i32]) {
+ for i in slice {
+ *i += 5;
+ }
+}
+
+let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
+add_5_to_all(array.as_flattened_mut());
+assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
sort_floats
)Sorts the slice of floats.
+This sort is in-place (i.e. does not allocate), O(n * log(n)) worst-case, and uses
+the ordering defined by f32::total_cmp
.
This uses the same sorting algorithm as sort_unstable_by
.
#![feature(sort_floats)]
+let mut v = [2.6, -5e-8, f32::NAN, 8.29, f32::INFINITY, -1.0, 0.0, -f32::INFINITY, -0.0];
+
+v.sort_floats();
+let sorted = [-f32::INFINITY, -1.0, -5e-8, -0.0, 0.0, 2.6, 8.29, f32::INFINITY, f32::NAN];
+assert_eq!(&v[..8], &sorted[..8]);
+assert!(v[8].is_nan());
sort_floats
)Sorts the slice of floats.
+This sort is in-place (i.e. does not allocate), O(n * log(n)) worst-case, and uses
+the ordering defined by f64::total_cmp
.
This uses the same sorting algorithm as sort_unstable_by
.
#![feature(sort_floats)]
+let mut v = [2.6, -5e-8, f64::NAN, 8.29, f64::INFINITY, -1.0, 0.0, -f64::INFINITY, -0.0];
+
+v.sort_floats();
+let sorted = [-f64::INFINITY, -1.0, -5e-8, -0.0, 0.0, 2.6, 8.29, f64::INFINITY, f64::NAN];
+assert_eq!(&v[..8], &sorted[..8]);
+assert!(v[8].is_nan());
Creates an iterator over the contiguous valid UTF-8 ranges of this +slice, and the non-UTF-8 fragments in between.
+This function formats arbitrary but mostly-UTF-8 bytes into Rust source
+code in the form of a C-string literal (c"..."
).
use std::fmt::Write as _;
+
+pub fn cstr_literal(bytes: &[u8]) -> String {
+ let mut repr = String::new();
+ repr.push_str("c\"");
+ for chunk in bytes.utf8_chunks() {
+ for ch in chunk.valid().chars() {
+ // Escapes \0, \t, \r, \n, \\, \', \", and uses \u{...} for non-printable characters.
+ write!(repr, "{}", ch.escape_debug()).unwrap();
+ }
+ for byte in chunk.invalid() {
+ write!(repr, "\\x{:02X}", byte).unwrap();
+ }
+ }
+ repr.push('"');
+ repr
+}
+
+fn main() {
+ let lit = cstr_literal(b"\xferris the \xf0\x9f\xa6\x80\x07");
+ let expected = stringify!(c"\xFErris the 🦀\u{7}");
+ assert_eq!(lit, expected);
+}
Sorts the slice, preserving initial order of equal elements.
+This sort is stable (i.e., does not reorder equal elements) and O(n * log(n)) +worst-case.
+If the implementation of Ord
for T
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for T
panics.
When applicable, unstable sorting is preferred because it is generally faster than stable
+sorting and it doesn’t allocate auxiliary memory. See
+sort_unstable
. The exception are partially sorted slices, which
+may be better served with slice::sort
.
Sorting types that only implement PartialOrd
such as f32
and f64
require
+additional precautions. For example, f32::NAN != f32::NAN
, which doesn’t fulfill the
+reflexivity requirement of Ord
. By using an alternative comparison function with
+slice::sort_by
such as f32::total_cmp
or f64::total_cmp
that defines a total
+order users can sort slices containing floating-point values. Alternatively, if all values
+in the slice are guaranteed to be in a subset for which PartialOrd::partial_cmp
forms a
+total order, it’s possible to sort the slice with sort_by(|a, b| a.partial_cmp(b).unwrap())
.
The current implementation is based on driftsort by Orson Peters and Lukas Bergdoll, which +combines the fast average case of quicksort with the fast worst case and partial run +detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs +with k distinct elements, the expected time to sort the data is O(n * log(k)).
+The auxiliary memory allocation behavior depends on the input length. Short slices are
+handled without allocation, medium sized slices allocate self.len()
and beyond that it
+clamps at self.len() / 2
.
May panic if the implementation of Ord
for T
does not implement a total order.
let mut v = [4, -5, 1, -3, 2];
+
+v.sort();
+assert_eq!(v, [-5, -3, 1, 2, 4]);
Sorts the slice with a comparison function, preserving initial order of equal elements.
+This sort is stable (i.e., does not reorder equal elements) and O(n * log(n)) +worst-case.
+If the comparison function compare
does not implement a total order the resulting order
+of elements in the slice is unspecified. All original elements will remain in the slice and
+any possible modifications via interior mutability are observed in the input. Same is true
+if compare
panics.
For example |a, b| (a - b).cmp(a)
is a comparison function that is neither transitive nor
+reflexive nor total, a < b < c < a
with a = 1, b = 2, c = 3
. For more information and
+examples see the Ord
documentation.
The current implementation is based on driftsort by Orson Peters and Lukas Bergdoll, which +combines the fast average case of quicksort with the fast worst case and partial run +detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs +with k distinct elements, the expected time to sort the data is O(n * log(k)).
+The auxiliary memory allocation behavior depends on the input length. Short slices are
+handled without allocation, medium sized slices allocate self.len()
and beyond that it
+clamps at self.len() / 2
.
May panic if compare
does not implement a total order.
let mut v = [4, -5, 1, -3, 2];
+v.sort_by(|a, b| a.cmp(b));
+assert_eq!(v, [-5, -3, 1, 2, 4]);
+
+// reverse sorting
+v.sort_by(|a, b| b.cmp(a));
+assert_eq!(v, [4, 2, 1, -3, -5]);
Sorts the slice with a key extraction function, preserving initial order of equal elements.
+This sort is stable (i.e., does not reorder equal elements) and O(m * n * log(n)) +worst-case, where the key function is O(m).
+If the implementation of Ord
for K
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for K
panics.
The current implementation is based on driftsort by Orson Peters and Lukas Bergdoll, which +combines the fast average case of quicksort with the fast worst case and partial run +detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs +with k distinct elements, the expected time to sort the data is O(n * log(k)).
+The auxiliary memory allocation behavior depends on the input length. Short slices are
+handled without allocation, medium sized slices allocate self.len()
and beyond that it
+clamps at self.len() / 2
.
May panic if the implementation of Ord
for K
does not implement a total order.
let mut v = [4i32, -5, 1, -3, 2];
+
+v.sort_by_key(|k| k.abs());
+assert_eq!(v, [1, 2, -3, 4, -5]);
Sorts the slice with a key extraction function, preserving initial order of equal elements.
+This sort is stable (i.e., does not reorder equal elements) and O(m * n + n * +log(n)) worst-case, where the key function is O(m).
+During sorting, the key function is called at most once per element, by using temporary +storage to remember the results of key evaluation. The order of calls to the key function is +unspecified and may change in future versions of the standard library.
+If the implementation of Ord
for K
does not implement a total order the resulting
+order of elements in the slice is unspecified. All original elements will remain in the
+slice and any possible modifications via interior mutability are observed in the input. Same
+is true if the implementation of Ord
for K
panics.
For simple key functions (e.g., functions that are property accesses or basic operations),
+sort_by_key
is likely to be faster.
The current implementation is based on instruction-parallel-network sort by Lukas +Bergdoll, which combines the fast average case of randomized quicksort with the fast worst +case of heapsort, while achieving linear time on fully sorted and reversed inputs. And +O(k * log(n)) where k is the number of distinct elements in the input. It leverages +superscalar out-of-order execution capabilities commonly found in CPUs, to efficiently +perform the operation.
+In the worst case, the algorithm allocates temporary storage in a Vec<(K, usize)>
the
+length of the slice.
May panic if the implementation of Ord
for K
does not implement a total order.
let mut v = [4i32, -5, 1, -3, 2, 10];
+
+// Strings are sorted by lexicographical order.
+v.sort_by_cached_key(|k| k.to_string());
+assert_eq!(v, [-3, -5, 1, 10, 2, 4]);
Copies self
into a new Vec
.
let s = [10, 40, 30];
+let x = s.to_vec();
+// Here, `s` and `x` can be modified independently.
allocator_api
)Copies self
into a new Vec
with an allocator.
#![feature(allocator_api)]
+
+use std::alloc::System;
+
+let s = [10, 40, 30];
+let x = s.to_vec_in(System);
+// Here, `s` and `x` can be modified independently.
Flattens a slice of T
into a single value Self::Output
.
assert_eq!(["hello", "world"].concat(), "helloworld");
+assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
Flattens a slice of T
into a single value Self::Output
, placing a
+given separator between each.
assert_eq!(["hello", "world"].join(" "), "hello world");
+assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
+assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]);
Flattens a slice of T
into a single value Self::Output
, placing a
+given separator between each.
assert_eq!(["hello", "world"].connect(" "), "hello world");
+assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
Returns a vector containing a copy of this slice where each byte +is mapped to its ASCII upper case equivalent.
+ASCII letters ‘a’ to ‘z’ are mapped to ‘A’ to ‘Z’, +but non-ASCII letters are unchanged.
+To uppercase the value in-place, use make_ascii_uppercase
.
Returns a vector containing a copy of this slice where each byte +is mapped to its ASCII lower case equivalent.
+ASCII letters ‘A’ to ‘Z’ are mapped to ‘a’ to ‘z’, +but non-ASCII letters are unchanged.
+To lowercase the value in-place, use make_ascii_lowercase
.
parameters
when converting.self
into C
, using the provided parameters.clone_to_uninit
)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
.Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
+further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &Any
’s vtable from &Trait
’s.&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &mut Any
’s vtable from &mut Trait
’s.angle
.other
into Self
, while performing the appropriate scaling,
+rounding and clamping.T
.parameters
when converting.self
into C
, using the provided parameters.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 moreself
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 moreself
as a ReadOnly
.self
into T
, while performing the appropriate scaling,
+rounding and clamping.Value
].Value
].try_into_colors
fails to cast.OutOfBounds
error is returned which contains
+the unclamped color. Read moreSubscriber
to this type, returning a
+[WithDispatch
] wrapper. Read morepub struct RunningAnimation { /* private fields */ }
parameters
when converting.self
into C
, using the provided parameters.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
.Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
+further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &Any
’s vtable from &Trait
’s.&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
+generate &mut Any
’s vtable from &mut Trait
’s.angle
.other
into Self
, while performing the appropriate scaling,
+rounding and clamping.T
.parameters
when converting.self
into C
, using the provided parameters.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 moreself
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 moreself
as a ReadOnly
.self
into T
, while performing the appropriate scaling,
+rounding and clamping.Value
].Value
].try_into_colors
fails to cast.OutOfBounds
error is returned which contains
+the unclamped color. Read moreSubscriber
to this type, returning a
+[WithDispatch
] wrapper. Read morepub enum BoneEnd {
+BoneEnd in funnybones - Rust Enum funnybones::BoneEnd
source · pub enum BoneEnd {
A,
B,
}
Expand description
A specific end of a Bone
.
Variants§
Implementations§
Trait Implementations§
source§impl<'de> Deserialize<'de> for BoneEnd
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
- __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Hash for BoneEnd
1.3.0 · source§fn hash_slice<H>(data: &[Self], state: &mut H)where
+
Implementations§
Trait Implementations§
source§impl<'de> Deserialize<'de> for BoneEnd
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
+ __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Copy for BoneEnd
source§impl Eq for BoneEnd
source§impl StructuralPartialEq for BoneEnd
Auto Trait Implementations§
§impl Freeze for BoneEnd
§impl RefUnwindSafe for BoneEnd
§impl Send for BoneEnd
§impl Sync for BoneEnd
§impl Unpin for BoneEnd
§impl UnwindSafe for BoneEnd
Blanket Implementations§
source§impl Copy for BoneEnd
source§impl Eq for BoneEnd
source§impl StructuralPartialEq for BoneEnd
Auto Trait Implementations§
§impl Freeze for BoneEnd
§impl RefUnwindSafe for BoneEnd
§impl Send for BoneEnd
§impl Sync for BoneEnd
§impl Unpin for BoneEnd
§impl UnwindSafe for BoneEnd
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
@@ -28,16 +28,15 @@
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> TConverts self
into C
, using the provided parameters.
§impl<A> Cast for A
source§impl<T> CloneToUninit for Twhere
- T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
- T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
+ A: CastFrom<B>,
source§impl<T> CloneToUninit for Twhere
+ T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
source§fn components_from(colors: C) -> T
Cast a collection of colors into a collection of color components.§impl<T> Downcast for Twhere
T: Any,
§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
.§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
.§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more§impl<Q, K> Equivalent<K> for Qwhere
diff --git a/main/funnybones/enum.BoneKind.html b/main/funnybones/enum.BoneKind.html
index 5944d2e..6181280 100644
--- a/main/funnybones/enum.BoneKind.html
+++ b/main/funnybones/enum.BoneKind.html
@@ -1,4 +1,4 @@
-BoneKind in funnybones - Rust Enum funnybones::BoneKind
source · pub enum BoneKind {
+BoneKind in funnybones - Rust Enum funnybones::BoneKind
source · pub enum BoneKind {
Rigid {
length: f32,
},
@@ -18,11 +18,11 @@
skeleton.
Implementations§
source§impl BoneKind
sourcepub fn with_label(self, label: impl Into<String>) -> LabeledBoneKind
Attaches a label to this bone when pushed into a skeleton.
-Trait Implementations§
source§impl<'de> Deserialize<'de> for BoneKind
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
- __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl From<BoneKind> for LabeledBoneKind
source§impl Copy for BoneKind
source§impl StructuralPartialEq for BoneKind
Auto Trait Implementations§
§impl Freeze for BoneKind
§impl RefUnwindSafe for BoneKind
§impl Send for BoneKind
§impl Sync for BoneKind
§impl Unpin for BoneKind
§impl UnwindSafe for BoneKind
Blanket Implementations§
Implementations§
source§impl BoneKind
sourcepub fn with_label(self, label: impl Into<String>) -> LabeledBoneKind
Attaches a label to this bone when pushed into a skeleton.
+Trait Implementations§
source§impl<'de> Deserialize<'de> for BoneKind
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
+ __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl From<BoneKind> for LabeledBoneKind
source§impl Copy for BoneKind
source§impl StructuralPartialEq for BoneKind
Auto Trait Implementations§
§impl Freeze for BoneKind
§impl RefUnwindSafe for BoneKind
§impl Send for BoneKind
§impl Sync for BoneKind
§impl Unpin for BoneKind
§impl UnwindSafe for BoneKind
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
@@ -40,16 +40,15 @@
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> TConverts self
into C
, using the provided parameters.
§impl<A> Cast for A
source§impl<T> CloneToUninit for Twhere
- T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
- T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
+ A: CastFrom<B>,
source§impl<T> CloneToUninit for Twhere
+ T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
source§fn components_from(colors: C) -> T
Cast a collection of colors into a collection of color components.§impl<T> Downcast for Twhere
T: Any,
§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
.§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
.§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
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 Twhere
U: IntoStimulus<T>,
source§fn from_stimulus(other: U) -> T
Converts other
into Self
, while performing the appropriate scaling,
diff --git a/main/funnybones/index.html b/main/funnybones/index.html
index c55c9ce..70d0273 100644
--- a/main/funnybones/index.html
+++ b/main/funnybones/index.html
@@ -1,4 +1,4 @@
-funnybones - Rust Crate funnybones
source · Expand description
+funnybones - Rust Crate funnybones
source · Expand description
MIT License or the
Apache License 2.0.
To learn more about contributing, please see CONTRIBUTING.md.
-Structs§
- A bone in a
Skeleton
. - A specific end of a specific bone.
- A connection between two bones.
- A
BoneKind
with an associated label. - A value representing a rotation between no rotation and a full rotation.
- A two dimensionsional offset/measurement.
Enums§
\ No newline at end of file
+Modules§
Structs§
- A bone in a
Skeleton
. - A specific end of a specific bone.
- A connection between two bones.
- A
BoneKind
with an associated label. - A value representing a rotation between no rotation and a full rotation.
- A two dimensionsional offset/measurement.
Enums§
\ No newline at end of file
diff --git a/main/funnybones/sidebar-items.js b/main/funnybones/sidebar-items.js
index 471ab6a..a7c7cf6 100644
--- a/main/funnybones/sidebar-items.js
+++ b/main/funnybones/sidebar-items.js
@@ -1 +1 @@
-window.SIDEBAR_ITEMS = {"enum":["BoneEnd","BoneKind"],"struct":["Bone","BoneAxis","BoneId","Joint","JointId","LabeledBoneKind","Rotation","Skeleton","Vector"]};
\ No newline at end of file
+window.SIDEBAR_ITEMS = {"enum":["BoneEnd","BoneKind"],"mod":["animation"],"struct":["Bone","BoneAxis","BoneId","Joint","JointId","LabeledBoneKind","Rotation","Skeleton","Vector"]};
\ No newline at end of file
diff --git a/main/funnybones/struct.Bone.html b/main/funnybones/struct.Bone.html
index 5091069..a9809a1 100644
--- a/main/funnybones/struct.Bone.html
+++ b/main/funnybones/struct.Bone.html
@@ -1,15 +1,15 @@
-Bone in funnybones - Rust Struct funnybones::Bone
source · pub struct Bone { /* private fields */ }
Expand description
A bone in a Skeleton
.
-Implementations§
source§impl Bone
sourcepub fn set_desired_end(&mut self, end: Option<Vector>)
Sets the location to aim the end of this bone towards.
+Bone in funnybones - Rust Struct funnybones::Bone
source · pub struct Bone { /* private fields */ }
Expand description
A bone in a Skeleton
.
+Implementations§
source§impl Bone
sourcepub fn set_desired_end(&mut self, end: Option<Vector>)
Sets the location to aim the end of this bone towards.
The end of the bone that is aimed is the end that is furthest from the
root of the skeleton.
This setting only impacts BoneKind::Jointed
bones.
-sourcepub const fn desired_end(&self) -> Option<Vector>
Returns the location this bone is being aimed towards.
-sourcepub const fn solved_joint(&self) -> Option<Vector>
If this is a BoneKind::Jointed
bone, returns the solved position of
+
sourcepub const fn desired_end(&self) -> Option<Vector>
Returns the location this bone is being aimed towards.
+sourcepub const fn solved_joint(&self) -> Option<Vector>
If this is a BoneKind::Jointed
bone, returns the solved position of
the joint.
-Trait Implementations§
Trait Implementations§
Auto Trait Implementations§
§impl Freeze for Bone
§impl RefUnwindSafe for Bone
§impl Send for Bone
§impl Sync for Bone
§impl Unpin for Bone
§impl UnwindSafe for Bone
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
@@ -35,7 +35,7 @@
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.
§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
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 Twhere
U: IntoStimulus<T>,
source§fn from_stimulus(other: U) -> T
Converts other
into Self
, while performing the appropriate scaling,
diff --git a/main/funnybones/struct.BoneAxis.html b/main/funnybones/struct.BoneAxis.html
index f3f4dcd..a8bb537 100644
--- a/main/funnybones/struct.BoneAxis.html
+++ b/main/funnybones/struct.BoneAxis.html
@@ -1,16 +1,16 @@
-BoneAxis in funnybones - Rust Struct funnybones::BoneAxis
source · pub struct BoneAxis {
+BoneAxis in funnybones - Rust Struct funnybones::BoneAxis
source · pub struct BoneAxis {
pub bone: BoneId,
pub end: BoneEnd,
}
Expand description
A specific end of a specific bone.
Fields§
§bone: BoneId
The unique id of the bone of this axis.
§end: BoneEnd
The end of the bone being referenced.
-Implementations§
Trait Implementations§
source§impl<'de> Deserialize<'de> for BoneAxis
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
- __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Hash for BoneAxis
1.3.0 · source§fn hash_slice<H>(data: &[Self], state: &mut H)where
+Implementations§
Trait Implementations§
source§impl<'de> Deserialize<'de> for BoneAxis
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
+ __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Copy for BoneAxis
source§impl Eq for BoneAxis
source§impl StructuralPartialEq for BoneAxis
Auto Trait Implementations§
§impl Freeze for BoneAxis
§impl RefUnwindSafe for BoneAxis
§impl Send for BoneAxis
§impl Sync for BoneAxis
§impl Unpin for BoneAxis
§impl UnwindSafe for BoneAxis
Blanket Implementations§
source§impl Copy for BoneAxis
source§impl Eq for BoneAxis
source§impl StructuralPartialEq for BoneAxis
Auto Trait Implementations§
§impl Freeze for BoneAxis
§impl RefUnwindSafe for BoneAxis
§impl Send for BoneAxis
§impl Sync for BoneAxis
§impl Unpin for BoneAxis
§impl UnwindSafe for BoneAxis
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
@@ -28,16 +28,15 @@
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> TConverts self
into C
, using the provided parameters.
§impl<A> Cast for A
source§impl<T> CloneToUninit for Twhere
- T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
- T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
+ A: CastFrom<B>,
source§impl<T> CloneToUninit for Twhere
+ T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
source§fn components_from(colors: C) -> T
Cast a collection of colors into a collection of color components.§impl<T> Downcast for Twhere
T: Any,
§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
.§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
.§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more§impl<Q, K> Equivalent<K> for Qwhere
diff --git a/main/funnybones/struct.BoneId.html b/main/funnybones/struct.BoneId.html
index 4091196..b3455f6 100644
--- a/main/funnybones/struct.BoneId.html
+++ b/main/funnybones/struct.BoneId.html
@@ -1,18 +1,18 @@
-BoneId in funnybones - Rust Struct funnybones::BoneId
source · pub struct BoneId(/* private fields */);
Implementations§
Trait Implementations§
source§impl<'de> Deserialize<'de> for BoneId
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
- __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Hash for BoneId
1.3.0 · source§fn hash_slice<H>(data: &[Self], state: &mut H)where
+BoneId in funnybones - Rust Struct funnybones::BoneId
source · pub struct BoneId(/* private fields */);
Implementations§
Trait Implementations§
source§impl<'de> Deserialize<'de> for BoneId
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
+ __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Ord for BoneId
source§impl PartialOrd for BoneId
source§impl PartialOrd for BoneId
source§impl Copy for BoneId
source§impl Eq for BoneId
source§impl StructuralPartialEq for BoneId
Auto Trait Implementations§
§impl Freeze for BoneId
§impl RefUnwindSafe for BoneId
§impl Send for BoneId
§impl Sync for BoneId
§impl Unpin for BoneId
§impl UnwindSafe for BoneId
Blanket Implementations§
source§impl Copy for BoneId
source§impl Eq for BoneId
source§impl StructuralPartialEq for BoneId
Auto Trait Implementations§
§impl Freeze for BoneId
§impl RefUnwindSafe for BoneId
§impl Send for BoneId
§impl Sync for BoneId
§impl Unpin for BoneId
§impl UnwindSafe for BoneId
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
@@ -30,9 +30,8 @@
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> TConverts self
into C
, using the provided parameters.
§impl<A> Cast for A
source§impl<T> CloneToUninit for Twhere
- T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
- T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
+ T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)§impl<Q, K> Comparable<K> for Q
source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
source§fn components_from(colors: C) -> T
Cast a collection of colors into a collection of color components.§impl<T> Downcast for Twhere
@@ -41,7 +40,7 @@
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.
§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more§impl<Q, K> Equivalent<K> for Qwhere
diff --git a/main/funnybones/struct.Joint.html b/main/funnybones/struct.Joint.html
index 5921a74..5be4771 100644
--- a/main/funnybones/struct.Joint.html
+++ b/main/funnybones/struct.Joint.html
@@ -1,17 +1,17 @@
-Joint in funnybones - Rust Struct funnybones::Joint
source · pub struct Joint { /* private fields */ }
Expand description
A connection between two bones.
-Implementations§
source§impl Joint
sourcepub const fn new(angle: Rotation, bone_a: BoneAxis, bone_b: BoneAxis) -> Self
Returns a new joint formed by joining bone_a
and bone_b
at angle
.
-sourcepub fn with_label(self, label: impl Into<String>) -> Self
Labels this joint and returns self.
-sourcepub fn other_axis(&self, axis: BoneAxis) -> BoneAxis
Given axis
is one of the two connections in this joint, return the
+
Joint in funnybones - Rust Struct funnybones::Joint
source · pub struct Joint { /* private fields */ }
Expand description
A connection between two bones.
+Implementations§
source§impl Joint
sourcepub const fn new(angle: Rotation, bone_a: BoneAxis, bone_b: BoneAxis) -> Self
Returns a new joint formed by joining bone_a
and bone_b
at angle
.
+sourcepub fn with_label(self, label: impl Into<String>) -> Self
Labels this joint and returns self.
+sourcepub fn other_axis(&self, axis: BoneAxis) -> BoneAxis
Given axis
is one of the two connections in this joint, return the
other axis.
§Panics
This function has a debug assertion that ensures that axis
is one of
the bones in this joint.
-sourcepub fn set_angle(&mut self, angle: Rotation)
Sets the angle to form between these joints.
This setting is ignored if the bone furthest from the root of the joint
is a BoneKind::Jointed
bone.
-Trait Implementations§
Trait Implementations§
Auto Trait Implementations§
§impl Freeze for Joint
§impl RefUnwindSafe for Joint
§impl Send for Joint
§impl Sync for Joint
§impl Unpin for Joint
§impl UnwindSafe for Joint
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
@@ -37,7 +37,7 @@ §Panics
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.
§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
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 Twhere
U: IntoStimulus<T>,
source§fn from_stimulus(other: U) -> T
Converts other
into Self
, while performing the appropriate scaling,
diff --git a/main/funnybones/struct.JointId.html b/main/funnybones/struct.JointId.html
index 772401c..cdc2502 100644
--- a/main/funnybones/struct.JointId.html
+++ b/main/funnybones/struct.JointId.html
@@ -1,16 +1,16 @@
-JointId in funnybones - Rust Struct funnybones::JointId
source · pub struct JointId(/* private fields */);
Trait Implementations§
source§impl<'de> Deserialize<'de> for JointId
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
- __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Hash for JointId
1.3.0 · source§fn hash_slice<H>(data: &[Self], state: &mut H)where
+JointId in funnybones - Rust Struct funnybones::JointId
source · pub struct JointId(/* private fields */);
Trait Implementations§
source§impl<'de> Deserialize<'de> for JointId
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
+ __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Ord for JointId
source§impl PartialOrd for JointId
source§impl PartialOrd for JointId
source§impl Copy for JointId
source§impl Eq for JointId
source§impl StructuralPartialEq for JointId
Auto Trait Implementations§
§impl Freeze for JointId
§impl RefUnwindSafe for JointId
§impl Send for JointId
§impl Sync for JointId
§impl Unpin for JointId
§impl UnwindSafe for JointId
Blanket Implementations§
source§impl Copy for JointId
source§impl Eq for JointId
source§impl StructuralPartialEq for JointId
Auto Trait Implementations§
§impl Freeze for JointId
§impl RefUnwindSafe for JointId
§impl Send for JointId
§impl Sync for JointId
§impl Unpin for JointId
§impl UnwindSafe for JointId
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
@@ -28,9 +28,8 @@
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> TConverts self
into C
, using the provided parameters.
§impl<A> Cast for A
source§impl<T> CloneToUninit for Twhere
- T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
- T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
+ T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)§impl<Q, K> Comparable<K> for Q
source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
source§fn components_from(colors: C) -> T
Cast a collection of colors into a collection of color components.§impl<T> Downcast for Twhere
@@ -39,7 +38,7 @@
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.
§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
§impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more§impl<Q, K> Equivalent<K> for Qwhere
diff --git a/main/funnybones/struct.LabeledBoneKind.html b/main/funnybones/struct.LabeledBoneKind.html
index 96c9531..d33b33e 100644
--- a/main/funnybones/struct.LabeledBoneKind.html
+++ b/main/funnybones/struct.LabeledBoneKind.html
@@ -1,10 +1,10 @@
-LabeledBoneKind in funnybones - Rust Struct funnybones::LabeledBoneKind
source · pub struct LabeledBoneKind {
+LabeledBoneKind in funnybones - Rust Struct funnybones::LabeledBoneKind
source · pub struct LabeledBoneKind {
pub kind: BoneKind,
pub label: String,
}
Expand description
A BoneKind
with an associated label.
Fields§
§kind: BoneKind
The bone to create.
§label: String
The label of the bone.
-Trait Implementations§
Auto Trait Implementations§
§impl Freeze for LabeledBoneKind
§impl RefUnwindSafe for LabeledBoneKind
§impl Send for LabeledBoneKind
§impl Sync for LabeledBoneKind
§impl Unpin for LabeledBoneKind
§impl UnwindSafe for LabeledBoneKind
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
+Trait Implementations§
Auto Trait Implementations§
§impl Freeze for LabeledBoneKind
§impl RefUnwindSafe for LabeledBoneKind
§impl Send for LabeledBoneKind
§impl Sync for LabeledBoneKind
§impl Unpin for LabeledBoneKind
§impl UnwindSafe for LabeledBoneKind
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
@@ -29,7 +29,7 @@
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.
§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.§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.
§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
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 Twhere
U: IntoStimulus<T>,
source§fn from_stimulus(other: U) -> T
Converts other
into Self
, while performing the appropriate scaling,
diff --git a/main/funnybones/struct.Rotation.html b/main/funnybones/struct.Rotation.html
index 51793b5..639f15c 100644
--- a/main/funnybones/struct.Rotation.html
+++ b/main/funnybones/struct.Rotation.html
@@ -1,19 +1,19 @@
-Rotation in funnybones - Rust Struct funnybones::Rotation
source · pub struct Rotation { /* private fields */ }
Expand description
A value representing a rotation between no rotation and a full rotation.
-Implementations§
source§impl Rotation
sourcepub fn to_degrees(self) -> f32
Returns this rotation represented in degrees.
+Rotation in funnybones - Rust Struct funnybones::Rotation
source · pub struct Rotation { /* private fields */ }
Expand description
A value representing a rotation between no rotation and a full rotation.
+Implementations§
source§impl Rotation
sourcepub fn to_degrees(self) -> f32
Returns this rotation represented in degrees.
This value will always be greater than or equal to 0 and will always be
less than 360.0.
-sourcepub const fn to_radians(self) -> f32
Returns this rotation represented in radians.
+sourcepub const fn to_radians(self) -> f32
Returns this rotation represented in radians.
This value will always be greater than or equal to 0 and will always be
less than 2π
.
-Trait Implementations§
source§impl<'de> Deserialize<'de> for Rotation
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
- __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moreTrait Implementations§
source§impl<'de> Deserialize<'de> for Rotation
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
+ __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl PartialOrd for Rotation
source§impl PercentBetween for Rotation
source§fn percent_between(&self, min: &Self, max: &Self) -> ZeroToOne
Return the percentage that self
is between min
and max
.source§impl Copy for Rotation
source§impl StructuralPartialEq for Rotation
Auto Trait Implementations§
§impl Freeze for Rotation
§impl RefUnwindSafe for Rotation
§impl Send for Rotation
§impl Sync for Rotation
§impl Unpin for Rotation
§impl UnwindSafe for Rotation
Blanket Implementations§
source§impl PercentBetween for Rotation
source§fn percent_between(&self, min: &Self, max: &Self) -> ZeroToOne
Return the percentage that self
is between min
and max
.source§impl Copy for Rotation
source§impl StructuralPartialEq for Rotation
Auto Trait Implementations§
§impl Freeze for Rotation
§impl RefUnwindSafe for Rotation
§impl Send for Rotation
§impl Sync for Rotation
§impl Unpin for Rotation
§impl UnwindSafe for Rotation
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
@@ -31,16 +31,15 @@
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> TConverts self
into C
, using the provided parameters.
§impl<A> Cast for A
source§impl<T> CloneToUninit for Twhere
- T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
- T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
+ A: CastFrom<B>,
source§impl<T> CloneToUninit for Twhere
+ T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
source§fn components_from(colors: C) -> T
Cast a collection of colors into a collection of color components.§impl<T> Downcast for Twhere
T: Any,
§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
.§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
.§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
§impl<T> DynamicDisplay for Twhere
T: Display,
§fn fmt(
&self,
diff --git a/main/funnybones/struct.Skeleton.html b/main/funnybones/struct.Skeleton.html
index 1950bec..c6326ca 100644
--- a/main/funnybones/struct.Skeleton.html
+++ b/main/funnybones/struct.Skeleton.html
@@ -1,21 +1,21 @@
-Skeleton in funnybones - Rust Struct funnybones::Skeleton
source · pub struct Skeleton { /* private fields */ }
Implementations§
source§impl Skeleton
sourcepub fn push_bone(&mut self, bone: impl Into<LabeledBoneKind>) -> BoneId
Creates a new Bone
into the skeleton. Returns the unique id of the
+
Skeleton in funnybones - Rust Struct funnybones::Skeleton
source · pub struct Skeleton { /* private fields */ }
Implementations§
source§impl Skeleton
sourcepub fn push_bone(&mut self, bone: impl Into<LabeledBoneKind>) -> BoneId
sourcepub fn push_joint(&mut self, joint: Joint) -> JointId
Creates a new Joint
in the skeleton, connecting two bones together
+
sourcepub fn push_joint(&mut self, joint: Joint) -> JointId
sourcepub fn find_joint_by_label(&self, label: &str) -> Option<JointId>
Finds an existing Joint
by its label.
-sourcepub fn find_bone_by_label(&self, label: &str) -> Option<BoneId>
Finds an existing Bone
by its label.
-sourcepub fn set_translation(&mut self, translation: Vector)
Sets a translation to be applied to the entire skeleton.
-sourcepub fn translation(&self) -> Vector
Returns the translation applied to the entire skeleton.
-sourcepub fn set_rotation(&mut self, rotation: Rotation)
Sets a base rotation to apply to the entire skeleton.
-sourcepub fn rotation(&self) -> Rotation
Returns the base rotation being applied to the entire skeleton.
-sourcepub fn find_joint_by_label(&self, label: &str) -> Option<JointId>
Finds an existing Joint
by its label.
+sourcepub fn find_bone_by_label(&self, label: &str) -> Option<BoneId>
Finds an existing Bone
by its label.
+sourcepub fn set_translation(&mut self, translation: Vector)
Sets a translation to be applied to the entire skeleton.
+sourcepub fn translation(&self) -> Vector
Returns the translation applied to the entire skeleton.
+sourcepub fn set_rotation(&mut self, rotation: Rotation)
Sets a base rotation to apply to the entire skeleton.
+Trait Implementations§
source§impl<'de> Deserialize<'de> for Skeleton
source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
- D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moreTrait Implementations§
source§impl<'de> Deserialize<'de> for Skeleton
source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
+ D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moreAuto Trait Implementations§
§impl Freeze for Skeleton
§impl RefUnwindSafe for Skeleton
§impl Send for Skeleton
§impl Sync for Skeleton
§impl Unpin for Skeleton
§impl UnwindSafe for Skeleton
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
@@ -41,7 +41,7 @@
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.
§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
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 Twhere
U: IntoStimulus<T>,
source§fn from_stimulus(other: U) -> T
Converts other
into Self
, while performing the appropriate scaling,
diff --git a/main/funnybones/struct.Vector.html b/main/funnybones/struct.Vector.html
index a8046c0..6eaf676 100644
--- a/main/funnybones/struct.Vector.html
+++ b/main/funnybones/struct.Vector.html
@@ -1,20 +1,20 @@
-Vector in funnybones - Rust Struct funnybones::Vector
source · pub struct Vector {
+Vector in funnybones - Rust Struct funnybones::Vector
source · pub struct Vector {
pub x: f32,
pub y: f32,
}
Expand description
A two dimensionsional offset/measurement.
Fields§
§x: f32
The x-axis component of this vector.
§y: f32
The y-axis component of this vector.
-Implementations§
Trait Implementations§
source§impl<'de> Deserialize<'de> for Vector
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
- __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl FromComponents<f32> for Vector
source§fn from_components(components: (f32, f32)) -> Self
Returns a new instance from the 2d vector components provided.§fn from_vec<Type>(other: Type) -> Selfwhere
+Implementations§
Trait Implementations§
source§impl<'de> Deserialize<'de> for Vector
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
+ __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read moresource§impl Copy for Vector
source§impl StructuralPartialEq for Vector
Auto Trait Implementations§
§impl Freeze for Vector
§impl RefUnwindSafe for Vector
§impl Send for Vector
§impl Sync for Vector
§impl Unpin for Vector
§impl UnwindSafe for Vector
Blanket Implementations§
source§impl Copy for Vector
source§impl StructuralPartialEq for Vector
Auto Trait Implementations§
§impl Freeze for Vector
§impl RefUnwindSafe for Vector
§impl Send for Vector
§impl Sync for Vector
§impl Unpin for Vector
§impl UnwindSafe for Vector
Blanket Implementations§
source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
@@ -32,16 +32,15 @@
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> TConverts self
into C
, using the provided parameters.
§impl<A> Cast for A
source§impl<T> CloneToUninit for Twhere
- T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
- T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
+ A: CastFrom<B>,
source§impl<T> CloneToUninit for Twhere
+ T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
🔬This is a nightly-only experimental API. (clone_to_uninit
)source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
source§fn components_from(colors: C) -> T
Cast a collection of colors into a collection of color components.§impl<T> Downcast for Twhere
T: Any,
§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
.§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
.§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.§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.§impl<T> DowncastSync for T
§fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>
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 Twhere
U: IntoStimulus<T>,
source§fn from_stimulus(other: U) -> T
Converts other
into Self
, while performing the appropriate scaling,
diff --git a/main/help.html b/main/help.html
index 0de7f21..a9e765b 100644
--- a/main/help.html
+++ b/main/help.html
@@ -1 +1 @@
-Help Rustdoc help
Back
\ No newline at end of file
+Help Rustdoc help
Back
\ No newline at end of file
diff --git a/main/search-index.js b/main/search-index.js
index 91665d5..f2a8699 100644
--- a/main/search-index.js
+++ b/main/search-index.js
@@ -1,5 +1,5 @@
var searchIndex = new Map(JSON.parse('[\
-["funnybones",{"t":"PPFFGFGFFPFPFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOO","n":["A","B","Bone","BoneAxis","BoneEnd","BoneId","BoneKind","Joint","JointId","Jointed","LabeledBoneKind","Rigid","Rotation","Skeleton","Vector","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","add","angle","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","axis_a","axis_b","bone","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cast","cast","cast","cast","cast","cast","cast","cast","cast","cast","cast","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","cmp","cmp","compare","compare","compare","compare","components_from","components_from","components_from","components_from","components_from","components_from","components_from","components_from","components_from","components_from","components_from","default","default","default","degrees","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","desired_end","downcast","downcast","downcast","downcast","downcast","downcast","downcast","downcast","downcast","downcast","downcast","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","end","end","eq","eq","eq","eq","eq","eq","eq","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","find_bone_by_label","find_joint_by_label","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_components","from_parts","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","hash","hash","hash","hash","index","index","index_mut","index_mut","init","init","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","into","into","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_components","into_components","into_components","into_components","into_components","into_components","into_components","into_components","into_parts","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","inverse","inverse","kind","label","label","label","lerp","magnitude","map","neg","new","new","other_axis","partial_cmp","partial_cmp","partial_cmp","percent_between","push_bone","push_joint","radians","rotation","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","set_angle","set_desired_end","set_rotation","set_translation","solve","solved_joint","start","sub","sub","to_degrees","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_radians","to_smolstr","to_string","translation","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","upcast","upcast","upcast","upcast","upcast","upcast","upcast","upcast","upcast","upcast","upcast","with_label","with_label","x","y","end_length","inverse","length","start_length"],"q":[[0,"funnybones"],[618,"funnybones::BoneKind"],[622,"palette::chromatic_adaptation"],[623,"core::any"],[624,"palette::cam16::parameters"],[625,"intentional::cast"],[626,"core::cmp"],[627,"core::result"],[628,"serde::de"],[629,"core::option"],[630,"core::fmt"],[631,"cushy::context"],[632,"core::hash"],[633,"alloc::boxed"],[634,"alloc::sync"],[635,"alloc::rc"],[636,"cushy::value"],[637,"core::ops::function"],[638,"cushy::animation"],[639,"core::convert"],[640,"serde::ser"],[641,"smol_str"],[642,"alloc::string"],[643,"palette::convert::try_from_into_color"]],"i":[14,14,0,0,0,0,0,0,0,12,0,12,0,0,0,30,11,2,12,17,8,22,3,7,13,14,2,3,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,7,7,8,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,11,2,12,8,7,13,14,11,2,12,8,7,13,14,11,11,2,2,12,12,8,8,7,7,13,13,14,14,7,13,7,7,13,13,30,11,2,12,17,8,22,3,7,13,14,11,2,17,2,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,11,2,12,17,8,7,13,14,22,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,22,8,11,2,12,8,7,13,14,8,8,8,7,7,7,13,13,13,14,14,14,17,17,11,2,2,2,12,17,8,22,3,7,13,14,30,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,11,2,30,11,2,12,17,8,22,3,7,13,14,8,7,13,14,17,17,17,17,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,11,11,2,12,8,7,13,14,2,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,30,11,11,2,2,12,12,17,17,8,8,22,22,3,3,7,7,13,13,14,14,8,14,30,22,3,30,2,11,11,2,11,3,3,2,7,13,2,17,17,2,17,11,2,12,17,8,22,3,7,13,14,3,22,17,17,17,22,22,11,2,2,11,2,12,8,7,13,14,2,2,2,17,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,12,3,11,11,47,47,48,47],"f":"```````````````{eg{}{{b{c}}}{}}0000000000{{dd}c{}}{{{h{f}}}d}{ce{}{}}0000000000{{}c{}}0000000000{h{{h{j}}}}0000000000{{{h{l}}}{{h{lj}}}}0000000000{nA`}0`{h{{h{c}}}{}}0000000000{{{h{l}}}{{h{lc}}}{}}0000000000{{{Ab{c}}}e{}{}}0000000000{{}e{}{{Ad{c}}}}000000000077777777777{{{h{Af}}}Af}{{{h{d}}}d}{{{h{Ah}}}Ah}{{{h{A`}}}A`}{{{h{n}}}n}{{{h{Aj}}}Aj}{{{h{Al}}}Al}{{h{h{lc}}}An{}}000000{hAn}0000000000000{{{h{n}}{h{n}}}B`}{{{h{Aj}}{h{Aj}}}B`}{{h{h{c}}}B`{}}000{ce{}{}}0000000000{{}Af}{{}d}{{}Bb}{Bdd}{Bf{{h{c}}}{}}0000000000{Bf{{h{lc}}}{}}0000000000{c{{Bh{Af}}}Bj}{c{{Bh{d}}}Bj}{c{{Bh{Ah}}}Bj}{c{{Bh{Bb}}}Bj}{c{{Bh{A`}}}Bj}{c{{Bh{n}}}Bj}{c{{Bh{Aj}}}Bj}{c{{Bh{Al}}}Bj}{{{h{Bl}}}{{Bn{Af}}}}{h{{h{c}}}{}}0000000000{BfAn}0000000000{{{h{Bl}}}Af}`{{{h{Af}}{h{Af}}}C`}{{{h{d}}{h{d}}}C`}{{{h{Ah}}{h{Ah}}}C`}{{{h{A`}}{h{A`}}}C`}{{{h{n}}{h{n}}}C`}{{{h{Aj}}{h{Aj}}}C`}{{{h{Al}}{h{Al}}}C`}{{h{h{c}}}C`{}}00000000000{{{h{Bb}}{h{Cb}}}{{Bn{n}}}}{{{h{Bb}}{h{Cb}}}{{Bn{Aj}}}}{{{h{Af}}{h{lCd}}}Cf}{{{h{d}}{h{lCd}}}Cf}0{{h{h{Ch}}{h{lCd}}}{{Bh{AnCj}}}}{{{h{Ah}}{h{lCd}}}Cf}{{{h{Bb}}{h{lCd}}}Cf}{{{h{A`}}{h{lCd}}}Cf}{{{h{Bl}}{h{lCd}}}Cf}{{{h{f}}{h{lCd}}}Cf}{{{h{n}}{h{lCd}}}Cf}{{{h{Aj}}{h{lCd}}}Cf}{{{h{Al}}{h{lCd}}}Cf}{cc{}}{AhCl}11111111111111111111111111111111{{{Cn{BdBd}}}Af}{Bnc{}}{ce{}{}}0000000000{{{h{A`}}{h{lc}}}AnD`}{{{h{n}}{h{lc}}}AnD`}{{{h{Aj}}{h{lc}}}AnD`}{{{h{Al}}{h{lc}}}AnD`}{{{h{Bb}}Aj}{{h{c}}}{}}{{{h{Bb}}n}{{h{c}}}{}}{{{h{lBb}}n}{{h{lc}}}{}}{{{h{lBb}}Aj}{{h{lc}}}{}}{{}Bf}0000000000{{}c{}}000000000000000000000{{{Db{c}}}{{Db{j}}}{}}0000000000{{{Dd{c}}}{{Dd{j}}}{}}0000000000{{{Df{c}}}{{Df{j}}}{}}0000000000{{{Ab{c}}}e{}{}}00000000004444444444444444444444{Af{{Cn{BdBd}}}}{{}{{Cn{cc}}}{}}000000{{}{{Cn{Bn}}}}{{}{{Dh{c}}}{}}000000000088888888888{{}{{Dj{c}}}{}}{{}{{Dj{{Bn{c}}}}}{}}01100110101001101001{A`A`}{AlAl}`{{{h{Bl}}}{{h{Cb}}}}{{{h{f}}}{{h{Cb}}}}`{{{h{d}}{h{d}}Bd}d}{{{h{Af}}}Bd}{{Afc}Af{{Dn{Bd}{{Dl{Bd}}}}}}{dc{}}{{BdBd}Af}{{dA`A`}f}{{{h{f}}A`}A`}{{{h{d}}{h{d}}}{{Bn{B`}}}}{{{h{n}}{h{n}}}{{Bn{B`}}}}{{{h{Aj}}{h{Aj}}}{{Bn{B`}}}}{{{h{d}}{h{d}}{h{d}}}E`}{{{h{lBb}}c}n{{Eb{Cl}}}}{{{h{lBb}}f}Aj}{Bdd}{{{h{Bb}}}d}{{{h{Af}}c}BhEd}{{{h{d}}c}BhEd}{{{h{Ah}}c}BhEd}{{{h{Bb}}c}BhEd}{{{h{A`}}c}BhEd}{{{h{Bl}}c}BhEd}{{{h{f}}c}BhEd}{{{h{n}}c}BhEd}{{{h{Aj}}c}BhEd}{{{h{Al}}c}BhEd}{{{h{lf}}d}An}{{{h{lBl}}{Bn{Af}}}An}{{{h{lBb}}d}An}{{{h{lBb}}Af}An}{{{h{lBb}}}An}{{{h{Bl}}}{{Bn{Af}}}}{{{h{Bl}}}Af}{{AfAf}c{}}{{dd}c{}}{dBd}{hc{}}0000001{hEf}{hEh}{{{h{Bb}}}Af}{{}{{Bh{c}}}{}}0000000000{c{{Bh{e}}}{}{}}000000000011111111111{{}{{Bh{c{Ej{c}}}}}{}}0000000000{hEl}0000000000{ce{}{}}0000000000{{}c{}}0000000000{h{{Bn{{h{c}}}}}{}}0000000000{{Ahc}Cl{{Eb{Eh}}}}{{fc}f{{Eb{Eh}}}}``````","D":"Jb","p":[[10,"TransformMatrix",622],[5,"Rotation",0],[5,"Joint",0],[1,"reference"],[10,"Any",623],[0,"mut"],[5,"BoneId",0],[5,"BoneAxis",0],[5,"BakedParameters",624],[10,"CastFrom",625],[5,"Vector",0],[6,"BoneKind",0],[5,"JointId",0],[6,"BoneEnd",0],[1,"unit"],[6,"Ordering",626],[5,"Skeleton",0],[1,"f32"],[1,"usize"],[6,"Result",627],[10,"Deserializer",628],[5,"Bone",0],[6,"Option",629],[1,"bool"],[1,"str"],[5,"Formatter",630],[8,"Result",630],[5,"WidgetContext",631],[5,"Error",630],[5,"LabeledBoneKind",0],[1,"tuple"],[10,"Hasher",632],[5,"Box",633],[5,"Arc",634],[5,"Rc",635],[6,"ReadOnly",636],[6,"Value",636],[17,"Output"],[10,"FnMut",637],[5,"ZeroToOne",638],[10,"Into",639],[10,"Serializer",640],[5,"SmolStr",641],[5,"String",642],[5,"OutOfBounds",643],[5,"TypeId",623],[15,"Jointed",618],[15,"Rigid",618]],"r":[],"b":[[256,"impl-Display-for-Rotation"],[257,"impl-Debug-for-Rotation"],[318,"impl-Index%3CJointId%3E-for-Skeleton"],[319,"impl-Index%3CBoneId%3E-for-Skeleton"],[320,"impl-IndexMut%3CBoneId%3E-for-Skeleton"],[321,"impl-IndexMut%3CJointId%3E-for-Skeleton"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAB0CEgAQAAsAHQArAEwAZgC0AB0A0wAVAOsAEgAAAQsADQEAABgBNQBZAYEA4QEAAOQBAADoAQMA8AEJAAECAQAEAgYADAIBAA8CVwA="}]\
+["funnybones",{"t":"PPFFGFGFFPFPFFFNNNNNNNNNNNNNCNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOFPFGFPFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOO","n":["A","B","Bone","BoneAxis","BoneEnd","BoneId","BoneKind","Joint","JointId","Jointed","LabeledBoneKind","Rigid","Rotation","Skeleton","Vector","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","add","angle","animation","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","axis_a","axis_b","bone","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cast","cast","cast","cast","cast","cast","cast","cast","cast","cast","cast","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","cast_into","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","cmp","cmp","compare","compare","compare","compare","components_from","components_from","components_from","components_from","components_from","components_from","components_from","components_from","components_from","components_from","components_from","default","default","default","degrees","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","desired_end","downcast","downcast","downcast","downcast","downcast","downcast","downcast","downcast","downcast","downcast","downcast","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","end","end","eq","eq","eq","eq","eq","eq","eq","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","find_bone_by_label","find_joint_by_label","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_angle","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_cast","from_components","from_parts","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","hash","hash","hash","hash","index","index","index_mut","index_mut","init","init","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","into","into","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_angle","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_components","into_components","into_components","into_components","into_components","into_components","into_components","into_components","into_parts","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","inverse","inverse","kind","label","label","label","lerp","magnitude","map","neg","new","new","other_axis","partial_cmp","partial_cmp","partial_cmp","percent_between","push_bone","push_joint","radians","rotation","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","set_angle","set_desired_end","set_rotation","set_translation","solve","solved_joint","start","sub","sub","to_degrees","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_radians","to_smolstr","to_string","translation","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_from","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","uints_into","upcast","upcast","upcast","upcast","upcast","upcast","upcast","upcast","upcast","upcast","upcast","with_label","with_label","x","y","end_length","inverse","length","start_length","Animation","Bone","Change","ChangeKind","Frame","Joint","RunningAnimation","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","adapt_into_using","arrays_from","arrays_from","arrays_from","arrays_from","arrays_from","arrays_into","arrays_into","arrays_into","arrays_into","arrays_into","as_any","as_any","as_any","as_any","as_any","as_any_mut","as_any_mut","as_any_mut","as_any_mut","as_any_mut","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cam16_into_unclamped","cast","cast","cast","cast","cast","cast_into","cast_into","cast_into","cast_into","cast_into","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_to_uninit","clone_to_uninit","clone_to_uninit","clone_to_uninit","components_from","components_from","components_from","components_from","components_from","default","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","downcast","downcast","downcast","downcast","downcast","drop","drop","drop","drop","drop","duration","eq","eq","eq","eq","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from_angle","from_angle","from_angle","from_angle","from_angle","from_cast","from_cast","from_cast","from_cast","from_cast","from_stimulus","from_stimulus","from_stimulus","from_stimulus","from_stimulus","init","init","init","init","init","insert","into","into","into","into","into","into_angle","into_angle","into_angle","into_angle","into_angle","into_any","into_any","into_any","into_any","into_any","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_arc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_cam16_unclamped","into_color","into_color","into_color","into_color","into_color","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_color_unclamped","into_components","into_components","into_read_only","into_read_only","into_read_only","into_read_only","into_read_only","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_stimulus","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","into_value","looping","new","push","push_change","remove","serialize","serialize","serialize","set_duration","set_variable","start","to_owned","to_owned","to_owned","to_owned","try_components_into","try_components_into","try_components_into","try_components_into","try_components_into","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into_color","try_into_color","try_into_color","try_into_color","try_into_color","type_id","type_id","type_id","type_id","type_id","uints_from","uints_from","uints_from","uints_from","uints_from","uints_into","uints_into","uints_into","uints_into","uints_into","upcast","upcast","upcast","upcast","upcast","update","variable","with","with_change","with_easing","with_variable","bone","joint","position","rotation"],"q":[[0,"funnybones"],[612,"funnybones::BoneKind"],[616,"funnybones::animation"],[877,"funnybones::animation::ChangeKind"],[881,"palette::chromatic_adaptation"],[882,"core::any"],[883,"palette::cam16::parameters"],[884,"intentional::cast"],[885,"core::cmp"],[886,"core::result"],[887,"serde::de"],[888,"core::option"],[889,"core::fmt"],[890,"cushy::context"],[891,"core::hash"],[892,"alloc::boxed"],[893,"alloc::sync"],[894,"alloc::rc"],[895,"cushy::value"],[896,"core::ops::function"],[897,"cushy::animation"],[898,"core::convert"],[899,"serde::ser"],[900,"smol_str"],[901,"alloc::string"],[902,"palette::convert::try_from_into_color"],[903,"core::time"],[904,"alloc::borrow"],[905,"easing_function::easings"]],"i":[14,14,0,0,0,0,0,0,0,12,0,12,0,0,0,30,11,2,12,17,8,22,3,7,13,14,2,3,0,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,7,7,8,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,11,2,12,8,7,13,14,11,2,12,8,7,13,14,11,2,12,8,7,13,14,7,13,7,7,13,13,30,11,2,12,17,8,22,3,7,13,14,11,2,17,2,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,11,2,12,17,8,7,13,14,22,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,22,8,11,2,12,8,7,13,14,8,8,8,7,7,7,13,13,13,14,14,14,17,17,11,2,2,2,12,17,8,22,3,7,13,14,30,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,11,2,30,11,2,12,17,8,22,3,7,13,14,8,7,13,14,17,17,17,17,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,11,11,2,12,8,7,13,14,2,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,30,11,11,2,2,12,12,17,17,8,8,22,22,3,3,7,7,13,13,14,14,8,14,30,22,3,30,2,11,11,2,11,3,3,2,7,13,2,17,17,2,17,11,2,12,17,8,22,3,7,13,14,3,22,17,17,17,22,22,11,2,2,11,2,12,8,7,13,14,2,2,2,17,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,30,11,2,12,17,8,22,3,7,13,14,12,3,11,11,55,55,56,55,0,50,0,0,0,50,0,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,47,48,49,50,47,48,49,50,47,48,49,50,52,47,48,49,50,47,52,47,47,48,48,49,50,52,47,47,48,48,49,50,48,49,50,52,47,48,49,50,52,47,48,49,50,48,47,48,49,50,47,48,49,50,52,47,48,49,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,47,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,49,50,52,47,48,49,50,52,47,48,49,50,52,52,47,47,48,48,49,49,50,50,52,48,47,48,47,48,49,50,48,47,47,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,48,49,50,52,47,47,48,50,47,57,58,57,58],"f":"```````````````{eg{}{{b{c}}}{}}0000000000{{dd}c{}}{{{h{f}}}d}`{ce{}{}}0000000000{{}c{}}0000000000{h{{h{j}}}}0000000000{{{h{l}}}{{h{lj}}}}0000000000{nA`}0`{h{{h{c}}}{}}0000000000{{{h{l}}}{{h{lc}}}{}}0000000000{{{Ab{c}}}e{}{}}0000000000{{}e{}{{Ad{c}}}}000000000077777777777{{{h{Af}}}Af}{{{h{d}}}d}{{{h{Ah}}}Ah}{{{h{A`}}}A`}{{{h{n}}}n}{{{h{Aj}}}Aj}{{{h{Al}}}Al}{{h{h{lc}}}An{}}000000{hAn}000000{{{h{n}}{h{n}}}B`}{{{h{Aj}}{h{Aj}}}B`}{{h{h{c}}}B`{}}000{ce{}{}}0000000000{{}Af}{{}d}{{}Bb}{Bdd}{Bf{{h{c}}}{}}0000000000{Bf{{h{lc}}}{}}0000000000{c{{Bh{Af}}}Bj}{c{{Bh{d}}}Bj}{c{{Bh{Ah}}}Bj}{c{{Bh{Bb}}}Bj}{c{{Bh{A`}}}Bj}{c{{Bh{n}}}Bj}{c{{Bh{Aj}}}Bj}{c{{Bh{Al}}}Bj}{{{h{Bl}}}{{Bn{Af}}}}{h{{h{c}}}{}}0000000000{BfAn}0000000000{{{h{Bl}}}Af}`{{{h{Af}}{h{Af}}}C`}{{{h{d}}{h{d}}}C`}{{{h{Ah}}{h{Ah}}}C`}{{{h{A`}}{h{A`}}}C`}{{{h{n}}{h{n}}}C`}{{{h{Aj}}{h{Aj}}}C`}{{{h{Al}}{h{Al}}}C`}{{h{h{c}}}C`{}}00000000000{{{h{Bb}}{h{Cb}}}{{Bn{n}}}}{{{h{Bb}}{h{Cb}}}{{Bn{Aj}}}}{{{h{Af}}{h{lCd}}}Cf}{{h{h{Ch}}{h{lCd}}}{{Bh{AnCj}}}}{{{h{d}}{h{lCd}}}Cf}0{{{h{Ah}}{h{lCd}}}Cf}{{{h{Bb}}{h{lCd}}}Cf}{{{h{A`}}{h{lCd}}}Cf}{{{h{Bl}}{h{lCd}}}Cf}{{{h{f}}{h{lCd}}}Cf}{{{h{n}}{h{lCd}}}Cf}{{{h{Aj}}{h{lCd}}}Cf}{{{h{Al}}{h{lCd}}}Cf}{AhCl}{cc{}}00000000000000000000000000000000{{{Cn{BdBd}}}Af}{Bnc{}}{ce{}{}}0000000000{{{h{A`}}{h{lc}}}AnD`}{{{h{n}}{h{lc}}}AnD`}{{{h{Aj}}{h{lc}}}AnD`}{{{h{Al}}{h{lc}}}AnD`}{{{h{Bb}}Aj}{{h{c}}}{}}{{{h{Bb}}n}{{h{c}}}{}}{{{h{lBb}}Aj}{{h{lc}}}{}}{{{h{lBb}}n}{{h{lc}}}{}}{{}Bf}0000000000{{}c{}}000000000000000000000{{{Db{c}}}{{Db{j}}}{}}0000000000{{{Dd{c}}}{{Dd{j}}}{}}0000000000{{{Df{c}}}{{Df{j}}}{}}0000000000{{{Ab{c}}}e{}{}}00000000004444444444444444444444{{}{{Cn{cc}}}{}}{Af{{Cn{BdBd}}}}111111{{}{{Cn{Bn}}}}{{}{{Dh{c}}}{}}000000000088888888888{{}{{Dj{c}}}{}}{{}{{Dj{{Bn{c}}}}}{}}10101010101001100101{A`A`}{AlAl}`{{{h{Bl}}}{{h{Cb}}}}{{{h{f}}}{{h{Cb}}}}`{{{h{d}}{h{d}}Bd}d}{{{h{Af}}}Bd}{{Afc}Af{{Dn{Bd}{{Dl{Bd}}}}}}{dc{}}{{BdBd}Af}{{dA`A`}f}{{{h{f}}A`}A`}{{{h{d}}{h{d}}}{{Bn{B`}}}}{{{h{n}}{h{n}}}{{Bn{B`}}}}{{{h{Aj}}{h{Aj}}}{{Bn{B`}}}}{{{h{d}}{h{d}}{h{d}}}E`}{{{h{lBb}}c}n{{Eb{Cl}}}}{{{h{lBb}}f}Aj}{Bdd}{{{h{Bb}}}d}{{{h{Af}}c}BhEd}{{{h{d}}c}BhEd}{{{h{Ah}}c}BhEd}{{{h{Bb}}c}BhEd}{{{h{A`}}c}BhEd}{{{h{Bl}}c}BhEd}{{{h{f}}c}BhEd}{{{h{n}}c}BhEd}{{{h{Aj}}c}BhEd}{{{h{Al}}c}BhEd}{{{h{lf}}d}An}{{{h{lBl}}{Bn{Af}}}An}{{{h{lBb}}d}An}{{{h{lBb}}Af}An}{{{h{lBb}}}An}{{{h{Bl}}}{{Bn{Af}}}}{{{h{Bl}}}Af}{{AfAf}c{}}{{dd}c{}}{dBd}{hc{}}0000001{hEf}{hEh}{{{h{Bb}}}Af}{{}{{Bh{c}}}{}}0000000000{c{{Bh{e}}}{}{}}000000000011111111111{{}{{Bh{c{Ej{c}}}}}{}}0000000000{hEl}0000000000{ce{}{}}0000000000{{}c{}}0000000000{h{{Bn{{h{c}}}}}{}}0000000000{{Ahc}Cl{{Eb{Eh}}}}{{fc}f{{Eb{Eh}}}}`````````````{eg{}{{b{c}}}{}}00005555544444{h{{h{j}}}}0000{{{h{l}}}{{h{lj}}}}0000{h{{h{c}}}{}}0000{{{h{l}}}{{h{lc}}}{}}0000{{{Ab{c}}}e{}{}}0000{{}e{}{{Ad{c}}}}0000:::::{{{h{En}}}En}{{{h{F`}}}F`}{{{h{Fb}}}Fb}{{{h{Fd}}}Fd}{{h{h{lc}}}An{}}000{hAn}000{ce{}{}}0000{{}En}{Bf{{h{c}}}{}}{{{h{En}}}{{h{c}}}{}}11{{{h{F`}}}{{h{c}}}{}}22{Bf{{h{lc}}}{}}0{{{h{lEn}}}{{h{lc}}}{}}1{{{h{lF`}}}{{h{lc}}}{}}22{c{{Bh{F`}}}Bj}{c{{Bh{Fb}}}Bj}{c{{Bh{Fd}}}Bj}{h{{h{c}}}{}}0000{BfAn}0000{{{h{F`}}}Ff}{{{h{En}}{h{En}}}C`}{{{h{F`}}{h{F`}}}C`}{{{h{Fb}}{h{Fb}}}C`}{{{h{Fd}}{h{Fd}}}C`}{{{h{En}}{h{lCd}}}Cf}{{{h{F`}}{h{lCd}}}Cf}{{{h{Fb}}{h{lCd}}}Cf}{{{h{Fd}}{h{lCd}}}Cf}{cc{}}000{FdFb}11111111111{ce{}{}}0000{{}Bf}0000{{{h{lEn}}BfF`}An}{{}c{}}000000000{{{Db{c}}}{{Db{j}}}{}}0000{{{Dd{c}}}{{Dd{j}}}{}}0000{{{Df{c}}}{{Df{j}}}{}}0000{{{Ab{c}}}e{}{}}00004444444444{{}{{Cn{cc}}}{}}0{{}{{Dh{c}}}{}}000066666{{}{{Dj{{Bn{c}}}}}{}}{{}{{Dj{c}}}{}}01101010{FhFh}{FfF`}{{{h{lEn}}F`}An}{{{h{lF`}}c}An{{Eb{Fb}}}}{{{h{lEn}}Bf}F`}{{{h{F`}}c}BhEd}{{{h{Fb}}c}BhEd}{{{h{Fd}}c}BhEd}{{{h{lF`}}Ff}An}{{{h{lEn}}cBd}An{{Eb{{Fj{Cb}}}}}}{{{h{En}}}Fh}{hc{}}000{{}{{Bh{c}}}{}}0000{c{{Bh{e}}}{}{}}000011111{{}{{Bh{c{Ej{c}}}}}{}}0000{hEl}0000{ce{}{}}0000{{}c{}}0000{h{{Bn{{h{c}}}}}{}}0000{{{h{lFh}}Ff{h{lBb}}}C`}{{{h{En}}{h{Cb}}}{{Bn{Bd}}}}{{EnF`}En}{{F`c}F`{{Eb{Fb}}}}{{FdFl}Fb}{{EncBd}En{{Eb{Eh}}}}````","D":"Kf","p":[[10,"TransformMatrix",881],[5,"Rotation",0],[5,"Joint",0],[1,"reference"],[10,"Any",882],[0,"mut"],[5,"BoneId",0],[5,"BoneAxis",0],[5,"BakedParameters",883],[10,"CastFrom",884],[5,"Vector",0],[6,"BoneKind",0],[5,"JointId",0],[6,"BoneEnd",0],[1,"unit"],[6,"Ordering",885],[5,"Skeleton",0],[1,"f32"],[1,"usize"],[6,"Result",886],[10,"Deserializer",887],[5,"Bone",0],[6,"Option",888],[1,"bool"],[1,"str"],[5,"Formatter",889],[8,"Result",889],[5,"WidgetContext",890],[5,"Error",889],[5,"LabeledBoneKind",0],[1,"tuple"],[10,"Hasher",891],[5,"Box",892],[5,"Arc",893],[5,"Rc",894],[6,"ReadOnly",895],[6,"Value",895],[17,"Output"],[10,"FnMut",896],[5,"ZeroToOne",897],[10,"Into",898],[10,"Serializer",899],[5,"SmolStr",900],[5,"String",901],[5,"OutOfBounds",902],[5,"TypeId",882],[5,"Animation",616],[5,"Frame",616],[5,"Change",616],[6,"ChangeKind",616],[5,"Duration",903],[5,"RunningAnimation",616],[6,"Cow",904],[6,"StandardEasing",905],[15,"Jointed",612],[15,"Rigid",612],[15,"Bone",877],[15,"Joint",877]],"r":[],"b":[[251,"impl-Display-for-Rotation"],[252,"impl-Debug-for-Rotation"],[312,"impl-Index%3CJointId%3E-for-Skeleton"],[313,"impl-Index%3CBoneId%3E-for-Skeleton"],[314,"impl-IndexMut%3CJointId%3E-for-Skeleton"],[315,"impl-IndexMut%3CBoneId%3E-for-Skeleton"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAABYDFQAQAAsAHQAsAE0AXwCuAB0AzQAVAOUAEgD6AAwAEgE1AFMBgQDbAQAA3gEAAOIBAwDqAQkA+wEBAP4BBgAGAgEACQJXAGkCbgDcAgAA3gIUAPgCeQA="}]\
]'));
if (typeof exports !== 'undefined') exports.searchIndex = searchIndex;
else if (window.initSearch) window.initSearch(searchIndex);
diff --git a/main/search.desc/funnybones/funnybones-desc-0-.js b/main/search.desc/funnybones/funnybones-desc-0-.js
index 64a6aff..e700f1f 100644
--- a/main/search.desc/funnybones/funnybones-desc-0-.js
+++ b/main/search.desc/funnybones/funnybones-desc-0-.js
@@ -1 +1 @@
-searchState.loadedDescShard("funnybones", 0, "FunnyBones is considered experimental and unsupported …\nThe first end of a bone.\nThe second end of a bone.\nA bone in a Skeleton
.\nA specific end of a specific bone.\nA specific end of a Bone
.\nThe unique ID of a Bone
in a Skeleton
.\nA representation of a bone structure inside of a Skeleton
.\nA connection between two bones.\nThe unique ID of a Joint
in a Skeleton
.\nTwo bones connected with a joint that automatically …\nA BoneKind
with an associated label.\nA single bone of a fixed length.\nA value representing a rotation between no rotation and a …\nA collection of Bone
s. connected by Joint
s.\nA two dimensionsional offset/measurement.\nReturns the rotation of this joint.\nReturns the first axis of this bone.\nReturns the second axis of this bone.\nThe unique id of the bone of this axis.\nReturns a rotation representing the given degrees.\nReturns the location this bone is being aimed towards.\nReturns the solved end position of this bone.\nThe end of the bone being referenced.\nFinds an existing Bone
by its label.\nFinds an existing Joint
by its label.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nReturns the opposite axis on the same bone.\nReturns the opposite end of self
.\nThe bone to create.\nReturns the label this bone was created with.\nReturns the label of this joint.\nThe label of the bone.\nReturns the magnitude of this vector.\nReturns the result of mapping x
and y
to f
.\nReturns a new vector from the x and y values.\nReturns a new joint formed by joining bone_a
and bone_b
at …\nGiven axis
is one of the two connections in this joint, …\nCreates a new Bone
into the skeleton. Returns the unique …\nCreates a new Joint
in the skeleton, connecting two bones …\nReturns a rotation representing the given radians.\nReturns the base rotation being applied to the entire …\nSets the angle to form between these joints.\nSets the location to aim the end of this bone towards.\nSets a base rotation to apply to the entire skeleton.\nSets a translation to be applied to the entire skeleton.\nUpdates the solved positions of all bones in this skeleton …\nIf this is a BoneKind::Jointed
bone, returns the solved …\nReturns the solved start position of this bone.\nReturns this rotation represented in degrees.\nReturns this rotation represented in radians.\nReturns the translation applied to the entire skeleton.\nAttaches a label to this bone when pushed into a skeleton.\nLabels this joint and returns self.\nThe x-axis component of this vector.\nThe y-axis component of this vector.\nThe length of the bone connected furthes from the root of …\nThe bend of the simulated joint always goes in one of two …\nThe length of the bone.\nThe length of the bone connected closest to the root of the")
\ No newline at end of file
+searchState.loadedDescShard("funnybones", 0, "FunnyBones is considered experimental and unsupported …\nThe first end of a bone.\nThe second end of a bone.\nA bone in a Skeleton
.\nA specific end of a specific bone.\nA specific end of a Bone
.\nThe unique ID of a Bone
in a Skeleton
.\nA representation of a bone structure inside of a Skeleton
.\nA connection between two bones.\nThe unique ID of a Joint
in a Skeleton
.\nTwo bones connected with a joint that automatically …\nA BoneKind
with an associated label.\nA single bone of a fixed length.\nA value representing a rotation between no rotation and a …\nA collection of Bone
s. connected by Joint
s.\nA two dimensionsional offset/measurement.\nReturns the rotation of this joint.\nReturns the first axis of this bone.\nReturns the second axis of this bone.\nThe unique id of the bone of this axis.\nReturns a rotation representing the given degrees.\nReturns the location this bone is being aimed towards.\nReturns the solved end position of this bone.\nThe end of the bone being referenced.\nFinds an existing Bone
by its label.\nFinds an existing Joint
by its label.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nReturns the opposite axis on the same bone.\nReturns the opposite end of self
.\nThe bone to create.\nReturns the label this bone was created with.\nReturns the label of this joint.\nThe label of the bone.\nReturns the magnitude of this vector.\nReturns the result of mapping x
and y
to f
.\nReturns a new vector from the x and y values.\nReturns a new joint formed by joining bone_a
and bone_b
at …\nGiven axis
is one of the two connections in this joint, …\nCreates a new Bone
into the skeleton. Returns the unique …\nCreates a new Joint
in the skeleton, connecting two bones …\nReturns a rotation representing the given radians.\nReturns the base rotation being applied to the entire …\nSets the angle to form between these joints.\nSets the location to aim the end of this bone towards.\nSets a base rotation to apply to the entire skeleton.\nSets a translation to be applied to the entire skeleton.\nUpdates the solved positions of all bones in this skeleton …\nIf this is a BoneKind::Jointed
bone, returns the solved …\nReturns the solved start position of this bone.\nReturns this rotation represented in degrees.\nReturns this rotation represented in radians.\nReturns the translation applied to the entire skeleton.\nAttaches a label to this bone when pushed into a skeleton.\nLabels this joint and returns self.\nThe x-axis component of this vector.\nThe y-axis component of this vector.\nThe length of the bone connected furthes from the root of …\nThe bend of the simulated joint always goes in one of two …\nThe length of the bone.\nThe length of the bone connected closest to the root of the\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.\nCalls U::from(self)
.")
\ No newline at end of file
diff --git a/main/settings.html b/main/settings.html
index a830a1c..64b7f77 100644
--- a/main/settings.html
+++ b/main/settings.html
@@ -1 +1 @@
-Settings Rustdoc settings
Back
\ No newline at end of file
+Settings Rustdoc settings
Back
\ No newline at end of file
diff --git a/main/src-files.js b/main/src-files.js
index cedf492..1728f46 100644
--- a/main/src-files.js
+++ b/main/src-files.js
@@ -1,4 +1,4 @@
var srcIndex = new Map(JSON.parse('[\
-["funnybones",["",[],["lib.rs","serde.rs"]]]\
+["funnybones",["",[],["animation.rs","lib.rs","serde.rs"]]]\
]'));
createSrcSidebar();
diff --git a/main/src/funnybones/animation.rs.html b/main/src/funnybones/animation.rs.html
new file mode 100644
index 0000000..4ce61d1
--- /dev/null
+++ b/main/src/funnybones/animation.rs.html
@@ -0,0 +1,633 @@
+animation.rs - source 1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+
#![allow(missing_docs)]
+use std::{
+ borrow::Cow,
+ collections::HashMap,
+ ops::{Deref, DerefMut},
+ sync::Arc,
+ time::Duration,
+};
+
+use easing_function::{easings::StandardEasing, Easing};
+
+use crate::{BoneId, JointId, Rotation, Skeleton, Vector};
+
+#[derive(Default, Debug, PartialEq, Clone)]
+pub struct Animation(Arc<AnimationData>);
+
+impl Animation {
+ fn data_mut(&mut self) -> &mut AnimationData {
+ Arc::make_mut(&mut self.0)
+ }
+
+ pub fn push(&mut self, frame: Frame) {
+ self.data_mut().frames.push(frame);
+ }
+
+ #[must_use]
+ pub fn with(mut self, frame: Frame) -> Self {
+ self.push(frame);
+ self
+ }
+
+ pub fn remove(&mut self, frame_index: usize) -> Frame {
+ self.data_mut().frames.remove(frame_index)
+ }
+
+ pub fn insert(&mut self, index: usize, frame: Frame) {
+ self.data_mut().frames.insert(index, frame);
+ }
+
+ #[must_use]
+ pub fn with_variable(mut self, name: impl Into<String>, value: f32) -> Self {
+ self.set_variable(name.into(), value);
+ self
+ }
+
+ pub fn set_variable<'a>(&mut self, name: impl Into<Cow<'a, str>>, value: f32) {
+ match name.into() {
+ Cow::Owned(name) => {
+ self.data_mut().variables.insert(name, value);
+ }
+ Cow::Borrowed(name) => {
+ if let Some(var) = self.data_mut().variables.get_mut(name) {
+ *var = value;
+ } else {
+ self.data_mut().variables.insert(name.to_string(), value);
+ }
+ }
+ }
+ }
+
+ #[must_use]
+ pub fn variable(&self, name: &str) -> Option<f32> {
+ self.0.variables.get(name).copied()
+ }
+
+ #[must_use]
+ pub fn start(&self) -> RunningAnimation {
+ RunningAnimation {
+ animation: self.clone(),
+ frame_elapsed: Duration::ZERO,
+ frame: 0,
+ repeat: false,
+ frame_props: Vec::new(),
+ }
+ }
+}
+
+impl Deref for Animation {
+ type Target = [Frame];
+
+ fn deref(&self) -> &Self::Target {
+ &self.0.frames
+ }
+}
+
+impl DerefMut for Animation {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.data_mut().frames
+ }
+}
+
+#[derive(Default, Debug, PartialEq, Clone)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(feature = "serde", serde(rename = "Animation"))]
+struct AnimationData {
+ variables: HashMap<String, f32>,
+ frames: Vec<Frame>,
+}
+
+#[derive(Debug, PartialEq, Clone)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub struct Frame {
+ duration: Duration,
+ changes: Vec<Change>,
+}
+
+impl Frame {
+ #[must_use]
+ pub const fn new(duration: Duration) -> Self {
+ Self {
+ duration,
+ changes: Vec::new(),
+ }
+ }
+
+ pub fn set_duration(&mut self, duration: Duration) {
+ self.duration = duration;
+ }
+
+ #[must_use]
+ pub const fn duration(&self) -> Duration {
+ self.duration
+ }
+
+ #[must_use]
+ pub fn with_change(mut self, change: impl Into<Change>) -> Self {
+ self.push_change(change.into());
+ self
+ }
+
+ pub fn push_change(&mut self, change: impl Into<Change>) {
+ self.changes.push(change.into());
+ }
+}
+
+impl Deref for Frame {
+ type Target = [Change];
+
+ fn deref(&self) -> &Self::Target {
+ &self.changes
+ }
+}
+
+impl DerefMut for Frame {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.changes
+ }
+}
+
+#[derive(Debug, PartialEq, Clone, Copy)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub struct Change {
+ kind: ChangeKind,
+ easing: StandardEasing,
+}
+
+impl From<ChangeKind> for Change {
+ fn from(kind: ChangeKind) -> Self {
+ Self {
+ kind,
+ easing: StandardEasing::Linear,
+ }
+ }
+}
+
+#[derive(Debug, PartialEq, Clone, Copy)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub enum ChangeKind {
+ Bone { bone: BoneId, position: Vector },
+ Joint { joint: JointId, rotation: Rotation },
+}
+
+impl ChangeKind {
+ #[must_use]
+ pub const fn with_easing(self, easing: StandardEasing) -> Change {
+ Change { kind: self, easing }
+ }
+}
+
+enum OriginalProperty {
+ Rotation(Rotation),
+ Vector(Vector),
+}
+
+pub struct RunningAnimation {
+ animation: Animation,
+ frame: usize,
+ frame_elapsed: Duration,
+ repeat: bool,
+ frame_props: Vec<OriginalProperty>,
+}
+
+impl RunningAnimation {
+ #[must_use]
+ pub fn looping(mut self) -> Self {
+ self.repeat = true;
+ self
+ }
+
+ pub fn update(&mut self, elapsed: Duration, skeleton: &mut Skeleton) -> bool {
+ loop {
+ let Some(frame) = self.animation.get(self.frame) else {
+ return false;
+ };
+
+ self.frame_elapsed += elapsed;
+ if let Some(after_frame) = self.frame_elapsed.checked_sub(frame.duration) {
+ self.frame_elapsed = after_frame;
+ self.frame += 1;
+ self.frame_props.clear();
+ if self.frame == self.animation.len() && self.repeat {
+ self.frame = 0;
+ }
+ // Ensure all of the changes are fully tweened.
+ for change in &frame.changes {
+ match change.kind {
+ ChangeKind::Bone {
+ bone,
+ position: target,
+ } => {
+ skeleton[bone].set_desired_end(Some(target));
+ }
+
+ ChangeKind::Joint {
+ joint,
+ rotation: target,
+ } => {
+ skeleton[joint].set_angle(target);
+ }
+ }
+ }
+ } else {
+ // If this is the start of the frame, grab the currrent values
+ // to tween towards the next keyframe.
+ if self.frame_props.len() != frame.changes.len() {
+ self.frame_props.clear();
+ self.frame_props.reserve(frame.changes.len());
+ for change in &frame.changes {
+ self.frame_props.push(match change.kind {
+ ChangeKind::Bone { bone, .. } => {
+ OriginalProperty::Vector(skeleton[bone].end())
+ }
+
+ ChangeKind::Joint { joint, .. } => {
+ OriginalProperty::Rotation(skeleton[joint].angle())
+ }
+ });
+ }
+ }
+
+ let percent = self.frame_elapsed.as_secs_f32() / frame.duration.as_secs_f32();
+ for (change, original) in frame.changes.iter().zip(&self.frame_props) {
+ let factor = change.easing.ease(percent);
+ match (change.kind, original) {
+ (
+ ChangeKind::Bone {
+ bone,
+ position: target,
+ },
+ OriginalProperty::Vector(original),
+ ) => {
+ skeleton[bone].set_desired_end(Some(original.lerp(target, factor)));
+ }
+ (
+ ChangeKind::Joint {
+ joint,
+ rotation: target,
+ },
+ OriginalProperty::Rotation(original),
+ ) => {
+ skeleton[joint].set_angle(original.lerp(target, factor));
+ }
+ _ => unreachable!(),
+ }
+ }
+ return true;
+ }
+ }
+ }
+}
+
+trait Lerp: Sized {
+ fn lerp(self, target: Self, percent: f32) -> Self;
+}
+
+impl Lerp for f32 {
+ fn lerp(self, target: Self, percent: f32) -> Self {
+ let delta = target - self;
+ self + delta * percent
+ }
+}
+
+impl Lerp for Vector {
+ fn lerp(self, target: Self, percent: f32) -> Self {
+ Vector::new(
+ self.x.lerp(target.x, percent),
+ self.y.lerp(target.y, percent),
+ )
+ }
+}
+
+impl Lerp for Rotation {
+ fn lerp(self, target: Self, percent: f32) -> Self {
+ let delta_neg = self.radians - target.radians;
+ let delta_pos = target.radians - self.radians;
+
+ Self::radians(
+ self.radians
+ + if delta_neg.abs() < delta_pos.abs() {
+ delta_neg * percent
+ } else {
+ delta_pos * percent
+ },
+ )
+ }
+}
+
\ No newline at end of file
diff --git a/main/src/funnybones/lib.rs.html b/main/src/funnybones/lib.rs.html
index 7f948d8..4d01654 100644
--- a/main/src/funnybones/lib.rs.html
+++ b/main/src/funnybones/lib.rs.html
@@ -1,4 +1,4 @@
-lib.rs - source 1
+lib.rs - source #![doc = include_str!(".crate-docs.md")]
use std::{
@@ -783,6 +784,7 @@
sync::Arc,
};
+pub mod animation;
#[cfg(feature = "serde")]
mod serde;
diff --git a/main/src/funnybones/serde.rs.html b/main/src/funnybones/serde.rs.html
index c9b81f3..af4e5cf 100644
--- a/main/src/funnybones/serde.rs.html
+++ b/main/src/funnybones/serde.rs.html
@@ -1,4 +1,4 @@
-serde.rs - source 1
+serde.rs - source 1
2
3
4
diff --git a/main/trait.impl/core/clone/trait.Clone.js b/main/trait.impl/core/clone/trait.Clone.js
index 1693670..cc6f287 100644
--- a/main/trait.impl/core/clone/trait.Clone.js
+++ b/main/trait.impl/core/clone/trait.Clone.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Clone for BoneEnd"],["impl Clone for BoneKind"],["impl Clone for BoneAxis"],["impl Clone for BoneId"],["impl Clone for JointId"],["impl Clone for Rotation"],["impl Clone for Vector"]]
+"funnybones":[["impl Clone for ChangeKind"],["impl Clone for BoneEnd"],["impl Clone for BoneKind"],["impl Clone for Animation"],["impl Clone for Change"],["impl Clone for Frame"],["impl Clone for BoneAxis"],["impl Clone for BoneId"],["impl Clone for JointId"],["impl Clone for Rotation"],["impl Clone for Vector"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/cmp/trait.PartialEq.js b/main/trait.impl/core/cmp/trait.PartialEq.js
index 3aa09f9..f345e51 100644
--- a/main/trait.impl/core/cmp/trait.PartialEq.js
+++ b/main/trait.impl/core/cmp/trait.PartialEq.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl PartialEq for BoneEnd"],["impl PartialEq for BoneKind"],["impl PartialEq for BoneAxis"],["impl PartialEq for BoneId"],["impl PartialEq for JointId"],["impl PartialEq for Rotation"],["impl PartialEq for Vector"]]
+"funnybones":[["impl PartialEq for ChangeKind"],["impl PartialEq for BoneEnd"],["impl PartialEq for BoneKind"],["impl PartialEq for Animation"],["impl PartialEq for Change"],["impl PartialEq for Frame"],["impl PartialEq for BoneAxis"],["impl PartialEq for BoneId"],["impl PartialEq for JointId"],["impl PartialEq for Rotation"],["impl PartialEq for Vector"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/convert/trait.From.js b/main/trait.impl/core/convert/trait.From.js
index e733166..18ff028 100644
--- a/main/trait.impl/core/convert/trait.From.js
+++ b/main/trait.impl/core/convert/trait.From.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl From<BoneKind> for LabeledBoneKind"]]
+"funnybones":[["impl From<ChangeKind> for Change"],["impl From<BoneKind> for LabeledBoneKind"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/default/trait.Default.js b/main/trait.impl/core/default/trait.Default.js
index ceaec82..f7d4976 100644
--- a/main/trait.impl/core/default/trait.Default.js
+++ b/main/trait.impl/core/default/trait.Default.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Default for Rotation"],["impl Default for Skeleton"],["impl Default for Vector"]]
+"funnybones":[["impl Default for Animation"],["impl Default for Rotation"],["impl Default for Skeleton"],["impl Default for Vector"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/fmt/trait.Debug.js b/main/trait.impl/core/fmt/trait.Debug.js
index 468d7eb..856f5ef 100644
--- a/main/trait.impl/core/fmt/trait.Debug.js
+++ b/main/trait.impl/core/fmt/trait.Debug.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Debug for BoneEnd"],["impl Debug for BoneKind"],["impl Debug for Bone"],["impl Debug for BoneAxis"],["impl Debug for BoneId"],["impl Debug for Joint"],["impl Debug for JointId"],["impl Debug for Rotation"],["impl Debug for Skeleton"],["impl Debug for Vector"]]
+"funnybones":[["impl Debug for ChangeKind"],["impl Debug for BoneEnd"],["impl Debug for BoneKind"],["impl Debug for Animation"],["impl Debug for Change"],["impl Debug for Frame"],["impl Debug for Bone"],["impl Debug for BoneAxis"],["impl Debug for BoneId"],["impl Debug for Joint"],["impl Debug for JointId"],["impl Debug for Rotation"],["impl Debug for Skeleton"],["impl Debug for Vector"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/marker/trait.Copy.js b/main/trait.impl/core/marker/trait.Copy.js
index f53d96d..d0887a5 100644
--- a/main/trait.impl/core/marker/trait.Copy.js
+++ b/main/trait.impl/core/marker/trait.Copy.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Copy for BoneEnd"],["impl Copy for BoneKind"],["impl Copy for BoneAxis"],["impl Copy for BoneId"],["impl Copy for JointId"],["impl Copy for Rotation"],["impl Copy for Vector"]]
+"funnybones":[["impl Copy for ChangeKind"],["impl Copy for BoneEnd"],["impl Copy for BoneKind"],["impl Copy for Change"],["impl Copy for BoneAxis"],["impl Copy for BoneId"],["impl Copy for JointId"],["impl Copy for Rotation"],["impl Copy for Vector"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/marker/trait.Freeze.js b/main/trait.impl/core/marker/trait.Freeze.js
index 1d2ffb7..96657d2 100644
--- a/main/trait.impl/core/marker/trait.Freeze.js
+++ b/main/trait.impl/core/marker/trait.Freeze.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Freeze for BoneEnd",1,["funnybones::BoneEnd"]],["impl Freeze for BoneKind",1,["funnybones::BoneKind"]],["impl Freeze for Bone",1,["funnybones::Bone"]],["impl Freeze for BoneAxis",1,["funnybones::BoneAxis"]],["impl Freeze for BoneId",1,["funnybones::BoneId"]],["impl Freeze for Joint",1,["funnybones::Joint"]],["impl Freeze for JointId",1,["funnybones::JointId"]],["impl Freeze for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl Freeze for Rotation",1,["funnybones::Rotation"]],["impl Freeze for Skeleton",1,["funnybones::Skeleton"]],["impl Freeze for Vector",1,["funnybones::Vector"]]]
+"funnybones":[["impl Freeze for ChangeKind",1,["funnybones::animation::ChangeKind"]],["impl Freeze for BoneEnd",1,["funnybones::BoneEnd"]],["impl Freeze for BoneKind",1,["funnybones::BoneKind"]],["impl Freeze for Animation",1,["funnybones::animation::Animation"]],["impl Freeze for Change",1,["funnybones::animation::Change"]],["impl Freeze for Frame",1,["funnybones::animation::Frame"]],["impl Freeze for RunningAnimation",1,["funnybones::animation::RunningAnimation"]],["impl Freeze for Bone",1,["funnybones::Bone"]],["impl Freeze for BoneAxis",1,["funnybones::BoneAxis"]],["impl Freeze for BoneId",1,["funnybones::BoneId"]],["impl Freeze for Joint",1,["funnybones::Joint"]],["impl Freeze for JointId",1,["funnybones::JointId"]],["impl Freeze for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl Freeze for Rotation",1,["funnybones::Rotation"]],["impl Freeze for Skeleton",1,["funnybones::Skeleton"]],["impl Freeze for Vector",1,["funnybones::Vector"]]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/marker/trait.Send.js b/main/trait.impl/core/marker/trait.Send.js
index 93407bb..cfde7ad 100644
--- a/main/trait.impl/core/marker/trait.Send.js
+++ b/main/trait.impl/core/marker/trait.Send.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Send for BoneEnd",1,["funnybones::BoneEnd"]],["impl Send for BoneKind",1,["funnybones::BoneKind"]],["impl Send for Bone",1,["funnybones::Bone"]],["impl Send for BoneAxis",1,["funnybones::BoneAxis"]],["impl Send for BoneId",1,["funnybones::BoneId"]],["impl Send for Joint",1,["funnybones::Joint"]],["impl Send for JointId",1,["funnybones::JointId"]],["impl Send for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl Send for Rotation",1,["funnybones::Rotation"]],["impl Send for Skeleton",1,["funnybones::Skeleton"]],["impl Send for Vector",1,["funnybones::Vector"]]]
+"funnybones":[["impl Send for ChangeKind",1,["funnybones::animation::ChangeKind"]],["impl Send for BoneEnd",1,["funnybones::BoneEnd"]],["impl Send for BoneKind",1,["funnybones::BoneKind"]],["impl Send for Animation",1,["funnybones::animation::Animation"]],["impl Send for Change",1,["funnybones::animation::Change"]],["impl Send for Frame",1,["funnybones::animation::Frame"]],["impl Send for RunningAnimation",1,["funnybones::animation::RunningAnimation"]],["impl Send for Bone",1,["funnybones::Bone"]],["impl Send for BoneAxis",1,["funnybones::BoneAxis"]],["impl Send for BoneId",1,["funnybones::BoneId"]],["impl Send for Joint",1,["funnybones::Joint"]],["impl Send for JointId",1,["funnybones::JointId"]],["impl Send for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl Send for Rotation",1,["funnybones::Rotation"]],["impl Send for Skeleton",1,["funnybones::Skeleton"]],["impl Send for Vector",1,["funnybones::Vector"]]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/marker/trait.StructuralPartialEq.js b/main/trait.impl/core/marker/trait.StructuralPartialEq.js
index d4b5fea..efe323e 100644
--- a/main/trait.impl/core/marker/trait.StructuralPartialEq.js
+++ b/main/trait.impl/core/marker/trait.StructuralPartialEq.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl StructuralPartialEq for BoneEnd"],["impl StructuralPartialEq for BoneKind"],["impl StructuralPartialEq for BoneAxis"],["impl StructuralPartialEq for BoneId"],["impl StructuralPartialEq for JointId"],["impl StructuralPartialEq for Rotation"],["impl StructuralPartialEq for Vector"]]
+"funnybones":[["impl StructuralPartialEq for ChangeKind"],["impl StructuralPartialEq for BoneEnd"],["impl StructuralPartialEq for BoneKind"],["impl StructuralPartialEq for Animation"],["impl StructuralPartialEq for Change"],["impl StructuralPartialEq for Frame"],["impl StructuralPartialEq for BoneAxis"],["impl StructuralPartialEq for BoneId"],["impl StructuralPartialEq for JointId"],["impl StructuralPartialEq for Rotation"],["impl StructuralPartialEq for Vector"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/marker/trait.Sync.js b/main/trait.impl/core/marker/trait.Sync.js
index d4e675c..58f37d8 100644
--- a/main/trait.impl/core/marker/trait.Sync.js
+++ b/main/trait.impl/core/marker/trait.Sync.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Sync for BoneEnd",1,["funnybones::BoneEnd"]],["impl Sync for BoneKind",1,["funnybones::BoneKind"]],["impl Sync for Bone",1,["funnybones::Bone"]],["impl Sync for BoneAxis",1,["funnybones::BoneAxis"]],["impl Sync for BoneId",1,["funnybones::BoneId"]],["impl Sync for Joint",1,["funnybones::Joint"]],["impl Sync for JointId",1,["funnybones::JointId"]],["impl Sync for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl Sync for Rotation",1,["funnybones::Rotation"]],["impl Sync for Skeleton",1,["funnybones::Skeleton"]],["impl Sync for Vector",1,["funnybones::Vector"]]]
+"funnybones":[["impl Sync for ChangeKind",1,["funnybones::animation::ChangeKind"]],["impl Sync for BoneEnd",1,["funnybones::BoneEnd"]],["impl Sync for BoneKind",1,["funnybones::BoneKind"]],["impl Sync for Animation",1,["funnybones::animation::Animation"]],["impl Sync for Change",1,["funnybones::animation::Change"]],["impl Sync for Frame",1,["funnybones::animation::Frame"]],["impl Sync for RunningAnimation",1,["funnybones::animation::RunningAnimation"]],["impl Sync for Bone",1,["funnybones::Bone"]],["impl Sync for BoneAxis",1,["funnybones::BoneAxis"]],["impl Sync for BoneId",1,["funnybones::BoneId"]],["impl Sync for Joint",1,["funnybones::Joint"]],["impl Sync for JointId",1,["funnybones::JointId"]],["impl Sync for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl Sync for Rotation",1,["funnybones::Rotation"]],["impl Sync for Skeleton",1,["funnybones::Skeleton"]],["impl Sync for Vector",1,["funnybones::Vector"]]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/marker/trait.Unpin.js b/main/trait.impl/core/marker/trait.Unpin.js
index 6e8e785..902fced 100644
--- a/main/trait.impl/core/marker/trait.Unpin.js
+++ b/main/trait.impl/core/marker/trait.Unpin.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Unpin for BoneEnd",1,["funnybones::BoneEnd"]],["impl Unpin for BoneKind",1,["funnybones::BoneKind"]],["impl Unpin for Bone",1,["funnybones::Bone"]],["impl Unpin for BoneAxis",1,["funnybones::BoneAxis"]],["impl Unpin for BoneId",1,["funnybones::BoneId"]],["impl Unpin for Joint",1,["funnybones::Joint"]],["impl Unpin for JointId",1,["funnybones::JointId"]],["impl Unpin for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl Unpin for Rotation",1,["funnybones::Rotation"]],["impl Unpin for Skeleton",1,["funnybones::Skeleton"]],["impl Unpin for Vector",1,["funnybones::Vector"]]]
+"funnybones":[["impl Unpin for ChangeKind",1,["funnybones::animation::ChangeKind"]],["impl Unpin for BoneEnd",1,["funnybones::BoneEnd"]],["impl Unpin for BoneKind",1,["funnybones::BoneKind"]],["impl Unpin for Animation",1,["funnybones::animation::Animation"]],["impl Unpin for Change",1,["funnybones::animation::Change"]],["impl Unpin for Frame",1,["funnybones::animation::Frame"]],["impl Unpin for RunningAnimation",1,["funnybones::animation::RunningAnimation"]],["impl Unpin for Bone",1,["funnybones::Bone"]],["impl Unpin for BoneAxis",1,["funnybones::BoneAxis"]],["impl Unpin for BoneId",1,["funnybones::BoneId"]],["impl Unpin for Joint",1,["funnybones::Joint"]],["impl Unpin for JointId",1,["funnybones::JointId"]],["impl Unpin for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl Unpin for Rotation",1,["funnybones::Rotation"]],["impl Unpin for Skeleton",1,["funnybones::Skeleton"]],["impl Unpin for Vector",1,["funnybones::Vector"]]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/ops/deref/trait.Deref.js b/main/trait.impl/core/ops/deref/trait.Deref.js
new file mode 100644
index 0000000..f45facd
--- /dev/null
+++ b/main/trait.impl/core/ops/deref/trait.Deref.js
@@ -0,0 +1,3 @@
+(function() {var implementors = {
+"funnybones":[["impl Deref for Animation"],["impl Deref for Frame"]]
+};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/ops/deref/trait.DerefMut.js b/main/trait.impl/core/ops/deref/trait.DerefMut.js
new file mode 100644
index 0000000..1142645
--- /dev/null
+++ b/main/trait.impl/core/ops/deref/trait.DerefMut.js
@@ -0,0 +1,3 @@
+(function() {var implementors = {
+"funnybones":[["impl DerefMut for Animation"],["impl DerefMut for Frame"]]
+};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js b/main/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js
index fbaed67..4764451 100644
--- a/main/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js
+++ b/main/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl RefUnwindSafe for BoneEnd",1,["funnybones::BoneEnd"]],["impl RefUnwindSafe for BoneKind",1,["funnybones::BoneKind"]],["impl RefUnwindSafe for Bone",1,["funnybones::Bone"]],["impl RefUnwindSafe for BoneAxis",1,["funnybones::BoneAxis"]],["impl RefUnwindSafe for BoneId",1,["funnybones::BoneId"]],["impl RefUnwindSafe for Joint",1,["funnybones::Joint"]],["impl RefUnwindSafe for JointId",1,["funnybones::JointId"]],["impl RefUnwindSafe for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl RefUnwindSafe for Rotation",1,["funnybones::Rotation"]],["impl RefUnwindSafe for Skeleton",1,["funnybones::Skeleton"]],["impl RefUnwindSafe for Vector",1,["funnybones::Vector"]]]
+"funnybones":[["impl RefUnwindSafe for ChangeKind",1,["funnybones::animation::ChangeKind"]],["impl RefUnwindSafe for BoneEnd",1,["funnybones::BoneEnd"]],["impl RefUnwindSafe for BoneKind",1,["funnybones::BoneKind"]],["impl RefUnwindSafe for Animation",1,["funnybones::animation::Animation"]],["impl RefUnwindSafe for Change",1,["funnybones::animation::Change"]],["impl RefUnwindSafe for Frame",1,["funnybones::animation::Frame"]],["impl RefUnwindSafe for RunningAnimation",1,["funnybones::animation::RunningAnimation"]],["impl RefUnwindSafe for Bone",1,["funnybones::Bone"]],["impl RefUnwindSafe for BoneAxis",1,["funnybones::BoneAxis"]],["impl RefUnwindSafe for BoneId",1,["funnybones::BoneId"]],["impl RefUnwindSafe for Joint",1,["funnybones::Joint"]],["impl RefUnwindSafe for JointId",1,["funnybones::JointId"]],["impl RefUnwindSafe for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl RefUnwindSafe for Rotation",1,["funnybones::Rotation"]],["impl RefUnwindSafe for Skeleton",1,["funnybones::Skeleton"]],["impl RefUnwindSafe for Vector",1,["funnybones::Vector"]]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js b/main/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js
index a23e0db..63fde79 100644
--- a/main/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js
+++ b/main/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl UnwindSafe for BoneEnd",1,["funnybones::BoneEnd"]],["impl UnwindSafe for BoneKind",1,["funnybones::BoneKind"]],["impl UnwindSafe for Bone",1,["funnybones::Bone"]],["impl UnwindSafe for BoneAxis",1,["funnybones::BoneAxis"]],["impl UnwindSafe for BoneId",1,["funnybones::BoneId"]],["impl UnwindSafe for Joint",1,["funnybones::Joint"]],["impl UnwindSafe for JointId",1,["funnybones::JointId"]],["impl UnwindSafe for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl UnwindSafe for Rotation",1,["funnybones::Rotation"]],["impl UnwindSafe for Skeleton",1,["funnybones::Skeleton"]],["impl UnwindSafe for Vector",1,["funnybones::Vector"]]]
+"funnybones":[["impl UnwindSafe for ChangeKind",1,["funnybones::animation::ChangeKind"]],["impl UnwindSafe for BoneEnd",1,["funnybones::BoneEnd"]],["impl UnwindSafe for BoneKind",1,["funnybones::BoneKind"]],["impl UnwindSafe for Animation",1,["funnybones::animation::Animation"]],["impl UnwindSafe for Change",1,["funnybones::animation::Change"]],["impl UnwindSafe for Frame",1,["funnybones::animation::Frame"]],["impl UnwindSafe for RunningAnimation",1,["funnybones::animation::RunningAnimation"]],["impl UnwindSafe for Bone",1,["funnybones::Bone"]],["impl UnwindSafe for BoneAxis",1,["funnybones::BoneAxis"]],["impl UnwindSafe for BoneId",1,["funnybones::BoneId"]],["impl UnwindSafe for Joint",1,["funnybones::Joint"]],["impl UnwindSafe for JointId",1,["funnybones::JointId"]],["impl UnwindSafe for LabeledBoneKind",1,["funnybones::LabeledBoneKind"]],["impl UnwindSafe for Rotation",1,["funnybones::Rotation"]],["impl UnwindSafe for Skeleton",1,["funnybones::Skeleton"]],["impl UnwindSafe for Vector",1,["funnybones::Vector"]]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/serde/de/trait.Deserialize.js b/main/trait.impl/serde/de/trait.Deserialize.js
index c6d5deb..391c42f 100644
--- a/main/trait.impl/serde/de/trait.Deserialize.js
+++ b/main/trait.impl/serde/de/trait.Deserialize.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl<'de> Deserialize<'de> for BoneEnd"],["impl<'de> Deserialize<'de> for BoneKind"],["impl<'de> Deserialize<'de> for BoneAxis"],["impl<'de> Deserialize<'de> for BoneId"],["impl<'de> Deserialize<'de> for JointId"],["impl<'de> Deserialize<'de> for Rotation"],["impl<'de> Deserialize<'de> for Skeleton"],["impl<'de> Deserialize<'de> for Vector"]]
+"funnybones":[["impl<'de> Deserialize<'de> for ChangeKind"],["impl<'de> Deserialize<'de> for BoneEnd"],["impl<'de> Deserialize<'de> for BoneKind"],["impl<'de> Deserialize<'de> for Change"],["impl<'de> Deserialize<'de> for Frame"],["impl<'de> Deserialize<'de> for BoneAxis"],["impl<'de> Deserialize<'de> for BoneId"],["impl<'de> Deserialize<'de> for JointId"],["impl<'de> Deserialize<'de> for Rotation"],["impl<'de> Deserialize<'de> for Skeleton"],["impl<'de> Deserialize<'de> for Vector"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/main/trait.impl/serde/ser/trait.Serialize.js b/main/trait.impl/serde/ser/trait.Serialize.js
index eab377e..59c8c5d 100644
--- a/main/trait.impl/serde/ser/trait.Serialize.js
+++ b/main/trait.impl/serde/ser/trait.Serialize.js
@@ -1,3 +1,3 @@
(function() {var implementors = {
-"funnybones":[["impl Serialize for BoneEnd"],["impl Serialize for BoneKind"],["impl Serialize for Bone"],["impl Serialize for BoneAxis"],["impl Serialize for BoneId"],["impl Serialize for Joint"],["impl Serialize for JointId"],["impl Serialize for Rotation"],["impl Serialize for Skeleton"],["impl Serialize for Vector"]]
+"funnybones":[["impl Serialize for ChangeKind"],["impl Serialize for BoneEnd"],["impl Serialize for BoneKind"],["impl Serialize for Change"],["impl Serialize for Frame"],["impl Serialize for Bone"],["impl Serialize for BoneAxis"],["impl Serialize for BoneId"],["impl Serialize for Joint"],["impl Serialize for JointId"],["impl Serialize for Rotation"],["impl Serialize for Skeleton"],["impl Serialize for Vector"]]
};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file