Skip to content

Commit 05aed40

Browse files
Add some helper utilities (#10289)
This change introduces a couple of helper utilities into MS.ANC.Razor.Utilities.Shared. Most notably, I've introduced an `ArgHelper` type that can be used for argument validation. This is analogous to the various `ArgumentNullException.Throw*`, `ArgumentException.Throw*`, and `ArgumentOutOfRangeException.Throw*` APIs that were added in .NET 8+. In addition, I've included `PooledArrayBufferWriter<T>`, which is a use implementation of `IBufferWriter<T>` that uses shared array pools.
2 parents 7ae5e9a + 3f76cf3 commit 05aed40

File tree

20 files changed

+1405
-0
lines changed

20 files changed

+1405
-0
lines changed

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectSystem/RazorProjectInfo.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT license. See License.txt in the project root for license information.
33

4+
using System;
5+
using System.Buffers;
46
using System.Collections.Immutable;
57
using System.IO;
68
using MessagePack;
@@ -45,9 +47,15 @@ public RazorProjectInfo(
4547
Documents = documents.NullToEmpty();
4648
}
4749

50+
public void SerializeTo(IBufferWriter<byte> bufferWriter)
51+
=> MessagePackSerializer.Serialize(bufferWriter, this, s_options);
52+
4853
public void SerializeTo(Stream stream)
4954
=> MessagePackSerializer.Serialize(stream, this, s_options);
5055

56+
public static RazorProjectInfo? DeserializeFrom(ReadOnlyMemory<byte> buffer)
57+
=> MessagePackSerializer.Deserialize<RazorProjectInfo>(buffer, s_options);
58+
5159
public static RazorProjectInfo? DeserializeFrom(Stream stream)
5260
=> MessagePackSerializer.Deserialize<RazorProjectInfo>(stream, s_options);
5361
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT license. See License.txt in the project root for license information.
3+
4+
using System;
5+
using Xunit;
6+
7+
namespace Microsoft.AspNetCore.Razor.Utilities.Shared.Test;
8+
9+
public class ArgHelperTests
10+
{
11+
[Theory]
12+
[InlineData(null, typeof(ArgumentNullException))]
13+
[InlineData("test")]
14+
public void ThrowIfNull(string? s, Type? exceptionType = null)
15+
{
16+
Verify(() => ArgHelper.ThrowIfNull(s), exceptionType);
17+
}
18+
19+
[Fact]
20+
public unsafe void ThrowIfNull_NullPtr_Throws()
21+
{
22+
byte* ptr = null;
23+
24+
Assert.Throws<ArgumentNullException>(() =>
25+
{
26+
ArgHelper.ThrowIfNull(ptr);
27+
});
28+
}
29+
30+
[Fact]
31+
public unsafe void ThrowIfNull_Ptr_DoesNotThrow()
32+
{
33+
fixed (byte* ptr = new byte[8])
34+
{
35+
ArgHelper.ThrowIfNull(ptr);
36+
}
37+
}
38+
39+
[Theory]
40+
[InlineData(null, typeof(ArgumentNullException))]
41+
[InlineData("", typeof(ArgumentException))]
42+
[InlineData(" ")]
43+
[InlineData("test")]
44+
public void ThrowIfNullOrEmpty(string? s, Type? exceptionType = null)
45+
{
46+
Verify(() => ArgHelper.ThrowIfNullOrEmpty(s), exceptionType);
47+
}
48+
49+
[Theory]
50+
[InlineData(null, typeof(ArgumentNullException))]
51+
[InlineData("", typeof(ArgumentException))]
52+
[InlineData(" ", typeof(ArgumentException))]
53+
[InlineData("test")]
54+
public void ThrowIfNullOrWhiteSpace(string? s, Type? exceptionType = null)
55+
{
56+
Verify(() => ArgHelper.ThrowIfNullOrWhiteSpace(s), exceptionType);
57+
}
58+
59+
[Theory]
60+
[InlineData(null, null, typeof(ArgumentOutOfRangeException))]
61+
[InlineData(null, "test")]
62+
[InlineData("test", null)]
63+
[InlineData("test", "test", typeof(ArgumentOutOfRangeException))]
64+
[InlineData("test", "TeSt")]
65+
public void ThrowIfEqual(string? s1, string? s2, Type? exceptionType = null)
66+
{
67+
Verify(() => ArgHelper.ThrowIfEqual(s1, s2), exceptionType);
68+
}
69+
70+
[Theory]
71+
[InlineData(null, null)]
72+
[InlineData(null, "test", typeof(ArgumentOutOfRangeException))]
73+
[InlineData("test", null, typeof(ArgumentOutOfRangeException))]
74+
[InlineData("test", "test")]
75+
[InlineData("test", "TeSt", typeof(ArgumentOutOfRangeException))]
76+
public void ThrowIfNotEqual(string? s1, string? s2, Type? exceptionType = null)
77+
{
78+
Verify(() => ArgHelper.ThrowIfNotEqual(s1, s2), exceptionType);
79+
}
80+
81+
[Theory]
82+
[InlineData(0, typeof(ArgumentOutOfRangeException))]
83+
[InlineData(-1)]
84+
[InlineData(1)]
85+
public void ThrowIfZero(int v, Type? exceptionType = null)
86+
{
87+
Verify(() => ArgHelper.ThrowIfZero(v), exceptionType);
88+
}
89+
90+
[Theory]
91+
[InlineData(0)]
92+
[InlineData(-1, typeof(ArgumentOutOfRangeException))]
93+
[InlineData(1)]
94+
public void ThrowIfNegative(int v, Type? exceptionType = null)
95+
{
96+
Verify(() => ArgHelper.ThrowIfNegative(v), exceptionType);
97+
}
98+
99+
[Theory]
100+
[InlineData(0, typeof(ArgumentOutOfRangeException))]
101+
[InlineData(-1, typeof(ArgumentOutOfRangeException))]
102+
[InlineData(1)]
103+
public void ThrowIfNegativeOrZero(int v, Type? exceptionType = null)
104+
{
105+
Verify(() => ArgHelper.ThrowIfNegativeOrZero(v), exceptionType);
106+
}
107+
108+
[Theory]
109+
[InlineData(42, 42)]
110+
[InlineData(41, 42)]
111+
[InlineData(43, 42, typeof(ArgumentOutOfRangeException))]
112+
public void ThrowIfGreaterThan(int v1, int v2, Type? exceptionType = null)
113+
{
114+
Verify(() => ArgHelper.ThrowIfGreaterThan(v1, v2), exceptionType);
115+
}
116+
117+
[Theory]
118+
[InlineData(42, 42, typeof(ArgumentOutOfRangeException))]
119+
[InlineData(41, 42)]
120+
[InlineData(43, 42, typeof(ArgumentOutOfRangeException))]
121+
public void ThrowIfGreaterThanOrEqual(int v1, int v2, Type? exceptionType = null)
122+
{
123+
Verify(() => ArgHelper.ThrowIfGreaterThanOrEqual(v1, v2), exceptionType);
124+
}
125+
126+
[Theory]
127+
[InlineData(42, 42)]
128+
[InlineData(41, 42, typeof(ArgumentOutOfRangeException))]
129+
[InlineData(43, 42)]
130+
public void ThrowIfLessThan(int v1, int v2, Type? exceptionType = null)
131+
{
132+
Verify(() => ArgHelper.ThrowIfLessThan(v1, v2), exceptionType);
133+
}
134+
135+
[Theory]
136+
[InlineData(42, 42, typeof(ArgumentOutOfRangeException))]
137+
[InlineData(41, 42, typeof(ArgumentOutOfRangeException))]
138+
[InlineData(43, 42)]
139+
public void ThrowIfLessThanOrEqual(int v1, int v2, Type? exceptionType = null)
140+
{
141+
Verify(() => ArgHelper.ThrowIfLessThanOrEqual(v1, v2), exceptionType);
142+
}
143+
144+
private static void Verify(Action a, Type? exceptionType = null)
145+
{
146+
if (exceptionType is not null)
147+
{
148+
Assert.Throws(exceptionType, a);
149+
}
150+
else
151+
{
152+
a();
153+
}
154+
}
155+
}

src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/Microsoft.AspNetCore.Razor.Utilities.Shared.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<PropertyGroup>
44
<TargetFrameworks>$(DefaultNetCoreTargetFrameworks)</TargetFrameworks>
55
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);$(DefaultNetFxTargetFramework)</TargetFrameworks>
6+
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
67
</PropertyGroup>
78

89
<ItemGroup>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT license. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Buffers;
6+
using Xunit;
7+
8+
namespace Microsoft.AspNetCore.Razor.Utilities.Shared.Test;
9+
10+
public class PooledArrayBufferWriterTests
11+
{
12+
[Theory]
13+
[InlineData(42)]
14+
[InlineData(256)]
15+
[InlineData(400)]
16+
[InlineData(1024)]
17+
[InlineData(8 * 1024)]
18+
public void FillBufferWriter(int arraySize)
19+
{
20+
// Create an array filled with byte data.
21+
Span<byte> span = new byte[arraySize];
22+
23+
for (var i = 0; i < arraySize; i++)
24+
{
25+
span[i] = (byte)(i % 255);
26+
}
27+
28+
using var bufferWriter = new PooledArrayBufferWriter<byte>();
29+
30+
bufferWriter.Write(span);
31+
32+
Assert.True(span.SequenceEqual(bufferWriter.WrittenMemory.Span));
33+
}
34+
}

0 commit comments

Comments
 (0)