Skip to content

Commit b25d39e

Browse files
Expose an iterator for GeneratedMessage.ExtendableMessage.extensions
This iterates over the wrapper class `GeneratedMessage.ExtendableMessage.FieldValue` to keep the mutable underlying structure of the extensions FieldSet hidden. The entries' values exposed here are a subset of the values exposed by `GeneratedMessage.getallFields`. This iterator has less overhead than calling allFields and does not create a new map object. PiperOrigin-RevId: 786884890
1 parent 6754bf4 commit b25d39e

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

‎java/core/src/main/java/com/google/protobuf/GeneratedMessage.java‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,14 @@ protected ExtendableMessage(ExtendableBuilder<MessageT, ?> builder) {
949949
this.extensions = builder.buildExtensions();
950950
}
951951

952+
/**
953+
* Returns an iterator over the set extensions lazily wrapped in {@link FieldEntry} objects.
954+
* Order is unspecified.
955+
*/
956+
public final Iterator<FieldEntry> extensionsIterator() {
957+
return new FieldEntryIterator(extensions);
958+
}
959+
952960
private void verifyExtensionContainingType(final Extension<? extends MessageT, ?> extension) {
953961
if (extension.getDescriptor().getContainingType() != getDescriptorForType()) {
954962
// This can only happen if someone uses unchecked operations.
@@ -1232,6 +1240,45 @@ private void verifyContainingType(final FieldDescriptor field) {
12321240
throw new IllegalArgumentException("FieldDescriptor does not match message type.");
12331241
}
12341242
}
1243+
1244+
/** A wrapper for a field descriptor and its value. */
1245+
public static final class FieldEntry {
1246+
private final FieldDescriptor descriptor;
1247+
private final Object value;
1248+
1249+
public FieldDescriptor getDescriptor() {
1250+
return descriptor;
1251+
}
1252+
1253+
public Object getValue() {
1254+
return value;
1255+
}
1256+
1257+
FieldEntry(FieldDescriptor descriptor, Object value) {
1258+
this.descriptor = descriptor;
1259+
this.value = value;
1260+
}
1261+
}
1262+
1263+
private static final class FieldEntryIterator implements Iterator<FieldEntry> {
1264+
private final Iterator<Map.Entry<FieldDescriptor, Object>> iter;
1265+
1266+
FieldEntryIterator(FieldSet<FieldDescriptor> fieldSet) {
1267+
this.iter = fieldSet.iterator();
1268+
}
1269+
1270+
@Override
1271+
public final boolean hasNext() {
1272+
return iter.hasNext();
1273+
}
1274+
1275+
@Override
1276+
public final FieldEntry next() {
1277+
// Just let the inner iterator throw the NoSuchElementException.
1278+
Map.Entry<FieldDescriptor, Object> entry = iter.next();
1279+
return new FieldEntry(entry.getKey(), entry.getValue());
1280+
}
1281+
}
12351282
}
12361283

12371284
/**

0 commit comments

Comments
 (0)