diff options
author | csharptest <roger@csharptest.net> | 2010-11-09 20:49:12 -0600 |
---|---|---|
committer | csharptest <roger@csharptest.net> | 2010-11-09 20:49:12 -0600 |
commit | 272cb8aee775de65e08b4ab17c485cd678d08266 (patch) | |
tree | 3489244ff5bd901592b535ea5ad9352096d1521f /src/ProtocolBuffers | |
parent | e49547735834485dd22842e1a82bc5ae4139b8a8 (diff) | |
download | protobuf-272cb8aee775de65e08b4ab17c485cd678d08266.tar.gz protobuf-272cb8aee775de65e08b4ab17c485cd678d08266.tar.bz2 protobuf-272cb8aee775de65e08b4ab17c485cd678d08266.zip |
Lite feature complete.
Diffstat (limited to 'src/ProtocolBuffers')
-rw-r--r-- | src/ProtocolBuffers/AbstractMessage.cs | 4 | ||||
-rw-r--r-- | src/ProtocolBuffers/AbstractMessageLite.cs | 2 | ||||
-rw-r--r-- | src/ProtocolBuffers/EnumLite.cs | 12 | ||||
-rw-r--r-- | src/ProtocolBuffers/ExtendableMessageLite.cs | 28 | ||||
-rw-r--r-- | src/ProtocolBuffers/ExtensionInfo.cs | 4 | ||||
-rw-r--r-- | src/ProtocolBuffers/FieldSet.cs | 1 | ||||
-rw-r--r-- | src/ProtocolBuffers/GeneratedExtensionBase.cs | 8 | ||||
-rw-r--r-- | src/ProtocolBuffers/GeneratedExtensionLite.cs | 16 | ||||
-rw-r--r-- | src/ProtocolBuffers/GeneratedMessageLite.cs | 80 | ||||
-rw-r--r-- | src/ProtocolBuffers/IMessageLite.cs | 5 | ||||
-rw-r--r-- | src/ProtocolBuffers/TextFormat.cs | 16 | ||||
-rw-r--r-- | src/ProtocolBuffers/UninitializedMessageException.cs | 14 | ||||
-rw-r--r-- | src/ProtocolBuffers/UnknownFieldSet.cs | 12 |
13 files changed, 176 insertions, 26 deletions
diff --git a/src/ProtocolBuffers/AbstractMessage.cs b/src/ProtocolBuffers/AbstractMessage.cs index e2cf3827..203b71a4 100644 --- a/src/ProtocolBuffers/AbstractMessage.cs +++ b/src/ProtocolBuffers/AbstractMessage.cs @@ -101,6 +101,10 @@ namespace Google.ProtocolBuffers { return TextFormat.PrintToString(this); } + public sealed override void PrintTo(TextWriter writer) { + TextFormat.Print(this, writer); + } + /// <summary> /// Serializes the message and writes it to the given output stream. /// This does not flush or close the stream. diff --git a/src/ProtocolBuffers/AbstractMessageLite.cs b/src/ProtocolBuffers/AbstractMessageLite.cs index 96884753..ee75f3dd 100644 --- a/src/ProtocolBuffers/AbstractMessageLite.cs +++ b/src/ProtocolBuffers/AbstractMessageLite.cs @@ -63,6 +63,8 @@ namespace Google.ProtocolBuffers { //public override int GetHashCode() { //} + public abstract void PrintTo(TextWriter writer); + #region IMessageLite<TMessage,TBuilder> Members /// <summary> diff --git a/src/ProtocolBuffers/EnumLite.cs b/src/ProtocolBuffers/EnumLite.cs index ab13c9ab..12497d8e 100644 --- a/src/ProtocolBuffers/EnumLite.cs +++ b/src/ProtocolBuffers/EnumLite.cs @@ -46,6 +46,7 @@ namespace Google.ProtocolBuffers { ///</summary> public interface IEnumLite { int Number { get; } + string Name { get; } } ///<summary> @@ -69,12 +70,15 @@ namespace Google.ProtocolBuffers { where TEnum : struct, IComparable, IFormattable { struct EnumValue : IEnumLite { - readonly int value; - public EnumValue(int value) { + readonly TEnum value; + public EnumValue(TEnum value) { this.value = value; } int IEnumLite.Number { - get { return value; } + get { return Convert.ToInt32(value); } + } + string IEnumLite.Name { + get { return value.ToString(); } } } @@ -83,7 +87,7 @@ namespace Google.ProtocolBuffers { public EnumLiteMap() { items = new SortedList<int, IEnumLite>(); foreach (TEnum evalue in Enum.GetValues(typeof(TEnum))) - items.Add(Convert.ToInt32(evalue), new EnumValue(Convert.ToInt32(evalue))); + items.Add(Convert.ToInt32(evalue), new EnumValue(evalue)); } IEnumLite IEnumLiteMap.FindValueByNumber(int number) { diff --git a/src/ProtocolBuffers/ExtendableMessageLite.cs b/src/ProtocolBuffers/ExtendableMessageLite.cs index fc2ccb6c..aed8545d 100644 --- a/src/ProtocolBuffers/ExtendableMessageLite.cs +++ b/src/ProtocolBuffers/ExtendableMessageLite.cs @@ -33,7 +33,10 @@ #endregion using System; +using System.Collections; using System.Collections.Generic; +using Google.ProtocolBuffers.Collections; + namespace Google.ProtocolBuffers { public abstract class ExtendableMessageLite<TMessage, TBuilder> : GeneratedMessageLite<TMessage, TBuilder> where TMessage : GeneratedMessageLite<TMessage, TBuilder> @@ -49,6 +52,31 @@ namespace Google.ProtocolBuffers { get { return extensions; } } + public override bool Equals(object obj) { + ExtendableMessageLite<TMessage, TBuilder> other = obj as ExtendableMessageLite<TMessage, TBuilder>; + return !ReferenceEquals(null, other) && + Dictionaries.Equals(extensions.AllFields, other.extensions.AllFields); + } + + public override int GetHashCode() { + return Dictionaries.GetHashCode(extensions.AllFields); + } + + /// <summary> + /// writes the extensions to the text stream + /// </summary> + public override void PrintTo(System.IO.TextWriter writer) { + foreach (KeyValuePair<IFieldDescriptorLite, object> entry in extensions.AllFields) { + string fn = string.Format("[{0}]", entry.Key.FullName); + if (entry.Key.IsRepeated) { + foreach (object o in ((IEnumerable)entry.Value)) + PrintField(fn, true, o, writer); + } else { + PrintField(fn, true, entry.Value, writer); + } + } + } + /// <summary> /// Checks if a singular extension is present. /// </summary> diff --git a/src/ProtocolBuffers/ExtensionInfo.cs b/src/ProtocolBuffers/ExtensionInfo.cs index 482f006a..5d99b8ff 100644 --- a/src/ProtocolBuffers/ExtensionInfo.cs +++ b/src/ProtocolBuffers/ExtensionInfo.cs @@ -48,12 +48,12 @@ namespace Google.ProtocolBuffers /// A default instance of the extensions's type, if it has a message type, /// or null otherwise. /// </summary> - public IMessage DefaultInstance { get; private set; } + public IMessageLite DefaultInstance { get; private set; } internal ExtensionInfo(FieldDescriptor descriptor) : this(descriptor, null) { } - internal ExtensionInfo(FieldDescriptor descriptor, IMessage defaultInstance) { + internal ExtensionInfo(FieldDescriptor descriptor, IMessageLite defaultInstance) { Descriptor = descriptor; DefaultInstance = defaultInstance; } diff --git a/src/ProtocolBuffers/FieldSet.cs b/src/ProtocolBuffers/FieldSet.cs index 838d0568..c3e3d740 100644 --- a/src/ProtocolBuffers/FieldSet.cs +++ b/src/ProtocolBuffers/FieldSet.cs @@ -47,6 +47,7 @@ namespace Google.ProtocolBuffers { bool IsExtension { get; } bool MessageSetWireFormat { get; } //field.ContainingType.Options.MessageSetWireFormat int FieldNumber { get; } + string FullName { get; } IEnumLiteMap EnumType { get; } FieldType FieldType { get; } MappedType MappedType { get; } diff --git a/src/ProtocolBuffers/GeneratedExtensionBase.cs b/src/ProtocolBuffers/GeneratedExtensionBase.cs index 36da58e6..aacc0655 100644 --- a/src/ProtocolBuffers/GeneratedExtensionBase.cs +++ b/src/ProtocolBuffers/GeneratedExtensionBase.cs @@ -66,7 +66,7 @@ namespace Google.ProtocolBuffers { public abstract class GeneratedExtensionBase<TExtension> { private readonly FieldDescriptor descriptor; - private readonly IMessage messageDefaultInstance; + private readonly IMessageLite messageDefaultInstance; protected GeneratedExtensionBase(FieldDescriptor descriptor, Type singularExtensionType) { if (!descriptor.IsExtension) { @@ -80,8 +80,8 @@ namespace Google.ProtocolBuffers { if (defaultInstanceProperty == null) { throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name); } -#warning ToDo - Invalid cast, could be IMessageLite - messageDefaultInstance = (IMessage)defaultInstanceProperty.GetValue(null, null); + + messageDefaultInstance = (IMessageLite)defaultInstanceProperty.GetValue(null, null); } } @@ -96,7 +96,7 @@ namespace Google.ProtocolBuffers { /// <summary> /// Returns the default message instance for extensions which are message types. /// </summary> - public IMessage MessageDefaultInstance { + public IMessageLite MessageDefaultInstance { get { return messageDefaultInstance; } } diff --git a/src/ProtocolBuffers/GeneratedExtensionLite.cs b/src/ProtocolBuffers/GeneratedExtensionLite.cs index 81d8d41b..33969f4b 100644 --- a/src/ProtocolBuffers/GeneratedExtensionLite.cs +++ b/src/ProtocolBuffers/GeneratedExtensionLite.cs @@ -48,6 +48,7 @@ namespace Google.ProtocolBuffers { } public class ExtensionDescriptorLite : IFieldDescriptorLite { + private readonly string fullName; private readonly IEnumLiteMap enumTypeMap; private readonly int number; private readonly FieldType type; @@ -56,7 +57,8 @@ namespace Google.ProtocolBuffers { private readonly MappedType mapType; private readonly object defaultValue; - public ExtensionDescriptorLite(IEnumLiteMap enumTypeMap, int number, FieldType type, object defaultValue, bool isRepeated, bool isPacked) { + public ExtensionDescriptorLite(string fullName, IEnumLiteMap enumTypeMap, int number, FieldType type, object defaultValue, bool isRepeated, bool isPacked) { + this.fullName = fullName; this.enumTypeMap = enumTypeMap; this.number = number; this.type = type; @@ -66,6 +68,8 @@ namespace Google.ProtocolBuffers { this.defaultValue = defaultValue; } + public string FullName { get { return fullName; } } + public bool IsRepeated { get { return isRepeated; } } @@ -116,9 +120,9 @@ namespace Google.ProtocolBuffers { public class GeneratedRepeatExtensionLite<TContainingType, TExtensionType> : GeneratedExtensionLite<TContainingType, IList<TExtensionType>> where TContainingType : IMessageLite { - public GeneratedRepeatExtensionLite(TContainingType containingTypeDefaultInstance, + public GeneratedRepeatExtensionLite(string fullName, TContainingType containingTypeDefaultInstance, IMessageLite messageDefaultInstance, IEnumLiteMap enumTypeMap, int number, FieldType type, bool isPacked) : - base(containingTypeDefaultInstance, new List<TExtensionType>(), messageDefaultInstance, enumTypeMap, number, type, isPacked) { + base(fullName, containingTypeDefaultInstance, new List<TExtensionType>(), messageDefaultInstance, enumTypeMap, number, type, isPacked) { } public override object ToReflectionType(object value) { @@ -167,6 +171,7 @@ namespace Google.ProtocolBuffers { /** For use by generated code only. */ public GeneratedExtensionLite( + string fullName, TContainingType containingTypeDefaultInstance, TExtensionType defaultValue, IMessageLite messageDefaultInstance, @@ -174,13 +179,14 @@ namespace Google.ProtocolBuffers { int number, FieldType type) : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance, - new ExtensionDescriptorLite(enumTypeMap, number, type, defaultValue, + new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, defaultValue, false /* isRepeated */, false /* isPacked */)) { } private static readonly IList<object> Empty = new object[0]; /** Repeating fields: For use by generated code only. */ protected GeneratedExtensionLite( + string fullName, TContainingType containingTypeDefaultInstance, TExtensionType defaultValue, IMessageLite messageDefaultInstance, @@ -189,7 +195,7 @@ namespace Google.ProtocolBuffers { FieldType type, bool isPacked) : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance, - new ExtensionDescriptorLite(enumTypeMap, number, type, Empty, + new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, Empty, true /* isRepeated */, isPacked)) { } diff --git a/src/ProtocolBuffers/GeneratedMessageLite.cs b/src/ProtocolBuffers/GeneratedMessageLite.cs index fd1c6216..b2a009c4 100644 --- a/src/ProtocolBuffers/GeneratedMessageLite.cs +++ b/src/ProtocolBuffers/GeneratedMessageLite.cs @@ -35,6 +35,8 @@ using System; using System.Collections.Generic; using System.Collections; +using System.Globalization; +using Google.ProtocolBuffers.Descriptors; namespace Google.ProtocolBuffers { @@ -48,5 +50,83 @@ namespace Google.ProtocolBuffers { where TBuilder : GeneratedBuilderLite<TMessage, TBuilder> { protected abstract TMessage ThisMessage { get; } + + public sealed override string ToString() { + using (System.IO.StringWriter wtr = new System.IO.StringWriter()) { + PrintTo(wtr); + return wtr.ToString(); + } + } + + /// <summary> + /// PrintTo() helper methods for Lite Runtime + /// </summary> + protected static void PrintField<T>(string name, IList<T> value, System.IO.TextWriter writer) { + foreach (T item in value) + PrintField(name, true, (object)item, writer); + } + /// <summary> + /// PrintTo() helper methods for Lite Runtime + /// </summary> + protected static void PrintField(string name, bool hasValue, object value, System.IO.TextWriter writer) { + if (!hasValue) return; + if (value is IMessageLite) { + writer.WriteLine("{0} {{", name); + ((IMessageLite)value).PrintTo(writer); + writer.WriteLine("}"); + } else if (value is ByteString || value is String) { + writer.Write("{0}: \"", name); + if(value is String) + EscapeBytes( System.Text.Encoding.UTF8.GetBytes((string)value), writer); + else + EscapeBytes(((ByteString)value), writer); + writer.WriteLine("\""); + } else if (value is bool) { + writer.WriteLine("{0}: {1}", name, (bool)value ? "true" : "false"); + } else if (value is IEnumLite) { + writer.WriteLine("{0}: {1}", name, ((IEnumLite)value).Name); + } + else { + writer.WriteLine("{0}: {1}", name, ((IConvertible)value).ToString(CultureInfo.InvariantCulture)); + } + } + + /// <summary> + /// COPIED from TextFormat + /// Escapes bytes in the format used in protocol buffer text format, which + /// is the same as the format used for C string literals. All bytes + /// that are not printable 7-bit ASCII characters are escaped, as well as + /// backslash, single-quote, and double-quote characters. Characters for + /// which no defined short-hand escape sequence is defined will be escaped + /// using 3-digit octal sequences. + /// The returned value is guaranteed to be entirely ASCII. + /// </summary> + private static void EscapeBytes(IEnumerable<byte> input, System.IO.TextWriter writer) { + foreach (byte b in input) { + switch (b) { + // C# does not use \a or \v + case 0x07: writer.Write("\\a"); break; + case (byte)'\b': writer.Write("\\b"); break; + case (byte)'\f': writer.Write("\\f"); break; + case (byte)'\n': writer.Write("\\n"); break; + case (byte)'\r': writer.Write("\\r"); break; + case (byte)'\t': writer.Write("\\t"); break; + case 0x0b: writer.Write("\\v"); break; + case (byte)'\\': writer.Write("\\\\"); break; + case (byte)'\'': writer.Write("\\\'"); break; + case (byte)'"': writer.Write("\\\""); break; + default: + if (b >= 0x20 && b < 128) { + writer.Write((char)b); + } else { + writer.Write('\\'); + writer.Write((char)('0' + ((b >> 6) & 3))); + writer.Write((char)('0' + ((b >> 3) & 7))); + writer.Write((char)('0' + (b & 7))); + } + break; + } + } + } } } diff --git a/src/ProtocolBuffers/IMessageLite.cs b/src/ProtocolBuffers/IMessageLite.cs index cb64e021..48660882 100644 --- a/src/ProtocolBuffers/IMessageLite.cs +++ b/src/ProtocolBuffers/IMessageLite.cs @@ -104,6 +104,11 @@ namespace Google.ProtocolBuffers { string ToString(); /// <summary> + /// Converts the message to a string. + /// </summary> + void PrintTo(TextWriter writer); + + /// <summary> /// Serializes the message to a ByteString. This is a trivial wrapper /// around WriteTo(CodedOutputStream). /// </summary> diff --git a/src/ProtocolBuffers/TextFormat.cs b/src/ProtocolBuffers/TextFormat.cs index 81033087..81b3447c 100644 --- a/src/ProtocolBuffers/TextFormat.cs +++ b/src/ProtocolBuffers/TextFormat.cs @@ -170,17 +170,19 @@ namespace Google.ProtocolBuffers { } case FieldType.Enum: { - generator.Print(((EnumValueDescriptor) value).Name); + if (value is IEnumLite && !(value is EnumValueDescriptor)) { + throw new NotSupportedException("Lite enumerations are not supported."); + } + generator.Print(((EnumValueDescriptor)value).Name); break; } case FieldType.Message: case FieldType.Group: - if (value is IMessage) { - Print((IMessage)value, generator); - } else { -#warning ToDo - What do we print for IMessageLite? + if (value is IMessageLite && !(value is IMessage)) { + throw new NotSupportedException("Lite messages are not supported."); } + Print((IMessage)value, generator); break; } } @@ -580,7 +582,9 @@ namespace Google.ProtocolBuffers { if (extension == null) { subBuilder = builder.CreateBuilderForField(field); } else { - subBuilder = extension.DefaultInstance.WeakCreateBuilderForType(); + subBuilder = extension.DefaultInstance.WeakCreateBuilderForType() as IBuilder; + if (subBuilder == null) + throw new NotSupportedException("Lite messages are not supported."); } while (!tokenizer.TryConsume(endToken)) { diff --git a/src/ProtocolBuffers/UninitializedMessageException.cs b/src/ProtocolBuffers/UninitializedMessageException.cs index c5bcd822..d7f58197 100644 --- a/src/ProtocolBuffers/UninitializedMessageException.cs +++ b/src/ProtocolBuffers/UninitializedMessageException.cs @@ -124,16 +124,24 @@ namespace Google.ProtocolBuffers { foreach (KeyValuePair<FieldDescriptor, object> entry in message.AllFields) { FieldDescriptor field = entry.Key; object value = entry.Value; -#warning ToDo - bad assumption, could be IMessageLite + 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); + if (element is IMessage) { + FindMissingFields((IMessage)element, SubMessagePrefix(prefix, field, i++), results); + } else { + results.Add(prefix + field.Name); + } } } else { if (message.HasField(field)) { - FindMissingFields((IMessage) value, SubMessagePrefix(prefix, field, -1), results); + if (value is IMessage) { + FindMissingFields((IMessage)value, SubMessagePrefix(prefix, field, -1), results); + } else { + results.Add(prefix + field.Name); + } } } } diff --git a/src/ProtocolBuffers/UnknownFieldSet.cs b/src/ProtocolBuffers/UnknownFieldSet.cs index 515637cc..594ae8bd 100644 --- a/src/ProtocolBuffers/UnknownFieldSet.cs +++ b/src/ProtocolBuffers/UnknownFieldSet.cs @@ -139,6 +139,14 @@ namespace Google.ProtocolBuffers { } /// <summary> + /// Converts the set to a string in protocol buffer text format. This + /// is just a trivial wrapper around TextFormat.PrintToString. + /// </summary> + public void PrintTo(TextWriter writer) { + TextFormat.Print(this, writer); + } + + /// <summary> /// Serializes the message to a ByteString and returns it. This is /// just a trivial wrapper around WriteTo(CodedOutputStream). /// </summary> @@ -533,7 +541,7 @@ namespace Google.ProtocolBuffers { int fieldNumber = WireFormat.GetTagFieldNumber(tag); FieldDescriptor field; - IMessage defaultFieldInstance = null; + IMessageLite defaultFieldInstance = null; if (type.IsExtensionNumber(fieldNumber)) { ExtensionInfo extension = extensionRegistry[type, fieldNumber]; @@ -644,7 +652,7 @@ namespace Google.ProtocolBuffers { int typeId = 0; ByteString rawBytes = null; // If we encounter "message" before "typeId" - IBuilder subBuilder = null; + IBuilderLite subBuilder = null; FieldDescriptor field = null; while (true) { |