-
Notifications
You must be signed in to change notification settings - Fork 184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle unknown fields part of a oneof #324
base: master
Are you sure you want to change the base?
Changes from all commits
a1cfc04
2e9934d
d53a9fb
5f66ac0
2f7be7e
309d4cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -236,24 +236,23 @@ class _FieldSet { | |
bool _hasField(int tagNumber) { | ||
var fi = _nonExtensionInfo(tagNumber); | ||
if (fi != null) return _$has(fi.index); | ||
if (_hasUnknownFields && _unknownFields.hasField(tagNumber)) { | ||
return true; | ||
} | ||
if (!_hasExtensions) return false; | ||
return _extensions._hasField(tagNumber); | ||
} | ||
|
||
void _clearField(int tagNumber) { | ||
_ensureWritable(); | ||
int oneofIndex = _meta.oneofs[tagNumber]; | ||
if (oneofIndex != null) _oneofCases.remove(oneofIndex); | ||
|
||
var fi = _nonExtensionInfo(tagNumber); | ||
if (fi != null) { | ||
// clear a non-extension field | ||
if (_hasObservers) _eventPlugin.beforeClearField(fi); | ||
_values[fi.index] = null; | ||
|
||
if (_meta.oneofs.containsKey(fi.tagNumber)) { | ||
_oneofCases.remove(_meta.oneofs[fi.tagNumber]); | ||
} | ||
|
||
int oneofIndex = _meta.oneofs[fi.tagNumber]; | ||
if (oneofIndex != null) _oneofCases[oneofIndex] = 0; | ||
return; | ||
} | ||
|
||
|
@@ -265,8 +264,9 @@ class _FieldSet { | |
} | ||
} | ||
|
||
// neither a regular field nor an extension. | ||
// TODO(skybrian) throw? | ||
if (_hasUnknownFields) { | ||
_unknownFields._clearField(tagNumber); | ||
} | ||
} | ||
|
||
/// Sets a non-repeated field with error-checking. | ||
|
@@ -342,14 +342,18 @@ class _FieldSet { | |
return newValue; | ||
} | ||
|
||
/// Sets a non-extended field and fires events. | ||
void _setNonExtensionFieldUnchecked(FieldInfo fi, value) { | ||
int tag = fi.tagNumber; | ||
int oneofIndex = _meta.oneofs[tag]; | ||
void _updateOneOfCase(int newTagnumber) { | ||
sigurdm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
int oneofIndex = _meta.oneofs[newTagnumber]; | ||
if (oneofIndex != null) { | ||
_clearField(_oneofCases[oneofIndex]); | ||
_oneofCases[oneofIndex] = tag; | ||
final currentTagnumber = _oneofCases[oneofIndex]; | ||
if (currentTagnumber != null) _clearField(currentTagnumber); | ||
_oneofCases[oneofIndex] = newTagnumber; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe only call it conditionally final currentTag = _oneofCases[oneofIndex];
if (currentTag != null) _clearField(currentTag); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes - that's better |
||
} | ||
} | ||
|
||
/// Sets a non-extended field and fires events. | ||
void _setNonExtensionFieldUnchecked(FieldInfo fi, value) { | ||
_updateOneOfCase(fi.tagNumber); | ||
|
||
// It is important that the callback to the observers is not moved to the | ||
// beginning of this method but happens just before the value is set. | ||
|
@@ -498,13 +502,7 @@ class _FieldSet { | |
if (_hasObservers) { | ||
_eventPlugin.beforeSetField(_nonExtensionInfoByIndex(index), value); | ||
} | ||
int tag = _meta.byIndex[index].tagNumber; | ||
int oneofIndex = _meta.oneofs[tag]; | ||
|
||
if (oneofIndex != null) { | ||
_clearField(_oneofCases[oneofIndex]); | ||
_oneofCases[oneofIndex] = tag; | ||
} | ||
_updateOneOfCase(_meta.byIndex[index].tagNumber); | ||
_values[index] = value; | ||
} | ||
|
||
|
@@ -713,7 +711,12 @@ class _FieldSet { | |
} | ||
|
||
if (other._hasUnknownFields) { | ||
_ensureUnknownFields().mergeFromUnknownFieldSet(other._unknownFields); | ||
final unknownFieldSet = _ensureUnknownFields(); | ||
final otherUnknownFieldSet = other._unknownFields; | ||
otherUnknownFieldSet._fields.forEach((key, value) { | ||
_updateOneOfCase(key); | ||
unknownFieldSet.mergeField(key, value); | ||
}); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -300,8 +300,11 @@ abstract class GeneratedMessage { | |
|
||
/// Clears the contents of a given field. | ||
/// | ||
/// If it's an extension field, the Extension will be kept. | ||
/// The tagNumber should be a valid tag or extension. | ||
/// If it's an extension field, the value will be removed, but the Extension | ||
/// will be kept. | ||
/// | ||
/// If the tagNumber is present as an unknown field, that field will be | ||
/// removed. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
void _mergeFromMessage(_FieldSet other) {
for (FieldInfo fi in other._infosSortedByTag) {
var value = other._values[fi.index];
if (value != null) _mergeField(fi, value, isExtension: false);
}
if (other._hasExtensions) {
var others = other._extensions;
for (int tagNumber in others._tagNumbers) {
var extension = others._getInfoOrNull(tagNumber);
var value = others._getFieldOrNull(extension);
_mergeField(extension, value, isExtension: true);
}
}
if (other._hasUnknownFields) {
_ensureUnknownFields().mergeFromUnknownFieldSet(other._unknownFields);
}
} This merging does not seem to account for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe my comment was not clear, what I meant is the following: We seem to have an invariant now
This invariant is violated because of this line: if (other._hasUnknownFields) {
_ensureUnknownFields().mergeFromUnknownFieldSet(other._unknownFields);
} We might have already a oneof candidate in the fieldset (or the unknown fieldset). Yet this code blindly copies There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah - now I get it - thanks! I updated the merging of unknown fields to go field by field, and also update the one-ofs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, Martin. Thanks. |
||
void clearField(int tagNumber) => _fieldSet._clearField(tagNumber); | ||
|
||
int $_whichOneof(int oneofIndex) => _fieldSet._oneofCases[oneofIndex] ?? 0; | ||
|
@@ -355,6 +358,8 @@ abstract class GeneratedMessage { | |
_fieldSet._extensions._getFieldOrNull(extension) != null; | ||
|
||
/// Returns [:true:] if this message has a field associated with [tagNumber]. | ||
/// | ||
/// Will return [:true:] even if that field is an unknown field. | ||
bool hasField(int tagNumber) => _fieldSet._hasField(tagNumber); | ||
|
||
/// Merges the contents of the [other] into this message. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it intentional that
_clearField(tagNumber)
checks unknown field set, but e.g._hasField(tagNumber)
does not?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question!
I think we could change the _hasField semantics also.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are now changing semantics to include unknowns, I agree that it is inconsistent if we don't also update
_hasField
. Good catch!