| // 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::{ | |
| __internal::runtime::{InnerRepeated, InnerRepeatedMut, RawRepeatedField}, | |
| __internal::{Private, SealedInternal}, | |
| AsMut, AsView, IntoMut, IntoProxied, IntoView, Message, Mut, MutProxied, Proxied, Singular, | |
| View, | |
| }; | |
| /// 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: Singular> { | |
| pub(crate) inner: InnerRepeated, | |
| _phantom: PhantomData<T>, | |
| } | |
| // SAFETY: `Repeated` is Sync because it does not implement interior mutability. | |
| unsafe impl<T: Singular> Sync for Repeated<T> {} | |
| // SAFETY: `Repeated` is Send because it's not bound to a specific thread e.g. | |
| // it does not use thread-local data or similar. | |
| unsafe impl<T: Singular> Send for Repeated<T> {} | |
| impl<T: Singular> Repeated<T> { | |
| pub fn new() -> Self { | |
| T::repeated_new(Private) | |
| } | |
| pub(crate) fn as_mut(&mut self) -> RepeatedMut<'_, T> { | |
| RepeatedMut { inner: self.inner.as_mut(), _phantom: PhantomData } | |
| } | |
| pub fn as_view(&self) -> View<'_, Repeated<T>> { | |
| RepeatedView { raw: self.inner.raw(), _phantom: PhantomData } | |
| } | |
| #[doc(hidden)] | |
| pub fn inner(&self, _private: Private) -> &InnerRepeated { | |
| &self.inner | |
| } | |
| #[doc(hidden)] | |
| pub fn from_inner(_private: Private, inner: InnerRepeated) -> Self { | |
| Self { inner, _phantom: PhantomData } | |
| } | |
| } | |
| impl<T: Singular, I, U> IntoProxied<Repeated<T>> for I | |
| where | |
| I: Iterator<Item = U>, | |
| U: IntoProxied<T>, | |
| { | |
| fn into_proxied(self, _private: Private) -> Repeated<T> { | |
| let mut repeated: Repeated<T> = Repeated::new(); | |
| repeated.as_mut().extend(self); | |
| repeated | |
| } | |
| } | |
| impl<T: Singular> Default for Repeated<T> { | |
| fn default() -> Self { | |
| Repeated::new() | |
| } | |
| } | |
| impl<T: Singular> Drop for Repeated<T> { | |
| fn drop(&mut self) { | |
| // SAFETY: only called once | |
| unsafe { T::repeated_free(Private, self) } | |
| } | |
| } | |
| impl<T: Singular> Proxied for Repeated<T> { | |
| type View<'msg> | |
| = RepeatedView<'msg, T> | |
| where | |
| Repeated<T>: 'msg; | |
| } | |
| impl<T: Singular> SealedInternal for Repeated<T> {} | |
| impl<T: Singular> crate::codegen_traits::EntityType for Repeated<T> { | |
| type Tag = crate::codegen_traits::entity_tag::RepeatedTag; | |
| } | |
| impl<T: Singular> AsView for Repeated<T> { | |
| type Proxied = Self; | |
| fn as_view(&self) -> RepeatedView<'_, T> { | |
| self.as_view() | |
| } | |
| } | |
| impl<T: Singular> MutProxied for Repeated<T> { | |
| type Mut<'msg> | |
| = RepeatedMut<'msg, T> | |
| where | |
| Repeated<T>: 'msg; | |
| } | |
| impl<T: Singular> AsMut for Repeated<T> { | |
| type MutProxied = Self; | |
| fn as_mut(&mut self) -> RepeatedMut<'_, T> { | |
| self.as_mut() | |
| } | |
| } | |
| /// Views the elements in a `repeated` field of `T`. | |
| #[repr(transparent)] | |
| pub struct RepeatedView<'msg, T> { | |
| // 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> Copy for RepeatedView<'msg, T> {} | |
| impl<'msg, T> Clone for RepeatedView<'msg, T> { | |
| fn clone(&self) -> Self { | |
| *self | |
| } | |
| } | |
| unsafe impl<'msg, T> Sync for RepeatedView<'msg, T> {} | |
| unsafe impl<'msg, T> Send for RepeatedView<'msg, T> {} | |
| impl<'msg, T> Debug for RepeatedView<'msg, T> { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| f.debug_struct("RepeatedView").field("raw", &self.raw).finish() | |
| } | |
| } | |
| impl<'msg, T: Singular> SealedInternal for RepeatedView<'msg, T> {} | |
| #[doc(hidden)] | |
| impl<'msg, T> RepeatedView<'msg, T> { | |
| #[doc(hidden)] | |
| #[inline] | |
| pub fn as_raw(&self, _private: Private) -> RawRepeatedField { | |
| self.raw | |
| } | |
| /// # Safety | |
| /// - `inner` must be valid to read from for `'msg` | |
| #[doc(hidden)] | |
| #[inline] | |
| pub unsafe fn from_raw(_private: Private, raw: RawRepeatedField) -> Self { | |
| Self { raw, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, T: Singular> RepeatedView<'msg, T> { | |
| /// Gets the length of the repeated field. | |
| #[inline] | |
| pub fn len(&self) -> usize { | |
| T::repeated_len(Private, *self) | |
| } | |
| /// Returns true if the repeated field has no values. | |
| #[inline] | |
| pub fn is_empty(&self) -> bool { | |
| self.len() == 0 | |
| } | |
| /// Gets the value at `index`. | |
| /// | |
| /// Returns `None` if `index > len`. | |
| #[inline] | |
| 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` | |
| #[inline] | |
| pub unsafe fn get_unchecked(self, index: usize) -> View<'msg, T> { | |
| // SAFETY: in-bounds as promised | |
| unsafe { T::repeated_get_unchecked(Private, self, index) } | |
| } | |
| /// Iterates over the values in the repeated field. | |
| pub fn iter(self) -> RepeatedIter<'msg, T> { | |
| self.into_iter() | |
| } | |
| /// Returns the first element of the repeated field, or `None` if it is empty. | |
| #[inline] | |
| pub fn first(self) -> Option<View<'msg, T>> { | |
| self.get(0) | |
| } | |
| /// Returns the last element of the repeated field, or `None` if it is empty. | |
| #[inline] | |
| pub fn last(self) -> Option<View<'msg, T>> { | |
| let len = self.len(); | |
| if len == 0 { | |
| None | |
| } else { | |
| // SAFETY: len is not 0, so len - 1 is a valid index | |
| unsafe { Some(self.get_unchecked(len - 1)) } | |
| } | |
| } | |
| } | |
| impl<'msg, T: Singular> AsView for RepeatedView<'msg, T> { | |
| type Proxied = Repeated<T>; | |
| #[inline] | |
| fn as_view(&self) -> View<'msg, Self::Proxied> { | |
| *self | |
| } | |
| } | |
| impl<'msg, T: Singular> IntoView<'msg> for RepeatedView<'msg, T> { | |
| #[inline] | |
| fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> | |
| where | |
| 'msg: 'shorter, | |
| { | |
| RepeatedView { raw: self.raw, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, T: Singular> IntoProxied<Repeated<T>> for RepeatedView<'msg, T> { | |
| fn into_proxied(self, _private: Private) -> Repeated<T> { | |
| let mut repeated: Repeated<T> = Repeated::new(); | |
| T::repeated_copy_from(Private, self, repeated.as_mut()); | |
| repeated | |
| } | |
| } | |
| /// Mutates the elements in a `repeated` field of `T`. | |
| pub struct RepeatedMut<'msg, T> { | |
| pub(crate) inner: InnerRepeatedMut<'msg>, | |
| _phantom: PhantomData<&'msg mut T>, | |
| } | |
| unsafe impl<'msg, T> Sync for RepeatedMut<'msg, T> {} | |
| impl<'msg, T> 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> 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)] | |
| #[inline] | |
| pub unsafe fn from_inner(_private: Private, inner: InnerRepeatedMut<'msg>) -> Self { | |
| Self { inner, _phantom: PhantomData } | |
| } | |
| #[doc(hidden)] | |
| #[inline] | |
| pub fn as_raw(&mut self, _private: Private) -> RawRepeatedField { | |
| self.inner.raw | |
| } | |
| } | |
| impl<'msg, T: Singular> RepeatedMut<'msg, T> { | |
| /// Gets the length of the repeated field. | |
| #[inline] | |
| pub fn len(&self) -> usize { | |
| self.as_view().len() | |
| } | |
| /// Returns true if the repeated field has no values. | |
| #[inline] | |
| pub fn is_empty(&self) -> bool { | |
| self.len() == 0 | |
| } | |
| /// Gets the value at `index`. | |
| /// | |
| /// Returns `None` if `index >= len`. | |
| #[inline] | |
| pub fn get(&self, index: usize) -> Option<View<'_, T>> { | |
| self.as_view().get(index) | |
| } | |
| /// Gets the value at `index`. | |
| /// | |
| /// Returns `None` if `index >= len`. | |
| #[inline] | |
| pub fn get_mut(&mut self, index: usize) -> Option<Mut<'_, T>> | |
| where | |
| T: Message, | |
| { | |
| if index >= self.len() { | |
| return None; | |
| } | |
| // SAFETY: `index` has been checked to be in-bounds | |
| Some(unsafe { self.get_mut_unchecked(index) }) | |
| } | |
| /// Gets the value at `index` without bounds-checking. | |
| /// | |
| /// # Safety | |
| /// Undefined behavior if `index >= len`. | |
| #[inline] | |
| pub unsafe fn get_mut_unchecked(&mut self, index: usize) -> Mut<'_, T> | |
| where | |
| T: Message, | |
| { | |
| // SAFETY: in-bounds as promised | |
| unsafe { T::repeated_get_mut_unchecked(Private, self.as_mut(), index) } | |
| } | |
| /// Gets the value at `index` without bounds-checking. | |
| /// | |
| /// # Safety | |
| /// Undefined behavior if `index >= len`. | |
| #[inline] | |
| 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. | |
| #[inline] | |
| pub fn push(&mut self, val: impl IntoProxied<T>) { | |
| T::repeated_push(Private, self.as_mut(), val); | |
| } | |
| /// Appends the default message instance of T and returns a mutable reference to it. | |
| #[inline] | |
| pub fn push_default(&mut self) -> Mut<'_, T> | |
| where | |
| T: Message, | |
| { | |
| // TODO: This should be optimized on Cpp kernel by adding another thunk to expose Add(). | |
| self.push(T::default()); | |
| // SAFETY: we just pushed a value into the repeated field, so there is at least one element. | |
| unsafe { self.get_mut_unchecked(self.len() - 1) } | |
| } | |
| /// Sets the value at `index` to the value `val`. | |
| /// | |
| /// # Panics | |
| /// Panics if `index >= len`. | |
| #[inline] | |
| pub fn set(&mut self, index: usize, val: impl IntoProxied<T>) { | |
| let len = self.len(); | |
| if index >= len { | |
| panic!("index {index} >= repeated len {len}"); | |
| } | |
| unsafe { self.set_unchecked(index, val) } | |
| } | |
| /// Sets the value at `index` to the value `val`. | |
| /// | |
| /// # Safety | |
| /// Undefined behavior if `index >= len`. | |
| #[inline] | |
| pub unsafe fn set_unchecked(&mut self, index: usize, val: impl IntoProxied<T>) { | |
| unsafe { T::repeated_set_unchecked(Private, 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. | |
| pub fn copy_from(&mut self, src: RepeatedView<'_, T>) { | |
| T::repeated_copy_from(Private, src, self.as_mut()) | |
| } | |
| /// Clears the repeated field. | |
| pub fn clear(&mut self) { | |
| T::repeated_clear(Private, self.as_mut()) | |
| } | |
| /// Shortens the repeated field, keeping the first `new_len` elements and | |
| /// dropping the rest, or does nothing if `new_len >= self.len()`. | |
| pub fn truncate(&mut self, new_len: usize) { | |
| if new_len >= self.len() { | |
| return; | |
| } | |
| T::repeated_truncate(Private, self.as_mut(), new_len) | |
| } | |
| /// Resizes the repeated field in-place so that `len` is equal to `new_len`, | |
| /// either extending with copies of `value` or truncating. | |
| pub fn resize(&mut self, new_len: usize, value: impl IntoProxied<T>) | |
| where | |
| for<'a> View<'a, T>: IntoProxied<T>, | |
| { | |
| let len = self.len(); | |
| if new_len < len { | |
| self.truncate(new_len); | |
| } else if new_len > len { | |
| let count = new_len - len; | |
| T::repeated_reserve(Private, self.as_mut(), count); | |
| let val = value.into_proxied(Private); | |
| for _ in 1..count { | |
| self.push(val.as_view()); | |
| } | |
| self.push(val); | |
| } | |
| } | |
| /// Returns the first element of the repeated field, or `None` if it is empty. | |
| #[inline] | |
| pub fn first(&self) -> Option<View<'_, T>> { | |
| self.as_view().first() | |
| } | |
| /// Returns the last element of the repeated field, or `None` if it is empty. | |
| #[inline] | |
| pub fn last(&self) -> Option<View<'_, T>> { | |
| self.as_view().last() | |
| } | |
| } | |
| impl<'msg, T: Singular> IntoProxied<Repeated<T>> for RepeatedMut<'msg, T> { | |
| fn into_proxied(self, _private: Private) -> Repeated<T> { | |
| IntoProxied::into_proxied(self.as_view(), _private) | |
| } | |
| } | |
| impl<'msg, T: Singular> SealedInternal for RepeatedMut<'msg, T> {} | |
| impl<'msg, T: Singular> AsView for RepeatedMut<'msg, T> { | |
| type Proxied = Repeated<T>; | |
| #[inline] | |
| fn as_view(&self) -> RepeatedView<'_, T> { | |
| RepeatedView { raw: self.inner.raw, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, T: Singular> IntoView<'msg> for RepeatedMut<'msg, T> { | |
| #[inline] | |
| fn into_view<'shorter>(self) -> RepeatedView<'shorter, T> | |
| where | |
| 'msg: 'shorter, | |
| { | |
| RepeatedView { raw: self.inner.raw, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, T: Singular> AsMut for RepeatedMut<'msg, T> { | |
| type MutProxied = Repeated<T>; | |
| #[inline] | |
| fn as_mut(&mut self) -> RepeatedMut<'_, T> { | |
| RepeatedMut { inner: self.inner, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, T: Singular> IntoMut<'msg> for RepeatedMut<'msg, T> { | |
| #[inline] | |
| fn into_mut<'shorter>(self) -> RepeatedMut<'shorter, T> | |
| where | |
| 'msg: 'shorter, | |
| { | |
| RepeatedMut { inner: self.inner, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, T: Singular, ViewT> Extend<ViewT> for RepeatedMut<'msg, T> | |
| where | |
| ViewT: IntoProxied<T>, | |
| { | |
| fn extend<I: IntoIterator<Item = ViewT>>(&mut self, iter: I) { | |
| let iter = iter.into_iter(); | |
| T::repeated_reserve(Private, self.as_mut(), iter.size_hint().0); | |
| for item in iter { | |
| self.push(item); | |
| } | |
| } | |
| } | |
| impl<T: Singular, U> std::iter::FromIterator<U> for Repeated<T> | |
| where | |
| U: IntoProxied<T>, | |
| { | |
| fn from_iter<I: IntoIterator<Item = U>>(iter: I) -> Self { | |
| let mut repeated = Repeated::new(); | |
| repeated.as_mut().extend(iter); | |
| repeated | |
| } | |
| } | |
| /// An iterator over the values inside of a [`View<Repeated<T>>`](RepeatedView). | |
| #[derive(Clone)] | |
| pub struct RepeatedIter<'msg, T> { | |
| view: RepeatedView<'msg, T>, | |
| current_index: usize, | |
| end_index: usize, | |
| } | |
| impl<'msg, T> 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() | |
| } | |
| } | |
| impl<'msg, T: Singular> iter::Iterator for RepeatedIter<'msg, T> { | |
| type Item = View<'msg, T>; | |
| #[inline] | |
| fn next(&mut self) -> Option<Self::Item> { | |
| if self.current_index >= self.end_index { | |
| return None; | |
| } | |
| // SAFETY: current_index < end_index <= view.len() | |
| let val = unsafe { self.view.get_unchecked(self.current_index) }; | |
| self.current_index += 1; | |
| Some(val) | |
| } | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| let len = self.len(); | |
| (len, Some(len)) | |
| } | |
| } | |
| impl<'msg, T: Singular> ExactSizeIterator for RepeatedIter<'msg, T> { | |
| fn len(&self) -> usize { | |
| self.end_index - self.current_index | |
| } | |
| } | |
| impl<'msg, T: Singular> iter::DoubleEndedIterator for RepeatedIter<'msg, T> { | |
| #[inline] | |
| fn next_back(&mut self) -> Option<Self::Item> { | |
| if self.current_index >= self.end_index { | |
| return None; | |
| } | |
| self.end_index -= 1; | |
| // SAFETY: current_index <= end_index < view.len() | |
| Some(unsafe { self.view.get_unchecked(self.end_index) }) | |
| } | |
| } | |
| impl<'msg, T: Singular> FusedIterator for RepeatedIter<'msg, T> {} | |
| impl<'msg, T: Singular> iter::IntoIterator for RepeatedView<'msg, T> { | |
| type Item = View<'msg, T>; | |
| type IntoIter = RepeatedIter<'msg, T>; | |
| fn into_iter(self) -> Self::IntoIter { | |
| RepeatedIter { view: self, current_index: 0, end_index: self.len() } | |
| } | |
| } | |
| impl<'msg, T: Singular> iter::IntoIterator for &'_ RepeatedView<'msg, T> { | |
| type Item = View<'msg, T>; | |
| type IntoIter = RepeatedIter<'msg, T>; | |
| fn into_iter(self) -> Self::IntoIter { | |
| RepeatedIter { view: *self, current_index: 0, end_index: self.len() } | |
| } | |
| } | |
| impl<'borrow, T: Singular> iter::IntoIterator for &'borrow RepeatedMut<'_, T> { | |
| type Item = View<'borrow, T>; | |
| type IntoIter = RepeatedIter<'borrow, T>; | |
| fn into_iter(self) -> Self::IntoIter { | |
| let view = self.as_view(); | |
| RepeatedIter { view, current_index: 0, end_index: view.len() } | |
| } | |
| } | |
| /// An iterator over the mutable values inside of a [`RepeatedMut`]. | |
| /// | |
| /// **WARNING**: This has transitioned to a **Lending Iterator**. Standard `for` loops are not | |
| /// supported anymore. Use `while let Some(item) = iter.next()` instead. | |
| pub struct RepeatedMutIter<'msg, T> { | |
| inner: InnerRepeatedMut<'msg>, | |
| current_index: usize, | |
| end_index: usize, | |
| _phantom: PhantomData<&'msg mut T>, | |
| } | |
| impl<'msg, T: Message> RepeatedMutIter<'msg, T> { | |
| #[inline] | |
| pub fn next(&mut self) -> Option<Mut<'_, T>> { | |
| if self.current_index >= self.end_index { | |
| return None; | |
| } | |
| let index = self.current_index; | |
| self.current_index += 1; | |
| // SAFETY: index is valid. | |
| let val = unsafe { | |
| let temp_repeated = RepeatedMut::from_inner(Private, self.inner); | |
| T::repeated_get_mut_unchecked(Private, temp_repeated, index) | |
| }; | |
| Some(val) | |
| } | |
| #[inline] | |
| pub fn len(&self) -> usize { | |
| self.end_index - self.current_index | |
| } | |
| #[inline] | |
| pub fn next_back(&mut self) -> Option<Mut<'_, T>> { | |
| if self.current_index >= self.end_index { | |
| return None; | |
| } | |
| self.end_index -= 1; | |
| let index = self.end_index; | |
| // SAFETY: index is guaranteed to be in bounds. | |
| let val = unsafe { | |
| let temp_repeated = RepeatedMut::from_inner(Private, self.inner); | |
| T::repeated_get_mut_unchecked(Private, temp_repeated, index) | |
| }; | |
| Some(val) | |
| } | |
| } | |
| impl<'msg, T: Message> RepeatedMut<'msg, T> { | |
| /// Returns an iterator that allows modifying each value. | |
| pub fn iter_mut(self) -> RepeatedMutIter<'msg, T> { | |
| RepeatedMutIter { | |
| end_index: self.len(), | |
| inner: self.inner, | |
| current_index: 0, | |
| _phantom: PhantomData, | |
| } | |
| } | |
| /// Returns a mutable reference to the first element of the repeated field, or `None` if it is | |
| /// empty. | |
| #[inline] | |
| pub fn first_mut<'r>(&'r mut self) -> Option<Mut<'msg, T>> | |
| where | |
| 'r: 'msg, | |
| { | |
| self.get_mut(0) | |
| } | |
| /// Returns a mutable reference to the last element of the repeated field, or `None` if it is | |
| /// empty. | |
| #[inline] | |
| pub fn last_mut<'r>(&'r mut self) -> Option<Mut<'msg, T>> | |
| where | |
| 'r: 'msg, | |
| { | |
| let len = self.len(); | |
| if len == 0 { | |
| None | |
| } else { | |
| // SAFETY: len is not 0, so len - 1 is valid | |
| Some(unsafe { self.get_mut_unchecked(len - 1) }) | |
| } | |
| } | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use super::*; | |
| use googletest::prelude::*; | |
| #[gtest] | |
| 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, 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], | |
| ); | |
| } | |
| #[gtest] | |
| 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(), 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(), elements_are![eq(0), eq(1), eq(2), eq(3)]); | |
| } | |
| #[gtest] | |
| fn test_repeated_iter() { | |
| let r: Repeated<i32> = [0, 1, 2, 3].into_iter().into_proxied(Private); | |
| assert_that!(r.as_view(), elements_are![eq(0), eq(1), eq(2), eq(3)]); | |
| let mut iter = r.as_view().into_iter(); | |
| assert_that!(iter.next(), eq(Some(0))); | |
| let mut clone = iter.clone(); | |
| assert_that!(clone.next(), eq(Some(1))); | |
| assert_that!(iter.next(), eq(Some(1))); | |
| } | |
| #[gtest] | |
| fn test_first_last() { | |
| let mut r = Repeated::<i32>::new(); | |
| assert!(r.as_view().first().is_none()); | |
| assert!(r.as_view().last().is_none()); | |
| assert!(r.as_mut().first().is_none()); | |
| assert!(r.as_mut().last().is_none()); | |
| let mut m = r.as_mut(); | |
| m.push(10); | |
| assert_that!(m.first(), eq(Some(10))); | |
| assert_that!(m.last(), eq(Some(10))); | |
| assert_that!(m.as_view().first(), eq(Some(10))); | |
| assert_that!(m.as_view().last(), eq(Some(10))); | |
| m.push(20); | |
| assert_that!(m.first(), eq(Some(10))); | |
| assert_that!(m.last(), eq(Some(20))); | |
| } | |
| #[gtest] | |
| fn test_double_ended_iter() { | |
| let r: Repeated<i32> = [1, 2, 3].into_iter().collect(); | |
| let mut iter = r.as_view().into_iter(); | |
| assert_that!(iter.next(), eq(Some(1))); | |
| assert_that!(iter.next_back(), eq(Some(3))); | |
| assert_that!(iter.next(), eq(Some(2))); | |
| assert_that!(iter.next(), eq(None)); | |
| assert_that!(iter.next_back(), eq(None)); | |
| } | |
| #[gtest] | |
| fn test_from_iter() { | |
| let r: Repeated<i32> = [10, 20, 30].into_iter().collect(); | |
| assert_that!(r.as_view(), elements_are![eq(10), eq(20), eq(30)]); | |
| } | |
| #[gtest] | |
| fn test_truncate() { | |
| let mut r: Repeated<i32> = [10, 20, 30, 40].into_iter().collect(); | |
| r.as_mut().truncate(5); | |
| expect_that!(r.as_view(), elements_are![eq(10), eq(20), eq(30), eq(40)]); | |
| r.as_mut().truncate(4); | |
| expect_that!(r.as_view(), elements_are![eq(10), eq(20), eq(30), eq(40)]); | |
| r.as_mut().truncate(2); | |
| expect_that!(r.as_view(), elements_are![eq(10), eq(20)]); | |
| r.as_mut().push(50); | |
| expect_that!(r.as_view(), elements_are![eq(10), eq(20), eq(50)]); | |
| r.as_mut().truncate(0); | |
| expect_true!(r.as_view().is_empty()); | |
| r.as_mut().push(60); | |
| expect_that!(r.as_view(), elements_are![eq(60)]); | |
| } | |
| #[gtest] | |
| fn test_resize() { | |
| let mut r: Repeated<i32> = [10, 20, 30, 40].into_iter().collect(); | |
| r.as_mut().resize(4, 99); | |
| expect_that!(r.as_view(), elements_are![eq(10), eq(20), eq(30), eq(40)]); | |
| r.as_mut().resize(6, 99); | |
| expect_that!(r.as_view(), elements_are![eq(10), eq(20), eq(30), eq(40), eq(99), eq(99)]); | |
| r.as_mut().resize(2, 0); | |
| expect_that!(r.as_view(), elements_are![eq(10), eq(20)]); | |
| r.as_mut().push(50); | |
| expect_that!(r.as_view(), elements_are![eq(10), eq(20), eq(50)]); | |
| r.as_mut().resize(0, 0); | |
| expect_true!(r.as_view().is_empty()); | |
| r.as_mut().resize(1, 60); | |
| expect_that!(r.as_view(), elements_are![eq(60)]); | |
| } | |
| } |