open Astring open Rresult type os_t = Darwin | FreeBSD | OpenBSD | Linux type version_t = { major : int; minor : int; extra : string; } type t = { os : os_t; version : version_t; hostname : string; uuid : Uuidm.t; } let os_of_string = function | "Darwin" -> Darwin | "FreeBSD" -> FreeBSD | "OpenBSD" -> OpenBSD | "Linux" -> Linux | _ -> die "Unknown operating system" let string_of_os = function | Darwin -> "Darwin" | FreeBSD -> "FreeBSD" | OpenBSD -> "OpenBSD" | Linux -> "Linux" let string_of_version v = Printf.sprintf "%d.%d%s" v.major v.minor v.extra type extra_behavior = NoExtra | SeparateWith of char let version_of_os_string = let parse_into_version extra str = let open String in match cuts "." str with | major :: fld2 :: tail -> ( let major = int_of_string major in match extra with | NoExtra -> {major=major; minor=int_of_string fld2; extra=""} | SeparateWith(extra_separator) -> if extra_separator = '.' then let minor = int_of_string fld2 and extra = "." ^ concat ~sep:"." tail in {major; minor; extra} else let separator_string = of_char extra_separator in match cuts (of_char extra_separator) fld2 with | minor :: rs -> {major=major; minor=int_of_string minor; extra=separator_string ^ concat ~sep:separator_string rs} | _ -> die "Unable to parse minor component of version") | _ -> die "Unable to parse major component of version" in function | OpenBSD -> parse_into_version NoExtra | Linux | Darwin -> parse_into_version (SeparateWith('.')) | FreeBSD -> parse_into_version (SeparateWith('-'))