Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import std.traits;
- import std.exception;
- import std.stdio;
- pure bool msbIsSet( const ubyte* a )
- {
- import core.bitop: bt;
- return bt( cast(size_t*) a, 7 ) != 0;
- }
- unittest
- {
- ubyte t_neg = 0b_00000000;
- ubyte t_pos = 0b_10000000;
- assert( msbIsSet( &t_neg ) == false );
- assert( msbIsSet( &t_pos ) == true );
- }
- static
- ubyte[] packVarint(T)( T value )
- if( isIntegral!T && isUnsigned!T )
- out( arr )
- {
- T d;
- size_t size = d.unpackVarint( &arr[0] );
- writeln( "out contract, type=", typeid(T), " isUnsigned=", isUnsigned!T, " arg=", value, " result=", arr );
- stdout.flush;
- assert( size == arr.length );
- //assert( d == value );
- }
- body
- {
- writeln( "value inside of body: ", value, " type=", typeid( typeof(value) ) );
- stdout.flush;
- ubyte[] res;
- immutable ubyte maximal = 0b_1000_0000;
- while( value >= maximal )
- {
- res ~= cast( ubyte )( value | maximal );
- value >>= 7;
- }
- import std.conv: to;
- res ~= to!( ubyte )( value );
- return res;
- }
- unittest
- {
- auto v = packVarint!ulong( 300 );
- assert( v.length == 2 );
- assert( v == [ 0b_10101100, 0b_00000010 ] );
- }
- pure size_t unpackVarint( T )( out T result, inout ubyte* data )
- if( isIntegral!T && isUnsigned!T )
- {
- size_t i;
- size_t res; // big sized type used also for overflow checking
- do {
- res |= ( data[i] & 0b_0111_1111 ) << 7 * i;
- enforce( res <= T.max, "Varint is too big for type " ~ T.stringof );
- } while( msbIsSet( &data[i++] ) );
- result = cast(T) res;
- return i;
- }
- unittest
- {
- ubyte d[2] = [ 0b_10101100, 0b_00000010 ];
- size_t result;
- assert( result.unpackVarint( &d[0] ) == d.length );
- assert( result == 300 );
- }
- void main()
- {
- packVarint( cast(ulong) 2 );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement