lib.bend source
lib.bend on the hub · documented module
# Semver v1 — Base-only semantic versions.## The accepted textual subset is exactly decimal-major "." decimal-minor# "." decimal-patch, with no whitespace, prefix, prerelease, or build# metadata. Decimal components use Base U32.read, so values must fit U32.# Leading zeroes are accepted in v1; show/to_string always emit canonical# decimal digits. Prerelease/build ordering is intentionally deferred.import Basetype Semver is Data: Semver{major: U32, minor: U32, patch: U32}# Construct a semantic version from its three numeric components.def Semver.make(major: U32, minor: U32, patch: U32) -> Semver: Semver{major, minor, patch}# Parse one complete v1 version. The whole input must be consumed.def Semver.parse.patch( major: U32, minor: U32, +patch_text: String, m: Maybe<&2, U32>) -> Maybe<&2, Semver>: match m: case None{}: None{} case Some{patch}: Some{Semver{major, minor, patch}}def Semver.parse.minor( major: U32, +minor_text: String, +patch_text: String, m: Maybe<&2, U32>) -> Maybe<&2, Semver>: match m: case None{}: None{} case Some{minor}: Semver.parse.patch(major, minor, patch_text, U32.read(patch_text))def Semver.parse.major( major_text: String, +minor_text: String, patch_text: String, m: Maybe<&2, U32>) -> Maybe<&2, Semver>: match m: case None{}: None{} case Some{major}: Semver.parse.minor(major, minor_text, patch_text, U32.read(minor_text))def Semver.parse.parts( ps: List<&2, String>) -> Maybe<&2, Semver>: match ps: case Nil{}: None{} case +major_text <> rest: match rest: case Nil{}: None{} case +minor_text <> rest2: match rest2: case Nil{}: None{} case +patch_text <> tail: match tail: case Nil{}: Semver.parse.major( major_text, minor_text, patch_text, U32.read(major_text)) case _ <> _: None{}def Semver.parse(s: String) -> Maybe<&2, Semver>: Semver.parse.parts(String.split(s, '.'))# Canonical decimal rendering of a version.def Semver.to_string(v: Semver) -> String: match v: case Semver{major, minor, patch}: String.append( U32.show(major), String.append(".", String.append( U32.show(minor), String.append(".", U32.show(patch)))))# show is the conventional alias for to_string.def Semver.show(v: Semver) -> String: Semver.to_string(v)# Semantic-version precedence: major, then minor, then patch.def Semver.cmp.patch(minor_cmp: Cmp, patch_cmp: Cmp) -> Cmp: match patch_cmp: case LT{}: LT{} case GT{}: GT{} case EQ{}: minor_cmpdef Semver.cmp.minor( major_cmp: Cmp, minor_cmp: Cmp, patch_cmp: Cmp) -> Cmp: match minor_cmp: case LT{}: LT{} case GT{}: GT{} case EQ{}: Semver.cmp.patch(minor_cmp, patch_cmp)def Semver.cmp.major( major_cmp: Cmp, minor_cmp: Cmp, patch_cmp: Cmp) -> Cmp: match major_cmp: case LT{}: LT{} case GT{}: GT{} case EQ{}: Semver.cmp.minor(major_cmp, minor_cmp, patch_cmp)def Semver.cmp(a: Semver, b: Semver) -> Cmp: match a b: case Semver{major_a, minor_a, patch_a} Semver{major_b, minor_b, patch_b}: Semver.cmp.major( U32.cmp(major_a, major_b), U32.cmp(minor_a, minor_b), U32.cmp(patch_a, patch_b))# Ordering aliases for callers that prefer order/precedence terminology.def Semver.order(a: Semver, b: Semver) -> Cmp: Semver.cmp(a, b)def Semver.precedes(a: Semver, b: Semver) -> Bool: Cmp.is_lt(Semver.cmp(a, b))