Skip to content

Instantly share code, notes, and snippets.

@iOliverNguyen
Created March 1, 2022 17:25
Show Gist options
  • Save iOliverNguyen/de7390aead33f3ee82160adddd0dd76b to your computer and use it in GitHub Desktop.
Save iOliverNguyen/de7390aead33f3ee82160adddd0dd76b to your computer and use it in GitHub Desktop.
// unpopulatedFieldRanger wraps a protoreflect.Message and modifies its Range
// method to additionally iterate over unpopulated fields.
type unpopulatedFieldRanger struct{ pref.Message }
func (m unpopulatedFieldRanger) Range(f func(pref.FieldDescriptor, pref.Value) bool) {
fds := m.Descriptor().Fields()
for i := 0; i < fds.Len(); i++ {
fd := fds.Get(i)
if m.Has(fd) || fd.ContainingOneof() != nil {
continue // ignore populated fields and fields within a oneofs
}
v := m.Get(fd)
isProto2Scalar := fd.Syntax() == pref.Proto2 && fd.Default().IsValid()
isSingularMessage := fd.Cardinality() != pref.Repeated && fd.Message() != nil
if isProto2Scalar || isSingularMessage {
v = pref.Value{} // use invalid value to emit null
}
if !f(fd, v) {
return
}
}
m.Message.Range(f)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment