1 /*
2  * This file was automatically generated by sel-utils and
3  * released under the MIT License.
4  * 
5  * License: https://github.com/sel-project/sel-utils/blob/master/LICENSE
6  * Repository: https://github.com/sel-project/sel-utils
7  */
8 
9 module sul.utils.var;
10 
11 import std.traits : isNumeric, isIntegral, isSigned, isUnsigned, Unsigned;
12 
13 struct var(T) if(isNumeric!T && isIntegral!T && T.sizeof > 1) {
14 	
15 	alias U = Unsigned!T;
16 	
17 	public static immutable U MASK = U.max - 0x7F;
18 	public static immutable size_t MAX_BYTES = T.sizeof * 8 / 7 + (T.sizeof * 8 % 7 == 0 ? 0 : 1);
19 	public static immutable size_t RIGHT_SHIFT = (T.sizeof * 8) - 1;
20 	
21 	public static pure nothrow @safe ubyte[] encode(T value) {
22 		ubyte[] buffer;
23 		static if(isUnsigned!T) {
24 			U unsigned = value;
25 		} else {
26 			U unsigned;
27 			if(value >= 0) {
28 				unsigned = cast(U)(value << 1);
29 			} else if(value < 0) {
30 				unsigned = cast(U)((-value << 1) - 1);
31 			}
32 		}
33 		while((unsigned & MASK) != 0) {
34 			buffer ~= unsigned & 0x7F | 0x80;
35 			unsigned >>>= 7;
36 		}
37 		buffer ~= unsigned & 0xFF;
38 		return buffer;
39 	}
40 
41 	public static pure nothrow @trusted T decode(ubyte[] buffer, size_t index=0) {
42 		return decode(buffer, &index);
43 	}
44 	
45 	public static pure nothrow @safe T decode(ubyte[] buffer, size_t* index) {
46 		if(buffer.length <= *index) return T.init;
47 		U unsigned = 0;
48 		size_t j, k;
49 		do {
50 			k = buffer[*index];
51 			unsigned |= cast(U)(k & 0x7F) << (j++ * 7);
52 		} while(++*index < buffer.length && j < MAX_BYTES && (k & 0x80) != 0);
53 		static if(isUnsigned!T) {
54 			return unsigned;
55 		} else {
56 			T value = unsigned >> 1;
57 			if(unsigned & 1) {
58 				value++;
59 				return -value;
60 			} else {
61 				return value;
62 			}
63 		}
64 	}
65 
66 	public static pure nothrow @trusted T fromBuffer(ref ubyte[] buffer) {
67 		size_t index = 0;
68 		auto ret = decode(buffer, &index);
69 		buffer = buffer[index..$];
70 		return ret;
71 	}
72 	
73 	public enum stringof = "var" ~ T.stringof;
74 	
75 }
76 
77 alias varshort = var!short;
78 
79 alias varushort = var!ushort;
80 
81 alias varint = var!int;
82 
83 alias varuint = var!uint;
84 
85 alias varlong = var!long;
86 
87 alias varulong = var!ulong;
88