Commit fb248822 authored by Jon Skeet's avatar Jon Skeet

Implement JSON parsing in C#.

This includes all the well-known types except Any.
Some aspects are likely to require further work when the details of the JSON parsing expectations are hammered out in more detail. Some of these have "ignored" tests already.

Note that the choice *not* to use Json.NET was made for two reasons:
- Going from 0 dependencies to 1 dependency is a big hit, and there's not much benefit here
- Json.NET parses more leniently than we'd want; accommodating that would be nearly as much work as writing the tokenizer
This only really affects the JsonTokenizer, which could be replaced by Json.NET. The JsonParser code would be about the same length with Json.NET... but I wouldn't be as confident in it.
parent aa367541
...@@ -82,6 +82,8 @@ csharp_EXTRA_DIST= \ ...@@ -82,6 +82,8 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj \ csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj \
csharp/src/Google.Protobuf.Test/IssuesTest.cs \ csharp/src/Google.Protobuf.Test/IssuesTest.cs \
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs \ csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs \
csharp/src/Google.Protobuf.Test/JsonParserTest.cs \
csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs \
csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml \ csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml \
csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs \ csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs \
csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \
...@@ -119,6 +121,9 @@ csharp_EXTRA_DIST= \ ...@@ -119,6 +121,9 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/IMessage.cs \ csharp/src/Google.Protobuf/IMessage.cs \
csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs \ csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs \
csharp/src/Google.Protobuf/JsonFormatter.cs \ csharp/src/Google.Protobuf/JsonFormatter.cs \
csharp/src/Google.Protobuf/JsonParser.cs \
csharp/src/Google.Protobuf/JsonToken.cs \
csharp/src/Google.Protobuf/JsonTokenizer.cs \
csharp/src/Google.Protobuf/LimitedInputStream.cs \ csharp/src/Google.Protobuf/LimitedInputStream.cs \
csharp/src/Google.Protobuf/MessageExtensions.cs \ csharp/src/Google.Protobuf/MessageExtensions.cs \
csharp/src/Google.Protobuf/MessageParser.cs \ csharp/src/Google.Protobuf/MessageParser.cs \
......
...@@ -95,6 +95,8 @@ ...@@ -95,6 +95,8 @@
<Compile Include="Collections\MapFieldTest.cs" /> <Compile Include="Collections\MapFieldTest.cs" />
<Compile Include="Collections\RepeatedFieldTest.cs" /> <Compile Include="Collections\RepeatedFieldTest.cs" />
<Compile Include="JsonFormatterTest.cs" /> <Compile Include="JsonFormatterTest.cs" />
<Compile Include="JsonParserTest.cs" />
<Compile Include="JsonTokenizerTest.cs" />
<Compile Include="Reflection\DescriptorsTest.cs" /> <Compile Include="Reflection\DescriptorsTest.cs" />
<Compile Include="Reflection\FieldAccessTest.cs" /> <Compile Include="Reflection\FieldAccessTest.cs" />
<Compile Include="SampleEnum.cs" /> <Compile Include="SampleEnum.cs" />
......
...@@ -275,6 +275,13 @@ namespace Google.Protobuf ...@@ -275,6 +275,13 @@ namespace Google.Protobuf
AssertJson(expectedJson, JsonFormatter.Default.Format(message)); AssertJson(expectedJson, JsonFormatter.Default.Format(message));
} }
[Test]
public void WrapperFormatting_Message()
{
Assert.AreEqual("\"\"", JsonFormatter.Default.Format(new StringValue()));
Assert.AreEqual("0", JsonFormatter.Default.Format(new Int32Value()));
}
[Test] [Test]
public void WrapperFormatting_IncludeNull() public void WrapperFormatting_IncludeNull()
{ {
...@@ -376,12 +383,12 @@ namespace Google.Protobuf ...@@ -376,12 +383,12 @@ namespace Google.Protobuf
{ {
Fields = Fields =
{ {
{ "a", new Value { NullValue = new NullValue() } }, { "a", Value.ForNull() },
{ "b", new Value { BoolValue = false } }, { "b", Value.ForBool(false) },
{ "c", new Value { NumberValue = 10.5 } }, { "c", Value.ForNumber(10.5) },
{ "d", new Value { StringValue = "text" } }, { "d", Value.ForString("text") },
{ "e", new Value { ListValue = new ListValue { Values = { new Value { StringValue = "t1" }, new Value { NumberValue = 5 } } } } }, { "e", Value.ForList(Value.ForString("t1"), Value.ForNumber(5)) },
{ "f", new Value { StructValue = new Struct { Fields = { { "nested", new Value { StringValue = "value" } } } } } } { "f", Value.ForStruct(new Struct { Fields = { { "nested", Value.ForString("value") } } }) }
} }
}; };
AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString()); AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString());
...@@ -405,6 +412,14 @@ namespace Google.Protobuf ...@@ -405,6 +412,14 @@ namespace Google.Protobuf
AssertJson("{ 'fieldMaskField': 'user.displayName,photo' }", JsonFormatter.Default.Format(message)); AssertJson("{ 'fieldMaskField': 'user.displayName,photo' }", JsonFormatter.Default.Format(message));
} }
// SourceContext is an example of a well-known type with no special JSON handling
[Test]
public void SourceContextStandalone()
{
var message = new SourceContext { FileName = "foo.proto" };
AssertJson("{ 'fileName': 'foo.proto' }", JsonFormatter.Default.Format(message));
}
/// <summary> /// <summary>
/// Checks that the actual JSON is the same as the expected JSON - but after replacing /// Checks that the actual JSON is the same as the expected JSON - but after replacing
/// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier
......
This diff is collapsed.
This diff is collapsed.
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion #endregion
using Google.Protobuf.WellKnownTypes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
...@@ -261,20 +262,17 @@ namespace Google.Protobuf ...@@ -261,20 +262,17 @@ namespace Google.Protobuf
/// </remarks> /// </remarks>
private static class WrapperCodecs private static class WrapperCodecs
{ {
// All the field numbers are the same (1). private static readonly Dictionary<System.Type, object> Codecs = new Dictionary<System.Type, object>
private const int WrapperValueFieldNumber = Google.Protobuf.WellKnownTypes.Int32Value.ValueFieldNumber; {
{ typeof(bool), ForBool(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
private static readonly Dictionary<Type, object> Codecs = new Dictionary<Type, object> { typeof(int), ForInt32(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
{ { typeof(long), ForInt64(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
{ typeof(bool), ForBool(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, { typeof(uint), ForUInt32(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
{ typeof(int), ForInt32(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, { typeof(ulong), ForUInt64(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
{ typeof(long), ForInt64(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, { typeof(float), ForFloat(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.Fixed32)) },
{ typeof(uint), ForUInt32(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, { typeof(double), ForDouble(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.Fixed64)) },
{ typeof(ulong), ForUInt64(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, { typeof(string), ForString(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) },
{ typeof(float), ForFloat(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Fixed32)) }, { typeof(ByteString), ForBytes(WireFormat.MakeTag(Wrappers.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) }
{ typeof(double), ForDouble(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Fixed64)) },
{ typeof(string), ForString(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) },
{ typeof(ByteString), ForBytes(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) }
}; };
/// <summary> /// <summary>
......
...@@ -85,6 +85,9 @@ ...@@ -85,6 +85,9 @@
<Compile Include="FrameworkPortability.cs" /> <Compile Include="FrameworkPortability.cs" />
<Compile Include="IDeepCloneable.cs" /> <Compile Include="IDeepCloneable.cs" />
<Compile Include="JsonFormatter.cs" /> <Compile Include="JsonFormatter.cs" />
<Compile Include="JsonParser.cs" />
<Compile Include="JsonToken.cs" />
<Compile Include="JsonTokenizer.cs" />
<Compile Include="MessageExtensions.cs" /> <Compile Include="MessageExtensions.cs" />
<Compile Include="IMessage.cs" /> <Compile Include="IMessage.cs" />
<Compile Include="InvalidProtocolBufferException.cs" /> <Compile Include="InvalidProtocolBufferException.cs" />
...@@ -130,7 +133,9 @@ ...@@ -130,7 +133,9 @@
<Compile Include="WellKnownTypes\Timestamp.cs" /> <Compile Include="WellKnownTypes\Timestamp.cs" />
<Compile Include="WellKnownTypes\TimestampPartial.cs" /> <Compile Include="WellKnownTypes\TimestampPartial.cs" />
<Compile Include="WellKnownTypes\Type.cs" /> <Compile Include="WellKnownTypes\Type.cs" />
<Compile Include="WellKnownTypes\ValuePartial.cs" />
<Compile Include="WellKnownTypes\Wrappers.cs" /> <Compile Include="WellKnownTypes\Wrappers.cs" />
<Compile Include="WellKnownTypes\WrappersPartial.cs" />
<Compile Include="WireFormat.cs" /> <Compile Include="WireFormat.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
...@@ -189,6 +189,7 @@ namespace Google.Protobuf ...@@ -189,6 +189,7 @@ namespace Google.Protobuf
} }
// Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase // Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase
// TODO: Use the new field in FieldDescriptor.
internal static string ToCamelCase(string input) internal static string ToCamelCase(string input)
{ {
bool capitalizeNext = false; bool capitalizeNext = false;
...@@ -382,10 +383,19 @@ namespace Google.Protobuf ...@@ -382,10 +383,19 @@ namespace Google.Protobuf
WriteNull(builder); WriteNull(builder);
return; return;
} }
// For wrapper types, the value will be the (possibly boxed) "native" value, // For wrapper types, the value will either be the (possibly boxed) "native" value,
// so we can write it as if we were unconditionally writing the Value field for the wrapper type. // or the message itself if we're formatting it at the top level (e.g. just calling ToString on the object itself).
// If it's the message form, we can extract the value first, which *will* be the (possibly boxed) native value,
// and then proceed, writing it as if we were definitely in a field. (We never need to wrap it in an extra string...
// WriteValue will do the right thing.)
// TODO: Detect this differently when we have dynamic messages.
if (descriptor.File == Int32Value.Descriptor.File) if (descriptor.File == Int32Value.Descriptor.File)
{ {
if (value is IMessage)
{
var message = (IMessage) value;
value = message.Descriptor.Fields[Wrappers.WrapperValueFieldNumber].Accessor.GetValue(message);
}
WriteValue(builder, value); WriteValue(builder, value);
return; return;
} }
...@@ -750,7 +760,6 @@ namespace Google.Protobuf ...@@ -750,7 +760,6 @@ namespace Google.Protobuf
private readonly bool formatDefaultValues; private readonly bool formatDefaultValues;
/// <summary> /// <summary>
/// Whether fields whose values are the default for the field type (e.g. 0 for integers) /// Whether fields whose values are the default for the field type (e.g. 0 for integers)
/// should be formatted (true) or omitted (false). /// should be formatted (true) or omitted (false).
......
This diff is collapsed.
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
namespace Google.Protobuf
{
internal sealed class JsonToken : IEquatable<JsonToken>
{
// Tokens with no value can be reused.
private static readonly JsonToken _true = new JsonToken(TokenType.True);
private static readonly JsonToken _false = new JsonToken(TokenType.False);
private static readonly JsonToken _null = new JsonToken(TokenType.Null);
private static readonly JsonToken startObject = new JsonToken(TokenType.StartObject);
private static readonly JsonToken endObject = new JsonToken(TokenType.EndObject);
private static readonly JsonToken startArray = new JsonToken(TokenType.StartArray);
private static readonly JsonToken endArray = new JsonToken(TokenType.EndArray);
private static readonly JsonToken endDocument = new JsonToken(TokenType.EndDocument);
internal static JsonToken Null { get { return _null; } }
internal static JsonToken False { get { return _false; } }
internal static JsonToken True { get { return _true; } }
internal static JsonToken StartObject{ get { return startObject; } }
internal static JsonToken EndObject { get { return endObject; } }
internal static JsonToken StartArray { get { return startArray; } }
internal static JsonToken EndArray { get { return endArray; } }
internal static JsonToken EndDocument { get { return endDocument; } }
internal static JsonToken Name(string name)
{
return new JsonToken(TokenType.Name, stringValue: name);
}
internal static JsonToken Value(string value)
{
return new JsonToken(TokenType.StringValue, stringValue: value);
}
internal static JsonToken Value(double value)
{
return new JsonToken(TokenType.Number, numberValue: value);
}
internal enum TokenType
{
Null,
False,
True,
StringValue,
Number,
Name,
StartObject,
EndObject,
StartArray,
EndArray,
EndDocument
}
// A value is a string, number, array, object, null, true or false
// Arrays and objects have start/end
// A document consists of a value
// Objects are name/value sequences.
private readonly TokenType type;
private readonly string stringValue;
private readonly double numberValue;
internal TokenType Type { get { return type; } }
internal string StringValue { get { return stringValue; } }
internal double NumberValue { get { return numberValue; } }
private JsonToken(TokenType type, string stringValue = null, double numberValue = 0)
{
this.type = type;
this.stringValue = stringValue;
this.numberValue = numberValue;
}
public override bool Equals(object obj)
{
return Equals(obj as JsonToken);
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 31 + (int) type;
hash = hash * 31 + stringValue == null ? 0 : stringValue.GetHashCode();
hash = hash * 31 + numberValue.GetHashCode();
return hash;
}
}
public override string ToString()
{
switch (type)
{
case TokenType.Null:
return "null";
case TokenType.True:
return "true";
case TokenType.False:
return "false";
case TokenType.Name:
return "name (" + stringValue + ")";
case TokenType.StringValue:
return "value (" + stringValue + ")";
case TokenType.Number:
return "number (" + numberValue + ")";
case TokenType.StartObject:
return "start-object";
case TokenType.EndObject:
return "end-object";
case TokenType.StartArray:
return "start-array";
case TokenType.EndArray:
return "end-array";
case TokenType.EndDocument:
return "end-document";
default:
throw new InvalidOperationException("Token is of unknown type " + type);
}
}
public bool Equals(JsonToken other)
{
if (ReferenceEquals(other, null))
{
return false;
}
// Note use of other.numberValue.Equals rather than ==, so that NaN compares appropriately.
return other.type == type && other.stringValue == stringValue && other.numberValue.Equals(numberValue);
}
}
}
This diff is collapsed.
...@@ -142,5 +142,17 @@ namespace Google.Protobuf ...@@ -142,5 +142,17 @@ namespace Google.Protobuf
message.MergeFrom(input); message.MergeFrom(input);
return message; return message;
} }
/// <summary>
/// Parses a message from the given JSON.
/// </summary>
/// <param name="json">The JSON to parse.</param>
/// <returns>The parsed message.</returns>
public T ParseJson(string json)
{
T message = factory();
JsonParser.Default.Merge(message, json);
return message;
}
} }
} }
...@@ -46,7 +46,10 @@ using System.Security; ...@@ -46,7 +46,10 @@ using System.Security;
[assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
#if !NCRUNCH
[assembly: AllowPartiallyTrustedCallers] [assembly: AllowPartiallyTrustedCallers]
#endif
#if SIGNED #if SIGNED
[assembly: InternalsVisibleTo("Google.Protobuf.Test, PublicKey=" + [assembly: InternalsVisibleTo("Google.Protobuf.Test, PublicKey=" +
......
...@@ -47,6 +47,16 @@ namespace Google.Protobuf.WellKnownTypes ...@@ -47,6 +47,16 @@ namespace Google.Protobuf.WellKnownTypes
/// </summary> /// </summary>
public const int NanosecondsPerTick = 100; public const int NanosecondsPerTick = 100;
/// <summary>
/// The maximum permitted number of seconds.
/// </summary>
public const long MaxSeconds = 315576000000L;
/// <summary>
/// The minimum permitted number of seconds.
/// </summary>
public const long MinSeconds = -315576000000L;
/// <summary> /// <summary>
/// Converts this <see cref="Duration"/> to a <see cref="TimeSpan"/>. /// Converts this <see cref="Duration"/> to a <see cref="TimeSpan"/>.
/// </summary> /// </summary>
......
...@@ -38,6 +38,8 @@ namespace Google.Protobuf.WellKnownTypes ...@@ -38,6 +38,8 @@ namespace Google.Protobuf.WellKnownTypes
{ {
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static readonly long BclSecondsAtUnixEpoch = UnixEpoch.Ticks / TimeSpan.TicksPerSecond; private static readonly long BclSecondsAtUnixEpoch = UnixEpoch.Ticks / TimeSpan.TicksPerSecond;
internal static readonly long UnixSecondsAtBclMinValue = -BclSecondsAtUnixEpoch;
internal static readonly long UnixSecondsAtBclMaxValue = (DateTime.MaxValue.Ticks / TimeSpan.TicksPerSecond) - BclSecondsAtUnixEpoch;
/// <summary> /// <summary>
/// Returns the difference between one <see cref="Timestamp"/> and another, as a <see cref="Duration"/>. /// Returns the difference between one <see cref="Timestamp"/> and another, as a <see cref="Duration"/>.
......
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
namespace Google.Protobuf.WellKnownTypes
{
public partial class Value
{
/// <summary>
/// Convenience method to create a Value message with a string value.
/// </summary>
/// <param name="value">Value to set for the StringValue property.</param>
/// <returns>A newly-created Value message with the given value.</returns>
public static Value ForString(string value)
{
Preconditions.CheckNotNull(value, "value");
return new Value { StringValue = value };
}
/// <summary>
/// Convenience method to create a Value message with a number value.
/// </summary>
/// <param name="value">Value to set for the NumberValue property.</param>
/// <returns>A newly-created Value message with the given value.</returns>
public static Value ForNumber(double value)
{
return new Value { NumberValue = value };
}
/// <summary>
/// Convenience method to create a Value message with a Boolean value.
/// </summary>
/// <param name="value">Value to set for the BoolValue property.</param>
/// <returns>A newly-created Value message with the given value.</returns>
public static Value ForBool(bool value)
{
return new Value { BoolValue = value };
}
/// <summary>
/// Convenience method to create a Value message with a null initial value.
/// </summary>
/// <returns>A newly-created Value message a null initial value.</returns>
public static Value ForNull()
{
return new Value { NullValue = 0 };
}
/// <summary>
/// Convenience method to create a Value message with an initial list of values.
/// </summary>
/// <remarks>The values provided are not cloned; the references are copied directly.</remarks>
/// <returns>A newly-created Value message an initial list value.</returns>
public static Value ForList(params Value[] values)
{
Preconditions.CheckNotNull(values, "values");
return new Value { ListValue = new ListValue { Values = { values } } };
}
/// <summary>
/// Convenience method to create a Value message with an initial struct value
/// </summary>
/// <remarks>The value provided is not cloned; the reference is copied directly.</remarks>
/// <returns>A newly-created Value message an initial struct value.</returns>
public static Value ForStruct(Struct value)
{
Preconditions.CheckNotNull(value, "value");
return new Value { StructValue = value };
}
}
}
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
namespace Google.Protobuf.WellKnownTypes
{
public static partial class Wrappers
{
/// <summary>
/// Field number for the single "value" field in all wrapper types.
/// </summary>
internal const int WrapperValueFieldNumber = Int32Value.ValueFieldNumber;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment