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
C# Proto2 feature : Groups #5183
Merged
anandolee
merged 11 commits into
protocolbuffers:master
from
ObsidianMinor:csharp/proto2-feature/groups
Nov 5, 2018
Merged
Changes from 5 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
8c13fe7
Group library changes
ObsidianMinor 9024b49
Group compiler changes
ObsidianMinor 9c079c5
Fixed a typo in FieldCodec which resulted in some failed tests
ObsidianMinor 8a43b56
Added new group files to cmake build files
ObsidianMinor 1048bf0
Insert ReachedTagLimit check on ReadTag to return 0 on last tag
ObsidianMinor f7f732d
Compiler changes (end tag review)
ObsidianMinor 7b7b436
Generated code changes (end tag review)
ObsidianMinor 97b7da7
Library changes (end tag review)
ObsidianMinor 6864106
Write group end tags in repeated fields
ObsidianMinor 75b6351
Readability review
ObsidianMinor 1f97065
Remove C# group files from libprotoc.cmake
ObsidianMinor File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -108,6 +108,7 @@ public sealed class CodedInputStream : IDisposable | |
/// The absolute position of the end of the current message. | ||
/// </summary> | ||
private int currentLimit = int.MaxValue; | ||
private uint tagLimit = uint.MaxValue; | ||
|
||
private int recursionDepth = 0; | ||
|
||
|
@@ -373,7 +374,7 @@ public uint ReadTag() | |
if (IsAtEnd) | ||
{ | ||
lastTag = 0; | ||
return 0; // This is the only case in which we return 0. | ||
return 0; | ||
} | ||
|
||
lastTag = ReadRawVarint32(); | ||
|
@@ -383,6 +384,10 @@ public uint ReadTag() | |
// If we actually read a tag with a field of 0, that's not a valid tag. | ||
throw InvalidProtocolBufferException.InvalidTag(); | ||
} | ||
if (ReachedLimit || ReachedTagLimit) | ||
{ | ||
return 0; | ||
} | ||
return lastTag; | ||
} | ||
|
||
|
@@ -591,6 +596,26 @@ public void ReadMessage(IMessage builder) | |
PopLimit(oldLimit); | ||
} | ||
|
||
/// <summary> | ||
/// Reads an embedded group field from the stream. | ||
/// </summary> | ||
public void ReadGroup(IMessage builder) | ||
{ | ||
if (recursionDepth >= recursionLimit) | ||
{ | ||
throw InvalidProtocolBufferException.RecursionLimitExceeded(); | ||
} | ||
uint oldTag = PushTag(); | ||
++recursionDepth; | ||
builder.MergeFrom(this); | ||
if (!ReachedTagLimit) | ||
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. No need to push and pop the expected end group tag. Can calculate the expected tag and do the compare here directly. |
||
{ | ||
throw InvalidProtocolBufferException.TruncatedMessage(); | ||
} | ||
--recursionDepth; | ||
PopTag(oldTag); | ||
} | ||
|
||
/// <summary> | ||
/// Reads a bytes field value from the stream. | ||
/// </summary> | ||
|
@@ -953,6 +978,19 @@ internal int PushLimit(int byteLimit) | |
return oldLimit; | ||
} | ||
|
||
/// <summary> | ||
/// Sets tagLimit to the limit calculated by the last tag. | ||
/// This is called when descending into a group message. The previous limit is returns. | ||
/// </summary> | ||
/// <returns>The old limit</returns> | ||
internal uint PushTag() | ||
{ | ||
uint oldLimit = tagLimit; | ||
uint newLimit = WireFormat.MakeTag(WireFormat.GetTagFieldNumber(LastTag), WireFormat.WireType.EndGroup); | ||
tagLimit = newLimit; | ||
return oldLimit; | ||
} | ||
|
||
private void RecomputeBufferSizeAfterLimit() | ||
{ | ||
bufferSize += bufferSizeAfterLimit; | ||
|
@@ -978,6 +1016,14 @@ internal void PopLimit(int oldLimit) | |
RecomputeBufferSizeAfterLimit(); | ||
} | ||
|
||
/// <summary> | ||
/// Discards the current limit, returning the previous limit | ||
/// </summary> | ||
internal void PopTag(uint oldTag) | ||
{ | ||
tagLimit = oldTag; | ||
} | ||
|
||
/// <summary> | ||
/// Returns whether or not all the data before the limit has been read. | ||
/// </summary> | ||
|
@@ -995,6 +1041,14 @@ internal bool ReachedLimit | |
} | ||
} | ||
|
||
internal bool ReachedTagLimit | ||
{ | ||
get | ||
{ | ||
return tagLimit == lastTag; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Returns true if the stream has reached the end of the input. This is the | ||
/// case if either the end of the underlying input source has been reached or | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
I understand you want to ReadTag returns 0 for the expected end group thus Merge/Parse can be stopped at the tag. However end group tag is a valid tag and returns 0 makes this function logically wrong. It will also introduce some error for example in SkipGroup():
protobuf/csharp/src/Google.Protobuf/CodedInputStream.cs
Line 447 in d9ccd0c
It is easy to fix SkipGroup though but I still think ReadTag should return the valid tag. For Merge/Parse stop issue, I checked with java and it is using parseUnknownField() for decision :
protobuf/src/google/protobuf/compiler/java/java_message.cc
Line 1287 in ba8692f