v/vlib/semver/parse.v

85 lines
2.0 KiB
V

module semver
// * Private structs and functions.
struct RawVersion {
prerelease string
metadata string
mut:
raw_ints []string
}
const (
ver_major = 0
ver_minor = 1
ver_patch = 2
versions = [ver_major, ver_minor, ver_patch]
)
// TODO: Rewrite using regexps?
// /(\d+)\.(\d+)\.(\d+)(?:\-([0-9A-Za-z-.]+))?(?:\+([0-9A-Za-z-]+))?/
fn parse(input string) RawVersion {
mut raw_version := input
mut prerelease := ''
mut metadata := ''
plus_idx := raw_version.last_index('+') or { -1 }
if plus_idx > 0 {
metadata = raw_version[(plus_idx + 1)..]
raw_version = raw_version[0..plus_idx]
}
hyphen_idx := raw_version.index('-') or { -1 }
if hyphen_idx > 0 {
prerelease = raw_version[(hyphen_idx + 1)..]
raw_version = raw_version[0..hyphen_idx]
}
raw_ints := raw_version.split('.')
return RawVersion{
prerelease: prerelease
metadata: metadata
raw_ints: raw_ints
}
}
fn (ver RawVersion) is_valid() bool {
if ver.raw_ints.len != 3 {
return false
}
return is_valid_number(ver.raw_ints[ver_major]) && is_valid_number(ver.raw_ints[ver_minor])
&& is_valid_number(ver.raw_ints[ver_patch]) && is_valid_string(ver.prerelease)
&& is_valid_string(ver.metadata)
}
fn (ver RawVersion) is_missing(typ int) bool {
return typ >= ver.raw_ints.len - 1
}
fn (raw_ver RawVersion) coerce() ?Version {
ver := raw_ver.complete()
if !is_valid_number(ver.raw_ints[ver_major]) {
return error('Invalid major version: $ver.raw_ints[ver_major]')
}
return ver.to_version()
}
fn (raw_ver RawVersion) complete() RawVersion {
mut raw_ints := raw_ver.raw_ints
for raw_ints.len < 3 {
raw_ints << '0'
}
return RawVersion{
prerelease: raw_ver.prerelease
metadata: raw_ver.metadata
raw_ints: raw_ints
}
}
fn (raw_ver RawVersion) validate() ?Version {
if !raw_ver.is_valid() {
return none
}
return raw_ver.to_version()
}
fn (raw_ver RawVersion) to_version() Version {
return Version{raw_ver.raw_ints[ver_major].int(), raw_ver.raw_ints[ver_minor].int(), raw_ver.raw_ints[ver_patch].int(), raw_ver.prerelease, raw_ver.metadata}
}