aboutsummaryrefslogtreecommitdiff
path: root/csharp/ProtocolBuffers
diff options
context:
space:
mode:
authorJon Skeet <skeet@pobox.com>2008-08-14 20:35:25 +0100
committerJon Skeet <skeet@pobox.com>2008-08-14 20:35:25 +0100
commitcabd06d12fd7bd53c1896e8f77617cc00de70c4c (patch)
treeffae881275c3f2dd6d4021b355a1a477fa1470b7 /csharp/ProtocolBuffers
parent794409b379305d18dd0bb4d9ee1cabfd9b6da2d5 (diff)
downloadprotobuf-cabd06d12fd7bd53c1896e8f77617cc00de70c4c.tar.gz
protobuf-cabd06d12fd7bd53c1896e8f77617cc00de70c4c.tar.bz2
protobuf-cabd06d12fd7bd53c1896e8f77617cc00de70c4c.zip
More tests, and implementation of UninitializedMessageException description.
Diffstat (limited to 'csharp/ProtocolBuffers')
-rw-r--r--csharp/ProtocolBuffers/AbstractBuilder.cs4
-rw-r--r--csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs75
-rw-r--r--csharp/ProtocolBuffers/DynamicMessage.cs13
-rw-r--r--csharp/ProtocolBuffers/GeneratedBuilder.cs6
-rw-r--r--csharp/ProtocolBuffers/IBuilder.cs4
-rw-r--r--csharp/ProtocolBuffers/UninitializedMessageException.cs98
6 files changed, 128 insertions, 72 deletions
diff --git a/csharp/ProtocolBuffers/AbstractBuilder.cs b/csharp/ProtocolBuffers/AbstractBuilder.cs
index d65c0911..94077d4f 100644
--- a/csharp/ProtocolBuffers/AbstractBuilder.cs
+++ b/csharp/ProtocolBuffers/AbstractBuilder.cs
@@ -12,7 +12,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
public abstract class AbstractBuilder : IBuilder {
#region Unimplemented members of IBuilder
- public abstract bool Initialized { get; }
+ public abstract bool IsInitialized { get; }
public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
public abstract object this[FieldDescriptor field] { get; set; }
public abstract MessageDescriptor DescriptorForType { get; }
@@ -78,7 +78,7 @@ namespace Google.ProtocolBuffers {
// implementations).
// TODO(jonskeet): Provide a function somewhere called makeDeepCopy()
// which allows people to make secure deep copies of messages.
- foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
+ foreach (KeyValuePair<FieldDescriptor, object> entry in other.AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
// Concatenate repeated fields
diff --git a/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
index 14e1f177..a7772cf8 100644
--- a/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
+++ b/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
@@ -278,9 +278,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
#region Messages
public sealed partial class FileDescriptorProto : pb::GeneratedMessage<FileDescriptorProto, FileDescriptorProto.Builder> {
- // Use FileDescriptorProto.CreateBuilder() to construct.
- private FileDescriptorProto() {}
-
private static readonly FileDescriptorProto defaultInstance = new FileDescriptorProto();
public static FileDescriptorProto DefaultInstance {
get { return defaultInstance; }
@@ -471,7 +468,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::FileDescriptorProto ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::FileDescriptorProto parseFrom(byte[] data,
+ public static self::FileDescriptorProto ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -960,9 +957,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class DescriptorProto : pb::GeneratedMessage<DescriptorProto, DescriptorProto.Builder> {
- // Use DescriptorProto.CreateBuilder() to construct.
- private DescriptorProto() {}
-
private static readonly DescriptorProto defaultInstance = new DescriptorProto();
public static DescriptorProto DefaultInstance {
get { return defaultInstance; }
@@ -983,9 +977,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
#region Nested types
public static class Types {
public sealed partial class ExtensionRange : pb::GeneratedMessage<ExtensionRange, ExtensionRange.Builder> {
- // Use ExtensionRange.CreateBuilder() to construct.
- private ExtensionRange() {}
-
private static readonly ExtensionRange defaultInstance = new ExtensionRange();
public static ExtensionRange DefaultInstance {
get { return defaultInstance; }
@@ -1069,7 +1060,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::DescriptorProto.Types.ExtensionRange ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::DescriptorProto.Types.ExtensionRange parseFrom(byte[] data,
+ public static self::DescriptorProto.Types.ExtensionRange ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -1389,7 +1380,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::DescriptorProto ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::DescriptorProto parseFrom(byte[] data,
+ public static self::DescriptorProto ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -1867,9 +1858,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class FieldDescriptorProto : pb::GeneratedMessage<FieldDescriptorProto, FieldDescriptorProto.Builder> {
- // Use FieldDescriptorProto.CreateBuilder() to construct.
- private FieldDescriptorProto() {}
-
private static readonly FieldDescriptorProto defaultInstance = new FieldDescriptorProto();
public static FieldDescriptorProto DefaultInstance {
get { return defaultInstance; }
@@ -2079,7 +2067,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::FieldDescriptorProto ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::FieldDescriptorProto parseFrom(byte[] data,
+ public static self::FieldDescriptorProto ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -2428,9 +2416,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class EnumDescriptorProto : pb::GeneratedMessage<EnumDescriptorProto, EnumDescriptorProto.Builder> {
- // Use EnumDescriptorProto.CreateBuilder() to construct.
- private EnumDescriptorProto() {}
-
private static readonly EnumDescriptorProto defaultInstance = new EnumDescriptorProto();
public static EnumDescriptorProto DefaultInstance {
get { return defaultInstance; }
@@ -2532,7 +2517,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::EnumDescriptorProto ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::EnumDescriptorProto parseFrom(byte[] data,
+ public static self::EnumDescriptorProto ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -2774,9 +2759,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class EnumValueDescriptorProto : pb::GeneratedMessage<EnumValueDescriptorProto, EnumValueDescriptorProto.Builder> {
- // Use EnumValueDescriptorProto.CreateBuilder() to construct.
- private EnumValueDescriptorProto() {}
-
private static readonly EnumValueDescriptorProto defaultInstance = new EnumValueDescriptorProto();
public static EnumValueDescriptorProto DefaultInstance {
get { return defaultInstance; }
@@ -2876,7 +2858,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::EnumValueDescriptorProto ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::EnumValueDescriptorProto parseFrom(byte[] data,
+ public static self::EnumValueDescriptorProto ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -3085,9 +3067,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class ServiceDescriptorProto : pb::GeneratedMessage<ServiceDescriptorProto, ServiceDescriptorProto.Builder> {
- // Use ServiceDescriptorProto.CreateBuilder() to construct.
- private ServiceDescriptorProto() {}
-
private static readonly ServiceDescriptorProto defaultInstance = new ServiceDescriptorProto();
public static ServiceDescriptorProto DefaultInstance {
get { return defaultInstance; }
@@ -3189,7 +3168,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::ServiceDescriptorProto ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::ServiceDescriptorProto parseFrom(byte[] data,
+ public static self::ServiceDescriptorProto ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -3431,9 +3410,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class MethodDescriptorProto : pb::GeneratedMessage<MethodDescriptorProto, MethodDescriptorProto.Builder> {
- // Use MethodDescriptorProto.CreateBuilder() to construct.
- private MethodDescriptorProto() {}
-
private static readonly MethodDescriptorProto defaultInstance = new MethodDescriptorProto();
public static MethodDescriptorProto DefaultInstance {
get { return defaultInstance; }
@@ -3549,7 +3525,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::MethodDescriptorProto ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::MethodDescriptorProto parseFrom(byte[] data,
+ public static self::MethodDescriptorProto ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -3784,9 +3760,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class FileOptions : pb::GeneratedMessage<FileOptions, FileOptions.Builder> {
- // Use FileOptions.CreateBuilder() to construct.
- private FileOptions() {}
-
private static readonly FileOptions defaultInstance = new FileOptions();
public static FileOptions DefaultInstance {
get { return defaultInstance; }
@@ -3991,7 +3964,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::FileOptions ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::FileOptions parseFrom(byte[] data,
+ public static self::FileOptions ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -4340,9 +4313,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class MessageOptions : pb::GeneratedMessage<MessageOptions, MessageOptions.Builder> {
- // Use MessageOptions.CreateBuilder() to construct.
- private MessageOptions() {}
-
private static readonly MessageOptions defaultInstance = new MessageOptions();
public static MessageOptions DefaultInstance {
get { return defaultInstance; }
@@ -4410,7 +4380,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::MessageOptions ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::MessageOptions parseFrom(byte[] data,
+ public static self::MessageOptions ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -4546,9 +4516,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class FieldOptions : pb::GeneratedMessage<FieldOptions, FieldOptions.Builder> {
- // Use FieldOptions.CreateBuilder() to construct.
- private FieldOptions() {}
-
private static readonly FieldOptions defaultInstance = new FieldOptions();
public static FieldOptions DefaultInstance {
get { return defaultInstance; }
@@ -4641,7 +4608,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::FieldOptions ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::FieldOptions parseFrom(byte[] data,
+ public static self::FieldOptions ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -4808,9 +4775,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class EnumOptions : pb::GeneratedMessage<EnumOptions, EnumOptions.Builder> {
- // Use EnumOptions.CreateBuilder() to construct.
- private EnumOptions() {}
-
private static readonly EnumOptions defaultInstance = new EnumOptions();
public static EnumOptions DefaultInstance {
get { return defaultInstance; }
@@ -4862,7 +4826,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::EnumOptions ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::EnumOptions parseFrom(byte[] data,
+ public static self::EnumOptions ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -4972,9 +4936,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class EnumValueOptions : pb::GeneratedMessage<EnumValueOptions, EnumValueOptions.Builder> {
- // Use EnumValueOptions.CreateBuilder() to construct.
- private EnumValueOptions() {}
-
private static readonly EnumValueOptions defaultInstance = new EnumValueOptions();
public static EnumValueOptions DefaultInstance {
get { return defaultInstance; }
@@ -5026,7 +4987,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::EnumValueOptions ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::EnumValueOptions parseFrom(byte[] data,
+ public static self::EnumValueOptions ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -5136,9 +5097,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class ServiceOptions : pb::GeneratedMessage<ServiceOptions, ServiceOptions.Builder> {
- // Use ServiceOptions.CreateBuilder() to construct.
- private ServiceOptions() {}
-
private static readonly ServiceOptions defaultInstance = new ServiceOptions();
public static ServiceOptions DefaultInstance {
get { return defaultInstance; }
@@ -5190,7 +5148,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::ServiceOptions ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::ServiceOptions parseFrom(byte[] data,
+ public static self::ServiceOptions ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
@@ -5300,9 +5258,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public sealed partial class MethodOptions : pb::GeneratedMessage<MethodOptions, MethodOptions.Builder> {
- // Use MethodOptions.CreateBuilder() to construct.
- private MethodOptions() {}
-
private static readonly MethodOptions defaultInstance = new MethodOptions();
public static MethodOptions DefaultInstance {
get { return defaultInstance; }
@@ -5354,7 +5309,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static self::MethodOptions ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
- public static self::MethodOptions parseFrom(byte[] data,
+ public static self::MethodOptions ParseFrom(byte[] data,
pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))
.BuildParsed();
diff --git a/csharp/ProtocolBuffers/DynamicMessage.cs b/csharp/ProtocolBuffers/DynamicMessage.cs
index 5ffbdfbb..675c4c18 100644
--- a/csharp/ProtocolBuffers/DynamicMessage.cs
+++ b/csharp/ProtocolBuffers/DynamicMessage.cs
@@ -5,6 +5,11 @@ using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// An implementation of IMessage that can represent arbitrary types, given a MessageaDescriptor.
+ /// TODO: Implement appropriate generics.
+ /// </summary>
public class DynamicMessage : AbstractMessage {
private readonly MessageDescriptor type;
@@ -242,7 +247,7 @@ namespace Google.ProtocolBuffers {
return this;
}
- public override IBuilder MergeFrom(IMessage other) {
+ public override IBuilder MergeFrom(IMessage other) {
if (other.DescriptorForType != type) {
throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type.");
}
@@ -251,7 +256,7 @@ namespace Google.ProtocolBuffers {
}
protected override IMessage BuildImpl() {
- if (!Initialized) {
+ if (!IsInitialized) {
throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields));
}
return BuildPartialImpl();
@@ -263,7 +268,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
/// <returns></returns>
internal DynamicMessage BuildParsed() {
- if (!Initialized) {
+ if (!IsInitialized) {
throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)).AsInvalidProtocolBufferException();
}
return (DynamicMessage) BuildPartialImpl();
@@ -283,7 +288,7 @@ namespace Google.ProtocolBuffers {
return result;
}
- public override bool Initialized {
+ public override bool IsInitialized {
get { return fields.IsInitializedWithRespectTo(type); }
}
diff --git a/csharp/ProtocolBuffers/GeneratedBuilder.cs b/csharp/ProtocolBuffers/GeneratedBuilder.cs
index 154aa05f..a4114b5d 100644
--- a/csharp/ProtocolBuffers/GeneratedBuilder.cs
+++ b/csharp/ProtocolBuffers/GeneratedBuilder.cs
@@ -26,7 +26,7 @@ namespace Google.ProtocolBuffers {
get { return MessageBeingBuilt.FieldAccesseorsFromBuilder; }
}
- public override bool Initialized {
+ public override bool IsInitialized {
get { return MessageBeingBuilt.IsInitialized; }
}
@@ -212,7 +212,7 @@ namespace Google.ProtocolBuffers {
/// TODO(jonskeet): This used to be generated for each class. Find out why.
/// </summary>
public TMessage BuildParsed() {
- if (!Initialized) {
+ if (!IsInitialized) {
throw new UninitializedMessageException(MessageBeingBuilt).AsInvalidProtocolBufferException();
}
return BuildPartial();
@@ -223,7 +223,7 @@ namespace Google.ProtocolBuffers {
/// TODO(jonskeet): This used to be generated for each class. Find out why.
/// </summary>
public TMessage Build() {
- if (!Initialized) {
+ if (!IsInitialized) {
throw new UninitializedMessageException(MessageBeingBuilt);
}
return BuildPartial();
diff --git a/csharp/ProtocolBuffers/IBuilder.cs b/csharp/ProtocolBuffers/IBuilder.cs
index b46842cd..dcb3d272 100644
--- a/csharp/ProtocolBuffers/IBuilder.cs
+++ b/csharp/ProtocolBuffers/IBuilder.cs
@@ -33,7 +33,7 @@ namespace Google.ProtocolBuffers {
/// Returns true iff all required fields in the message and all
/// embedded messages are set.
/// </summary>
- bool Initialized { get; }
+ bool IsInitialized { get; }
/// <summary>
/// Behaves like the equivalent property in IMessage&lt;T&gt;.
@@ -172,7 +172,7 @@ namespace Google.ProtocolBuffers {
/// required fields, it will throw an UninitializedMessageException.
/// There are a few good ways to deal with this:
/// <list>
- /// <item>Call Initialized to verify to verify that all required fields are
+ /// <item>Call IsInitialized to verify to verify that all required fields are
/// set before building.</item>
/// <item>Parse the message separately using one of the static ParseFrom
/// methods, then use MergeFrom(IMessage&lt;T&gt;) to merge it with
diff --git a/csharp/ProtocolBuffers/UninitializedMessageException.cs b/csharp/ProtocolBuffers/UninitializedMessageException.cs
index 530f2057..01cdd2f1 100644
--- a/csharp/ProtocolBuffers/UninitializedMessageException.cs
+++ b/csharp/ProtocolBuffers/UninitializedMessageException.cs
@@ -14,15 +14,111 @@
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Google.ProtocolBuffers.Collections;
+using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
public class UninitializedMessageException : Exception {
- public UninitializedMessageException(IMessage message) {
+ private readonly IList<string> missingFields;
+
+ public UninitializedMessageException(IMessage message)
+ : this(FindMissingFields(message)) {
+ }
+
+ private UninitializedMessageException(IList<string> missingFields)
+ : base(BuildDescription(missingFields)) {
+ this.missingFields = Lists.AsReadOnly(missingFields);
}
+
+ /// <summary>
+ /// Converts this exception into an InvalidProtocolBufferException.
+ /// When a parsed message is missing required fields, this should be thrown
+ /// instead of UninitializedMessageException.
+ /// </summary>
public InvalidProtocolBufferException AsInvalidProtocolBufferException() {
return new InvalidProtocolBufferException(Message);
}
+
+ /// <summary>
+ /// Constructs the description string for a given list of missing fields.
+ /// </summary>
+ private static string BuildDescription(IEnumerable<string> missingFields) {
+ StringBuilder description = new StringBuilder("Message missing required fields: ");
+ bool first = true;
+ foreach(string field in missingFields) {
+ if (first) {
+ first = false;
+ } else {
+ description.Append(", ");
+ }
+ description.Append(field);
+ }
+ return description.ToString();
+ }
+
+ /// <summary>
+ /// Returns a list of the full "paths" of missing required
+ /// fields in the specified message.
+ /// </summary>
+ private static IList<String> FindMissingFields(IMessage message) {
+ List<String> results = new List<String>();
+ FindMissingFields(message, "", results);
+ return results;
+ }
+
+ /// <summary>
+ /// Recursive helper implementing FindMissingFields.
+ /// </summary>
+ private static void FindMissingFields(IMessage message, String prefix, List<String> results) {
+ foreach (FieldDescriptor field in message.DescriptorForType.Fields) {
+ if (field.IsRequired && !message.HasField(field)) {
+ results.Add(prefix + field.Name);
+ }
+ }
+
+ foreach (KeyValuePair<FieldDescriptor, object> entry in message.AllFields) {
+ FieldDescriptor field = entry.Key;
+ object value = entry.Value;
+
+ if (field.MappedType == MappedType.Message) {
+ if (field.IsRepeated) {
+ int i = 0;
+ foreach (object element in (IEnumerable) value) {
+ FindMissingFields((IMessage) element, SubMessagePrefix(prefix, field, i++), results);
+ }
+ } else {
+ if (message.HasField(field)) {
+ FindMissingFields((IMessage) value, SubMessagePrefix(prefix, field, -1), results);
+ }
+ }
+ }
+ }
+ }
+
+ private static String SubMessagePrefix(String prefix, FieldDescriptor field, int index) {
+ StringBuilder result = new StringBuilder(prefix);
+ if (field.IsExtension) {
+ result.Append('(')
+ .Append(field.FullName)
+ .Append(')');
+ } else {
+ result.Append(field.Name);
+ }
+ if (index != -1) {
+ result.Append('[')
+ .Append(index)
+ .Append(']');
+ }
+ result.Append('.');
+ return result.ToString();
+ }
}
}
+
+
+