PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/MassTransit/NewId/NewId.cs

http://github.com/phatboyg/MassTransit
C# | 354 lines | 280 code | 53 blank | 21 comment | 60 complexity | 3d64cddb9aa9fe8fd117d09489d10c38 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, LGPL-2.1
  1. // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  4. // this file except in compliance with the License. You may obtain a copy of the
  5. // License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software distributed
  10. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  11. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  12. // specific language governing permissions and limitations under the License.
  13. namespace MassTransit
  14. {
  15. using System;
  16. using NewIdFormatters;
  17. using NewIdProviders;
  18. /// <summary>
  19. /// A NewId is a type that fits into the same space as a Guid/Uuid/uniqueidentifier,
  20. /// but is guaranteed to be both unique and ordered, assuming it is generated using
  21. /// a single instance of the generator for each network address used.
  22. /// </summary>
  23. public struct NewId :
  24. IEquatable<NewId>,
  25. IComparable<NewId>,
  26. IComparable,
  27. IFormattable
  28. {
  29. public static readonly NewId Empty = new NewId(0, 0, 0, 0);
  30. static INewIdFormatter _braceFormatter = new DashedHexFormatter('{', '}');
  31. static INewIdFormatter _dashedHexFormatter = new DashedHexFormatter();
  32. static NewIdGenerator _generator;
  33. static INewIdFormatter _hexFormatter = new HexFormatter();
  34. static INewIdFormatter _parenFormatter = new DashedHexFormatter('(', ')');
  35. static ITickProvider _tickProvider;
  36. static IWorkerIdProvider _workerIdProvider;
  37. readonly Int32 _a;
  38. readonly Int32 _b;
  39. readonly Int32 _c;
  40. readonly Int32 _d;
  41. /// <summary>
  42. /// Creates a NewId using the specified byte array.
  43. /// </summary>
  44. /// <param name="bytes"></param>
  45. public NewId(byte[] bytes)
  46. {
  47. if (bytes == null)
  48. throw new ArgumentNullException("bytes");
  49. if (bytes.Length != 16)
  50. throw new ArgumentException("Exactly 16 bytes expected", "bytes");
  51. FromByteArray(bytes, out _a, out _b, out _c, out _d);
  52. }
  53. public NewId(string value)
  54. {
  55. if(string.IsNullOrEmpty(value))
  56. throw new ArgumentException("must not be null or empty", "value");
  57. var guid = new Guid(value);
  58. byte[] bytes = guid.ToByteArray();
  59. FromByteArray(bytes, out _a, out _b, out _c, out _d);
  60. }
  61. public NewId(int a, int b, int c, int d)
  62. {
  63. _a = a;
  64. _b = b;
  65. _c = c;
  66. _d = d;
  67. }
  68. public NewId(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
  69. {
  70. _a = (f << 24) | (g << 16) | (h << 8) | i;
  71. _b = (j << 24) | (k << 16) | (d << 8) | e;
  72. _c = (c << 16) | b;
  73. _d = a;
  74. }
  75. static NewIdGenerator Generator
  76. {
  77. get { return _generator ?? (_generator = new NewIdGenerator(TickProvider, WorkerIdProvider)); }
  78. }
  79. static IWorkerIdProvider WorkerIdProvider
  80. {
  81. get { return _workerIdProvider ?? (_workerIdProvider = new BestPossibleWorkerIdProvider()); }
  82. }
  83. static ITickProvider TickProvider
  84. {
  85. get { return _tickProvider ?? (_tickProvider = new StopwatchTickProvider()); }
  86. }
  87. public DateTime Timestamp
  88. {
  89. get
  90. {
  91. var ticks = (long)(((ulong)_a) << 32 | (uint)_b);
  92. return new DateTime(ticks, DateTimeKind.Utc);
  93. }
  94. }
  95. public int CompareTo(object obj)
  96. {
  97. if (obj == null)
  98. return 1;
  99. if (!(obj is NewId))
  100. throw new ArgumentException("Argument must be a NewId");
  101. return CompareTo((NewId)obj);
  102. }
  103. public int CompareTo(NewId other)
  104. {
  105. if (_a != other._a)
  106. return ((uint)_a < (uint)other._a) ? -1 : 1;
  107. if (_b != other._b)
  108. return ((uint)_b < (uint)other._b) ? -1 : 1;
  109. if (_c != other._c)
  110. return ((uint)_c < (uint)other._c) ? -1 : 1;
  111. if (_d != other._d)
  112. return ((uint)_d < (uint)other._d) ? -1 : 1;
  113. return 0;
  114. }
  115. public bool Equals(NewId other)
  116. {
  117. return other._a == _a && other._b == _b && other._c == _c && other._d == _d;
  118. }
  119. public string ToString(string format, IFormatProvider formatProvider)
  120. {
  121. if (string.IsNullOrEmpty(format))
  122. format = "D";
  123. bool sequential = false;
  124. if (format.Length == 2 && (format[1] == 'S' || format[1] == 's'))
  125. sequential = true;
  126. else if (format.Length != 1)
  127. throw new FormatException("The format string must be exactly one character or null");
  128. char formatCh = format[0];
  129. byte[] bytes = sequential ? GetSequentialFormatteryArray() : GetFormatteryArray();
  130. if (formatCh == 'B' || formatCh == 'b')
  131. return _braceFormatter.Format(bytes);
  132. if (formatCh == 'P' || formatCh == 'p')
  133. return _parenFormatter.Format(bytes);
  134. if (formatCh == 'D' || formatCh == 'd')
  135. return _dashedHexFormatter.Format(bytes);
  136. if (formatCh == 'N' || formatCh == 'n')
  137. return _hexFormatter.Format(bytes);
  138. throw new FormatException("The format string was not valid");
  139. }
  140. public string ToString(INewIdFormatter formatter, bool sequential = false)
  141. {
  142. byte[] bytes = sequential ? GetSequentialFormatteryArray() : GetFormatteryArray();
  143. return formatter.Format(bytes);
  144. }
  145. byte[] GetFormatteryArray()
  146. {
  147. var bytes = new byte[16];
  148. bytes[0] = (byte)(_d >> 24);
  149. bytes[1] = (byte)(_d >> 16);
  150. bytes[2] = (byte)(_d >> 8);
  151. bytes[3] = (byte)_d;
  152. bytes[4] = (byte)(_c >> 8);
  153. bytes[5] = (byte)_c;
  154. bytes[6] = (byte)(_c >> 24);
  155. bytes[7] = (byte)(_c >> 16);
  156. bytes[8] = (byte)(_b >> 8);
  157. bytes[9] = (byte)_b;
  158. bytes[10] = (byte)(_a >> 24);
  159. bytes[11] = (byte)(_a >> 16);
  160. bytes[12] = (byte)(_a >> 8);
  161. bytes[13] = (byte)_a;
  162. bytes[14] = (byte)(_b >> 24);
  163. bytes[15] = (byte)(_b >> 16);
  164. return bytes;
  165. }
  166. byte[] GetSequentialFormatteryArray()
  167. {
  168. var bytes = new byte[16];
  169. bytes[0] = (byte)(_a >> 24);
  170. bytes[1] = (byte)(_a >> 16);
  171. bytes[2] = (byte)(_a >> 8);
  172. bytes[3] = (byte)_a;
  173. bytes[4] = (byte)(_b >> 24);
  174. bytes[5] = (byte)(_b >> 16);
  175. bytes[6] = (byte)(_b >> 8);
  176. bytes[7] = (byte)_b;
  177. bytes[8] = (byte)(_c >> 24);
  178. bytes[9] = (byte)(_c >> 16);
  179. bytes[10] = (byte)(_c >> 8);
  180. bytes[11] = (byte)_c;
  181. bytes[12] = (byte)(_d >> 24);
  182. bytes[13] = (byte)(_d >> 16);
  183. bytes[14] = (byte)(_d >> 8);
  184. bytes[15] = (byte)_d;
  185. return bytes;
  186. }
  187. public Guid ToGuid()
  188. {
  189. int a = _d;
  190. var b = (short)_c;
  191. var c = (short)(_c >> 16);
  192. var d = (byte)(_b >> 8);
  193. var e = (byte)_b;
  194. var f = (byte)(_a >> 24);
  195. var g = (byte)(_a >> 16);
  196. var h = (byte)(_a >> 8);
  197. var i = (byte)_a;
  198. var j = (byte)(_b >> 24);
  199. var k = (byte)(_b >> 16);
  200. return new Guid(a, b, c, d, e, f, g, h, i, j, k);
  201. }
  202. public Guid ToSequentialGuid()
  203. {
  204. int a = _a;
  205. var b = (short)(_b >> 16);
  206. var c = (short)_b;
  207. var d = (byte)(_c >> 24);
  208. var e = (byte)(_c >> 16);
  209. var f = (byte)(_c >> 8);
  210. var g = (byte)(_c);
  211. var h = (byte)(_d >> 24);
  212. var i = (byte)(_d >> 16);
  213. var j = (byte)(_d >> 8);
  214. var k = (byte)(_d);
  215. return new Guid(a, b, c, d, e, f, g, h, i, j, k);
  216. }
  217. public byte[] ToByteArray()
  218. {
  219. var bytes = new byte[16];
  220. bytes[0] = (byte)(_d);
  221. bytes[1] = (byte)(_d >> 8);
  222. bytes[2] = (byte)(_d >> 16);
  223. bytes[3] = (byte)(_d >> 24);
  224. bytes[4] = (byte)(_c);
  225. bytes[5] = (byte)(_c >> 8);
  226. bytes[6] = (byte)(_c >> 16);
  227. bytes[7] = (byte)(_c >> 24);
  228. bytes[8] = (byte)(_b >> 8);
  229. bytes[9] = (byte)(_b);
  230. bytes[10] = (byte)(_a >> 24);
  231. bytes[11] = (byte)(_a >> 16);
  232. bytes[12] = (byte)(_a >> 8);
  233. bytes[13] = (byte)(_a);
  234. bytes[14] = (byte)(_b >> 24);
  235. bytes[15] = (byte)(_b >> 16);
  236. return bytes;
  237. }
  238. public override string ToString()
  239. {
  240. return ToString("D", null);
  241. }
  242. public string ToString(string format)
  243. {
  244. return ToString(format, null);
  245. }
  246. public override bool Equals(object obj)
  247. {
  248. if (ReferenceEquals(null, obj))
  249. return false;
  250. if (obj.GetType() != typeof(NewId))
  251. return false;
  252. return Equals((NewId)obj);
  253. }
  254. public override int GetHashCode()
  255. {
  256. unchecked
  257. {
  258. int result = _a;
  259. result = (result * 397) ^ _b;
  260. result = (result * 397) ^ _c;
  261. result = (result * 397) ^ _d;
  262. return result;
  263. }
  264. }
  265. public static bool operator ==(NewId left, NewId right)
  266. {
  267. return left._a == right._a && left._b == right._b && left._c == right._c && left._d == right._d;
  268. }
  269. public static bool operator !=(NewId left, NewId right)
  270. {
  271. return !(left == right);
  272. }
  273. public static void SetGenerator(NewIdGenerator generator)
  274. {
  275. _generator = generator;
  276. }
  277. public static void SetWorkerIdProvider(IWorkerIdProvider provider)
  278. {
  279. _workerIdProvider = provider;
  280. }
  281. public static void SetTickProvider(ITickProvider provider)
  282. {
  283. _tickProvider = provider;
  284. }
  285. public static NewId Next()
  286. {
  287. return Generator.Next();
  288. }
  289. public static Guid NextGuid()
  290. {
  291. return Generator.Next().ToGuid();
  292. }
  293. static void FromByteArray(byte[] bytes, out Int32 a, out Int32 b, out Int32 c, out Int32 d)
  294. {
  295. a = bytes[10] << 24 | bytes[11] << 16 | bytes[12] << 8 | bytes[13];
  296. b = bytes[14] << 24 | bytes[15] << 16 | bytes[8] << 8 | bytes[9];
  297. c = bytes[7] << 24 | bytes[6] << 16 | bytes[5] << 8 | bytes[4];
  298. d = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
  299. }
  300. }
  301. }