Simplify method call
[NovacoinLibrary.git] / Novacoin / VarInt.cs
1 \feffusing System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Novacoin
8 {
9     public class VarInt
10     {
11         /// <summary>
12         /// Encodes unsigned integer value into compact representation.
13         /// 
14         /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
15         /// </summary>
16         /// <param name="n">Unsigned integer value</param>
17         /// <returns>Byte sequence</returns>
18         public static IList<byte> EncodeVarInt(ulong n)
19         {
20             List<byte> resultBytes = new List<byte>();
21
22             if (n <= 0xfc)
23             {
24                 // Values up to 0xfc are stored directly without any prefix
25                 resultBytes.Add((byte)n);
26             }
27             else
28             {
29                 byte prefix;
30                 byte[] valueBytes;
31
32                 if (n <= ushort.MaxValue)
33                 {
34                     // ushort flag
35                     prefix = 0xfd;
36                     valueBytes = Interop.LEBytes((ushort)n);
37                 }
38                 else if (n <= uint.MaxValue)
39                 {
40                     // uint flag
41                     prefix = 0xfe;
42                     valueBytes = Interop.LEBytes((uint)n);
43                 }
44                 else
45                 {
46                     // ulong flag
47                     prefix = 0xff;
48                     valueBytes = Interop.LEBytes(n);
49                 }
50
51                 resultBytes.Add(prefix);
52                 resultBytes.AddRange(valueBytes);
53             }
54
55             return resultBytes;
56         }
57
58         /// <summary>
59         /// Encodes integer value into compact representation.
60         /// 
61         /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
62         /// </summary>
63         /// <param name="n">Integer value</param>
64         /// <returns>Byte sequence</returns>
65         public static IList<byte> EncodeVarInt(long n)
66         {
67             return EncodeVarInt((ulong)n);
68         }
69
70         /// <summary>
71         /// Decodes integer value from compact representation
72         /// 
73         /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
74         /// </summary>
75         /// <param name="bytes">Byte sequence</param>
76         /// <returns>Integer value</returns>
77         public static ulong DecodeVarInt(IList<byte> bytes)
78         {
79             byte prefix = bytes[0];
80
81             bytes.RemoveAt(0); // Remove prefix
82
83             byte[] bytesArray = bytes.ToArray();
84
85             if (BitConverter.IsLittleEndian)
86             {
87                 switch (prefix)
88                 {
89                     case 0xfd: // ushort flag
90                         return BitConverter.ToUInt16(bytesArray, 0);
91                     case 0xfe: // uint flag
92                         return BitConverter.ToUInt32(bytesArray, 0);
93                     case 0xff: // ulong flag
94                         return BitConverter.ToUInt64(bytesArray, 0);
95                     default:
96                         return prefix;
97                 }
98             }
99             else
100             {
101                 // Values are stored in little-endian order
102                 switch (prefix)
103                 {
104                     case 0xfd: // ushort flag
105                         Array.Resize(ref bytesArray, 2);
106                         Array.Reverse(bytesArray);
107                         return BitConverter.ToUInt16(bytesArray, 0);
108                     case 0xfe: // uint flag
109                         Array.Resize(ref bytesArray, 4);
110                         Array.Reverse(bytesArray);
111                         return BitConverter.ToUInt32(bytesArray, 0);
112                     case 0xff: // ulong flag
113                         Array.Resize(ref bytesArray, 8);
114                         Array.Reverse(bytesArray);
115                         return BitConverter.ToUInt64(bytesArray, 0);
116                     default:
117                         return prefix;
118                 }
119             }
120         }
121
122         /// <summary>
123         /// Read and decode variable integer from wrapped list object.
124         /// 
125         /// Note: Should be used only if there is some variable integer data at current position. Otherwise you will get undefined behavior, so make sure that you know what you are doing.
126         /// </summary>
127         /// <param name="wBytes"></param>
128         /// <returns></returns>
129         public static ulong ReadVarInt(ref WrappedList<byte> wBytes)
130         {
131             byte prefix = wBytes.GetItem();
132
133             switch (prefix)
134             {
135                 case 0xfd: // ushort
136                     return Interop.LEBytesToUInt16(wBytes.GetItems(2));
137                 case 0xfe: // uint
138                     return Interop.LEBytesToUInt32(wBytes.GetItems(4));
139                 case 0xff: // ulong
140                     return Interop.LEBytesToUInt64(wBytes.GetItems(8));
141                 default:
142                     return prefix;
143             }
144
145         }
146     }
147 }