ADD: added new version of protobuf

This commit is contained in:
Henry Winkel
2022-12-20 10:09:28 +01:00
parent 4a79559129
commit 1e2b3dda7b
1513 changed files with 123720 additions and 83381 deletions

View File

@@ -37,8 +37,13 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
#if !NET35
using System.Threading;
using System.Threading.Tasks;
#endif
#if NET35
using Google.Protobuf.Compatibility;
#endif
namespace Google.Protobuf
{
@@ -181,6 +186,7 @@ namespace Google.Protobuf
return AttachBytes(bytes);
}
#if !NET35
/// <summary>
/// Constructs a <see cref="ByteString"/> from data in the given stream, asynchronously.
/// </summary>
@@ -189,11 +195,12 @@ namespace Google.Protobuf
/// <param name="stream">The stream to copy into a ByteString.</param>
/// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>
/// <returns>A ByteString with content read from the given stream.</returns>
public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default)
public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
ProtoPreconditions.CheckNotNull(stream, nameof(stream));
return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken);
}
#endif
/// <summary>
/// Constructs a <see cref="ByteString" /> from the given array. The contents
@@ -340,7 +347,7 @@ namespace Google.Protobuf
{
return true;
}
if (lhs is null || rhs is null)
if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
{
return false;
}

View File

@@ -43,6 +43,7 @@ namespace Google.Protobuf
/// </summary>
internal static class ByteStringAsync
{
#if !NET35
internal static async Task<ByteString> FromStreamAsyncCore(Stream stream, CancellationToken cancellationToken)
{
int capacity = stream.CanSeek ? checked((int)(stream.Length - stream.Position)) : 0;
@@ -58,5 +59,6 @@ namespace Google.Protobuf
#endif
return ByteString.AttachBytes(bytes);
}
#endif
}
}

View File

@@ -32,7 +32,10 @@
using Google.Protobuf.Collections;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
namespace Google.Protobuf
@@ -646,6 +649,21 @@ namespace Google.Protobuf
}
}
/// <summary>
/// Called when buffer is empty to read more bytes from the
/// input. If <paramref name="mustSucceed"/> is true, RefillBuffer() guarantees that
/// either there will be at least one byte in the buffer when it returns
/// or it will throw an exception. If <paramref name="mustSucceed"/> is false,
/// RefillBuffer() returns false if no more bytes were available.
/// </summary>
/// <param name="mustSucceed"></param>
/// <returns></returns>
private bool RefillBuffer(bool mustSucceed)
{
var span = new ReadOnlySpan<byte>(buffer);
return state.segmentedBufferHelper.RefillBuffer(ref span, ref state, mustSucceed);
}
/// <summary>
/// Reads a fixed size of bytes from the input.
/// </summary>

View File

@@ -30,9 +30,11 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using Google.Protobuf.Collections;
using System;
using System.IO;
using System.Security;
using System.Text;
namespace Google.Protobuf
{

View File

@@ -31,6 +31,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Google.Protobuf.Collections
{

View File

@@ -31,7 +31,9 @@
#endregion
using Google.Protobuf.Compatibility;
using Google.Protobuf.Reflection;
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.IO;
@@ -66,14 +68,18 @@ namespace Google.Protobuf.Collections
/// in future versions.
/// </para>
/// </remarks>
public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary, IReadOnlyDictionary<TKey, TValue>
public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
#if !NET35
, IReadOnlyDictionary<TKey, TValue>
#endif
{
private static readonly EqualityComparer<TValue> ValueEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TValue>();
private static readonly EqualityComparer<TKey> KeyEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TKey>();
// TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map = new(KeyEqualityComparer);
private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new();
private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(KeyEqualityComparer);
private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
/// <summary>
/// Creates a deep clone of this object.
@@ -141,7 +147,8 @@ namespace Google.Protobuf.Collections
public bool Remove(TKey key)
{
ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
if (map.TryGetValue(key, out LinkedListNode<KeyValuePair<TKey, TValue>> node))
LinkedListNode<KeyValuePair<TKey, TValue>> node;
if (map.TryGetValue(key, out node))
{
map.Remove(key);
node.List.Remove(node);
@@ -163,14 +170,15 @@ namespace Google.Protobuf.Collections
/// <returns><c>true</c> if the map contains an element with the specified key; otherwise, <c>false</c>.</returns>
public bool TryGetValue(TKey key, out TValue value)
{
if (map.TryGetValue(key, out LinkedListNode<KeyValuePair<TKey, TValue>> node))
LinkedListNode<KeyValuePair<TKey, TValue>> node;
if (map.TryGetValue(key, out node))
{
value = node.Value.Value;
return true;
}
else
{
value = default;
value = default(TValue);
return false;
}
}
@@ -187,7 +195,8 @@ namespace Google.Protobuf.Collections
get
{
ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
if (TryGetValue(key, out TValue value))
TValue value;
if (TryGetValue(key, out value))
{
return value;
}
@@ -201,8 +210,9 @@ namespace Google.Protobuf.Collections
{
ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
}
LinkedListNode<KeyValuePair<TKey, TValue>> node;
var pair = new KeyValuePair<TKey, TValue>(key, value);
if (map.TryGetValue(key, out LinkedListNode<KeyValuePair<TKey, TValue>> node))
if (map.TryGetValue(key, out node))
{
node.Value = pair;
}
@@ -217,12 +227,12 @@ namespace Google.Protobuf.Collections
/// <summary>
/// Gets a collection containing the keys in the map.
/// </summary>
public ICollection<TKey> Keys => new MapView<TKey>(this, pair => pair.Key, ContainsKey);
public ICollection<TKey> Keys { get { return new MapView<TKey>(this, pair => pair.Key, ContainsKey); } }
/// <summary>
/// Gets a collection containing the values in the map.
/// </summary>
public ICollection<TValue> Values => new MapView<TValue>(this, pair => pair.Value, ContainsValue);
public ICollection<TValue> Values { get { return new MapView<TValue>(this, pair => pair.Value, ContainsValue); } }
/// <summary>
/// Adds the specified entries to the map. The keys and values are not automatically cloned.
@@ -237,28 +247,16 @@ namespace Google.Protobuf.Collections
}
}
/// <summary>
/// Adds the specified entries to the map, replacing any existing entries with the same keys.
/// The keys and values are not automatically cloned.
/// </summary>
/// <remarks>This method primarily exists to be called from MergeFrom methods in generated classes for messages.</remarks>
/// <param name="entries">The entries to add to the map.</param>
public void MergeFrom(IDictionary<TKey, TValue> entries)
{
ProtoPreconditions.CheckNotNull(entries, nameof(entries));
foreach (var pair in entries)
{
this[pair.Key] = pair.Value;
}
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// An enumerator that can be used to iterate through the collection.
/// </returns>
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => list.GetEnumerator();
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return list.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
@@ -266,13 +264,19 @@ namespace Google.Protobuf.Collections
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Adds the specified item to the map.
/// </summary>
/// <param name="item">The item to add to the map.</param>
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
/// <summary>
/// Removes all items from the map.
@@ -288,16 +292,21 @@ namespace Google.Protobuf.Collections
/// </summary>
/// <param name="item">The key/value pair to find.</param>
/// <returns></returns>
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) =>
TryGetValue(item.Key, out TValue value) && ValueEqualityComparer.Equals(item.Value, value);
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
TValue value;
return TryGetValue(item.Key, out value) && ValueEqualityComparer.Equals(item.Value, value);
}
/// <summary>
/// Copies the key/value pairs in this map to an array.
/// </summary>
/// <param name="array">The array to copy the entries into.</param>
/// <param name="arrayIndex">The index of the array at which to start copying values.</param>
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) =>
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
list.CopyTo(array, arrayIndex);
}
/// <summary>
/// Removes the specified key/value pair from the map.
@@ -311,7 +320,8 @@ namespace Google.Protobuf.Collections
{
throw new ArgumentException("Key is null", nameof(item));
}
if (map.TryGetValue(item.Key, out LinkedListNode<KeyValuePair<TKey, TValue>> node) &&
LinkedListNode<KeyValuePair<TKey, TValue>> node;
if (map.TryGetValue(item.Key, out node) &&
EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.Value))
{
map.Remove(item.Key);
@@ -327,12 +337,12 @@ namespace Google.Protobuf.Collections
/// <summary>
/// Gets the number of elements contained in the map.
/// </summary>
public int Count => list.Count;
public int Count { get { return list.Count; } }
/// <summary>
/// Gets a value indicating whether the map is read-only.
/// </summary>
public bool IsReadOnly => false;
public bool IsReadOnly { get { return false; } }
/// <summary>
/// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
@@ -341,7 +351,10 @@ namespace Google.Protobuf.Collections
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object other) => Equals(other as MapField<TKey, TValue>);
public override bool Equals(object other)
{
return Equals(other as MapField<TKey, TValue>);
}
/// <summary>
/// Returns a hash code for this instance.
@@ -386,7 +399,8 @@ namespace Google.Protobuf.Collections
var valueComparer = ValueEqualityComparer;
foreach (var pair in this)
{
if (!other.TryGetValue(pair.Key, out TValue value))
TValue value;
if (!other.TryGetValue(pair.Key, out value))
{
return false;
}
@@ -518,20 +532,33 @@ namespace Google.Protobuf.Collections
}
#region IDictionary explicit interface implementation
void IDictionary.Add(object key, object value)
{
Add((TKey)key, (TValue)value);
}
void IDictionary.Add(object key, object value) => Add((TKey)key, (TValue)value);
bool IDictionary.Contains(object key)
{
if (!(key is TKey))
{
return false;
}
return ContainsKey((TKey)key);
}
bool IDictionary.Contains(object key) => key is TKey k && ContainsKey(k);
IDictionaryEnumerator IDictionary.GetEnumerator() => new DictionaryEnumerator(GetEnumerator());
IDictionaryEnumerator IDictionary.GetEnumerator()
{
return new DictionaryEnumerator(GetEnumerator());
}
void IDictionary.Remove(object key)
{
ProtoPreconditions.CheckNotNull(key, nameof(key));
if (key is TKey k)
if (!(key is TKey))
{
Remove(k);
return;
}
Remove((TKey)key);
}
void ICollection.CopyTo(Array array, int index)
@@ -541,27 +568,28 @@ namespace Google.Protobuf.Collections
temp.CopyTo(array, index);
}
bool IDictionary.IsFixedSize => false;
bool IDictionary.IsFixedSize { get { return false; } }
ICollection IDictionary.Keys => (ICollection)Keys;
ICollection IDictionary.Keys { get { return (ICollection)Keys; } }
ICollection IDictionary.Values => (ICollection)Values;
ICollection IDictionary.Values { get { return (ICollection)Values; } }
bool ICollection.IsSynchronized => false;
bool ICollection.IsSynchronized { get { return false; } }
object ICollection.SyncRoot => this;
object ICollection.SyncRoot { get { return this; } }
object IDictionary.this[object key]
{
get
{
ProtoPreconditions.CheckNotNull(key, nameof(key));
if (key is TKey k)
if (!(key is TKey))
{
TryGetValue(k, out TValue value);
return value;
return null;
}
return null;
TValue value;
TryGetValue((TKey)key, out value);
return value;
}
set
@@ -572,8 +600,11 @@ namespace Google.Protobuf.Collections
#endregion
#region IReadOnlyDictionary explicit interface implementation
#if !NET35
IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;
#endif
#endregion
private class DictionaryEnumerator : IDictionaryEnumerator
@@ -585,14 +616,20 @@ namespace Google.Protobuf.Collections
this.enumerator = enumerator;
}
public bool MoveNext() => enumerator.MoveNext();
public bool MoveNext()
{
return enumerator.MoveNext();
}
public void Reset() => enumerator.Reset();
public void Reset()
{
enumerator.Reset();
}
public object Current => Entry;
public DictionaryEntry Entry => new DictionaryEntry(Key, Value);
public object Key => enumerator.Current.Key;
public object Value => enumerator.Current.Value;
public object Current { get { return Entry; } }
public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }
public object Key { get { return enumerator.Current.Key; } }
public object Value { get { return enumerator.Current.Value; } }
}
/// <summary>
@@ -651,19 +688,28 @@ namespace Google.Protobuf.Collections
this.containsCheck = containsCheck;
}
public int Count => parent.Count;
public int Count { get { return parent.Count; } }
public bool IsReadOnly => true;
public bool IsReadOnly { get { return true; } }
public bool IsSynchronized => false;
public bool IsSynchronized { get { return false; } }
public object SyncRoot => parent;
public object SyncRoot { get { return parent; } }
public void Add(T item) => throw new NotSupportedException();
public void Add(T item)
{
throw new NotSupportedException();
}
public void Clear() => throw new NotSupportedException();
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(T item) => containsCheck(item);
public bool Contains(T item)
{
return containsCheck(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
@@ -686,9 +732,15 @@ namespace Google.Protobuf.Collections
return parent.list.Select(projection).GetEnumerator();
}
public bool Remove(T item) => throw new NotSupportedException();
public bool Remove(T item)
{
throw new NotSupportedException();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void CopyTo(Array array, int index)
{

View File

@@ -0,0 +1,147 @@
#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;
using System.Collections;
using System.Collections.Generic;
namespace Google.Protobuf.Collections
{
/// <summary>
/// Read-only wrapper around another dictionary.
/// </summary>
internal sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> wrapped;
public ReadOnlyDictionary(IDictionary<TKey, TValue> wrapped)
{
this.wrapped = wrapped;
}
public void Add(TKey key, TValue value)
{
throw new InvalidOperationException();
}
public bool ContainsKey(TKey key)
{
return wrapped.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get { return wrapped.Keys; }
}
public bool Remove(TKey key)
{
throw new InvalidOperationException();
}
public bool TryGetValue(TKey key, out TValue value)
{
return wrapped.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get { return wrapped.Values; }
}
public TValue this[TKey key]
{
get { return wrapped[key]; }
set { throw new InvalidOperationException(); }
}
public void Add(KeyValuePair<TKey, TValue> item)
{
throw new InvalidOperationException();
}
public void Clear()
{
throw new InvalidOperationException();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return wrapped.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
wrapped.CopyTo(array, arrayIndex);
}
public int Count
{
get { return wrapped.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
throw new InvalidOperationException();
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return wrapped.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable) wrapped).GetEnumerator();
}
public override bool Equals(object obj)
{
return wrapped.Equals(obj);
}
public override int GetHashCode()
{
return wrapped.GetHashCode();
}
public override string ToString()
{
return wrapped.ToString();
}
}
}

View File

@@ -35,6 +35,7 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Threading;
namespace Google.Protobuf.Collections
{
@@ -47,7 +48,10 @@ namespace Google.Protobuf.Collections
/// supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases.
/// </remarks>
/// <typeparam name="T">The element type of the repeated field.</typeparam>
public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>, IReadOnlyList<T>
public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>
#if !NET35
, IReadOnlyList<T>
#endif
{
private static readonly EqualityComparer<T> EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<T>();
private static readonly T[] EmptyArray = new T[0];
@@ -73,7 +77,8 @@ namespace Google.Protobuf.Collections
if (array != EmptyArray)
{
clone.array = (T[])array.Clone();
if (clone.array is IDeepCloneable<T>[] cloneableArray)
IDeepCloneable<T>[] cloneableArray = clone.array as IDeepCloneable<T>[];
if (cloneableArray != null)
{
for (int i = 0; i < count; i++)
{
@@ -279,9 +284,8 @@ namespace Google.Protobuf.Collections
}
/// <summary>
/// Gets and sets the capacity of the RepeatedField's internal array.
/// When set, the internal array is reallocated to the given capacity.
/// <exception cref="ArgumentOutOfRangeException">The new value is less than <see cref="Count"/>.</exception>
/// Gets and sets the capacity of the RepeatedField's internal array. WHen set, the internal array is reallocated to the given capacity.
/// <exception cref="ArgumentOutOfRangeException">The new value is less than Count -or- when Count is less than 0.</exception>
/// </summary>
public int Capacity
{
@@ -339,10 +343,7 @@ namespace Google.Protobuf.Collections
/// </summary>
public void Clear()
{
// Clear the content of the array (so that any objects it referred to can be garbage collected)
// but keep the capacity the same. This allows large repeated fields to be reused without
// array reallocation.
Array.Clear(array, 0, count);
array = EmptyArray;
count = 0;
}
@@ -351,7 +352,10 @@ namespace Google.Protobuf.Collections
/// </summary>
/// <param name="item">The item to find.</param>
/// <returns><c>true</c> if this collection contains the given item; <c>false</c> otherwise.</returns>
public bool Contains(T item) => IndexOf(item) != -1;
public bool Contains(T item)
{
return IndexOf(item) != -1;
}
/// <summary>
/// Copies this collection to the given array.
@@ -377,7 +381,7 @@ namespace Google.Protobuf.Collections
}
Array.Copy(array, index + 1, array, index, count - index - 1);
count--;
array[count] = default;
array[count] = default(T);
return true;
}
@@ -401,7 +405,8 @@ namespace Google.Protobuf.Collections
// Optimization 1: If the collection we're adding is already a RepeatedField<T>,
// we know the values are valid.
if (values is RepeatedField<T> otherRepeatedField)
var otherRepeatedField = values as RepeatedField<T>;
if (otherRepeatedField != null)
{
EnsureSize(count + otherRepeatedField.count);
Array.Copy(otherRepeatedField.array, 0, array, count, otherRepeatedField.count);
@@ -411,7 +416,8 @@ namespace Google.Protobuf.Collections
// Optimization 2: The collection is an ICollection, so we can expand
// just once and ask the collection to copy itself into the array.
if (values is ICollection collection)
var collection = values as ICollection;
if (collection != null)
{
var extraCount = collection.Count;
// For reference types and nullable value types, we need to check that there are no nulls
@@ -481,15 +487,21 @@ namespace Google.Protobuf.Collections
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj) => Equals(obj as RepeatedField<T>);
public override bool Equals(object obj)
{
return Equals(obj as RepeatedField<T>);
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Returns a hash code for this instance.
@@ -514,7 +526,7 @@ namespace Google.Protobuf.Collections
/// <returns><c>true</c> if <paramref name="other"/> refers to an equal repeated field; <c>false</c> otherwise.</returns>
public bool Equals(RepeatedField<T> other)
{
if (other is null)
if (ReferenceEquals(other, null))
{
return false;
}
@@ -587,7 +599,7 @@ namespace Google.Protobuf.Collections
}
Array.Copy(array, index + 1, array, index, count - index - 1);
count--;
array[count] = default;
array[count] = default(T);
}
/// <summary>
@@ -633,7 +645,10 @@ namespace Google.Protobuf.Collections
#region Explicit interface implementation for IList and ICollection.
bool IList.IsFixedSize => false;
void ICollection.CopyTo(Array array, int index) => Array.Copy(this.array, 0, array, index, count);
void ICollection.CopyTo(Array array, int index)
{
Array.Copy(this.array, 0, array, index, count);
}
bool ICollection.IsSynchronized => false;
@@ -641,8 +656,8 @@ namespace Google.Protobuf.Collections
object IList.this[int index]
{
get => this[index];
set => this[index] = (T)value;
get { return this[index]; }
set { this[index] = (T)value; }
}
int IList.Add(object value)
@@ -651,18 +666,32 @@ namespace Google.Protobuf.Collections
return count - 1;
}
bool IList.Contains(object value) => (value is T t && Contains(t));
bool IList.Contains(object value)
{
return (value is T && Contains((T)value));
}
int IList.IndexOf(object value) => (value is T t) ? IndexOf(t) : -1;
int IList.IndexOf(object value)
{
if (!(value is T))
{
return -1;
}
return IndexOf((T)value);
}
void IList.Insert(int index, object value) => Insert(index, (T) value);
void IList.Insert(int index, object value)
{
Insert(index, (T) value);
}
void IList.Remove(object value)
{
if (value is T t)
if (!(value is T))
{
Remove(t);
return;
}
Remove((T)value);
}
#endregion
}

View File

@@ -0,0 +1,47 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2017 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
#if NET35
using System;
using System.Reflection;
namespace Google.Protobuf.Compatibility
{
// .NET Core (at least netstandard1.0) doesn't have Delegate.CreateDelegate, and .NET 3.5 doesn't have
// MethodInfo.CreateDelegate. Proxy from one to the other on .NET 3.5...
internal static class MethodInfoExtensions
{
internal static Delegate CreateDelegate(this MethodInfo method, Type type) =>
Delegate.CreateDelegate(type, method);
}
}
#endif

View File

@@ -47,7 +47,11 @@ namespace Google.Protobuf.Compatibility
/// </summary>
internal static MethodInfo GetGetMethod(this PropertyInfo target)
{
#if NET35
var method = target.GetGetMethod();
#else
var method = target.GetMethod;
#endif
return method != null && method.IsPublic ? method : null;
}
@@ -57,7 +61,11 @@ namespace Google.Protobuf.Compatibility
/// </summary>
internal static MethodInfo GetSetMethod(this PropertyInfo target)
{
#if NET35
var method = target.GetSetMethod();
#else
var method = target.SetMethod;
#endif
return method != null && method.IsPublic ? method : null;
}
}

View File

@@ -0,0 +1,66 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2015 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
#if NET35
using System;
using System.IO;
namespace Google.Protobuf.Compatibility
{
/// <summary>
/// Extension methods for <see cref="Stream"/> in order to provide
/// backwards compatibility with .NET 3.5
/// </summary>
public static class StreamExtensions
{
// 81920 seems to be the default buffer size used in .NET 4.5.1
private const int BUFFER_SIZE = 81920;
/// <summary>
/// Write the contents of the current stream to the destination stream
/// </summary>
public static void CopyTo(this Stream source, Stream destination)
{
if (destination == null)
{
throw new ArgumentNullException(nameof(destination));
}
byte[] buffer = new byte[BUFFER_SIZE];
int numBytesRead;
while ((numBytesRead = source.Read(buffer, 0, buffer.Length)) > 0) {
destination.Write(buffer, 0, numBytesRead);
}
}
}
}
#endif

View File

@@ -34,6 +34,7 @@ using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
#if !NET35
namespace Google.Protobuf.Compatibility
{
/// <summary>
@@ -111,3 +112,4 @@ namespace Google.Protobuf.Compatibility
}
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -77,7 +77,7 @@ namespace Google.Protobuf
this.codec = codec;
}
internal TValue DefaultValue => codec != null ? codec.DefaultValue : default;
internal TValue DefaultValue => codec != null ? codec.DefaultValue : default(TValue);
internal override Type TargetType => typeof(TTarget);

View File

@@ -55,7 +55,7 @@ namespace Google.Protobuf
internal static ExtensionComparer Instance = new ExtensionComparer();
}
private readonly IDictionary<ObjectIntPair<Type>, Extension> extensions;
private IDictionary<ObjectIntPair<Type>, Extension> extensions;
/// <summary>
/// Creates a new empty extension registry

