1 /** Codecs. 2 Copyright: Per Nordlöw 2018-. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: $(WEB Per Nordlöw) 5 */ 6 module nxt.codec; 7 8 import std.typecons : Tuple; 9 import std.range.primitives : front, isInputRange, ElementType; 10 import std.array : array; 11 import nxt.algorithm_ex : forwardDifference; 12 13 /** Packing of $(D r) using a `forwardDifference`. 14 Used to pack elements of type ptrdiff, times, etc. 15 */ 16 struct ForwardDifferenceCode(R) if (isInputRange!R) 17 { 18 this(R r) 19 { 20 _front = r.front; 21 _diff = r.forwardDifference.array; // TODO: Can we make msgpack pack r.forwardDifference without .array 22 } 23 private: 24 typeof(R.init.front) _front; // First element 25 typeof(R.init.forwardDifference.array) _diff; // The Difference 26 } 27 28 /** Instantiator for $(D ForwardDifferenceCode). 29 */ 30 auto encodeForwardDifference(R)(R r) if (isInputRange!R) 31 { 32 return ForwardDifferenceCode!R(r); // TODO: Use named parts? 33 } 34 35 // version = use_msgpack; 36 37 unittest 38 { 39 import std.range: dropOne; 40 import core.exception: AssertError; 41 import std.exception: assertThrown; 42 version(use_msgpack) import msgpack; 43 44 assertThrown!AssertError([1].dropOne.encodeForwardDifference_alt); 45 46 auto x = [1, int.min, 22, 0, int.max, -1100]; 47 48 auto fdp = x.encodeForwardDifference; 49 50 version(use_msgpack) 51 { 52 alias FDP = typeof(fdp); 53 54 auto raw = fdp.pack; 55 auto raw2 = raw.dup; 56 57 FDP fdp_; // restored 58 aw.unpack(fdp_); // restore it 59 assert(fdp == fdp_); 60 61 auto fdp__ = raw2.unpack!FDP; // restore it (alternatively) 62 assert(fdp == fdp__); 63 } 64 } 65 66 /** Alternative. */ 67 auto encodeForwardDifference_alt(R)(R r) if (isInputRange!R) 68 { 69 import std.typecons: tuple; 70 return tuple(r.front, r.forwardDifference); 71 } 72 /** Alternative. */ 73 auto decodeForwardDifference_alt(E, R)(Tuple!(E, R) x) 74 if (isInputRange!R && 75 is(ElementType!R == typeof(E - E))) 76 { 77 /* TODO: Extract as ForwardSum */ 78 auto diffs = x[1]; // differences 79 immutable n = diffs.array.length; 80 auto y = new E[1 + n]; // TODO: Remove array and keep extra length argument in forwardDifference 81 y[0] = x[0]; 82 auto a = diffs.array; 83 foreach (ix; 0..n) { 84 y[ix + 1] = y[ix] + a[ix]; 85 } 86 return y; 87 } 88 89 unittest 90 { 91 auto x = [1, int.min, 22, 0, int.max, -1100]; 92 // in memory pack and unpack 93 auto pfd = x.encodeForwardDifference_alt; 94 assert(x == pfd.decodeForwardDifference_alt); 95 }