1 module dud.semver.versionunion; 2 3 import std.algorithm.sorting : sort; 4 import std.array : empty, front, popFront; 5 import std.format : format, formattedWrite; 6 import dud.semver.versionrange; 7 import dud.semver.semver; 8 9 @safe pure: 10 11 struct VersionUnion { 12 @safe pure: 13 VersionRange[] ranges; 14 15 this(const(VersionRange)[] rng) { 16 foreach(it; rng) { 17 this.insert(it); 18 } 19 } 20 21 void insert(const(VersionRange) nvu) { 22 this.ranges = merge(this.ranges, nvu); 23 } 24 25 VersionUnion dup() const { 26 import std.array : array; 27 import std.algorithm.iteration : map; 28 VersionUnion ret; 29 ret.ranges = this.ranges.map!(it => it.dup).array; 30 return ret; 31 } 32 } 33 34 VersionRange merge(const(VersionRange) a, const(VersionRange) b) { 35 const SemVer low = a.low < b.low ? a.low : b.low; 36 const Inclusive lowInc = low == a.low ? a.inclusiveLow : b.inclusiveLow; 37 38 const SemVer high = a.high > b.high ? a.high : b.high; 39 const Inclusive highInc = high == a.high ? a.inclusiveHigh : b.inclusiveHigh; 40 41 const bool notIntersect = 42 (a.high == b.low 43 && (a.inclusiveHigh == false || b.inclusiveLow == false)) 44 || (a.low == b.high 45 && (a.inclusiveLow == false || b.inclusiveHigh == false)) 46 || (a.high < b.low) 47 || (a.low > b.high); 48 49 return notIntersect 50 ? VersionRange.init 51 : VersionRange(low, lowInc, high, highInc); 52 } 53 54 package VersionRange[] merge(const(VersionRange)[] old, 55 const(VersionRange) nvu) 56 { 57 VersionRange[] ret; 58 if(old.empty) { 59 return [ nvu.dup() ]; 60 } 61 62 ret ~= nvu.dup; 63 64 foreach(it; old) { 65 VersionRange top = ret.front(); 66 ret.popFront(); 67 68 VersionRange m = merge(top, it); 69 if(m == VersionRange.init) { 70 ret ~= top; 71 ret ~= it.dup(); 72 } else { 73 ret ~= m; 74 } 75 } 76 77 ret.sort(); 78 79 return ret; 80 }