View File

@@ -61,7 +61,8 @@ namespace Google.Protobuf
/// </summary>
public static TValue Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
if (TryGetValue(ref set, extension, out IExtensionValue value))
IExtensionValue value;
if (TryGetValue(ref set, extension, out value))
{
// The stored ExtensionValue can be a different type to what is being requested.
// This happens when the same extension proto is compiled in different assemblies.
@@ -97,7 +98,7 @@ namespace Google.Protobuf
}
}
}
else
else
{
return extension.DefaultValue;
}
@@ -108,7 +109,8 @@ namespace Google.Protobuf
/// </summary>
public static RepeatedField<TValue> Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
if (TryGetValue(ref set, extension, out IExtensionValue value))
IExtensionValue value;
if (TryGetValue(ref set, extension, out value))
{
if (value is RepeatedExtensionValue<TValue> extensionValue)
{
@@ -130,7 +132,7 @@ namespace Google.Protobuf
}
}
}
else
else
{
return null;
}
@@ -191,7 +193,8 @@ namespace Google.Protobuf
/// </summary>
public static bool Has<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
return TryGetValue(ref set, extension, out IExtensionValue _);
IExtensionValue value;
return TryGetValue(ref set, extension, out value);
}
/// <summary>
@@ -249,18 +252,20 @@ namespace Google.Protobuf
/// </summary>
public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, ref ParseContext ctx) where TTarget : IExtendableMessage<TTarget>
{
Extension extension;
int lastFieldNumber = WireFormat.GetTagFieldNumber(ctx.LastTag);
if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out IExtensionValue extensionValue))
IExtensionValue extensionValue;
if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out extensionValue))
{
extensionValue.MergeFrom(ref ctx);
return true;
}
else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out Extension extension))
else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out extension))
{
IExtensionValue value = extension.CreateValue();
value.MergeFrom(ref ctx);
set ??= new ExtensionSet<TTarget>();
set = (set ?? new ExtensionSet<TTarget>());
set.ValuesByNumber.Add(extension.FieldNumber, value);
return true;
}
@@ -285,7 +290,8 @@ namespace Google.Protobuf
}
foreach (var pair in second.ValuesByNumber)
{
if (first.ValuesByNumber.TryGetValue(pair.Key, out IExtensionValue value))
IExtensionValue value;
if (first.ValuesByNumber.TryGetValue(pair.Key, out value))
{
value.MergeFrom(pair.Value);
}
@@ -359,7 +365,8 @@ namespace Google.Protobuf
}
foreach (var pair in ValuesByNumber)
{
if (!otherSet.ValuesByNumber.TryGetValue(pair.Key, out IExtensionValue secondValue))
IExtensionValue secondValue;
if (!otherSet.ValuesByNumber.TryGetValue(pair.Key, out secondValue))
{
return false;
}

View File

@@ -32,6 +32,7 @@
using Google.Protobuf.Collections;
using System;
using System.Linq;
namespace Google.Protobuf
{
@@ -49,7 +50,7 @@ namespace Google.Protobuf
internal sealed class ExtensionValue<T> : IExtensionValue
{
private T field;
private readonly FieldCodec<T> codec;
private FieldCodec<T> codec;
internal ExtensionValue(FieldCodec<T> codec)
{

View File

@@ -31,6 +31,7 @@
#endregion
using Google.Protobuf.Collections;
using Google.Protobuf.Compatibility;
using Google.Protobuf.WellKnownTypes;
using System;
using System.Collections.Generic;
@@ -50,105 +51,150 @@ namespace Google.Protobuf
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<string> ForString(uint tag) => ForString(tag, "");
public static FieldCodec<string> ForString(uint tag)
{
return FieldCodec.ForString(tag, "");
}
/// <summary>
/// Retrieves a codec suitable for a bytes field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ByteString> ForBytes(uint tag) => ForBytes(tag, ByteString.Empty);
public static FieldCodec<ByteString> ForBytes(uint tag)
{
return FieldCodec.ForBytes(tag, ByteString.Empty);
}
/// <summary>
/// Retrieves a codec suitable for a bool field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<bool> ForBool(uint tag) => ForBool(tag, false);
public static FieldCodec<bool> ForBool(uint tag)
{
return FieldCodec.ForBool(tag, false);
}
/// <summary>
/// Retrieves a codec suitable for an int32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForInt32(uint tag) => ForInt32(tag, 0);
public static FieldCodec<int> ForInt32(uint tag)
{
return FieldCodec.ForInt32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an sint32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForSInt32(uint tag) => ForSInt32(tag, 0);
public static FieldCodec<int> ForSInt32(uint tag)
{
return FieldCodec.ForSInt32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a fixed32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<uint> ForFixed32(uint tag) => ForFixed32(tag, 0);
public static FieldCodec<uint> ForFixed32(uint tag)
{
return FieldCodec.ForFixed32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an sfixed32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForSFixed32(uint tag) => ForSFixed32(tag, 0);
public static FieldCodec<int> ForSFixed32(uint tag)
{
return FieldCodec.ForSFixed32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a uint32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<uint> ForUInt32(uint tag) => ForUInt32(tag, 0);
public static FieldCodec<uint> ForUInt32(uint tag)
{
return FieldCodec.ForUInt32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an int64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForInt64(uint tag) => ForInt64(tag, 0);
public static FieldCodec<long> ForInt64(uint tag)
{
return FieldCodec.ForInt64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an sint64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForSInt64(uint tag) => ForSInt64(tag, 0);
public static FieldCodec<long> ForSInt64(uint tag)
{
return FieldCodec.ForSInt64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a fixed64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ulong> ForFixed64(uint tag) => ForFixed64(tag, 0);
public static FieldCodec<ulong> ForFixed64(uint tag)
{
return FieldCodec.ForFixed64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an sfixed64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForSFixed64(uint tag) => ForSFixed64(tag, 0);
public static FieldCodec<long> ForSFixed64(uint tag)
{
return FieldCodec.ForSFixed64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a uint64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ulong> ForUInt64(uint tag) => ForUInt64(tag, 0);
public static FieldCodec<ulong> ForUInt64(uint tag)
{
return FieldCodec.ForUInt64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a float field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<float> ForFloat(uint tag) => ForFloat(tag, 0);
public static FieldCodec<float> ForFloat(uint tag)
{
return FieldCodec.ForFloat(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a double field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<double> ForDouble(uint tag) => ForDouble(tag, 0);
public static FieldCodec<double> ForDouble(uint tag)
{
return FieldCodec.ForDouble(tag, 0);
}
// Enums are tricky. We can probably use expression trees to build these delegates automatically,
// but it's easy to generate the code for it.
@@ -160,8 +206,10 @@ namespace Google.Protobuf
/// <param name="toInt32">A conversion function from <see cref="Int32"/> to the enum type.</param>
/// <param name="fromInt32">A conversion function from the enum type to <see cref="Int32"/>.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32) =>
ForEnum(tag, toInt32, fromInt32, default);
public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32)
{
return FieldCodec.ForEnum(tag, toInt32, fromInt32, default(T));
}
/// <summary>
/// Retrieves a codec suitable for a string field with the given tag.
@@ -517,7 +565,8 @@ namespace Google.Protobuf
/// </summary>
internal static FieldCodec<T> GetCodec<T>()
{
if (!Codecs.TryGetValue(typeof(T), out object value))
object value;
if (!Codecs.TryGetValue(typeof(T), out value))
{
throw new InvalidOperationException("Invalid type argument requested for wrapper codec: " + typeof(T));
}
@@ -526,7 +575,8 @@ namespace Google.Protobuf
internal static ValueReader<T?> GetReader<T>() where T : struct
{
if (!Readers.TryGetValue(typeof(T), out object value))
object value;
if (!Readers.TryGetValue(typeof(T), out value))
{
throw new InvalidOperationException("Invalid type argument requested for wrapper reader: " + typeof(T));
}

View File

@@ -120,7 +120,8 @@ namespace Google.Protobuf
return this;
}
if (!node.Children.TryGetValue(part, out Node childNode))
Node childNode;
if (!node.Children.TryGetValue(part, out childNode))
{
createNewBranch = true;
childNode = new Node();
@@ -332,24 +333,15 @@ namespace Google.Protobuf
{
if (sourceField != null)
{
// Well-known wrapper types are represented as nullable primitive types, so we do not "merge" them.
// Instead, any non-null value just overwrites the previous value directly.
if (field.MessageType.IsWrapperType)
var sourceByteString = ((IMessage)sourceField).ToByteString();
var destinationValue = (IMessage)field.Accessor.GetValue(destination);
if (destinationValue != null)
{
field.Accessor.SetValue(destination, sourceField);
destinationValue.MergeFrom(sourceByteString);
}
else
{
var sourceByteString = ((IMessage)sourceField).ToByteString();
var destinationValue = (IMessage)field.Accessor.GetValue(destination);
if (destinationValue != null)
{
destinationValue.MergeFrom(sourceByteString);
}
else
{
field.Accessor.SetValue(destination, field.MessageType.Parser.ParseFrom(sourceByteString));
}
field.Accessor.SetValue(destination, field.MessageType.Parser.ParseFrom(sourceByteString));
}
}
}

View File

@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- If you update this, update the .csproj in the Docker file as well -->
<PropertyGroup>
<Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
<Copyright>Copyright 2015, Google Inc.</Copyright>
<AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
<VersionPrefix>3.21.8</VersionPrefix>
<LangVersion>10.0</LangVersion>
<VersionPrefix>3.21.12</VersionPrefix>
<!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence -->
<LangVersion>7.2</LangVersion>
<Authors>Google Inc.</Authors>
<TargetFrameworks>netstandard1.1;netstandard2.0;net45;net50</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

View File

@@ -136,5 +136,5 @@ namespace Google.Protobuf
{
return new InvalidProtocolBufferException("Message was missing required fields");
}
}
}
}

View File

@@ -62,13 +62,9 @@ namespace Google.Protobuf
internal const string AnyTypeUrlField = "@type";
internal const string AnyDiagnosticValueField = "@value";
internal const string AnyWellKnownTypeValueField = "value";
private const string TypeUrlPrefix = "type.googleapis.com";
private const string NameValueSeparator = ": ";
private const string ValueSeparator = ", ";
private const string MultilineValueSeparator = ",";
private const char ObjectOpenBracket = '{';
private const char ObjectCloseBracket = '}';
private const char ListBracketOpen = '[';
private const char ListBracketClose = ']';
private const string PropertySeparator = ", ";
/// <summary>
/// Returns a formatter using the default settings.
@@ -145,26 +141,11 @@ namespace Google.Protobuf
/// Formats the specified message as JSON.
/// </summary>
/// <param name="message">The message to format.</param>
/// <remarks>This method delegates to <c>Format(IMessage, int)</c> with <c>indentationLevel = 0</c>.</remarks>
/// <returns>The formatted message.</returns>
public string Format(IMessage message) => Format(message, indentationLevel: 0);
/// <summary>
/// Formats the specified message as JSON.
/// </summary>
/// <param name="message">The message to format.</param>
/// <param name="indentationLevel">Indentation level to start at.</param>
/// <remarks>To keep consistent indentation when embedding a message inside another JSON string, set <paramref name="indentationLevel"/>. E.g:
/// <code>
/// var response = $@"{{
/// ""data"": { Format(message, indentationLevel: 1) }
/// }}"</code>
/// </remarks>
/// <returns>The formatted message.</returns>
public string Format(IMessage message, int indentationLevel)
public string Format(IMessage message)
{
var writer = new StringWriter();
Format(message, writer, indentationLevel);
Format(message, writer);
return writer.ToString();
}
@@ -173,29 +154,19 @@ namespace Google.Protobuf
/// </summary>
/// <param name="message">The message to format.</param>
/// <param name="writer">The TextWriter to write the formatted message to.</param>
/// <remarks>This method delegates to <c>Format(IMessage, TextWriter, int)</c> with <c>indentationLevel = 0</c>.</remarks>
/// <returns>The formatted message.</returns>
public void Format(IMessage message, TextWriter writer) => Format(message, writer, indentationLevel: 0);
/// <summary>
/// Formats the specified message as JSON. When <see cref="Settings.Indentation"/> is not null, start indenting at the specified <paramref name="indentationLevel"/>.
/// </summary>
/// <param name="message">The message to format.</param>
/// <param name="writer">The TextWriter to write the formatted message to.</param>
/// <param name="indentationLevel">Indentation level to start at.</param>
/// <remarks>To keep consistent indentation when embedding a message inside another JSON string, set <paramref name="indentationLevel"/>.</remarks>
public void Format(IMessage message, TextWriter writer, int indentationLevel)
public void Format(IMessage message, TextWriter writer)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(writer, nameof(writer));
if (message.Descriptor.IsWellKnownType)
{
WriteWellKnownTypeValue(writer, message.Descriptor, message, indentationLevel);
WriteWellKnownTypeValue(writer, message.Descriptor, message);
}
else
{
WriteMessage(writer, message, indentationLevel);
WriteMessage(writer, message);
}
}
@@ -222,7 +193,7 @@ namespace Google.Protobuf
return diagnosticFormatter.Format(message);
}
private void WriteMessage(TextWriter writer, IMessage message, int indentationLevel)
private void WriteMessage(TextWriter writer, IMessage message)
{
if (message == null)
{
@@ -231,19 +202,19 @@ namespace Google.Protobuf
}
if (DiagnosticOnly)
{
if (message is ICustomDiagnosticMessage customDiagnosticMessage)
ICustomDiagnosticMessage customDiagnosticMessage = message as ICustomDiagnosticMessage;
if (customDiagnosticMessage != null)
{
writer.Write(customDiagnosticMessage.ToDiagnosticString());
return;
}
}
WriteBracketOpen(writer, ObjectOpenBracket);
bool writtenFields = WriteMessageFields(writer, message, false, indentationLevel + 1);
WriteBracketClose(writer, ObjectCloseBracket, writtenFields, indentationLevel);
writer.Write("{ ");
bool writtenFields = WriteMessageFields(writer, message, false);
writer.Write(writtenFields ? " }" : "}");
}
private bool WriteMessageFields(TextWriter writer, IMessage message, bool assumeFirstFieldWritten, int indentationLevel)
private bool WriteMessageFields(TextWriter writer, IMessage message, bool assumeFirstFieldWritten)
{
var fields = message.Descriptor.Fields;
bool first = !assumeFirstFieldWritten;
@@ -257,8 +228,10 @@ namespace Google.Protobuf
continue;
}
MaybeWriteValueSeparator(writer, first);
MaybeWriteValueWhitespace(writer, indentationLevel);
if (!first)
{
writer.Write(PropertySeparator);
}
if (settings.PreserveProtoFieldNames)
{
@@ -269,23 +242,13 @@ namespace Google.Protobuf
WriteString(writer, accessor.Descriptor.JsonName);
}
writer.Write(NameValueSeparator);
WriteValue(writer, value, indentationLevel);
WriteValue(writer, value);
first = false;
}
return !first;
}
private void MaybeWriteValueSeparator(TextWriter writer, bool first)
{
if (first)
{
return;
}
writer.Write(settings.Indentation == null ? ValueSeparator : MultilineValueSeparator);
}
/// <summary>
/// Determines whether or not a field value should be serialized according to the field,
/// its value in the message, and the settings of this formatter.
@@ -357,20 +320,39 @@ namespace Google.Protobuf
IList list = (IList) value;
return list.Count == 0;
}
return descriptor.FieldType switch
switch (descriptor.FieldType)
{
FieldType.Bool => (bool) value == false,
FieldType.Bytes => (ByteString) value == ByteString.Empty,
FieldType.String => (string) value == "",
FieldType.Double => (double) value == 0.0,
FieldType.SInt32 or FieldType.Int32 or FieldType.SFixed32 or FieldType.Enum => (int) value == 0,
FieldType.Fixed32 or FieldType.UInt32 => (uint) value == 0,
FieldType.Fixed64 or FieldType.UInt64 => (ulong) value == 0,
FieldType.SFixed64 or FieldType.Int64 or FieldType.SInt64 => (long) value == 0,
FieldType.Float => (float) value == 0f,
FieldType.Message or FieldType.Group => value == null,
_ => throw new ArgumentException("Invalid field type"),
};
case FieldType.Bool:
return (bool) value == false;
case FieldType.Bytes:
return (ByteString) value == ByteString.Empty;
case FieldType.String:
return (string) value == "";
case FieldType.Double:
return (double) value == 0.0;
case FieldType.SInt32:
case FieldType.Int32:
case FieldType.SFixed32:
case FieldType.Enum:
return (int) value == 0;
case FieldType.Fixed32:
case FieldType.UInt32:
return (uint) value == 0;
case FieldType.Fixed64:
case FieldType.UInt64:
return (ulong) value == 0;
case FieldType.SFixed64:
case FieldType.Int64:
case FieldType.SInt64:
return (long) value == 0;
case FieldType.Float:
return (float) value == 0f;
case FieldType.Message:
case FieldType.Group: // Never expect to get this, but...
return value == null;
default:
throw new ArgumentException("Invalid field type");
}
}
/// <summary>
@@ -381,46 +363,34 @@ namespace Google.Protobuf
/// </summary>
/// <param name="writer">The writer to write the value to. Must not be null.</param>
/// <param name="value">The value to write. May be null.</param>
/// <remarks>Delegates to <c>WriteValue(TextWriter, object, int)</c> with <c>indentationLevel = 0</c>.</remarks>
public void WriteValue(TextWriter writer, object value) => WriteValue(writer, value, 0);
/// <summary>
/// Writes a single value to the given writer as JSON. Only types understood by
/// Protocol Buffers can be written in this way. This method is only exposed for
/// advanced use cases; most users should be using <see cref="Format(IMessage)"/>
/// or <see cref="Format(IMessage, TextWriter)"/>.
/// </summary>
/// <param name="writer">The writer to write the value to. Must not be null.</param>
/// <param name="value">The value to write. May be null.</param>
/// <param name="indentationLevel">The current indentationLevel. Not used when <see cref="Settings.Indentation"/> is null.</param>
public void WriteValue(TextWriter writer, object value, int indentationLevel)
public void WriteValue(TextWriter writer, object value)
{
if (value == null || value is NullValue)
{
WriteNull(writer);
}
else if (value is bool b)
else if (value is bool)
{
writer.Write(b ? "true" : "false");
writer.Write((bool)value ? "true" : "false");
}
else if (value is ByteString byteString)
else if (value is ByteString)
{
// Nothing in Base64 needs escaping
writer.Write('"');
writer.Write(byteString.ToBase64());
writer.Write(((ByteString)value).ToBase64());
writer.Write('"');
}
else if (value is string str)
else if (value is string)
{
WriteString(writer, str);
WriteString(writer, (string)value);
}
else if (value is IDictionary dictionary)
else if (value is IDictionary)
{
WriteDictionary(writer, dictionary, indentationLevel);
WriteDictionary(writer, (IDictionary)value);
}
else if (value is IList list)
else if (value is IList)
{
WriteList(writer, list, indentationLevel);
WriteList(writer, (IList)value);
}
else if (value is int || value is uint)
{
@@ -467,9 +437,9 @@ namespace Google.Protobuf
writer.Write(text);
}
}
else if (value is IMessage message)
else if (value is IMessage)
{
Format(message, writer, indentationLevel);
Format((IMessage)value, writer);
}
else
{
@@ -483,7 +453,7 @@ namespace Google.Protobuf
/// values are using the embedded well-known types, in order to allow for dynamic messages
/// in the future.
/// </summary>
private void WriteWellKnownTypeValue(TextWriter writer, MessageDescriptor descriptor, object value, int indentationLevel)
private void WriteWellKnownTypeValue(TextWriter writer, MessageDescriptor descriptor, object value)
{
// Currently, we can never actually get here, because null values are always handled by the caller. But if we *could*,
// this would do the right thing.
@@ -499,8 +469,9 @@ namespace Google.Protobuf
// WriteValue will do the right thing.)
if (descriptor.IsWrapperType)
{
if (value is IMessage message)
if (value is IMessage)
{
var message = (IMessage) value;
value = message.Descriptor.Fields[WrappersReflection.WrapperValueFieldNumber].Accessor.GetValue(message);
}
WriteValue(writer, value);
@@ -523,26 +494,26 @@ namespace Google.Protobuf
}
if (descriptor.FullName == Struct.Descriptor.FullName)
{
WriteStruct(writer, (IMessage)value, indentationLevel);
WriteStruct(writer, (IMessage)value);
return;
}
if (descriptor.FullName == ListValue.Descriptor.FullName)
{
var fieldAccessor = descriptor.Fields[ListValue.ValuesFieldNumber].Accessor;
WriteList(writer, (IList)fieldAccessor.GetValue((IMessage)value), indentationLevel);
WriteList(writer, (IList)fieldAccessor.GetValue((IMessage)value));
return;
}
if (descriptor.FullName == Value.Descriptor.FullName)
{
WriteStructFieldValue(writer, (IMessage)value, indentationLevel);
WriteStructFieldValue(writer, (IMessage)value);
return;
}
if (descriptor.FullName == Any.Descriptor.FullName)
{
WriteAny(writer, (IMessage)value, indentationLevel);
WriteAny(writer, (IMessage)value);
return;
}
WriteMessage(writer, (IMessage)value, indentationLevel);
WriteMessage(writer, (IMessage)value);
}
private void WriteTimestamp(TextWriter writer, IMessage value)
@@ -570,7 +541,7 @@ namespace Google.Protobuf
writer.Write(FieldMask.ToJson(paths, DiagnosticOnly));
}
private void WriteAny(TextWriter writer, IMessage value, int indentationLevel)
private void WriteAny(TextWriter writer, IMessage value)
{
if (DiagnosticOnly)
{
@@ -587,23 +558,23 @@ namespace Google.Protobuf
throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'");
}
IMessage message = descriptor.Parser.ParseFrom(data);
WriteBracketOpen(writer, ObjectOpenBracket);
writer.Write("{ ");
WriteString(writer, AnyTypeUrlField);
writer.Write(NameValueSeparator);
WriteString(writer, typeUrl);
if (descriptor.IsWellKnownType)
{
writer.Write(ValueSeparator);
writer.Write(PropertySeparator);
WriteString(writer, AnyWellKnownTypeValueField);
writer.Write(NameValueSeparator);
WriteWellKnownTypeValue(writer, descriptor, message, indentationLevel);
WriteWellKnownTypeValue(writer, descriptor, message);
}
else
{
WriteMessageFields(writer, message, true, indentationLevel);
WriteMessageFields(writer, message, true);
}
WriteBracketClose(writer, ObjectCloseBracket, true, indentationLevel);
writer.Write(" }");
}
private void WriteDiagnosticOnlyAny(TextWriter writer, IMessage value)
@@ -614,7 +585,7 @@ namespace Google.Protobuf
WriteString(writer, AnyTypeUrlField);
writer.Write(NameValueSeparator);
WriteString(writer, typeUrl);
writer.Write(ValueSeparator);
writer.Write(PropertySeparator);
WriteString(writer, AnyDiagnosticValueField);
writer.Write(NameValueSeparator);
writer.Write('"');
@@ -623,9 +594,9 @@ namespace Google.Protobuf
writer.Write(" }");
}
private void WriteStruct(TextWriter writer, IMessage message, int indentationLevel)
private void WriteStruct(TextWriter writer, IMessage message)
{
WriteBracketOpen(writer, ObjectOpenBracket);
writer.Write("{ ");
IDictionary fields = (IDictionary) message.Descriptor.Fields[Struct.FieldsFieldNumber].Accessor.GetValue(message);
bool first = true;
foreach (DictionaryEntry entry in fields)
@@ -637,17 +608,19 @@ namespace Google.Protobuf
throw new InvalidOperationException("Struct fields cannot have an empty key or a null value.");
}
MaybeWriteValueSeparator(writer, first);
MaybeWriteValueWhitespace(writer, indentationLevel + 1);
if (!first)
{
writer.Write(PropertySeparator);
}
WriteString(writer, key);
writer.Write(NameValueSeparator);
WriteStructFieldValue(writer, value, indentationLevel + 1);
WriteStructFieldValue(writer, value);
first = false;
}
WriteBracketClose(writer, ObjectCloseBracket, !first, indentationLevel);
writer.Write(first ? "}" : " }");
}
private void WriteStructFieldValue(TextWriter writer, IMessage message, int indentationLevel)
private void WriteStructFieldValue(TextWriter writer, IMessage message)
{
var specifiedField = message.Descriptor.Oneofs[0].Accessor.GetCaseFieldDescriptor(message);
if (specifiedField == null)
@@ -668,7 +641,7 @@ namespace Google.Protobuf
case Value.ListValueFieldNumber:
// Structs and ListValues are nested messages, and already well-known types.
var nestedMessage = (IMessage) specifiedField.Accessor.GetValue(message);
WriteWellKnownTypeValue(writer, nestedMessage.Descriptor, nestedMessage, indentationLevel);
WriteWellKnownTypeValue(writer, nestedMessage.Descriptor, nestedMessage);
return;
case Value.NullValueFieldNumber:
WriteNull(writer);
@@ -678,40 +651,43 @@ namespace Google.Protobuf
}
}
internal void WriteList(TextWriter writer, IList list, int indentationLevel = 0)
internal void WriteList(TextWriter writer, IList list)
{
WriteBracketOpen(writer, ListBracketOpen);
writer.Write("[ ");
bool first = true;
foreach (var value in list)
{
MaybeWriteValueSeparator(writer, first);
MaybeWriteValueWhitespace(writer, indentationLevel + 1);
WriteValue(writer, value, indentationLevel + 1);
if (!first)
{
writer.Write(PropertySeparator);
}
WriteValue(writer, value);
first = false;
}
WriteBracketClose(writer, ListBracketClose, !first, indentationLevel);
writer.Write(first ? "]" : " ]");
}
internal void WriteDictionary(TextWriter writer, IDictionary dictionary, int indentationLevel = 0)
internal void WriteDictionary(TextWriter writer, IDictionary dictionary)
{
WriteBracketOpen(writer, ObjectOpenBracket);
writer.Write("{ ");
bool first = true;
// This will box each pair. Could use IDictionaryEnumerator, but that's ugly in terms of disposal.
foreach (DictionaryEntry pair in dictionary)
{
if (!first)
{
writer.Write(PropertySeparator);
}
string keyText;
if (pair.Key is string s)
if (pair.Key is string)
{
keyText = s;
keyText = (string) pair.Key;
}
else if (pair.Key is bool b)
else if (pair.Key is bool)
{
keyText = b ? "true" : "false";
keyText = (bool) pair.Key ? "true" : "false";
}
else if (pair.Key is int || pair.Key is uint || pair.Key is long || pair.Key is ulong)
else if (pair.Key is int || pair.Key is uint | pair.Key is long || pair.Key is ulong)
{
keyText = ((IFormattable) pair.Key).ToString("d", CultureInfo.InvariantCulture);
}
@@ -723,16 +699,12 @@ namespace Google.Protobuf
}
throw new ArgumentException("Unhandled dictionary key type: " + pair.Key.GetType());
}
MaybeWriteValueSeparator(writer, first);
MaybeWriteValueWhitespace(writer, indentationLevel + 1);
WriteString(writer, keyText);
writer.Write(NameValueSeparator);
WriteValue(writer, pair.Value);
first = false;
}
WriteBracketClose(writer, ObjectCloseBracket, !first, indentationLevel);
writer.Write(first ? "}" : " }");
}
/// <summary>
@@ -816,49 +788,6 @@ namespace Google.Protobuf
writer.Write(Hex[(c >> 0) & 0xf]);
}
private void WriteBracketOpen(TextWriter writer, char openChar)
{
writer.Write(openChar);
if (settings.Indentation == null)
{
writer.Write(' ');
}
}
private void WriteBracketClose(TextWriter writer, char closeChar, bool hasFields, int indentationLevel)
{
if (hasFields)
{
if (settings.Indentation != null)
{
writer.WriteLine();
WriteIndentation(writer, indentationLevel);
}
else
{
writer.Write(" ");
}
}
writer.Write(closeChar);
}
private void MaybeWriteValueWhitespace(TextWriter writer, int indentationLevel)
{
if (settings.Indentation != null) {
writer.WriteLine();
WriteIndentation(writer, indentationLevel);
}
}
private void WriteIndentation(TextWriter writer, int indentationLevel)
{
for (int i = 0; i < indentationLevel; i++)
{
writer.Write(settings.Indentation);
}
}
/// <summary>
/// Settings controlling JSON formatting.
/// </summary>
@@ -899,10 +828,6 @@ namespace Google.Protobuf
/// </summary>
public bool PreserveProtoFieldNames { get; }
/// <summary>
/// Indentation string, used for formatting. Setting null disables indentation.
/// </summary>
public string Indentation { get; }
/// <summary>
/// Creates a new <see cref="Settings"/> object with the specified formatting of default values
@@ -930,54 +855,40 @@ namespace Google.Protobuf
/// <param name="typeRegistry">The <see cref="TypeRegistry"/> to use when formatting <see cref="Any"/> messages. TypeRegistry.Empty will be used if it is null.</param>
/// <param name="formatEnumsAsIntegers"><c>true</c> to format the enums as integers; <c>false</c> to format enums as enum names.</param>
/// <param name="preserveProtoFieldNames"><c>true</c> to preserve proto field names; <c>false</c> to convert them to lowerCamelCase.</param>
/// <param name="indentation">The indentation string to use for multi-line formatting. <c>null</c> to disable multi-line format.</param>
private Settings(bool formatDefaultValues,
TypeRegistry typeRegistry,
bool formatEnumsAsIntegers,
bool preserveProtoFieldNames,
string indentation = null)
bool preserveProtoFieldNames)
{
FormatDefaultValues = formatDefaultValues;
TypeRegistry = typeRegistry ?? TypeRegistry.Empty;
FormatEnumsAsIntegers = formatEnumsAsIntegers;
PreserveProtoFieldNames = preserveProtoFieldNames;
Indentation = indentation;
}
/// <summary>
/// Creates a new <see cref="Settings"/> object with the specified formatting of default values and the current settings.
/// </summary>
/// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param>
public Settings WithFormatDefaultValues(bool formatDefaultValues) => new Settings(formatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames, Indentation);
public Settings WithFormatDefaultValues(bool formatDefaultValues) => new Settings(formatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames);
/// <summary>
/// Creates a new <see cref="Settings"/> object with the specified type registry and the current settings.
/// </summary>
/// <param name="typeRegistry">The <see cref="TypeRegistry"/> to use when formatting <see cref="Any"/> messages.</param>
public Settings WithTypeRegistry(TypeRegistry typeRegistry) => new Settings(FormatDefaultValues, typeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames, Indentation);
public Settings WithTypeRegistry(TypeRegistry typeRegistry) => new Settings(FormatDefaultValues, typeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames);
/// <summary>
/// Creates a new <see cref="Settings"/> object with the specified enums formatting option and the current settings.
/// </summary>
/// <param name="formatEnumsAsIntegers"><c>true</c> to format the enums as integers; <c>false</c> to format enums as enum names.</param>
public Settings WithFormatEnumsAsIntegers(bool formatEnumsAsIntegers) => new Settings(FormatDefaultValues, TypeRegistry, formatEnumsAsIntegers, PreserveProtoFieldNames, Indentation);
public Settings WithFormatEnumsAsIntegers(bool formatEnumsAsIntegers) => new Settings(FormatDefaultValues, TypeRegistry, formatEnumsAsIntegers, PreserveProtoFieldNames);
/// <summary>
/// Creates a new <see cref="Settings"/> object with the specified field name formatting option and the current settings.
/// </summary>
/// <param name="preserveProtoFieldNames"><c>true</c> to preserve proto field names; <c>false</c> to convert them to lowerCamelCase.</param>
public Settings WithPreserveProtoFieldNames(bool preserveProtoFieldNames) => new Settings(FormatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, preserveProtoFieldNames, Indentation);
/// <summary>
/// Creates a new <see cref="Settings"/> object with the specified indentation and the current settings.
/// </summary>
/// <param name="indentation">The string to output for each level of indentation (nesting). The default is two spaces per level. Use null to disable indentation entirely.</param>
/// <remarks>A non-null value for <see cref="Indentation"/> will insert additional line-breaks to the JSON output.
/// Each line will contain either a single value, or braces. The default line-break is determined by <see cref="Environment.NewLine"/>,
/// which is <c>"\n"</c> on Unix platforms, and <c>"\r\n"</c> on Windows. If <see cref="JsonFormatter"/> seems to produce empty lines,
/// you need to pass a <see cref="TextWriter"/> that uses a <c>"\n"</c> newline. See <see cref="JsonFormatter.Format(Google.Protobuf.IMessage, TextWriter)"/>.
/// </remarks>
public Settings WithIndentation(string indentation = " ") => new Settings(FormatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames, indentation);
public Settings WithPreserveProtoFieldNames(bool preserveProtoFieldNames) => new Settings(FormatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, preserveProtoFieldNames);
}
// Effectively a cache of mapping from enum values to the original name as specified in the proto file,
@@ -1005,8 +916,9 @@ namespace Google.Protobuf
}
}
string originalName;
// If this returns false, originalName will be null, which is what we want.
nameMapping.TryGetValue(value, out string originalName);
nameMapping.TryGetValue(value, out originalName);
return originalName;
}

