Skip to content

Commit 9dc9e47

Browse files
committed
Cleanup
1 parent 585aea1 commit 9dc9e47

File tree

1 file changed

+91
-138
lines changed

1 file changed

+91
-138
lines changed
Lines changed: 91 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,112 @@
11
using System;
2-
using System.Buffers;
3-
using System.Runtime.CompilerServices;
42
using DuckDB.NET.Native;
53

64
namespace DuckDB.NET.Data.Extensions;
75

86
internal static class GuidConverter
97
{
10-
#if !NET6_0_OR_GREATER
11-
private const string GuidFormat = "D";
12-
private static readonly char[] HexDigits = "0123456789abcdef".ToCharArray();
8+
private const int GuidSize = 16;
139

14-
//Ported from duckdb source code UUID::ToString
15-
//https://github.com/duckdb/duckdb/blob/9c91b3a329073ea1767b0aaff94b51da98dd03e2/src/common/types/uuid.cpp#L56
16-
public static Guid ConvertToGuid(this DuckDBHugeInt input)
10+
public static unsafe Guid ConvertToGuid(this DuckDBHugeInt input)
1711
{
18-
Span<char> buffer = stackalloc char[36];
19-
var num = input.Upper ^ long.MinValue;
20-
var position = 0;
21-
22-
ByteToHex(buffer, ref position, (ulong)((num >> 56) & 0xFF));
23-
ByteToHex(buffer, ref position, (ulong)((num >> 48) & 0xFF));
24-
ByteToHex(buffer, ref position, (ulong)((num >> 40) & 0xFF));
25-
ByteToHex(buffer, ref position, (ulong)((num >> 32) & 0xFF));
26-
27-
buffer[position++] = '-';
28-
29-
ByteToHex(buffer, ref position, (ulong)((num >> 24) & 0xFF));
30-
ByteToHex(buffer, ref position, (ulong)((num >> 16) & 0xFF));
31-
32-
buffer[position++] = '-';
33-
34-
ByteToHex(buffer, ref position, (ulong)((num >> 8) & 0xFF));
35-
ByteToHex(buffer, ref position, (ulong)(num & 0xFF));
36-
37-
buffer[position++] = '-';
38-
39-
ByteToHex(buffer, ref position, (input.Lower >> 56) & 0xFF);
40-
ByteToHex(buffer, ref position, (input.Lower >> 48) & 0xFF);
41-
42-
buffer[position++] = '-';
43-
44-
ByteToHex(buffer, ref position, (input.Lower >> 40) & 0xFF);
45-
ByteToHex(buffer, ref position, (input.Lower >> 32) & 0xFF);
46-
ByteToHex(buffer, ref position, (input.Lower >> 24) & 0xFF);
47-
ByteToHex(buffer, ref position, (input.Lower >> 16) & 0xFF);
48-
ByteToHex(buffer, ref position, (input.Lower >> 8) & 0xFF);
49-
ByteToHex(buffer, ref position, input.Lower & 0xFF);
50-
51-
return Guid.ParseExact(new string(buffer.ToArray()), GuidFormat);
52-
53-
static void ByteToHex(Span<char> buffer, ref int position, ulong value)
54-
{
55-
buffer[position++] = HexDigits[(value >> 4) & 0xF];
56-
buffer[position++] = HexDigits[value & 0xF];
57-
}
58-
}
12+
Span<byte> bytes = stackalloc byte[32];
13+
14+
// Reverse the bit flip on the upper 64 bits
15+
var upper = input.Upper ^ ((long)1 << 63);
16+
17+
#if NET6_0_OR_GREATER
18+
// Write upper 64 bits (bytes 0-7)
19+
BitConverter.TryWriteBytes(bytes[GuidSize..], upper);
20+
21+
// Write lower 64 bits (bytes 8-15)
22+
BitConverter.TryWriteBytes(bytes[(GuidSize + 8)..], input.Lower);
5923
#else
60-
public static Guid ConvertToGuid(this DuckDBHugeInt input)
61-
{
62-
var bytes = ArrayPool<byte>.Shared.Rent(32);
63-
try
64-
{
65-
// Reverse the bit flip on the upper 64 bits
66-
long upper = input.Upper ^ ((long)1 << 63);
67-
68-
// Write upper 64 bits (bytes 0-7)
69-
BitConverter.TryWriteBytes(bytes.AsSpan(16), upper);
70-
71-
// Write lower 64 bits (bytes 8-15)
72-
BitConverter.TryWriteBytes(bytes.AsSpan(16 + 8), input.Lower);
73-
74-
// Reconstruct the Guid bytes (reverse the original byte reordering)
75-
ReorderBytesForGuid();
76-
77-
// Create Guid from the first 16 bytes
78-
return new Guid(bytes.AsSpan(0, 16));
79-
}
80-
finally
81-
{
82-
ArrayPool<byte>.Shared.Return(bytes);
83-
}
84-
85-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
86-
void ReorderBytesForGuid()
87-
{
88-
// First 4 bytes (little-endian)
89-
bytes[6] = bytes[16 + 0];
90-
bytes[7] = bytes[16 + 1];
91-
bytes[4] = bytes[16 + 2];
92-
bytes[5] = bytes[16 + 3];
93-
94-
// Next 4 bytes (little-endian)
95-
bytes[0] = bytes[16 + 4];
96-
bytes[1] = bytes[16 + 5];
97-
bytes[2] = bytes[16 + 6];
98-
bytes[3] = bytes[16 + 7];
99-
100-
// Last 8 bytes (big-endian)
101-
bytes[15] = bytes[16 + 8];
102-
bytes[14] = bytes[16 + 9];
103-
bytes[13] = bytes[16 + 10];
104-
bytes[12] = bytes[16 + 11];
105-
bytes[11] = bytes[16 + 12];
106-
bytes[10] = bytes[16 + 13];
107-
bytes[9] = bytes[16 + 14];
108-
bytes[8] = bytes[16 + 15];
109-
}
110-
}
24+
var data = BitConverter.GetBytes(upper);
25+
data.CopyTo(bytes);
26+
27+
data = BitConverter.GetBytes(input.Lower);
28+
data.CopyTo(bytes.Slice(GuidSize + 8));
29+
#endif
30+
31+
// Reconstruct the Guid bytes (reverse the original byte reordering)
32+
33+
// First 4 bytes (little-endian)
34+
bytes[6] = bytes[GuidSize + 0];
35+
bytes[7] = bytes[GuidSize + 1];
36+
bytes[4] = bytes[GuidSize + 2];
37+
bytes[5] = bytes[GuidSize + 3];
38+
39+
// Next 4 bytes (little-endian)
40+
bytes[0] = bytes[GuidSize + 4];
41+
bytes[1] = bytes[GuidSize + 5];
42+
bytes[2] = bytes[GuidSize + 6];
43+
bytes[3] = bytes[GuidSize + 7];
44+
45+
// Last 8 bytes (big-endian)
46+
bytes[15] = bytes[GuidSize + 8];
47+
bytes[14] = bytes[GuidSize + 9];
48+
bytes[13] = bytes[GuidSize + 10];
49+
bytes[12] = bytes[GuidSize + 11];
50+
bytes[11] = bytes[GuidSize + 12];
51+
bytes[10] = bytes[GuidSize + 13];
52+
bytes[9] = bytes[GuidSize + 14];
53+
bytes[8] = bytes[GuidSize + 15];
54+
55+
// Create Guid from the first 16 bytes
56+
#if NET6_0_OR_GREATER
57+
return new Guid(bytes[..GuidSize]);
58+
#else
59+
return new Guid(bytes.Slice(0, GuidSize).ToArray());
11160
#endif
61+
}
62+
11263

