diff options
Diffstat (limited to 'csharp/src/Google.Protobuf/MessageExtensions.cs')
-rw-r--r-- | csharp/src/Google.Protobuf/MessageExtensions.cs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs index 62181eb9..e1c57dc4 100644 --- a/csharp/src/Google.Protobuf/MessageExtensions.cs +++ b/csharp/src/Google.Protobuf/MessageExtensions.cs @@ -30,7 +30,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Reflection; +using System.Collections; using System.IO; +using System.Linq; namespace Google.Protobuf { @@ -140,6 +143,53 @@ namespace Google.Protobuf return ByteString.AttachBytes(message.ToByteArray()); } + /// <summary> + /// Checks if all required fields in a message have values set. For proto3 messages, this returns true + /// </summary> + public static bool IsInitialized(this IMessage message) + { + if (message.Descriptor.File.Proto.Syntax != "proto2") + { + return true; + } + + return message.Descriptor + .Fields + .InDeclarationOrder() + .All(f => + { + if (f.IsMap) + { + var map = (IDictionary)f.Accessor.GetValue(message); + return map.Values.OfType<IMessage>().All(IsInitialized); + } + else if (f.IsRepeated && f.MessageType != null) + { + var enumerable = (IEnumerable)f.Accessor.GetValue(message); + return enumerable.Cast<IMessage>().All(IsInitialized); + } + else if (f.MessageType != null) + { + if (f.Accessor.HasValue(message)) + { + return ((IMessage)f.Accessor.GetValue(message)).IsInitialized(); + } + else + { + return !f.IsRequired; + } + } + else if (f.IsRequired) + { + return f.Accessor.HasValue(message); + } + else + { + return true; + } + }); + } + // Implementations allowing unknown fields to be discarded. internal static void MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields) { |