View File

@@ -70,7 +70,8 @@ namespace Google.Protobuf
// TODO: Consider introducing a class containing parse state of the parser, tokenizer and depth. That would simplify these handlers
// and the signatures of various methods.
private static readonly Dictionary<string, Action<JsonParser, IMessage, JsonTokenizer>> WellKnownTypeHandlers = new()
private static readonly Dictionary<string, Action<JsonParser, IMessage, JsonTokenizer>>
WellKnownTypeHandlers = new Dictionary<string, Action<JsonParser, IMessage, JsonTokenizer>>
{
{ Timestamp.Descriptor.FullName, (parser, message, tokenizer) => MergeTimestamp(message, tokenizer.Next()) },
{ Duration.Descriptor.FullName, (parser, message, tokenizer) => MergeDuration(message, tokenizer.Next()) },
@@ -155,7 +156,8 @@ namespace Google.Protobuf
}
if (message.Descriptor.IsWellKnownType)
{
if (WellKnownTypeHandlers.TryGetValue(message.Descriptor.FullName, out Action<JsonParser, IMessage, JsonTokenizer> handler))
Action<JsonParser, IMessage, JsonTokenizer> handler;
if (WellKnownTypeHandlers.TryGetValue(message.Descriptor.FullName, out handler))
{
handler(this, message, tokenizer);
return;
@@ -185,7 +187,8 @@ namespace Google.Protobuf
throw new InvalidOperationException("Unexpected token type " + token.Type);
}
string name = token.StringValue;
if (jsonFieldMap.TryGetValue(name, out FieldDescriptor field))
FieldDescriptor field;
if (jsonFieldMap.TryGetValue(name, out field))
{
if (field.ContainingOneof != null)
{
@@ -300,7 +303,11 @@ namespace Google.Protobuf
}
object key = ParseMapKey(keyField, token.StringValue);
object value = ParseSingleValue(valueField, tokenizer);
dictionary[key] = value ?? throw new InvalidProtocolBufferException("Map values must not be null");
if (value == null)
{
throw new InvalidProtocolBufferException("Map values must not be null");
}
dictionary[key] = value;
}
}
@@ -642,15 +649,19 @@ namespace Google.Protobuf
{
return float.NaN;
}
float converted = (float) value;
// If the value is out of range of float, the cast representation will be infinite.
// If the original value was infinite as well, that's fine - we'll return the 32-bit
// version (with the correct sign).
if (float.IsInfinity(converted) && !double.IsInfinity(value))
if (value > float.MaxValue || value < float.MinValue)
{
if (double.IsPositiveInfinity(value))
{
return float.PositiveInfinity;
}
if (double.IsNegativeInfinity(value))
{
return float.NegativeInfinity;
}
throw new InvalidProtocolBufferException($"Value out of range: {value}");
}
return converted;
return (float) value;
case FieldType.Enum:
CheckInteger(value);
// Just return it as an int, and let the CLR convert it.
@@ -842,7 +853,7 @@ namespace Google.Protobuf
if (secondsToAdd < 0 && nanosToAdd > 0)
{
secondsToAdd++;
nanosToAdd -= Duration.NanosecondsPerSecond;
nanosToAdd = nanosToAdd - Duration.NanosecondsPerSecond;
}
if (secondsToAdd != 0 || nanosToAdd != 0)
{
@@ -1038,20 +1049,23 @@ namespace Google.Protobuf
/// when unknown fields are encountered.
/// </summary>
/// <param name="ignoreUnknownFields"><c>true</c> if unknown fields should be ignored when parsing; <c>false</c> to throw an exception.</param>
public Settings WithIgnoreUnknownFields(bool ignoreUnknownFields) => new(RecursionLimit, TypeRegistry, ignoreUnknownFields);
public Settings WithIgnoreUnknownFields(bool ignoreUnknownFields) =>
new Settings(RecursionLimit, TypeRegistry, ignoreUnknownFields);
/// <summary>
/// Creates a new <see cref="Settings"/> object based on this one, but with the specified recursion limit.
/// </summary>
/// <param name="recursionLimit">The new recursion limit.</param>
public Settings WithRecursionLimit(int recursionLimit) => new(recursionLimit, TypeRegistry, IgnoreUnknownFields);
public Settings WithRecursionLimit(int recursionLimit) =>
new Settings(recursionLimit, TypeRegistry, IgnoreUnknownFields);
/// <summary>
/// Creates a new <see cref="Settings"/> object based on this one, but with the specified type registry.
/// </summary>
/// <param name="typeRegistry">The new type registry. Must not be null.</param>
public Settings WithTypeRegistry(TypeRegistry typeRegistry) =>
new(RecursionLimit,
new Settings(
RecursionLimit,
ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)),
IgnoreUnknownFields);
}

View File

