///|
priv enum ReleaseType {
Major
Minor
Patch
Premajor
Preminor
Prepatch
Prerelease
Release
Pre
}
///|
fn parse_release_type(release : String) -> ReleaseType? {
match release {
"major" => Some(ReleaseType::Major)
"minor" => Some(ReleaseType::Minor)
"patch" => Some(ReleaseType::Patch)
"premajor" => Some(ReleaseType::Premajor)
"preminor" => Some(ReleaseType::Preminor)
"prepatch" => Some(ReleaseType::Prepatch)
"prerelease" => Some(ReleaseType::Prerelease)
"release" => Some(ReleaseType::Release)
"pre" => Some(ReleaseType::Pre)
_ => None
}
}
///|
fn normalize_identifier_base(base : Int) -> Int {
if base < 0 {
0
} else {
base
}
}
///|
fn parse_identifier_opt(identifier : String?) -> PreId? {
match identifier {
None => None
Some(value) => Some(parse_prerelease_ident(value)) catch { _ => None }
}
}
///|
fn inc_pre_ids(
current : Array[PreId],
identifier : PreId?,
base : Int,
) -> Array[PreId] {
let next = current.copy()
let mut last_numeric : Int? = None
for i, id in next {
if id is Num(_) {
last_numeric = Some(i)
}
}
match last_numeric {
Some(i) =>
match next[i] {
Num(value) => next[i] = Num(value + 1)
_ => ()
}
None => next.push(Num(base))
}
match identifier {
None => next
Some(id) => {
let reset = [id, Num(base)]
match next.get(0) {
Some(first) if first == id =>
if next.length() < 2 {
reset
} else {
match next[1] {
Num(_) => next
_ => reset
}
}
_ => reset
}
}
}
}
///|
fn inc_semver(
version : SemVer,
release : ReleaseType,
identifier : PreId?,
identifier_base : Int,
) -> SemVer {
let base = normalize_identifier_base(identifier_base)
let mut major = version.major
let mut minor = version.minor
let mut patch = version.patch
let mut pre : Array[PreId] = []
match release {
ReleaseType::Major => {
if version.minor != 0 || version.patch != 0 || version.pre.is_empty() {
major = major + 1
}
minor = 0
patch = 0
pre = []
}
ReleaseType::Minor => {
if version.patch != 0 || version.pre.is_empty() {
minor = minor + 1
}
patch = 0
pre = []
}
ReleaseType::Patch => {
if version.pre.is_empty() {
patch = patch + 1
}
pre = []
}
ReleaseType::Premajor => {
major = major + 1
minor = 0
patch = 0
pre = inc_pre_ids([], identifier, base)
}
ReleaseType::Preminor => {
minor = minor + 1
patch = 0
pre = inc_pre_ids([], identifier, base)
}
ReleaseType::Prepatch => {
patch = patch + 1
pre = inc_pre_ids([], identifier, base)
}
ReleaseType::Prerelease =>
if version.pre.is_empty() {
patch = patch + 1
pre = inc_pre_ids([], identifier, base)
} else {
pre = inc_pre_ids(version.pre, identifier, base)
}
ReleaseType::Release => pre = []
ReleaseType::Pre => pre = inc_pre_ids(version.pre, identifier, base)
}
SemVer::{ major, minor, patch, pre, build: [] }
}
///|
pub fn SemVer::inc(
self : SemVer,
release : String,
identifier? : String,
identifier_base? : Int = 0,
) -> SemVer? {
inc_semver_option(self, release, identifier, identifier_base)
}
///|
pub fn inc(
version : String,
release : String,
identifier? : String,
identifier_base? : Int = 0,
) -> String? {
match try_parse(version) {
Ok(value) =>
match inc_semver_option(value, release, identifier, identifier_base) {
Some(next) => Some(next.to_string())
None => None
}
Err(_) => None
}
}
///|
fn inc_semver_option(
version : SemVer,
release : String,
identifier : String?,
identifier_base : Int,
) -> SemVer? {
match parse_release_type(release) {
None => None
Some(release_type) =>
match parse_identifier_opt(identifier) {
None =>
if identifier is None {
Some(inc_semver(version, release_type, None, identifier_base))
} else {
None
}
Some(id) =>
Some(inc_semver(version, release_type, Some(id), identifier_base))
}
}
}