未验证 提交 7e95181f 编写于 作者: K Kevin Jones 提交者: GitHub

Implement initial capacity for AsnWriter

上级 de03d8a8
......@@ -144,6 +144,7 @@ public partial struct AsnReaderOptions
public sealed partial class AsnWriter
{
public AsnWriter(System.Formats.Asn1.AsnEncodingRules ruleSet) { }
public AsnWriter(System.Formats.Asn1.AsnEncodingRules ruleSet, int initialCapacity) { }
public System.Formats.Asn1.AsnEncodingRules RuleSet { get { throw null; } }
public void CopyTo(System.Formats.Asn1.AsnWriter destination) { }
public byte[] Encode() { throw null; }
......
......@@ -99,6 +99,9 @@
<data name="Argument_WriteEncodedValue_OneValueAtATime" xml:space="preserve">
<value>The input to WriteEncodedValue must represent a single encoded value with no trailing data.</value>
</data>
<data name="ArgumentOutOfRange_NeedNonNegNum" xml:space="preserve">
<value>Non-negative number required.</value>
</data>
<data name="AsnWriter_EncodeUnbalancedStack" xml:space="preserve">
<value>Encode cannot be called while a Sequence, Set-Of, or Octet String is still open.</value>
</data>
......
......@@ -48,6 +48,31 @@ public AsnWriter(AsnEncodingRules ruleSet)
RuleSet = ruleSet;
}
/// <summary>
/// Create a new <see cref="AsnWriter"/> with a given set of encoding rules and an initial capacity.
/// </summary>
/// <param name="ruleSet">The encoding constraints for the writer.</param>
/// <param name="initialCapacity">The minimum capacity with which to initialize the underlying buffer.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// <para><paramref name="ruleSet"/> is not defined.</para>
/// <para> -or- </para>
/// <para><paramref name="initialCapacity"/> is a negative number.</para>
/// </exception>
/// <remarks>
/// Specifying <paramref name="initialCapacity" /> with a value of zero behaves as if no initial capacity were
/// specified.
/// </remarks>
public AsnWriter(AsnEncodingRules ruleSet, int initialCapacity) : this(ruleSet)
{
if (initialCapacity < 0)
throw new ArgumentOutOfRangeException(nameof(initialCapacity), SR.ArgumentOutOfRange_NeedNonNegNum);
if (initialCapacity > 0)
{
_buffer = new byte[initialCapacity];
}
}
/// <summary>
/// Reset the writer to have no data, without releasing resources.
/// </summary>
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Reflection;
using Xunit;
namespace System.Formats.Asn1.Tests.Writer
......@@ -17,6 +18,20 @@ public static void ValidateRuleSet(int value)
AssertExtensions.Throws<ArgumentOutOfRangeException>(
"ruleSet",
() => new AsnWriter((AsnEncodingRules)value));
AssertExtensions.Throws<ArgumentOutOfRangeException>(
"ruleSet",
() => new AsnWriter((AsnEncodingRules)value, initialCapacity: 1000));
}
[Theory]
[InlineData(-1)]
[InlineData(int.MinValue)]
public static void ValidateInitialCapacity(int initialCapacity)
{
AssertExtensions.Throws<ArgumentOutOfRangeException>(
"initialCapacity",
() => new AsnWriter(AsnEncodingRules.DER, initialCapacity));
}
[Theory]
......@@ -138,5 +153,92 @@ public static void CopyTo_Null(AsnEncodingRules ruleSet)
"destination",
() => writer.CopyTo(null));
}
[Fact]
public static void InitialCapacity_ExactCapacity()
{
ReadOnlySpan<byte> value = new byte[] { 0x04, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
AsnWriter writer = new AsnWriter(AsnEncodingRules.DER, initialCapacity: 8);
writer.WriteEncodedValue(value);
byte[]? buffer = PeekRawBuffer(writer);
Assert.Equal(8, buffer?.Length);
byte[] encoded = writer.Encode();
AssertExtensions.SequenceEqual(value, encoded);
writer.Reset();
buffer = PeekRawBuffer(writer);
Assert.Equal(8, buffer?.Length);
writer.WriteEncodedValue(value);
buffer = PeekRawBuffer(writer);
Assert.Equal(8, buffer?.Length);
}
[Fact]
public static void InitialCapacity_ZeroHasNoInitialCapacity()
{
AsnWriter writer = new AsnWriter(AsnEncodingRules.DER, initialCapacity: 0);
byte[]? buffer = PeekRawBuffer(writer);
Assert.Null(buffer);
}
[Fact]
public static void InitialCapacity_UnderCapacity()
{
ReadOnlySpan<byte> value = new byte[] { 0x04, 0x01, 0x01 };
AsnWriter writer = new AsnWriter(AsnEncodingRules.DER, initialCapacity: 8);
writer.WriteEncodedValue(value);
byte[]? buffer = PeekRawBuffer(writer);
Assert.Equal(8, buffer?.Length);
byte[] encoded = writer.Encode();
AssertExtensions.SequenceEqual(value, encoded);
writer.Reset();
buffer = PeekRawBuffer(writer);
Assert.Equal(8, buffer?.Length);
}
[Fact]
public static void InitialCapacity_ExceedCapacity()
{
ReadOnlySpan<byte> value = new byte[] { 0x04, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
AsnWriter writer = new AsnWriter(AsnEncodingRules.DER, initialCapacity: 8);
writer.WriteEncodedValue(value);
byte[]? buffer = PeekRawBuffer(writer);
Assert.Equal(1024, buffer?.Length);
}
[Fact]
public static void InitialCapacity_ResizeBlockAligns()
{
ReadOnlySpan<byte> value = new byte[] { 0x04, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
ReadOnlySpan<byte> valueLarge = new byte[] { 0x04, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
AsnWriter writer = new AsnWriter(AsnEncodingRules.DER, initialCapacity: 8);
writer.WriteEncodedValue(value);
byte[]? buffer = PeekRawBuffer(writer);
Assert.Equal(8, buffer?.Length);
writer.Reset();
buffer = PeekRawBuffer(writer);
Assert.Equal(8, buffer?.Length);
writer.WriteEncodedValue(valueLarge);
buffer = PeekRawBuffer(writer);
Assert.Equal(1024, buffer?.Length);
}
private static byte[]? PeekRawBuffer(AsnWriter writer)
{
FieldInfo bufField = typeof(AsnWriter).GetField("_buffer", BindingFlags.Instance | BindingFlags.NonPublic);
return (byte[]?)bufField.GetValue(writer);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册