@@ -36,14 +36,24 @@ namespace Google.Protobuf
{
internal sealed class JsonToken : IEquatable<JsonToken>
{
internal static JsonToken Null { get; } = new JsonToken(TokenType.Null);
internal static JsonToken False { get; } = new JsonToken(TokenType.False);
internal static JsonToken True { get; } = new JsonToken(TokenType.True);
internal static JsonToken StartObject { get; } = new JsonToken(TokenType.StartObject);
internal static JsonToken EndObject { get; } = new JsonToken(TokenType.EndObject);
internal static JsonToken StartArray { get; } = new JsonToken(TokenType.StartArray);
internal static JsonToken EndArray { get; } = new JsonToken(TokenType.EndArray);
internal static JsonToken EndDocument { get; } = new JsonToken(TokenType.EndDocument);
// 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)
{
@@ -84,9 +94,9 @@ namespace Google.Protobuf
private readonly string stringValue;
private readonly double numberValue;
internal TokenType Type => type;
internal string StringValue => stringValue;
internal double NumberValue => 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)
{
@@ -95,7 +105,10 @@ namespace Google.Protobuf
this.numberValue = numberValue;
}
public override bool Equals(object obj) => Equals(obj as JsonToken);
public override bool Equals(object obj)
{
return Equals(obj as JsonToken);
}
public override int GetHashCode()
{
@@ -111,26 +124,38 @@ namespace Google.Protobuf
public override string ToString()
{
return type switch
switch (type)
{
TokenType.Null => "null",
TokenType.True => "true",
TokenType.False => "false",
TokenType.Name => $"name ({stringValue})",
TokenType.StringValue => $"value ({stringValue})",
TokenType.Number => $"number ({numberValue})",
TokenType.StartObject => "start-object",
TokenType.EndObject => "end-object",
TokenType.StartArray => "start-array",
TokenType.EndArray => "end-array",
TokenType.EndDocument => "end-document",
_ => throw new InvalidOperationException($"Token is of unknown type {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 (other is null)
if (ReferenceEquals(other, null))
{
return false;
}

View File

@@ -29,7 +29,6 @@
// (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;
using System.Collections.Generic;
using System.Globalization;
@@ -363,19 +362,29 @@ namespace Google.Protobuf
private char ReadEscapedCharacter()
{
char c = reader.ReadOrFail("Unexpected end of text while reading character escape sequence");
return c switch
switch (c)
{
'n' => '\n',
'\\' => '\\',
'b' => '\b',
'f' => '\f',
'r' => '\r',
't' => '\t',
'"' => '"',
'/' => '/',
'u' => ReadUnicodeEscape(),
_ => throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int)c)),
};
case 'n':
return '\n';
case '\\':
return '\\';
case 'b':
return '\b';
case 'f':
return '\f';
case 'r':
return '\r';
case 't':
return '\t';
case '"':
return '"';
case '/':
return '/';
case 'u':
return ReadUnicodeEscape();
default:
throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c));
}
}
/// <summary>
@@ -489,7 +498,8 @@ namespace Google.Protobuf
throw reader.CreateException("Invalid numeric literal");
}
builder.Append(first);
char? next = ConsumeDigits(builder, out int digitCount);
int digitCount;
char? next = ConsumeDigits(builder, out digitCount);
if (first == '0' && digitCount != 0)
{
throw reader.CreateException("Invalid numeric literal: leading 0 for non-zero value.");
@@ -500,7 +510,8 @@ namespace Google.Protobuf
private char? ReadFrac(StringBuilder builder)
{
builder.Append('.'); // Already consumed this
char? next = ConsumeDigits(builder, out int digitCount);
int digitCount;
char? next = ConsumeDigits(builder, out digitCount);
if (digitCount == 0)
{
throw reader.CreateException("Invalid numeric literal: fraction with no trailing digits");
@@ -524,7 +535,8 @@ namespace Google.Protobuf
{
reader.PushBack(next.Value);
}
next = ConsumeDigits(builder, out int digitCount);
int digitCount;
next = ConsumeDigits(builder, out digitCount);
if (digitCount == 0)
{
throw reader.CreateException("Invalid numeric literal: exponent without value");
@@ -579,13 +591,20 @@ namespace Google.Protobuf
{
containerStack.Pop();
var parent = containerStack.Peek();
state = parent switch
switch (parent)
{
ContainerType.Object => State.ObjectAfterProperty,
ContainerType.Array => State.ArrayAfterValue,
ContainerType.Document => State.ExpectedEndOfDocument,
_ => throw new InvalidOperationException("Unexpected container type: " + parent),
};
case ContainerType.Object:
state = State.ObjectAfterProperty;
break;
case ContainerType.Array:
state = State.ArrayAfterValue;
break;
case ContainerType.Document:
state = State.ExpectedEndOfDocument;
break;
default:
throw new InvalidOperationException("Unexpected container type: " + parent);
}
}
private enum ContainerType

View File

@@ -51,20 +51,34 @@ namespace Google.Protobuf
bytesLeft = size;
}
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override void Flush()
{
}
public override long Length => throw new NotSupportedException();
public override long Length
{
get { throw new NotSupportedException(); }
}
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -78,10 +92,19 @@ namespace Google.Protobuf
return 0;
}
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value) => throw new NotSupportedException();
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
}
}

View File

