1 /** 2 * Copyright © DiamondMVC 2019 3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE) 4 * Author: Jacob Jensen (bausshf) 5 */ 6 module diamond.data.snapshot; 7 8 import std.traits : isScalarType; 9 10 /// Wrapper for a snapshot type, which is a type that keeps track of a type's value history. 11 final class Snapshot(T) 12 if (is(T == struct) || isScalarType!T) 13 { 14 private: 15 /// The values. 16 T[] _values; 17 /// The current value. 18 T _current; 19 20 public: 21 final: 22 /// Creates a new snapshot of a type. 23 this() { } 24 25 /** 26 * Creates a new snapshot of a type. 27 * Params: 28 * initValue = The initializationValue 29 */ 30 this(T initValue) 31 { 32 value = initValue; 33 } 34 35 @property 36 { 37 /// Sets the value. 38 void value(T newValue) 39 { 40 _values ~= newValue; 41 _current = newValue; 42 } 43 44 /// Gets the value. 45 T value() 46 { 47 if (!_values || !_values.length) 48 { 49 return T.init; 50 } 51 52 return _current; 53 } 54 } 55 56 /// Rolls back to the previous value. 57 void prev() 58 { 59 if (!_values || !_values.length) 60 { 61 return; 62 } 63 64 _values = _values[0 .. $-1]; 65 _current = _values[$-1]; 66 } 67 68 /** 69 * Rolls back a specific amount of states. 70 * Params: 71 * states = The amount of states to roll back. 72 */ 73 void prev(size_t states) 74 { 75 if (states >= _values.length) 76 { 77 _values = []; 78 _current = T.init; 79 } 80 else 81 { 82 _values = _values[0 .. $-states]; 83 _current = _values[$-1]; 84 } 85 } 86 87 /// Resets the value to its first known value. 88 void reset() 89 { 90 if (!_values || !_values.length) 91 { 92 return; 93 } 94 95 _values = [_values[0]]; 96 } 97 98 /** 99 * Operator overload for indexing to retrieve a specific historical snapshot of the type. 100 * Params: 101 * index = The index to retrieve the snapshot of. 102 * Returns: 103 * The value at the index if found, T.init otherwise. 104 */ 105 T opIndex(size_t index) 106 { 107 if (index >= _values.length) 108 { 109 return T.init; 110 } 111 112 return _values[index]; 113 } 114 115 static if (isScalarType!T) 116 { 117 /// Operator overload for comparing scalar types. 118 int opCmp(T comparison) 119 { 120 if (_current < comparison) 121 { 122 return -1; 123 } 124 125 if (_current > comparison) 126 { 127 return 1; 128 } 129 130 return 0; 131 } 132 133 /// Operator overload for equality comparison between scalar types. 134 bool opEquals(T comparison) 135 { 136 return opCmp(comparison) == 0; 137 } 138 } 139 140 /// Alias this to set the value directly for the snapshot. 141 alias value this; 142 }