(* libtool version format: current[:revision[:age]] https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html *) open Syntax type t = { (* The most recent interface number that this library implements *) current: int; (* The implementation number of the current interface *) revision: int option; (* The difference between the newest and oldest interfaces that this library implements *) age: int option; } let is_compatible ~implementation v = v.current <= implementation.current && implementation.current - Option.value ~default:0 implementation.age <= v.current let of_string s = let error = Fmt.error "string does not match a libtool version format" in let to_int s = match int_of_string_opt s with | None -> error | Some i -> if i < 0 then error else Ok i in let* l = String.split_on_char ':' s |> Syntax.list_map to_int in match l with | [] -> Fmt.failwith "not possible" | [ current ] -> Ok { current; revision= None; age= None } | [ current; revision ] -> Ok { current; revision= Some revision; age= None } | [ current; revision; age ] -> Ok { current; revision= Some revision; age= Some age } | _ -> error let pp ppf v = match v with | { current; revision= None; age= None } -> Fmt.pf ppf "%d" current | { current; revision= Some revision; age= None } -> Fmt.pf ppf "%d:%d" current revision | { current; revision= Some revision; age= Some age } -> Fmt.pf ppf "%d:%d:%d" current revision age | _ -> Fmt.failwith "corrupt version data: has age with no revision" let jsont = Jsont.of_of_string ~kind:"libtool version" of_string ~enc:(Fmt.str "%a" pp) let mte_protocol_version = "31:0:0" |> of_string |> function Error e -> Fmt.failwith "%s" e | Ok v -> v