1 2 module markov.binary.decoder; 3 4 import markov.chain; 5 import markov.counter; 6 import markov.serialize; 7 import markov.state; 8 9 import std.algorithm; 10 import std.array; 11 import std.bitmanip; 12 import std.conv; 13 import std.range; 14 import std.stdio; 15 import std.traits; 16 17 struct BinaryDecoder(T) 18 if(isDecodable!(T, ubyte[])) 19 { 20 public: 21 MarkovChain!T decode()(ubyte[] input) 22 { 23 auto range = inputRangeObject(input); 24 return decode(range); 25 } 26 27 MarkovChain!T decode(Range)(ref Range input) 28 if(isInputRange!Range && is(ElementType!Range : ubyte)) 29 { 30 return MarkovChain!(T)(decodeStates(input)); 31 } 32 33 State!T[] decodeStates(Range)(ref Range input) 34 if(isInputRange!Range && is(ElementType!Range : ubyte)) 35 { 36 uint count = decodeValue!(uint)(input); 37 return iota(0, count).map!(i => decodeState(input)).array; 38 } 39 40 State!T decodeState(Range)(ref Range input) 41 if(isInputRange!Range && is(ElementType!Range : ubyte)) 42 { 43 State!T state = State!T(decodeValue!(uint)(input)); 44 uint length = decodeValue!(uint)(input); 45 46 foreach(i; 0 .. length) 47 { 48 state.set( 49 decodeTokens(input), 50 decodeCounter(input) 51 ); 52 } 53 54 return state; 55 } 56 57 Counter!T decodeCounter(Range)(ref Range input) 58 if(isInputRange!Range && is(ElementType!Range : ubyte)) 59 { 60 Counter!T counter; 61 uint length = decodeValue!(uint)(input); 62 63 foreach(i; 0 .. length) 64 { 65 counter.set( 66 decodeToken(input), 67 decodeValue!(uint)(input) 68 ); 69 } 70 71 return counter; 72 } 73 74 private: 75 Type decodeValue(Type, Range)(ref Range input) 76 if(isInputRange!Range && is(ElementType!Range : ubyte) && isSomeString!Type) 77 { 78 // TODO : Handle wide strings. 79 uint length = decodeValue!(uint)(input); 80 return input.take(length).map!(b => b.to!char).array.idup; 81 } 82 83 Type decodeValue(Type, Range)(ref Range input) 84 if(isInputRange!Range && is(ElementType!Range : ubyte) && isArray!Type && !isSomeString!Type) 85 { 86 uint length = decodeValue!(uint)(input); 87 return iota(0, length).map!(i => decodeValue!(ElementType!Type)(input)).array; 88 } 89 90 Type decodeValue(Type, Range)(ref Range input) 91 if(isInputRange!Range && is(ElementType!Range : ubyte) && isArray!Type && !isSomeString!Type) 92 { 93 ValueType!Type[KeyType!Type] data; 94 uint length = decodeValue!(uint)(input); 95 96 foreach(i; 0 .. length) 97 { 98 data[decodeValue!(KeyType!Type)(input)] = decodeValue!(ValueType!Type)(input); 99 } 100 101 return data; 102 } 103 104 Type decodeValue(Type, Range)(ref Range input) 105 if(isInputRange!Range && is(ElementType!Range : ubyte) && isNumeric!Type) 106 { 107 ubyte[Type.sizeof] b = input.take(Type.sizeof).array[0 .. Type.sizeof]; 108 return b.bigEndianToNative!Type; 109 } 110 111 Type decodeValue(Type, Range)(ref Range input) 112 if(isInputRange!Range && is(ElementType!Range : ubyte) && isBoolean!Type) 113 { 114 scope(exit) input.popFront; 115 return !!input.front; 116 } 117 118 T decodeToken(Range)(ref Range input) 119 if(isInputRange!Range && is(ElementType!Range : ubyte)) 120 { 121 static if(hasDecodeProperty!(T, ubyte[])) 122 { 123 return T.decode(input.table(T.sizeof)); 124 } 125 else 126 { 127 return decodeValue!(T)(input); 128 } 129 } 130 131 T[] decodeTokens(Range)(ref Range input) 132 if(isInputRange!Range && is(ElementType!Range : ubyte)) 133 { 134 uint count = decodeValue!(uint)(input); 135 return iota(0, count).map!(i => decodeToken(input)).array; 136 } 137 } 138 139 MarkovChain!T decodeBinary(T)(ubyte[] encoded) 140 { 141 BinaryDecoder!T decoder; 142 return decoder.decode(encoded); 143 } 144 145 MarkovChain!T decodeBinary(T, Range)(ref Range input) 146 if(isInputRange!Range && is(ElementType!Range : ubyte)) 147 { 148 BinaryDecoder!T decoder; 149 return decoder.decode(input); 150 } 151 152 MarkovChain!T decodeBinary(T)(File input) 153 { 154 static struct FileInputRange 155 { 156 ubyte[] _buffer; 157 File _file; 158 159 this(File file) 160 { 161 _file = file; 162 _buffer = [ 0 ]; 163 164 if(!empty) popFront; 165 } 166 167 @property 168 bool empty() 169 { 170 return _file.eof || _file.error; 171 } 172 173 @property 174 ubyte front() 175 { 176 return _buffer.length ? _buffer[0] : 0; 177 } 178 179 void popFront() 180 { 181 _file.rawRead(_buffer); 182 } 183 } 184 185 BinaryDecoder!T decoder; 186 auto range = FileInputRange(input); 187 188 return decoder.decode(range); 189 }