@@ -107,7 +107,7 @@ namespace Google.Protobuf
/// <returns>The message data as a byte array.</returns>
public static byte[] ToByteArray(this IMessage message)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(message, "message");
byte[] result = new byte[message.CalculateSize()];
CodedOutputStream output = new CodedOutputStream(result);
message.WriteTo(output);
@@ -122,8 +122,8 @@ namespace Google.Protobuf
/// <param name="output">The stream to write to.</param>
public static void WriteTo(this IMessage message, Stream output)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(output, nameof(output));
ProtoPreconditions.CheckNotNull(message, "message");
ProtoPreconditions.CheckNotNull(output, "output");
CodedOutputStream codedOutput = new CodedOutputStream(output);
message.WriteTo(codedOutput);
codedOutput.Flush();
@@ -136,8 +136,8 @@ namespace Google.Protobuf
/// <param name="output">The output stream to write to.</param>
public static void WriteDelimitedTo(this IMessage message, Stream output)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(output, nameof(output));
ProtoPreconditions.CheckNotNull(message, "message");
ProtoPreconditions.CheckNotNull(output, "output");
CodedOutputStream codedOutput = new CodedOutputStream(output);
codedOutput.WriteLength(message.CalculateSize());
message.WriteTo(codedOutput);
@@ -151,7 +151,7 @@ namespace Google.Protobuf
/// <returns>The message data as a byte string.</returns>
public static ByteString ToByteString(this IMessage message)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(message, "message");
return ByteString.AttachBytes(message.ToByteArray());
}
@@ -251,34 +251,30 @@ namespace Google.Protobuf
// Implementations allowing unknown fields to be discarded.
internal static void MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields, ExtensionRegistry registry)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(data, nameof(data));
CodedInputStream input = new CodedInputStream(data)
{
DiscardUnknownFields = discardUnknownFields,
ExtensionRegistry = registry
};
ProtoPreconditions.CheckNotNull(message, "message");
ProtoPreconditions.CheckNotNull(data, "data");
CodedInputStream input = new CodedInputStream(data);
input.DiscardUnknownFields = discardUnknownFields;
input.ExtensionRegistry = registry;
message.MergeFrom(input);
input.CheckReadEndOfStreamTag();
}
internal static void MergeFrom(this IMessage message, byte[] data, int offset, int length, bool discardUnknownFields, ExtensionRegistry registry)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(data, nameof(data));
CodedInputStream input = new CodedInputStream(data, offset, length)
{
DiscardUnknownFields = discardUnknownFields,
ExtensionRegistry = registry
};
ProtoPreconditions.CheckNotNull(message, "message");
ProtoPreconditions.CheckNotNull(data, "data");
CodedInputStream input = new CodedInputStream(data, offset, length);
input.DiscardUnknownFields = discardUnknownFields;
input.ExtensionRegistry = registry;
message.MergeFrom(input);
input.CheckReadEndOfStreamTag();
}
internal static void MergeFrom(this IMessage message, ByteString data, bool discardUnknownFields, ExtensionRegistry registry)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(data, nameof(data));
ProtoPreconditions.CheckNotNull(message, "message");
ProtoPreconditions.CheckNotNull(data, "data");
CodedInputStream input = data.CreateCodedInput();
input.DiscardUnknownFields = discardUnknownFields;
input.ExtensionRegistry = registry;
@@ -288,13 +284,11 @@ namespace Google.Protobuf
internal static void MergeFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(input, nameof(input));
CodedInputStream codedInput = new CodedInputStream(input)
{
DiscardUnknownFields = discardUnknownFields,
ExtensionRegistry = registry
};
ProtoPreconditions.CheckNotNull(message, "message");
ProtoPreconditions.CheckNotNull(input, "input");
CodedInputStream codedInput = new CodedInputStream(input);
codedInput.DiscardUnknownFields = discardUnknownFields;
codedInput.ExtensionRegistry = registry;
message.MergeFrom(codedInput);
codedInput.CheckReadEndOfStreamTag();
}
@@ -321,8 +315,8 @@ namespace Google.Protobuf
internal static void MergeDelimitedFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry)
{
ProtoPreconditions.CheckNotNull(message, nameof(message));
ProtoPreconditions.CheckNotNull(input, nameof(input));
ProtoPreconditions.CheckNotNull(message, "message");
ProtoPreconditions.CheckNotNull(input, "input");
int size = (int) CodedInputStream.ReadRawVarint32(input);
Stream limitedStream = new LimitedInputStream(input, size);
MergeFrom(message, limitedStream, discardUnknownFields, registry);

View File

@@ -43,8 +43,9 @@ namespace Google.Protobuf
/// </summary>
public class MessageParser
{
private readonly Func<IMessage> factory;
private protected bool DiscardUnknownFields { get; }
private Func<IMessage> factory;
// TODO: When we use a C# 7.1 compiler, make this private protected.
internal bool DiscardUnknownFields { get; }
internal ExtensionRegistry Extensions { get; }
@@ -171,10 +172,6 @@ namespace Google.Protobuf
/// <summary>
/// Parses a message from the given JSON.
/// </summary>
/// <remarks>This method always uses the default JSON parser; it is not affected by <see cref="WithDiscardUnknownFields(bool)"/>.
/// To ignore unknown fields when parsing JSON, create a <see cref="JsonParser"/> using a <see cref="JsonParser.Settings"/>
/// with <see cref="JsonParser.Settings.IgnoreUnknownFields"/> set to true and call <see cref="JsonParser.Parse{T}(string)"/> directly.
/// </remarks>
/// <param name="json">The JSON to parse.</param>
/// <returns>The parsed message.</returns>
/// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
@@ -207,9 +204,6 @@ namespace Google.Protobuf
/// <summary>
/// Creates a new message parser which optionally discards unknown fields when parsing.
/// </summary>
/// <remarks>Note that this does not affect the behavior of <see cref="ParseJson(string)"/>
/// at all. To ignore unknown fields when parsing JSON, create a <see cref="JsonParser"/> using a <see cref="JsonParser.Settings"/>
/// with <see cref="JsonParser.Settings.IgnoreUnknownFields"/> set to true and call <see cref="JsonParser.Parse{T}(string)"/> directly.</remarks>
/// <param name="discardUnknownFields">Whether or not to discard unknown fields when parsing.</param>
/// <returns>A newly configured message parser.</returns>
public MessageParser WithDiscardUnknownFields(bool discardUnknownFields) =>

View File

@@ -23,7 +23,14 @@ namespace Google.Protobuf
&& number == other.number;
}
public override bool Equals(object obj) => obj is ObjectIntPair<T> pair && Equals(pair);
public override bool Equals(object obj)
{
if (obj is ObjectIntPair<T>)
{
return Equals((ObjectIntPair<T>)obj);
}
return false;
}
public override int GetHashCode()
{

View File

@@ -32,8 +32,14 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{
@@ -47,7 +53,7 @@ namespace Google.Protobuf
public ref struct ParseContext
{
internal const int DefaultRecursionLimit = 100;
internal const int DefaultSizeLimit = int.MaxValue;
internal const int DefaultSizeLimit = Int32.MaxValue;
internal ReadOnlySpan<byte> buffer;
internal ParserInternalState state;
@@ -121,15 +127,14 @@ namespace Google.Protobuf
/// Returns the last tag read, or 0 if no tags have been read or we've read beyond
/// the end of the input.
/// </summary>
internal uint LastTag => state.lastTag;
internal uint LastTag { get { return state.lastTag; } }
/// <summary>
/// Internal-only property; when set to true, unknown fields will be discarded while parsing.
/// </summary>
internal bool DiscardUnknownFields
{
get => state.DiscardUnknownFields;
set => state.DiscardUnknownFields = value;
internal bool DiscardUnknownFields {
get { return state.DiscardUnknownFields; }
set { state.DiscardUnknownFields = value; }
}
/// <summary>
@@ -137,8 +142,8 @@ namespace Google.Protobuf
/// </summary>
internal ExtensionRegistry ExtensionRegistry
{
get => state.ExtensionRegistry;
set => state.ExtensionRegistry = value;
get { return state.ExtensionRegistry; }
set { state.ExtensionRegistry = value; }
}
/// <summary>
@@ -151,85 +156,125 @@ namespace Google.Protobuf
/// </remarks>
/// <returns>The next field tag, or 0 for end of input. (0 is never a valid tag.)</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadTag() => ParsingPrimitives.ParseTag(ref buffer, ref state);
public uint ReadTag()
{
return ParsingPrimitives.ParseTag(ref buffer, ref state);
}
/// <summary>
/// Reads a double field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double ReadDouble() => ParsingPrimitives.ParseDouble(ref buffer, ref state);
public double ReadDouble()
{
return ParsingPrimitives.ParseDouble(ref buffer, ref state);
}
/// <summary>
/// Reads a float field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float ReadFloat() => ParsingPrimitives.ParseFloat(ref buffer, ref state);
public float ReadFloat()
{
return ParsingPrimitives.ParseFloat(ref buffer, ref state);
}
/// <summary>
/// Reads a uint64 field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ulong ReadUInt64() => ParsingPrimitives.ParseRawVarint64(ref buffer, ref state);
public ulong ReadUInt64()
{
return ParsingPrimitives.ParseRawVarint64(ref buffer, ref state);
}
/// <summary>
/// Reads an int64 field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long ReadInt64() => (long)ParsingPrimitives.ParseRawVarint64(ref buffer, ref state);
public long ReadInt64()
{
return (long)ParsingPrimitives.ParseRawVarint64(ref buffer, ref state);
}
/// <summary>
/// Reads an int32 field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadInt32() => (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
public int ReadInt32()
{
return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
}
/// <summary>
/// Reads a fixed64 field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ulong ReadFixed64() => ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state);
public ulong ReadFixed64()
{
return ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state);
}
/// <summary>
/// Reads a fixed32 field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadFixed32() => ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state);
public uint ReadFixed32()
{
return ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state);
}
/// <summary>
/// Reads a bool field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool ReadBool() => ParsingPrimitives.ParseRawVarint64(ref buffer, ref state) != 0;
public bool ReadBool()
{
return ParsingPrimitives.ParseRawVarint64(ref buffer, ref state) != 0;
}
/// <summary>
/// Reads a string field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadString() => ParsingPrimitives.ReadString(ref buffer, ref state);
public string ReadString()
{
return ParsingPrimitives.ReadString(ref buffer, ref state);
}
/// <summary>
/// Reads an embedded message field value from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ReadMessage(IMessage message) => ParsingPrimitivesMessages.ReadMessage(ref this, message);
public void ReadMessage(IMessage message)
{
ParsingPrimitivesMessages.ReadMessage(ref this, message);
}
/// <summary>
/// Reads an embedded group field from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ReadGroup(IMessage message) => ParsingPrimitivesMessages.ReadGroup(ref this, message);
public void ReadGroup(IMessage message)
{
ParsingPrimitivesMessages.ReadGroup(ref this, message);
}
/// <summary>
/// Reads a bytes field value from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ByteString ReadBytes() => ParsingPrimitives.ReadBytes(ref buffer, ref state);
public ByteString ReadBytes()
{
return ParsingPrimitives.ReadBytes(ref buffer, ref state);
}
/// <summary>
/// Reads a uint32 field value from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadUInt32() => ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
public uint ReadUInt32()
{
return ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
}
/// <summary>
/// Reads an enum field value from the input.
@@ -245,25 +290,37 @@ namespace Google.Protobuf
/// Reads an sfixed32 field value from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadSFixed32() => (int)ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state);
public int ReadSFixed32()
{
return (int)ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state);
}
/// <summary>
/// Reads an sfixed64 field value from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long ReadSFixed64() => (long)ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state);
public long ReadSFixed64()
{
return (long)ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state);
}
/// <summary>
/// Reads an sint32 field value from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadSInt32() => ParsingPrimitives.DecodeZigZag32(ParsingPrimitives.ParseRawVarint32(ref buffer, ref state));
public int ReadSInt32()
{
return ParsingPrimitives.DecodeZigZag32(ParsingPrimitives.ParseRawVarint32(ref buffer, ref state));
}
/// <summary>
/// Reads an sint64 field value from the input.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long ReadSInt64() => ParsingPrimitives.DecodeZigZag64(ParsingPrimitives.ParseRawVarint64(ref buffer, ref state));
public long ReadSInt64()
{
return ParsingPrimitives.DecodeZigZag64(ParsingPrimitives.ParseRawVarint64(ref buffer, ref state));
}
/// <summary>
/// Reads a length for length-delimited data.
@@ -273,7 +330,10 @@ namespace Google.Protobuf
/// to make the calling code clearer.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadLength() => (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
public int ReadLength()
{
return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
}
internal void CopyStateTo(CodedInputStream input)
{

View File

@@ -30,8 +30,20 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{
// warning: this is a mutable struct, so it needs to be only passed as a ref!
internal struct ParserInternalState
{

View File

@@ -34,10 +34,13 @@ using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{

View File

@@ -33,6 +33,8 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Security;
using Google.Protobuf.Collections;

View File

@@ -31,7 +31,15 @@
#endregion
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{

View File

@@ -47,3 +47,10 @@ using System.Security;
"981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
"b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
"c5ae9cb6")]
[assembly: InternalsVisibleTo("Google.Protobuf.Benchmarks, PublicKey=" +
"002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
"7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
"981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
"b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
"c5ae9cb6")]

View File

@@ -31,6 +31,7 @@
#endregion
using Google.Protobuf.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
@@ -225,21 +226,24 @@ namespace Google.Protobuf.Reflection
{
if (values == null)
{
value = default;
value = default(T);
return false;
}
if (values.TryGetValue(field, out IExtensionValue extensionValue))
IExtensionValue extensionValue;
if (values.TryGetValue(field, out extensionValue))
{
if (extensionValue is ExtensionValue<T> single)
if (extensionValue is ExtensionValue<T>)
{
ExtensionValue<T> single = extensionValue as ExtensionValue<T>;
ByteString bytes = single.GetValue().ToByteString();
value = new T();
value.MergeFrom(bytes);
return true;
}
else if (extensionValue is RepeatedExtensionValue<T> repeated)
else if (extensionValue is RepeatedExtensionValue<T>)
{
RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>;
value = repeated.GetValue()
.Select(v => v.ToByteString())
.Aggregate(new T(), (t, b) =>
@@ -260,19 +264,22 @@ namespace Google.Protobuf.Reflection
{
if (values == null)
{
value = default;
value = default(T);
return false;
}
if (values.TryGetValue(field, out IExtensionValue extensionValue))
IExtensionValue extensionValue;
if (values.TryGetValue(field, out extensionValue))
{
if (extensionValue is ExtensionValue<T> single)
if (extensionValue is ExtensionValue<T>)
{
ExtensionValue<T> single = extensionValue as ExtensionValue<T>;
value = single.GetValue();
return true;
}
else if (extensionValue is RepeatedExtensionValue<T> repeated)
else if (extensionValue is RepeatedExtensionValue<T>)
{
RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>;
if (repeated.GetValue().Count != 0)
{
RepeatedField<T> repeatedField = repeated.GetValue();
@@ -310,7 +317,7 @@ namespace Google.Protobuf.Reflection
}
}
value = default;
value = default(T);
return false;
}
}

View File

@@ -26,7 +26,7 @@ namespace Google.Protobuf.Reflection {
string.Concat(
"CiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90bxIPZ29vZ2xlLnBy",
"b3RvYnVmIkcKEUZpbGVEZXNjcmlwdG9yU2V0EjIKBGZpbGUYASADKAsyJC5n",
"b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byLsAwoTRmlsZURl",
"b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byLbAwoTRmlsZURl",
"c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg8KB3BhY2thZ2UYAiABKAkS",
"EgoKZGVwZW5kZW5jeRgDIAMoCRIZChFwdWJsaWNfZGVwZW5kZW5jeRgKIAMo",
"BRIXCg93ZWFrX2RlcGVuZGVuY3kYCyADKAUSNgoMbWVzc2FnZV90eXBlGAQg",
@@ -37,137 +37,134 @@ namespace Google.Protobuf.Reflection {
"LnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYCCAB",
"KAsyHC5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMSOQoQc291cmNlX2Nv",
"ZGVfaW5mbxgJIAEoCzIfLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2RlSW5m",
"bxIOCgZzeW50YXgYDCABKAkSDwoHZWRpdGlvbhgNIAEoCSKpBQoPRGVzY3Jp",
"cHRvclByb3RvEgwKBG5hbWUYASABKAkSNAoFZmllbGQYAiADKAsyJS5nb29n",
"bGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8SOAoJZXh0ZW5zaW9u",
"GAYgAygLMiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3Rv",
"EjUKC25lc3RlZF90eXBlGAMgAygLMiAuZ29vZ2xlLnByb3RvYnVmLkRlc2Ny",
"aXB0b3JQcm90bxI3CgllbnVtX3R5cGUYBCADKAsyJC5nb29nbGUucHJvdG9i",
"dWYuRW51bURlc2NyaXB0b3JQcm90bxJICg9leHRlbnNpb25fcmFuZ2UYBSAD",
"KAsyLy5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvclByb3RvLkV4dGVuc2lv",
"blJhbmdlEjkKCm9uZW9mX2RlY2wYCCADKAsyJS5nb29nbGUucHJvdG9idWYu",
"T25lb2ZEZXNjcmlwdG9yUHJvdG8SMAoHb3B0aW9ucxgHIAEoCzIfLmdvb2ds",
"ZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxJGCg5yZXNlcnZlZF9yYW5nZRgJ",
"IAMoCzIuLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9yUHJvdG8uUmVzZXJ2",
"ZWRSYW5nZRIVCg1yZXNlcnZlZF9uYW1lGAogAygJGmUKDkV4dGVuc2lvblJh",
"bmdlEg0KBXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBRI3CgdvcHRpb25zGAMg",
"ASgLMiYuZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJhbmdlT3B0aW9ucxor",
"Cg1SZXNlcnZlZFJhbmdlEg0KBXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBSJn",
"ChVFeHRlbnNpb25SYW5nZU9wdGlvbnMSQwoUdW5pbnRlcnByZXRlZF9vcHRp",
"b24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRp",
"b24qCQjoBxCAgICAAiLVBQoURmllbGREZXNjcmlwdG9yUHJvdG8SDAoEbmFt",
"ZRgBIAEoCRIOCgZudW1iZXIYAyABKAUSOgoFbGFiZWwYBCABKA4yKy5nb29n",
"bGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8uTGFiZWwSOAoEdHlw",
"ZRgFIAEoDjIqLmdvb2dsZS5wcm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90",
"by5UeXBlEhEKCXR5cGVfbmFtZRgGIAEoCRIQCghleHRlbmRlZRgCIAEoCRIV",
"Cg1kZWZhdWx0X3ZhbHVlGAcgASgJEhMKC29uZW9mX2luZGV4GAkgASgFEhEK",
"CWpzb25fbmFtZRgKIAEoCRIuCgdvcHRpb25zGAggASgLMh0uZ29vZ2xlLnBy",
"b3RvYnVmLkZpZWxkT3B0aW9ucxIXCg9wcm90bzNfb3B0aW9uYWwYESABKAgi",
"tgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQARIOCgpUWVBFX0ZMT0FUEAISDgoK",
"VFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0EAQSDgoKVFlQRV9JTlQzMhAF",
"EhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVfRklYRUQzMhAHEg0KCVRZUEVf",
"Qk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoKVFlQRV9HUk9VUBAKEhAKDFRZ",
"UEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQDBIPCgtUWVBFX1VJTlQzMhAN",
"Eg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJWEVEMzIQDxIRCg1UWVBFX1NG",
"SVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIPCgtUWVBFX1NJTlQ2NBASIkMK",
"BUxhYmVsEhIKDkxBQkVMX09QVElPTkFMEAESEgoOTEFCRUxfUkVRVUlSRUQQ",
"AhISCg5MQUJFTF9SRVBFQVRFRBADIlQKFE9uZW9mRGVzY3JpcHRvclByb3Rv",
"EgwKBG5hbWUYASABKAkSLgoHb3B0aW9ucxgCIAEoCzIdLmdvb2dsZS5wcm90",
"b2J1Zi5PbmVvZk9wdGlvbnMipAIKE0VudW1EZXNjcmlwdG9yUHJvdG8SDAoE",
"bmFtZRgBIAEoCRI4CgV2YWx1ZRgCIAMoCzIpLmdvb2dsZS5wcm90b2J1Zi5F",
"bnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SLQoHb3B0aW9ucxgDIAEoCzIcLmdv",
"b2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9ucxJOCg5yZXNlcnZlZF9yYW5nZRgE",
"IAMoCzI2Lmdvb2dsZS5wcm90b2J1Zi5FbnVtRGVzY3JpcHRvclByb3RvLkVu",
"dW1SZXNlcnZlZFJhbmdlEhUKDXJlc2VydmVkX25hbWUYBSADKAkaLwoRRW51",
"bVJlc2VydmVkUmFuZ2USDQoFc3RhcnQYASABKAUSCwoDZW5kGAIgASgFImwK",
"GEVudW1WYWx1ZURlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg4KBm51",
"bWJlchgCIAEoBRIyCgdvcHRpb25zGAMgASgLMiEuZ29vZ2xlLnByb3RvYnVm",
"LkVudW1WYWx1ZU9wdGlvbnMikAEKFlNlcnZpY2VEZXNjcmlwdG9yUHJvdG8S",
"DAoEbmFtZRgBIAEoCRI2CgZtZXRob2QYAiADKAsyJi5nb29nbGUucHJvdG9i",
"dWYuTWV0aG9kRGVzY3JpcHRvclByb3RvEjAKB29wdGlvbnMYAyABKAsyHy5n",
"b29nbGUucHJvdG9idWYuU2VydmljZU9wdGlvbnMiwQEKFU1ldGhvZERlc2Ny",
"aXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEhIKCmlucHV0X3R5cGUYAiABKAkS",
"EwoLb3V0cHV0X3R5cGUYAyABKAkSLwoHb3B0aW9ucxgEIAEoCzIeLmdvb2ds",
"ZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zEh8KEGNsaWVudF9zdHJlYW1pbmcY",
"BSABKAg6BWZhbHNlEh8KEHNlcnZlcl9zdHJlYW1pbmcYBiABKAg6BWZhbHNl",
"IqUGCgtGaWxlT3B0aW9ucxIUCgxqYXZhX3BhY2thZ2UYASABKAkSHAoUamF2",
"YV9vdXRlcl9jbGFzc25hbWUYCCABKAkSIgoTamF2YV9tdWx0aXBsZV9maWxl",
"cxgKIAEoCDoFZmFsc2USKQodamF2YV9nZW5lcmF0ZV9lcXVhbHNfYW5kX2hh",
"c2gYFCABKAhCAhgBEiUKFmphdmFfc3RyaW5nX2NoZWNrX3V0ZjgYGyABKAg6",
"BWZhbHNlEkYKDG9wdGltaXplX2ZvchgJIAEoDjIpLmdvb2dsZS5wcm90b2J1",
"Zi5GaWxlT3B0aW9ucy5PcHRpbWl6ZU1vZGU6BVNQRUVEEhIKCmdvX3BhY2th",
"Z2UYCyABKAkSIgoTY2NfZ2VuZXJpY19zZXJ2aWNlcxgQIAEoCDoFZmFsc2US",
"JAoVamF2YV9nZW5lcmljX3NlcnZpY2VzGBEgASgIOgVmYWxzZRIiChNweV9n",
"ZW5lcmljX3NlcnZpY2VzGBIgASgIOgVmYWxzZRIjChRwaHBfZ2VuZXJpY19z",
"ZXJ2aWNlcxgqIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRlZBgXIAEoCDoFZmFs",
"c2USHgoQY2NfZW5hYmxlX2FyZW5hcxgfIAEoCDoEdHJ1ZRIZChFvYmpjX2Ns",
"YXNzX3ByZWZpeBgkIAEoCRIYChBjc2hhcnBfbmFtZXNwYWNlGCUgASgJEhQK",
"DHN3aWZ0X3ByZWZpeBgnIAEoCRIYChBwaHBfY2xhc3NfcHJlZml4GCggASgJ",
"EhUKDXBocF9uYW1lc3BhY2UYKSABKAkSHgoWcGhwX21ldGFkYXRhX25hbWVz",
"cGFjZRgsIAEoCRIUCgxydWJ5X3BhY2thZ2UYLSABKAkSQwoUdW5pbnRlcnBy",
"ZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJw",
"cmV0ZWRPcHRpb24iOgoMT3B0aW1pemVNb2RlEgkKBVNQRUVEEAESDQoJQ09E",
"RV9TSVpFEAISEAoMTElURV9SVU5USU1FEAMqCQjoBxCAgICAAkoECCYQJyKE",
"AgoOTWVzc2FnZU9wdGlvbnMSJgoXbWVzc2FnZV9zZXRfd2lyZV9mb3JtYXQY",
"ASABKAg6BWZhbHNlEi4KH25vX3N0YW5kYXJkX2Rlc2NyaXB0b3JfYWNjZXNz",
"b3IYAiABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhEK",
"CW1hcF9lbnRyeRgHIAEoCBJDChR1bmludGVycHJldGVkX29wdGlvbhjnByAD",
"KAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgH",
"EICAgIACSgQIBBAFSgQIBRAGSgQIBhAHSgQICBAJSgQICRAKIr4DCgxGaWVs",
"ZE9wdGlvbnMSOgoFY3R5cGUYASABKA4yIy5nb29nbGUucHJvdG9idWYuRmll",
"bGRPcHRpb25zLkNUeXBlOgZTVFJJTkcSDgoGcGFja2VkGAIgASgIEj8KBmpz",
"dHlwZRgGIAEoDjIkLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuSlNU",
"eXBlOglKU19OT1JNQUwSEwoEbGF6eRgFIAEoCDoFZmFsc2USHgoPdW52ZXJp",
"ZmllZF9sYXp5GA8gASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMgASgIOgVm",
"YWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29w",
"dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w",
"dGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABIICgRDT1JEEAESEAoMU1RSSU5H",
"X1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpTX05PUk1BTBAAEg0KCUpTX1NUUklO",
"RxABEg0KCUpTX05VTUJFUhACKgkI6AcQgICAgAJKBAgEEAUiXgoMT25lb2ZP",
"bxIOCgZzeW50YXgYDCABKAkiqQUKD0Rlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
"GAEgASgJEjQKBWZpZWxkGAIgAygLMiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
"RGVzY3JpcHRvclByb3RvEjgKCWV4dGVuc2lvbhgGIAMoCzIlLmdvb2dsZS5w",
"cm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90bxI1CgtuZXN0ZWRfdHlwZRgD",
"IAMoCzIgLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9yUHJvdG8SNwoJZW51",
"bV90eXBlGAQgAygLMiQuZ29vZ2xlLnByb3RvYnVmLkVudW1EZXNjcmlwdG9y",
"UHJvdG8SSAoPZXh0ZW5zaW9uX3JhbmdlGAUgAygLMi8uZ29vZ2xlLnByb3Rv",
"YnVmLkRlc2NyaXB0b3JQcm90by5FeHRlbnNpb25SYW5nZRI5CgpvbmVvZl9k",
"ZWNsGAggAygLMiUuZ29vZ2xlLnByb3RvYnVmLk9uZW9mRGVzY3JpcHRvclBy",
"b3RvEjAKB29wdGlvbnMYByABKAsyHy5nb29nbGUucHJvdG9idWYuTWVzc2Fn",
"ZU9wdGlvbnMSRgoOcmVzZXJ2ZWRfcmFuZ2UYCSADKAsyLi5nb29nbGUucHJv",
"dG9idWYuRGVzY3JpcHRvclByb3RvLlJlc2VydmVkUmFuZ2USFQoNcmVzZXJ2",
"ZWRfbmFtZRgKIAMoCRplCg5FeHRlbnNpb25SYW5nZRINCgVzdGFydBgBIAEo",
"BRILCgNlbmQYAiABKAUSNwoHb3B0aW9ucxgDIAEoCzImLmdvb2dsZS5wcm90",
"b2J1Zi5FeHRlbnNpb25SYW5nZU9wdGlvbnMaKwoNUmVzZXJ2ZWRSYW5nZRIN",
"CgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUiZwoVRXh0ZW5zaW9uUmFuZ2VP",
"cHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2ds",
"ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIikwEK",
"C0VudW1PcHRpb25zEhMKC2FsbG93X2FsaWFzGAIgASgIEhkKCmRlcHJlY2F0",
"ZWQYAyABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo",
"CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQ",
"gICAgAJKBAgFEAYifQoQRW51bVZhbHVlT3B0aW9ucxIZCgpkZXByZWNhdGVk",
"GAEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsy",
"JC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICA",
"gIACInsKDlNlcnZpY2VPcHRpb25zEhkKCmRlcHJlY2F0ZWQYISABKAg6BWZh",
"bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w",
"cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIirQIKDU1l",
"dGhvZE9wdGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USXwoRaWRl",
"bXBvdGVuY3lfbGV2ZWwYIiABKA4yLy5nb29nbGUucHJvdG9idWYuTWV0aG9k",
"T3B0aW9ucy5JZGVtcG90ZW5jeUxldmVsOhNJREVNUE9URU5DWV9VTktOT1dO",
"EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90",
"b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIlAKEElkZW1wb3RlbmN5TGV2ZWwS",
"FwoTSURFTVBPVEVOQ1lfVU5LTk9XThAAEhMKD05PX1NJREVfRUZGRUNUUxAB",
"Eg4KCklERU1QT1RFTlQQAioJCOgHEICAgIACIp4CChNVbmludGVycHJldGVk",
"T3B0aW9uEjsKBG5hbWUYAiADKAsyLS5nb29nbGUucHJvdG9idWYuVW5pbnRl",
"cnByZXRlZE9wdGlvbi5OYW1lUGFydBIYChBpZGVudGlmaWVyX3ZhbHVlGAMg",
"ASgJEhoKEnBvc2l0aXZlX2ludF92YWx1ZRgEIAEoBBIaChJuZWdhdGl2ZV9p",
"bnRfdmFsdWUYBSABKAMSFAoMZG91YmxlX3ZhbHVlGAYgASgBEhQKDHN0cmlu",
"Z192YWx1ZRgHIAEoDBIXCg9hZ2dyZWdhdGVfdmFsdWUYCCABKAkaMwoITmFt",
"ZVBhcnQSEQoJbmFtZV9wYXJ0GAEgAigJEhQKDGlzX2V4dGVuc2lvbhgCIAIo",
"CCLVAQoOU291cmNlQ29kZUluZm8SOgoIbG9jYXRpb24YASADKAsyKC5nb29n",
"bGUucHJvdG9idWYuU291cmNlQ29kZUluZm8uTG9jYXRpb24ahgEKCExvY2F0",
"aW9uEhAKBHBhdGgYASADKAVCAhABEhAKBHNwYW4YAiADKAVCAhABEhgKEGxl",
"YWRpbmdfY29tbWVudHMYAyABKAkSGQoRdHJhaWxpbmdfY29tbWVudHMYBCAB",
"KAkSIQoZbGVhZGluZ19kZXRhY2hlZF9jb21tZW50cxgGIAMoCSKcAgoRR2Vu",
"ZXJhdGVkQ29kZUluZm8SQQoKYW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5w",
"cm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5Bbm5vdGF0aW9uGsMBCgpBbm5v",
"dGF0aW9uEhAKBHBhdGgYASADKAVCAhABEhMKC3NvdXJjZV9maWxlGAIgASgJ",
"Eg0KBWJlZ2luGAMgASgFEgsKA2VuZBgEIAEoBRJICghzZW1hbnRpYxgFIAEo",
"DjI2Lmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5Bbm5vdGF0",
"aW9uLlNlbWFudGljIigKCFNlbWFudGljEggKBE5PTkUQABIHCgNTRVQQARIJ",
"CgVBTElBUxACQn4KE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2NyaXB0b3JQ",
"cm90b3NIAVotZ29vZ2xlLmdvbGFuZy5vcmcvcHJvdG9idWYvdHlwZXMvZGVz",
"Y3JpcHRvcnBi+AEBogIDR1BCqgIaR29vZ2xlLlByb3RvYnVmLlJlZmxlY3Rp",
"b24="));
"ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi1QUK",
"FEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoGbnVtYmVy",
"GAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
"RGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5cGUYBSABKA4yKi5nb29nbGUu",
"cHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8uVHlwZRIRCgl0eXBlX25h",
"bWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkSFQoNZGVmYXVsdF92YWx1ZRgH",
"IAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIRCglqc29uX25hbWUYCiABKAkS",
"LgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlv",
"bnMSFwoPcHJvdG8zX29wdGlvbmFsGBEgASgIIrYCCgRUeXBlEg8KC1RZUEVf",
"RE9VQkxFEAESDgoKVFlQRV9GTE9BVBACEg4KClRZUEVfSU5UNjQQAxIPCgtU",
"WVBFX1VJTlQ2NBAEEg4KClRZUEVfSU5UMzIQBRIQCgxUWVBFX0ZJWEVENjQQ",
"BhIQCgxUWVBFX0ZJWEVEMzIQBxINCglUWVBFX0JPT0wQCBIPCgtUWVBFX1NU",
"UklORxAJEg4KClRZUEVfR1JPVVAQChIQCgxUWVBFX01FU1NBR0UQCxIOCgpU",
"WVBFX0JZVEVTEAwSDwoLVFlQRV9VSU5UMzIQDRINCglUWVBFX0VOVU0QDhIR",
"Cg1UWVBFX1NGSVhFRDMyEA8SEQoNVFlQRV9TRklYRUQ2NBAQEg8KC1RZUEVf",
"U0lOVDMyEBESDwoLVFlQRV9TSU5UNjQQEiJDCgVMYWJlbBISCg5MQUJFTF9P",
"UFRJT05BTBABEhIKDkxBQkVMX1JFUVVJUkVEEAISEgoOTEFCRUxfUkVQRUFU",
"RUQQAyJUChRPbmVvZkRlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEi4K",
"B29wdGlvbnMYAiABKAsyHS5nb29nbGUucHJvdG9idWYuT25lb2ZPcHRpb25z",
"IqQCChNFbnVtRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSOAoFdmFs",
"dWUYAiADKAsyKS5nb29nbGUucHJvdG9idWYuRW51bVZhbHVlRGVzY3JpcHRv",
"clByb3RvEi0KB29wdGlvbnMYAyABKAsyHC5nb29nbGUucHJvdG9idWYuRW51",
"bU9wdGlvbnMSTgoOcmVzZXJ2ZWRfcmFuZ2UYBCADKAsyNi5nb29nbGUucHJv",
"dG9idWYuRW51bURlc2NyaXB0b3JQcm90by5FbnVtUmVzZXJ2ZWRSYW5nZRIV",
"Cg1yZXNlcnZlZF9uYW1lGAUgAygJGi8KEUVudW1SZXNlcnZlZFJhbmdlEg0K",
"BXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBSJsChhFbnVtVmFsdWVEZXNjcmlw",
"dG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZudW1iZXIYAiABKAUSMgoHb3B0",
"aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVPcHRpb25z",
"IpABChZTZXJ2aWNlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSNgoG",
"bWV0aG9kGAIgAygLMiYuZ29vZ2xlLnByb3RvYnVmLk1ldGhvZERlc2NyaXB0",
"b3JQcm90bxIwCgdvcHRpb25zGAMgASgLMh8uZ29vZ2xlLnByb3RvYnVmLlNl",
"cnZpY2VPcHRpb25zIsEBChVNZXRob2REZXNjcmlwdG9yUHJvdG8SDAoEbmFt",
"ZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJEhMKC291dHB1dF90eXBlGAMg",
"ASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29nbGUucHJvdG9idWYuTWV0aG9k",
"T3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5nGAUgASgIOgVmYWxzZRIfChBz",
"ZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxzZSKlBgoLRmlsZU9wdGlvbnMS",
"FAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGphdmFfb3V0ZXJfY2xhc3NuYW1l",
"GAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmlsZXMYCiABKAg6BWZhbHNlEikK",
"HWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9oYXNoGBQgASgIQgIYARIlChZq",
"YXZhX3N0cmluZ19jaGVja191dGY4GBsgASgIOgVmYWxzZRJGCgxvcHRpbWl6",
"ZV9mb3IYCSABKA4yKS5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMuT3B0",
"aW1pemVNb2RlOgVTUEVFRBISCgpnb19wYWNrYWdlGAsgASgJEiIKE2NjX2dl",
"bmVyaWNfc2VydmljZXMYECABKAg6BWZhbHNlEiQKFWphdmFfZ2VuZXJpY19z",
"ZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoTcHlfZ2VuZXJpY19zZXJ2aWNlcxgS",
"IAEoCDoFZmFsc2USIwoUcGhwX2dlbmVyaWNfc2VydmljZXMYKiABKAg6BWZh",
"bHNlEhkKCmRlcHJlY2F0ZWQYFyABKAg6BWZhbHNlEh4KEGNjX2VuYWJsZV9h",
"cmVuYXMYHyABKAg6BHRydWUSGQoRb2JqY19jbGFzc19wcmVmaXgYJCABKAkS",
"GAoQY3NoYXJwX25hbWVzcGFjZRglIAEoCRIUCgxzd2lmdF9wcmVmaXgYJyAB",
"KAkSGAoQcGhwX2NsYXNzX3ByZWZpeBgoIAEoCRIVCg1waHBfbmFtZXNwYWNl",
"GCkgASgJEh4KFnBocF9tZXRhZGF0YV9uYW1lc3BhY2UYLCABKAkSFAoMcnVi",
"eV9wYWNrYWdlGC0gASgJEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo",
"CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w",
"dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf",
"UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECcihAIKDk1lc3NhZ2VPcHRpb25z",
"EiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9u",
"b19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZ",
"CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgS",
"QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
"YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAQQBUoECAUQ",
"BkoECAYQB0oECAgQCUoECAkQCiK+AwoMRmllbGRPcHRpb25zEjoKBWN0eXBl",
"GAEgASgOMiMuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToG",
"U1RSSU5HEg4KBnBhY2tlZBgCIAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29n",
"bGUucHJvdG9idWYuRmllbGRPcHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMK",
"BGxhenkYBSABKAg6BWZhbHNlEh4KD3VudmVyaWZpZWRfbGF6eRgPIAEoCDoF",
"ZmFsc2USGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USEwoEd2VhaxgKIAEo",
"CDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29v",
"Z2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24iLwoFQ1R5cGUSCgoG",
"U1RSSU5HEAASCAoEQ09SRBABEhAKDFNUUklOR19QSUVDRRACIjUKBkpTVHlw",
"ZRINCglKU19OT1JNQUwQABINCglKU19TVFJJTkcQARINCglKU19OVU1CRVIQ",
"AioJCOgHEICAgIACSgQIBBAFIl4KDE9uZW9mT3B0aW9ucxJDChR1bmludGVy",
"cHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRl",
"cnByZXRlZE9wdGlvbioJCOgHEICAgIACIpMBCgtFbnVtT3B0aW9ucxITCgth",
"bGxvd19hbGlhcxgCIAEoCBIZCgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRJD",
"ChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9i",
"dWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACSgQIBRAGIn0KEEVu",
"dW1WYWx1ZU9wdGlvbnMSGQoKZGVwcmVjYXRlZBgBIAEoCDoFZmFsc2USQwoU",
"dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm",
"LlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiJ7Cg5TZXJ2aWNlT3B0",
"aW9ucxIZCgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJDChR1bmludGVycHJl",
"dGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnBy",
"ZXRlZE9wdGlvbioJCOgHEICAgIACIq0CCg1NZXRob2RPcHRpb25zEhkKCmRl",
"cHJlY2F0ZWQYISABKAg6BWZhbHNlEl8KEWlkZW1wb3RlbmN5X2xldmVsGCIg",
"ASgOMi8uZ29vZ2xlLnByb3RvYnVmLk1ldGhvZE9wdGlvbnMuSWRlbXBvdGVu",
"Y3lMZXZlbDoTSURFTVBPVEVOQ1lfVU5LTk9XThJDChR1bmludGVycHJldGVk",
"X29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRl",
"ZE9wdGlvbiJQChBJZGVtcG90ZW5jeUxldmVsEhcKE0lERU1QT1RFTkNZX1VO",
"S05PV04QABITCg9OT19TSURFX0VGRkVDVFMQARIOCgpJREVNUE9URU5UEAIq",
"CQjoBxCAgICAAiKeAgoTVW5pbnRlcnByZXRlZE9wdGlvbhI7CgRuYW1lGAIg",
"AygLMi0uZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24uTmFt",
"ZVBhcnQSGAoQaWRlbnRpZmllcl92YWx1ZRgDIAEoCRIaChJwb3NpdGl2ZV9p",
"bnRfdmFsdWUYBCABKAQSGgoSbmVnYXRpdmVfaW50X3ZhbHVlGAUgASgDEhQK",
"DGRvdWJsZV92YWx1ZRgGIAEoARIUCgxzdHJpbmdfdmFsdWUYByABKAwSFwoP",
"YWdncmVnYXRlX3ZhbHVlGAggASgJGjMKCE5hbWVQYXJ0EhEKCW5hbWVfcGFy",
"dBgBIAIoCRIUCgxpc19leHRlbnNpb24YAiACKAgi1QEKDlNvdXJjZUNvZGVJ",
"bmZvEjoKCGxvY2F0aW9uGAEgAygLMiguZ29vZ2xlLnByb3RvYnVmLlNvdXJj",
"ZUNvZGVJbmZvLkxvY2F0aW9uGoYBCghMb2NhdGlvbhIQCgRwYXRoGAEgAygF",
"QgIQARIQCgRzcGFuGAIgAygFQgIQARIYChBsZWFkaW5nX2NvbW1lbnRzGAMg",
"ASgJEhkKEXRyYWlsaW5nX2NvbW1lbnRzGAQgASgJEiEKGWxlYWRpbmdfZGV0",
"YWNoZWRfY29tbWVudHMYBiADKAkipwEKEUdlbmVyYXRlZENvZGVJbmZvEkEK",
"CmFubm90YXRpb24YASADKAsyLS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVk",
"Q29kZUluZm8uQW5ub3RhdGlvbhpPCgpBbm5vdGF0aW9uEhAKBHBhdGgYASAD",
"KAVCAhABEhMKC3NvdXJjZV9maWxlGAIgASgJEg0KBWJlZ2luGAMgASgFEgsK",
"A2VuZBgEIAEoBUJ+ChNjb20uZ29vZ2xlLnByb3RvYnVmQhBEZXNjcmlwdG9y",
"UHJvdG9zSAFaLWdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2Rl",
"c2NyaXB0b3JwYvgBAaICA0dQQqoCGkdvb2dsZS5Qcm90b2J1Zi5SZWZsZWN0",
"aW9u"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), global::Google.Protobuf.Reflection.FileDescriptorSet.Parser, new[]{ "File" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax", "Edition" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End", "Options" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null, null)}),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ExtensionRangeOptions), global::Google.Protobuf.Reflection.ExtensionRangeOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null, null),
@@ -187,7 +184,7 @@ namespace Google.Protobuf.Reflection {
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), global::Google.Protobuf.Reflection.MethodOptions.Parser, new[]{ "Deprecated", "IdempotencyLevel", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), global::Google.Protobuf.Reflection.UninterpretedOption.Parser, new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser, new[]{ "NamePart_", "IsExtension" }, null, null, null, null)}),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), global::Google.Protobuf.Reflection.SourceCodeInfo.Parser, new[]{ "Location" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location.Parser, new[]{ "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments" }, null, null, null, null)}),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Parser, new[]{ "Annotation" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser, new[]{ "Path", "SourceFile", "Begin", "End", "Semantic" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic) }, null, null)})
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Parser, new[]{ "Annotation" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser, new[]{ "Path", "SourceFile", "Begin", "End" }, null, null, null, null)})
}));
}
#endregion
@@ -425,7 +422,6 @@ namespace Google.Protobuf.Reflection {
options_ = other.options_ != null ? other.options_.Clone() : null;
sourceCodeInfo_ = other.sourceCodeInfo_ != null ? other.sourceCodeInfo_.Clone() : null;
syntax_ = other.syntax_;
edition_ = other.edition_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -620,9 +616,7 @@ namespace Google.Protobuf.Reflection {
private string syntax_;
/// <summary>
/// The syntax of the proto file.
/// The supported values are "proto2", "proto3", and "editions".
///
/// If `edition` is present, this value must be "editions".
/// The supported values are "proto2" and "proto3".
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -645,35 +639,6 @@ namespace Google.Protobuf.Reflection {
syntax_ = null;
}
/// <summary>Field number for the "edition" field.</summary>
public const int EditionFieldNumber = 13;
private readonly static string EditionDefaultValue = "";
private string edition_;
/// <summary>
/// The edition of the proto file, which is an opaque string.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Edition {
get { return edition_ ?? EditionDefaultValue; }
set {
edition_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Gets whether the "edition" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool HasEdition {
get { return edition_ != null; }
}
/// <summary>Clears the value of the "edition" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void ClearEdition() {
edition_ = null;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
@@ -701,7 +666,6 @@ namespace Google.Protobuf.Reflection {
if (!object.Equals(Options, other.Options)) return false;
if (!object.Equals(SourceCodeInfo, other.SourceCodeInfo)) return false;
if (Syntax != other.Syntax) return false;
if (Edition != other.Edition) return false;
return Equals(_unknownFields, other._unknownFields);
}
@@ -721,7 +685,6 @@ namespace Google.Protobuf.Reflection {
if (options_ != null) hash ^= Options.GetHashCode();
if (sourceCodeInfo_ != null) hash ^= SourceCodeInfo.GetHashCode();
if (HasSyntax) hash ^= Syntax.GetHashCode();
if (HasEdition) hash ^= Edition.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@@ -767,10 +730,6 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(98);
output.WriteString(Syntax);
}
if (HasEdition) {
output.WriteRawTag(106);
output.WriteString(Edition);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@@ -808,10 +767,6 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(98);
output.WriteString(Syntax);
}
if (HasEdition) {
output.WriteRawTag(106);
output.WriteString(Edition);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
@@ -844,9 +799,6 @@ namespace Google.Protobuf.Reflection {
if (HasSyntax) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Syntax);
}
if (HasEdition) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Edition);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
@@ -887,9 +839,6 @@ namespace Google.Protobuf.Reflection {
if (other.HasSyntax) {
Syntax = other.Syntax;
}
if (other.HasEdition) {
Edition = other.Edition;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@@ -961,10 +910,6 @@ namespace Google.Protobuf.Reflection {
Syntax = input.ReadString();
break;
}
case 106: {
Edition = input.ReadString();
break;
}
}
}
#endif
@@ -1036,10 +981,6 @@ namespace Google.Protobuf.Reflection {
Syntax = input.ReadString();
break;
}
case 106: {
Edition = input.ReadString();
break;
}
}
}
}
@@ -6641,10 +6582,6 @@ namespace Google.Protobuf.Reflection {
private bool mapEntry_;
/// <summary>
/// NOTE: Do not set the option in .proto files. Always use the maps syntax
/// instead. The option should only be implicitly set by the proto compiler
/// parser.
///
/// Whether the message is an automatically generated map entry type for the
/// maps field.
///
@@ -6662,6 +6599,10 @@ namespace Google.Protobuf.Reflection {
/// use a native map in the target language to hold the keys and values.
/// The reflection APIs in such implementations still need to work as
/// if the field is a repeated message field.
///
/// NOTE: Do not set the option in .proto files. Always use the maps syntax
/// instead. The option should only be implicitly set by the proto compiler
/// parser.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -7157,8 +7098,11 @@ namespace Google.Protobuf.Reflection {
/// check its required fields, regardless of whether or not the message has
/// been parsed.
///
/// As of May 2022, lazy verifies the contents of the byte stream during
/// parsing. An invalid byte stream will cause the overall parsing to fail.
/// As of 2021, lazy does no correctness checks on the byte stream during
/// parsing. This may lead to crashes if and when an invalid byte stream is
/// finally parsed upon access.
///
/// TODO(b/211906113): Enable validation on lazy fields.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -10814,7 +10758,6 @@ namespace Google.Protobuf.Reflection {
sourceFile_ = other.sourceFile_;
begin_ = other.begin_;
end_ = other.end_;
semantic_ = other.semantic_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -10906,7 +10849,7 @@ namespace Google.Protobuf.Reflection {
private int end_;
/// <summary>
/// Identifies the ending offset in bytes in the generated code that
/// relates to the identified object. The end offset should be one past
/// relates to the identified offset. The end offset should be one past
/// the last relevant byte (so the length of the text = end - begin).
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -10931,33 +10874,6 @@ namespace Google.Protobuf.Reflection {
_hasBits0 &= ~2;
}
/// <summary>Field number for the "semantic" field.</summary>
public const int SemanticFieldNumber = 5;
private readonly static global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic SemanticDefaultValue = global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic.None;
private global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic semantic_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic Semantic {
get { if ((_hasBits0 & 4) != 0) { return semantic_; } else { return SemanticDefaultValue; } }
set {
_hasBits0 |= 4;
semantic_ = value;
}
}
/// <summary>Gets whether the "semantic" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool HasSemantic {
get { return (_hasBits0 & 4) != 0; }
}
/// <summary>Clears the value of the "semantic" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void ClearSemantic() {
_hasBits0 &= ~4;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
@@ -10977,7 +10893,6 @@ namespace Google.Protobuf.Reflection {
if (SourceFile != other.SourceFile) return false;
if (Begin != other.Begin) return false;
if (End != other.End) return false;
if (Semantic != other.Semantic) return false;
return Equals(_unknownFields, other._unknownFields);
}
@@ -10989,7 +10904,6 @@ namespace Google.Protobuf.Reflection {
if (HasSourceFile) hash ^= SourceFile.GetHashCode();
if (HasBegin) hash ^= Begin.GetHashCode();
if (HasEnd) hash ^= End.GetHashCode();
if (HasSemantic) hash ^= Semantic.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@@ -11021,10 +10935,6 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(32);
output.WriteInt32(End);
}
if (HasSemantic) {
output.WriteRawTag(40);
output.WriteEnum((int) Semantic);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@@ -11048,10 +10958,6 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(32);
output.WriteInt32(End);
}
if (HasSemantic) {
output.WriteRawTag(40);
output.WriteEnum((int) Semantic);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
@@ -11072,9 +10978,6 @@ namespace Google.Protobuf.Reflection {
if (HasEnd) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
}
if (HasSemantic) {
size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Semantic);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
@@ -11097,9 +11000,6 @@ namespace Google.Protobuf.Reflection {
if (other.HasEnd) {
End = other.End;
}
if (other.HasSemantic) {
Semantic = other.Semantic;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@@ -11132,10 +11032,6 @@ namespace Google.Protobuf.Reflection {
End = input.ReadInt32();
break;
}
case 40: {
Semantic = (global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic) input.ReadEnum();
break;
}
}
}
#endif
@@ -11168,42 +11064,11 @@ namespace Google.Protobuf.Reflection {
End = input.ReadInt32();
break;
}
case 40: {
Semantic = (global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic) input.ReadEnum();
break;
}
}
}
}
#endif
#region Nested types
/// <summary>Container for nested types declared in the Annotation message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static partial class Types {
/// <summary>
/// Represents the identified object's effect on the element in the original
/// .proto file.
/// </summary>
public enum Semantic {
/// <summary>
/// There is no effect or the effect is indescribable.
/// </summary>
[pbr::OriginalName("NONE")] None = 0,
/// <summary>
/// The element is set or otherwise mutated.
/// </summary>
[pbr::OriginalName("SET")] Set = 1,
/// <summary>
/// An alias to the element is returned.
/// </summary>
[pbr::OriginalName("ALIAS")] Alias = 2,
}
}
#endregion
}
}

