diff --git a/Tests/NFUnitTestSystemLib/UnitTestGuid.cs b/Tests/NFUnitTestSystemLib/UnitTestGuid.cs
index e2b3ea3..a85d00f 100644
--- a/Tests/NFUnitTestSystemLib/UnitTestGuid.cs
+++ b/Tests/NFUnitTestSystemLib/UnitTestGuid.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
@@ -60,7 +60,7 @@ public void ByteArrayConstructor_Test2()
///
///
- Byte[] guid16 = GetRandomBytes(16);
+ byte[] guid16 = GetRandomBytes(16);
Guid myGuid1 = new Guid(guid16);
}
@@ -82,7 +82,7 @@ public void ArgumentException_Test3()
{
size = random.Next(100);
}
- Byte[] guidNot16 = GetRandomBytes(size);
+ byte[] guidNot16 = GetRandomBytes(size);
Assert.ThrowsException(typeof(ArgumentException), () => { Guid myGuid1 = new Guid(guidNot16); });
}
@@ -95,7 +95,7 @@ public void ArgumentNullException_Test4()
///
///
- Byte[] nullByte = null;
+ byte[] nullByte = null;
Assert.ThrowsException(typeof(ArgumentNullException), () => { Guid myGuid1 = new Guid(nullByte); });
}
@@ -157,11 +157,11 @@ public void Int_Short_Constructor_Test6()
///
Random random = new Random();
- int _int = random.Next(Int32.MaxValue);
+ int _int = random.Next(int.MaxValue);
short _short1 = (short)random.Next(32768);
short _short2 = (short)random.Next(32768);
- Byte[] _bArr = GetRandomBytes(8);
- Guid _guid = new Guid(_int, _short1, _short2, _bArr[0], _bArr[1], _bArr[2], _bArr[3], _bArr[4], _bArr[5], _bArr[6], _bArr[7]);
+ byte[] _bArr = GetRandomBytes(8);
+ _ = new Guid(_int, _short1, _short2, _bArr[0], _bArr[1], _bArr[2], _bArr[3], _bArr[4], _bArr[5], _bArr[6], _bArr[7]);
}
[TestMethod]
@@ -174,11 +174,11 @@ public void UInt_Ushort_Constructor_Test7()
///
Random random = new Random();
- int randoInt = random.Next(Int32.MaxValue);
+ int randoInt = random.Next(int.MaxValue);
uint _uInt = (uint)(randoInt * 2);
ushort _uShort1 = (ushort)random.Next(65536);
ushort _uShort2 = (ushort)random.Next(65536);
- Byte[] _bArr = GetRandomBytes(8);
+ byte[] _bArr = GetRandomBytes(8);
Guid _guid = new Guid(_uInt, _uShort1, _uShort1, _bArr[0], _bArr[1], _bArr[2], _bArr[3], _bArr[4], _bArr[5], _bArr[6], _bArr[7]);
}
@@ -192,7 +192,7 @@ public void Guid_Empty_Test8()
///
///
Guid guid = Guid.Empty;
- Byte[] _bArr = guid.ToByteArray();
+ byte[] _bArr = guid.ToByteArray();
for (int i = 0; i < 16; i++)
{
Assert.AreEqual(_bArr[i], (byte)0);
@@ -211,26 +211,21 @@ public void Guid_CompareTo_Test9()
Guid guid1 = Guid.Empty;
// Verifing any instance of Guid, regardless of its value, is greater than null
Assert.AreEqual(guid1.CompareTo(null), 1);
- Byte[] _bArr = new Byte[16];
+ byte[] _bArr = new byte[16];
+
// Creating a Guid with all bytes zero
Guid guid2 = new Guid(_bArr);
Assert.AreEqual(guid1.CompareTo(guid2), 0);
+
Guid guid3 = new Guid(0x4dff36b5, 0x9dde, 0x4f76, 0x9a, 0x2a, 0x96, 0x43, 0x50, 0x47, 0x06, 0x3d);
- if (guid3.CompareTo(guid1) <= 0)
- {
- throw new Exception("Expected : " + guid3.ToString() + " is greater than " + guid1.ToString());
- }
+ Assert.IsTrue(guid3.CompareTo(guid1) > 0, "Expected : " + guid3.ToString() + " is greater than " + guid1.ToString());
+
Guid guid4 = new Guid(0x4dff36b5, 0x9dde, 0x4f76, 0x9a, 0x2a, 0x96, 0x43, 0x50, 0x47, 0x06, 0x3d);
Assert.AreEqual(guid4.CompareTo(guid3), 0);
+
Guid guid5 = new Guid(0x4dff36b5, 0x9dde, 0x4f76, 0x9a, 0x2a, 0x96, 0x43, 0x50, 0x47, 0x06, 0x3e);
- if (guid5.CompareTo(guid4) <= 0)
- {
- throw new Exception("Expected : " + guid5.ToString() + " is greater than " + guid4.ToString());
- }
- if (guid4.CompareTo(guid5) >= 0)
- {
- throw new Exception("Expected : " + guid4.ToString() + " is less than " + guid5.ToString());
- }
+ Assert.IsTrue(guid5.CompareTo(guid4) > 0, "Expected : " + guid5.ToString() + " is greater than " + guid4.ToString());
+ Assert.IsTrue(guid4.CompareTo(guid5) < 0, "Expected : " + guid4.ToString() + " is less than " + guid5.ToString());
}
[TestMethod]
@@ -242,25 +237,34 @@ public void Guid_ToString_Test10()
///
///
- String[] strArr1 = new String[] { "00000000-0000-0000-0000-000000000000",
+ string[] strArr1 = new string[]
+ {
+ "00000000-0000-0000-0000-000000000000",
"00000000-0000-0000-0000-000000000000",
"4dff36b5-9dde-4f76-9a2a-96435047063d",
- "ffffffff-ffff-ffff-ffff-ffffffffffff"};
+ "ffffffff-ffff-ffff-ffff-ffffffffffff"
+ };
+
Guid guid1 = Guid.Empty;
- Byte[] _byteArr1 = new Byte[16];
+ byte[] _byteArr1 = new byte[16];
Guid guid2 = new Guid(_byteArr1);
Guid guid3 = new Guid(0x4dff36b5, 0x9dde, 0x4f76, 0x9a, 0x2a, 0x96, 0x43, 0x50, 0x47, 0x06, 0x3d);
- Byte[] _byteArr2 = new Byte[16];
+
+ byte[] _byteArr2 = new byte[16];
+
for (int i = 0; i < _byteArr2.Length; i++)
{
- _byteArr2[i] = Byte.MaxValue;
+ _byteArr2[i] = byte.MaxValue;
}
+
Guid guid4 = new Guid(_byteArr2);
- String[] strArr2 = new String[] { guid1.ToString(), guid2.ToString(), guid3.ToString(), guid4.ToString() };
+
+ string[] strArr2 = new string[] { guid1.ToString(), guid2.ToString(), guid3.ToString(), guid4.ToString() };
+
for (int i = 0; i < strArr1.Length; i++)
{
OutputHelper.WriteLine(strArr1[i]);
- Assert.AreEqual(String.Compare(strArr1[i], strArr2[i]), 0);
+ Assert.AreEqual(string.Compare(strArr1[i], strArr2[i]), 0);
}
}
@@ -280,11 +284,14 @@ public void Guid_Equals_Test11()
Guid[] gArr1 = new Guid[] { guid11, guid12, guid13 };
// Creating Guids with 16 bytes constructor
- Byte[] _bArr1 = new Byte[16];
+ byte[] _bArr1 = new byte[16];
+
Guid guid21 = new Guid(_bArr1);
- Byte[] _bArr2 = new Byte[] { 181, 54, 255, 77, 222, 157, 118, 79, 154, 42, 150, 67, 80, 71, 6, 61 };
+ byte[] _bArr2 = new byte[] { 181, 54, 255, 77, 222, 157, 118, 79, 154, 42, 150, 67, 80, 71, 6, 61 };
+
Guid guid22 = new Guid(_bArr2);
- Byte[] _bArr3 = new Byte[] { 255, 255, 255, 127, 255, 127, 255, 127, 255, 255, 255, 255, 255, 255, 255, 255 };
+ byte[] _bArr3 = new byte[] { 255, 255, 255, 127, 255, 127, 255, 127, 255, 255, 255, 255, 255, 255, 255, 255 };
+
Guid guid23 = new Guid(_bArr3);
Guid[] gArr2 = new Guid[] { guid21, guid22, guid23 };
@@ -315,5 +322,120 @@ public void Guid_Equals_Test11()
}
}
+ [DataRow("00000000-0000-0000-0000-000000000000")]
+ [DataRow("4dff36b5-9dde-4f76-9a2a-96435047063d")]
+ [DataRow("ffffffff-ffff-ffff-ffff-ffffffffffff")]
+ [DataRow("a8a110d5-fc49-43c5-bf46-802db8f843ff")]
+ [DataRow("44332211-6655-8877-9900-aabbccddeeff")]
+ [DataRow("11223344-5566-7788-9900-aabbccddeeff")]
+ [TestMethod]
+ public void Ctor_FromString_Test00(string guidString)
+ {
+ ///
+ /// 1. Creates a Guid from a string
+ /// 2. Verifies the Guid is created correctly
+ ///
+
+ Guid guid = new Guid(guidString);
+
+ Assert.AreEqual(guidString, guid.ToString());
+ }
+ [DataRow("{00000000-0000-0000-0000-000000000000}")]
+ [DataRow("{4dff36b5-9dde-4f76-9a2a-96435047063d}")]
+ [DataRow("{ffffffff-ffff-ffff-ffff-ffffffffffff}")]
+ [DataRow("{a8a110d5-fc49-43c5-bf46-802db8f843ff}")]
+ [DataRow("{44332211-6655-8877-9900-aabbccddeeff}")]
+ [DataRow("{11223344-5566-7788-9900-aabbccddeeff}")]
+ [TestMethod]
+ public void Ctor_FromString_Test01(string guidString)
+ {
+ ///
+ /// 1. Creates a Guid from a string
+ /// 2. Verifies the Guid is created correctly
+ ///
+
+ Guid guid = new Guid(guidString);
+
+ Assert.AreEqual(guidString, $"{{{guid.ToString()}}}");
+ }
+
+ [TestMethod]
+ public void Ctor_FromString_Test02()
+ {
+ Guid testGuid = new Guid("a8a110d5-fc49-43c5-bf46-802db8f843ff");
+ Guid fullGuid = new Guid(uint.MaxValue, ushort.MaxValue, ushort.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
+
+ Assert.AreEqual(new Guid("ffffffff-ffff-ffff-ffff-ffffffffffff"), fullGuid);
+ Assert.AreEqual((new Guid("a8a110d5-fc49-43c5-bf46-802db8f843ff")).ToString(), testGuid.ToString());
+ }
+
+ [TestMethod]
+ public void Guid_ByteArray_Test()
+ {
+ object[][] testData = new object[][]
+ {
+ new object[] { Guid.Empty, new byte[16] },
+ new object[] { new Guid("44332211-6655-8877-9900-aabbccddeeff"), new byte[] { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } },
+ new object[] { new Guid("11223344-5566-7788-9900-aabbccddeeff"), new byte[] { 0x44, 0x33, 0x22, 0x11, 0x66, 0x55, 0x88, 0x77, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } },
+ new object[] { new Guid("a8a110d5-fc49-43c5-bf46-802db8f843ff"), new byte[] { 0xd5, 0x10, 0xa1, 0xa8, 0x49, 0xfc, 0xc5, 0x43, 0xbf, 0x46, 0x80, 0x2d, 0xb8, 0xf8, 0x43, 0xff } }
+ };
+
+ foreach (object[] item in testData)
+ {
+ Guid guid = new Guid((byte[])item[1]);
+
+ OutputHelper.WriteLine($"Actual: {guid}");
+ OutputHelper.WriteLine($"Expected: {item[0]}");
+
+ Assert.AreEqual(item[0], guid);
+ }
+ }
+
+ [TestMethod]
+ public void Ctor_NullByteArray_ThrowsArgumentNullException()
+ {
+ Assert.ThrowsException(
+ typeof(ArgumentNullException),
+ () => new Guid((byte[])null));
+ }
+
+ [DataRow(15)]
+ [DataRow(17)]
+ [TestMethod]
+ public void Ctor_InvalidLengthByteArray_ThrowsArgumentException(int length)
+ {
+ Assert.ThrowsException(
+ typeof(ArgumentException),
+ () => new Guid(new byte[length]));
+ }
+
+ [TestMethod]
+ public void Ctor_UInt_UShort_UShort_Byte_Byte_Byte_Byte_Byte_Byte_Byte_Byte()
+ {
+ Guid guid = new Guid(0xa8a110d5, 0xfc49, 0x43c5, 0xbf, 0x46, 0x80, 0x2d, 0xb8, 0xf8, 0x43, 0xff);
+ Assert.AreEqual(new Guid("a8a110d5-fc49-43c5-bf46-802db8f843ff"), guid);
+ }
+
+ [TestMethod]
+ public void NewGuid()
+ {
+ Guid guid1 = Guid.NewGuid();
+
+ Assert.AreNotEqual(Guid.Empty, guid1);
+ Assert.IsTrue((guid1.ToByteArray()[7] & 0xF0) == 0x40);
+
+ Guid guid2 = Guid.NewGuid();
+
+ Assert.AreNotEqual(guid1, guid2);
+ Assert.IsTrue((guid2.ToByteArray()[7] & 0xF0) == 0x40);
+ }
+
+ [TestMethod]
+ public void ToByteArray()
+ {
+ byte[] myGuidAsArray = new Guid("a8a110d5-fc49-43c5-bf46-802db8f843ff").ToByteArray();
+
+ CollectionAssert.AreEqual(new byte[] { 0xd5, 0x10, 0xa1, 0xa8, 0x49, 0xfc, 0xc5, 0x43, 0xbf, 0x46, 0x80, 0x2d, 0xb8, 0xf8, 0x43, 0xff }, myGuidAsArray);
+ }
}
}
diff --git a/nanoFramework.CoreLibrary/System/Guid.cs b/nanoFramework.CoreLibrary/System/Guid.cs
index 77794b6..6ccee86 100644
--- a/nanoFramework.CoreLibrary/System/Guid.cs
+++ b/nanoFramework.CoreLibrary/System/Guid.cs
@@ -135,12 +135,6 @@ public Guid(byte[] b)
///
/// A string that contains a GUID in one of the following formats ("d" represents a hexadecimal digit whose case is ignored):
///
- /// 32 contiguous hexadecimal digits:
- ///
- /// dddddddddddddddddddddddddddddddd
- ///
- /// -or-
- ///
/// Groups of 8, 4, 4, 4, and 12 hexadecimal digits with hyphens between the groups. The entire GUID can optionally be enclosed in matching braces or parentheses:
///
/// dddddddd-dddd-dddd-dddd-dddddddddddd
@@ -149,18 +143,6 @@ public Guid(byte[] b)
///
/// {dddddddd-dddd-dddd-dddd-dddddddddddd}
///
- /// -or-
- ///
- /// (dddddddd-dddd-dddd-dddd-dddddddddddd)
- ///
- /// -or-
- ///
- /// Groups of 8, 4, and 4 hexadecimal digits, and a subset of eight groups of 2 hexadecimal digits, with each group prefixed by "0x" or "0X", and separated by commas. The entire GUID, as well as the subset, is enclosed in matching braces:
- ///
- /// {0xdddddddd, 0xdddd, 0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}}
- ///
- /// All braces, commas, and "0x" prefixes are required. All embedded spaces are ignored. All leading zeros in a group are ignored.
- ///
/// The hexadecimal digits shown in a group are the maximum number of meaningful hexadecimal digits that can appear in that group. You can specify from 1 to the number of hexadecimal digits shown for a group. The specified digits are assumed to be the low-order digits of the group.
///
/// is ."
@@ -172,11 +154,13 @@ public Guid(string g)
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
if (!TryParseGuidWithDashes(
g,
- out this))
+ out Guid result))
{
throw new ArgumentException();
}
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one
+
+ this = result;
}
///
@@ -342,78 +326,114 @@ private static char HexToChar(int a)
}
///
- /// Creates a new based on the value in the string. The value is made up
- /// of hex digits speared by the dash ("-"). The string may begin and end with
- /// brackets ("{", "}").
- ///
- /// The string must be of the form dddddddd-dddd-dddd-dddd-dddddddddddd. where
- /// d is a hex digit. (That is 8 hex digits, followed by 4, then 4, then 4,
- /// then 12) such as: "CA761232-ED42-11CE-BACD-00AA0057B223"
+ /// Converts the string representation of a GUID to the equivalent structure.
///
- /// A string containing the GUID to convert.
+ /// A string containing the GUID to convert.
/// When this method returns, contains the parsed value. If the method returns , result contains a valid . If the method returns , result equals .
/// if the parse operation was successful; otherwise, .
+ ///
+ /// The .NET nanoFramework implementation of this method only supports 'D' and 'N' format specifiers.
+ ///
+ [Obsolete("This will be renamed to TryParse in a future version.")]
public static bool TryParseGuidWithDashes(
- string guidString,
+ string input,
out Guid result)
{
int startPos = 0;
- int temp;
- long templ;
- result = Empty;
- // check to see that it's the proper length
- if (guidString[0] == '{')
+ // because this is a struct we can't assign the Empty directly to result,
+ // otherwise it will overwrite the _data field of the struct, as this is a shallow copy
+ result = new Guid(Empty.ToByteArray());
+
+ // Check for optional surrounding braces
+ if (input[0] == '{')
{
- if (guidString.Length != 38 || guidString[37] != '}')
+ if (input.Length != 38 || input[37] != '}')
{
return false;
}
+
startPos = 1;
}
- else if (guidString.Length != 36)
+ else if (input.Length != 36)
{
return false;
}
- if (guidString[8 + startPos] != '-' ||
- guidString[13 + startPos] != '-' ||
- guidString[18 + startPos] != '-' ||
- guidString[23 + startPos] != '-')
+ // Verify hyphen positions
+ if (input[8 + startPos] != '-' ||
+ input[13 + startPos] != '-' ||
+ input[18 + startPos] != '-' ||
+ input[23 + startPos] != '-')
{
return false;
}
int currentPos = startPos;
+
try
{
- result._data[0] = (int)HexStringToLong(guidString, ref currentPos, 8);
+ // Data1: 8 hex digits
+ result._data[0] = (int)HexStringToLong(input, ref currentPos, 8);
- // Increment past the '-'
+ // Skip dash
++currentPos;
- result._data[1] = (ushort)HexStringToLong(guidString, ref currentPos, 4)
- | ((ushort)HexStringToLong(guidString, ref currentPos, 4) << 16);
+ // Data2: 4 hex digits
+ ushort data2 = (ushort)HexStringToLong(input, ref currentPos, 4);
- // Increment past the '-'
+ // Skip dash
++currentPos;
- temp = (int)HexStringToLong(guidString, ref currentPos, 4);
+ // Data3: 4 hex digits
+ ushort data3 = (ushort)HexStringToLong(input, ref currentPos, 4);
- // Increment past the '-'
+ // These values are already in big‑endian order as in the string
+ // They must be stored directly (without swapping) in the internal little‑endian representation
+ result._data[1] = data2 | (data3 << 16);
+
+ // Skip dash
++currentPos;
- templ = HexStringToLong(guidString, ref currentPos, 12);
+ // Data4 – first part: 4 hex digits (2 bytes)
+ ushort group4 = (ushort)HexStringToLong(input, ref currentPos, 4);
+
+ // Skip dash
+ ++currentPos;
+
+ // Data4 – second part: 12 hex digits (6 bytes)
+ long group5 = HexStringToLong(input, ref currentPos, 12);
+
+ // For Data4, we need to convert from big‑endian to little‑endian
+ // Swap the 2-byte group
+ ushort group4_le = (ushort)(((group4 & 0xFF) << 8) | (group4 >> 8));
+
+ // Split the 6-byte group into its high 2 bytes and low 4 bytes
+ // high 16 bits (big‑endian)
+ ushort group5High = (ushort)(group5 >> 32);
+
+ // low 32 bits (big‑endian)
+ uint group5Low = (uint)(group5 & 0xFFFFFFFF);
+
+ // Swap bytes for each
+ ushort group5High_le = (ushort)(((group5High & 0xFF) << 8) | (group5High >> 8));
+ uint group5Low_le = ((group5Low & 0xFF) << 24) |
+ (((group5Low >> 8) & 0xFF) << 16) |
+ (((group5Low >> 16) & 0xFF) << 8) |
+ ((group5Low >> 24) & 0xFF);
+
+ // Combine the converted Data4 parts into _data[2] and _data[3]
+ // _data[2]: lower 16 bits from swapped group4, upper 16 bits from swapped group5High
+ result._data[2] = group4_le | (group5High_le << 16);
+
+ // _data[3]: swapped group5Low
+ result._data[3] = (int)group5Low_le;
}
catch
{
- result = Empty;
return false;
}
- result._data[2] = temp | (int)(templ >> 32) << 16;
- result._data[3] = (int)templ;
-
return true;
}