11364
//https://github.com/duckdb/duckdb/blob/9c91b3a329073ea1767b0aaff94b51da98dd03e2/src/common/types/uuid.cpp#L6
11465
public static DuckDBHugeInt ToHugeInt(this Guid guid)
11566
{
116-
var bytes = ArrayPool<byte>.Shared.Rent(32);
67+
Span<byte> bytes = stackalloc byte[32];
11768

118-
try
119-
{
12069
#if NET6_0_OR_GREATER
121-
guid.TryWriteBytes(bytes);
70+
guid.TryWriteBytes(bytes);
12271
#else
123-
Buffer.BlockCopy(guid.ToByteArray(), 0, bytes, 0, 16);
72+
var byteArray = guid.ToByteArray();
73+
byteArray.AsSpan().CopyTo(bytes);
12474
#endif
125-
bytes[16 + 0] = bytes[6]; // First 4 bytes (little-endian)
126-
bytes[16 + 1] = bytes[7];
127-
bytes[16 + 2] = bytes[4];
128-
bytes[16 + 3] = bytes[5];
129-
bytes[16 + 4] = bytes[0]; // Next 4 bytes (little-endian)
130-
bytes[16 + 5] = bytes[1];
131-
bytes[16 + 6] = bytes[2];
132-
bytes[16 + 7] = bytes[3];
133-
134-
bytes[16 + 8] = bytes[15]; // Big endian
135-
bytes[16 + 9] = bytes[14];
136-
bytes[16 + 10] = bytes[13];
137-
bytes[16 + 11] = bytes[12];
138-
bytes[16 + 12] = bytes[11];
139-
bytes[16 + 13] = bytes[10];
140-
bytes[16 + 14] = bytes[9];
141-
bytes[16 + 15] = bytes[8];
142-
143-
// Upper 64 bits (bytes 0-7)
144-
long upper = BitConverter.ToInt64(bytes, 16 + 0);
145-
146-
// Lower 64 bits (bytes 8-15)
147-
ulong lower = BitConverter.ToUInt64(bytes, 16 + 8);
148-
149-
// Flip the first bit to make `order by uuid` same as `order by uuid::varchar`
150-
upper ^= ((long)1 << 63);
151-
152-
return new DuckDBHugeInt(lower, upper);
153-
}
154-
finally
155-
{
156-
ArrayPool<byte>.Shared.Return(bytes);
157-
}
75+
bytes[GuidSize + 0] = bytes[6]; // First 4 bytes (little-endian)
76+
bytes[GuidSize + 1] = bytes[7];
77+
bytes[GuidSize + 2] = bytes[4];
78+
bytes[GuidSize + 3] = bytes[5];
79+
80+
bytes[GuidSize + 4] = bytes[0]; // Next 4 bytes (little-endian)
81+
bytes[GuidSize + 5] = bytes[1];
82+
bytes[GuidSize + 6] = bytes[2];
83+
bytes[GuidSize + 7] = bytes[3];
84+
85+
bytes[GuidSize + 8] = bytes[15]; // Big endian
86+
bytes[GuidSize + 9] = bytes[14];
87+
bytes[GuidSize + 10] = bytes[13];
88+
bytes[GuidSize + 11] = bytes[12];
89+
bytes[GuidSize + 12] = bytes[11];
90+
bytes[GuidSize + 13] = bytes[10];
91+
bytes[GuidSize + 14] = bytes[9];
92+
bytes[GuidSize + 15] = bytes[8];
93+
94+
#if NET6_0_OR_GREATER
95+
// Upper 64 bits (bytes 0-7)
96+
long upper = BitConverter.ToInt64(bytes[GuidSize..]);
97+
98+
// Lower 64 bits (bytes 8-15)
99+
ulong lower = BitConverter.ToUInt64(bytes[(GuidSize + 8)..]);
100+
#else
101+
var array = bytes.ToArray();
102+
103+
long upper = BitConverter.ToInt64(array, GuidSize);
104+
ulong lower = BitConverter.ToUInt64(array, GuidSize + 8);
105+
#endif
106+
107+
// Flip the first bit to make `order by uuid` same as `order by uuid::varchar`
108+
upper ^= (long)1 << 63;
109+
110+
return new DuckDBHugeInt(lower, upper);
158111
}
159112
}

0 commit comments

Comments
 (0)