Commit c34ed5c9 authored by Jon Skeet's avatar Jon Skeet

Merge pull request #846 from jskeet/tostring

Support ToString in RepeatedField and MapField.
parents 2842568f 9ed6d4da
...@@ -562,6 +562,20 @@ namespace Google.Protobuf.Collections ...@@ -562,6 +562,20 @@ namespace Google.Protobuf.Collections
Assert.IsFalse(values.Contains(null)); Assert.IsFalse(values.Contains(null));
} }
[Test]
public void ToString_StringToString()
{
var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
Assert.AreEqual("{ \"foo\": \"bar\", \"x\": \"y\" }", map.ToString());
}
[Test]
public void ToString_UnsupportedKeyType()
{
var map = new MapField<byte, string> { { 10, "foo" } };
Assert.Throws<ArgumentException>(() => map.ToString());
}
private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value) private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
{ {
return new KeyValuePair<TKey, TValue>(key, value); return new KeyValuePair<TKey, TValue>(key, value);
......
...@@ -37,6 +37,7 @@ using System.IO; ...@@ -37,6 +37,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Google.Protobuf.TestProtos; using Google.Protobuf.TestProtos;
using Google.Protobuf.WellKnownTypes;
using NUnit.Framework; using NUnit.Framework;
namespace Google.Protobuf.Collections namespace Google.Protobuf.Collections
...@@ -599,5 +600,61 @@ namespace Google.Protobuf.Collections ...@@ -599,5 +600,61 @@ namespace Google.Protobuf.Collections
list.Insert(1, "middle"); list.Insert(1, "middle");
CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list); CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
} }
[Test]
public void ToString_Integers()
{
var list = new RepeatedField<int> { 5, 10, 20 };
var text = list.ToString();
Assert.AreEqual("[ 5, 10, 20 ]", text);
}
[Test]
public void ToString_Strings()
{
var list = new RepeatedField<string> { "x", "y", "z" };
var text = list.ToString();
Assert.AreEqual("[ \"x\", \"y\", \"z\" ]", text);
}
[Test]
public void ToString_Messages()
{
var list = new RepeatedField<TestAllTypes> { new TestAllTypes { SingleDouble = 1.5 }, new TestAllTypes { SingleInt32 = 10 } };
var text = list.ToString();
Assert.AreEqual("[ { \"singleDouble\": 1.5 }, { \"singleInt32\": 10 } ]", text);
}
[Test]
public void ToString_Empty()
{
var list = new RepeatedField<TestAllTypes> { };
var text = list.ToString();
Assert.AreEqual("[ ]", text);
}
[Test]
public void ToString_InvalidElementType()
{
var list = new RepeatedField<decimal> { 15m };
Assert.Throws<ArgumentException>(() => list.ToString());
}
[Test]
public void ToString_Timestamp()
{
var list = new RepeatedField<Timestamp> { Timestamp.FromDateTime(new DateTime(2015, 10, 1, 12, 34, 56, DateTimeKind.Utc)) };
var text = list.ToString();
Assert.AreEqual("[ \"2015-10-01T12:34:56Z\" ]", text);
}
[Test]
public void ToString_Struct()
{
var message = new Struct { Fields = { { "foo", new Value { NumberValue = 20 } } } };
var list = new RepeatedField<Struct> { message };
var text = list.ToString();
Assert.AreEqual(text, "[ { \"foo\": 20 } ]", message.ToString());
}
} }
} }
...@@ -35,6 +35,7 @@ using System; ...@@ -35,6 +35,7 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using Google.Protobuf.Compatibility; using Google.Protobuf.Compatibility;
namespace Google.Protobuf.Collections namespace Google.Protobuf.Collections
...@@ -45,10 +46,17 @@ namespace Google.Protobuf.Collections ...@@ -45,10 +46,17 @@ namespace Google.Protobuf.Collections
/// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam> /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>
/// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam> /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>
/// <remarks> /// <remarks>
/// <para>
/// This implementation preserves insertion order for simplicity of testing /// This implementation preserves insertion order for simplicity of testing
/// code using maps fields. Overwriting an existing entry does not change the /// code using maps fields. Overwriting an existing entry does not change the
/// position of that entry within the map. Equality is not order-sensitive. /// position of that entry within the map. Equality is not order-sensitive.
/// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal" />. /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal" />.
/// </para>
/// <para>
/// This implementation does not generally prohibit the use of key/value types which are not
/// supported by Protocol Buffers (e.g. using a key type of <code>byte</code>) but nor does it guarantee
/// that all operations will work in such cases.
/// </para>
/// </remarks> /// </remarks>
public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
{ {
...@@ -482,6 +490,17 @@ namespace Google.Protobuf.Collections ...@@ -482,6 +490,17 @@ namespace Google.Protobuf.Collections
return size; return size;
} }
/// <summary>
/// Returns a string representation of this repeated field, in the same
/// way as it would be represented by the default JSON formatter.
/// </summary>
public override string ToString()
{
var builder = new StringBuilder();
JsonFormatter.Default.WriteDictionary(builder, this);
return builder.ToString();
}
#region IDictionary explicit interface implementation #region IDictionary explicit interface implementation
void IDictionary.Add(object key, object value) void IDictionary.Add(object key, object value)
{ {
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using Google.Protobuf.Compatibility; using Google.Protobuf.Compatibility;
namespace Google.Protobuf.Collections namespace Google.Protobuf.Collections
...@@ -41,6 +42,10 @@ namespace Google.Protobuf.Collections ...@@ -41,6 +42,10 @@ namespace Google.Protobuf.Collections
/// The contents of a repeated field: essentially, a collection with some extra /// The contents of a repeated field: essentially, a collection with some extra
/// restrictions (no null values) and capabilities (deep cloning). /// restrictions (no null values) and capabilities (deep cloning).
/// </summary> /// </summary>
/// <remarks>
/// This implementation does not generally prohibit the use of types which are not
/// 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> /// <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>> public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>
{ {
...@@ -464,6 +469,17 @@ namespace Google.Protobuf.Collections ...@@ -464,6 +469,17 @@ namespace Google.Protobuf.Collections
array[count] = default(T); array[count] = default(T);
} }
/// <summary>
/// Returns a string representation of this repeated field, in the same
/// way as it would be represented by the default JSON formatter.
/// </summary>
public override string ToString()
{
var builder = new StringBuilder();
JsonFormatter.Default.WriteList(builder, this);
return builder.ToString();
}
/// <summary> /// <summary>
/// Gets or sets the item at the specified index. /// Gets or sets the item at the specified index.
/// </summary> /// </summary>
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment