Skip to content

Commit 70590a5

Browse files
RustProto: Add the ability to iterate over the muts of a repeated message-typed field.
PiperOrigin-RevId: 904479108
1 parent ce7538a commit 70590a5

2 files changed

Lines changed: 80 additions & 0 deletions

File tree

rust/repeated.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,60 @@ impl<'borrow, T: Singular> iter::IntoIterator for &'borrow RepeatedMut<'_, T> {
511511
}
512512
}
513513

514+
/// An iterator over the mutable values inside of a [`RepeatedMut`].
515+
pub struct RepeatedMutIter<'msg, T> {
516+
inner: InnerRepeatedMut<'msg>,
517+
current_index: usize,
518+
len: usize,
519+
_phantom: PhantomData<&'msg mut T>,
520+
}
521+
522+
impl<'msg, T: Message> iter::Iterator for RepeatedMutIter<'msg, T> {
523+
type Item = Mut<'msg, T>;
524+
525+
#[inline]
526+
fn next(&mut self) -> Option<Self::Item> {
527+
if self.current_index >= self.len {
528+
return None;
529+
}
530+
let index = self.current_index;
531+
self.current_index += 1;
532+
533+
// SAFETY: index is valid.
534+
let val = unsafe {
535+
let temp_repeated = RepeatedMut::from_inner(Private, self.inner);
536+
T::repeated_get_mut_unchecked(Private, temp_repeated, index)
537+
};
538+
539+
Some(val)
540+
}
541+
542+
fn size_hint(&self) -> (usize, Option<usize>) {
543+
let len = self.len();
544+
(len, Some(len))
545+
}
546+
}
547+
548+
impl<'msg, T: Message> ExactSizeIterator for RepeatedMutIter<'msg, T> {
549+
fn len(&self) -> usize {
550+
self.len - self.current_index
551+
}
552+
}
553+
554+
impl<'msg, T: Message> FusedIterator for RepeatedMutIter<'msg, T> {}
555+
556+
impl<'msg, T: Message> RepeatedMut<'msg, T> {
557+
/// Returns an iterator that allows modifying each value.
558+
pub fn iter_mut(self) -> RepeatedMutIter<'msg, T> {
559+
RepeatedMutIter {
560+
len: self.len(),
561+
inner: self.inner,
562+
current_index: 0,
563+
_phantom: PhantomData,
564+
}
565+
}
566+
}
567+
514568
#[cfg(test)]
515569
mod tests {
516570
use super::*;

rust/test/shared/accessors_repeated_test.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,32 @@ fn test_repeated_message() {
247247
assert_that!(msg2.repeated_nested_message().len(), eq(0));
248248
}
249249

250+
#[gtest]
251+
fn test_repeated_message_iter_mut_empty() {
252+
let mut msg = TestAllTypes::new();
253+
let mut iter = msg.repeated_nested_message_mut().iter_mut();
254+
assert_that!(iter.next(), none());
255+
}
256+
257+
#[gtest]
258+
fn test_repeated_message_iter_mut() {
259+
let mut msg = TestAllTypes::new();
260+
for i in 0..3 {
261+
let mut nested = NestedMessage::new();
262+
nested.set_bb(i);
263+
msg.repeated_nested_message_mut().push(nested);
264+
}
265+
266+
for mut nested in msg.repeated_nested_message_mut().iter_mut() {
267+
let bb = nested.bb();
268+
nested.set_bb(bb + 1);
269+
}
270+
271+
assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(1));
272+
assert_that!(msg.repeated_nested_message().get(1).unwrap().bb(), eq(2));
273+
assert_that!(msg.repeated_nested_message().get(2).unwrap().bb(), eq(3));
274+
}
275+
250276
#[gtest]
251277
fn test_repeated_message_setter() {
252278
let mut msg = TestAllTypes::new();

0 commit comments

Comments
 (0)