silk.semver.version.

Semantic versions: strict SemVer 2.0.0 parsing, precedence, and display.

When to use#

Use Version.parse to read a version such as 1.4.0-beta.2+build.7, and compare versions with <, ==, or Version.comparePrecedence. To test a version against a requirement such as ^1.2 or >=1.0.0, <2.0.0, use silk.semver.range.

Details#

A Version holds the three numbers as u64 values and borrows the pre-release and build text from the parsed input. Parsing does not allocate. The parser accepts exactly the grammar of SemVer 2.0.0: no v prefix, no spaces, and no leading zeros in numbers.

Precedence follows SemVer 2.0.0: numbers compare numerically, a pre-release version is lower than its release, and build metadata does not change precedence. == and < also compare build metadata after precedence, so two versions are equal only if their text is the same.

Gotchas#

1.0.0+a and 1.0.0+b have the same precedence, but == returns false for them. Use Version.comparePrecedence to compare versions as SemVer 2.0.0 does.

Examples#

Find the newer of two versions#

silk
import silk.core.result { Result }
import silk.semver.version { Version, SemverError }

pub fn main() -> i32 {
  let release = match Version.parse("1.4.0") {
    Result<Version, SemverError>.Success { value } => value
    Result<Version, SemverError>.Failure { error: _ } => { return 1 }
  }
  let beta = match Version.parse("1.4.0-beta.2+build.7") {
    Result<Version, SemverError>.Success { value } => value
    Result<Version, SemverError>.Failure { error: _ } => { return 1 }
  }
  if !(&beta < &release) || beta.prerelease != "beta.2" || beta.build != "build.7" {
    return 1
  }
  return 0
}

See also#

Semantic Versioning 2.0.0 defines the grammar and the precedence rules.

Import as Version with import silk.semver.version { Version }.

Public declarations: 3.

SemverErrorReason#

silk
pub enum SemverErrorReason

The cause of a SemverError.

Empty#

silk
Empty

The text is empty.

UnexpectedEnd#

silk
UnexpectedEnd

The text ends where a number, an identifier, or a version must start.

UnexpectedCharacter#

silk
UnexpectedCharacter

The byte at the error offset is not valid in that position.

LeadingZero#

silk
LeadingZero

A number, or a numeric pre-release identifier, has a leading zero, as 01.

NumberTooLarge#

silk
NumberTooLarge

A number is larger than the largest u64, 18446744073709551615.

EmptyIdentifier#

silk
EmptyIdentifier

A pre-release or build identifier is empty, as in 1.0.0- or 1.0.0-a..b.

TooManyComparators#

silk
TooManyComparators

A Cargo requirement has more than 32 comparators.

Implementation Debug for SemverErrorReason#

silk
impl Debug for SemverErrorReason

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant, such as LeadingZero.

SemverError#

silk
pub struct SemverError

A version or range syntax error: the cause and the byte position.

Field reason#

silk
pub reason: SemverErrorReason

The cause of the error.

Field offset#

silk
pub offset: usize

The position of the first byte that is not valid, from the start of the text. If the text ends too early, it is the length of the text.

Implementation Copy for SemverError#

silk
impl Copy for SemverError

Implementation Debug for SemverError#

silk
impl Debug for SemverError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the fields, as SemverError { reason: LeadingZero, offset: 2 }.

Version#

silk
pub struct Version<'text>

A semantic version, MAJOR.MINOR.PATCH with an optional pre-release and build metadata.

Details#

The pre-release and build fields borrow the text that was parsed, without the - or +. They are empty when the version has none. The value is Copy and cannot live longer than its text.

== and < compare precedence first and then build metadata, so == is true only for versions with the same text. Build identifiers compare in the same way as pre-release identifiers.

Gotchas#

A value made with a struct literal is not checked. Use Version.parse or Version.make to get a valid version.

Field major#

silk
pub major: u64

The major version. It changes for incompatible API changes.

Field minor#

silk
pub minor: u64

The minor version. It changes for compatible additions.

Field patch#

silk
pub patch: u64

The patch version. It changes for compatible fixes.

Field prerelease#

silk
pub prerelease: string<'text>

The pre-release identifiers without the -, as beta.2, or empty for a release.

Field build#

silk
pub build: string<'text>

The build metadata without the +, as build.7, or empty if there is none.