View File

@@ -30,9 +30,11 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
namespace Google.Protobuf.Reflection

View File

@@ -51,11 +51,12 @@ namespace Google.Protobuf.Reflection
private readonly IDictionary<ObjectIntPair<IDescriptor>, EnumValueDescriptor> enumValuesByNumber =
new Dictionary<ObjectIntPair<IDescriptor>, EnumValueDescriptor>();
private readonly HashSet<FileDescriptor> dependencies = new HashSet<FileDescriptor>();
private readonly HashSet<FileDescriptor> dependencies;
internal DescriptorPool(IEnumerable<FileDescriptor> dependencyFiles)
{
foreach (FileDescriptor dependencyFile in dependencyFiles)
dependencies = new HashSet<FileDescriptor>();
foreach (var dependencyFile in dependencyFiles)
{
dependencies.Add(dependencyFile);
ImportPublicDependencies(dependencyFile);
@@ -87,8 +88,10 @@ namespace Google.Protobuf.Reflection
/// or null if the symbol doesn't exist or has the wrong type</returns>
internal T FindSymbol<T>(string fullName) where T : class
{
descriptorsByName.TryGetValue(fullName, out IDescriptor result);
if (result is T descriptor)
IDescriptor result;
descriptorsByName.TryGetValue(fullName, out result);
T descriptor = result as T;
if (descriptor != null)
{
return descriptor;
}
@@ -128,9 +131,10 @@ namespace Google.Protobuf.Reflection
name = fullName;
}
if (descriptorsByName.TryGetValue(fullName, out IDescriptor old))
IDescriptor old;
if (descriptorsByName.TryGetValue(fullName, out old))
{
if (old is not PackageDescriptor)
if (!(old is PackageDescriptor))
{
throw new DescriptorValidationException(file,
"\"" + name +
@@ -149,9 +153,10 @@ namespace Google.Protobuf.Reflection
internal void AddSymbol(IDescriptor descriptor)
{
ValidateSymbolName(descriptor);
string fullName = descriptor.FullName;
String fullName = descriptor.FullName;
if (descriptorsByName.TryGetValue(fullName, out IDescriptor old))
IDescriptor old;
if (descriptorsByName.TryGetValue(fullName, out old))
{
int dotPos = fullName.LastIndexOf('.');
string message;
@@ -176,7 +181,8 @@ namespace Google.Protobuf.Reflection
descriptorsByName[fullName] = descriptor;
}
private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$", FrameworkPortability.CompiledRegexWhereAvailable);
private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$",
FrameworkPortability.CompiledRegexWhereAvailable);
/// <summary>
/// Verifies that the descriptor's name is valid (i.e. it contains
@@ -185,7 +191,7 @@ namespace Google.Protobuf.Reflection
/// <param name="descriptor"></param>
private static void ValidateSymbolName(IDescriptor descriptor)
{
if (descriptor.Name.Length == 0)
if (descriptor.Name == "")
{
throw new DescriptorValidationException(descriptor, "Missing name.");
}
@@ -202,13 +208,15 @@ namespace Google.Protobuf.Reflection
/// </summary>
internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number)
{
fieldsByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(messageDescriptor, number), out FieldDescriptor ret);
FieldDescriptor ret;
fieldsByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(messageDescriptor, number), out ret);
return ret;
}
internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number)
{
enumValuesByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(enumDescriptor, number), out EnumValueDescriptor ret);
EnumValueDescriptor ret;
enumValuesByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(enumDescriptor, number), out ret);
return ret;
}
@@ -221,7 +229,8 @@ namespace Google.Protobuf.Reflection
{
// for extensions, we use the extended type, otherwise we use the containing type
ObjectIntPair<IDescriptor> key = new ObjectIntPair<IDescriptor>(field.Proto.HasExtendee ? field.ExtendeeType : field.ContainingType, field.FieldNumber);
if (fieldsByNumber.TryGetValue(key, out FieldDescriptor old))
FieldDescriptor old;
if (fieldsByNumber.TryGetValue(key, out old))
{
throw new DescriptorValidationException(field, "Field number " + field.FieldNumber +
"has already been used in \"" +

View File

@@ -40,16 +40,25 @@ namespace Google.Protobuf.Reflection
/// </summary>
public sealed class DescriptorValidationException : Exception
{
private readonly String name;
private readonly string description;
/// <value>
/// The full name of the descriptor where the error occurred.
/// </value>
public string ProblemSymbolName { get; }
public String ProblemSymbolName
{
get { return name; }
}
/// <value>
/// A human-readable description of the error. (The Message property
/// is made up of the descriptor's name and this description.)
/// </value>
public string Description { get; }
public string Description
{
get { return description; }
}
internal DescriptorValidationException(IDescriptor problemDescriptor, string description) :
base(problemDescriptor.FullName + ": " + description)
@@ -57,15 +66,15 @@ namespace Google.Protobuf.Reflection
// Note that problemDescriptor may be partially uninitialized, so we
// don't want to expose it directly to the user. So, we only provide
// the name and the original proto.
ProblemSymbolName = problemDescriptor.FullName;
Description = description;
name = problemDescriptor.FullName;
this.description = description;
}
internal DescriptorValidationException(IDescriptor problemDescriptor, string description, Exception cause) :
base(problemDescriptor.FullName + ": " + description, cause)
{
ProblemSymbolName = problemDescriptor.FullName;
Description = description;
name = problemDescriptor.FullName;
this.description = description;
}
}
}

View File

@@ -41,12 +41,17 @@ namespace Google.Protobuf.Reflection
/// </summary>
public sealed class EnumDescriptor : DescriptorBase
{
private readonly EnumDescriptorProto proto;
private readonly MessageDescriptor containingType;
private readonly IList<EnumValueDescriptor> values;
private readonly Type clrType;
internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, Type clrType)
: base(file, file.ComputeFullName(parent, proto.Name), index)
{
Proto = proto;
ClrType = clrType;
ContainingType = parent;
this.proto = proto;
this.clrType = clrType;
containingType = parent;
if (proto.Value.Count == 0)
{
@@ -55,13 +60,13 @@ namespace Google.Protobuf.Reflection
throw new DescriptorValidationException(this, "Enums must contain at least one value.");
}
Values = DescriptorUtil.ConvertAndMakeReadOnly(proto.Value,
values = DescriptorUtil.ConvertAndMakeReadOnly(proto.Value,
(value, i) => new EnumValueDescriptor(value, file, this, i));
File.DescriptorPool.AddSymbol(this);
}
internal EnumDescriptorProto Proto { get; }
internal EnumDescriptorProto Proto { get { return proto; } }
/// <summary>
/// Returns a clone of the underlying <see cref="EnumDescriptorProto"/> describing this enum.
@@ -74,29 +79,39 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The brief name of the descriptor's target.
/// </summary>
public override string Name => Proto.Name;
public override string Name { get { return proto.Name; } }
internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) =>
fieldNumber switch
internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
{
switch (fieldNumber)
{
EnumDescriptorProto.ValueFieldNumber => (IReadOnlyList<DescriptorBase>)Values,
_ => null,
};
case EnumDescriptorProto.ValueFieldNumber:
return (IReadOnlyList<DescriptorBase>) Values;
default:
return null;
}
}
/// <summary>
/// The CLR type for this enum. For generated code, this will be a CLR enum type.
/// </summary>
public Type ClrType { get; }
public Type ClrType { get { return clrType; } }
/// <value>
/// If this is a nested type, get the outer descriptor, otherwise null.
/// </value>
public MessageDescriptor ContainingType { get; }
public MessageDescriptor ContainingType
{
get { return containingType; }
}
/// <value>
/// An unmodifiable list of defined value descriptors for this enum.
/// </value>
public IList<EnumValueDescriptor> Values { get; }
public IList<EnumValueDescriptor> Values
{
get { return values; }
}
/// <summary>
/// Finds an enum value by number. If multiple enum values have the

