Skip to content

Commit b007605

Browse files
committed
Finalize alternative integer representations
Finally unsafe code
1 parent 3700985 commit b007605

11 files changed

Lines changed: 486 additions & 106 deletions
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Syndiesis.Utilities;
2+
3+
namespace Syndiesis.Tests;
4+
5+
public sealed class BinaryIntegerWriterTests
6+
{
7+
[Test]
8+
[MethodDataSource(nameof(WriterTestCasesSource))]
9+
public async Task Test(WriterTestCase @case)
10+
{
11+
var info = IntegerInfo.Create(@case.Value);
12+
var result = BinaryIntegerWriter.Write(info, @case.GroupLength);
13+
await Assert.That(result).IsEqualTo(@case.Expected);
14+
}
15+
16+
public IReadOnlyList<WriterTestCase> WriterTestCasesSource()
17+
{
18+
return
19+
[
20+
// int
21+
new(0b1, 0, "1"),
22+
new(0b0001, 0, "1"),
23+
24+
new(0b0001, 4, "1"),
25+
new(0b0010_0101_0001_0000, 4, "10_0101_0001_0000"),
26+
27+
new(0b101010101, 2, "1_01_01_01_01"),
28+
29+
new(0b1111111, 3, "1_111_111"),
30+
];
31+
}
32+
33+
public sealed record WriterTestCase(
34+
object Value, int GroupLength, string Expected);
35+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Syndiesis.Utilities;
2+
3+
namespace Syndiesis.Tests;
4+
5+
public sealed class HexIntegerWriterTests
6+
{
7+
[Test]
8+
[MethodDataSource(nameof(WriterTestCasesSource))]
9+
public async Task Test(WriterTestCase @case)
10+
{
11+
var info = IntegerInfo.Create(@case.Value);
12+
var result = HexIntegerWriter.Write(info, @case.GroupLength);
13+
await Assert.That(result).IsEqualTo(@case.Expected);
14+
}
15+
16+
public IReadOnlyList<WriterTestCase> WriterTestCasesSource()
17+
{
18+
return
19+
[
20+
new(0x00000123, 0, "00000123"),
21+
22+
new(0x0000_0123, 4, "0000_0123"),
23+
new(0x1021_3201, 4, "1021_3201"),
24+
25+
new(0x01_23_45_67, 2, "01_23_45_67"),
26+
27+
new(0x01234567, 3, "01_234_567"),
28+
];
29+
}
30+
31+
public sealed record WriterTestCase(
32+
object Value, int GroupLength, string Expected);
33+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
using Syndiesis.Utilities;
2+
3+
namespace Syndiesis.Tests;
4+
5+
public sealed class RightSideBufferWriterTests
6+
{
7+
[Test]
8+
public async Task UseCase0()
9+
{
10+
const int capacity = 10;
11+
Span<char> s = stackalloc char[capacity];
12+
var writer = new RightSideBufferWriter<char>(s);
13+
writer.Write("312");
14+
writer.Write('4');
15+
writer.Write("01");
16+
17+
var finalized = writer.GetFinalized();
18+
await Assert.That(finalized.ToString()).IsEqualTo("014312");
19+
}
20+
21+
[Test]
22+
public async Task TestOverflowWithChar()
23+
{
24+
const int capacity = 1;
25+
Span<char> s = stackalloc char[capacity];
26+
var writer = new RightSideBufferWriter<char>(s);
27+
writer.Write('4');
28+
29+
// Can't use writer inside a lambda; hence the manual try block
30+
try
31+
{
32+
writer.Write('0');
33+
Assert.Fail("Expected an exception");
34+
}
35+
catch { }
36+
37+
var finalized = writer.GetFinalized();
38+
await Assert.That(finalized.ToString()).IsEqualTo("4");
39+
}
40+
41+
[Test]
42+
public async Task TestOverflowWithString0()
43+
{
44+
const int capacity = 1;
45+
Span<char> s = stackalloc char[capacity];
46+
var writer = new RightSideBufferWriter<char>(s);
47+
writer.Write('4');
48+
49+
// Can't use writer inside a lambda; hence the manual try block
50+
try
51+
{
52+
writer.Write("0");
53+
Assert.Fail("Expected an exception");
54+
}
55+
catch { }
56+
57+
try
58+
{
59+
writer.Write("041");
60+
Assert.Fail("Expected an exception");
61+
}
62+
catch { }
63+
64+
// Expect no exception with an empty string
65+
writer.Write(string.Empty);
66+
67+
var finalized = writer.GetFinalized();
68+
await Assert.That(finalized.ToString()).IsEqualTo("4");
69+
}
70+
71+
[Test]
72+
public async Task TestOverflowWithString1()
73+
{
74+
const int capacity = 2;
75+
Span<char> s = stackalloc char[capacity];
76+
var writer = new RightSideBufferWriter<char>(s);
77+
writer.Write('4');
78+
79+
try
80+
{
81+
writer.Write("041");
82+
Assert.Fail("Expected an exception");
83+
}
84+
catch { }
85+
86+
try
87+
{
88+
writer.Write("01");
89+
Assert.Fail("Expected an exception");
90+
}
91+
catch { }
92+
93+
// Expect no exception with an empty string
94+
writer.Write(string.Empty);
95+
96+
// Expect the buffer to have one more char of remaining space
97+
writer.Write("0");
98+
99+
// Now the buffer should be full
100+
try
101+
{
102+
writer.Write("0");
103+
Assert.Fail("Expected an exception");
104+
}
105+
catch { }
106+
107+
var finalized = writer.GetFinalized();
108+
await Assert.That(finalized.ToString()).IsEqualTo("04");
109+
}
110+
111+
[Test]
112+
public async Task TestEmpty()
113+
{
114+
Span<char> s = [];
115+
var writer = new RightSideBufferWriter<char>(s);
116+
var finalized = writer.GetFinalized();
117+
await Assert.That(finalized.ToString()).IsEqualTo(string.Empty);
118+
}
119+
}

Syndiesis/Controls/Editor/RoslynColorizer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,4 @@ private static LazilyUpdatedGradientBrush DoubleColorGradientBrush(
258258
return new LazilyUpdatedGradientBrush(brush, [startStop, endStop]);
259259
}
260260
}
261-
}
261+
}

