1 module dud.semver.setoperation; 2 3 import std.array : array; 4 import std.algorithm.iteration : map, filter, joiner; 5 import std.exception : enforce; 6 import std.stdio; 7 8 import dud.semver.versionunion; 9 import dud.semver.versionrange; 10 import dud.semver.semver; 11 12 import dud.semver.checks; 13 14 @safe pure: 15 16 // 17 // unionOf 18 // 19 20 VersionUnion unionOf(const(SemVer) a, const(SemVer) b) { 21 VersionUnion ret = VersionUnion( 22 [ VersionRange(a, Inclusive.yes, a, Inclusive.yes) 23 , VersionRange(b, Inclusive.yes, b, Inclusive.yes) 24 ]); 25 return ret; 26 } 27 28 VersionUnion unionOf(const(SemVer) a, const(VersionRange) b) { 29 return unionOf(b, a); 30 } 31 32 VersionUnion unionOf(const(VersionRange) a, const(SemVer) b) { 33 VersionUnion ret = VersionUnion( 34 [ a.dup 35 , VersionRange(b, Inclusive.yes, b, Inclusive.yes) 36 ]); 37 return ret; 38 } 39 40 VersionUnion unionOf(const(SemVer) a, const(VersionUnion) b) { 41 return unionOf(b, a); 42 } 43 44 VersionUnion unionOf(const(VersionUnion) a, const(SemVer) b) { 45 VersionUnion ret = a.dup(); 46 ret.insert(VersionRange(b, Inclusive.yes, b, Inclusive.yes)); 47 return ret; 48 } 49 50 VersionUnion unionOf(const(VersionRange) a, const(VersionRange) b) { 51 VersionUnion ret = VersionUnion([a.dup , b.dup]); 52 return ret; 53 } 54 55 VersionUnion unionOf(const(VersionRange) a, const(VersionUnion) b) { 56 return unionOf(b, a); 57 } 58 59 VersionUnion unionOf(const(VersionUnion) a, const(VersionRange) b) { 60 VersionUnion ret = a.dup(); 61 ret.insert(b); 62 return ret; 63 } 64 65 VersionUnion unionOf(const(VersionUnion) a, const(VersionUnion) b) { 66 import std.algorithm.iteration : each; 67 68 VersionUnion ret = a.dup(); 69 b.ranges.each!(it => ret.insert(it)); 70 return ret; 71 } 72 73 // 74 // intersectionOf 75 // 76 77 SemVer intersectionOf(const(SemVer) a, const(SemVer) b) { 78 return a == b ? a.dup : SemVer.init; 79 } 80 81 SemVer intersectionOf(const(VersionRange) a, const(SemVer) b) { 82 return allowsAny(a, b) ? b.dup : SemVer.init; 83 } 84 85 SemVer intersectionOf(const(SemVer) a, const(VersionRange) b) { 86 return intersectionOf(b, a); 87 } 88 89 SemVer intersectionOf(const(VersionUnion) a, const(SemVer) b) { 90 return allowsAny(a, b) ? b.dup : SemVer.init; 91 } 92 93 SemVer intersectionOf(const(SemVer) a, const(VersionUnion) b) { 94 return intersectionOf(b, a); 95 } 96 97 VersionRange intersectionOf(const(VersionRange) a, const(VersionRange) b) { 98 // a: . . ( . . ] . . 99 // b: . [ . . ) . . . 100 101 // a: . [ . . ) . . . 102 // b: . . ( . . ] . . 103 104 // a: . [ . ] . . . . 105 // b: . . . . [ ] . . 106 107 // a: . . . . [ ] . . 108 // b: . [ . ] . . . . 109 110 // a: . . [ ] . . . . 111 // b: . [ . . ] . . . 112 113 // a: . . . . ( . ] . 114 // b: . [ . . ] . . . 115 116 const SemVer low = a.low < b.low ? b.low : a.low; 117 const SemVer high = a.high > b.high ? b.high : a.high; 118 119 const Inclusive incLow = 120 a.low == b.low && (!a.inclusiveLow || !b.inclusiveLow) 121 ? Inclusive.no 122 : a.low == low ? a.inclusiveLow : b.inclusiveLow; 123 124 const Inclusive incHigh = 125 a.high == b.high && (!a.inclusiveHigh || !b.inclusiveHigh) 126 ? Inclusive.no 127 : a.high == high ? a.inclusiveHigh : b.inclusiveHigh; 128 129 return low < high 130 ? VersionRange(low, incLow, high, incHigh) 131 : a.high == b.low && a.inclusiveHigh && b.inclusiveLow 132 ? VersionRange(a.high, Inclusive.yes, a.high, Inclusive.yes) 133 : b.high == a.low && b.inclusiveHigh && a.inclusiveLow 134 ? VersionRange(b.high, Inclusive.yes, b.high, Inclusive.yes) 135 : VersionRange.init; 136 } 137 138 VersionUnion intersectionOf(const(VersionUnion) a, const(VersionRange) b) { 139 return a.ranges 140 .map!(it => intersectionOf(it, b)) 141 .filter!(it => it != VersionRange.init) 142 .array 143 .VersionUnion; 144 } 145 146 VersionUnion intersectionOf(const(VersionRange) a, const(VersionUnion) b) { 147 return intersectionOf(b, a); 148 } 149 150 VersionUnion intersectionOf(const(VersionUnion) a, const(VersionUnion) b) { 151 return a.ranges 152 .map!(it => b.ranges.map!(jt => intersectionOf(it, jt))) 153 .joiner 154 .filter!(it => it != VersionRange.init) 155 .array 156 .VersionUnion; 157 } 158 159 // 160 // invert 161 // 162 163 VersionUnion invert(const(SemVer) a) { 164 enforce(a != SemVer.init); 165 return VersionUnion( 166 [ VersionRange(SemVer.min, Inclusive.yes, a.dup, Inclusive.no) 167 , VersionRange(a.dup, Inclusive.no, SemVer.max, Inclusive.yes) 168 ]); 169 } 170 171 VersionUnion invert(const(VersionRange) a) { 172 enforce(a.low != SemVer.init); 173 return VersionUnion( 174 [ VersionRange(SemVer.init, Inclusive.yes, a.low.dup, cast(Inclusive)!a.inclusiveLow) 175 , VersionRange(a.high.dup, cast(Inclusive)!a.inclusiveHigh, SemVer.max, Inclusive.yes) 176 ]); 177 } 178 179 VersionUnion invert(const(VersionUnion) a) { 180 import std.range : chain, chunks, only, repeat, take; 181 182 auto zz = chain( 183 [ [ VersionRange(SemVer.min(), Inclusive.no, SemVer.min(), Inclusive.no) ] 184 , a.ranges.map!(r => r.dup.repeat.take(2)).joiner.array 185 , [ VersionRange(SemVer.max(), Inclusive.no, SemVer.max(), Inclusive.yes) ] 186 ] 187 ) 188 .joiner 189 .array 190 .chunks(2) 191 .map!(c => VersionRange(c[0].high, cast(Inclusive)!c[0].inclusiveHigh, 192 c[1].low, cast(Inclusive)!c[1].inclusiveLow)) 193 .array; 194 195 return VersionUnion(zz); 196 } 197 198 // 199 // difference 200 // 201 202 SemVer differenceOf(const(SemVer) a, const(SemVer) b) { 203 const VersionUnion bInt = invert(b); 204 return intersectionOf(a, bInt); 205 } 206 207 VersionUnion differenceOf(const(VersionRange) a, const(SemVer) b) { 208 const VersionUnion bInt = invert(b); 209 return intersectionOf(a, bInt); 210 } 211 212 SemVer differenceOf(const(SemVer) a, const(VersionRange) b) { 213 const VersionUnion bInt = invert(b); 214 return intersectionOf(a, bInt); 215 } 216 217 VersionUnion differenceOf(const(VersionRange) a, const(VersionRange) b) { 218 const VersionUnion bInt = invert(b); 219 auto ret = intersectionOf(a, bInt); 220 return ret; 221 } 222 223 VersionUnion differenceOf(const(VersionUnion) a, const(VersionRange) b) { 224 const VersionUnion bInt = invert(b); 225 auto ret = intersectionOf(a, bInt); 226 return ret; 227 } 228 229 VersionUnion differenceOf(const(VersionRange) a, const(VersionUnion) b) { 230 const VersionUnion bInt = invert(b); 231 auto ret = intersectionOf(a, bInt); 232 return ret; 233 } 234 235 VersionUnion differenceOf(const(VersionUnion) a, const(VersionUnion) b) { 236 const VersionUnion bInt = invert(b); 237 auto ret = intersectionOf(a, bInt); 238 return ret; 239 }