Implementation Copy for Version<'text>#

silk
impl<'text> Copy for Version<'text>

Implementation Version<'text>#

silk
impl<'text> Version<'text>

Associated function make#

silk
pub fn make(major: u64, minor: u64, patch: u64) -> Version<'static>

Returns the release version major.minor.patch, with no pre-release and no build metadata.

Associated function parse#

silk
pub fn parse(text: string<'text>) -> Result<Version<'text>, SemverError>

Parses a SemVer 2.0.0 version, such as 1.4.0-beta.2+build.7.

Details#

The text must be exactly MAJOR.MINOR.PATCH, then optionally - and dot-separated pre-release identifiers, then optionally + and dot-separated build identifiers. Identifiers use ASCII letters, digits, and -. A number fits in u64. The result borrows text. Nothing is allocated.

Errors#

  • SemverError with the reason and the byte offset of the first problem:

    • Empty for empty text.

    • UnexpectedEnd if a part is missing, as in 1.2.

    • UnexpectedCharacter for a byte that is not valid there, as the v of v1.2.3.

    • LeadingZero for a number or numeric pre-release identifier such as 01.

    • NumberTooLarge for a number above 18446744073709551615.

    • EmptyIdentifier for an empty identifier, as in 1.2.3- or 1.2.3+a..b.

Gotchas#

Leading and trailing spaces and a v prefix are errors. Version requirements accept a v prefix, but versions do not.

Method isPrerelease#

silk
pub fn isPrerelease(self: &Self) -> bool

Returns true if the version has pre-release identifiers, as 1.0.0-rc.1 has.

Associated function comparePrecedence#

silk
pub fn comparePrecedence(left: &Version<'_>, right: &Version<'_>) -> Ordering

Compares the SemVer 2.0.0 precedence of two versions. Build metadata does not count.

Details#

The major, minor, and patch numbers compare numerically, in that order. Then a version without a pre-release is greater than one with a pre-release. Pre-release identifiers compare one at a time from the left: numeric identifiers compare as numbers, other identifiers compare by ASCII byte order, and a numeric identifier is lower than a non-numeric one. If all shared identifiers are equal, the version with more identifiers is greater. So 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0.

Gotchas#

1.0.0+a and 1.0.0+b have Equal precedence, but == on them returns false because == also compares build metadata.

Method nextMajor#

silk
pub fn nextMajor(self: &Self) -> Version<'static>

Returns the next major release: major + 1 with 0.0, or the same numbers for a pre-release of X.0.0.

Details#

The result has no pre-release and no build metadata. 1.4.2 becomes 2.0.0, and 2.0.0-rc.1 becomes 2.0.0, because 2.0.0 is the release that 2.0.0-rc.1 comes before.

Gotchas#

The program traps if the major number is 18446744073709551615 and must increase.

Method nextMinor#

silk
pub fn nextMinor(self: &Self) -> Version<'static>

Returns the next minor release: minor + 1 with patch 0, or the same numbers for a pre-release of X.Y.0.

Details#

The result has no pre-release and no build metadata. 1.4.2 becomes 1.5.0, and 1.5.0-rc.1 becomes 1.5.0.

Gotchas#

The program traps if the minor number is 18446744073709551615 and must increase.

Method nextPatch#

silk
pub fn nextPatch(self: &Self) -> Version<'static>

Returns the next patch release: patch + 1, or the same numbers for a pre-release.

Details#

The result has no pre-release and no build metadata. 1.4.2 becomes 1.4.3, and 1.4.3-rc.1 becomes 1.4.3.

Gotchas#

The program traps if the patch number is 18446744073709551615 and must increase.

Implementation Equal for Version<'text>#

silk
impl<'text> Equal for Version<'text>

Operation equals#

silk
equals: Version.same

Implementation Order for Version<'text>#

silk
impl<'text> Order for Version<'text>

Operation compare#

silk
compare: Version.compare

Implementation Display for Version<'text>#

silk
impl<'text> Display for Version<'text>

Operation display#

silk
effect fn display(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the version text, as 1.4.0-beta.2+build.7. Writer failures propagate unchanged.

Implementation Debug for Version<'text>#

silk
impl<'text> Debug for Version<'text>

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the version text, as 1.4.0-beta.2+build.7. Writer failures propagate unchanged.

Category: Data formats.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.

View the source of this page