Syndiesis/Core/DisplayAnalysis/BaseAnalysisNodeCreator.cs

Lines changed: 5 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using Garyon.Extensions;
33
using Garyon.Reflection;
44
using Microsoft.CodeAnalysis;
5-
using Syndiesis.ColorHelpers;
65
using Syndiesis.Controls.AnalysisVisualization;
76
using Syndiesis.Controls.Inlines;
87
using Syndiesis.InternalGenerators.Core;
@@ -19,7 +18,6 @@
1918

2019
namespace Syndiesis.Core.DisplayAnalysis;
2120

22-
using static System.Net.Mime.MediaTypeNames;
2321
using AnalysisTreeListNode = UIBuilder.AnalysisTreeListNode;
2422
using AnalysisTreeListNodeLine = UIBuilder.AnalysisTreeListNodeLine;
2523
using ComplexGroupedRunInline = ComplexGroupedRunInline.Builder;
@@ -787,39 +785,26 @@ private static bool IsInteger(object value)
787785
protected ImmutableArray<RunOrGrouped> IntegerValueRuns(object value)
788786
{
789787
var info = IntegerInfo.Create(value);
790-
791-
var text = value.ToString()!;
792-
var textRun = Run(text, CommonStyles.RawValueBrush);
793-
var hexInline = CreateHexRunGroup(ref info);
794-
var binaryInline = CreateBinaryRunGroup(ref info);
795788
return
796789
[
797-
new SingleRunInline(textRun),
790+
SingleRun(value.ToString()!, ColorizationStyles.NumericLiteralBrush),
798791
CreateLargeSplitterRun(),
799-
hexInline,
792+
CreateHexRunGroup(ref info),
800793
CreateLargeSplitterRun(),
801-
binaryInline,
794+
CreateBinaryRunGroup(ref info),
802795
];
803796
}
804797

805798
private static ComplexGroupedRunInline CreateHexRunGroup(
806799
ref readonly IntegerInfo info)
807800
{
808-
var value = info.ValueBits;
809-
var size = info.ByteSize;
810-
811-
// TODO: Create the value strings
812-
return CreateAlternativeNumericGroup("0x", "3412431");
801+
return CreateAlternativeNumericGroup("0x", HexIntegerWriter.Write(info, 4));
813802
}
814803