View File

@@ -40,17 +40,20 @@ namespace Google.Protobuf.Reflection
/// </summary>
public sealed class EnumValueDescriptor : DescriptorBase
{
private readonly EnumDescriptor enumDescriptor;
private readonly EnumValueDescriptorProto proto;
internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file,
EnumDescriptor parent, int index)
: base(file, parent.FullName + "." + proto.Name, index)
{
Proto = proto;
EnumDescriptor = parent;
this.proto = proto;
enumDescriptor = parent;
file.DescriptorPool.AddSymbol(this);
file.DescriptorPool.AddEnumValueByNumber(this);
}
internal EnumValueDescriptorProto Proto { get; }
internal EnumValueDescriptorProto Proto { get { return proto; } }
/// <summary>
/// Returns a clone of the underlying <see cref="EnumValueDescriptorProto"/> describing this enum value.
@@ -63,17 +66,17 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Returns the name of the enum value described by this object.
/// </summary>
public override string Name => Proto.Name;
public override string Name { get { return proto.Name; } }
/// <summary>
/// Returns the number associated with this enum value.
/// </summary>
public int Number => Proto.Number;
public int Number { get { return Proto.Number; } }
/// <summary>
/// Returns the enum descriptor that this value is part of.
/// </summary>
public EnumDescriptor EnumDescriptor { get; }
public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } }
/// <summary>
/// The (possibly empty) set of custom options for this enum value.

View File

@@ -107,7 +107,8 @@ namespace Google.Protobuf.Reflection
{
descriptor.CrossLink();
if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out IList<FieldDescriptor> list))
IList<FieldDescriptor> list;
if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out list))
{
list = new List<FieldDescriptor>();
declarationOrder.Add(descriptor.ExtendeeType, list);

View File

@@ -42,14 +42,15 @@ namespace Google.Protobuf.Reflection
internal abstract class FieldAccessorBase : IFieldAccessor
{
private readonly Func<IMessage, object> getValueDelegate;
private readonly FieldDescriptor descriptor;
internal FieldAccessorBase(PropertyInfo property, FieldDescriptor descriptor)
{
Descriptor = descriptor;
this.descriptor = descriptor;
getValueDelegate = ReflectionUtil.CreateFuncIMessageObject(property.GetGetMethod());
}
public FieldDescriptor Descriptor { get; }
public FieldDescriptor Descriptor { get { return descriptor; } }
public object GetValue(IMessage message)
{

View File

@@ -176,28 +176,47 @@ namespace Google.Protobuf.Reflection
/// </summary>
private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type)
{
return type switch
switch (type)
{
FieldDescriptorProto.Types.Type.Double => FieldType.Double,
FieldDescriptorProto.Types.Type.Float => FieldType.Float,
FieldDescriptorProto.Types.Type.Int64 => FieldType.Int64,
FieldDescriptorProto.Types.Type.Uint64 => FieldType.UInt64,
FieldDescriptorProto.Types.Type.Int32 => FieldType.Int32,
FieldDescriptorProto.Types.Type.Fixed64 => FieldType.Fixed64,
FieldDescriptorProto.Types.Type.Fixed32 => FieldType.Fixed32,
FieldDescriptorProto.Types.Type.Bool => FieldType.Bool,
FieldDescriptorProto.Types.Type.String => FieldType.String,
FieldDescriptorProto.Types.Type.Group => FieldType.Group,
FieldDescriptorProto.Types.Type.Message => FieldType.Message,
FieldDescriptorProto.Types.Type.Bytes => FieldType.Bytes,
FieldDescriptorProto.Types.Type.Uint32 => FieldType.UInt32,
FieldDescriptorProto.Types.Type.Enum => FieldType.Enum,
FieldDescriptorProto.Types.Type.Sfixed32 => FieldType.SFixed32,
FieldDescriptorProto.Types.Type.Sfixed64 => FieldType.SFixed64,
FieldDescriptorProto.Types.Type.Sint32 => FieldType.SInt32,
FieldDescriptorProto.Types.Type.Sint64 => FieldType.SInt64,
_ => throw new ArgumentException("Invalid type specified"),
};
case FieldDescriptorProto.Types.Type.Double:
return FieldType.Double;
case FieldDescriptorProto.Types.Type.Float:
return FieldType.Float;
case FieldDescriptorProto.Types.Type.Int64:
return FieldType.Int64;
case FieldDescriptorProto.Types.Type.Uint64:
return FieldType.UInt64;
case FieldDescriptorProto.Types.Type.Int32:
return FieldType.Int32;
case FieldDescriptorProto.Types.Type.Fixed64:
return FieldType.Fixed64;
case FieldDescriptorProto.Types.Type.Fixed32:
return FieldType.Fixed32;
case FieldDescriptorProto.Types.Type.Bool:
return FieldType.Bool;
case FieldDescriptorProto.Types.Type.String:
return FieldType.String;
case FieldDescriptorProto.Types.Type.Group:
return FieldType.Group;
case FieldDescriptorProto.Types.Type.Message:
return FieldType.Message;
case FieldDescriptorProto.Types.Type.Bytes:
return FieldType.Bytes;
case FieldDescriptorProto.Types.Type.Uint32:
return FieldType.UInt32;
case FieldDescriptorProto.Types.Type.Enum:
return FieldType.Enum;
case FieldDescriptorProto.Types.Type.Sfixed32:
return FieldType.SFixed32;
case FieldDescriptorProto.Types.Type.Sfixed64:
return FieldType.SFixed64;
case FieldDescriptorProto.Types.Type.Sint32:
return FieldType.SInt32;
case FieldDescriptorProto.Types.Type.Sint64:
return FieldType.SInt64;
default:
throw new ArgumentException("Invalid type specified");
}
}
/// <summary>
@@ -372,11 +391,11 @@ namespace Google.Protobuf.Reflection
if (fieldType == FieldType.Message || fieldType == FieldType.Group)
{
if (typeDescriptor is not MessageDescriptor m)
if (!(typeDescriptor is MessageDescriptor))
{
throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a message type.");
}
messageType = m;
messageType = (MessageDescriptor) typeDescriptor;
if (Proto.HasDefaultValue)
{
@@ -385,11 +404,11 @@ namespace Google.Protobuf.Reflection
}
else if (fieldType == FieldType.Enum)
{
if (typeDescriptor is not EnumDescriptor e)
if (!(typeDescriptor is EnumDescriptor))
{
throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not an enum type.");
}
enumType = e;
enumType = (EnumDescriptor) typeDescriptor;
}
else
{

View File

@@ -35,6 +35,7 @@ using Google.Protobuf.WellKnownTypes;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
@@ -172,18 +173,25 @@ namespace Google.Protobuf.Reflection
return list[index];
}
private IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) =>
fieldNumber switch
private IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
{
switch (fieldNumber)
{
FileDescriptorProto.ServiceFieldNumber => (IReadOnlyList<DescriptorBase>)Services,
FileDescriptorProto.MessageTypeFieldNumber => (IReadOnlyList<DescriptorBase>)MessageTypes,
FileDescriptorProto.EnumTypeFieldNumber => (IReadOnlyList<DescriptorBase>)EnumTypes,
_ => null,
};
case FileDescriptorProto.ServiceFieldNumber:
return (IReadOnlyList<DescriptorBase>) Services;
case FileDescriptorProto.MessageTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) MessageTypes;
case FileDescriptorProto.EnumTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) EnumTypes;
default:
return null;
}
}
internal DescriptorDeclaration GetDeclaration(IDescriptor descriptor)
{
declarations.Value.TryGetValue(descriptor, out DescriptorDeclaration declaration);
DescriptorDeclaration declaration;
declarations.Value.TryGetValue(descriptor, out declaration);
return declaration;
}
@@ -219,7 +227,8 @@ namespace Google.Protobuf.Reflection
throw new DescriptorValidationException(@this, "Invalid public dependency index.");
}
string name = proto.Dependency[index];
if (!nameToFileMap.TryGetValue(name, out FileDescriptor file))
FileDescriptor file;
if (!nameToFileMap.TryGetValue(name, out file))
{
if (!allowUnknownDependencies)
{
@@ -323,7 +332,7 @@ namespace Google.Protobuf.Reflection
/// <param name="name">The unqualified type name to look for.</param>
/// <typeparam name="T">The type of descriptor to look for</typeparam>
/// <returns>The type's descriptor, or null if not found.</returns>
public T FindTypeByName<T>(string name)
public T FindTypeByName<T>(String name)
where T : class, IDescriptor
{
// Don't allow looking up nested types. This will make optimization
@@ -498,7 +507,8 @@ namespace Google.Protobuf.Reflection
var dependencies = new List<FileDescriptor>();
foreach (var dependencyName in proto.Dependency)
{
if (!descriptorsByName.TryGetValue(dependencyName, out FileDescriptor dependency))
FileDescriptor dependency;
if (!descriptorsByName.TryGetValue(dependencyName, out dependency))
{
throw new ArgumentException($"Dependency missing: {dependencyName}");
}
@@ -555,7 +565,7 @@ namespace Google.Protobuf.Reflection
/// <value>
/// The file descriptor for <c>descriptor.proto</c>.
/// </value>
public static FileDescriptor DescriptorProtoFileDescriptor => DescriptorReflection.Descriptor;
public static FileDescriptor DescriptorProtoFileDescriptor { get { return DescriptorReflection.Descriptor; } }
/// <summary>
/// The (possibly empty) set of custom options for this file.

View File

@@ -29,7 +29,6 @@
// (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;
using System.Diagnostics.CodeAnalysis;
@@ -58,7 +57,7 @@ namespace Google.Protobuf.Reflection
/// Irrelevant for file descriptors; the CLR type for the message for message descriptors.
/// </summary>
[DynamicallyAccessedMembers(MessageAccessibility)]
public Type ClrType { get; }
public Type ClrType { get; private set; }
/// <summary>
/// Irrelevant for file descriptors; the parser for message descriptors.

View File

@@ -36,6 +36,10 @@ using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
#if NET35
// Needed for ReadOnlyDictionary, which does not exist in .NET 3.5
using Google.Protobuf.Collections;
#endif
namespace Google.Protobuf.Reflection
{
@@ -130,14 +134,20 @@ namespace Google.Protobuf.Reflection
/// </summary>
public override string Name => Proto.Name;
internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) =>
fieldNumber switch
internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
{
switch (fieldNumber)
{
DescriptorProto.FieldFieldNumber => (IReadOnlyList<DescriptorBase>)fieldsInDeclarationOrder,
DescriptorProto.NestedTypeFieldNumber => (IReadOnlyList<DescriptorBase>)NestedTypes,
DescriptorProto.EnumTypeFieldNumber => (IReadOnlyList<DescriptorBase>)EnumTypes,
_ => null,
};
case DescriptorProto.FieldFieldNumber:
return (IReadOnlyList<DescriptorBase>) fieldsInDeclarationOrder;
case DescriptorProto.NestedTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) NestedTypes;
case DescriptorProto.EnumTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) EnumTypes;
default:
return null;
}
}
internal DescriptorProto Proto { get; }
@@ -266,7 +276,7 @@ namespace Google.Protobuf.Reflection
/// </summary>
/// <param name="name">The unqualified name of the field (e.g. "foo").</param>
/// <returns>The field's descriptor, or null if not found.</returns>
public FieldDescriptor FindFieldByName(string name) => File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name);
public FieldDescriptor FindFieldByName(String name) => File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name);
/// <summary>
/// Finds a field by field number.

View File

@@ -40,31 +40,35 @@ namespace Google.Protobuf.Reflection
/// </summary>
public sealed class MethodDescriptor : DescriptorBase
{
private readonly MethodDescriptorProto proto;
private readonly ServiceDescriptor service;
private MessageDescriptor inputType;
private MessageDescriptor outputType;
/// <value>
/// The service this method belongs to.
/// </value>
public ServiceDescriptor Service { get; }
public ServiceDescriptor Service { get { return service; } }
/// <value>
/// The method's input type.
/// </value>
public MessageDescriptor InputType { get; private set; }
public MessageDescriptor InputType { get { return inputType; } }
/// <value>
/// The method's input type.
/// </value>
public MessageDescriptor OutputType { get; private set; }
public MessageDescriptor OutputType { get { return outputType; } }
/// <value>
/// Indicates if client streams multiple requests.
/// </value>
public bool IsClientStreaming => Proto.ClientStreaming;
public bool IsClientStreaming { get { return proto.ClientStreaming; } }
/// <value>
/// Indicates if server streams multiple responses.
/// </value>
public bool IsServerStreaming => Proto.ServerStreaming;
public bool IsServerStreaming { get { return proto.ServerStreaming; } }
/// <summary>
/// The (possibly empty) set of custom options for this method.
@@ -87,7 +91,7 @@ namespace Google.Protobuf.Reflection
public T GetOption<T>(Extension<MethodOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> c ? c.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@@ -103,12 +107,12 @@ namespace Google.Protobuf.Reflection
ServiceDescriptor parent, int index)
: base(file, parent.FullName + "." + proto.Name, index)
{
Proto = proto;
Service = parent;
this.proto = proto;
service = parent;
file.DescriptorPool.AddSymbol(this);
}
internal MethodDescriptorProto Proto { get; private set; }
internal MethodDescriptorProto Proto { get { return proto; } }
/// <summary>
/// Returns a clone of the underlying <see cref="MethodDescriptorProto"/> describing this method.
@@ -121,23 +125,23 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The brief name of the descriptor's target.
/// </summary>
public override string Name => Proto.Name;
public override string Name { get { return proto.Name; } }
internal void CrossLink()
{
IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this);
if (lookup is not MessageDescriptor inpoutType)
if (!(lookup is MessageDescriptor))
{
throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type.");
}
InputType = inpoutType;
inputType = (MessageDescriptor) lookup;
lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this);
if (lookup is not MessageDescriptor outputType)
if (!(lookup is MessageDescriptor))
{
throw new DescriptorValidationException(this, "\"" + Proto.OutputType + "\" is not a message type.");
}
OutputType = outputType;
outputType = (MessageDescriptor) lookup;
}
}
}

View File

@@ -60,5 +60,6 @@ namespace Google.Protobuf.Reflection
Name = ProtoPreconditions.CheckNotNull(name, nameof(name));
PreferredAlias = true;
}
}
}

View File

@@ -39,15 +39,30 @@ namespace Google.Protobuf.Reflection
/// </summary>
internal sealed class PackageDescriptor : IDescriptor
{
private readonly string name;
private readonly string fullName;
private readonly FileDescriptor file;
internal PackageDescriptor(string name, string fullName, FileDescriptor file)
{
File = file;
FullName = fullName;
Name = name;
this.file = file;
this.fullName = fullName;
this.name = name;
}
public string Name { get; }
public string FullName { get; }
public FileDescriptor File { get; }
public string Name
{
get { return name; }
}
public string FullName
{
get { return fullName; }
}
public FileDescriptor File
{
get { return file; }
}
}
}

View File

@@ -221,18 +221,20 @@ namespace Google.Protobuf.Reflection
public object GetExtension(IMessage message)
{
if (message is not T1 extensionMessage)
if (!(message is T1))
{
throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage");
}
if (extension is Extension<T1, T3> ext13)
T1 extensionMessage = (T1)message;
if (extension is Extension<T1, T3>)
{
return extensionMessage.GetExtension(ext13);
return extensionMessage.GetExtension(extension as Extension<T1, T3>);
}
else if (extension is RepeatedExtension<T1, T3> repeatedExt13)
else if (extension is RepeatedExtension<T1, T3>)
{
return extensionMessage.GetOrInitializeExtension(repeatedExt13);
return extensionMessage.GetOrInitializeExtension(extension as RepeatedExtension<T1, T3>);
}
else
{
@@ -242,14 +244,16 @@ namespace Google.Protobuf.Reflection
public bool HasExtension(IMessage message)
{
if (message is not T1 extensionMessage)
if (!(message is T1))
{
throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage");
}
if (extension is Extension<T1, T3> ext13)
T1 extensionMessage = (T1)message;
if (extension is Extension<T1, T3>)
{
return extensionMessage.HasExtension(ext13);
return extensionMessage.HasExtension(extension as Extension<T1, T3>);
}
else if (extension is RepeatedExtension<T1, T3>)
{
@@ -263,14 +267,16 @@ namespace Google.Protobuf.Reflection
public void SetExtension(IMessage message, object value)
{
if (message is not T1 extensionMessage)
if (!(message is T1))
{
throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage");
}
if (extension is Extension<T1, T3> ext13)
T1 extensionMessage = (T1)message;
if (extension is Extension<T1, T3>)
{
extensionMessage.SetExtension(ext13, (T3)value);
extensionMessage.SetExtension(extension as Extension<T1, T3>, (T3)value);
}
else if (extension is RepeatedExtension<T1, T3>)
{
@@ -284,18 +290,20 @@ namespace Google.Protobuf.Reflection
public void ClearExtension(IMessage message)
{
if (message is not T1 extensionMessage)
if (!(message is T1))
{
throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage");
}
if (extension is Extension<T1, T3> ext13)
T1 extensionMessage = (T1)message;
if (extension is Extension<T1, T3>)
{
extensionMessage.ClearExtension(ext13);
extensionMessage.ClearExtension(extension as Extension<T1, T3>);
}
else if (extension is RepeatedExtension<T1, T3> repeatedExt13)
else if (extension is RepeatedExtension<T1, T3>)
{
extensionMessage.GetExtension(repeatedExt13).Clear();
extensionMessage.GetExtension(extension as RepeatedExtension<T1, T3>).Clear();
}
else
{

View File

@@ -60,5 +60,6 @@ namespace Google.Protobuf.Reflection
{
throw new InvalidOperationException("SetValue is not implemented for repeated fields");
}
}
}

View File

@@ -33,6 +33,7 @@
using Google.Protobuf.Collections;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Google.Protobuf.Reflection
{
@@ -41,11 +42,14 @@ namespace Google.Protobuf.Reflection
/// </summary>
public sealed class ServiceDescriptor : DescriptorBase
{
private readonly ServiceDescriptorProto proto;
private readonly IList<MethodDescriptor> methods;
internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)
: base(file, file.ComputeFullName(null, proto.Name), index)
{
Proto = proto;
Methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method,
this.proto = proto;
methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method,
(method, i) => new MethodDescriptor(method, file, this, i));
file.DescriptorPool.AddSymbol(this);
@@ -54,16 +58,20 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The brief name of the descriptor's target.
/// </summary>
public override string Name => Proto.Name;
public override string Name { get { return proto.Name; } }
internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) =>
fieldNumber switch
internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
{
switch (fieldNumber)
{
ServiceDescriptorProto.MethodFieldNumber => (IReadOnlyList<DescriptorBase>)Methods,
_ => null,
};
case ServiceDescriptorProto.MethodFieldNumber:
return (IReadOnlyList<DescriptorBase>) methods;
default:
return null;
}
}
internal ServiceDescriptorProto Proto { get; }
internal ServiceDescriptorProto Proto { get { return proto; } }
/// <summary>
/// Returns a clone of the underlying <see cref="ServiceDescriptorProto"/> describing this service.
@@ -76,15 +84,20 @@ namespace Google.Protobuf.Reflection
/// <value>
/// An unmodifiable list of methods in this service.
/// </value>
public IList<MethodDescriptor> Methods { get; }
public IList<MethodDescriptor> Methods
{
get { return methods; }
}
/// <summary>
/// Finds a method by name.
/// </summary>
/// <param name="name">The unqualified name of the method (e.g. "Foo").</param>
/// <returns>The method's descriptor, or null if not found.</returns>
public MethodDescriptor FindMethodByName(string name) =>
File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name);
public MethodDescriptor FindMethodByName(String name)
{
return File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name);
}
/// <summary>
/// The (possibly empty) set of custom options for this service.
@@ -121,7 +134,7 @@ namespace Google.Protobuf.Reflection
internal void CrossLink()
{
foreach (MethodDescriptor method in Methods)
foreach (MethodDescriptor method in methods)
{
method.CrossLink();
}

View File

@@ -31,6 +31,7 @@
#endregion
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Google.Protobuf.Compatibility;
@@ -107,7 +108,7 @@ namespace Google.Protobuf.Reflection
// Primitive proto3 fields without the optional keyword, which aren't in oneofs.
else
{
hasDelegate = message => throw new InvalidOperationException("Presence is not implemented for this field");
hasDelegate = message => { throw new InvalidOperationException("Presence is not implemented for this field"); };
// While presence isn't supported, clearing still is; it's just setting to a default value.
object defaultValue = GetDefaultValue(descriptor);
@@ -115,21 +116,42 @@ namespace Google.Protobuf.Reflection
}
}
private static object GetDefaultValue(FieldDescriptor descriptor) =>
descriptor.FieldType switch
private static object GetDefaultValue(FieldDescriptor descriptor)
{
switch (descriptor.FieldType)
{
FieldType.Bool => false,
FieldType.Bytes => ByteString.Empty,
FieldType.String => "",
FieldType.Double => 0.0,
FieldType.SInt32 or FieldType.Int32 or FieldType.SFixed32 or FieldType.Enum => 0,
FieldType.Fixed32 or FieldType.UInt32 => (uint)0,
FieldType.Fixed64 or FieldType.UInt64 => 0UL,
FieldType.SFixed64 or FieldType.Int64 or FieldType.SInt64 => 0L,
FieldType.Float => 0f,
FieldType.Message or FieldType.Group => null,
_ => throw new ArgumentException("Invalid field type"),
};
case FieldType.Bool:
return false;
case FieldType.Bytes:
return ByteString.Empty;
case FieldType.String:
return "";
case FieldType.Double:
return 0.0;
case FieldType.SInt32:
case FieldType.Int32:
case FieldType.SFixed32:
case FieldType.Enum:
return 0;
case FieldType.Fixed32:
case FieldType.UInt32:
return (uint)0;
case FieldType.Fixed64:
case FieldType.UInt64:
return 0UL;
case FieldType.SFixed64:
case FieldType.Int64:
case FieldType.SInt64:
return 0L;
case FieldType.Float:
return 0f;
case FieldType.Message:
case FieldType.Group: // Never expect to get this, but...
return null;
default:
throw new ArgumentException("Invalid field type");
}
}
public override void Clear(IMessage message) => clearDelegate(message);
public override bool HasValue(IMessage message) => hasDelegate(message);

View File

@@ -29,7 +29,6 @@
// (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.Collections.Generic;
using System.Linq;
@@ -61,8 +60,9 @@ namespace Google.Protobuf.Reflection
/// if there is no such message descriptor.</returns>
public MessageDescriptor Find(string fullName)
{
MessageDescriptor ret;
// Ignore the return value as ret will end up with the right value either way.
fullNameToMessageMap.TryGetValue(fullName, out MessageDescriptor ret);
fullNameToMessageMap.TryGetValue(fullName, out ret);
return ret;
}

View File

@@ -30,7 +30,9 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Google.Protobuf.Collections;
namespace Google.Protobuf
@@ -71,12 +73,13 @@ namespace Google.Protobuf
{
return true;
}
return other is UnknownField otherField
&& Lists.Equals(varintList, otherField.varintList)
&& Lists.Equals(fixed32List, otherField.fixed32List)
&& Lists.Equals(fixed64List, otherField.fixed64List)
&& Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList)
&& Lists.Equals(groupList, otherField.groupList);
UnknownField otherField = other as UnknownField;
return otherField != null
&& Lists.Equals(varintList, otherField.varintList)
&& Lists.Equals(fixed32List, otherField.fixed32List)
&& Lists.Equals(fixed64List, otherField.fixed64List)
&& Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList)
&& Lists.Equals(groupList, otherField.groupList);
}
/// <summary>

