1 /** Codecs. 2 Copyright: Per Nordlöw 2022-. 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 this(R r) { 18 _front = r.front; 19 _diff = r.forwardDifference.array; /+ TODO: Can we make msgpack pack r.forwardDifference without .array +/ 20 } 21 private: 22 typeof(R.init.front) _front; // First element 23 typeof(R.init.forwardDifference.array) _diff; // The Difference 24 } 25 26 /** Instantiator for $(D ForwardDifferenceCode). 27 */ 28 auto encodeForwardDifference(R)(R r) if (isInputRange!R) { 29 return ForwardDifferenceCode!R(r); /+ TODO: Use named parts? +/ 30 } 31 32 // version = use_msgpack; 33 34 unittest { 35 import std.range: dropOne; 36 import core.exception: AssertError; 37 import std.exception: assertThrown; 38 version (use_msgpack) import msgpack; 39 40 assertThrown!AssertError([1].dropOne.encodeForwardDifference_alt); 41 42 auto x = [1, int.min, 22, 0, int.max, -1100]; 43 44 auto fdp = x.encodeForwardDifference; 45 46 version (use_msgpack) { 47 alias FDP = typeof(fdp); 48 49 auto raw = fdp.pack; 50 auto raw2 = raw.dup; 51 52 FDP fdp_; // restored 53 aw.unpack(fdp_); // restore it 54 assert(fdp == fdp_); 55 56 auto fdp__ = raw2.unpack!FDP; // restore it (alternatively) 57 assert(fdp == fdp__); 58 } 59 } 60 61 /** Alternative. */ 62 auto encodeForwardDifference_alt(R)(R r) if (isInputRange!R) { 63 import std.typecons: tuple; 64 return tuple(r.front, r.forwardDifference); 65 } 66 /** Alternative. */ 67 auto decodeForwardDifference_alt(E, R)(Tuple!(E, R) x) 68 if (isInputRange!R && 69 is(ElementType!R == typeof(E - E))) { 70 /* TODO: Extract as ForwardSum */ 71 auto diffs = x[1]; // differences 72 immutable n = diffs.array.length; 73 auto y = new E[1 + n]; /+ TODO: Remove array and keep extra length argument in forwardDifference +/ 74 y[0] = x[0]; 75 auto a = diffs.array; 76 foreach (ix; 0..n) { 77 y[ix + 1] = y[ix] + a[ix]; 78 } 79 return y; 80 } 81 82 unittest { 83 auto x = [1, int.min, 22, 0, int.max, -1100]; 84 // in memory pack and unpack 85 auto pfd = x.encodeForwardDifference_alt; 86 assert(x == pfd.decodeForwardDifference_alt); 87 }