815804
private static ComplexGroupedRunInline CreateBinaryRunGroup(
816805
ref readonly IntegerInfo info)
817806
{
818-
var value = info.ValueBits;
819-
var size = info.ByteSize;
820-
821-
// TODO: Create the value strings
822-
return CreateAlternativeNumericGroup("0b", "3412431");
807+
return CreateAlternativeNumericGroup("0b", BinaryIntegerWriter.Write(info, 4));
823808
}
824809

825810
private static ComplexGroupedRunInline CreateAlternativeNumericGroup(
@@ -1683,88 +1668,3 @@ public NodeTypeDisplay ThrowsExceptionDisplay
16831668
=> new(CommonTypes.ThrowsException, ThrowsColor);
16841669
}
16851670
}
1686-
1687-
/// <summary>
1688-
/// Contains information about an integer value that was derived from an object.
1689-
/// </summary>
1690-
/// <param name="Value">The original value as an object as it was retrieved.</param>
1691-
/// <param name="ValueBits">The bits of the integer value in a 64-bit integer.</param>
1692-
/// <param name="ByteSize">The number of bytes the integer has.</param>
1693-
/// <remarks>
1694-
/// This only supports up to <see cref="UInt64"/>. Larger integers are not
1695-
/// natively implemented and are thus ignored.
1696-
/// </remarks>
1697-
internal readonly record struct IntegerInfo(
1698-
object Value,
1699-
ulong ValueBits,
1700-
int ByteSize)
1701-
{
1702-
public TypeCode TypeCode => Value.GetType().GetTypeCode();
1703-
1704-
public static IntegerInfo Create(object value)
1705-
{
1706-
switch (value.GetType().GetTypeCode())
1707-
{
1708-
case TypeCode.SByte:
1709-
{
1710-
var @sbyte = (sbyte)value;
1711-
var @byte = unchecked((byte)@sbyte);
1712-
ulong bits = @byte;
1713-
return new IntegerInfo(value, bits, sizeof(sbyte));
1714-
}
1715-
case TypeCode.Byte:
1716-
{
1717-
var @byte = (byte)value;
1718-
ulong bits = @byte;
1719-
return new IntegerInfo(value, bits, sizeof(byte));
1720-
}
1721-
1722-
case TypeCode.Int16:
1723-
{
1724-
var @short = (short)value;
1725-
var @ushort = unchecked((ushort)@short);
1726-
ulong bits = @ushort;
1727-
return new IntegerInfo(value, bits, sizeof(short));
1728-
}
1729-
case TypeCode.UInt16:
1730-
{
1731-
var @ushort = (ushort)value;
1732-
ulong bits = @ushort;
1733-
return new IntegerInfo(value, bits, sizeof(ushort));
1734-
}
1735-
1736-
case TypeCode.Int32:
1737-
{
1738-
var @int = (int)value;
1739-
var @uint = unchecked((uint)@int);
1740-
ulong bits = @uint;
1741-
return new IntegerInfo(value, bits, sizeof(int));
1742-
}
1743-
case TypeCode.UInt32:
1744-
{
1745-
var @uint = (uint)value;
1746-
ulong bits = @uint;
1747-
return new IntegerInfo(value, bits, sizeof(uint));
1748-
}
1749-
1750-
case TypeCode.Int64:
1751-
{
1752-
var @long = (long)value;
1753-
var @ulong = unchecked((ulong)@long);
1754-
ulong bits = @ulong;
1755-
return new IntegerInfo(value, bits, sizeof(long));
1756-
}
1757-
case TypeCode.UInt64:
1758-
{
1759-
var @ulong = (ulong)value;
1760-
ulong bits = @ulong;
1761-
return new IntegerInfo(value, bits, sizeof(ulong));
1762-
}
1763-
}
1764-
1765-
throw new NotSupportedException("The object type is not supported.");
1766-
}
1767-
1768-
// TODO: Create hex representation
1769-
// TODO: Create binary representation
1770-
}

Syndiesis/Syndiesis.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<Description>The most revolutionary syntax visualizer for C#</Description>
2020
<RepositoryUrl>https://github.com/Rekkonnect/Syndiesis</RepositoryUrl>
2121
<RepositoryType>git</RepositoryType>
22+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
2223
</PropertyGroup>
2324

2425
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Allow Dev Errors|AnyCPU'">

0 commit comments

Comments
 (0)