Distinguish UUID and GUID storage
Intermediate · C#. UUID stores bytes in network order; Windows GUID storage reverses the first three integer fields. The enclosing layout byte order does not select between them.
Run this example
Prerequisites: the repository's .NET 10 SDK and a checkout of this source. Run from the repository root:
dotnet run --project docs/examples/CStructSharp.Docs.Examples.csproj -c Release -- identifier-order
The runner checks the same Guid value in two distinct 16-byte storage orders. Success includes PASS identifier-order.
Try the related browser lesson.
Complete program
The layout, options, input bytes, helper methods, and required types are all included. To adapt it outside the repository, create a .NET 10 console project, add CStructSharp, and replace Program.cs with this complete file. These examples follow the source version; use a matching package when testing a release.
Download the complete C# source.
// Generated from executable documentation examples. Edit the source region, then regenerate.
using System;
using System.IO;
using System.IO.Pipelines;
using System.Linq;
using System.Buffers;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using CStructSharp;
using CStructSharp.Codecs;
using CStructSharp.Diagnostics;
using CStructSharp.Introspection;
using CStructSharp.Values;
internal static partial class Program
{
public static void Main()
{
IdentifierOrder();
Console.WriteLine("PASS identifier-order");
}
private static void IdentifierOrder()
{
var layout = new CStruct("struct root { uuid network; guid windows; };", aligned: false);
Guid id = Guid.Parse("00112233-4455-6677-8899-aabbccddeeff");
byte[] bytes = layout.Serialize("root", new Dictionary<string, object?> { ["network"] = id, ["windows"] = id });
SequenceEqual(Convert.FromHexString("00112233445566778899AABBCCDDEEFF33221100554477668899AABBCCDDEEFF"), bytes);
Equal(id, layout.ReadValue<Guid>(bytes.AsSpan(), "root.network"));
Equal(id, layout.ReadValue<Guid>(bytes.AsSpan(), "root.windows"));
using var stream = new MemoryStream(bytes);
Equal(16L, layout.ResolveAddress(stream, "root.windows"));
}
private static void Equal<T>(T expected, T actual)
{
if (!EqualityComparer<T>.Default.Equals(expected, actual))
{
throw new InvalidOperationException($"Expected '{expected}', received '{actual}'.");
}
}
private static void SequenceEqual(byte[] expected, byte[] actual)
{
if (!expected.AsSpan().SequenceEqual(actual))
{
throw new InvalidOperationException(
$"Expected {Convert.ToHexString(expected)}, received {Convert.ToHexString(actual)}.");
}
}
}
Try it and diagnose mistakes
Swap the uuid and guid type names without changing bytes.
Answer: Both fields still consume 16 bytes, but the first groups of the interpreted identifiers change. The program contains assertions for its original inputs. When changing an input intentionally, update the expected assertion too; an unchanged assertion is not evidence that the new value is wrong.
Continue with the related guide or choose another recipe.