aboutsummaryrefslogtreecommitdiff
path: root/csharp/ProtocolBuffers
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/ProtocolBuffers')
-rw-r--r--csharp/ProtocolBuffers/Delegates.cs8
-rw-r--r--csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs32
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs2
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs4
-rw-r--r--csharp/ProtocolBuffers/InvalidProtocolBufferException.cs5
-rw-r--r--csharp/ProtocolBuffers/MessageStreamIterator.cs124
-rw-r--r--csharp/ProtocolBuffers/MessageStreamWriter.cs33
-rw-r--r--csharp/ProtocolBuffers/ProtocolBuffers.csproj5
8 files changed, 193 insertions, 20 deletions
diff --git a/csharp/ProtocolBuffers/Delegates.cs b/csharp/ProtocolBuffers/Delegates.cs
new file mode 100644
index 00000000..2aa440b1
--- /dev/null
+++ b/csharp/ProtocolBuffers/Delegates.cs
@@ -0,0 +1,8 @@
+using System.IO;
+namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// Delegate to return a stream when asked, used by MessageStreamIterator.
+ /// </summary>
+ public delegate Stream StreamProvider();
+}
diff --git a/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
index c103cb19..e42c36f3 100644
--- a/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
+++ b/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
@@ -363,7 +363,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet result = new global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet();
@@ -726,7 +726,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto result = new global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto();
@@ -1326,7 +1326,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange result = new global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange();
@@ -1646,7 +1646,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto result = new global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto();
@@ -2337,7 +2337,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto result = new global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto();
@@ -2791,7 +2791,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto result = new global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto();
@@ -3136,7 +3136,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto result = new global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto();
@@ -3450,7 +3450,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto result = new global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto();
@@ -3811,7 +3811,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto result = new global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto();
@@ -4254,7 +4254,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.FileOptions result = new global::Google.ProtocolBuffers.DescriptorProtos.FileOptions();
@@ -4674,7 +4674,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions result = new global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions();
@@ -4906,7 +4906,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions result = new global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions();
@@ -5128,7 +5128,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions result = new global::Google.ProtocolBuffers.DescriptorProtos.EnumOptions();
@@ -5293,7 +5293,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions result = new global::Google.ProtocolBuffers.DescriptorProtos.EnumValueOptions();
@@ -5458,7 +5458,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions result = new global::Google.ProtocolBuffers.DescriptorProtos.ServiceOptions();
@@ -5623,7 +5623,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
// Construct using global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions.CreateBuilder()
- internal Builder() {}
+ public Builder() {}
global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions result = new global::Google.ProtocolBuffers.DescriptorProtos.MethodOptions();
diff --git a/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
index fe801182..35d7b1a8 100644
--- a/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
@@ -36,7 +36,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
private readonly Func<IBuilder> createBuilderDelegate;
internal RepeatedMessageAccessor(string name) : base(name) {
- MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", new Type[0]);
+ MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", Type.EmptyTypes);
if (createBuilderMethod == null) {
throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);
}
diff --git a/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
index 931848b5..5aa9f777 100644
--- a/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
@@ -31,8 +31,8 @@ namespace Google.ProtocolBuffers.FieldAccess {
/// </summary>
private readonly Func<IBuilder> createBuilderDelegate;
- internal SingleMessageAccessor(string name) : base(name) {
- MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", new Type[0]);
+ internal SingleMessageAccessor(string name) : base(name) {
+ MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", Type.EmptyTypes);
if (createBuilderMethod == null) {
throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);
}
diff --git a/csharp/ProtocolBuffers/InvalidProtocolBufferException.cs b/csharp/ProtocolBuffers/InvalidProtocolBufferException.cs
index 10257542..4f1b1a92 100644
--- a/csharp/ProtocolBuffers/InvalidProtocolBufferException.cs
+++ b/csharp/ProtocolBuffers/InvalidProtocolBufferException.cs
@@ -71,5 +71,10 @@ namespace Google.ProtocolBuffers {
"Protocol message was too large. May be malicious. " +
"Use CodedInputStream.SetSizeLimit() to increase the size limit.");
}
+
+ internal static InvalidProtocolBufferException InvalidMessageStreamTag() {
+ return new InvalidProtocolBufferException(
+ "Stream of protocol messages had invalid tag. Expected tag is length-delimited field 1.");
+ }
}
}
diff --git a/csharp/ProtocolBuffers/MessageStreamIterator.cs b/csharp/ProtocolBuffers/MessageStreamIterator.cs
new file mode 100644
index 00000000..4944e5ce
--- /dev/null
+++ b/csharp/ProtocolBuffers/MessageStreamIterator.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+
+namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// Helper class to create MessageStreamIterators without explicitly specifying
+ /// the builder type. The concrete builder type is determined by reflection, based
+ /// on the message type. The reflection step looks for a <c>CreateBuilder</c> method
+ /// in the message type which is public and static, and uses the return type of that
+ /// method as the builder type. This will work for all generated messages, whether
+ /// optimised for size or speed. It won't work for dynamic messages.
+ ///
+ /// TODO(jonskeet): This also won't work for non-public protos :(
+ /// Pass in delegate to create a builder?
+ /// </summary>
+ public static class MessageStreamIterator {
+
+ public static IEnumerable<TMessage> FromFile<TMessage>(string file)
+ where TMessage : IMessage<TMessage> {
+ return FromStreamProvider<TMessage>(() => File.OpenRead(file));
+ }
+
+ public static IEnumerable<TMessage> FromStreamProvider<TMessage>(StreamProvider streamProvider)
+ where TMessage : IMessage<TMessage> {
+ MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", Type.EmptyTypes);
+ if (createBuilderMethod == null) {
+ throw new ArgumentException("Message type " + typeof(TMessage).FullName + " has no CreateBuilder method.");
+ }
+ if (createBuilderMethod.ReturnType == typeof(void)) {
+ throw new ArgumentException("CreateBuilder method in " + typeof(TMessage).FullName + " has void return type");
+ }
+ Type builderType = createBuilderMethod.ReturnType;
+ if (builderType.GetConstructor(Type.EmptyTypes) == null) {
+ throw new ArgumentException("Builder type " + builderType.FullName + " has no public parameterless constructor.");
+ }
+ Type messageInterface = typeof(IMessage<,>).MakeGenericType(typeof(TMessage), builderType);
+ Type builderInterface = typeof(IBuilder<,>).MakeGenericType(typeof(TMessage), builderType);
+ if (Array.IndexOf(typeof (TMessage).GetInterfaces(), messageInterface) == -1) {
+ throw new ArgumentException("Message type " + typeof(TMessage) + " doesn't implement " + messageInterface.FullName);
+ }
+ if (Array.IndexOf(builderType.GetInterfaces(), builderInterface) == -1) {
+ throw new ArgumentException("Builder type " + typeof(TMessage) + " doesn't implement " + builderInterface.FullName);
+ }
+ Type iteratorType = typeof(MessageStreamIterator<,>).MakeGenericType(typeof(TMessage), builderType);
+ MethodInfo factoryMethod = iteratorType.GetMethod("FromStreamProvider", new Type[] { typeof(StreamProvider) });
+ return (IEnumerable<TMessage>) factoryMethod.Invoke(null, new object[] { streamProvider });
+ }
+ }
+
+ /// <summary>
+ /// Iterates over data created using a <see cref="MessageStreamWriter{T}" />.
+ /// Unlike MessageStreamWriter, this class is not usually constructed directly with
+ /// a stream; instead it is provided with a way of opening a stream when iteration
+ /// is started. The stream is closed when the iteration is completed or the enumerator
+ /// is disposed. (This occurs naturally when using <c>foreach</c>.)
+ /// This type is generic in both the message type and the builder type; if only the
+ /// iteration is required (i.e. just <see cref="IEnumerable{T}" />) then the static
+ /// generic methods in the nongeneric class are more appropriate.
+ /// </summary>
+ public sealed class MessageStreamIterator<TMessage, TBuilder> : IEnumerable<TMessage>
+ where TMessage : IMessage<TMessage, TBuilder>
+ where TBuilder : IBuilder<TMessage, TBuilder>, new() {
+
+ private readonly StreamProvider streamProvider;
+ private readonly ExtensionRegistry extensionRegistry;
+ private static readonly uint ExpectedTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+
+ private MessageStreamIterator(StreamProvider streamProvider, ExtensionRegistry extensionRegistry) {
+ this.streamProvider = streamProvider;
+ this.extensionRegistry = extensionRegistry;
+ }
+
+ /// <summary>
+ /// Creates an instance which opens the specified file when it begins
+ /// iterating. No extension registry is used when reading messages.
+ /// </summary>
+ public static MessageStreamIterator<TMessage, TBuilder> FromFile(string file) {
+ return new MessageStreamIterator<TMessage, TBuilder>(() => File.OpenRead(file), ExtensionRegistry.Empty);
+ }
+
+ /// <summary>
+ /// Creates an instance which calls the given delegate when it begins
+ /// iterating. No extension registry is used when reading messages.
+ /// </summary>
+ public static MessageStreamIterator<TMessage, TBuilder> FromStreamProvider(StreamProvider streamProvider) {
+ return new MessageStreamIterator<TMessage, TBuilder>(streamProvider, ExtensionRegistry.Empty);
+ }
+
+ /// <summary>
+ /// Creates a new instance which uses the same stream provider as this one,
+ /// but the specified extension registry.
+ /// </summary>
+ public MessageStreamIterator<TMessage, TBuilder> WithExtensionRegistry(ExtensionRegistry newRegistry) {
+ return new MessageStreamIterator<TMessage, TBuilder>(streamProvider, newRegistry);
+ }
+
+ public IEnumerator<TMessage> GetEnumerator() {
+ using (Stream stream = streamProvider()) {
+ CodedInputStream input = CodedInputStream.CreateInstance(stream);
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ if (tag != ExpectedTag) {
+ throw InvalidProtocolBufferException.InvalidMessageStreamTag();
+ }
+ TBuilder builder = new TBuilder();
+ input.ReadMessage(builder, extensionRegistry);
+ yield return builder.Build();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Explicit implementation of nongeneric IEnumerable interface.
+ /// </summary>
+ IEnumerator IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+ }
+}
diff --git a/csharp/ProtocolBuffers/MessageStreamWriter.cs b/csharp/ProtocolBuffers/MessageStreamWriter.cs
new file mode 100644
index 00000000..9ff33b05
--- /dev/null
+++ b/csharp/ProtocolBuffers/MessageStreamWriter.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace Google.ProtocolBuffers {
+ /// <summary>
+ /// Writes multiple messages to the same stream. Each message is written
+ /// as if it were an element of a repeated field 1 in a larger protocol buffer.
+ /// This class takes no ownership of the stream it is given; it never closes the
+ /// stream.
+ /// </summary>
+ public sealed class MessageStreamWriter<T> where T : IMessage<T> {
+
+ private readonly CodedOutputStream codedOutput;
+
+ /// <summary>
+ /// Creates an instance which writes to the given stream.
+ /// </summary>
+ /// <param name="output">Stream to write messages to.</param>
+ public MessageStreamWriter(Stream output) {
+ codedOutput = CodedOutputStream.CreateInstance(output);
+ }
+
+ public void Write(T message) {
+ codedOutput.WriteMessage(1, message);
+ }
+
+ public void Flush() {
+ codedOutput.Flush();
+ }
+ }
+}
diff --git a/csharp/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/ProtocolBuffers/ProtocolBuffers.csproj
index 88a21226..25f7cdbb 100644
--- a/csharp/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/csharp/ProtocolBuffers/ProtocolBuffers.csproj
@@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
+ <ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -41,6 +41,7 @@
<Compile Include="AbstractBuilder.cs" />
<Compile Include="AbstractMessage.cs" />
<Compile Include="ByteString.cs" />
+ <Compile Include="Delegates.cs" />
<Compile Include="CodedInputStream.cs" />
<Compile Include="CodedOutputStream.cs" />
<Compile Include="Collections\Dictionaries.cs" />
@@ -93,6 +94,8 @@
<Compile Include="IRpcChannel.cs" />
<Compile Include="IRpcController.cs" />
<Compile Include="IService.cs" />
+ <Compile Include="MessageStreamIterator.cs" />
+ <Compile Include="MessageStreamWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RpcUtil.cs" />
<Compile Include="TextFormat.cs" />