Enable inherent next() and next_back() API for RepeatedMutIter besides trait implementation.

This is in preparation for removing the impl Iterator on RepeatedMutIter, since we intend to make it a lending iterator which the std Iterator trait does not support.

PiperOrigin-RevId: 962265415
This commit is contained in:
Runze Wang 2026-08-10 11:23:29 -07:00 committed by Copybara-Service
parent 081ecdd861
commit b1b5f993e8
2 changed files with 99 additions and 0 deletions

View file

@ -568,6 +568,9 @@ impl<'borrow, T: Singular> iter::IntoIterator for &'borrow RepeatedMut<'_, T> {
}
/// An iterator over the mutable values inside of a [`RepeatedMut`].
///
/// **WARNING**: This is transitioning to a **Lending Iterator**. Standard `for` loops will soon be
/// unsupported. Use `while let Some(item) = iter.next()` instead.
pub struct RepeatedMutIter<'msg, T> {
inner: InnerRepeatedMut<'msg>,
current_index: usize,
@ -575,6 +578,47 @@ pub struct RepeatedMutIter<'msg, T> {
_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> iter::Iterator for RepeatedMutIter<'msg, T> {
type Item = Mut<'msg, T>;

View file

@ -273,6 +273,61 @@ fn test_repeated_message_iter_mut() {
assert_that!(msg.repeated_nested_message().get(2).unwrap().bb(), eq(3));
}
#[gtest]
fn test_repeated_message_iter_mut_custom_next() {
let mut msg = TestAllTypes::new();
for i in 0..3 {
let mut nested = NestedMessage::new();
nested.set_bb(i);
msg.repeated_nested_message_mut().push(nested);
}
let mut iter = msg.repeated_nested_message_mut().iter_mut();
assert_that!(iter.len(), eq(3));
assert_that!(iter.size_hint(), eq((3, Some(3))));
while let Some(mut nested) = iter.next() {
let bb = nested.bb();
nested.set_bb(bb + 10);
}
assert_that!(iter.len(), eq(0));
assert_that!(iter.size_hint(), eq((0, Some(0))));
assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(10));
assert_that!(msg.repeated_nested_message().get(1).unwrap().bb(), eq(11));
assert_that!(msg.repeated_nested_message().get(2).unwrap().bb(), eq(12));
}
#[gtest]
fn test_repeated_message_iter_mut_custom_next_back() {
let mut msg = TestAllTypes::new();
for i in 0..3 {
let mut nested = NestedMessage::new();
nested.set_bb(i);
msg.repeated_nested_message_mut().push(nested);
}
let mut iter = msg.repeated_nested_message_mut().iter_mut();
if let Some(mut nested) = iter.next_back() {
nested.set_bb(200);
}
if let Some(mut nested) = iter.next_back() {
nested.set_bb(100);
}
if let Some(mut nested) = iter.next_back() {
nested.set_bb(0);
}
assert_that!(iter.next_back(), none());
assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(0));
assert_that!(msg.repeated_nested_message().get(1).unwrap().bb(), eq(100));
assert_that!(msg.repeated_nested_message().get(2).unwrap().bb(), eq(200));
}
#[gtest]
fn test_repeated_message_setter() {
let mut msg = TestAllTypes::new();