Independent implementation of semver.org 2.0.0. Supports full version strings including pre-release identifiers and build metadata. Comparison follows § 11 precedence rules (build metadata ignored).

let v = Version.from("1.2.3-alpha.1+exp.sha.5114f85")
assert(v.major == 1 && v.is_prerelease())

let a = Version.from("1.0.0-alpha")
let b = Version.from("1.0.0")
assert(a < b)   // pre-release < release

Types

Version

stable since 0.1
export type Version {
    readonly major u64
    readonly minor u64
    readonly patch u64
    readonly pre   []str
    readonly build []str
}

SemVer version (semver.org 2.0.0). All fields are readonlyVersion is immutable; operations return a new value. pre holds pre-release identifiers split by . (e.g. "alpha.1"["alpha", "1"]). build holds build metadata identifiers; they are not considered for precedence comparison.

ParseVersionError

stable since 0.1
export type ParseVersionError
    | EmptyInput
    | MissingMinor
    | MissingPatch
    | LeadingZero       { component str; value str }
    | InvalidComponent  { component str; value str }
    | EmptyIdentifier   { section str }
    | InvalidIdentifier { section str; value str }

Error variants returned by Version.from. Each carries positional info (component / section + value) for diagnostic messages.


Constructors

Version.from

stable since 0.1
fn Version.from(s str) Fail[ParseVersionError] -> Self

Parses a semver string per § 9–10 grammar. Throws Fail[ParseVersionError] on any error. Handle it with a with Fail[ParseVersionError] block.

Examples

let v = Version.from("2.5.1")
assert(v.major == 2 && v.minor == 5 && v.patch == 1)

let v2 = Version.from("1.0.0-beta+exp.sha.5114f85")
assert(v2.pre[0] == "beta")

Version.new

stable since 0.1
fn Version.new(major u64, minor u64, patch u64) -> Self

Simple constructor without pre-release or build metadata. The most common case.

Examples

let v = Version.new(1, 2, 3)
assert(v.into() == "1.2.3")

Version.full

stable since 0.1
fn Version.full(major u64, minor u64, patch u64, pre []str, build []str) -> Self

Full constructor with explicit pre-release and build metadata arrays.


Inspection

is_prerelease

stable since 0.1
fn Version @is_prerelease() -> bool

Returns true if the version has at least one pre-release identifier.

is_stable

stable since 0.1
fn Version @is_stable() -> bool

Returns true if major > 0 and there is no pre-release identifier (stable release per semver convention).

Examples

assert(Version.from("1.0.0").is_stable())
assert(!Version.from("0.9.0").is_stable())      // 0.x.y — unstable
assert(!Version.from("1.0.0-alpha").is_stable()) // pre-release

has_build

stable since 0.1
fn Version @has_build() -> bool

Returns true if build metadata is present.


Comparison

All comparisons implement § 11 precedence: major > minor > patch > pre-release. Build metadata is ignored. Pre-release versions have lower precedence than the release (1.0.0-alpha < 1.0.0).

Operator overloading (D46) means v1 < v2, v1 == v2, v1 != v2 work directly.

lt / gt / le / ge

stable since 0.1
fn Version @lt(other Version) -> bool   // <
fn Version @le(other Version) -> bool   // <=
fn Version @gt(other Version) -> bool   // >
fn Version @ge(other Version) -> bool   // >=

Examples

// semver.org §11 chain example
let chain = [
    Version.from("1.0.0-alpha"),
    Version.from("1.0.0-alpha.1"),
    Version.from("1.0.0-beta"),
    Version.from("1.0.0-rc.1"),
    Version.from("1.0.0"),
]
for i in 0..chain.len() - 1 {
    assert(chain[i] < chain[i + 1])
}

eq / eq_precedence

stable since 0.1
fn Version @eq(other Version) -> bool            // structural (includes build)
fn Version @eq_precedence(other Version) -> bool  // semver §10 (ignores build)

eq is structural — it compares all fields including build. eq_precedence follows § 10 and ignores build metadata.

Examples

let a = Version.from("1.0.0+build.1")
let b = Version.from("1.0.0+build.2")
assert(a.eq_precedence(b))   // same precedence
assert(!a.eq(b))              // different build metadata

Serialization

into

stable since 0.1
fn Version @into() -> str

Serializes to MAJOR.MINOR.PATCH[-PRE][+BUILD]. Round-trip: Version.from(v.into()).eq(v) holds for any valid Version.

Examples

let v = Version.new(1, 2, 3)
let s str = v.into()
assert(s == "1.2.3")