View File

@@ -32,7 +32,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Security;
using Google.Protobuf.Reflection;
namespace Google.Protobuf
{
@@ -47,13 +49,14 @@ namespace Google.Protobuf
/// </summary>
public sealed partial class UnknownFieldSet
{
private readonly IDictionary<int, UnknownField> fields = new Dictionary<int, UnknownField>();
private readonly IDictionary<int, UnknownField> fields;
/// <summary>
/// Creates a new UnknownFieldSet.
/// </summary>
internal UnknownFieldSet()
{
this.fields = new Dictionary<int, UnknownField>();
}
/// <summary>
@@ -122,7 +125,8 @@ namespace Google.Protobuf
}
foreach (KeyValuePair<int, UnknownField> leftEntry in fields)
{
if (!otherFields.TryGetValue(leftEntry.Key, out UnknownField rightValue))
UnknownField rightValue;
if (!otherFields.TryGetValue(leftEntry.Key, out rightValue))
{
return false;
}
@@ -166,7 +170,8 @@ namespace Google.Protobuf
return null;
}
if (fields.TryGetValue(number, out UnknownField existing))
UnknownField existing;
if (fields.TryGetValue(number, out existing))
{
return existing;
}

View File

@@ -112,7 +112,7 @@ namespace Google.Protobuf.WellKnownTypes
T target = new T();
if (GetTypeName(TypeUrl) != target.Descriptor.FullName)
{
result = default; // Can't use null as there's no class constraint, but this always *will* be null in real usage.
result = default(T); // Can't use null as there's no class constraint, but this always *will* be null in real usage.
return false;
}
target.MergeFrom(Value);
@@ -120,26 +120,6 @@ namespace Google.Protobuf.WellKnownTypes
return true;
}
/// <summary>
/// Attempts to unpack the content of this Any message into one of the message types
/// in the given type registry, based on the type URL.
/// </summary>
/// <param name="registry">The type registry to consult for messages.</param>
/// <returns>The unpacked message, or <c>null</c> if no matching message was found.</returns>
public IMessage Unpack(TypeRegistry registry)
{
string typeName = GetTypeName(TypeUrl);
MessageDescriptor descriptor = registry.Find(typeName);
if (descriptor == null)
{
return null;
}
var message = descriptor.Parser.CreateTemplate();
message.MergeFrom(Value);
return message;
}
/// <summary>
/// Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com".
/// </summary>

View File

@@ -38,7 +38,7 @@ namespace Google.Protobuf.WellKnownTypes
{
// Manually-written partial class for the Duration well-known type,
// providing a conversion to TimeSpan and convenience operators.
public partial class Duration : ICustomDiagnosticMessage, IComparable<Duration>
public partial class Duration : ICustomDiagnosticMessage
{
/// <summary>
/// The number of nanoseconds in a second.
@@ -266,26 +266,5 @@ namespace Google.Protobuf.WellKnownTypes
}
}
}
/// <summary>
/// Given another duration, returns 0 if the durations are equivalent, -1 if this duration is shorter than the other, and 1 otherwise.
/// </summary>
/// <remarks>
/// This method expects that both durations are normalized; that is, that the values of <see cref="Seconds"/>
/// and <see cref="Nanos"/> are within the documented bounds.
/// If either value is not normalized, the results of this method are unspecified.
/// </remarks>
/// <param name="other">The duration to compare with this object.</param>
/// <returns>An integer indicating whether this duration is shorter or longer than <paramref name="other"/>.</returns>
public int CompareTo(Duration other)
{
return other == null ? 1
: Seconds < other.Seconds ? -1
: Seconds > other.Seconds ? 1
: Nanos < other.Nanos ? -1
: Nanos > other.Nanos ? 1
: 0;
}
}
}

View File

@@ -63,7 +63,12 @@ namespace Google.Protobuf.WellKnownTypes
if (firstInvalid == null)
{
var writer = new StringWriter();
#if NET35
var query = paths.Select(JsonFormatter.ToJsonName);
JsonFormatter.WriteString(writer, string.Join(",", query.ToArray()));
#else
JsonFormatter.WriteString(writer, string.Join(",", paths.Select(JsonFormatter.ToJsonName)));
#endif
return writer.ToString();
}
else

View File

@@ -212,7 +212,7 @@ namespace Google.Protobuf.WellKnownTypes {
if (other == null) {
return;
}
fields_.MergeFrom(other.fields_);
fields_.Add(other.fields_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}

View File

@@ -59,8 +59,8 @@ namespace Google.Protobuf.WellKnownTypes
/// <returns>The difference between the two specified timestamps.</returns>
public static Duration operator -(Timestamp lhs, Timestamp rhs)
{
ProtoPreconditions.CheckNotNull(lhs, nameof(lhs));
ProtoPreconditions.CheckNotNull(rhs, nameof(rhs));
ProtoPreconditions.CheckNotNull(lhs, "lhs");
ProtoPreconditions.CheckNotNull(rhs, "rhs");
checked
{
return Duration.Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos);
@@ -75,8 +75,8 @@ namespace Google.Protobuf.WellKnownTypes
/// <returns>The result of adding the duration to the timestamp.</returns>
public static Timestamp operator +(Timestamp lhs, Duration rhs)
{
ProtoPreconditions.CheckNotNull(lhs, nameof(lhs));
ProtoPreconditions.CheckNotNull(rhs, nameof(rhs));
ProtoPreconditions.CheckNotNull(lhs, "lhs");
ProtoPreconditions.CheckNotNull(rhs, "rhs");
checked
{
return Normalize(lhs.Seconds + rhs.Seconds, lhs.Nanos + rhs.Nanos);
@@ -91,8 +91,8 @@ namespace Google.Protobuf.WellKnownTypes
/// <returns>The result of subtracting the duration from the timestamp.</returns>
public static Timestamp operator -(Timestamp lhs, Duration rhs)
{
ProtoPreconditions.CheckNotNull(lhs, nameof(lhs));
ProtoPreconditions.CheckNotNull(rhs, nameof(rhs));
ProtoPreconditions.CheckNotNull(lhs, "lhs");
ProtoPreconditions.CheckNotNull(rhs, "rhs");
checked
{
return Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos);
@@ -308,7 +308,7 @@ namespace Google.Protobuf.WellKnownTypes
/// <returns>true if the two timestamps refer to the same nanosecond</returns>
public static bool operator ==(Timestamp a, Timestamp b)
{
return ReferenceEquals(a, b) || (a is null ? (b is null) : a.Equals(b));
return ReferenceEquals(a, b) || (ReferenceEquals(a, null) ? (ReferenceEquals(b, null) ? true : false) : a.Equals(b));
}
/// <summary>

View File

@@ -41,7 +41,7 @@ namespace Google.Protobuf.WellKnownTypes
/// <returns>A newly-created Value message with the given value.</returns>
public static Value ForString(string value)
{
ProtoPreconditions.CheckNotNull(value, nameof(value));
ProtoPreconditions.CheckNotNull(value, "value");
return new Value { StringValue = value };
}
@@ -81,7 +81,7 @@ namespace Google.Protobuf.WellKnownTypes
/// <returns>A newly-created Value message an initial list value.</returns>
public static Value ForList(params Value[] values)
{
ProtoPreconditions.CheckNotNull(values, nameof(values));
ProtoPreconditions.CheckNotNull(values, "values");
return new Value { ListValue = new ListValue { Values = { values } } };
}
@@ -92,7 +92,7 @@ namespace Google.Protobuf.WellKnownTypes
/// <returns>A newly-created Value message an initial struct value.</returns>
public static Value ForStruct(Struct value)
{
ProtoPreconditions.CheckNotNull(value, nameof(value));
ProtoPreconditions.CheckNotNull(value, "value");
return new Value { StructValue = value };
}
}

View File

@@ -32,6 +32,7 @@
using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Security;

View File

@@ -32,8 +32,14 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{
@@ -95,112 +101,166 @@ namespace Google.Protobuf
/// Writes a double field value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteDouble(double value) => WritingPrimitives.WriteDouble(ref buffer, ref state, value);
public void WriteDouble(double value)
{
WritingPrimitives.WriteDouble(ref buffer, ref state, value);
}
/// <summary>
/// Writes a float field value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteFloat(float value) => WritingPrimitives.WriteFloat(ref buffer, ref state, value);
public void WriteFloat(float value)
{
WritingPrimitives.WriteFloat(ref buffer, ref state, value);
}
/// <summary>
/// Writes a uint64 field value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteUInt64(ulong value) => WritingPrimitives.WriteUInt64(ref buffer, ref state, value);
public void WriteUInt64(ulong value)
{
WritingPrimitives.WriteUInt64(ref buffer, ref state, value);
}
/// <summary>
/// Writes an int64 field value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteInt64(long value) => WritingPrimitives.WriteInt64(ref buffer, ref state, value);
public void WriteInt64(long value)
{
WritingPrimitives.WriteInt64(ref buffer, ref state, value);
}
/// <summary>
/// Writes an int32 field value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteInt32(int value) => WritingPrimitives.WriteInt32(ref buffer, ref state, value);
public void WriteInt32(int value)
{
WritingPrimitives.WriteInt32(ref buffer, ref state, value);
}
/// <summary>
/// Writes a fixed64 field value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteFixed64(ulong value) => WritingPrimitives.WriteFixed64(ref buffer, ref state, value);
public void WriteFixed64(ulong value)
{
WritingPrimitives.WriteFixed64(ref buffer, ref state, value);
}
/// <summary>
/// Writes a fixed32 field value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteFixed32(uint value) => WritingPrimitives.WriteFixed32(ref buffer, ref state, value);
public void WriteFixed32(uint value)
{
WritingPrimitives.WriteFixed32(ref buffer, ref state, value);
}
/// <summary>
/// Writes a bool field value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteBool(bool value) => WritingPrimitives.WriteBool(ref buffer, ref state, value);
public void WriteBool(bool value)
{
WritingPrimitives.WriteBool(ref buffer, ref state, value);
}
/// <summary>
/// Writes a string field value, without a tag.
/// The data is length-prefixed.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteString(string value) => WritingPrimitives.WriteString(ref buffer, ref state, value);
public void WriteString(string value)
{
WritingPrimitives.WriteString(ref buffer, ref state, value);
}
/// <summary>
/// Writes a message, without a tag.
/// The data is length-prefixed.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteMessage(IMessage value) => WritingPrimitivesMessages.WriteMessage(ref this, value);
public void WriteMessage(IMessage value)
{
WritingPrimitivesMessages.WriteMessage(ref this, value);
}
/// <summary>
/// Writes a group, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteGroup(IMessage value) => WritingPrimitivesMessages.WriteGroup(ref this, value);
public void WriteGroup(IMessage value)
{
WritingPrimitivesMessages.WriteGroup(ref this, value);
}
/// <summary>
/// Write a byte string, without a tag, to the stream.
/// The data is length-prefixed.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteBytes(ByteString value) => WritingPrimitives.WriteBytes(ref buffer, ref state, value);
public void WriteBytes(ByteString value)
{
WritingPrimitives.WriteBytes(ref buffer, ref state, value);
}
/// <summary>
/// Writes a uint32 value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteUInt32(uint value) => WritingPrimitives.WriteUInt32(ref buffer, ref state, value);
public void WriteUInt32(uint value)
{
WritingPrimitives.WriteUInt32(ref buffer, ref state, value);
}
/// <summary>
/// Writes an enum value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteEnum(int value) => WritingPrimitives.WriteEnum(ref buffer, ref state, value);
public void WriteEnum(int value)
{
WritingPrimitives.WriteEnum(ref buffer, ref state, value);
}
/// <summary>
/// Writes an sfixed32 value, without a tag.
/// </summary>
/// <param name="value">The value to write.</param>
public void WriteSFixed32(int value) => WritingPrimitives.WriteSFixed32(ref buffer, ref state, value);
public void WriteSFixed32(int value)
{
WritingPrimitives.WriteSFixed32(ref buffer, ref state, value);
}
/// <summary>
/// Writes an sfixed64 value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteSFixed64(long value) => WritingPrimitives.WriteSFixed64(ref buffer, ref state, value);
public void WriteSFixed64(long value)
{
WritingPrimitives.WriteSFixed64(ref buffer, ref state, value);
}
/// <summary>
/// Writes an sint32 value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteSInt32(int value) => WritingPrimitives.WriteSInt32(ref buffer, ref state, value);
public void WriteSInt32(int value)
{
WritingPrimitives.WriteSInt32(ref buffer, ref state, value);
}
/// <summary>
/// Writes an sint64 value, without a tag.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteSInt64(long value) => WritingPrimitives.WriteSInt64(ref buffer, ref state, value);
public void WriteSInt64(long value)
{
WritingPrimitives.WriteSInt64(ref buffer, ref state, value);
}
/// <summary>
/// Writes a length (in bytes) for length-delimited data.
@@ -209,33 +269,48 @@ namespace Google.Protobuf
/// This method simply writes a rawint, but exists for clarity in calling code.
/// </remarks>
/// <param name="length">Length value, in bytes.</param>
public void WriteLength(int length) => WritingPrimitives.WriteLength(ref buffer, ref state, length);
public void WriteLength(int length)
{
WritingPrimitives.WriteLength(ref buffer, ref state, length);
}
/// <summary>
/// Encodes and writes a tag.
/// </summary>
/// <param name="fieldNumber">The number of the field to write the tag for</param>
/// <param name="type">The wire format type of the tag to write</param>
public void WriteTag(int fieldNumber, WireFormat.WireType type) => WritingPrimitives.WriteTag(ref buffer, ref state, fieldNumber, type);
public void WriteTag(int fieldNumber, WireFormat.WireType type)
{
WritingPrimitives.WriteTag(ref buffer, ref state, fieldNumber, type);
}
/// <summary>
/// Writes an already-encoded tag.
/// </summary>
/// <param name="tag">The encoded tag</param>
public void WriteTag(uint tag) => WritingPrimitives.WriteTag(ref buffer, ref state, tag);
public void WriteTag(uint tag)
{
WritingPrimitives.WriteTag(ref buffer, ref state, tag);
}
/// <summary>
/// Writes the given single-byte tag.
/// </summary>
/// <param name="b1">The encoded tag</param>
public void WriteRawTag(byte b1) => WritingPrimitives.WriteRawTag(ref buffer, ref state, b1);
public void WriteRawTag(byte b1)
{
WritingPrimitives.WriteRawTag(ref buffer, ref state, b1);
}
/// <summary>
/// Writes the given two-byte tag.
/// </summary>
/// <param name="b1">The first byte of the encoded tag</param>
/// <param name="b2">The second byte of the encoded tag</param>
public void WriteRawTag(byte b1, byte b2) => WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2);
public void WriteRawTag(byte b1, byte b2)
{
WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2);
}
/// <summary>
/// Writes the given three-byte tag.
@@ -243,7 +318,10 @@ namespace Google.Protobuf
/// <param name="b1">The first byte of the encoded tag</param>
/// <param name="b2">The second byte of the encoded tag</param>
/// <param name="b3">The third byte of the encoded tag</param>
public void WriteRawTag(byte b1, byte b2, byte b3) => WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3);
public void WriteRawTag(byte b1, byte b2, byte b3)
{
WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3);
}
/// <summary>
/// Writes the given four-byte tag.
@@ -252,7 +330,10 @@ namespace Google.Protobuf
/// <param name="b2">The second byte of the encoded tag</param>
/// <param name="b3">The third byte of the encoded tag</param>
/// <param name="b4">The fourth byte of the encoded tag</param>
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4) => WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4);
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)
{
WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4);
}
/// <summary>
/// Writes the given five-byte tag.
@@ -262,11 +343,20 @@ namespace Google.Protobuf
/// <param name="b3">The third byte of the encoded tag</param>
/// <param name="b4">The fourth byte of the encoded tag</param>
/// <param name="b5">The fifth byte of the encoded tag</param>
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5) => WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4, b5);
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)
{
WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4, b5);
}
internal void Flush() => WriteBufferHelper.Flush(ref buffer, ref state);
internal void Flush()
{
WriteBufferHelper.Flush(ref buffer, ref state);
}
internal void CheckNoSpaceLeft() => WriteBufferHelper.CheckNoSpaceLeft(ref state);
internal void CheckNoSpaceLeft()
{
WriteBufferHelper.CheckNoSpaceLeft(ref state);
}
internal void CopyStateTo(CodedOutputStream output)
{

View File

@@ -30,8 +30,20 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{
// warning: this is a mutable struct, so it needs to be only passed as a ref!
internal struct WriterInternalState
{

View File

@@ -32,6 +32,7 @@
using System;
using System.Buffers.Binary;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if GOOGLE_PROTOBUF_SIMD

View File

@@ -30,7 +30,9 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
namespace Google.Protobuf