|
|
|
// Protocol Buffers - Google's data interchange format
|
|
|
|
// Copyright 2023 Google LLC. All rights reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
|
|
|
|
use std::fmt::{self, Debug};
|
|
|
|
use std::iter;
|
|
|
|
use std::iter::FusedIterator;
|
|
|
|
/// Repeated scalar fields are implemented around the runtime-specific
|
|
|
|
/// `RepeatedField` struct. `RepeatedField` stores an opaque pointer to the
|
|
|
|
/// runtime-specific representation of a repeated scalar (`upb_Array*` on upb,
|
|
|
|
/// and `RepeatedField<T>*` on cpp).
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
Mut, MutProxied, MutProxy, Proxied, View, ViewProxy,
|
|
|
|
__internal::Private,
|
|
|
|
__runtime::{InnerRepeated, InnerRepeatedMut, RawRepeatedField},
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Views the elements in a `repeated` field of `T`.
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct RepeatedView<'msg, T: ?Sized> {
|
|
|
|
// This does not need to carry an arena in upb, so it can be just the raw repeated field
|
|
|
|
raw: RawRepeatedField,
|
|
|
|
_phantom: PhantomData<&'msg T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T: ?Sized> Copy for RepeatedView<'msg, T> {}
|
|
|
|
impl<'msg, T: ?Sized> Clone for RepeatedView<'msg, T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl<'msg, T: ?Sized> Sync for RepeatedView<'msg, T> {}
|
|
|
|
unsafe impl<'msg, T: ?Sized> Send for RepeatedView<'msg, T> {}
|
|
|
|
|
|
|
|
impl<'msg, T: ?Sized> Debug for RepeatedView<'msg, T> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.debug_struct("RepeatedView").field("raw", &self.raw).finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Mutates the elements in a `repeated` field of `T`.
|
|
|
|
pub struct RepeatedMut<'msg, T: ?Sized> {
|
|
|
|
pub(crate) inner: InnerRepeatedMut<'msg>,
|
|
|
|
_phantom: PhantomData<&'msg mut T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl<'msg, T: ?Sized> Sync for RepeatedMut<'msg, T> {}
|
|
|
|
|
|
|
|
impl<'msg, T: ?Sized> Debug for RepeatedMut<'msg, T> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.debug_struct("RepeatedMut").field("raw", &self.inner.raw).finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl<'msg, T: ?Sized> RepeatedView<'msg, T> {
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn as_raw(&self, _private: Private) -> RawRepeatedField {
|
|
|
|
self.raw
|
|
|
|
}
|
|
|
|
|
|
|
|
/// # Safety
|
|
|
|
/// - `inner` must be valid to read from for `'msg`
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub unsafe fn from_raw(_private: Private, raw: RawRepeatedField) -> Self {
|
|
|
|
Self { raw, _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T> RepeatedView<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'msg,
|
|
|
|
{
|
|
|
|
/// Gets the length of the repeated field.
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
T::repeated_len(*self)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if the repeated field has no values.
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.len() == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the value at `index`.
|
|
|
|
///
|
|
|
|
/// Returns `None` if `index > len`.
|
|
|
|
pub fn get(self, index: usize) -> Option<View<'msg, T>> {
|
|
|
|
if index >= self.len() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
// SAFETY: `index` has been checked to be in-bounds
|
|
|
|
Some(unsafe { self.get_unchecked(index) })
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the value at `index` without bounds-checking.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// Undefined behavior if `index >= len`
|
|
|
|
pub unsafe fn get_unchecked(self, index: usize) -> View<'msg, T> {
|
|
|
|
// SAFETY: in-bounds as promised
|
|
|
|
unsafe { T::repeated_get_unchecked(self, index) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterates over the values in the repeated field.
|
|
|
|
pub fn iter(self) -> RepeatedIter<'msg, T> {
|
|
|
|
self.into_iter()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl<'msg, T: ?Sized> RepeatedMut<'msg, T> {
|
|
|
|
/// # Safety
|
|
|
|
/// - `inner` must be valid to read and write from for `'msg`
|
|
|
|
/// - There must be no aliasing references or mutations on the same
|
|
|
|
/// underlying object.
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub unsafe fn from_inner(_private: Private, inner: InnerRepeatedMut<'msg>) -> Self {
|
|
|
|
Self { inner, _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn as_raw(&mut self, _private: Private) -> RawRepeatedField {
|
|
|
|
self.inner.raw
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T> RepeatedMut<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'msg,
|
|
|
|
{
|
|
|
|
/// Gets the length of the repeated field.
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.as_view().len()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if the repeated field has no values.
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.len() == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the value at `index`.
|
|
|
|
///
|
|
|
|
/// Returns `None` if `index > len`.
|
|
|
|
pub fn get(&self, index: usize) -> Option<View<T>> {
|
|
|
|
self.as_view().get(index)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the value at `index` without bounds-checking.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// Undefined behavior if `index >= len`
|
|
|
|
pub unsafe fn get_unchecked(&self, index: usize) -> View<T> {
|
|
|
|
// SAFETY: in-bounds as promised
|
|
|
|
unsafe { self.as_view().get_unchecked(index) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Appends `val` to the end of the repeated field.
|
|
|
|
pub fn push(&mut self, val: View<T>) {
|
|
|
|
// TODO: b/320936046 - Use SettableValue instead of View for added ergonomics.
|
|
|
|
T::repeated_push(self.as_mut(), val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the value at `index` to the value `val`.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
/// Panics if `index >= len`
|
|
|
|
pub fn set(&mut self, index: usize, val: View<T>) {
|
|
|
|
let len = self.len();
|
|
|
|
if index >= len {
|
|
|
|
panic!("index {index} >= repeated len {len}");
|
|
|
|
}
|
|
|
|
// TODO: b/320936046 - Use SettableValue instead of View for added ergonomics.
|
|
|
|
// SAFETY: `index` has been checked to be in-bounds.
|
|
|
|
unsafe { self.set_unchecked(index, val) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the value at `index` to the value `val`.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// Undefined behavior if `index >= len`
|
|
|
|
pub unsafe fn set_unchecked(&mut self, index: usize, val: View<T>) {
|
|
|
|
// TODO: b/320936046 - Use SettableValue instead of View for added ergonomics.
|
|
|
|
// SAFETY: `index` is in-bounds as promised by the caller.
|
|
|
|
unsafe { T::repeated_set_unchecked(self.as_mut(), index, val) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterates over the values in the repeated field.
|
|
|
|
pub fn iter(&self) -> RepeatedIter<T> {
|
|
|
|
self.as_view().into_iter()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Copies from the `src` repeated field into this one.
|
|
|
|
///
|
|
|
|
/// Also provided by [`MutProxy::set`].
|
|
|
|
pub fn copy_from(&mut self, src: RepeatedView<'_, T>) {
|
|
|
|
T::repeated_copy_from(src, self.as_mut())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Clears the repeated field.
|
|
|
|
pub fn clear(&mut self) {
|
|
|
|
T::repeated_clear(self.as_mut())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Types that can appear in a `Repeated<T>`.
|
|
|
|
///
|
|
|
|
/// This trait is implemented by generated code to communicate how the proxied
|
|
|
|
/// type can be manipulated for a repeated field.
|
|
|
|
///
|
|
|
|
/// Scalars and messages implement `ProxiedInRepeated`.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// - It must be sound to call `*_unchecked*(x)` with an `index` less than
|
|
|
|
/// `repeated_len(x)`.
|
|
|
|
pub unsafe trait ProxiedInRepeated: Proxied {
|
|
|
|
/// Constructs a new owned `Repeated` field.
|
|
|
|
#[doc(hidden)]
|
|
|
|
fn repeated_new(_private: Private) -> Repeated<Self> {
|
|
|
|
unimplemented!("not required")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Frees the repeated field in-place, for use in `Drop`.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// - After `repeated_free`, no other methods on the input are safe to call.
|
|
|
|
#[doc(hidden)]
|
|
|
|
unsafe fn repeated_free(_private: Private, _repeated: &mut Repeated<Self>) {
|
|
|
|
unimplemented!("not required")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the length of the repeated field.
|
|
|
|
fn repeated_len(repeated: View<Repeated<Self>>) -> usize;
|
|
|
|
|
|
|
|
/// Appends a new element to the end of the repeated field.
|
|
|
|
fn repeated_push(repeated: Mut<Repeated<Self>>, val: View<Self>);
|
|
|
|
|
|
|
|
/// Clears the repeated field of elements.
|
|
|
|
fn repeated_clear(repeated: Mut<Repeated<Self>>);
|
|
|
|
|
|
|
|
/// # Safety
|
|
|
|
/// `index` must be less than `Self::repeated_len(repeated)`
|
|
|
|
unsafe fn repeated_get_unchecked(repeated: View<Repeated<Self>>, index: usize) -> View<Self>;
|
|
|
|
|
|
|
|
/// # Safety
|
|
|
|
/// `index` must be less than `Self::repeated_len(repeated)`
|
|
|
|
unsafe fn repeated_set_unchecked(repeated: Mut<Repeated<Self>>, index: usize, val: View<Self>);
|
|
|
|
|
|
|
|
/// Copies the values in the `src` repeated field into `dest`.
|
|
|
|
fn repeated_copy_from(src: View<Repeated<Self>>, dest: Mut<Repeated<Self>>);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An iterator over the values inside of a [`View<Repeated<T>>`](RepeatedView).
|
|
|
|
pub struct RepeatedIter<'msg, T: ?Sized> {
|
|
|
|
view: RepeatedView<'msg, T>,
|
|
|
|
current_index: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T: ?Sized> Debug for RepeatedIter<'msg, T> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.debug_struct("RepeatedIter")
|
|
|
|
.field("view", &self.view)
|
|
|
|
.field("current_index", &self.current_index)
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A `repeated` field of `T`, used as the owned target for `Proxied`.
|
|
|
|
///
|
|
|
|
/// Users will generally write [`View<Repeated<T>>`](RepeatedView) or
|
|
|
|
/// [`Mut<Repeated<T>>`](RepeatedMut) to access the repeated elements
|
|
|
|
pub struct Repeated<T: ?Sized + ProxiedInRepeated> {
|
|
|
|
inner: InnerRepeated,
|
|
|
|
_phantom: PhantomData<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ?Sized + ProxiedInRepeated> Repeated<T> {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
T::repeated_new(Private)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn from_inner(inner: InnerRepeated) -> Self {
|
|
|
|
Self { inner, _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn as_mut(&mut self) -> RepeatedMut<'_, T> {
|
|
|
|
RepeatedMut { inner: self.inner.as_mut(), _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ?Sized + ProxiedInRepeated> Default for Repeated<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Repeated::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ?Sized + ProxiedInRepeated> Drop for Repeated<T> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
// SAFETY: only called once
|
|
|
|
unsafe { T::repeated_free(Private, self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SAFETY: `Repeated` does not allow for shared mutability.
|
|
|
|
unsafe impl<T: ProxiedInRepeated> Sync for Repeated<T> {}
|
|
|
|
|
|
|
|
impl<T> Proxied for Repeated<T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized,
|
|
|
|
{
|
|
|
|
type View<'msg> = RepeatedView<'msg, T> where Repeated<T>: 'msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> MutProxied for Repeated<T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized,
|
|
|
|
{
|
|
|
|
type Mut<'msg> = RepeatedMut<'msg, T> where Repeated<T>: 'msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T> ViewProxy<'msg> for RepeatedView<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'msg,
|
|
|
|
{
|
|
|
|
type Proxied = Repeated<T>;
|
|
|
|
|
|
|
|
fn as_view(&self) -> View<'_, Self::Proxied> {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied>
|
|
|
|
where
|
|
|
|
'msg: 'shorter,
|
|
|
|
{
|
|
|
|
RepeatedView { raw: self.raw, _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T> ViewProxy<'msg> for RepeatedMut<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'msg,
|
|
|
|
{
|
|
|
|
type Proxied = Repeated<T>;
|
|
|
|
|
|
|
|
fn as_view(&self) -> View<'_, Self::Proxied> {
|
|
|
|
RepeatedView { raw: self.inner.raw, _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied>
|
|
|
|
where
|
|
|
|
'msg: 'shorter,
|
|
|
|
{
|
|
|
|
RepeatedView { raw: self.inner.raw, _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T> MutProxy<'msg> for RepeatedMut<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'msg,
|
|
|
|
{
|
|
|
|
fn as_mut(&mut self) -> Mut<'_, Self::Proxied> {
|
|
|
|
RepeatedMut { inner: self.inner, _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied>
|
|
|
|
where
|
|
|
|
'msg: 'shorter,
|
|
|
|
{
|
|
|
|
RepeatedMut { inner: self.inner, _phantom: PhantomData }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T> iter::Iterator for RepeatedIter<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'msg,
|
|
|
|
{
|
|
|
|
type Item = View<'msg, T>;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
let val = self.view.get(self.current_index);
|
|
|
|
if val.is_some() {
|
|
|
|
self.current_index += 1;
|
|
|
|
}
|
|
|
|
val
|
|
|
|
}
|
|
|
|
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
let len = self.len();
|
|
|
|
(len, Some(len))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T: ?Sized + ProxiedInRepeated> ExactSizeIterator for RepeatedIter<'msg, T> {
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
self.view.len() - self.current_index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: impl DoubleEndedIterator
|
|
|
|
impl<'msg, T: ?Sized + ProxiedInRepeated> FusedIterator for RepeatedIter<'msg, T> {}
|
|
|
|
|
|
|
|
impl<'msg, T> iter::IntoIterator for RepeatedView<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'msg,
|
|
|
|
{
|
|
|
|
type Item = View<'msg, T>;
|
|
|
|
type IntoIter = RepeatedIter<'msg, T>;
|
|
|
|
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
|
|
RepeatedIter { view: self, current_index: 0 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, T> iter::IntoIterator for &'_ RepeatedView<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'msg,
|
|
|
|
{
|
|
|
|
type Item = View<'msg, T>;
|
|
|
|
type IntoIter = RepeatedIter<'msg, T>;
|
|
|
|
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
|
|
RepeatedIter { view: *self, current_index: 0 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'borrow, T> iter::IntoIterator for &'borrow RepeatedMut<'_, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'borrow,
|
|
|
|
{
|
|
|
|
type Item = View<'borrow, T>;
|
|
|
|
type IntoIter = RepeatedIter<'borrow, T>;
|
|
|
|
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
|
|
RepeatedIter { view: self.as_view(), current_index: 0 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'msg, 'view, T, ViewT> Extend<ViewT> for RepeatedMut<'msg, T>
|
|
|
|
where
|
|
|
|
T: ProxiedInRepeated + ?Sized + 'view,
|
|
|
|
ViewT: Into<View<'view, T>>,
|
|
|
|
{
|
|
|
|
fn extend<I: IntoIterator<Item = ViewT>>(&mut self, iter: I) {
|
|
|
|
for item in iter {
|
|
|
|
self.push(item.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use googletest::prelude::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_primitive_repeated() {
|
|
|
|
macro_rules! primitive_repeated_tests {
|
|
|
|
($($t:ty => [$($vals:expr),* $(,)?]),* $(,)?) => {
|
|
|
|
$({
|
|
|
|
// Constructs a new, owned, `Repeated`, only used for tests.
|
|
|
|
let mut r = Repeated::<$t>::new();
|
|
|
|
let mut r = r.as_mut();
|
|
|
|
assert_that!(r.len(), eq(0));
|
|
|
|
assert!(r.iter().next().is_none(), "starts with empty iter");
|
|
|
|
assert!(r.iter().next().is_none(), "starts with empty mut iter");
|
|
|
|
assert!(r.is_empty(), "starts is_empty");
|
|
|
|
|
|
|
|
let mut expected_len = 0usize;
|
|
|
|
$(
|
|
|
|
let val: View<$t> = $vals;
|
|
|
|
r.push(val);
|
|
|
|
assert_that!(r.get(expected_len), eq(Some(val)));
|
|
|
|
expected_len += 1;
|
|
|
|
assert_that!(r.len(), eq(expected_len));
|
|
|
|
|
|
|
|
)*
|
|
|
|
assert_that!(
|
|
|
|
r.iter().collect::<Vec<$t>>(), elements_are![$(eq($vals)),*]);
|
|
|
|
r.set(0, <$t as Default>::default());
|
|
|
|
assert_that!(r.get(0).expect("elem 0"), eq(<$t as Default>::default()));
|
|
|
|
|
|
|
|
r.clear();
|
|
|
|
assert!(r.is_empty(), "is_empty after clear");
|
|
|
|
assert!(r.iter().next().is_none(), "iter empty after clear");
|
|
|
|
assert!(r.into_iter().next().is_none(), "mut iter empty after clear");
|
|
|
|
})*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
primitive_repeated_tests!(
|
|
|
|
u32 => [1,2,3],
|
|
|
|
i32 => [1,2],
|
|
|
|
f64 => [10.0, 0.1234f64],
|
|
|
|
bool => [false, true, true, false],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_repeated_extend() {
|
|
|
|
let mut r = Repeated::<i32>::new();
|
|
|
|
|
|
|
|
r.as_mut().extend([0; 0]);
|
|
|
|
assert_that!(r.as_mut().len(), eq(0));
|
|
|
|
|
|
|
|
r.as_mut().extend([0, 1]);
|
|
|
|
assert_that!(r.as_mut().iter().collect::<Vec<_>>(), elements_are![eq(0), eq(1)]);
|
|
|
|
let mut x = Repeated::<i32>::new();
|
|
|
|
x.as_mut().extend([2, 3]);
|
|
|
|
|
|
|
|
r.as_mut().extend(&x.as_mut());
|
|
|
|
|
|
|
|
assert_that!(
|
|
|
|
r.as_mut().iter().collect::<Vec<_>>(),
|
|
|
|
elements_are![eq(0), eq(1), eq(2), eq(3)]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|