1 module dud.semver.semver; 2 3 @safe: 4 5 struct SemVer { 6 @safe: 7 8 uint major; 9 uint minor; 10 uint patch; 11 12 string[] preRelease; 13 string[] buildIdentifier; 14 15 static immutable(SemVer) MinRelease = SemVer(0, 0, 0); 16 static immutable(SemVer) MaxRelease = SemVer(uint.max, uint.max, uint.max); 17 18 bool opEquals(const(SemVer) other) const nothrow pure { 19 import dud.semver.comparision : compare; 20 return compare(this, other) == 0; 21 } 22 23 int opCmp(const(SemVer) other) const nothrow pure { 24 import dud.semver.comparision : compare; 25 return compare(this, other); 26 } 27 28 size_t toHash() const nothrow @nogc pure { 29 import std.algorithm.iteration : each; 30 size_t hash = this.major.hashOf(); 31 hash = this.minor.hashOf(hash); 32 hash = this.patch.hashOf(hash); 33 this.preRelease.each!(it => hash = it.hashOf(hash)); 34 this.buildIdentifier.each!(it => hash = it.hashOf(hash)); 35 return hash; 36 } 37 38 @property SemVer dup() const pure { 39 auto ret = SemVer(this.major, this.minor, this.patch, 40 this.preRelease.dup(), this.buildIdentifier.dup()); 41 return ret; 42 } 43 44 static SemVer max() pure { 45 return SemVer(uint.max, uint.max, uint.max); 46 } 47 48 static SemVer min() pure { 49 return SemVer(uint.min, uint.min, uint.min); 50 } 51 52 string toString() const @safe pure { 53 import std.array : appender, empty; 54 import std.format : format; 55 string ret = format("%s.%s.%s", this.major, this.minor, this.patch); 56 if(!this.preRelease.empty) { 57 ret ~= format("-%-(%s.%)", this.preRelease); 58 } 59 if(!this.buildIdentifier.empty) { 60 ret ~= format("+%-(%s.%)", this.buildIdentifier); 61 } 62 return ret; 63 } 64 }