-
Notifications
You must be signed in to change notification settings - Fork 396
Expand file tree
/
Copy pathNodeUuid.cs
More file actions
206 lines (169 loc) · 4.37 KB
/
NodeUuid.cs
File metadata and controls
206 lines (169 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
using System;
using System.Diagnostics.Contracts;
namespace ReClassNET.Nodes
{
public sealed class NodeUuid : IComparable<NodeUuid>, IEquatable<NodeUuid>
{
/// <summary>Size in bytes of a UUID.</summary>
public const int UuidSize = 16;
/// <summary>Zero UUID (all bytes are zero).</summary>
public static readonly NodeUuid Zero = new NodeUuid(false);
/// <summary>The maximum reserved UUID value.</summary>
private static readonly NodeUuid maxReserved = new NodeUuid(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF });
/// <summary>Checks if the given UUID is reserved.</summary>
/// <param name="uuid">The uuid.</param>
/// <returns>True if reserved, false if not.</returns>
public static bool IsReserved(NodeUuid uuid)
{
Contract.Requires(uuid != null);
return uuid.CompareTo(maxReserved) <= 0;
}
private byte[] uuidBytes;
private readonly int uuidHash;
/// <summary>Get the 16 UUID bytes.</summary>
public byte[] UuidBytes => uuidBytes;
/// <summary>Construct a new UUID object.</summary>
/// <param name="createNew">If this parameter is <c>true</c>, a new UUID is generated.
/// If it is <c>false</c>, the UUID is initialized to zero.</param>
public NodeUuid(bool createNew)
{
Contract.Ensures(uuidBytes != null);
if (createNew)
{
CreateNew();
}
else
{
SetZero();
}
uuidHash = CalculateHash();
}
/// <summary>Construct a new UUID object.</summary>
/// <param name="valueBytes">Initial value of the <see cref="NodeUuid"/> object.</param>
private NodeUuid(byte[] valueBytes)
{
Contract.Requires(valueBytes != null);
Contract.Requires(valueBytes.Length == UuidSize);
Contract.Ensures(uuidBytes != null);
SetValue(valueBytes);
uuidHash = CalculateHash();
}
public static NodeUuid FromBase64String(string base64, bool createNew)
{
try
{
if (base64 != null)
{
var bytes = Convert.FromBase64String(base64);
if (bytes.Length == UuidSize)
{
return new NodeUuid(bytes);
}
}
}
catch (ArgumentNullException)
{
}
return new NodeUuid(createNew);
}
/// <summary>Create a new, random UUID.</summary>
/// <returns>Returns <c>true</c> if a random UUID has been generated, otherwise it returns <c>false</c>.</returns>
private void CreateNew()
{
Contract.Ensures(uuidBytes != null);
while (true)
{
uuidBytes = Guid.NewGuid().ToByteArray();
if (uuidBytes == null || uuidBytes.Length != UuidSize)
{
throw new InvalidOperationException();
}
// Do not generate reserved UUIDs.
if (!IsReserved(this))
{
break;
}
}
}
/// <summary>Sets the UUID to the given value.</summary>
/// <param name="valueBytes">Initial value of the <see cref="NodeUuid"/> object.</param>
private void SetValue(byte[] valueBytes)
{
Contract.Requires(valueBytes != null);
Contract.Requires(valueBytes.Length == UuidSize);
Contract.Ensures(uuidBytes != null);
uuidBytes = new byte[UuidSize];
Array.Copy(valueBytes, uuidBytes, UuidSize);
}
/// <summary>Sets the UUID to zero.</summary>
private void SetZero()
{
Contract.Ensures(uuidBytes != null);
uuidBytes = new byte[UuidSize];
}
public override bool Equals(object obj)
{
return Equals(obj as NodeUuid);
}
public bool Equals(NodeUuid other)
{
if (other == null)
{
return false;
}
for (var i = 0; i < UuidSize; ++i)
{
if (uuidBytes[i] != other.uuidBytes[i])
{
return false;
}
}
return true;
}
private int CalculateHash()
{
var hash = 17;
unchecked
{
foreach (var b in uuidBytes)
{
hash = hash * 31 + b.GetHashCode();
}
}
return hash;
}
public override int GetHashCode()
{
return uuidHash;
}
public int CompareTo(NodeUuid other)
{
for (var i = 0; i < UuidSize; ++i)
{
if (uuidBytes[i] < other.uuidBytes[i])
{
return -1;
}
if (uuidBytes[i] > other.uuidBytes[i])
{
return 1;
}
}
return 0;
}
public string ToBase64String()
{
return Convert.ToBase64String(uuidBytes);
}
/// <summary>Convert the UUID to its string representation.</summary>
/// <returns>String containing the UUID value.</returns>
public string ToHexString()
{
return BitConverter.ToString(uuidBytes).Replace("-", string.Empty);
}
public override string ToString()
{
return ToHexString();
}
}
}