upb: implement IsExactlyEqual() for proto messages

PiperOrigin-RevId: 543780133
pull/13171/head
Eric Salo 1 year ago committed by Copybara-Service
parent dbbc4a30f9
commit 0c2a2511a8
  1. 24
      upb/message/accessors.c
  2. 4
      upb/message/accessors.h

@ -66,3 +66,27 @@ upb_MapInsertStatus upb_Message_InsertMapEntry(upb_Map* map,
&map_entry_value);
return upb_Map_Insert(map, map_entry_key, map_entry_value, arena);
}
bool upb_Message_IsExactlyEqual(const upb_Message* m1, const upb_Message* m2,
const upb_MiniTable* layout) {
if (m1 == m2) return true;
int opts = kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic;
upb_Arena* a = upb_Arena_New();
// Compare deterministically serialized payloads with no unknown fields.
size_t size1, size2;
char *data1, *data2;
upb_EncodeStatus status1 = upb_Encode(m1, layout, opts, a, &data1, &size1);
upb_EncodeStatus status2 = upb_Encode(m2, layout, opts, a, &data2, &size2);
if (status1 != kUpb_EncodeStatus_Ok || status2 != kUpb_EncodeStatus_Ok) {
// TODO(salo): How should we fail here? (In Ruby we throw an exception.)
upb_Arena_Free(a);
return false;
}
const bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
upb_Arena_Free(a);
return ret;
}

@ -387,6 +387,10 @@ upb_MapInsertStatus upb_Message_InsertMapEntry(upb_Map* map,
upb_Message* map_entry_message,
upb_Arena* arena);
// Compares two messages by serializing them and calling memcmp().
bool upb_Message_IsExactlyEqual(const upb_Message* m1, const upb_Message* m2,
const upb_MiniTable* layout);
#ifdef __cplusplus
} /* extern "C" */
#endif

Loading…
Cancel
Save