P35HCXDOT4NKKPTM6OMKEVKBLB3VLEODS7LNKRG7777RLOFDGU2AC open Containersmodule P = structopen Angstromlet is_ws = function ' ' | '\t' | '\n' -> true | _ -> falselet ws = skip_while is_wslet cmd prefix =let* name = ws *> string prefix *> take_till is_ws <* ws inlet+ args = many any_char <* end_of_input >>| String.of_list in(name, args)endlet parse = Angstrom.parse_string ~consume:Angstrom.Consume.Alllet of_message ~prefix msg =match parse (P.cmd prefix) msg with Error _ -> None | Ok cmd -> Some cmd
open Containerstype t = { token : string; prefix : string }let token { token; _ } = tokenlet prefix { prefix; _ } = prefixlet of_filename filename =match Toml.Parser.from_filename filename with| `Ok tbl ->let open Result inlet+ token =Toml.Lenses.(get tbl (key "auth" |-- table |-- key "token" |-- string))|> Option.to_result_lazy (fun () ->Format.asprintf "Invalid configuration: missing [auth.token]@.")inlet prefix =Toml.Lenses.(get tbl (key "commands" |-- table |-- key "prefix" |-- string))|> Option.get_or ~default:"!"in{ token; prefix }| `Error (_, loc) ->Error(Format.asprintf"Invalid TOML in configuration: @[file='%s'@] @[line=%d@] \@[column=%d@]@."filename loc.line loc.column)
module Config = structtype t = { token : string; prefix : string }let token { token; _ } = tokenlet prefix { prefix; _ } = prefixlet of_filename filename =match Toml.Parser.from_filename filename with| `Ok tbl ->let open Result inlet+ token =Toml.Lenses.(get tbl (key "auth" |-- table |-- key "token" |-- string))|> Option.to_result_lazy (fun () ->Format.asprintf "Invalid configuration: missing [auth.token]@.")inlet prefix =Toml.Lenses.(get tbl (key "commands" |-- table |-- key "prefix" |-- string))|> Option.get_or ~default:"!"in{ token; prefix }| `Error (_, loc) ->Error(Format.asprintf"Invalid TOML in configuration: @[file='%s'@] @[line=%d@] \@[column=%d@]@."filename loc.line loc.column)end
let is_ws = function ' ' | '\t' | '\n' -> true | _ -> falselet ws = skip_while is_wslet cmd prefix =let* name = ws *> string prefix *> take_till is_ws <* ws inlet+ args = many any_char <* end_of_input >>| String.of_list in(name, args)endlet parse = Angstrom.parse_string ~consume:Angstrom.Consume.Alllet of_message ~prefix msg =match parse (P.cmd prefix) msg with Error _ -> None | Ok cmd -> Some cmdend
| Some ("join", "") ->let msg =Msg.fmt"⚠️ Not supported yet, please provide a voice channel id"inD.Client.send_message channel_id msg client| Some ("join", v_channel_id) ->let guild_id = Option.get_exn guild_id inlet v_channel_id = M.Snowflake.of_string v_channel_id inD.Client.join_voice ~guild_id ~channel_id:v_channel_id client| Some ("play", "kiff") -> (let guild_id = Option.get_exn guild_id inlet* s = D.Audio_stream.Ffmpeg.of_file "./kiff.mp3" inmatch s with| Ok audio_stream ->D.Client.play_audio_stream ~guild_id audio_stream client| _ -> Lwt.return_unit)| Some ("play", "soundbite") -> (let guild_id = Option.get_exn guild_id inlet* s = D.Audio_stream.Ffmpeg.of_file "./bite2.mp3" inmatch s with| Ok audio_stream ->D.Client.play_audio_stream ~guild_id audio_stream client| _ -> Lwt.return_unit)
(executable(name discopotty)(public_name discopotty)(libraries discord containers toml relog.lib angstrom))
open Containerslet work () =let sine_stream = Discord.Audio_stream.Gen.sine ~freq:1000 3. inlet buf = Bigstringaf.create (960 * 2 * 4) inlet fill_buff frame =let f = Faraday.create (1024 * 4) inSeq.(0 --^ Bigarray.Array1.dim frame|> iter (fun i -> Faraday.LE.write_float f frame.{i}));Faraday.serialize_to_bigstring finsine_stream|> Lwt_pipe.Reader.iter_s ~f:(fun frame ->Lwt_io.write_from_exactly_bigstring Lwt_io.stdout (fill_buff frame) 0(Bigstringaf.length buf))(* let () = Lwt_main.run (work ())*)
*** DONE Investigate EOF reason in websocketsWebsocketAF was the issue: fixed parser buffer size of 4kb(when =GUILD_READY= payloads can go well over that size)Submitted a PR [[https://github.com/anmonteiro/websocketaf/pull/25][here]]* TODO ShardingFirst should actually research how to do it in a worthwhile way+(since we are essencially stuck in single-threaded mode for now)+[2021-2-23 Tue] /Nevermind: Sharding is useful if only to decrease rate limiting bottlenecks./** TODO Identify Concurrency handlingA global lock/token bucket should suffice.Maybe make it a map of ~(bot token)->(token bucket)~ in case the userwants to run multiple different bots in a single application.
* DONE Voice Connection** DONE Voice Gateway Protocol*** DONE IP Discovery** DONE Voice UDP*** DONE Test soundbite-------* TODO Music Player** TODO Replace external ffmpeg/ffprobe process with libav- Will this be a PITA because of all the needed codecswhen building? /probably/- Is it worth it? /no/ (maybe it's actually worse given that ocaml-multicore isn't here yet 😿)- Is it fun? /yeah/ 😝
* DOING Voice connection** DOING Voice Gateway** TODO Voice UDP*** TODO Test soundbiteI think hardcoding some bytes in the codeshould suffice for now
** TODO youtube-dl support** TODO Custom ytdl-like implementationI reckon this is really only worth it if we do the libav thing.-------
]},"overrides": [],"dependencies": [],"devDependencies": []},"esy-libsodium@archive:https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz#sha1:795b73e3f92a362fabee238a71735579bf46bb97@a5898027": {"id":"esy-libsodium@archive:https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz#sha1:795b73e3f92a362fabee238a71735579bf46bb97@a5898027","name": "esy-libsodium","version":"archive:https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz#sha1:795b73e3f92a362fabee238a71735579bf46bb97","source": {"type": "install","source": ["archive:https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz#sha1:795b73e3f92a362fabee238a71735579bf46bb97"]},"overrides": [ "esy.lock/overrides/a589802762d4c745d460324213040534" ],"dependencies": [],"devDependencies": []},"esy-libopus@archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b@24aa01e3": {"id":"esy-libopus@archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b@24aa01e3","name": "esy-libopus","version":"archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b","source": {"type": "install","source": ["archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b"]},"overrides": [ "vendor/esy-libopus/package.json" ],"dependencies": ["@opam/conf-pkg-config@opam:1.3@93481236","@opam/conf-autoconf@github:esy-packages/esy-autoconf:package.json#fb93edf@d41d8cd9"],"devDependencies": []},"esy-libffi@github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c@d41d8cd9": {"id":"esy-libffi@github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c@d41d8cd9","name": "esy-libffi","version":"github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c","source": {"type": "install","source": ["github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c"
"ocaml@4.11.1000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/websocketaf-lwt-unix@link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf-lwt-unix.opam","@opam/websocketaf@link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf.opam",
"ocaml@4.11.2000@d41d8cd9","esy-libsodium@archive:https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz#sha1:795b73e3f92a362fabee238a71735579bf46bb97@a5898027","@opam/yojson@opam:1.7.0@7056d985","@opam/websocketaf-lwt-unix@github:quartz55/websocketaf:websocketaf-lwt-unix.opam#d309d15@d41d8cd9","@opam/websocketaf@github:quartz55/websocketaf:websocketaf.opam#d309d15@d41d8cd9",
"@opam/zed@opam:3.1.0@86c55416": {"id": "@opam/zed@opam:3.1.0@86c55416","name": "@opam/zed","version": "opam:3.1.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/51/51e8676ba972e5ad727633c161e404b1#md5:51e8676ba972e5ad727633c161e404b1","archive:https://github.com/ocaml-community/zed/archive/3.1.0.tar.gz#md5:51e8676ba972e5ad727633c161e404b1"],"opam": {"name": "zed","version": "3.1.0","path": "esy.lock/opam/zed.3.1.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/react@opam:1.2.1@0e11855f","@opam/dune@opam:2.8.4@ee414d6c","@opam/charInfo_width@opam:1.1.0@4296bdfe","@opam/camomile@opam:1.0.2@40411a6b","@opam/base-bytes@opam:base@19d0c2ff","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/react@opam:1.2.1@0e11855f","@opam/dune@opam:2.8.4@ee414d6c","@opam/charInfo_width@opam:1.1.0@4296bdfe","@opam/camomile@opam:1.0.2@40411a6b","@opam/base-bytes@opam:base@19d0c2ff"]},
"ocaml@4.11.1000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.2@3d714e5f", "@opam/cppo@opam:1.6.7@c28ac3ae",
"ocaml@4.11.2000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.4@ee414d6c", "@opam/cppo@opam:1.6.7@c28ac3ae",
"ocaml@4.11.1000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.2@3d714e5f", "@opam/biniou@opam:1.2.1@d7570399"
"ocaml@4.11.2000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.4@ee414d6c", "@opam/biniou@opam:1.2.1@d7570399"
"ocaml@4.11.1000@d41d8cd9","@opam/websocketaf-lwt@link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf-lwt.opam","@opam/websocketaf@link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf.opam",
"ocaml@4.11.2000@d41d8cd9","@opam/websocketaf-lwt@github:quartz55/websocketaf:websocketaf-lwt.opam#d309d15@d41d8cd9","@opam/websocketaf@github:quartz55/websocketaf:websocketaf.opam#d309d15@d41d8cd9",
"ocaml@4.11.1000@d41d8cd9","@opam/websocketaf-lwt@link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf-lwt.opam","@opam/websocketaf@link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf.opam",
"ocaml@4.11.2000@d41d8cd9","@opam/websocketaf-lwt@github:quartz55/websocketaf:websocketaf-lwt.opam#d309d15@d41d8cd9","@opam/websocketaf@github:quartz55/websocketaf:websocketaf.opam#d309d15@d41d8cd9",
"@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/utop@opam:2.7.0@4ba5133d": {"id": "@opam/utop@opam:2.7.0@4ba5133d","name": "@opam/utop","version": "opam:2.7.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/e0/e068ac53df267c3cc0f2f69bbc204404f0362cc4e6472a1fc547e326a63c3fdd#sha256:e068ac53df267c3cc0f2f69bbc204404f0362cc4e6472a1fc547e326a63c3fdd","archive:https://github.com/ocaml-community/utop/releases/download/2.7.0/utop-2.7.0.tbz#sha256:e068ac53df267c3cc0f2f69bbc204404f0362cc4e6472a1fc547e326a63c3fdd"],"opam": {"name": "utop","version": "2.7.0","path": "esy.lock/opam/utop.2.7.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/react@opam:1.2.1@0e11855f","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/lwt_react@opam:1.1.4@7d2054d1","@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/lambda-term@opam:3.1.0@8adc2660","@opam/dune@opam:2.8.4@ee414d6c", "@opam/cppo@opam:1.6.7@c28ac3ae","@opam/camomile@opam:1.0.2@40411a6b","@opam/base-unix@opam:base@87d0b2eb","@opam/base-threads@opam:base@36803084",
"devDependencies": [ "ocaml@4.11.1000@d41d8cd9" ]
"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/react@opam:1.2.1@0e11855f","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/lwt_react@opam:1.1.4@7d2054d1","@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/lambda-term@opam:3.1.0@8adc2660","@opam/dune@opam:2.8.4@ee414d6c","@opam/camomile@opam:1.0.2@40411a6b","@opam/base-unix@opam:base@87d0b2eb","@opam/base-threads@opam:base@36803084"]
"@opam/dune@opam:2.8.2@3d714e5f"
"@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/trie@opam:1.0.0@d2efc587": {"id": "@opam/trie@opam:1.0.0@d2efc587","name": "@opam/trie","version": "opam:1.0.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/84/84519b5f8bd92490bfc68a52f706ba14#md5:84519b5f8bd92490bfc68a52f706ba14","archive:https://github.com/kandu/trie/archive/1.0.0.tar.gz#md5:84519b5f8bd92490bfc68a52f706ba14"],"opam": {"name": "trie","version": "1.0.0","path": "esy.lock/opam/trie.1.0.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"
"@opam/stdint@opam:0.7.0@f8c664d1": {"id": "@opam/stdint@opam:0.7.0@f8c664d1","name": "@opam/stdint","version": "opam:0.7.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/4f/4fcc66aef58e2b96e7af3bbca9d910aa239e045ba5fb2400aaef67d0041252dc#sha256:4fcc66aef58e2b96e7af3bbca9d910aa239e045ba5fb2400aaef67d0041252dc","archive:https://github.com/andrenth/ocaml-stdint/releases/download/0.7.0/stdint-0.7.0.tbz#sha256:4fcc66aef58e2b96e7af3bbca9d910aa239e045ba5fb2400aaef67d0041252dc"],"opam": {"name": "stdint","version": "0.7.0","path": "esy.lock/opam/stdint.0.7.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},
"@opam/sodium@github:quartz55/ocaml-sodium:sodium.opam#6088c1c@32227790": {"id":"@opam/sodium@github:quartz55/ocaml-sodium:sodium.opam#6088c1c@32227790","name": "@opam/sodium","version": "github:quartz55/ocaml-sodium:sodium.opam#6088c1c","source": {"type": "install","source": [ "github:quartz55/ocaml-sodium:sodium.opam#6088c1c" ]},"overrides": [ { "dependencies": { "@opam/conf-libsodium": "*" } } ],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/ocamlbuild@opam:0.14.0@6ac75d03","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c","@opam/ctypes@opam:0.18.0@1be5c5e5","@opam/conf-libsodium@github:EduardoRFS/esy-libsodium:libsodium.opam#caeedd7@d003f610","@opam/base-bytes@opam:base@19d0c2ff","@opam/base-bigarray@opam:base@b03491b0","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ctypes@opam:0.18.0@1be5c5e5","@opam/base-bytes@opam:base@19d0c2ff","@opam/base-bigarray@opam:base@b03491b0"]},
},"@opam/react@opam:1.2.1@0e11855f": {"id": "@opam/react@opam:1.2.1@0e11855f","name": "@opam/react","version": "opam:1.2.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/ce/ce1454438ce4e9d2931248d3abba1fcc#md5:ce1454438ce4e9d2931248d3abba1fcc","archive:http://erratique.ch/software/react/releases/react-1.2.1.tbz#md5:ce1454438ce4e9d2931248d3abba1fcc"],"opam": {"name": "react","version": "1.2.1","path": "esy.lock/opam/react.1.2.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/topkg@opam:1.0.3@e4e10f1c","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/ocamlbuild@opam:0.14.0@6ac75d03","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]
"ocaml@4.11.1000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.1000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.1000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.1000@d41d8cd9", "@opam/dune@opam:2.8.2@3d714e5f"
"ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/ppx_cstubs@opam:0.6.1.1@706c3a9f": {"id": "@opam/ppx_cstubs@opam:0.6.1.1@706c3a9f","name": "@opam/ppx_cstubs","version": "opam:0.6.1.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/33/33e520e369da5630c697318f6f4ed26d#md5:33e520e369da5630c697318f6f4ed26d","archive:https://github.com/fdopen/ppx_cstubs/archive/0.6.1.1.tar.gz#md5:33e520e369da5630c697318f6f4ed26d"],"opam": {"name": "ppx_cstubs","version": "0.6.1.1","path": "esy.lock/opam/ppx_cstubs.0.6.1.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/re@opam:1.9.0@d4d5e13d", "@opam/ppxlib@opam:0.22.0@d2d2223a","@opam/ocamlfind@opam:1.8.1@b7dc3072", "@opam/num@opam:1.4@a5195c8d","@opam/integers@opam:0.4.0@f7acfaeb","@opam/dune@opam:2.8.4@ee414d6c","@opam/ctypes@opam:0.18.0@1be5c5e5","@opam/cppo@opam:1.6.7@c28ac3ae","@opam/containers@opam:3.2@c4e3f662","@opam/bigarray-compat@opam:1.0.0@3a87ad65","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/re@opam:1.9.0@d4d5e13d", "@opam/ppxlib@opam:0.22.0@d2d2223a","@opam/ocamlfind@opam:1.8.1@b7dc3072", "@opam/num@opam:1.4@a5195c8d","@opam/integers@opam:0.4.0@f7acfaeb","@opam/dune@opam:2.8.4@ee414d6c","@opam/ctypes@opam:0.18.0@1be5c5e5","@opam/containers@opam:3.2@c4e3f662","@opam/bigarray-compat@opam:1.0.0@3a87ad65"
"archive:https://opam.ocaml.org/cache/sha256/24/24b2f324ea91cff98bb8790a6746ccce3173bac5f57cb457156e5c50a0467397#sha256:24b2f324ea91cff98bb8790a6746ccce3173bac5f57cb457156e5c50a0467397","archive:https://github.com/ocurrent/ocaml-version/releases/download/v3.0.0/ocaml-version-v3.0.0.tbz#sha256:24b2f324ea91cff98bb8790a6746ccce3173bac5f57cb457156e5c50a0467397"
"archive:https://opam.ocaml.org/cache/sha256/ac/ac7ba16a09d8f72212742f3936980fbfaebb698c7bbf625182af7d6b2c3cde5f#sha256:ac7ba16a09d8f72212742f3936980fbfaebb698c7bbf625182af7d6b2c3cde5f","archive:https://github.com/ocurrent/ocaml-version/releases/download/v3.1.0/ocaml-version-v3.1.0.tbz#sha256:ac7ba16a09d8f72212742f3936980fbfaebb698c7bbf625182af7d6b2c3cde5f"
"@opam/num@opam:1.4@a5195c8d": {"id": "@opam/num@opam:1.4@a5195c8d","name": "@opam/num","version": "opam:1.4","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/cd/cda2b727e116a0b6a9c03902cc4b2415#md5:cda2b727e116a0b6a9c03902cc4b2415","archive:https://github.com/ocaml/num/archive/v1.4.tar.gz#md5:cda2b727e116a0b6a9c03902cc4b2415"],"opam": {"name": "num","version": "1.4","path": "esy.lock/opam/num.1.4"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__num_opam__c__1.4_opam_override"}],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ocamlfind@opam:1.8.1@b7dc3072","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},
"ocaml@4.11.1000@d41d8cd9", "@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/mew_vi@opam:0.5.0@cf66c299": {"id": "@opam/mew_vi@opam:0.5.0@cf66c299","name": "@opam/mew_vi","version": "opam:0.5.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/34/341e9a9a20383641015bf503952906bc#md5:341e9a9a20383641015bf503952906bc","archive:https://github.com/kandu/mew_vi/archive/0.5.0.tar.gz#md5:341e9a9a20383641015bf503952906bc"],"opam": {"name": "mew_vi","version": "0.5.0","path": "esy.lock/opam/mew_vi.0.5.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/react@opam:1.2.1@0e11855f","@opam/mew@opam:0.1.0@a74f69d6", "@opam/dune@opam:2.8.4@ee414d6c",
"ocaml@4.11.1000@d41d8cd9", "@opam/dune@opam:2.8.2@3d714e5f"
"ocaml@4.11.2000@d41d8cd9", "@opam/react@opam:1.2.1@0e11855f","@opam/mew@opam:0.1.0@a74f69d6", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/mew@opam:0.1.0@a74f69d6": {"id": "@opam/mew@opam:0.1.0@a74f69d6","name": "@opam/mew","version": "opam:0.1.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/22/2298149d1415cd804ab4e01f01ea10a0#md5:2298149d1415cd804ab4e01f01ea10a0","archive:https://github.com/kandu/mew/archive/0.1.0.tar.gz#md5:2298149d1415cd804ab4e01f01ea10a0"],"opam": {"name": "mew","version": "0.1.0","path": "esy.lock/opam/mew.0.1.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/trie@opam:1.0.0@d2efc587","@opam/result@opam:1.5@6b753c82", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/trie@opam:1.0.0@d2efc587","@opam/result@opam:1.5@6b753c82", "@opam/dune@opam:2.8.4@ee414d6c"
"ocaml@4.11.1000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/result@opam:1.5@6b753c82", "@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/result@opam:1.5@6b753c82", "@opam/dune@opam:2.8.4@ee414d6c",
"ocaml@4.11.1000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/result@opam:1.5@6b753c82", "@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/result@opam:1.5@6b753c82", "@opam/dune@opam:2.8.4@ee414d6c",
"archive:https://opam.ocaml.org/cache/md5/f2/f27f8f5dedd316eff4c02d9130fced49#md5:f27f8f5dedd316eff4c02d9130fced49","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20201216/archive.tar.gz#md5:f27f8f5dedd316eff4c02d9130fced49"
"archive:https://opam.ocaml.org/cache/md5/1c/1cbc71c0bc1f3ddc3e71d5c1f919fd1a#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a"
"archive:https://opam.ocaml.org/cache/md5/f2/f27f8f5dedd316eff4c02d9130fced49#md5:f27f8f5dedd316eff4c02d9130fced49","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20201216/archive.tar.gz#md5:f27f8f5dedd316eff4c02d9130fced49"
"archive:https://opam.ocaml.org/cache/md5/1c/1cbc71c0bc1f3ddc3e71d5c1f919fd1a#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a"
"archive:https://opam.ocaml.org/cache/md5/f2/f27f8f5dedd316eff4c02d9130fced49#md5:f27f8f5dedd316eff4c02d9130fced49","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20201216/archive.tar.gz#md5:f27f8f5dedd316eff4c02d9130fced49"
"archive:https://opam.ocaml.org/cache/md5/1c/1cbc71c0bc1f3ddc3e71d5c1f919fd1a#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a"
"ocaml@4.11.1000@d41d8cd9", "@opam/menhirSdk@opam:20201216@5e08e674","@opam/menhirLib@opam:20201216@bb5a1851","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/menhirSdk@opam:20210310@5abaafca","@opam/menhirLib@opam:20210310@f9315713","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.1000@d41d8cd9", "@opam/menhirSdk@opam:20201216@5e08e674","@opam/menhirLib@opam:20201216@bb5a1851","@opam/dune@opam:2.8.2@3d714e5f"
"ocaml@4.11.2000@d41d8cd9", "@opam/menhirSdk@opam:20210310@5abaafca","@opam/menhirLib@opam:20210310@f9315713","@opam/dune@opam:2.8.4@ee414d6c"
"ocaml@4.11.1000@d41d8cd9", "@opam/ssl@opam:0.5.10@ae7a31df","@opam/lwt@opam:5.4.0@1ec6dbfd", "@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/ssl@opam:0.5.10@ae7a31df","@opam/lwt@opam:5.4.0@1ec6dbfd", "@opam/dune@opam:2.8.4@ee414d6c",
"ocaml@4.11.1000@d41d8cd9", "@opam/ssl@opam:0.5.10@ae7a31df","@opam/lwt@opam:5.4.0@1ec6dbfd", "@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/ssl@opam:0.5.10@ae7a31df","@opam/lwt@opam:5.4.0@1ec6dbfd", "@opam/dune@opam:2.8.4@ee414d6c",
"@opam/lwt_react@opam:1.1.4@7d2054d1": {"id": "@opam/lwt_react@opam:1.1.4@7d2054d1","name": "@opam/lwt_react","version": "opam:1.1.4","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/fc/fc4721bdb1a01225b96e3a2debde95fa#md5:fc4721bdb1a01225b96e3a2debde95fa","archive:https://github.com/ocsigen/lwt/archive/5.4.0.zip#md5:fc4721bdb1a01225b96e3a2debde95fa"],"opam": {"name": "lwt_react","version": "1.1.4","path": "esy.lock/opam/lwt_react.1.1.4"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/react@opam:1.2.1@0e11855f","@opam/lwt@opam:5.4.0@1ec6dbfd", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/react@opam:1.2.1@0e11855f","@opam/lwt@opam:5.4.0@1ec6dbfd", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/lwt_log@opam:1.1.1@2d7a797f": {"id": "@opam/lwt_log@opam:1.1.1@2d7a797f","name": "@opam/lwt_log","version": "opam:1.1.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/02/02e93be62288037870ae5b1ce099fe59#md5:02e93be62288037870ae5b1ce099fe59","archive:https://github.com/aantron/lwt_log/archive/1.1.1.tar.gz#md5:02e93be62288037870ae5b1ce099fe59"],"opam": {"name": "lwt_log","version": "1.1.1","path": "esy.lock/opam/lwt_log.1.1.1"}},"overrides": [],"dependencies": ["@opam/lwt@opam:5.4.0@1ec6dbfd", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["@opam/lwt@opam:5.4.0@1ec6dbfd", "@opam/dune@opam:2.8.4@ee414d6c"]},
"ocaml@4.11.1000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/lambda-term@opam:3.1.0@8adc2660": {"id": "@opam/lambda-term@opam:3.1.0@8adc2660","name": "@opam/lambda-term","version": "opam:3.1.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/78/78180c04ecfc8060b23d7d0014f24196#md5:78180c04ecfc8060b23d7d0014f24196","archive:https://github.com/ocaml-community/lambda-term/archive/3.1.0.tar.gz#md5:78180c04ecfc8060b23d7d0014f24196"],"opam": {"name": "lambda-term","version": "3.1.0","path": "esy.lock/opam/lambda-term.3.1.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/zed@opam:3.1.0@86c55416","@opam/react@opam:1.2.1@0e11855f","@opam/mew_vi@opam:0.5.0@cf66c299","@opam/lwt_react@opam:1.1.4@7d2054d1","@opam/lwt_log@opam:1.1.1@2d7a797f", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/dune@opam:2.8.4@ee414d6c","@opam/camomile@opam:1.0.2@40411a6b",
"devDependencies": [ "ocaml@4.11.1000@d41d8cd9" ]
"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/zed@opam:3.1.0@86c55416","@opam/react@opam:1.2.1@0e11855f","@opam/mew_vi@opam:0.5.0@cf66c299","@opam/lwt_react@opam:1.1.4@7d2054d1","@opam/lwt_log@opam:1.1.1@2d7a797f", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/dune@opam:2.8.4@ee414d6c","@opam/camomile@opam:1.0.2@40411a6b"]},"@opam/integers@opam:0.4.0@f7acfaeb": {"id": "@opam/integers@opam:0.4.0@f7acfaeb","name": "@opam/integers","version": "opam:0.4.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/c1/c1492352e6525048790508c57aad93c3#md5:c1492352e6525048790508c57aad93c3","archive:https://github.com/ocamllabs/ocaml-integers/archive/0.4.0.tar.gz#md5:c1492352e6525048790508c57aad93c3"],"opam": {"name": "integers","version": "0.4.0","path": "esy.lock/opam/integers.0.4.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/hxd@opam:0.3.1@a1c09d49": {"id": "@opam/hxd@opam:0.3.1@a1c09d49","name": "@opam/hxd","version": "opam:0.3.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/1c/1c226c91e17cd329dec0c287bfd20f36302aa533069ff9c6ced32721f96b29bc#sha256:1c226c91e17cd329dec0c287bfd20f36302aa533069ff9c6ced32721f96b29bc","archive:https://github.com/dinosaure/hxd/releases/download/v0.3.1/hxd-v0.3.1.tbz#sha256:1c226c91e17cd329dec0c287bfd20f36302aa533069ff9c6ced32721f96b29bc"],"opam": {"name": "hxd","version": "0.3.1","path": "esy.lock/opam/hxd.0.3.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c","@opam/cmdliner@opam:1.0.4@93208aac","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c","@opam/cmdliner@opam:1.0.4@93208aac"]
"ocaml@4.11.1000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/gluten@opam:0.2.1@fca26440", "@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/gluten@opam:0.2.1@fca26440", "@opam/dune@opam:2.8.4@ee414d6c",
"ocaml@4.11.1000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/gluten@opam:0.2.1@fca26440", "@opam/dune@opam:2.8.2@3d714e5f"
"ocaml@4.11.2000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/gluten@opam:0.2.1@fca26440", "@opam/dune@opam:2.8.4@ee414d6c"
"ocaml@4.11.1000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/faraday@opam:0.7.2@5dfdf1f9", "@opam/dune@opam:2.8.2@3d714e5f"
"ocaml@4.11.2000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/faraday@opam:0.7.2@5dfdf1f9", "@opam/dune@opam:2.8.4@ee414d6c"
"archive:https://opam.ocaml.org/cache/sha256/e2/e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e#sha256:e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e","archive:https://github.com/ocaml/dune/releases/download/2.8.2/dune-2.8.2.tbz#sha256:e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e"
"archive:https://opam.ocaml.org/cache/sha256/4e/4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac","archive:https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac"
"ocaml@4.11.1000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.2@3d714e5f", "@opam/csexp@opam:1.4.0@bd1cb034",
"ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c", "@opam/csexp@opam:1.4.0@bd1cb034",
"ocaml@4.11.1000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.2@3d714e5f", "@opam/csexp@opam:1.4.0@bd1cb034"
"ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c", "@opam/csexp@opam:1.4.0@bd1cb034"
"archive:https://opam.ocaml.org/cache/sha256/e2/e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e#sha256:e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e","archive:https://github.com/ocaml/dune/releases/download/2.8.2/dune-2.8.2.tbz#sha256:e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e"
"archive:https://opam.ocaml.org/cache/sha256/4e/4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac","archive:https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac"
"archive:https://opam.ocaml.org/cache/sha256/e2/e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e#sha256:e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e","archive:https://github.com/ocaml/dune/releases/download/2.8.2/dune-2.8.2.tbz#sha256:e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e"
"archive:https://opam.ocaml.org/cache/sha256/4e/4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac","archive:https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac"
"ocaml@4.11.1000@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/eqaf@opam:0.7@e7d6447e", "@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/eqaf@opam:0.7@e7d6447e", "@opam/dune@opam:2.8.4@ee414d6c",
"ocaml@4.11.1000@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/eqaf@opam:0.7@e7d6447e", "@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/eqaf@opam:0.7@e7d6447e", "@opam/dune@opam:2.8.4@ee414d6c",
},"@opam/ctypes-foreign@opam:0.4.0@6d218780": {"id": "@opam/ctypes-foreign@opam:0.4.0@6d218780","name": "@opam/ctypes-foreign","version": "opam:0.4.0","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "ctypes-foreign","version": "0.4.0","path": "esy.lock/opam/ctypes-foreign.0.4.0"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__ctypes_foreign_opam__c__0.4.0_opam_override"}],"dependencies": ["@opam/conf-libffi@opam:2.0.0@7c8981c5","@esy-ocaml/substs@0.0.1@d41d8cd9","@esy-ocaml/libffi@3.2.10@d41d8cd9"],"devDependencies": [ "@opam/conf-libffi@opam:2.0.0@7c8981c5" ]
"@opam/ctypes@opam:0.18.0@1be5c5e5": {"id": "@opam/ctypes@opam:0.18.0@1be5c5e5","name": "@opam/ctypes","version": "opam:0.18.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/5d/5d9ef3790fda7cd97a8cec08be4b5b61#md5:5d9ef3790fda7cd97a8cec08be4b5b61","archive:https://github.com/ocamllabs/ocaml-ctypes/archive/0.18.0.tar.gz#md5:5d9ef3790fda7cd97a8cec08be4b5b61"],"opam": {"name": "ctypes","version": "0.18.0","path": "esy.lock/opam/ctypes.0.18.0"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__ctypes_opam__c__0.18.0_opam_override"}],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/integers@opam:0.4.0@f7acfaeb","@opam/ctypes-foreign@opam:0.4.0@6d218780","@opam/bigarray-compat@opam:1.0.0@3a87ad65","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/integers@opam:0.4.0@f7acfaeb","@opam/bigarray-compat@opam:1.0.0@3a87ad65"]},
"ocaml@4.11.1000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.1000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune-configurator@opam:2.8.2@c90ff40b","@opam/dune@opam:2.8.2@3d714e5f",
"ocaml@4.11.2000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c",
"ocaml@4.11.1000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune-configurator@opam:2.8.2@c90ff40b","@opam/dune@opam:2.8.2@3d714e5f"
"ocaml@4.11.2000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c"
"@opam/conf-pkg-config@opam:1.3@93481236","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": []},"@opam/conf-libsodium@github:EduardoRFS/esy-libsodium:libsodium.opam#caeedd7@d003f610": {"id":"@opam/conf-libsodium@github:EduardoRFS/esy-libsodium:libsodium.opam#caeedd7@d003f610","name": "@opam/conf-libsodium","version": "github:EduardoRFS/esy-libsodium:libsodium.opam#caeedd7","source": {"type": "install","source": ["github:EduardoRFS/esy-libsodium:libsodium.opam#caeedd7"]},"overrides": [{"dependencies": {"esy-libsodium": "github:EduardoRFS/esy-libsodium#caeedd7"}}],"dependencies": ["esy-libsodium@archive:https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz#sha1:795b73e3f92a362fabee238a71735579bf46bb97@a5898027",
"@opam/conf-libopus@link:vendor/esy-libopus/conf-libopus.opam": {"id": "@opam/conf-libopus@link:vendor/esy-libopus/conf-libopus.opam","name": "@opam/conf-libopus","version": "link:vendor/esy-libopus/conf-libopus.opam","source": {"type": "link","path": "vendor/esy-libopus","manifest": "conf-libopus.opam"},"overrides": [{ "dependencies": { "esy-libopus": "./vendor/esy-libopus" } }],"dependencies": ["esy-libopus@archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b@24aa01e3","@opam/conf-pkg-config@opam:1.3@93481236","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": []},"@opam/conf-libffi@opam:2.0.0@7c8981c5": {"id": "@opam/conf-libffi@opam:2.0.0@7c8981c5","name": "@opam/conf-libffi","version": "opam:2.0.0","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "conf-libffi","version": "2.0.0","path": "esy.lock/opam/conf-libffi.2.0.0"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__conf_libffi_opam__c__2.0.0_opam_override"}],"dependencies": ["esy-libffi@github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c@d41d8cd9","@opam/conf-pkg-config@opam:1.3@93481236","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": []},
"devDependencies": [ "ocaml@4.11.1000@d41d8cd9" ]
"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/charInfo_width@opam:1.1.0@4296bdfe": {"id": "@opam/charInfo_width@opam:1.1.0@4296bdfe","name": "@opam/charInfo_width","version": "opam:1.1.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/a5/a539436d1da4aeb93711303f107bec7e#md5:a539436d1da4aeb93711303f107bec7e","archive:https://github.com/kandu/charInfo_width/archive/1.1.0.tar.gz#md5:a539436d1da4aeb93711303f107bec7e"],"opam": {"name": "charInfo_width","version": "1.1.0","path": "esy.lock/opam/charInfo_width.1.1.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c","@opam/camomile@opam:1.0.2@40411a6b","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c","@opam/camomile@opam:1.0.2@40411a6b"]},"@opam/camomile@opam:1.0.2@40411a6b": {"id": "@opam/camomile@opam:1.0.2@40411a6b","name": "@opam/camomile","version": "opam:1.0.2","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/f0/f0a419b0affc36500f83b086ffaa36c545560cee5d57e84b729e8f851b3d1632#sha256:f0a419b0affc36500f83b086ffaa36c545560cee5d57e84b729e8f851b3d1632","archive:https://github.com/yoriyuki/Camomile/releases/download/1.0.2/camomile-1.0.2.tbz#sha256:f0a419b0affc36500f83b086ffaa36c545560cee5d57e84b729e8f851b3d1632"],"opam": {"name": "camomile","version": "1.0.2","path": "esy.lock/opam/camomile.1.0.2"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]
"ocaml@4.11.1000@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.1000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"@opam/base-bigarray@opam:base@b03491b0": {"id": "@opam/base-bigarray@opam:base@b03491b0","name": "@opam/base-bigarray","version": "opam:base","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "base-bigarray","version": "base","path": "esy.lock/opam/base-bigarray.base"}},"overrides": [],"dependencies": [ "@esy-ocaml/substs@0.0.1@d41d8cd9" ],"devDependencies": []},
"ocaml@4.11.1000@d41d8cd9", "@opam/sexplib0@opam:v0.14.0@ddeb6438","@opam/dune-configurator@opam:2.8.2@c90ff40b","@opam/dune@opam:2.8.2@3d714e5f", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.2000@d41d8cd9", "@opam/sexplib0@opam:v0.14.0@ddeb6438","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"
"ocaml@4.11.1000@d41d8cd9", "@opam/sexplib0@opam:v0.14.0@ddeb6438","@opam/dune-configurator@opam:2.8.2@c90ff40b","@opam/dune@opam:2.8.2@3d714e5f"
"ocaml@4.11.2000@d41d8cd9", "@opam/sexplib0@opam:v0.14.0@ddeb6438","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c"
"devDependencies": [ "ocaml@4.11.1000@d41d8cd9" ]
"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/angstrom-lwt-unix@opam:0.15.0@2ffc8053": {"id": "@opam/angstrom-lwt-unix@opam:0.15.0@2ffc8053","name": "@opam/angstrom-lwt-unix","version": "opam:0.15.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/51/5104768c404ea92fd0a53a5b0f75cd50#md5:5104768c404ea92fd0a53a5b0f75cd50","archive:https://github.com/inhabitedtype/angstrom/archive/0.15.0.tar.gz#md5:5104768c404ea92fd0a53a5b0f75cd50"],"opam": {"name": "angstrom-lwt-unix","version": "0.15.0","path": "esy.lock/opam/angstrom-lwt-unix.0.15.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/dune@opam:2.8.4@ee414d6c","@opam/base-unix@opam:base@87d0b2eb","@opam/angstrom@opam:0.15.0@48ede9cb","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/lwt@opam:5.4.0@1ec6dbfd","@opam/dune@opam:2.8.4@ee414d6c","@opam/base-unix@opam:base@87d0b2eb","@opam/angstrom@opam:0.15.0@48ede9cb"]
"@opam/menhir@opam:20201216@1a09d886","@opam/fix@opam:20201120@5c318621", "@opam/dune@opam:2.8.2@3d714e5f"
"@opam/menhir@opam:20210310@50de9216","@opam/fix@opam:20201120@5c318621", "@opam/dune@opam:2.8.4@ee414d6c"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@esy-ocaml/libffi@3.2.10@d41d8cd9": {"id": "@esy-ocaml/libffi@3.2.10@d41d8cd9","name": "@esy-ocaml/libffi","version": "3.2.10","source": {"type": "install","source": ["archive:https://registry.npmjs.org/@esy-ocaml/libffi/-/libffi-3.2.10.tgz#sha1:72697f135ee228b94294ec32f0d5b0fa313de403"]},"overrides": [],"dependencies": [],"devDependencies": []},"@discopotty/opus@link:vendor/opus/package.json": {"id": "@discopotty/opus@link:vendor/opus/package.json","name": "@discopotty/opus","version": "link:vendor/opus/package.json","source": {"type": "link","path": "vendor/opus","manifest": "package.json"},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ppx_cstubs@opam:0.6.1.1@706c3a9f","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/dune@opam:2.8.4@ee414d6c","@opam/ctypes-foreign@opam:0.4.0@6d218780","@opam/ctypes@opam:0.18.0@1be5c5e5","@opam/conf-libopus@link:vendor/esy-libopus/conf-libopus.opam"
opam-version: "2.0"maintainer: "Spiros Eliopoulos <spiros@inhabitedtype.com>"authors: [ "Spiros Eliopoulos <spiros@inhabitedtype.com>" ]license: "BSD-3-clause"homepage: "https://github.com/inhabitedtype/angstrom"bug-reports: "https://github.com/inhabitedtype/angstrom/issues"dev-repo: "git+https://github.com/inhabitedtype/angstrom.git"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]depends: ["ocaml" {>= "4.03.0"}"dune" {>= "1.8"}"angstrom""lwt""base-unix"]synopsis: "Lwt_unix support for Angstrom"url {src: "https://github.com/inhabitedtype/angstrom/archive/0.15.0.tar.gz"checksum: "md5=5104768c404ea92fd0a53a5b0f75cd50"}
opam-version: "2.0"maintainer: "https://github.com/ocaml/opam-repository/issues"description: """Bigarray library distributed with the OCaml compiler"""
opam-version: "2.0"synopsis: "A Unicode library"description: """Camomile is a Unicode library for OCaml. Camomile provides Unicode charactertype, UTF-8, UTF-16, UTF-32 strings, conversion to/from about 200 encodings,collation and locale-sensitive case mappings, and more. The library is currentlydesigned for Unicode Standard 3.2."""maintainer: ["yoriyuki.y@gmail.com"]authors: ["Yoriyuki Yamagata"]license: "LGPL-2.1-or-later with OCaml-LGPL-linking-exception"homepage: "https://github.com/yoriyuki/Camomile"doc: "https://yoriyuki.github.io/Camomile/"bug-reports: "https://github.com/yoriyuki/Camomile/issues"depends: ["dune" {>= "1.11"}"ocaml" {>= "4.02.3"}]dev-repo: "git+https://github.com/yoriyuki/Camomile.git"build: [["ocaml" "configure.ml" "--share" "%{share}%/camomile"]["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs"@install""@doc" {with-doc}]]url {src:"https://github.com/yoriyuki/Camomile/releases/download/1.0.2/camomile-1.0.2.tbz"checksum: ["sha256=f0a419b0affc36500f83b086ffaa36c545560cee5d57e84b729e8f851b3d1632""sha512=7586422e68779476206027c6ebbe19b677fbe459153221f7c952c7fae374c5c8232249cb76fdb1f482069707aa1580be827cd39693906142988268b7f0e7f6d0"]}available: arch != "ppc64"
opam-version: "2.0"maintainer: "zandoye@gmail.com"authors: [ "ZAN DoYe" ]homepage: "https://github.com/kandu/charinfo_width/"bug-reports: "https://github.com/kandu/charinfo_width/issues"license: "MIT"dev-repo: "git://github.com/kandu/charinfo_width.git"build: [["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test & (ocaml:version >= "4.04.0")}]depends: ["ocaml" {>= "4.02.3"}"result""camomile" {>= "1.0.0" & < "2.0~"}"dune""ppx_expect" {with-test & < "v0.15"}]synopsis: "Determine column width for a character"description: """This module is implemented purely in OCaml and the width function follows the prototype of POSIX's wcwidth."""url {src:"https://github.com/kandu/charInfo_width/archive/1.1.0.tar.gz"checksum: "md5=a539436d1da4aeb93711303f107bec7e"}
opam-version: "2.0"maintainer: "blue-prawn"authors: ["Anthony Green"]homepage: "http://sourceware.org/libffi/"license: "MIT"build: ["pkg-config" "libffi"]depexts: [["libffi"] {os = "macos" & os-distribution = "homebrew"}["libffi"] {os = "macos" & os-distribution = "macports"}["libffi-dev"] {os-distribution = "alpine"}["libffi-dev"] {os-family = "debian"}["libffi-devel"] {os-distribution = "centos"}["libffi-devel"] {os-distribution = "fedora"}["libffi-devel"] {os-distribution = "mageia"}["libffi-devel"] {os-distribution = "ol"}["libffi-devel"] {os-family = "suse"}]synopsis: "Virtual package relying on libffi system installation"description: "This package can only install if libffi is installed on the system."depends: ["conf-pkg-config" {build}]bug-reports: "https://github.com/ocaml/opam-repository/issues"flags: conf
opam-version: "2.0"maintainer: "yallop@gmail.com"homepage: "https://github.com/ocamllabs/ocaml-ctypes"dev-repo: "git+http://github.com/ocamllabs/ocaml-ctypes.git"bug-reports: "http://github.com/ocamllabs/ocaml-ctypes/issues"depends: ["conf-libffi" {>= "2.0.0"}]tags: ["org:ocamllabs" "org:mirage"]post-messages: ["This package requires libffi on your system" {failure}]synopsis: "Virtual package for enabling the ctypes.foreign subpackage."description: """`ctypes-foreign` is just a virtual OPAM package that determineswhether the foreign subpackage should built as part of ctypes.In order to actually get the ctypes package, you should also:opam install ctypes ctypes-foreignYou can verify the existence of the ocamlfind subpackage by:ocamlfind list | grep ctypesWhich should output something like:ctypes (version: 0.4.1)ctypes.foreign (version: 0.4.1)ctypes.foreign.base (version: 0.4.1)ctypes.foreign.threaded (version: 0.4.1)ctypes.foreign.unthreaded (version: 0.4.1)ctypes.stubs (version: 0.4.1)ctypes.top (version: 0.4.1)"""authors: "yallop@gmail.com"
opam-version: "2.0"maintainer: "yallop@gmail.com"homepage: "https://github.com/ocamllabs/ocaml-ctypes"doc: "http://ocamllabs.github.io/ocaml-ctypes"dev-repo: "git+http://github.com/ocamllabs/ocaml-ctypes.git"bug-reports: "http://github.com/ocamllabs/ocaml-ctypes/issues"license: "MIT"build: [[make "XEN=%{mirage-xen:enable}%" "libffi.config"]{ctypes-foreign:installed}["touch" "libffi.config"] {!ctypes-foreign:installed}[make "XEN=%{mirage-xen:enable}%" "ctypes-base" "ctypes-stubs"][make "XEN=%{mirage-xen:enable}%" "ctypes-foreign"]{ctypes-foreign:installed}[make "test"] {with-test}]install: [[make "install" "XEN=%{mirage-xen:enable}%"]]depends: ["ocaml" {>= "4.02.3"}"integers" { >= "0.3.0" }"ocamlfind" {build}"lwt" {with-test & >= "3.2.0"}"ctypes-foreign" {with-test}"ounit" {with-test}"conf-ncurses" {with-test}"bigarray-compat"]depopts: ["ctypes-foreign""mirage-xen"]tags: ["org:ocamllabs" "org:mirage"]synopsis: "Combinators for binding to C libraries without writing any C"description: """ctypes is a library for binding to C libraries using pure OCaml. The primaryaim is to make writing C extensions as straightforward as possible.The core of ctypes is a set of combinators for describing the structure of Ctypes -- numeric types, arrays, pointers, structs, unions and functions. Youcan use these combinators to describe the types of the functions that you wantto call, then bind directly to those functions -- all without writing orgenerating any C!To install the optional `ctypes.foreign` interface (which uses `libffi` toprovide dynamic access to foreign libraries), you will need to also installthe `ctypes-foreign` optional dependency:opam install ctypes ctypes-foreignThis will make the `ctypes.foreign` ocamlfind subpackage available."""authors: "yallop@gmail.com"url {src: "https://github.com/ocamllabs/ocaml-ctypes/archive/0.18.0.tar.gz"checksum: "md5=5d9ef3790fda7cd97a8cec08be4b5b61"}conflicts: ["mirage-xen" {>= "6.0.0"}]
"sha256=e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e""sha512=d3cca73f5a72440273f7b4e3934dfa7e89fcb64710f3c734d2583123f5d9f3e573f0ab96a4892b2f11313038da6b4e2c614951199ffef0a3f12669d729b25376"
"sha256=4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac""sha512=efc1834c4add40138a101734665a1f462c19fe76d1cbb457b1fc20f95991118a50b24d485fb98d39046e41bec03885a8dc071bf8add51083ac9780bff9f6668a"
"sha256=e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e""sha512=d3cca73f5a72440273f7b4e3934dfa7e89fcb64710f3c734d2583123f5d9f3e573f0ab96a4892b2f11313038da6b4e2c614951199ffef0a3f12669d729b25376"
"sha256=4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac""sha512=efc1834c4add40138a101734665a1f462c19fe76d1cbb457b1fc20f95991118a50b24d485fb98d39046e41bec03885a8dc071bf8add51083ac9780bff9f6668a"
"sha256=e2c4e8230f7c96236503fd75f22bdbc263639971bf104509e446855ded35ae1e""sha512=d3cca73f5a72440273f7b4e3934dfa7e89fcb64710f3c734d2583123f5d9f3e573f0ab96a4892b2f11313038da6b4e2c614951199ffef0a3f12669d729b25376"
"sha256=4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac""sha512=efc1834c4add40138a101734665a1f462c19fe76d1cbb457b1fc20f95991118a50b24d485fb98d39046e41bec03885a8dc071bf8add51083ac9780bff9f6668a"
opam-version: "2.0"maintainer: "Romain Calascibetta <romain.calascibetta@gmail.com>"authors: "Romain Calascibetta <romain.calascibetta@gmail.com>"homepage: "https://github.com/dinosaure/hxd"bug-reports: "https://github.com/dinosaure/hxd/issues"dev-repo: "git+https://github.com/dinosaure/hxd.git"doc: "https://dinosaure.github.io/hxd/"license: "MIT"synopsis: "Hexdump in OCaml"description: """Please, help me to debug ocaml-git"""build: [[ "dune" "build" "-p" name "-j" jobs ][ "dune" "runtest" "-p" name "-j" jobs ] {with-test}]depends: ["ocaml" {>= "4.06.0"}"dune" {>= "2.7"}"dune-configurator" {>= "2.7"}"cmdliner"]depopts: ["lwt"]x-commit-hash: "cee4cc97391634d4c4cb15250946dfc5782e335e"url {src:"https://github.com/dinosaure/hxd/releases/download/v0.3.1/hxd-v0.3.1.tbz"checksum: ["sha256=1c226c91e17cd329dec0c287bfd20f36302aa533069ff9c6ced32721f96b29bc""sha512=93ff909eb519f750794684dcb050bdf51d271652dcea5501654e63b6ac17b79a85981f984a2e1a6db963240de594f21dde4dc541ef8e5873b906fa50d4ef803b"]}
opam-version: "2.0"maintainer: "yallop@gmail.com"authors: ["Jeremy Yallop""Demi Obenour""Stephane Glondu""Andreas Hauptmann"]homepage: "https://github.com/ocamllabs/ocaml-integers"bug-reports: "https://github.com/ocamllabs/ocaml-integers/issues"dev-repo: "git+https://github.com/ocamllabs/ocaml-integers.git"license: "MIT"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]depends: ["ocaml" {>= "4.02"}"dune"]doc: "http://ocamllabs.github.io/ocaml-integers/api.docdir/"synopsis: "Various signed and unsigned integer types for OCaml"url {src: "https://github.com/ocamllabs/ocaml-integers/archive/0.4.0.tar.gz"checksum: "md5=c1492352e6525048790508c57aad93c3"}
opam-version: "2.0"maintainer: "jeremie@dimino.org"authors: ["Jérémie Dimino"]homepage: "https://github.com/ocaml-community/lambda-term"bug-reports: "https://github.com/ocaml-community/lambda-term/issues"dev-repo: "git://github.com/ocaml-community/lambda-term.git"license: "BSD-3-Clause"build: [["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]depends: ["ocaml" {>= "4.02.3"}"lwt" {>= "4.0.0"}"lwt_log""react""zed" {>= "3.1.0" & < "4.0"}"camomile" {>= "1.0.1"}"lwt_react""mew_vi" {>= "0.5.0" & < "0.6.0"}"dune" {>= "1.1.0"}]synopsis: "Terminal manipulation library for OCaml"description: """Lambda-term is a cross-platform library for manipulating the terminal. Itprovides an abstraction for keys, mouse events, colors, as well as a set ofwidgets to write curses-like applications. The main objective of lambda-term isto provide a higher level functional interface to terminal manipulation than,for example, ncurses, by providing a native OCaml interface instead of bindingsto a C library. Lambda-term integrates with zed to provide text editionfacilities in console applications."""url {src: "https://github.com/ocaml-community/lambda-term/archive/3.1.0.tar.gz"checksum: "md5=78180c04ecfc8060b23d7d0014f24196"}
opam-version: "2.0"synopsis: "Lwt logging library (deprecated)"version: "1.1.1"license: "LGPL-2.0-or-later"homepage: "https://github.com/ocsigen/lwt_log"doc: "https://github.com/ocsigen/lwt_log/blob/master/src/core/lwt_log_core.mli"bug-reports: "https://github.com/ocsigen/lwt_log/issues"authors: ["Shawn Wagner""Jérémie Dimino"]maintainer: "Anton Bachin <antonbachin@yahoo.com>"dev-repo: "git+https://github.com/ocsigen/lwt_log.git"depends: ["dune" {>= "1.0"}"lwt" {>= "4.0.0"}]build: [["dune" "build" "-p" name "-j" jobs]]url {src: "https://github.com/aantron/lwt_log/archive/1.1.1.tar.gz"checksum: "md5=02e93be62288037870ae5b1ce099fe59"}
opam-version: "2.0"synopsis: "Helpers for using React with Lwt"maintainer: "Anton Bachin <antonbachin@yahoo.com>"authors: "Jérémie Dimino"license: "MIT"homepage: "https://github.com/ocsigen/lwt"doc: "https://ocsigen.org/lwt/dev/api/Lwt_react"bug-reports: "https://github.com/ocsigen/lwt/issues"depends: ["dune" {>= "1.8.0"}"lwt" {>= "3.0.0"}"ocaml""react" {>= "1.0.0"}]build: ["dune" "build" "-p" name "-j" jobs]dev-repo: "git+https://github.com/ocsigen/lwt.git"url {src: "https://github.com/ocsigen/lwt/archive/5.4.0.zip"checksum: ["md5=fc4721bdb1a01225b96e3a2debde95fa""sha512=e427f08223b77f9af696c9e6f90ff68e27e02e446910ef90d3da542e7b00bf23dd191ac77c1871288faa2289f8d28fc2f44efc3d3fe9165fe1c7a6be88ee49ff"]}
"md5=f27f8f5dedd316eff4c02d9130fced49""sha512=50f86fb2f55184f43c4be9c572ada4feb2208eb350ef64b2651351934a1b48a0b7e98c8c752c3c22e95676c5a0f38b0e638b3f845e53ecff1740dad95b50918c"
"md5=1cbc71c0bc1f3ddc3e71d5c1f919fd1a""sha512=3c309fa2cc4ad7c6fba85107bd946a542894882fa39741496b150307e93455b717418f19e94b5dad06ab269f5c55e8dc25705c96c0a5092e623fa38f1ce43c7f"
"md5=f27f8f5dedd316eff4c02d9130fced49""sha512=50f86fb2f55184f43c4be9c572ada4feb2208eb350ef64b2651351934a1b48a0b7e98c8c752c3c22e95676c5a0f38b0e638b3f845e53ecff1740dad95b50918c"
"md5=1cbc71c0bc1f3ddc3e71d5c1f919fd1a""sha512=3c309fa2cc4ad7c6fba85107bd946a542894882fa39741496b150307e93455b717418f19e94b5dad06ab269f5c55e8dc25705c96c0a5092e623fa38f1ce43c7f"
"md5=f27f8f5dedd316eff4c02d9130fced49""sha512=50f86fb2f55184f43c4be9c572ada4feb2208eb350ef64b2651351934a1b48a0b7e98c8c752c3c22e95676c5a0f38b0e638b3f845e53ecff1740dad95b50918c"
"md5=1cbc71c0bc1f3ddc3e71d5c1f919fd1a""sha512=3c309fa2cc4ad7c6fba85107bd946a542894882fa39741496b150307e93455b717418f19e94b5dad06ab269f5c55e8dc25705c96c0a5092e623fa38f1ce43c7f"
opam-version: "2.0"maintainer: "zandoye@gmail.com"authors: [ "ZAN DoYe" ]homepage: "https://github.com/kandu/mew"bug-reports: "https://github.com/kandu/mew/issues"license: "MIT"dev-repo: "git+https://github.com/kandu/mew.git"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.02.3"}"result""trie""dune" {>= "1.1.0"}]synopsis: "Modal editing witch"description: """This is the core module of mew, a general modal editing engine generator."""url {src: "https://github.com/kandu/mew/archive/0.1.0.tar.gz"checksum: "md5=2298149d1415cd804ab4e01f01ea10a0"}
opam-version: "2.0"maintainer: "zandoye@gmail.com"authors: [ "ZAN DoYe" ]homepage: "https://github.com/kandu/mew_vi"bug-reports: "https://github.com/kandu/mew_vi/issues"license: "MIT"dev-repo: "git+https://github.com/kandu/mew_vi.git"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.02.3"}"mew" {>= "0.1.0" & < "0.2"}"react""dune" {>= "1.1.0"}]synopsis: "Modal editing witch, VI interpreter"description: """A vi-like modal editing engine generator."""url {src: "https://github.com/kandu/mew_vi/archive/0.5.0.tar.gz"checksum: "md5=341e9a9a20383641015bf503952906bc"}
opam-version: "2.0"synopsis:"The legacy Num library for arbitrary-precision integer and rational arithmetic"maintainer: "Xavier Leroy <xavier.leroy@inria.fr>"authors: ["Valérie Ménissier-Morain" "Pierre Weis" "Xavier Leroy"]license: "LGPL-2.1-only with OCaml-LGPL-linking-exception"homepage: "https://github.com/ocaml/num/"bug-reports: "https://github.com/ocaml/num/issues"depends: ["ocaml" {>= "4.06.0"}"ocamlfind" {build & >= "1.7.3"}]conflicts: ["base-num"]build: makeinstall: [make"install" {!ocaml:preinstalled}"findlib-install" {ocaml:preinstalled}]dev-repo: "git+https://github.com/ocaml/num.git"url {src: "https://github.com/ocaml/num/archive/v1.4.tar.gz"checksum: ["md5=cda2b727e116a0b6a9c03902cc4b2415""sha512=0cc9be8ad95704bb683b4bf6698bada1ee9a40dc05924b72adc7b969685c33eeb68ccf174cc09f6a228c48c18fe94af06f28bebc086a24973a066da620db8e6f"]}
"sha256=24b2f324ea91cff98bb8790a6746ccce3173bac5f57cb457156e5c50a0467397""sha512=a1936198e6e563ed703c8cd9d481394660fb25e9e700ea481e5326536c2734d9356c99750ae3ef8a55614776cc040c05cbcf2e03f609ab1f78c34aab0c5de830"
"sha256=ac7ba16a09d8f72212742f3936980fbfaebb698c7bbf625182af7d6b2c3cde5f""sha512=6e11823531f1f70b5d4b90ed9f2fcc22cbf83924a7a0ef40eebc4b80598db6acdaca97f1d379e01860513d5dda492f5bc4d944f0c1dd7df491b2f36a0f729bb5"
opam-version: "2.0"maintainer: "andreashauptmann@t-online.de"authors: [ "andreashauptmann@t-online.de" ]license: "LGPL-2.1-or-later with OCaml-LGPL-linking-exception"homepage: "https://fdopen.github.io/ppx_cstubs/"dev-repo: "git+https://github.com/fdopen/ppx_cstubs.git"doc: "https://fdopen.github.io/ppx_cstubs/"bug-reports: "https://github.com/fdopen/ppx_cstubs/issues"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["bigarray-compat""ctypes" {>= "0.13.0" & < "0.19"}"integers""num""result""containers" {>= "2.2"}"cppo" {build & >= "1.3"}"ocaml" {>= "4.04.2" & < "4.13.0"}"ppxlib" {>= "0.22.0"}"ocamlfind" {>= "1.7.2"} # not only a build dependency, it depends on findlib.top"dune" {>= "1.6"}"re" {>= "1.7.2"}]synopsis: """Preprocessor for easier stub generation with ctypes"""description: """ppx_cstubs is a ppx-based preprocessor for stub generation withctypes. ppx_cstubs creates two files from a single ml file: a filewith c stub code and an OCaml file with all additional boilerplatecode."""url {src: "https://github.com/fdopen/ppx_cstubs/archive/0.6.1.1.tar.gz"checksum: ["md5=33e520e369da5630c697318f6f4ed26d""sha512=77f28fd93ba476ccad089029fb7c7254a4525ea2d61f4d0a74c69b8c771e2657929c16cfa334671ccead1c02743804fc3db7726fd3e47772f50dc4a16270435c"]}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"homepage: "http://erratique.ch/software/react"authors: ["Daniel Bünzli <daniel.buenzl i@erratique.ch>"]doc: "http://erratique.ch/software/react/doc/React"dev-repo: "git+http://erratique.ch/repos/react.git"bug-reports: "https://github.com/dbuenzli/react/issues"tags: [ "reactive" "declarative" "signal" "event" "frp" "org:erratique" ]license: "ISC"depends: ["ocaml" {>= "4.01.0"}"ocamlfind" {build}"ocamlbuild" {build}"topkg" {build & >= "0.9.0"}]build:[[ "ocaml" "pkg/pkg.ml" "build""--dev-pkg" "%{pinned}%" ]]synopsis: "Declarative events and signals for OCaml"description: """Release %%VERSION%%React is an OCaml module for functional reactive programming (FRP). Itprovides support to program with time varying values : declarativeevents and signals. React doesn't define any primitive event orsignal, it lets the client chooses the concrete timeline.React is made of a single, independent, module and distributed underthe ISC license."""url {src: "http://erratique.ch/software/react/releases/react-1.2.1.tbz"checksum: "md5=ce1454438ce4e9d2931248d3abba1fcc"}
opam-version: "2.0"maintainer: ["Markus W. Weissmann <markus.weissmann@in.tum.de>"]authors: ["Andre Nathan <andre@digirati.com.br>""Jeff Shaw <shawjef3@msu.edu>""Markus W. Weissmann <markus.weissmann@in.tum.de>""Florian Pichlmeier <florian.pichlmeier@mytum.de>"]bug-reports: "https://github.com/andrenth/ocaml-stdint/issues"homepage: "https://github.com/andrenth/ocaml-stdint"doc: "https://andrenth.github.io/ocaml-stdint/"license: "MIT"dev-repo: "git+https://github.com/andrenth/ocaml-stdint.git"synopsis: "Signed and unsigned integer types having specified widths"description: """The stdint library provides signed and unsigned integer types of various fixedwidths: 8, 16, 24, 32, 40, 48, 56, 64 and 128 bit.This interface is similar to Int32 and Int64 from the base library but providesmore functions and constants like arithmetic and bit-wise operations, constantslike maximum and minimum values, infix operators conversion to and from everyother integer type (including int, float and nativeint), parsing from andconversion to readable strings (binary, octal, decimal, hexademical), conversionto and from buffers in both big endian and little endian byte order."""depends: ["ocaml" {>= "4.03"}"odoc" {with-doc}"dune" {>= "1.10"}]build: [["dune" "subst"] {pinned}["dune""build""-p"name"-j"jobs"@install""@doc" {with-doc}]]x-commit-hash: "f3eb95c3807249e1fb8ca635bdaa1ef98f7249da"url {src:"https://github.com/andrenth/ocaml-stdint/releases/download/0.7.0/stdint-0.7.0.tbz"checksum: ["sha256=4fcc66aef58e2b96e7af3bbca9d910aa239e045ba5fb2400aaef67d0041252dc""sha512=9b05b6cf691320b718dd2118b1e3f96a2997e42e6c99a34b470b060c82fc16c50d57c6ee392d1b62bdb8df73094657eea56050da3e74745a4afb0f150a60a584"]}
opam-version: "2.0"maintainer: "zandoye@gmail.com"authors: [ "ZAN DoYe" ]homepage: "https://github.com/kandu/trie/"bug-reports: "https://github.com/kandu/trie/issues"license: "MIT"dev-repo: "git://github.com/kandu/trie.git"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.02"}"dune" {>= "1.0"}]synopsis: "Strict impure trie tree"url {src: "https://github.com/kandu/trie/archive/1.0.0.tar.gz"checksum: "md5=84519b5f8bd92490bfc68a52f706ba14"}
opam-version: "2.0"maintainer: "jeremie@dimino.org"authors: "Jérémie Dimino"license: "BSD3"homepage: "https://github.com/ocaml-community/utop"bug-reports: "https://github.com/ocaml-community/utop/issues"doc: "https://ocaml-community.github.io/utop/"depends: ["ocaml" {>= "4.03.0" & < "4.13"}"base-unix""base-threads""ocamlfind" {>= "1.7.2"}"lambda-term" {>= "3.1.0" & < "4.0"}"lwt""lwt_react""camomile""react" {>= "1.0.0"}"cppo" {build & >= "1.1.2"}"dune" {>= "1.0"}]build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]dev-repo: "git+https://github.com/ocaml-community/utop.git"synopsis: "Universal toplevel for OCaml"description: """utop is an improved toplevel (i.e., Read-Eval-Print Loop or REPL) forOCaml. It can run in a terminal or in Emacs. It supports lineedition, history, real-time and context sensitive completion, colors,and more. It integrates with the Tuareg mode in Emacs."""x-commit-hash: "a5ff52bbf608e1112b5c0d41a36e3267f39f4084"url {src:"https://github.com/ocaml-community/utop/releases/download/2.7.0/utop-2.7.0.tbz"checksum: ["sha256=e068ac53df267c3cc0f2f69bbc204404f0362cc4e6472a1fc547e326a63c3fdd""sha512=fc6237ff3e80c509a698872e5571b58e914d24c308a634e45972b7f104d960f17eba507535f56fcec972ea8c71143a8036cd122618e63cdf77fb6034297924df"]}
opam-version: "2.0"maintainer: "opam-devel@lists.ocaml.org"authors: ["Jérémie Dimino"]homepage: "https://github.com/ocaml-community/zed"bug-reports: "https://github.com/ocaml-community/zed/issues"dev-repo: "git://github.com/ocaml-community/zed.git"license: "BSD-3-Clause"depends: ["ocaml" {>= "4.02.3"}"dune" {>= "1.1.0"}"base-bytes""camomile" {>= "1.0.1"}"react""charInfo_width" {>= "1.1.0" & < "2.0~"}]build: [["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]synopsis: "Abstract engine for text edition in OCaml"description: """Zed is an abstract engine for text edition. It can be used to write texteditors, edition widgets, readlines, ... Zed uses Camomile to fully support theUnicode specification, and implements an UTF-8 encoded string type withvalidation, and a rope datastructure to achieve efficient operations on largeUnicode buffers. Zed also features a regular expression search on ropes. Tosupport efficient text edition capabilities, Zed provides macro recording andcursor management facilities."""url {src: "https://github.com/ocaml-community/zed/archive/3.1.0.tar.gz"checksum: "md5=51e8676ba972e5ad727633c161e404b1"}
name: esyon: [push, pull_request]jobs:native:name: Build for Nativestrategy:matrix:system: [ubuntu, macos]runs-on: ${{ matrix.system }}-lateststeps:- name: Checkout codeuses: actions/checkout@v2- uses: actions/setup-node@v2-betawith:node-version: 14- name: Install esyrun: npm install -g esy- name: Create esy wrapperrun: |echo '{"name": "build-sodium","dependencies": {"@opam/conf-libsodium": "*","@opam/sodium": "*"},"resolutions": {"@opam/conf-libsodium": {"source": "./libsodium.opam","override": {"dependencies": {"esy-libsodium": "github:EduardoRFS/esy-libsodium#'"${GITHUB_SHA}"'"}}},"@opam/sodium": "github:EduardoRFS/ocaml-sodium:sodium.json#d3f147594c0bd374c88d07d0274230770c40cc7d"}}' > build.json- name: Generate esy lockrun: esy @build solve- uses: esy/github-action@masterwith:manifest: ./build.jsoncache-key: ${{ hashFiles('esy.lock/index.json') }}
_esybuild.esy.lock
opam-version: "2.0"maintainer: "Grégoire Henry <gregoire.henry@ocamlpro.com>"authors: ["Adam Langley""Alex Biryukov""Bo-Yin Yang""Christian Winnerlein""Colin Percival""Daniel Dinu""Daniel J. Bernstein""Dmitry Khovratovich""Jean-Philippe Aumasson""Niels Duif""Peter Schwabe""Samuel Neves""Tanja Lange""Zooko Wilcox-O'Hearn"]homepage: "https://download.libsodium.org/doc/"license: "ISC"build: [["pkg-config" "libsodium"]]depends: ["conf-pkg-config" {build}]depexts: [["libsodium-dev"] {os-family = "debian"}["security/libsodium"] {os = "freebsd"}["libsodium"] {os-distribution = "homebrew" & os = "macos"}["libsodium-dev"] {os-distribution = "alpine"}]synopsis: "Virtual package relying on a libsodium system installation"description:"This package can only install if the libsodium is installed on the system."bug-reports: "https://github.com/ocaml/opam-repository/issues"flags: conf
{"version": "1.0.18123","source": "https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz#795b73e3f92a362fabee238a71735579bf46bb97","override": {"buildsInSource": true,"build": [["./configure","--disable-debug","--disable-dependency-tracking","--prefix=$cur__install"],["make","-j4"]],"install": "make install","exportedEnv": {"PKG_CONFIG_PATH": {"val": "#{self.lib / 'pkgconfig' }:$PKG_CONFIG_PATH","scope": "global"},"SODIUM_INCLUDE_PATH": {"val": "#{self.install / 'include'}","scope": "global"},"SODIUM_LIB_PATH": {"val": "#{self.lib}","scope": "global"},"LD_LIBRARY_PATH": {"val": "#{self.lib : $LD_LIBRARY_PATH}","scope": "global"}}}}
{"source": "github:dsheets/ocaml-sodium:opam#1f064fa90cd02c44e2dcc0708d4ba3a256a9c1f2","override": {"build": [["make", "CFLAGS=\"-I$SODIUM_INCLUDE_PATH -L$SODIUM_LIB_PATH\"", "-j4"]],"install": "make PREFIX=$cur__install install","dependencies": {"@opam/conf-libsodium": "*"}}}
{"build": "true","dependencies": {"esy-libffi": "esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c"}}
{"dependencies": {"@esy-ocaml/libffi": "3.2.10"}}
{"exportedEnv": {"CAML_LD_LIBRARY_PATH": {"val": "#{self.lib / 'ctypes' : $CAML_LD_LIBRARY_PATH}","scope": "global"}}}
diff --git a/src/Makefile b/src/Makefileindex 8ad0e2c..d41d63c 100644--- a/src/Makefile+++ b/src/Makefile@@ -1,16 +1,16 @@-OCAMLC=ocamlc-OCAMLOPT=ocamlopt-OCAMLDEP=ocamldep-OCAMLMKLIB=ocamlmklib-OCAMLFIND=ocamlfind+OCAMLC=$(shell which ocamlc)+OCAMLOPT=$(shell which ocamlopt)+OCAMLDEP=$(shell which ocamldep)+OCAMLMKLIB=$(shell which ocamlmklib)+OCAMLFIND=$(shell which ocamlfind)INSTALL_DATA=install -m 644INSTALL_DLL=installINSTALL_DIR=install -dSTDLIBDIR=$(shell $(OCAMLC) -where)DESTDIR ?=-include $(STDLIBDIR)/Makefile.config+include $(STDLIBDIR)/Makefile.configifeq "$(filter i386 amd64 arm64 power,$(ARCH))" ""# Unsupported architectureBNG_ARCH=generic@@ -86,14 +86,14 @@ endifVERSION=$(shell sed -ne 's/^ *version *: *"\([^"]*\)".*$$/\1/p' ../num.opam)install:- $(INSTALL_DIR) $(DESTDIR)$(STDLIBDIR)+ $(INSTALL_DIR) $(LIBDIR)sed -e 's/%%VERSION%%/$(VERSION)/g' META.in > META$(OCAMLFIND) install num METArm -f META- $(INSTALL_DATA) $(TOINSTALL) $(DESTDIR)$(STDLIBDIR)+ $(INSTALL_DATA) $(TOINSTALL) $(LIBDIR)ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"- $(INSTALL_DIR) $(DESTDIR)$(STDLIBDIR)/stublibs- $(INSTALL_DLL) $(TOINSTALL_STUBS) $(DESTDIR)$(STDLIBDIR)/stublibs+ $(INSTALL_DIR) $(LIBDIR)/stublibs+ $(INSTALL_DLL) $(TOINSTALL_STUBS) $(LIBDIR)/stublibsendiffindlib-install:@@ -105,9 +105,9 @@ findlib-uninstall:$(OCAMLFIND) remove numuninstall: findlib-uninstall- cd $(DESTDIR)$(STDLIBDIR) && rm -f $(TOINSTALL)+ cd $(LIBDIR) && rm -f $(TOINSTALL)ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"- cd $(DESTDIR)$(STDLIBDIR)/stublibs && rm -f $(TOINSTALL_STUBS)+ cd $(LIBDIR)/stublibs && rm -f $(TOINSTALL_STUBS)endifclean:
{"buildsInSource": true,"build": [["make"]],"install": [["make","LIBDIR=#{self.install / 'lib'}","findlib-install"]],"exportedEnv": {"CAML_LD_LIBRARY_PATH": {"val": "#{self.install / 'lib' / 'num' : $CAML_LD_LIBRARY_PATH}","scope": "global"}},"dependencies": {"ocaml": "*","@opam/ocamlfind": "*"}}
"nix-wrangle-pkg": {"flake": false,"locked": {"lastModified": 1606447617,"narHash": "sha256-yHejSB3cZbHyBgMiiu0BweKqimN0KVosBmjSY9mjT0E=","owner": "timbertson","repo": "nix-wrangle","rev": "25625d48f91785715dc62d7d90e44777839fa03d","type": "github"},"original": {"owner": "timbertson","repo": "nix-wrangle","type": "github"}},
"type": "github"}},"opam2nix-pkg": {"flake": false,"locked": {"lastModified": 1614045149,"narHash": "sha256-4SJSfK6vRGvQvTFfy3Jgg8u2rGHsya0ee0ziCIvhxew=","owner": "timbertson","repo": "opam2nix","rev": "d1d4cb15131bf45c9402aeff7df05dc78a92add7","type": "github"},"original": {"owner": "timbertson","repo": "opam2nix",
open Globalsmodule L = (val Relog.logger ~namespace:__MODULE__ ())open Lwt.Infixlet _SAMPLE_RATE = 48000let _CHANNELS = 2let _FRAME_LEN = 20let _FRAME_SIZE = _SAMPLE_RATE / 1000 * _FRAME_LEN(** Maximum packet size for a voice packet.Set a safe amount below the Ethernet MTU to avoid fragmentation/rejection. *)let _VOICE_PACKET_MAX = 1460(* https://tools.ietf.org/html/rfc7587#section-4.2 *)let ts_incr = Uint32.of_int @@ (48000 / 1000 * _FRAME_LEN)let silence_frame =[ '\xf8'; '\xff'; '\xfe' ] |> String.of_list|> Bigstringaf.of_string ~off:0 ~len:3let silence_stream = Lwt_stream.from_direct (fun () -> Some silence_frame)let n_silence_pipe ?(n = 10) () =Lwt_pipe.of_list (List.init n (fun _ -> silence_frame))let of_pipe p =let out = Lwt_pipe.create () inlet rec poll' () =Lwt_pipe.read p >>= function| None -> Lwt.return_unit| Some data -> (Lwt_pipe.write out data >>= function| true -> poll' ()| false -> Lwt.return_unit)inlet fwd = poll' () inLwt_pipe.keep out fwd;Lwt.on_termination fwd (fun () -> Lwt_pipe.close_nonblock out);outmodule Gen = struct(** Fractional part of a float. *)let fracf x = if x <. 1. then x else if x <. 2. then x -. 1. else fst (modf x)let s16 =let r = Int16.(max_int |> to_float) infun f -> Int.of_float (Float.(min 1. (max (-1.) f)) *. r)let sine ?(freq = 440) ?(phase = 0.) ?(samplerate = 48000) ?(framelen = 20)?(channels = 2) duration =let phase = ref phase inlet framesize = samplerate / 1000 * framelen inlet volume = 0.5 inlet omega = float freq /. float samplerate inlet gen =let buf =Bigarray.(Array1.create float32 c_layout (framesize * channels))infun () ->for i = 0 to framesize - 1 dolet sample = volume *. sin ((float i *. omega) +. !phase) in(* let sample = s16 sample in *)for c = 0 to channels - 1 dobuf.{i + c} <- sampledonedone;phase :=mod_float (!phase +. (float framesize *. omega)) (2. *. Float.pi);bufinlet p = Lwt_pipe.create () inlet rec write = function| 0 -> Lwt.return_unit| n ->Lwt_pipe.write p (gen ()) >>= fun ok ->if ok then write (n - 1) else Lwt.return_unitinlet nframes = Int.of_float (duration *. 1e3) / framelen inlet fut = write nframes inLwt_pipe.keep p fut;Lwt.on_termination fut (fun () -> Lwt_pipe.close_nonblock p);pendmodule Ffmpeg = structmodule L = (val Relog.clone (module L) ~namespace:"Ffmpeg")module Parser = structlet frame ~sample_p ~channels ~size ~kind =let buf =Bigarray.Array1.create kind Bigarray.c_layout (channels * size)inlet p =let open Angstrom inlet sample = count channels sample_p inlet rec samples ?(i = 0) () =end_of_input >>| (fun () -> `eof) <|> (sample >>| fun s -> `sample s)>>= function| `eof -> return ()| `sample chans ->List.iteri (fun ci c -> buf.{i + ci} <- c) chans;samples ~i:(i + channels) ()insamples () >>| fun () -> bufinfun buf ->Angstrom.parse_bigstring ~consume:Angstrom.Consume.All p buf |> function| Ok frame -> frame| Error str -> failwith @@ "error parsing raw audio frame " ^ strlet s16le ?(channels = 2) ?(frame_size = 48000) =frame ~sample_p:Angstrom.LE.any_int16 ~channels ~size:frame_size~kind:Bigarray.int16_signedlet s16be ?(channels = 2) ?(frame_size = 48000) =frame ~sample_p:Angstrom.BE.any_int16 ~channels ~size:frame_size~kind:Bigarray.int16_signedlet f32le ?(channels = 2) ?(frame_size = 48000) =frame ~sample_p:Angstrom.LE.any_float ~channels ~size:frame_size~kind:Bigarray.float32let f32be ?(channels = 2) ?(frame_size = 48000) =frame ~sample_p:Angstrom.BE.any_float ~channels ~size:frame_size~kind:Bigarray.float32let f64le ?(channels = 2) ?(frame_size = 48000) =frame ~sample_p:Angstrom.LE.any_double ~channels ~size:frame_size~kind:Bigarray.float64let f64be ?(channels = 2) ?(frame_size = 48000) =frame ~sample_p:Angstrom.BE.any_double ~channels ~size:frame_size~kind:Bigarray.float64endlet pcm_args =[ "-analyzeduration"; "0"; "-f"; "s16le"; "-ar"; "48000"; "-ac"; "2" ](* let ogg_args =[ "-analyzeduration"; "0"; "-f"; "s16le"; "-ar"; "48000"; "-ac"; "2" ] *)let stdout_args = [ "-" ]let of_file filename =let cmd = "ffmpeg" inlet args = List.concat [ [ "-i"; filename ]; pcm_args; stdout_args ] inlet p = Lwt_pipe.create () inlet p_p, u_p = Lwt.wait () inlet spawn () =let cmd_str = cmd :: args |> List.to_string ~sep:" " Fun.id inL.info (fun m -> m "running cmd: %s" cmd_str);Lwt_process.with_process_full("", Array.of_list @@ cmd :: args)(fun proc ->let raw = proc#stdout inlet logs () = Lwt_io.read proc#stderr inL.info (fun m -> m "ffmpeg running with pid=%d" proc#pid);let buf = Bigstringaf.create (_FRAME_SIZE * _CHANNELS * 2) inlet buf_len = Bigstringaf.length buf inlet parse_frame =let parser =Parser.s16le ~channels:_CHANNELS ~frame_size:_FRAME_SIZEinfun () -> parser bufinlet rec poll' () =L.trace (fun m -> m "polling");Lwt_io.read_into_exactly_bigstring raw buf 0 buf_len|> Lwt_result.catch>>= function| Ok () ->L.trace (fun m -> m "parsing frame");let frame = parse_frame () inif Lwt.is_sleeping p_p then Lwt.wakeup_later u_p (Ok p);Lwt_pipe.write p frame >>= fun ok ->if ok then poll' () else proc#close >|= ignore| Error End_of_file -> Lwt.return_unit| Error exn -> Lwt.fail exninlet open Lwt.Syntax inlet* status = poll' () >>= fun () -> proc#status inlet+ res =match status with| Unix.WEXITED 0 ->if Lwt.is_sleeping p_p thenLwt_result.fail (`Msg "0 byte stream?")else Lwt_result.return ()| WEXITED n ->L.error (fun m ->m "got non 0 status code for ffmpeg (status=%d)" n);let+ logs = logs () inL.error (fun m -> m "logs:@.%s" logs);Error(`Msg(Printf.sprintf"got non 0 status code for ffmpeg (status=%d)\n%s" n logs))| WSIGNALED n | WSTOPPED n ->L.warn (fun m -> m "ffmpeg process was closed with code=%d" n);Lwt_result.return ()inmatch (Lwt.is_sleeping p_p, res) with| true, (Error _ as e) -> Lwt.wakeup_later u_p e| true, Ok () -> ()| false, _ -> ())inlet k = spawn () inLwt_pipe.keep p k;Lwt.on_termination k (fun () -> Lwt_pipe.close_nonblock p);p_p |> Lwt_result.map of_pipeend
let msg = { content; nounce = Websocket.gen_nonce 20; tts = false } inlet uri = Format.sprintf "/channels/%s/messages" channel_id in
let msg = { content; nonce = Websocket.gen_nonce 20; tts = false } inlet uri =Format.sprintf "/channels/%s/messages"(Models.Snowflake.to_string channel_id)in
Lwt.async (fun () ->Http.post ~body:ser uri http|> Lwt.map (function| Ok _ -> ()| Error _ -> L.error (fun m -> m "error sending message")))
Http.post ~body:ser uri http|> Lwt.map (function| Ok _ -> ()| Error _ -> L.error (fun m -> m "error sending message"))let join_voice ~guild_id ~channel_id { gw; _ } =Gateway.join_voice ~guild_id ~channel_id gw|> Lwt.map (function| Ok _ -> ()| Error e ->L.error (fun m ->m "couldn't join voice channel '%Ld' on guild '%Ld: %s"channel_id guild_id (Error.to_string e)))
let catch_lwt p = Lwt_result.(catch p |> map_err (fun exn -> `Exn exn))let tap ~f r = function| Ok o -> Ok o| Error e ->f e;rlet tap_lwt ~f r = function| Ok o -> Lwt.return (Ok o)| Error e -> Lwt.bind (f e) (fun () -> r)
}[@@deriving yojson] [@@yojson.allow_extra_fields]endmodule VoiceState = structtype t = {guild_id : Models.Snowflake.t option; [@yojson.option]channel_id : Models.Snowflake.t option;user_id : Models.Snowflake.t;(* member: guild option; [@yojson.option]; *)session_id : string;deaf : bool;mute : bool;self_deaf : bool;self_mute : bool;self_stream : bool option; [@yojson.option]self_video : bool;suppress : bool;
{ session }
let rec t = { session; events; voice_sessions }and events = Session.events session |> Lwt_pipe.to_streamand voice_sessions = SfMap.empty intlet disconnect t =SfMap.to_seq t.voice_sessions|> Seq.map (fun (_, { conn; _ }) -> Voice.disconnect conn)|> Seq.to_list |> Lwt.join>>= fun () ->t.voice_sessions <- SfMap.empty;Session.disconnect t.sessionlet user { session; _ } = Session.user sessionlet events { events; _ } = events |> Lwt_pipe.of_streamlet _fork_events t = Lwt_stream.clone t.events |> Lwt_pipe.of_streamlet leave_voice ~guild_id ({ session; voice_sessions; _ } as t) =let open Lwt.Infix inmatch SfMap.get guild_id voice_sessions with| Some vs ->Voice.disconnect vs.conn >>= fun () ->t.voice_sessions <- SfMap.remove guild_id voice_sessions;Session.send_voice_state_update session ~self_mute:true ~self_deaf:trueguild_id| None -> Lwt.return_unitlet join_voice ~guild_id ~channel_id ({ session; _ } as t) =let open Lwt.Syntax inlet user = Session.user session inlet join () =let* () =Session.send_voice_state_update session ~channel_id ~self_deaf:false~self_mute:false guild_idinlet is_own_vs{ Events.VoiceState.guild_id = guild; channel_id = chan; user_id; _ } =match (guild, chan) with| Some g, Some c ->Models.Snowflake.(guild_id = g && channel_id = c && user_id = user.id)| _ -> falseinlet is_own_srv { Events.VoiceServerUpdate.guild_id = guild; _ } =Models.Snowflake.(guild_id = guild)in
let disconnect { session; _ } = Session.disconnect session
let wait_for_updates =let rec f' ?st ?srv () =let* evt = Lwt_pipe.read evs inmatch ((evt : Events.t option), st, srv) with| Some (VoiceStateUpdate st), _, None ->L.debug (fun m -> m "got voice state");f' ~st ?srv ()| Some (VoiceServerUpdate srv), None, _ ->L.debug (fun m -> m "got voice server");f' ?st ~srv ()| Some (VoiceStateUpdate st), _, Some srv| Some (VoiceServerUpdate srv), Some st, _ ->Lwt.return (st, srv)| _ -> assert falseand evs =_fork_events t|> Lwt_pipe.Reader.filter ~f:(function| Events.VoiceStateUpdate st -> is_own_vs st| Events.VoiceServerUpdate srv -> is_own_srv srv| _ -> false)inlet p = f' () inLwt.on_termination p (fun () ->L.info (fun m -> m "closing events fork");Lwt_pipe.close_nonblock evs);pinlet open Lwt_result.Syntax inlet* st, srv =Lwt.pick[Lwt_unix.sleep 5. |> Lwt.map (fun () -> `Timeout);wait_for_updates |> Lwt.map (fun o -> `Ok o);]|> Lwt.map (function| `Ok o -> Ok o| `Timeout -> Error (`Discord "timed out waiting for update events"))inlet cleanup _ =L.warn (fun m -> m "cleanup");match SfMap.get guild_id t.voice_sessions with| Some { mixer; _ } ->Mixer.destroy mixer;t.voice_sessions <- SfMap.remove guild_id t.voice_sessions| None -> ()inVoice.create ~on_destroy:cleanup ~server_id:guild_id ~user_id:user.id~session_id:st.session_id ~token:srv.token srv.endpointinlet open Lwt_result.Syntax inmatch SfMap.get guild_id t.voice_sessions with| Some vs when Models.Snowflake.(vs.channel_id = channel_id) ->L.info (fun m ->m "there an active voice connection for channel '%Ld' already"vs.channel_id);Lwt_result.return vs| Some _vs ->L.info (fun m ->m "already active voice session for guild %Ld, switching channel..."guild_id);let* conn = join () inlet+ mixer = Mixer.create conn |> Lwt_result.lift inlet vs = { conn; channel_id; mixer } int.voice_sessions <- SfMap.add guild_id vs t.voice_sessions;vs| None ->let* conn = join () inlet+ mixer = Mixer.create conn |> Lwt_result.lift inlet vs = { conn; channel_id; mixer } int.voice_sessions <- SfMap.add guild_id vs t.voice_sessions;vs
endmodule GuildRequestMembers = structtype t = {guild_id : Models.Snowflake.t;query : string option; [@yojson.option]limit : int;presences : bool option; [@yojson.option]user_ids : Models.Snowflake.t list option; [@yojson.option]nonce : string option; [@yojson.option]}[@@deriving yojson, show]type q =[ `All| `User of Models.Snowflake.t| `Users of Models.Snowflake.t list| `Query of string| `QueryLimit of string * int ]let make ?presences ?nonce ~q guild_id =let query, limit, user_ids =match q with| `All -> (Some "", 0, None)| `User id -> (None, 0, Some [ id ])| `Users users -> (None, 0, Some users)| `QueryLimit (q, l) -> (Some q, l, None)| `Query q -> (Some q, 0, None)in{ guild_id; query; limit; presences; user_ids; nonce }
let make_request_guild_members ?presences ?nonce ~q guild_id =RequestGuildMembers (GuildRequestMembers.make ?presences ?nonce ~q guild_id)
type snowflake = Models.Snowflake.ttype bigstring = Bigstringaf.tmodule Lwt_pipe = structinclude Lwt_pipe(* TODO this hasn't actually been tested *)let multicast ~n p =assert (n > 1);let main = create () inlet subs = Seq.(1 --^ n >|= (fun _ -> create ()) |> to_list) inlet running_pipes () = List.filter (fun p -> not @@ is_closed p) subs inlet rec fwd_rec () =let open Lwt.Infix inread p >>= function| Some d ->main :: running_pipes () |> Lwt_list.exists_p (fun p -> write p d)>>= fun ok -> if ok then fwd_rec () else Lwt.return_unit| None -> Lwt.return_unitinlet fwd = fwd_rec () inkeep main fwd;List.iter (fun p -> link_close p ~after:main) subs;Lwt.on_termination fwd (fun () -> close_nonblock main);(main, subs)let fork p =let p, sibs = multicast ~n:2 p in(p, List.hd sibs)end
open Globalsopen Lwt.Infixmodule L = (val Relog.logger ~namespace:__MODULE__ ())type pcm_s16_frame =(int, Bigarray.int16_signed_elt, Bigarray.c_layout) Bigarray.Array1.ttype pcm_f32_frame =(float, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array1.ttype silence_stream = bigstring Lwt_pipe.Reader.tmodule Driver = structtype t = {mutable state : state;mutable silence : silence_stream option;mutable dead : bool;}and state = Idle | Playing of streamand stream = { waker : waker; rx : bigstring Lwt_pipe.Reader.t }and waker = unit Lwt.t * unit Lwt.ulet waker : unit -> waker = Lwt.tasklet make_silence ?n () = Audio_stream.n_silence_pipe ?n ()let create () ={ state = Idle; silence = Some (make_silence ~n:20 ()); dead = false }let now () = Mtime_clock.elapsed_ns ()let destroy_active t =match t.state with| Playing s ->Lwt_pipe.close_nonblock s.rx;Lwt.cancel (fst s.waker);t.state <- Idle| Idle -> ()let stop = destroy_activelet play ~s t =match t.state with| Playing _ ->stop t;t.silence <- Some (make_silence ());t.state <- Playing s| Idle -> t.state <- Playing slet destroy t = if not t.dead then t.dead <- truelet run ~yield ~play ~stop t =let rec exhaust ?(i = 0) p =Lwt_pipe.read p >>= function| Some frame ->play frame >>= fun ok ->if ok then exhaust ~i:(i + 1) pelse if i = 0 then failwith "need to send at least 1 frame"else Lwt.return (`Yield i)| None -> Lwt.return (`Closed i)inlet framelen = float Rtp._FRAME_LEN /. 1e3 inlet schedule_next ?drift ?(frames = 1) () =let timeout = float frames *. framelen inlet with_drift d =let d = Lazy.force d inlet delta = Int64.(now () - d |> to_float) /. 1e9 intimeout -. Float.min delta timeoutinlet timeout =Option.map with_drift drift |> Option.get_or ~default:timeoutinL.trace (fun m ->m "sent %d frames, next tick in %f seconds" frames timeout);Lwt_unix.sleep timeout >|= fun () -> `Tickinlet rec yield_till tick =let y = yield t >|= fun () -> if t.dead then `Dead else `Yield inLwt.choose [ tick; y ] >>= function| `Dead ->Lwt.cancel tick;Lwt.return_unit| `Yield -> yield_till tick| `Tick ->Lwt.cancel y;Lwt.return_unitinlet rec f' ?(drift = lazy (now ())) ?(i = 0) () =match (t.silence, t.state) with| _ when t.dead ->destroy_active t;Lwt.return_unit| Some s, st -> (exhaust s >>= function| `Closed n ->t.silence <- None;(match st with Idle -> stop () | _ -> Lwt.return_unit)>>= f' ~drift ~i:(i + n)| `Yield n ->let frames = i + n inyield_till (schedule_next ~drift ~frames ()) >>= fun () -> f' ())| None, Idle -> yield t >>= fun () -> f' ()| None, Playing s -> (exhaust s.rx >>= function| `Closed n ->t.silence <- Some (make_silence ());t.state <- Idle;Lwt.wakeup_later (snd s.waker) ();f' ~drift ~i:(i + n) ()| `Yield n ->let frames = i + n inyield_till (schedule_next ~drift ~frames ()) >>= fun () -> f' ())inf' ()endtype t = { evloop_tx : evloop_msg Lwt_pipe.Writer.t }and evloop_msg = Stop | Play of pcm_s16_frame Lwt_pipe.Reader.t * Driver.wakerlet create_opus_encoder ?(frametype = `s16) () =let open Opus inlet open Result.Infix inlet rec set_ctls ~l enc =match l with| ctl :: l -> Encoder.ctl enc ctl >>= fun () -> set_ctls ~l enc| [] -> Ok encinEncoder.create ~samplerate:Rtp._SAMPLE_RATE ~channels:`stereo~application:Audio ()>>= (fun enc ->let shared =CTL.[Set_signal `music;Set_bitrate `max;Set_complexity 10;Set_packet_loss_perc 5;Set_complexity 10;Set_inband_FEC true;Set_DTX false;]inlet ctls =match frametype with| `s16 -> CTL.(Set_LSB_depth 16) :: shared| `f32 -> CTL.(Set_LSB_depth 24) :: sharedinset_ctls ~l:ctls enc)|> Result.map_err (fun e ->`Msg (Printf.sprintf "opus error: %s" (Opus.Error.to_string e)))let create ?(burst = 15) voice =let ( let+ ) = Result.( let+ ) inlet chan = Lwt_pipe.create () inlet evloop_tx = Lwt_pipe.Writer.map ~f:(fun msg -> `Req msg) chan inlet+ encoder = create_opus_encoder () inlet encode =let pkt_buf = Bigstringaf.create Rtp._VOICE_PACKET_MAX infun buf ->matchOpus.Encoder.encode_blit encoder ~duration:Rtp._FRAME_LEN buf pkt_bufwith| Ok `DTX ->L.err (fun m -> m "DTX!!!");None| Ok (`Packet p) -> Some p| Error e -> failwith ("opus error: " ^ Opus.Error.to_string e)inlet driver = Driver.create () inlet yield driver =Lwt.wrap_in_cancelable (Lwt_pipe.read chan)>|= Option.get_or ~default:`Poison>|= function| `Req (Play (s, waker)) ->let s = Lwt_pipe.Reader.filter_map ~f:encode s inDriver.play driver ~s:{ waker; rx = s }| `Req Stop -> Driver.stop driver| `Poison -> Driver.destroy driverinlet curr = ref 0 inlet play frame =if !curr < burst then (Voice.start_speaking voice >>= fun () ->Voice.send_rtp voice frame >|= fun () ->incr curr;true)else (curr := 0;Lwt.return false)inlet stop () = Voice.stop_speaking voice inlet f = Driver.run ~yield ~play ~stop driver inLwt_pipe.keep chan f;Lwt_pipe.link_close chan ~after:evloop_tx;Lwt.on_termination f (fun () -> Lwt_pipe.close_nonblock chan);{ evloop_tx }let play ?k t stream =let ((wp, _) as waker) = Driver.waker () inlet () = match k with Some f -> Lwt.on_success wp f | None -> () inLwt_pipe.write_exn t.evloop_tx (Play (stream, waker))let destroy t = Lwt_pipe.close_nonblock t.evloop_tx
type t = string [@@deriving yojson]
type t = int64let of_string = Int64.of_stringlet to_string = Int64.to_stringlet t_of_yojson : Yojson.Safe.t -> t = function| `String s | `Intlit s -> of_string s| _ -> assert falselet yojson_of_t t = `String (to_string t)let discord_epoch = 1420070400000Llet timestamp t = CCInt64.((t lsr 22) + discord_epoch)let worker_id t = CCInt64.((t land 0x3E0000L) lsr 17 |> to_int)
(* let t_of_yojson = function| `String s | `Intlit s -> Int64.of_string s| _ -> assert false *)
let increment t = CCInt64.(t land 0xFFFL |> to_int)let pp fmt t =Format.fprintf fmt"@[(%Ld@[(ts=%Ld)@] @[(wid=%d)@] @[(pid=%d)@] @[(inc=%d)@])@]" t(timestamp t) (worker_id t) (process_id t) (increment t)let compare = Int64.comparelet ( = ) = Int64.equal
type t
type t = {id : Snowflake.t;username : string;discriminator : string;avatar : string option;bot : bool option; [@yojson.option]system : bool option; [@yojson.option]mfa_enabled : bool option; [@yojson.option]locale : string option; [@yojson.option]verified : bool option; [@yojson.option]email : string option option; [@yojson.option]flags : int option; [@yojson.option]premium_type : int option; [@yojson.option]public_flags : int option; [@yojson.option]}[@@deriving yojson] [@@yojson.allow_extra_fields]
open Globalslet _SAMPLE_RATE = 48000let _CHANNELS = 2let _FRAME_LEN = 20let _FRAME_SIZE = _SAMPLE_RATE / 1000 * _FRAME_LEN(** Maximum packet size for a voice packet.Set below Ethernet MTU to avoid fragmentation/rejection. *)let _VOICE_PACKET_MAX = 1460(* https://tools.ietf.org/html/rfc7587#section-4.2 *)let ts_incr = Uint32.of_int @@ (48000 / 1000 * _FRAME_LEN)module Sync = structtype t = uint16 * uint32let add_uint16_safe a b =let open Uint16 inif compare (max_int - b) a < 0 then a - (max_int - b) else a + blet add_uint32_safe a b =let open Uint32 inif compare (max_int - b) a < 0 then a - (max_int - b) else a + blet make () =let seq = Random.(run (int Int.(2 ** 16))) |> Uint16.of_int inlet ts = Random.int64 Int64.(2L ** 32L) |> Uint32.of_int64 in(seq, ts)let seq = fstlet ts = sndlet tick (seq, ts) =(add_uint16_safe seq Uint16.one, add_uint32_safe ts ts_incr)endtype t = {udp : Udp_connection.t;mutable crypt : Udp_connection.crypt;mutable sync : Sync.t;}let make ~udp ~crypt = { udp; crypt; sync = Sync.make () }let ssrc { udp; _ } = udp.ssrclet set_crypt t crypt = t.crypt <- cryptlet send_packet t bs =let seq, ts = t.sync int.sync <- Sync.tick t.sync;Udp_connection.send_voice_packet ~crypt:t.crypt ~seq ~ts ~audio:bs t.udplet destroy t = Udp_connection.destroy t.udp
module Ws = structtype t = t' refand t' = Open of Token_bucket.t * Ws_Conn.t | Closedlet create conn = ref (Open (Token_bucket.make ~capacity:2 1., conn))let send t pl =match !t with| Open (tb, conn) ->Lwt.(Token_bucket.take tb >|= fun () ->Ws_Conn.send conn pl;Ok ())| Closed -> Lwt.return (Error (`Msg "cannot send payload to closed ws"))let send_exn t pl =Lwt.(send t pl >|= function| Ok () -> ()| Error e -> failwith (Error.to_string e))let close ~code t =match !t with| Open (tb, conn) ->t := Closed;Token_bucket.cancel_waiting tb;Ws_Conn.close ~code conn| Closed -> ()endtype info = { id : string; seq : int }
mutable state : state;mutable ws : Ws_Conn.t;mutable disconnect : unit -> unit;ev_pipe : (Events.t, [ `r | `w ]) Lwt_pipe.t;
user : Models.User.t;disconnect : unit -> unit Lwt.t;ev_rx : Events.t Lwt_pipe.Reader.t;pl_tx : Pl.send Lwt_pipe.Writer.t;
let session_logger : t -> (module Relog.Logger.S) =fun t ->Relog.clone~fields:F.[lazy_int "seq" (fun () ->match t.state with| Connected ({ seq; _ }, _)| Greeting (Reconnection { seq; _ })| Resuming ({ seq; _ }, _) ->seq| _ -> -1);lazy_str "session_id" (fun () ->match t.state with| Connected ({ id; _ }, _)| Greeting (Reconnection { id; _ })| Resuming ({ id; _ }, _) ->id| _ -> "<not connected>");lazy_bool "reconn" (fun () ->match t.state with| Resuming _ | Greeting (Reconnection _) -> true| _ -> false);](module L)
let state_reducer ~(session_logger : (module Relog.Logger.S)) ~forward_event~send_payload ~on_ready ~token state pl =let module L = (val session_logger) in
let do_handshake ~token ?reconn ws pl_rx =let module L =(val Relog.clone (module L) ~fields:F.[ bool "handshaking" true ])inlet open Lwt_result.Syntax in
L.debug (fun m ->m "sending heartbeat" ~fields:F.[ float "interval" interval ]);Lwt.async (fun () -> Ws.send_exn ws Pl.heartbeat))intervalinlet rec poll' st =let* pl =Lwt_pipe.read pl_rx >|= function| Some (`Pl pl) -> Ok pl| Some (`Closed code) -> Error (`Closed code)| None -> assert falseinmatch (st, pl) with| Greet Fresh, Pl.Hello hb ->let id = Pl.Identify.make token in
m "sending heartbeat" ~fields:F.[ float "hb_interval" interval ]);send_payload Pl.heartbeat)interval
m "got greeting, identifying (intents=%a)" Pl.Intents.pp id.intents);let* () = Ws.send ws (Pl.Identify id) inlet hb_secs = Float.of_int hb /. 1_000. inlet hb = make_hb hb_secs inpoll' (Id hb)|> Lwt_result.map_err (fun e ->hb.cancel ();e)| Greet (Reconnection (info, ev_tx)), Hello hb ->L.info (fun m ->m "got greeting, resuming session '%s' with seq=%d" info.id info.seq);let* () =Ws.send ws (Pl.make_resume ~token ~session_id:info.id ~seq:info.seq)inlet hb_secs = Float.of_int hb /. 1_000. inlet hb = make_hb hb_secs inpoll' (Resuming (info, ev_tx, hb))|> Lwt_result.map_err (fun e ->hb.cancel ();e)| (Greet _ as st), (Heartbeat | HeartbeatACK) ->(* safe to ignore heartbeat related payloads during greetingas we'll send an heartbeat as soon as we can *)poll' st| (Greet _ as st), _ ->L.err (fun m ->m"!!!PROTOCOL VIOLATION!!! got something else other than Hello \when greeting");poll' st| ((Id hb | Resuming (_, _, hb)) as st), Pl.Hello new_hb ->L.info (fun m -> m "got new greeting, updating heartbeat");let hb_secs = Float.of_int new_hb /. 1_000. inhb.preempt ~interval:hb_secs ();poll' st| ((Id hb | Resuming (_, _, hb)) as st), Pl.Heartbeat ->L.debug (fun m -> m "requested heartbeat, obliging...");hb.preempt ();poll' st| ((Id hb | Resuming (_, _, hb)) as st), Pl.HeartbeatACK ->L.debug (fun m -> m "got hearbeat ack");hb.ack ();poll' st| Id hb, Dispatch (seq, Events.Ready info) ->let id = info.session_id inL.info (fun m ->m "session is ready"~fields:F.[ int "version" info.v; str "id" id; int "seq" seq ]);Lwt_result.return (`Connected (info.user, { id; seq }, hb))| Id _, InvalidSession _ ->L.err (fun m -> m "session was invalidated while identifying");Lwt_result.fail `Invalidated| (Id _ as st), Dispatch _ ->L.warn (fun m ->m "ignoring non ready dispatch event during identification");poll' st| Resuming (info, _, hb), Dispatch (seq, Resumed) ->L.info (fun m -> m "successfully resumed session '%s'" info.id);Lwt_result.return (`Reconnected ({ info with seq }, hb))| Resuming (info, ev_tx, hb), Dispatch (seq, ev) ->L.debug (fun m ->m "forwarding replayed event"~fields:F.[ int "seq" seq; int "event_seq" seq ]);let* () = Lwt_pipe.write_exn ev_tx ev |> Error.catch_lwt inpoll' (Resuming ({ info with seq }, ev_tx, hb))| Resuming (_, _, hb), InvalidSession _ ->let rand_wait =let r = Random.(run (float_range 1. 5.)) in(* only need precision up to ms *)float (truncate (r *. 1e3)) /. 1e3inL.warn (fun m ->m "couldn't resume session, waiting for %fs and identifying..."rand_wait);let id = Pl.Identify.make token inL.info (fun m ->m "got greeting, identifying (intents=%a)" Pl.Intents.pp id.intents);let* () =Lwt_unix.sleep rand_wait >>= fun () -> Ws.send ws (Pl.Identify id)inpoll' (Id hb)| _, Reconnect -> Lwt_result.fail `Retryinlet c =match reconn with| Some (info, ev_tx) -> Reconnection (info, ev_tx)| None -> Freshinpoll' (Greet c)let create_conn uri =let open Lwt_result.Syntax inlet+ conn = Ws_Conn.create ~zlib:false uri inlet p =Lwt_pipe.of_stream (Ws_Conn.stream conn)|> Lwt_pipe.Reader.map ~f:(function| Ws_Conn.Payload pl -> `Pl pl| Close code ->L.warn (fun m ->m "gateway ws session was closed: %a" Websocket.Close_code.ppcode);`Closed code)
match (state, pl) with| Greeting Fresh, Pl.Hello hb ->let id = Pl.Identify.make token inL.info (fun m ->m "got greeting, identifying (intents=%a)" Pl.Intents.pp id.intents);send_payload (Pl.Identify id);let hb_secs = Float.of_int hb /. 1_000. inlet hb = make_hb hb_secs in`Update (Identifying hb)| Greeting (Reconnection ({ id; seq; _ } as info)), Hello hb ->L.info (fun m ->m "got greeting, resuming session '%s' with seq=%d" id seq);send_payload (Pl.make_resume ~token ~session_id:id ~seq);let hb_secs = Float.of_int hb /. 1_000. inlet hb = make_hb hb_secs in`Update (Resuming (info, hb))| Greeting _conn, InvalidSession _ ->L.warn (fun m -> m "invalid session during initial greeting");`Invalidated| Greeting _, Heartbeat ->L.warn (fun m -> m "got hearbeat request during greeting, ignoring...");`NoUpdate| Greeting _, HeartbeatACK ->L.warn (fun m -> m "got hearbeat ack during handshake, ignoring...");`NoUpdate| Greeting Fresh, Reconnect ->L.warn (fun m ->m "got reconnection request during greeting, obliging...");`Retry| Greeting (Reconnection info), Reconnect ->L.warn (fun m ->m "got reconnection request during reconnection greeting, obliging...");`RetryWith info| Identifying hb, Dispatch (seq, Events.Ready info) ->let s_id = info.session_id inL.info (fun m ->m "session is ready"~fields:F.[ int "version" info.v; str "id" s_id; int "seq" seq ]);on_ready ();`Update (Connected ({ id = s_id; seq }, hb))| (Identifying hb | Resuming (_, hb) | Connected (_, hb)), Hello new_hb ->L.warn (fun m -> m "got new greeting, updating heartbeat_interval");let hb_secs = Float.of_int new_hb /. 1_000. inhb.preempt ~interval:hb_secs ();`NoUpdate| Identifying hb, InvalidSession _ ->L.err (fun m -> m "session was invalidated while identifying");hb.cancel ();`Invalidated| Identifying hb, Reconnect ->L.warn (fun m -> m "got reconnection request while identifying");hb.cancel ();`Retry| (Greeting _ | Identifying _), Dispatch _ ->L.warn (fun m ->m "received dispatch during initial handshake, ignoring...");`NoUpdate| (Identifying hb | Resuming (_, hb) | Connected (_, hb)), Heartbeat ->L.info (fun m -> m "requested heartbeat, obliging...");hb.preempt ();`NoUpdate| (Identifying hb | Resuming (_, hb) | Connected (_, hb)), HeartbeatACK ->L.debug (fun m -> m "got hearbeat ack");hb.ack ();`NoUpdate| Resuming (_, hb), InvalidSession _ ->L.warn (fun m ->m "couldn't resume session, waiting for %fs and identifying..." 3.4);let id = Pl.Identify.make token inL.info (fun m ->m "got greeting, identifying (intents=%a)" Pl.Intents.pp id.intents);Lwt.async (fun () ->Lwt_unix.sleep 3.4|> Lwt.map (fun () -> send_payload (Pl.Identify id)));`Update (Identifying hb)| Resuming (info, hb), Reconnect ->hb.cancel ();`RetryWith info| Resuming (({ id; _ } as i), hb), Dispatch (e_seq, Resumed) ->on_ready ();L.info (fun m -> m "successfully resumed session '%s'" id);`Update (Connected ({ i with seq = e_seq }, hb))| Resuming (({ seq; _ } as i), hb), Dispatch (e_seq, e) ->L.info (fun m ->m "forwarding replayed event"~fields:F.[ int "seq" seq; int "event_seq" e_seq ]);forward_event e;`Update (Connected ({ i with seq = e_seq }, hb))| Connected (({ id; seq; _ } as info), hb), Reconnect ->L.warn (fun m ->m "got reconnection request" ~fields:F.[ str "id" id; int "seq" seq ]);hb.cancel ();`RetryWith info| Connected (({ seq; id; _ } as info), hb), InvalidSession resume ->L.warn (fun m ->m "session invalidated" ~fields:F.[ bool "resumable" resume ]);hb.cancel ();if resume then (L.info (fun m -> m "will try to resume session '%s' on seq=%d" id seq);`RetryWith info)else `Retry| Connected (({ seq; _ } as i), hb), Dispatch (e_seq, e) ->L.info (fun m ->m "forwarding event"~fields:F.[ int "seq" seq; int "event_seq" e_seq ]);forward_event e;`Update (Connected ({ i with seq = e_seq }, hb))
( Ws.create conn,(p: [ `Pl of Pl.recv | `Closed of Websocket.Close_code.t ] Lwt_pipe.Reader.t))
let rec manager ?t () =let p_connected, u_connected = Lwt.wait () inlet p_closed, u_closed = Lwt.wait () inlet ws_conn_handler : Ws_Conn.handler =fun ws ->let disconnect () =Lwt.wakeup_later u_closed `Disconnect;Ws_Conn.close ~code:`Going_away wsinlet t =match t with| Some t ->t.ws <- ws;t| None ->{state = Greeting Fresh;ws;ev_pipe = Lwt_pipe.create ~max_size:10 ();disconnect;}inlet module L = (val session_logger t) inlet forward_event ev =Lwt.async (fun () ->Lwt_pipe.write_exn t.ev_pipe ev|> Lwt.map (fun () -> L.debug (fun m -> m "wrote to events pipe")))inlet send_payload =let bucket = Token_bucket.make ~capacity:1 2. infun pl ->Lwt.async (fun () ->Token_bucket.take bucket|> Lwt.map (fun () -> Ws_Conn.send t.ws pl))inlet on_ready () = Lwt.wakeup_later u_connected (Ok t) inlet invalidated = ref false inlet handle_payload =let f' =state_reducer~session_logger:(module L)~forward_event ~send_payload ~on_ready ~tokeninfun pl ->match f' t.state pl with| `NoUpdate -> ()| `Update st -> t.state <- st| `Retry ->Ws_Conn.close ~code:`Normal_closure t.ws;Lwt.wakeup_later u_closed (`Retry None)| `RetryWith info ->Ws_Conn.close ~code:`Abnormal_closure t.ws;Lwt.wakeup_later u_closed (`Retry (Some info))| `Invalidated -> invalidated := trueinfun frame ->match (frame, !invalidated) with| Payload pl, false -> handle_payload pl| Payload _, true -> ()| Close code, _ ->L.warn (fun m ->m "session was closed with code %a" Websocket.Close_code.pp code);let reason =(* Make (or extend) type for Discord error codes *)match code with| `Other 4000 | `Other 4007 | `Other 4009 -> `Retry None| `Other 4004 -> `Invalid "invalid token"| _ -> `Invalid "unknown"inLwt.wakeup_later u_closed reason
let ev_pipe = Lwt_pipe.create () inlet pl_pipe = Lwt_pipe.create () inlet read_exn p = Lwt_pipe.read p >|= Option.get_exn inlet dc = ref (fun () -> Lwt.return ()) inlet rec manage' ?session () =let rec connect () =let* ws, pipe = create_conn uri indo_handshake ~token ?reconn:session ws pipe >>= function| Ok res -> Lwt_result.return (ws, pipe, res)| Error (`Closed _) ->L.warn (fun m -> m "session closed during handshake");Lwt_result.fail (`Discord "unrecoverable close code during handshake")| Error `Invalidated ->L.warn (fun m ->m "session invalidated during handshake, invalid permissions?");Lwt_result.fail (`Discord "unrecoverable close code during handshake")| Error `Retry ->L.warn (fun m -> m "retrying handshake");connect ()| Error #Error.t as e -> Lwt.return einlet* ws, pipe, res = connect () inlet bus =Lwt_pipe.Reader.merge_all[pipe |> Lwt_pipe.Reader.map ~f:(fun pl -> `Ws pl);pl_pipe |> Lwt_pipe.Reader.map ~f:(fun pl -> `Fwd pl);]inlet p_dc, u_dc = Lwt.wait () inlet p_dc'ed, u_dc'ed = Lwt.wait () in(dc :=fun () ->if Lwt.is_sleeping p_dc then Lwt.wakeup_later u_dc `Dc;p_dc'ed);let info, hb =match res with| `Connected (user, info, hb) ->if Lwt.is_sleeping p_init thenLwt.wakeup_later u_init(Ok{user;disconnect = (fun () -> !dc ());ev_rx = ev_pipe;pl_tx = pl_pipe;});(ref info, hb)| `Reconnected (info, hb) -> (ref info, hb)
let* () = Ws_Conn.create ~zlib ~handler:ws_conn_handler uri inlet* t = p_connected inif Lwt.is_sleeping p_init then Lwt.wakeup_later u_init (Ok t);let* reason = p_closed |> Lwt_result.ok inmatch reason with| `Retry None ->t.state <- Greeting Fresh;manager ~t ()| `Retry (Some info) ->t.state <- Greeting (Reconnection info);manager ~t ()| `Disconnect -> Lwt_result.return ()| `Invalid msg -> Lwt_result.fail (`Discord msg)
let rec poll' () =let open Lwt.Syntax inlet pl = read_exn bus inlet* res = Lwt.pick [ pl; p_dc ] inmatch res with| `Fwd pl -> Ws.send_exn ws pl >>= poll'| `Ws (`Pl pl) -> handle_payload pl| `Ws (`Closed code) ->L.error (fun m ->m "session closed with unrecoverable close code: %a"Websocket.Close_code.pp code);Lwt_result.fail(`Discord(Format.asprintf "unrecoverable close code: %a"Websocket.Close_code.pp code))| `Dc ->Ws.close ~code:`Normal_closure ws;Lwt_pipe.close_nonblock pipe;Lwt_pipe.close_nonblock pl_pipe;Lwt_pipe.close_nonblock bus;Lwt.wakeup_later u_dc'ed ();Lwt_result.return ()and handle_payload = function| Hello new_hb ->L.warn (fun m -> m "got new greeting, updating heartbeat");hb.preempt ~interval:(float new_hb /. 1e3) ();poll' ()| Heartbeat ->L.debug (fun m -> m "requested hearbeat, obliging...");hb.preempt ();poll' ()| HeartbeatACK ->L.debug (fun m -> m "got heartbeat ack");hb.ack ();poll' ()| InvalidSession resumable ->L.warn (fun m -> m "session invalidated (resumable=%b)" resumable);let session = if resumable then Some (!info, ev_pipe) else None inhb.cancel ();Lwt_pipe.close_nonblock bus;(* TODO what to do in case of `false` again?? *)manage' ?session ()| Reconnect ->L.warn (fun m -> m "got reconnection request, obliging...");hb.cancel ();Lwt_pipe.close_nonblock bus;manage' ~session:(!info, ev_pipe) ()| Dispatch (seq, Ready _) | Dispatch (seq, Resumed) ->L.warn (fun m ->m "ignoring handshake related payloads on established session");info := { !info with seq };poll' ()| Dispatch (seq, ev) ->info := { !info with seq };Lwt_pipe.write ev_pipe ev >>= fun ok ->if ok then poll' () else Lwt_result.return ()inpoll' () >>= fun out ->hb.cancel ();Ws.close ~code:`Going_away ws;Lwt_pipe.close_nonblock pipe;Lwt_pipe.close_nonblock pl_pipe;Lwt_pipe.close_nonblock bus;Lwt_pipe.close ev_pipe >|= fun () -> out
let events { ev_pipe; _ } = ev_pipe
let user { user; _ } = userlet _send_exn { pl_tx; _ } pl = Lwt_pipe.write_exn pl_tx pllet send_presence_update t ?since ~afk status =_send_exn t (Pl.make_presence_update ?since ~afk status)let send_voice_state_update t ?channel_id ?(self_mute = false)?(self_deaf = false) guild_id =_send_exn t(Pl.make_voice_state_update ?channel_id ~self_mute ~self_deaf guild_id)let send_guild_request_members t ?presences ?nonce ~q guild_id =_send_exn t (Pl.make_request_guild_members ?presences ?nonce ~q guild_id)
let cancel_waiting t =let rec f' () =match CCDeque.take_front_opt t.waiters with| Some (Waiter (_, _, p)) ->Lwt.cancel p;f' ()| None -> ()inf' ()
open Globalsopen Lwt.Infixmodule L = (val Relog.logger ~namespace:__MODULE__ ())module Packet = structmodule P = structopen Angstromlet is_num = function '0' .. '9' -> true | _ -> falselet is_null = function '\x00' -> true | _ -> falsemodule Ip = structlet packet =let* () =BE.any_uint16 >>= function| 2 -> return ()| d -> fail (Printf.sprintf "expected response type (0x2), got %X" d)inlet* len = BE.any_uint16 inlet* body_i = pos inlet* ssrc = BE.any_int32 >>| Int32.to_int inlet* addr_buf = take 64 inlet addr_p = take_while1 @@ Fun.(is_null %> not) inlet* addr =matchAngstrom.parse_string ~consume:Angstrom.Consume.Prefix addr_paddr_bufwith| Ok a -> return a| Error e -> fail einlet* port = BE.any_uint16 inlet+ () =end_of_input*> (pos >>= function| n when n - body_i = len -> return ()| n ->fail(Printf.sprintf"expected body length of %d bytes, got %d bytes" len n))in(ssrc, addr, port)endendmodule Ip = structlet of_bigstring bs =Angstrom.parse_bigstring ~consume:Angstrom.Consume.All P.Ip.packet bslet write ~ssrc f =Faraday.BE.write_uint16 f 0x1;Faraday.BE.write_uint16 f 70;Faraday.BE.write_uint32 f (Int32.of_int ssrc);Faraday.write_bytes f (Bytes.create 66)endmodule Keep_alive = structlet write ~ssrc f = Faraday.BE.write_uint32 f (Int32.of_int ssrc)let interval = 5.endmodule RTP = structlet header_len = 12let write_header ~seq ~ts ~ssrc f =let s = Faraday.pending_bytes f inFaraday.write_uint8 f 0x80;Faraday.write_uint8 f 0x78;Faraday.BE.write_uint16 f Uint16.(to_int seq);Faraday.BE.write_uint32 f Uint32.(to_int32 ts);Faraday.BE.write_uint32 f Int32.(of_int ssrc);assert (Faraday.pending_bytes f - s = header_len)endendlet ip_discovery ?(retries = 3) ?(timeout = 1.) ~ssrc sock =let open Lwt.Syntax inlet buf = Bigstringaf.create 74 inlet timeout () =Lwt_unix.sleep timeout |> Lwt.map (fun _ -> Error `Timeout)inlet send_ip ~f ~ssrc sock =Packet.Ip.write ~ssrc f;let b = Faraday.serialize_to_string f |> Bytes.unsafe_of_string inlet len = Bytes.length b inLwt_unix.send sock b 0 len [] >|= fun n -> assert (n = len)inlet recv_ip ~buf sock =let open Lwt.Syntax inlet b = Bigstringaf.to_string buf |> Bytes.unsafe_of_string inlet* _ = Lwt_unix.read sock b 0 74 inBigstringaf.blit_from_bytes b ~src_off:0 buf ~dst_off:0 ~len:74;let pkt = Packet.Ip.of_bigstring buf inmatch pkt with Ok pkt -> Lwt.return pkt | Error msg -> failwith msginlet rec retry' n =let f = Faraday.of_bigstring buf inlet* () = send_ip ~f ~ssrc sock inFaraday.close f;L.debug (fun m -> m "sent ip discovery request packet");let* o = Lwt.pick [ timeout (); recv_ip ~buf sock |> Lwt_result.ok ] inmatch o with| Ok (_, ip, port) -> Lwt_result.return (ip, port)| Error `Timeout when n > 0 ->L.warn (fun m ->m"timed out (%dx) waiting for ip discovery response packet, \retrying..."(retries - n + 1));retry' (n - 1)| Error `Timeout ->Lwt_result.fail "timed out waiting for ip discovery response"inretry' retriestype t = {sock : Lwt_unix.file_descr;local_addr : Unix.inet_addr * int;discord_addr : Unix.inet_addr * int;ssrc : int;f : Faraday.t;flush_packet : unit -> unit Lwt.t;send_tx : [ `Flush | `Keep_alive ] Lwt_pipe.Writer.t;}type encryption_mode = Normal | Suffix | Lite of uint32 reflet encryption_mode_of_string = function| "xsalsa20_poly1305" -> Normal| "xsalsa20_poly1305_suffix" -> Suffix| "xsalsa20_poly1305_lite" ->Lite (ref (Random.int64 Int64.(2L ** 32L) |> Uint32.of_int64))| m -> raise @@ Invalid_argument ("unsupported encryption mode " ^ m)type crypt = { mode : encryption_mode; secret : bytes }let encrypt ~nonce ~secret data =let nonce = Sodium.Secret_box.Bigbytes.to_nonce nonce inlet secret = Sodium.Secret_box.Bytes.to_key secret inSodium.Secret_box.Bigbytes.secret_box secret data noncelet send_voice_packet ~crypt ~ts ~seq ~audio t =let f = t.f inPacket.RTP.write_header ~seq ~ts ~ssrc:t.ssrc f;let encrypt nonce = encrypt audio ~nonce ~secret:crypt.secret inlet () =match crypt.mode with| Normal ->let nonce = Faraday.create 24 inPacket.RTP.write_header ~seq ~ts ~ssrc:t.ssrc nonce;let padding =String.make(Sodium.Secret_box.nonce_size - Faraday.pending_bytes nonce)'\x00'inFaraday.write_string nonce padding;nonce |> Faraday.serialize_to_bigstring |> encrypt|> Faraday.schedule_bigstring f| Suffix ->let nonce = Sodium.Secret_box.(random_nonce () |> Bigbytes.of_nonce) inFaraday.schedule_bigstring f (encrypt nonce);Faraday.schedule_bigstring f nonce| Lite n ->let nonce = Bigstringaf.create Sodium.Secret_box.nonce_size inBigstringaf.unsafe_set_int32_be nonce 0 (Uint32.to_int32 !n);let _padding =Seq.(4 --^ Bigstringaf.length nonce|> iter (fun i -> nonce.{i} <- '\x00'))inlet next =if Uint32.(compare !n max_int) = 0 then Uint32.zeroelse Uint32.(!n + one)inn := next;Faraday.schedule_bigstring f (encrypt nonce);Faraday.schedule_bigstring f nonceint.flush_packet ()let create ~ssrc (ip, port) =let open Lwt.Syntax inlet sock =Lwt_unix.socket Unix.PF_INET Unix.SOCK_DGRAM(Unix.getprotobyname "udp").Unix.p_protoinlet* () = Lwt_unix.bind sock Unix.(ADDR_INET (inet_addr_any, 0)) inlet addr = Unix.inet_addr_of_string ip inlet* () = Lwt_unix.connect sock Unix.(ADDR_INET (addr, port)) inlet discord_addr = (addr, port) inL.info (fun m ->m "discovering external ip using discord's voice server: %s:%d" ip port);let* ip_d, port_d =ip_discovery ~ssrc sock|> Lwt.map (function Ok d -> d | Error msg -> failwith msg)inL.info (fun m -> m "discovered ip and port: %s:%d" ip_d port_d);let local_addr = Unix.(inet_addr_of_string ip_d, port_d) inlet f = Faraday.create (1024 * 4) inlet writev = Faraday_lwt_unix.writev_of_fd sock inlet send_tx = Lwt_pipe.create () inlet t ={f;sock;local_addr;discord_addr;ssrc;flush_packet = (fun () -> Lwt_pipe.write send_tx `Flush >|= ignore);send_tx;}inlet yield =let keep_alive =Lwt_stream.from (fun () ->Lwt_unix.sleep Packet.Keep_alive.interval >|= fun () ->Some `Keep_alive)|> Lwt_pipe.of_streaminLwt_pipe.connect ~ownership:`OutOwnsIn keep_alive send_tx;fun f ->Lwt_pipe.read send_tx >|= function| Some `Keep_alive ->L.debug (fun m ->m "sending UDP keepalive packet"~fields:Relog.Field.[int "ssrc" ssrc;float "interval" Packet.Keep_alive.interval;]);Packet.Keep_alive.write ~ssrc f| Some `Flush -> ()| None ->L.debug (fun m -> m "closing udp socket");Faraday.close finlet write_worker = Faraday_lwt_unix.serialize f ~yield ~writev inlet read_worker =let open Lwt.Infix inlet b = Bytes.create (1024 * 4) inlet b_len = Bytes.length b inlet rec f () =if Lwt_pipe.is_closed send_tx then Lwt.return_unitelselet r = Lwt_unix.read sock b 0 b_len >|= fun n -> `read n inlet t = Lwt_unix.sleep (1. /. 5.) >|= fun () -> `timeout inLwt.pick [ r; t ] >>= function| `read n ->L.trace (fun m ->m "got %d bytes from UDP (ssrc=%d) (rtcp? keepalive ack?)" nssrc);f ()| `timeout -> f ()inf ()inLwt_pipe.keep send_tx write_worker;Lwt_pipe.keep send_tx read_worker;let+ () = Lwt_pipe.write_exn send_tx `Keep_alive intlet destroy { sock; send_tx; _ } =match Lwt_unix.state sock with| Lwt_unix.Opened ->L.debug (fun m -> m "closing udp serializer");Lwt_pipe.close_nonblock send_tx| Closed | Aborted _ -> ()let local_addr { local_addr; _ } = local_addrlet server_addr { discord_addr; _ } = discord_addr
open Globalsopen Lwt.Infixmodule L = (val Relog.logger ~namespace:__MODULE__ ())module F = Relog.Fieldmodule Ws_Conn = Websocket.Make (Voice_payload)module Pl = Voice_payloadmodule Ws = structtype t = t' refand t' = Open of Token_bucket.t * Ws_Conn.t | Closedlet create conn = ref (Open (Token_bucket.make ~capacity:2 1., conn))let send t pl =match !t with| Open (tb, conn) ->Lwt.(Token_bucket.take tb >|= fun () ->Ws_Conn.send conn pl;Ok ())| Closed -> Lwt.return (Error (`Msg "cannot send payload to closed ws"))let send_exn t pl =Lwt.(send t pl >|= function| Ok () -> ()| Error e -> failwith (Error.to_string e))let close ~code t =match !t with| Open (tb, conn) ->t := Closed;Token_bucket.cancel_waiting tb;Ws_Conn.close ~code conn| Closed -> ()endmodule Close_code = structtype discord =[ `Unknown_op| `Invalid_payload| `Not_authenticated| `Authentication_failed| `Already_authenticated| `Invalid_session| `Session_timeout| `Server_not_found| `Unknown_protocol| `Disconnected| `Voice_server_crashed| `Unknown_encryption_mode ]type t = [ Websocket.Close_code.standard | discord ]let is_discord = function #discord -> true | _ -> falselet is_std = function #Websocket.Close_code.standard -> true | _ -> falselet to_int = function| #Websocket.Close_code.standard as c -> Websocket.Close_code.to_int c| `Unknown_op -> 4001| `Invalid_payload -> 4002| `Not_authenticated -> 4003| `Authentication_failed -> 4004| `Already_authenticated -> 4005| `Invalid_session -> 4006| `Session_timeout -> 4009| `Server_not_found -> 4011| `Unknown_protocol -> 4012| `Disconnected -> 4014| `Voice_server_crashed -> 4015| `Unknown_encryption_mode -> 4016let of_close_code_exn = function| #Websocket.Close_code.standard as c -> c| `Other 4001 -> `Unknown_op| `Other 4002 -> `Invalid_payload| `Other 4003 -> `Not_authenticated| `Other 4004 -> `Authentication_failed| `Other 4005 -> `Already_authenticated| `Other 4006 -> `Invalid_session| `Other 4009 -> `Session_timeout| `Other 4011 -> `Server_not_found| `Other 4012 -> `Unknown_protocol| `Other 4014 -> `Disconnected| `Other 4015 -> `Voice_server_crashed| `Other 4016 -> `Unknown_encryption_mode| `Other c -> failwith (Printf.sprintf "unknown voice close code: %d" c)let pp =let pp' fmt = function| `Unknown_op -> Format.fprintf fmt "invalid opcode"| `Invalid_payload ->Format.fprintf fmt "invalid payload while identifying"| `Not_authenticated -> Format.fprintf fmt "not authenticated"| `Authentication_failed -> Format.fprintf fmt "authentication failed"| `Already_authenticated -> Format.fprintf fmt "already authenticated"| `Invalid_session -> Format.fprintf fmt "session is no longer valid"| `Session_timeout -> Format.fprintf fmt "session timed out"| `Server_not_found -> Format.fprintf fmt "voice server not found"| `Unknown_protocol -> Format.fprintf fmt "unknown protocol"| `Disconnected -> Format.fprintf fmt "disconnected"| `Voice_server_crashed -> Format.fprintf fmt "voice server crashed"| `Unknown_encryption_mode -> Format.fprintf fmt "unknown encryption mode"infun fmt t ->match t with| #Websocket.Close_code.standard as c -> Websocket.Close_code.pp fmt c| #discord as t -> Format.fprintf fmt "(%d %a)" (to_int t) pp' tlet is_recoverable = function| `Unknown_op | `Invalid_payload | `Not_authenticated| `Authentication_failed | `Already_authenticated | `Unknown_protocol| `Disconnected | `Unknown_encryption_mode| #Websocket.Close_code.standard ->false| _ -> trueendtype t = {disconnect : unit -> unit Lwt.t;ws_writer : Pl.send Lwt_pipe.Writer.t;speak : bool Lwt_pipe.Writer.t;rtp_writer : bigstring Lwt_pipe.Writer.t;}type hb = {mutable interval : float;mutable preempt : ?interval:float -> unit -> unit;mutable ack : int -> unit;mutable cancel : unit -> unit;}(* TODO Check if resuming also implies a fresh UDP handshake *)type handshake_state =| Greet of conn| Id of hb| Resuming of hb * session| Establish_udp of hb * Udp_connection.tand conn = Fresh | Reconnection of sessionand session = { rtp : Rtp.t; mutable speaking : bool }let make_heartbeat ?err fn interval =let err =Option.get_or~default:(fun () -> failwith "no ACK of last heartbeat received")errinlet out ={interval;preempt = (fun ?interval:_ -> ignore);ack = ignore;cancel = ignore;}inlet gen_nonce =let st = Random.State.make_self_init () infun () -> Random.State.bits stinlet rec loop () =let open Lwt.Syntax inlet acked = ref false inlet nonce = gen_nonce () inlet () = fn nonce inlet p_preempt, u_preempt = Lwt.wait () inlet p_sleep = Lwt_unix.sleep out.interval |> Lwt.map (Fun.const `Sleep) inout.ack <- (fun n -> if not !acked then acked := nonce = n);out.cancel <-(fun () ->if Lwt.is_sleeping p_preempt then Lwt.wakeup_later u_preempt `Cancel);out.preempt <-(fun ?(interval = interval) () ->if Lwt.is_sleeping p_preempt thenLwt.wakeup_later u_preempt (`Preempt interval));let* r = Lwt.pick [ p_sleep; p_preempt ] inmatch (r, !acked) with| `Sleep, true -> loop ()| `Preempt interval, _ ->out.interval <- interval;loop ()| `Sleep, false ->err ();Lwt.return ()| `Cancel, _ -> Lwt.return ()inLwt.async loop;outlet secret_of_int_list l =Seq.of_list l |> Seq.map Char.of_int_exn |> Bytes.of_seqlet with_ws_params ~version uri =let uri = Uri.with_path uri "/" inUri.with_query uri [ ("v", [ Versions.Voice.to_string version ]) ]let do_handshake ~server_id ~user_id ~session_id ~token ?session ws pl_pipe =let open Lwt_result.Syntax inlet make_hb interval =make_heartbeat(fun nonce -> Lwt.async (fun () -> Ws.send_exn ws (Pl.heartbeat nonce)))intervalinlet rec poll' st =let* pl =Lwt_pipe.read pl_pipe|> Lwt.map (function| Some (`Pl pl) -> Ok pl| Some (`Closed code) -> Error (`Closed code)| None -> assert false)inmatch (st, pl) with| Greet Fresh, Pl.Hello hb ->L.info (fun m -> m "got greeting, identifying");let* () =Ws.send ws (Pl.make_identify ~server_id ~user_id ~session_id ~token)inlet hb_secs = Float.of_int hb /. 1e3 inlet hb = make_hb hb_secs inpoll' (Id hb)| Greet (Reconnection session), Hello hb ->L.info (fun m -> m "got greeting, resuming session '%s'" session_id);let* () = Ws.send ws (Pl.make_resume ~server_id ~session_id ~token) inlet hb_secs = Float.of_int hb /. 1e3 inlet hb = make_hb hb_secs inpoll' (Resuming (hb, session))| ( ((Id hb | Resuming (hb, _) | Establish_udp (hb, _)) as st),Hello new_interval ) ->let hb_secs = Float.of_int new_interval /. 1e3 inL.warn (fun m -> m "got new greeting, updating heartbeat");hb.preempt ~interval:hb_secs ();poll' st| ( ((Id hb | Resuming (hb, _) | Establish_udp (hb, _)) as st),HeartbeatACK nonce ) ->L.debug (fun m -> m "got hearbeat ack for nonce '%d'" nonce);hb.ack nonce;poll' st| Resuming (hb, session), Resumed -> Lwt_result.return (hb, session)| Id hb, Ready ({ ip; port; ssrc; _ } as info) ->L.info (fun m ->m"voice ws session is ready, connecting to UDP voice server with:\n\%a"Pl.Ready.pp info);let* udp = Udp_connection.create ~ssrc (ip, port) |> Error.catch_lwt inlet ip, port = Udp_connection.local_addr udp inlet address = Unix.string_of_inet_addr ip inlet* () =Ws.send ws(Pl.make_select_protocol ~address ~port ~mode:"xsalsa20_poly1305")inpoll' (Establish_udp (hb, udp))| Establish_udp (hb, udp), SessionDescription desc ->L.info (fun m -> m "successfuly handshaked voice connection");let secret = secret_of_int_list desc.secret_key inlet mode = Udp_connection.encryption_mode_of_string desc.mode inlet crypt = Udp_connection.{ secret; mode } inLwt_result.return (hb, { rtp = Rtp.make ~udp ~crypt; speaking = false })| st, _pl ->L.warn (fun m -> m "ignoring non-control payload during handshake");poll' stinlet c = match session with Some s -> Reconnection s | None -> Fresh inpoll' (Greet c)let create_conn uri =let open Lwt_result.Syntax inlet+ conn = Ws_Conn.create ~zlib:false uri inlet p =Lwt_pipe.of_stream (Ws_Conn.stream conn)|> Lwt_pipe.Reader.map ~f:(function| Ws_Conn.Payload pl -> `Pl pl| Close code ->let code = Close_code.of_close_code_exn code inL.warn (fun m ->m "voice ws session was closed: %a" Close_code.pp code);`Closed code)in( Ws.create conn,(p : [ `Pl of Pl.recv | `Closed of Close_code.t ] Lwt_pipe.Reader.t) )let create ?(on_destroy = fun _ -> ()) ?(version = Versions.Voice.V4) ~server_id~user_id ~session_id ~token endpoint =let open Lwt_result.Syntax inlet uri = Uri.of_string ("wss://" ^ endpoint) |> with_ws_params ~version inlet p_init, u_init = Lwt.wait () inlet ws_writer = Lwt_pipe.create () inlet rtp_writer = Lwt_pipe.create () inlet speak_pipe = Lwt_pipe.create () inlet read_exn p = Lwt_pipe.read p >|= Option.get_exn inlet dc = ref (fun () -> Lwt.return ()) inlet rec manage' ?session () =let rec connect () =let* ws, pipe = create_conn uri inlet res =do_handshake ~server_id ~user_id ~session_id ~token ?session ws pipeinLwt.bind res (function| Ok (hb, session) -> Lwt_result.return (ws, pipe, hb, session)| Error (`Closed code) when Close_code.is_recoverable code ->L.warn (fun m ->m "recoverable close code during handshake, retrying...");connect ()| Error (`Closed `Disconnected) ->L.warn (fun m ->m "disconnected during handshake, invalid permissions?");Lwt.return(Error (`Discord "voice session disconnected during handshake"))| Error (`Closed _) ->L.error (fun m -> m "unrecoverable close code during handshake");assert false| Error #Error.t as e -> Lwt.return e)inlet* ws, pipe, hb, session = connect () inlet p_dc, u_dc = Lwt.wait () inlet p_dc'ed, u_dc'ed = Lwt.wait () in(dc :=fun () ->Lwt.wakeup_later u_dc `Dc;p_dc'ed);if Lwt.is_sleeping p_init thenLwt.wakeup_later u_init(Ok{disconnect = (fun () -> !dc ());ws_writer;rtp_writer;speak = speak_pipe;});let bus =Lwt_pipe.Reader.merge_all[pipe |> Lwt_pipe.Reader.map ~f:(fun pl -> `Ws pl);ws_writer |> Lwt_pipe.Reader.map ~f:(fun pl -> `Fwd pl);speak_pipe |> Lwt_pipe.Reader.map ~f:(fun sp -> `Speak sp);rtp_writer |> Lwt_pipe.Reader.map ~f:(fun pl -> `Fwd_rtp pl);]inlet rec poll' () =let open Lwt.Syntax inlet pl = read_exn bus inlet* res = Lwt.pick [ pl; p_dc ] inmatch res with| `Fwd pl -> Ws.send_exn ws pl >>= poll'| `Speak sp when Stdlib.(sp != session.speaking) ->session.speaking <- sp;Ws.send_exn ws(Pl.make_speaking ~ssrc:(Rtp.ssrc session.rtp) ~delay:0(if sp then 1 else 0))>>= poll'| `Speak _ -> poll' ()| `Fwd_rtp audio -> Rtp.send_packet session.rtp audio >>= poll'| `Ws (`Pl pl) -> handle_payload pl| `Ws (`Closed code) when Close_code.is_recoverable code ->L.warn (fun m ->m "session closed with recoverable close code, retrying...");session.speaking <- false;hb.cancel ();manage' ~session ()| `Ws (`Closed code) ->L.error (fun m ->m "session closed with unrecoverable close code: %a" Close_code.ppcode);Lwt.return(Error (`Discord (Format.asprintf "%a" Close_code.pp code)))| `Dc ->Lwt_pipe.close_nonblock rtp_writer;Rtp.destroy session.rtp;Ws.close ~code:`Normal_closure ws;Lwt_pipe.close_nonblock pipe;Lwt_pipe.close_nonblock ws_writer;Lwt_pipe.close_nonblock bus;Lwt.wakeup_later u_dc'ed ();Lwt.return (Ok ())and handle_payload = function| Hello new_hb ->L.warn (fun m -> m "got new greeting, updating heartbeat");hb.preempt ~interval:(Float.of_int new_hb /. 1e3) ();poll' ()| Ready info ->L.error (fun m ->m "got ready on established session, new voice server??@.%a"Pl.Ready.pp info);assert false| SessionDescription desc ->L.warn (fun m ->m "got session description, updating...@.%a"Pl.SessionDescription.pp desc);let secret = secret_of_int_list desc.secret_key inlet mode = Udp_connection.encryption_mode_of_string desc.mode inRtp.set_crypt session.rtp Udp_connection.{ secret; mode };poll' ()| HeartbeatACK nonce ->hb.ack nonce;poll' ()| Speaking _ | Resumed | ClientDisconnect ->L.debug (fun m -> m "ignoring speaking/resumed/clientdisconnect");poll' ()inpoll' () >|= fun out ->hb.cancel ();Lwt_pipe.close_nonblock rtp_writer;Rtp.destroy session.rtp;Ws.close ~code:`Going_away ws;Lwt_pipe.close_nonblock pipe;Lwt_pipe.close_nonblock ws_writer;Lwt_pipe.close_nonblock bus;outinLwt.async (fun () ->manage' ()|> Lwt.map (function| Ok () -> ()| Error e when Lwt.is_sleeping p_init ->Lwt.wakeup_later u_init (Error e)| Error e -> on_destroy e));p_initlet _speak s { speak; _ } = Lwt_pipe.write_exn speak slet start_speaking = _speak truelet stop_speaking = _speak falselet send_rtp { rtp_writer; _ } audio = Lwt_pipe.write_exn rtp_writer audiolet disconnect { disconnect; _ } = disconnect ()
module Hello = structlet t_of_yojson json =Yojson.Safe.Util.(json |> member "heartbeat_interval" |> to_float |> Int.of_float)endmodule Identify = structtype t = {server_id : Models.Snowflake.t;user_id : Models.Snowflake.t;session_id : string;token : string;}[@@deriving yojson, show] [@@yojson.allow_extra_fields]let make ~server_id ~user_id ~session_id ~token ={ server_id; user_id; session_id; token }end
module Ready = structtype t = { ssrc : int; ip : string; port : int; modes : string list }[@@deriving yojson, show] [@@yojson.allow_extra_fields]endmodule SelectProtocol = structtype t = { protocol : string; data : data }and data = { address : string; port : int; mode : string }[@@deriving yojson, show] [@@yojson.allow_extra_fields]let make ~address ~port ~mode ={ protocol = "udp"; data = { address; port; mode } }endmodule SessionDescription = structtype t = { mode : string; secret_key : int list }[@@deriving yojson, show] [@@yojson.allow_extra_fields]endmodule Resume = structtype t = {server_id : Models.Snowflake.t;session_id : string;token : string;}[@@deriving yojson, show] [@@yojson.allow_extra_fields]let make ~server_id ~session_id ~token = { server_id; session_id; token }endmodule Speaking = structtype t = {speaking : int;delay : int option; [@yojson.option]ssrc : int option; [@yojson.option]}[@@deriving yojson, show] [@@yojson.allow_extra_fields]let make ?delay ?ssrc speaking = { speaking; delay; ssrc }end
| Identify : Dir.send t| SelectProtocol : Dir.send t| Ready : Dir.recv t| Heartbeat : Dir.send t| SessionDescription : Dir.recv t| Speaking : _ Dir.bidi t| HeartbeatACK : Dir.recv t| Resume : Dir.send t| Hello : Dir.recv t
| Identify : Identify.t -> Dir.send t| SelectProtocol : SelectProtocol.t -> Dir.send t| Ready : Ready.t -> Dir.recv t| Heartbeat : int -> Dir.send t| SessionDescription : SessionDescription.t -> Dir.recv t| Speaking : Speaking.t -> _ Dir.bidi t| HeartbeatACK : int -> Dir.recv t| Resume : Resume.t -> Dir.send t| Hello : int -> Dir.recv t
| Identify -> 0| SelectProtocol -> 1| Ready -> 2| Heartbeat -> 3| SessionDescription -> 4| Speaking -> 5| HeartbeatACK -> 6| Resume -> 7| Hello -> 8
| Identify _ -> 0| SelectProtocol _ -> 1| Ready _ -> 2| Heartbeat _ -> 3| SessionDescription _ -> 4| Speaking _ -> 5| HeartbeatACK _ -> 6| Resume _ -> 7| Hello _ -> 8
| 2, Some _d -> Ready| 3, Some _d -> SessionDescription| 5, Some _d -> Speaking| 6, Some _d -> HeartbeatACK| 8, Some _d -> Hello| 9, Some _d -> Resumed
| 2, Some d -> Ready (Ready.t_of_yojson d)| 4, Some d -> SessionDescription (SessionDescription.t_of_yojson d)| 5, Some d -> Speaking (Speaking.t_of_yojson d)| 6, Some d -> HeartbeatACK ([%of_yojson: int] d)| 8, Some d -> Hello (Hello.t_of_yojson d)| 9, _ -> Resumed
| Identify -> Raw.make ()| SelectProtocol -> Raw.make ()| Heartbeat -> Raw.make ()| Speaking -> Raw.make ()| Resume -> Raw.make ()
| Identify id -> Raw.make ~d:(Identify.yojson_of_t id) ()| SelectProtocol sp -> Raw.make ~d:(SelectProtocol.yojson_of_t sp) ()| Heartbeat nonce -> Raw.make ~d:(`Int nonce) ()| Speaking d -> Raw.make ~d:(Speaking.yojson_of_t d) ()| Resume d -> Raw.make ~d:(Resume.yojson_of_t d) ()
let heartbeat nonce = Heartbeat noncelet make_identify ~server_id ~user_id ~session_id ~token =Identify (Identify.make ~server_id ~user_id ~session_id ~token)let make_select_protocol ~address ~port ~mode =SelectProtocol (SelectProtocol.make ~address ~port ~mode)let make_resume ~server_id ~session_id ~token =Resume (Resume.make ~server_id ~session_id ~token)let make_speaking ?ssrc ?delay s = Speaking (Speaking.make ?ssrc ?delay s)
let close ?code { close; _ } = close ?code ()
let send t (pl : send) =L.debug (fun m ->let pp = P.to_json pl |> Yojson.Safe.pretty_to_string inm "sending payload:@.%s" pp);let out = pl |> P.to_bytes inlet len = Bytes.length out inlet rec send' n =match len - n with| len when len > max_payload_len ->Websocketaf.Wsd.send_bytes t.wsd ~kind:`Continuation out ~off:n~len:max_payload_len;send' (n + max_payload_len)| len -> Websocketaf.Wsd.send_bytes t.wsd ~kind:`Text out ~off:n ~leninsend' 0
let rec _connect :enc:enc ->zlib:bool ->ssl:bool ->string ->int ->string ->handler:handler ->(unit, [> `Msg of string ]) Lwt_result.t =fun ~enc ~zlib ~ssl host port resource ~handler ->
let close ?code t = Websocketaf.Wsd.close ?code t.wsdlet rec _connect ~enc ~zlib ~ssl host port resource =
let send pl =L.debug (fun m ->let pp = P.to_json pl |> Yojson.Safe.pretty_to_string inm "sending payload:@.%s" pp);let out = pl |> P.to_bytes inlet len = Bytes.length out inlet rec send' n =match len - n with| len when len > max_payload_len ->Websocketaf.Wsd.send_bytes wsd ~kind:`Text out ~off:n~len:max_payload_len;send' (n + max_payload_len)| len -> Websocketaf.Wsd.send_bytes wsd ~kind:`Text out ~off:n ~len
let stream, push = Lwt_stream.create () inLwt.wakeup_later u (Ok { info = conn_info; wsd; stream });let do_read ~on_done payload =let buf = Faraday.create 1024 inlet on_eof () =L.debug (fun m -> m "done reading!");let out = Faraday.serialize_to_bigstring buf inon_done out
let close_code =Bigstringaf.get_int16_be bs off |> Close_code.of_int_exn
let on_done frame =let close_code =Bigstringaf.get_int16_be frame 0 |> Close_code.of_int_exninL.warn (fun m ->m "got close frame with code=%a" Close_code.pp close_code);push (Some (Close close_code));push None
let pl_json =tryBigstringaf.substring bs ~off ~len |> Yojson.Safe.from_stringwith exn ->L.err (fun m ->m "invalid json payload"~fields:F.[ str "exn" (Printexc.to_string exn) ]);raise exninL.debug (fun m ->m "got websocket payload:@.%s"(pl_json |> Yojson.Safe.pretty_to_string));let () =
let on_done frame =let pl_json =try Bigstringaf.to_string frame |> Yojson.Safe.from_stringwith exn ->L.err (fun m ->m "invalid json payload"~fields:F.[ str "exn" (Printexc.to_string exn) ]);raise exninL.debug (fun m ->m "got websocket payload:@.%s"(pl_json |> Yojson.Safe.pretty_to_string));
Lwt.bind p (function| Error (`Redir loc) ->let host, port, ssl, resource = _uri_info (Uri.of_string loc) in_connect ~enc ~zlib ~ssl host port resource ~handler| Error (`Msg _) as err -> Lwt.return err| Ok () -> Lwt.return (Ok ()))
p >>= function| Error (`Redir loc) ->let host, port, ssl, resource = _uri_info (Uri.of_string loc) in_connect ~enc ~zlib ~ssl host port resource| Error (`Msg _) as err -> Lwt.return err| Ok t -> Lwt.return (Ok t)
"@opam/piaf":"anmonteiro/piaf:piaf.opam#01601aeda4a415d335f61ac13fb738cdb7b834ea","@opam/websocketaf":"link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf.opam","@opam/websocketaf-lwt":"link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf-lwt.opam","@opam/websocketaf-lwt-unix":"link:/Users/jcosta/Documents/Workspace/contrib/websocketaf/websocketaf-lwt-unix.opam",
"@opam/piaf": "anmonteiro/piaf:piaf.opam#01601aeda4a415d335f61ac13fb738cdb7b834ea","@opam/websocketaf": "quartz55/websocketaf:websocketaf.opam#d309d15","@opam/websocketaf-lwt": "quartz55/websocketaf:websocketaf-lwt.opam#d309d15","@opam/websocketaf-lwt-unix": "quartz55/websocketaf:websocketaf-lwt-unix.opam#d309d15",
"@opam/conf-libsodium": {"source": "github:EduardoRFS/esy-libsodium:libsodium.opam#caeedd7","override": {"dependencies": {"esy-libsodium": "github:EduardoRFS/esy-libsodium#caeedd7"}}},"@opam/sodium": {"source": "github:quartz55/ocaml-sodium:sodium.opam#6088c1c","override": {"dependencies": {"@opam/conf-libsodium": "*"}}},"@discopotty/opus": "link:./vendor/opus/package.json","@opam/conf-libopus": {"source": "link:./vendor/esy-libopus/conf-libopus.opam","override": {"dependencies": {"esy-libopus": "./vendor/esy-libopus"}}},"esy-libopus": "./vendor/esy-libopus/package.json",
let setup_logging ?(level = Relog.Level.Debug) () =let cli_fmter = Relog.Formatter.default ~color:true ~oneline:false () inlet cli_fmt = Format.formatter_of_out_channel stderr inRelog.Sink.make (fun r ->if Relog.(Level.compare (Record.level r) level) <= 0 thencli_fmter cli_fmt relse ())|> Relog.Sink.set
opam-version: "2.0"maintainer: "https://github.com/ocaml/opam-repository/issues"homepage: "https://xiph.org/ogg/"bug-reports: "https://github.com/ocaml/opam-repository/issues"authors: "Xiph.Org Foundation"license: "BSD"build: ["pkg-config" "--exists" "ogg"]depends: ["conf-pkg-config" {build}]depexts: [["libogg-dev"] {os-distribution = "alpine"}["libogg"] {os-distribution = "arch"}["libogg-dev"] {os-family = "debian"}["libogg-devel"] {os-distribution = "centos"}["libogg-devel"] {os-distribution = "fedora"}["libogg-devel"] {os-family = "suse"}["libogg"] {os-distribution = "nixos"}["libogg"] {os-family = "bsd"}["libogg"] {os = "macos" & os-distribution = "homebrew"}]synopsis: "Virtual package relying on libogg"description:"This package can only install if the ogg library is installed on the system."flags: conf
{"name": "esy-libogg","version": "1.3.1","description": "Mirror of libogg","license": "BSD","source": "https://downloads.xiph.org/releases/ogg/libogg-1.3.4.tar.gz#851cef020b346d44893e5d1c3dab83c675d479d9","override": {"build": [["./configure","--prefix=$cur__install","--disable-dependency-tracking"],["make","-j4"]],"install": [["make","install"]],"buildsInSource": true,"exportedEnv": {"LD_LIBRARY_PATH": {"val": "#{self.lib : $LD_LIBRARY_PATH}","scope": "global"},"OGG_LIB_PATH": {"val": "#{self.lib}","scope": "global"},"OGG_INCLUDE_PATH": {"val": "#{self.install / 'include'}","scope": "global"},"PKG_CONFIG_PATH": {"val": "#{self.lib / 'pkgconfig' }:$PKG_CONFIG_PATH","scope": "global"}},"dependencies": {"@opam/conf-autoconf": "esy-packages/esy-autoconf:package.json#fb93edf","@opam/conf-pkg-config": "*"}}}
opam-version: "2.0"maintainer: "https://github.com/ocaml/opam-repository/issues"homepage: "https://opus-codec.org/"bug-reports: "https://github.com/ocaml/opam-repository/issues"authors: "Xiph.Org Foundation"license: "BSD"build: ["pkg-config" "--exists" "opus"]depends: ["conf-pkg-config" {build}]depexts: [["libopus-dev"] {os-distribution = "alpine"}["libopus"] {os-distribution = "arch"}["libopus-dev"] {os-family = "debian"}["libopus-devel"] {os-distribution = "centos"}["libopus-devel"] {os-distribution = "fedora"}["libopus-devel"] {os-family = "suse"}["libopus"] {os-distribution = "nixos"}["libopus"] {os-family = "bsd"}["libopus"] {os = "macos" & os-distribution = "homebrew"}]synopsis: "Virtual package relying on libopus"description:"This package can only install if the opus library is installed on the system."flags: conf
{"name": "esy-libopus","version": "1.3.1","description": "Mirror of libopus","license": "BSD","source": "https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#ed226536537861c9f0f1ef7ca79dffc225bc181b","override": {"build": [["./configure","--prefix=$cur__install"],["make","-j4"]],"install": [["make","install"]],"buildsInSource": true,"exportedEnv": {"LD_LIBRARY_PATH": {"val": "#{self.lib : $LD_LIBRARY_PATH}","scope": "global"},"OPUS_LIB_PATH": {"val": "#{self.lib}","scope": "global"},"OPUS_INCLUDE_PATH": {"val": "#{self.install / 'include'}","scope": "global"},"PKG_CONFIG_PATH": {"val": "#{self.lib / 'pkgconfig' }:$PKG_CONFIG_PATH","scope": "global"}},"dependencies": {"@opam/conf-autoconf": "esy-packages/esy-autoconf:package.json#fb93edf","@opam/conf-pkg-config": "*"}}}
(env(dev(flags(:standard -warn-error -32))))
(lang dune 2.8)(name opus)
# Set eol to LF so files aren't converted to CRLF-eol on Windows.* text eol=lf linguist-generated
# Reset any possible .gitignore, we want all esy.lock to be un-ignored.!*
{"checksum": "b01887b77e04c37ac3b1e6a8b300ab10","root": "@discopotty/opus@link-dev:./package.json","node": {"yarn-pkg-config@github:esy-ocaml/yarn-pkg-config#db3a0b63883606dd57c54a7158d560d6cba8cd79@d41d8cd9": {"id":"yarn-pkg-config@github:esy-ocaml/yarn-pkg-config#db3a0b63883606dd57c54a7158d560d6cba8cd79@d41d8cd9","name": "yarn-pkg-config","version":"github:esy-ocaml/yarn-pkg-config#db3a0b63883606dd57c54a7158d560d6cba8cd79","source": {"type": "install","source": ["github:esy-ocaml/yarn-pkg-config#db3a0b63883606dd57c54a7158d560d6cba8cd79"]},"overrides": [],"dependencies": [],"devDependencies": []},"ocaml@4.11.2000@d41d8cd9": {"id": "ocaml@4.11.2000@d41d8cd9","name": "ocaml","version": "4.11.2000","source": {"type": "install","source": ["archive:https://registry.npmjs.org/ocaml/-/ocaml-4.11.2000.tgz#sha1:ca152b7819a4dc9c00e2a9f788f8e62ddddef51d"]},"overrides": [],"dependencies": [],"devDependencies": []},"esy-m4@github:esy-packages/esy-m4#c7cf0ac9221be2b1f9d90e83559ca08397a629e7@d41d8cd9": {"id":"esy-m4@github:esy-packages/esy-m4#c7cf0ac9221be2b1f9d90e83559ca08397a629e7@d41d8cd9","name": "esy-m4","version":"github:esy-packages/esy-m4#c7cf0ac9221be2b1f9d90e83559ca08397a629e7","source": {"type": "install","source": ["github:esy-packages/esy-m4#c7cf0ac9221be2b1f9d90e83559ca08397a629e7"]},"overrides": [],"dependencies": [],"devDependencies": []},"esy-libopus@archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b@a8705a59": {"id":"esy-libopus@archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b@a8705a59","name": "esy-libopus","version":"archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b","source": {"type": "install","source": ["archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b"]},"overrides": [ "../esy-libopus" ],"dependencies": ["@opam/conf-pkg-config@opam:1.3@93481236","@opam/conf-autoconf@github:esy-packages/esy-autoconf:package.json#fb93edf@d41d8cd9"],"devDependencies": []},"esy-libffi@github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c@d41d8cd9": {"id":"esy-libffi@github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c@d41d8cd9","name": "esy-libffi","version":"github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c","source": {"type": "install","source": ["github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c"]},"overrides": [],"dependencies": [],"devDependencies": []},"esy-help2man@github:esy-packages/esy-help2man#c8e6931d1dcf58a81bd801145a777fd3b115c443@d41d8cd9": {"id":"esy-help2man@github:esy-packages/esy-help2man#c8e6931d1dcf58a81bd801145a777fd3b115c443@d41d8cd9","name": "esy-help2man","version":"github:esy-packages/esy-help2man#c8e6931d1dcf58a81bd801145a777fd3b115c443","source": {"type": "install","source": ["github:esy-packages/esy-help2man#c8e6931d1dcf58a81bd801145a777fd3b115c443"]},"overrides": [],"dependencies": [],"devDependencies": []},"@opam/yojson@opam:1.7.0@7056d985": {"id": "@opam/yojson@opam:1.7.0@7056d985","name": "@opam/yojson","version": "opam:1.7.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/b8/b89d39ca3f8c532abe5f547ad3b8f84d#md5:b89d39ca3f8c532abe5f547ad3b8f84d","archive:https://github.com/ocaml-community/yojson/releases/download/1.7.0/yojson-1.7.0.tbz#md5:b89d39ca3f8c532abe5f547ad3b8f84d"],"opam": {"name": "yojson","version": "1.7.0","path": "esy.lock/opam/yojson.1.7.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.4@ee414d6c", "@opam/cppo@opam:1.6.7@c28ac3ae","@opam/biniou@opam:1.2.1@d7570399","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.4@ee414d6c", "@opam/biniou@opam:1.2.1@d7570399"]},"@opam/uutf@opam:1.0.2@4440868f": {"id": "@opam/uutf@opam:1.0.2@4440868f","name": "@opam/uutf","version": "opam:1.0.2","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/a7/a7c542405a39630c689a82bd7ef2292c#md5:a7c542405a39630c689a82bd7ef2292c","archive:http://erratique.ch/software/uutf/releases/uutf-1.0.2.tbz#md5:a7c542405a39630c689a82bd7ef2292c"],"opam": {"name": "uutf","version": "1.0.2","path": "esy.lock/opam/uutf.1.0.2"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uchar@opam:0.0.2@c8218eea","@opam/topkg@opam:1.0.3@e4e10f1c","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/ocamlbuild@opam:0.14.0@6ac75d03","@opam/cmdliner@opam:1.0.4@93208aac","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uchar@opam:0.0.2@c8218eea"]},"@opam/uuseg@opam:13.0.0@f60712a7": {"id": "@opam/uuseg@opam:13.0.0@f60712a7","name": "@opam/uuseg","version": "opam:13.0.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/a0/a07a97fff61da604614ea8da0547ef6a#md5:a07a97fff61da604614ea8da0547ef6a","archive:https://erratique.ch/software/uuseg/releases/uuseg-13.0.0.tbz#md5:a07a97fff61da604614ea8da0547ef6a"],"opam": {"name": "uuseg","version": "13.0.0","path": "esy.lock/opam/uuseg.13.0.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uutf@opam:1.0.2@4440868f","@opam/uucp@opam:13.0.0@e9b515e0", "@opam/topkg@opam:1.0.3@e4e10f1c","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/ocamlbuild@opam:0.14.0@6ac75d03","@opam/cmdliner@opam:1.0.4@93208aac","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uucp@opam:13.0.0@e9b515e0"]},"@opam/uucp@opam:13.0.0@e9b515e0": {"id": "@opam/uucp@opam:13.0.0@e9b515e0","name": "@opam/uucp","version": "opam:13.0.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/07/07e706249ddb2d02f0fa298804d3c739#md5:07e706249ddb2d02f0fa298804d3c739","archive:https://erratique.ch/software/uucp/releases/uucp-13.0.0.tbz#md5:07e706249ddb2d02f0fa298804d3c739"],"opam": {"name": "uucp","version": "13.0.0","path": "esy.lock/opam/uucp.13.0.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uutf@opam:1.0.2@4440868f","@opam/topkg@opam:1.0.3@e4e10f1c","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/ocamlbuild@opam:0.14.0@6ac75d03","@opam/cmdliner@opam:1.0.4@93208aac","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/uchar@opam:0.0.2@c8218eea": {"id": "@opam/uchar@opam:0.0.2@c8218eea","name": "@opam/uchar","version": "opam:0.0.2","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/c9/c9ba2c738d264c420c642f7bb1cf4a36#md5:c9ba2c738d264c420c642f7bb1cf4a36","archive:https://github.com/ocaml/uchar/releases/download/v0.0.2/uchar-0.0.2.tbz#md5:c9ba2c738d264c420c642f7bb1cf4a36"],"opam": {"name": "uchar","version": "0.0.2","path": "esy.lock/opam/uchar.0.0.2"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ocamlbuild@opam:0.14.0@6ac75d03","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/tyxml@opam:4.4.0@1dca5713": {"id": "@opam/tyxml@opam:4.4.0@1dca5713","name": "@opam/tyxml","version": "opam:4.4.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/51/516394dd4a5c31726997c51d66aa31cacb91e3c46d4e16c7699130e204042530#sha256:516394dd4a5c31726997c51d66aa31cacb91e3c46d4e16c7699130e204042530","archive:https://github.com/ocsigen/tyxml/releases/download/4.4.0/tyxml-4.4.0.tbz#sha256:516394dd4a5c31726997c51d66aa31cacb91e3c46d4e16c7699130e204042530"],"opam": {"name": "tyxml","version": "4.4.0","path": "esy.lock/opam/tyxml.4.4.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uutf@opam:1.0.2@4440868f","@opam/seq@opam:base@d8d7de1d", "@opam/re@opam:1.9.0@d4d5e13d","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uutf@opam:1.0.2@4440868f","@opam/seq@opam:base@d8d7de1d", "@opam/re@opam:1.9.0@d4d5e13d","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/topkg@opam:1.0.3@e4e10f1c": {"id": "@opam/topkg@opam:1.0.3@e4e10f1c","name": "@opam/topkg","version": "opam:1.0.3","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/e2/e285f7a296d77ee7d831ba9a6bfb396f#md5:e285f7a296d77ee7d831ba9a6bfb396f","archive:http://erratique.ch/software/topkg/releases/topkg-1.0.3.tbz#md5:e285f7a296d77ee7d831ba9a6bfb396f"],"opam": {"name": "topkg","version": "1.0.3","path": "esy.lock/opam/topkg.1.0.3"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/ocamlbuild@opam:0.14.0@6ac75d03","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ocamlbuild@opam:0.14.0@6ac75d03"]},"@opam/stdlib-shims@opam:0.3.0@0d088929": {"id": "@opam/stdlib-shims@opam:0.3.0@0d088929","name": "@opam/stdlib-shims","version": "opam:0.3.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/ba/babf72d3917b86f707885f0c5528e36c63fccb698f4b46cf2bab5c7ccdd6d84a#sha256:babf72d3917b86f707885f0c5528e36c63fccb698f4b46cf2bab5c7ccdd6d84a","archive:https://github.com/ocaml/stdlib-shims/releases/download/0.3.0/stdlib-shims-0.3.0.tbz#sha256:babf72d3917b86f707885f0c5528e36c63fccb698f4b46cf2bab5c7ccdd6d84a"],"opam": {"name": "stdlib-shims","version": "0.3.0","path": "esy.lock/opam/stdlib-shims.0.3.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/stdio@opam:v0.14.0@a624e254": {"id": "@opam/stdio@opam:v0.14.0@a624e254","name": "@opam/stdio","version": "opam:v0.14.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/4c/4cbdf15f0be88c3258aaeff9e04e00e9#md5:4cbdf15f0be88c3258aaeff9e04e00e9","archive:https://ocaml.janestreet.com/ocaml-core/v0.14/files/stdio-v0.14.0.tar.gz#md5:4cbdf15f0be88c3258aaeff9e04e00e9"],"opam": {"name": "stdio","version": "v0.14.0","path": "esy.lock/opam/stdio.v0.14.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@opam/base@opam:v0.14.1@d14008e2","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@opam/base@opam:v0.14.1@d14008e2"]},"@opam/sexplib0@opam:v0.14.0@ddeb6438": {"id": "@opam/sexplib0@opam:v0.14.0@ddeb6438","name": "@opam/sexplib0","version": "opam:v0.14.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/37/37aff0af8f8f6f759249475684aebdc4#md5:37aff0af8f8f6f759249475684aebdc4","archive:https://ocaml.janestreet.com/ocaml-core/v0.14/files/sexplib0-v0.14.0.tar.gz#md5:37aff0af8f8f6f759249475684aebdc4"],"opam": {"name": "sexplib0","version": "v0.14.0","path": "esy.lock/opam/sexplib0.v0.14.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/seq@opam:base@d8d7de1d": {"id": "@opam/seq@opam:base@d8d7de1d","name": "@opam/seq","version": "opam:base","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "seq","version": "base","path": "esy.lock/opam/seq.base"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/result@opam:1.5@6b753c82": {"id": "@opam/result@opam:1.5@6b753c82","name": "@opam/result","version": "opam:1.5","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/1b/1b82dec78849680b49ae9a8a365b831b#md5:1b82dec78849680b49ae9a8a365b831b","archive:https://github.com/janestreet/result/releases/download/1.5/result-1.5.tbz#md5:1b82dec78849680b49ae9a8a365b831b"],"opam": {"name": "result","version": "1.5","path": "esy.lock/opam/result.1.5"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/re@opam:1.9.0@d4d5e13d": {"id": "@opam/re@opam:1.9.0@d4d5e13d","name": "@opam/re","version": "opam:1.9.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/bd/bddaed4f386a22cace7850c9c7dac296#md5:bddaed4f386a22cace7850c9c7dac296","archive:https://github.com/ocaml/ocaml-re/releases/download/1.9.0/re-1.9.0.tbz#md5:bddaed4f386a22cace7850c9c7dac296"],"opam": {"name": "re","version": "1.9.0","path": "esy.lock/opam/re.1.9.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/ppxlib@opam:0.22.0@d2d2223a": {"id": "@opam/ppxlib@opam:0.22.0@d2d2223a","name": "@opam/ppxlib","version": "opam:0.22.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/3e/3eeb91e03966662284a3222e612dee7f4fa2b7637c53d9572d2a74134bb96d7a#sha256:3eeb91e03966662284a3222e612dee7f4fa2b7637c53d9572d2a74134bb96d7a","archive:https://github.com/ocaml-ppx/ppxlib/releases/download/0.22.0/ppxlib-0.22.0.tbz#sha256:3eeb91e03966662284a3222e612dee7f4fa2b7637c53d9572d2a74134bb96d7a"],"opam": {"name": "ppxlib","version": "0.22.0","path": "esy.lock/opam/ppxlib.0.22.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/sexplib0@opam:v0.14.0@ddeb6438","@opam/ppx_derivers@opam:1.2.1@ecf0aa45","@opam/ocaml-migrate-parsetree@opam:2.1.0@a3b6747d","@opam/ocaml-compiler-libs@opam:v0.12.3@f0f069bd","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/sexplib0@opam:v0.14.0@ddeb6438","@opam/ppx_derivers@opam:1.2.1@ecf0aa45","@opam/ocaml-migrate-parsetree@opam:2.1.0@a3b6747d","@opam/ocaml-compiler-libs@opam:v0.12.3@f0f069bd","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/ppx_yojson_conv_lib@opam:v0.14.0@116b53d6": {"id": "@opam/ppx_yojson_conv_lib@opam:v0.14.0@116b53d6","name": "@opam/ppx_yojson_conv_lib","version": "opam:v0.14.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/e2/e23c5593a7211ad4fb09e26e9a74698a#md5:e23c5593a7211ad4fb09e26e9a74698a","archive:https://ocaml.janestreet.com/ocaml-core/v0.14/files/ppx_yojson_conv_lib-v0.14.0.tar.gz#md5:e23c5593a7211ad4fb09e26e9a74698a"],"opam": {"name": "ppx_yojson_conv_lib","version": "v0.14.0","path": "esy.lock/opam/ppx_yojson_conv_lib.v0.14.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/ppx_derivers@opam:1.2.1@ecf0aa45": {"id": "@opam/ppx_derivers@opam:1.2.1@ecf0aa45","name": "@opam/ppx_derivers","version": "opam:1.2.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/5d/5dc2bf130c1db3c731fe0fffc5648b41#md5:5dc2bf130c1db3c731fe0fffc5648b41","archive:https://github.com/ocaml-ppx/ppx_derivers/archive/1.2.1.tar.gz#md5:5dc2bf130c1db3c731fe0fffc5648b41"],"opam": {"name": "ppx_derivers","version": "1.2.1","path": "esy.lock/opam/ppx_derivers.1.2.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/ppx_cstubs@opam:0.6.1.1@706c3a9f": {"id": "@opam/ppx_cstubs@opam:0.6.1.1@706c3a9f","name": "@opam/ppx_cstubs","version": "opam:0.6.1.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/33/33e520e369da5630c697318f6f4ed26d#md5:33e520e369da5630c697318f6f4ed26d","archive:https://github.com/fdopen/ppx_cstubs/archive/0.6.1.1.tar.gz#md5:33e520e369da5630c697318f6f4ed26d"],"opam": {"name": "ppx_cstubs","version": "0.6.1.1","path": "esy.lock/opam/ppx_cstubs.0.6.1.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/re@opam:1.9.0@d4d5e13d", "@opam/ppxlib@opam:0.22.0@d2d2223a","@opam/ocamlfind@opam:1.8.1@b7dc3072", "@opam/num@opam:1.4@a5195c8d","@opam/integers@opam:0.4.0@f7acfaeb","@opam/dune@opam:2.8.4@ee414d6c","@opam/ctypes@opam:0.18.0@1be5c5e5","@opam/cppo@opam:1.6.7@c28ac3ae","@opam/containers@opam:3.2@c4e3f662","@opam/bigarray-compat@opam:1.0.0@3a87ad65","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/re@opam:1.9.0@d4d5e13d", "@opam/ppxlib@opam:0.22.0@d2d2223a","@opam/ocamlfind@opam:1.8.1@b7dc3072", "@opam/num@opam:1.4@a5195c8d","@opam/integers@opam:0.4.0@f7acfaeb","@opam/dune@opam:2.8.4@ee414d6c","@opam/ctypes@opam:0.18.0@1be5c5e5","@opam/containers@opam:3.2@c4e3f662","@opam/bigarray-compat@opam:1.0.0@3a87ad65"]},"@opam/odoc@opam:1.5.2@94f47c8b": {"id": "@opam/odoc@opam:1.5.2@94f47c8b","name": "@opam/odoc","version": "opam:1.5.2","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/d2/d24463f2660bc28c72cda001478360158e953721c9e23fb361ec4783113c4871#sha256:d24463f2660bc28c72cda001478360158e953721c9e23fb361ec4783113c4871","archive:https://github.com/ocaml/odoc/releases/download/1.5.2/odoc-1.5.2.tbz#sha256:d24463f2660bc28c72cda001478360158e953721c9e23fb361ec4783113c4871"],"opam": {"name": "odoc","version": "1.5.2","path": "esy.lock/opam/odoc.1.5.2"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/tyxml@opam:4.4.0@1dca5713","@opam/result@opam:1.5@6b753c82", "@opam/fpath@opam:0.7.3@674d8125","@opam/dune@opam:2.8.4@ee414d6c", "@opam/cppo@opam:1.6.7@c28ac3ae","@opam/cmdliner@opam:1.0.4@93208aac","@opam/astring@opam:0.8.5@1300cee8","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/tyxml@opam:4.4.0@1dca5713","@opam/result@opam:1.5@6b753c82", "@opam/fpath@opam:0.7.3@674d8125","@opam/dune@opam:2.8.4@ee414d6c","@opam/cmdliner@opam:1.0.4@93208aac","@opam/astring@opam:0.8.5@1300cee8"]},"@opam/ocamlformat@opam:0.17.0@643c4315": {"id": "@opam/ocamlformat@opam:0.17.0@643c4315","name": "@opam/ocamlformat","version": "opam:0.17.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/68/68848b12e82dc1077a29f63d2777680e692b1a565276fcd00f06fb93cced3438#sha256:68848b12e82dc1077a29f63d2777680e692b1a565276fcd00f06fb93cced3438","archive:https://github.com/ocaml-ppx/ocamlformat/releases/download/0.17.0/ocamlformat-0.17.0.tbz#sha256:68848b12e82dc1077a29f63d2777680e692b1a565276fcd00f06fb93cced3438"],"opam": {"name": "ocamlformat","version": "0.17.0","path": "esy.lock/opam/ocamlformat.0.17.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uutf@opam:1.0.2@4440868f","@opam/uuseg@opam:13.0.0@f60712a7","@opam/stdio@opam:v0.14.0@a624e254", "@opam/re@opam:1.9.0@d4d5e13d","@opam/ppxlib@opam:0.22.0@d2d2223a","@opam/odoc@opam:1.5.2@94f47c8b","@opam/ocaml-version@opam:3.1.0@a34970ed","@opam/ocaml-migrate-parsetree@opam:2.1.0@a3b6747d","@opam/menhirSdk@opam:20210310@5abaafca","@opam/menhirLib@opam:20210310@f9315713","@opam/menhir@opam:20210310@50de9216","@opam/fpath@opam:0.7.3@674d8125","@opam/fix@opam:20201120@5c318621","@opam/dune-build-info@opam:2.8.4@c3b98e33","@opam/dune@opam:2.8.4@ee414d6c","@opam/cmdliner@opam:1.0.4@93208aac","@opam/base-unix@opam:base@87d0b2eb","@opam/base@opam:v0.14.1@d14008e2","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/uutf@opam:1.0.2@4440868f","@opam/uuseg@opam:13.0.0@f60712a7","@opam/stdio@opam:v0.14.0@a624e254", "@opam/re@opam:1.9.0@d4d5e13d","@opam/ppxlib@opam:0.22.0@d2d2223a","@opam/odoc@opam:1.5.2@94f47c8b","@opam/ocaml-version@opam:3.1.0@a34970ed","@opam/ocaml-migrate-parsetree@opam:2.1.0@a3b6747d","@opam/menhirSdk@opam:20210310@5abaafca","@opam/menhirLib@opam:20210310@f9315713","@opam/menhir@opam:20210310@50de9216","@opam/fpath@opam:0.7.3@674d8125","@opam/fix@opam:20201120@5c318621","@opam/dune-build-info@opam:2.8.4@c3b98e33","@opam/dune@opam:2.8.4@ee414d6c","@opam/cmdliner@opam:1.0.4@93208aac","@opam/base-unix@opam:base@87d0b2eb","@opam/base@opam:v0.14.1@d14008e2"]},"@opam/ocamlfind@opam:1.8.1@b7dc3072": {"id": "@opam/ocamlfind@opam:1.8.1@b7dc3072","name": "@opam/ocamlfind","version": "opam:1.8.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/18/18ca650982c15536616dea0e422cbd8c#md5:18ca650982c15536616dea0e422cbd8c","archive:http://download2.camlcity.org/download/findlib-1.8.1.tar.gz#md5:18ca650982c15536616dea0e422cbd8c","archive:http://download.camlcity.org/download/findlib-1.8.1.tar.gz#md5:18ca650982c15536616dea0e422cbd8c"],"opam": {"name": "ocamlfind","version": "1.8.1","path": "esy.lock/opam/ocamlfind.1.8.1"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__ocamlfind_opam__c__1.8.1_opam_override"}],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/conf-m4@opam:1@196bf219","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/ocamlbuild@opam:0.14.0@6ac75d03": {"id": "@opam/ocamlbuild@opam:0.14.0@6ac75d03","name": "@opam/ocamlbuild","version": "opam:0.14.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/87/87b29ce96958096c0a1a8eeafeb6268077b2d11e1bf2b3de0f5ebc9cf8d42e78#sha256:87b29ce96958096c0a1a8eeafeb6268077b2d11e1bf2b3de0f5ebc9cf8d42e78","archive:https://github.com/ocaml/ocamlbuild/archive/0.14.0.tar.gz#sha256:87b29ce96958096c0a1a8eeafeb6268077b2d11e1bf2b3de0f5ebc9cf8d42e78"],"opam": {"name": "ocamlbuild","version": "0.14.0","path": "esy.lock/opam/ocamlbuild.0.14.0"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__ocamlbuild_opam__c__0.14.0_opam_override"}],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/ocaml-version@opam:3.1.0@a34970ed": {"id": "@opam/ocaml-version@opam:3.1.0@a34970ed","name": "@opam/ocaml-version","version": "opam:3.1.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/ac/ac7ba16a09d8f72212742f3936980fbfaebb698c7bbf625182af7d6b2c3cde5f#sha256:ac7ba16a09d8f72212742f3936980fbfaebb698c7bbf625182af7d6b2c3cde5f","archive:https://github.com/ocurrent/ocaml-version/releases/download/v3.1.0/ocaml-version-v3.1.0.tbz#sha256:ac7ba16a09d8f72212742f3936980fbfaebb698c7bbf625182af7d6b2c3cde5f"],"opam": {"name": "ocaml-version","version": "3.1.0","path": "esy.lock/opam/ocaml-version.3.1.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/ocaml-migrate-parsetree@opam:2.1.0@a3b6747d": {"id": "@opam/ocaml-migrate-parsetree@opam:2.1.0@a3b6747d","name": "@opam/ocaml-migrate-parsetree","version": "opam:2.1.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/38/387b788ee4c0537f1fe02c25e05f0335af424828fc6fe940acc0db5948a5a71f#sha256:387b788ee4c0537f1fe02c25e05f0335af424828fc6fe940acc0db5948a5a71f","archive:https://github.com/ocaml-ppx/ocaml-migrate-parsetree/releases/download/v2.1.0/ocaml-migrate-parsetree-v2.1.0.tbz#sha256:387b788ee4c0537f1fe02c25e05f0335af424828fc6fe940acc0db5948a5a71f"],"opam": {"name": "ocaml-migrate-parsetree","version": "2.1.0","path": "esy.lock/opam/ocaml-migrate-parsetree.2.1.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/ocaml-lsp-server@opam:1.4.1@cd85c376": {"id": "@opam/ocaml-lsp-server@opam:1.4.1@cd85c376","name": "@opam/ocaml-lsp-server","version": "opam:1.4.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/ce/cee8371e7048e24c90e916c373ef6f3aba6f474d8a5fcf507ab6650fd8575eeb#sha256:cee8371e7048e24c90e916c373ef6f3aba6f474d8a5fcf507ab6650fd8575eeb","archive:https://github.com/ocaml/ocaml-lsp/releases/download/1.4.1/jsonrpc-1.4.1.tbz#sha256:cee8371e7048e24c90e916c373ef6f3aba6f474d8a5fcf507ab6650fd8575eeb"],"opam": {"name": "ocaml-lsp-server","version": "1.4.1","path": "esy.lock/opam/ocaml-lsp-server.1.4.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/result@opam:1.5@6b753c82","@opam/ppx_yojson_conv_lib@opam:v0.14.0@116b53d6","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/dune-build-info@opam:2.8.4@c3b98e33","@opam/dune@opam:2.8.4@ee414d6c","@opam/dot-merlin-reader@opam:4.1@120afa42","@opam/csexp@opam:1.4.0@bd1cb034", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/stdlib-shims@opam:0.3.0@0d088929","@opam/result@opam:1.5@6b753c82","@opam/ppx_yojson_conv_lib@opam:v0.14.0@116b53d6","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/dune-build-info@opam:2.8.4@c3b98e33","@opam/dune@opam:2.8.4@ee414d6c","@opam/dot-merlin-reader@opam:4.1@120afa42","@opam/csexp@opam:1.4.0@bd1cb034"]},"@opam/ocaml-compiler-libs@opam:v0.12.3@f0f069bd": {"id": "@opam/ocaml-compiler-libs@opam:v0.12.3@f0f069bd","name": "@opam/ocaml-compiler-libs","version": "opam:v0.12.3","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/a8/a8403531439c14bbda2d504ef93610fd29a8e9520fc700f21889d893a513e3c9#sha256:a8403531439c14bbda2d504ef93610fd29a8e9520fc700f21889d893a513e3c9","archive:https://github.com/janestreet/ocaml-compiler-libs/releases/download/v0.12.3/ocaml-compiler-libs-v0.12.3.tbz#sha256:a8403531439c14bbda2d504ef93610fd29a8e9520fc700f21889d893a513e3c9"],"opam": {"name": "ocaml-compiler-libs","version": "v0.12.3","path": "esy.lock/opam/ocaml-compiler-libs.v0.12.3"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/num@opam:1.4@a5195c8d": {"id": "@opam/num@opam:1.4@a5195c8d","name": "@opam/num","version": "opam:1.4","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/cd/cda2b727e116a0b6a9c03902cc4b2415#md5:cda2b727e116a0b6a9c03902cc4b2415","archive:https://github.com/ocaml/num/archive/v1.4.tar.gz#md5:cda2b727e116a0b6a9c03902cc4b2415"],"opam": {"name": "num","version": "1.4","path": "esy.lock/opam/num.1.4"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__num_opam__c__1.4_opam_override"}],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ocamlfind@opam:1.8.1@b7dc3072","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/merlin@opam:4.1-411@2ac33a62": {"id": "@opam/merlin@opam:4.1-411@2ac33a62","name": "@opam/merlin","version": "opam:4.1-411","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/9e/9e2e6fc799c93ce1f2c7181645eafa37f64e43ace062b69218e1c29ac459937d#sha256:9e2e6fc799c93ce1f2c7181645eafa37f64e43ace062b69218e1c29ac459937d","archive:https://github.com/ocaml/merlin/releases/download/v4.1-411/merlin-v4.1-411.tbz#sha256:9e2e6fc799c93ce1f2c7181645eafa37f64e43ace062b69218e1c29ac459937d"],"opam": {"name": "merlin","version": "4.1-411","path": "esy.lock/opam/merlin.4.1-411"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/result@opam:1.5@6b753c82", "@opam/dune@opam:2.8.4@ee414d6c","@opam/dot-merlin-reader@opam:4.1@120afa42","@opam/csexp@opam:1.4.0@bd1cb034", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/result@opam:1.5@6b753c82", "@opam/dune@opam:2.8.4@ee414d6c","@opam/dot-merlin-reader@opam:4.1@120afa42","@opam/csexp@opam:1.4.0@bd1cb034"]},"@opam/menhirSdk@opam:20210310@5abaafca": {"id": "@opam/menhirSdk@opam:20210310@5abaafca","name": "@opam/menhirSdk","version": "opam:20210310","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/1c/1cbc71c0bc1f3ddc3e71d5c1f919fd1a#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a"],"opam": {"name": "menhirSdk","version": "20210310","path": "esy.lock/opam/menhirSdk.20210310"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/menhirLib@opam:20210310@f9315713": {"id": "@opam/menhirLib@opam:20210310@f9315713","name": "@opam/menhirLib","version": "opam:20210310","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/1c/1cbc71c0bc1f3ddc3e71d5c1f919fd1a#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a"],"opam": {"name": "menhirLib","version": "20210310","path": "esy.lock/opam/menhirLib.20210310"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/menhir@opam:20210310@50de9216": {"id": "@opam/menhir@opam:20210310@50de9216","name": "@opam/menhir","version": "opam:20210310","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/1c/1cbc71c0bc1f3ddc3e71d5c1f919fd1a#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a","archive:https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz#md5:1cbc71c0bc1f3ddc3e71d5c1f919fd1a"],"opam": {"name": "menhir","version": "20210310","path": "esy.lock/opam/menhir.20210310"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/menhirSdk@opam:20210310@5abaafca","@opam/menhirLib@opam:20210310@f9315713","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/menhirSdk@opam:20210310@5abaafca","@opam/menhirLib@opam:20210310@f9315713","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/integers@opam:0.4.0@f7acfaeb": {"id": "@opam/integers@opam:0.4.0@f7acfaeb","name": "@opam/integers","version": "opam:0.4.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/c1/c1492352e6525048790508c57aad93c3#md5:c1492352e6525048790508c57aad93c3","archive:https://github.com/ocamllabs/ocaml-integers/archive/0.4.0.tar.gz#md5:c1492352e6525048790508c57aad93c3"],"opam": {"name": "integers","version": "0.4.0","path": "esy.lock/opam/integers.0.4.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/fpath@opam:0.7.3@674d8125": {"id": "@opam/fpath@opam:0.7.3@674d8125","name": "@opam/fpath","version": "opam:0.7.3","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/07/0740b530e8fed5b0adc5eee8463cfc2f#md5:0740b530e8fed5b0adc5eee8463cfc2f","archive:https://erratique.ch/software/fpath/releases/fpath-0.7.3.tbz#md5:0740b530e8fed5b0adc5eee8463cfc2f"],"opam": {"name": "fpath","version": "0.7.3","path": "esy.lock/opam/fpath.0.7.3"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/topkg@opam:1.0.3@e4e10f1c","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/ocamlbuild@opam:0.14.0@6ac75d03","@opam/astring@opam:0.8.5@1300cee8","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/astring@opam:0.8.5@1300cee8"]},"@opam/fix@opam:20201120@5c318621": {"id": "@opam/fix@opam:20201120@5c318621","name": "@opam/fix","version": "opam:20201120","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/7e/7eb570b759635fe66f3556d2b1cc88e3#md5:7eb570b759635fe66f3556d2b1cc88e3","archive:https://gitlab.inria.fr/fpottier/fix/repository/20201120/archive.tar.gz#md5:7eb570b759635fe66f3556d2b1cc88e3"],"opam": {"name": "fix","version": "20201120","path": "esy.lock/opam/fix.20201120"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/easy-format@opam:1.3.2@0484b3c4": {"id": "@opam/easy-format@opam:1.3.2@0484b3c4","name": "@opam/easy-format","version": "opam:1.3.2","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/34/3440c2b882d537ae5e9011eb06abb53f5667e651ea4bb3b460ea8230fa8c1926#sha256:3440c2b882d537ae5e9011eb06abb53f5667e651ea4bb3b460ea8230fa8c1926","archive:https://github.com/mjambon/easy-format/releases/download/1.3.2/easy-format-1.3.2.tbz#sha256:3440c2b882d537ae5e9011eb06abb53f5667e651ea4bb3b460ea8230fa8c1926"],"opam": {"name": "easy-format","version": "1.3.2","path": "esy.lock/opam/easy-format.1.3.2"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/dune-configurator@opam:2.8.4@5eab5258": {"id": "@opam/dune-configurator@opam:2.8.4@5eab5258","name": "@opam/dune-configurator","version": "opam:2.8.4","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/4e/4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac","archive:https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac"],"opam": {"name": "dune-configurator","version": "2.8.4","path": "esy.lock/opam/dune-configurator.2.8.4"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c", "@opam/csexp@opam:1.4.0@bd1cb034","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c", "@opam/csexp@opam:1.4.0@bd1cb034"]},"@opam/dune-build-info@opam:2.8.4@c3b98e33": {"id": "@opam/dune-build-info@opam:2.8.4@c3b98e33","name": "@opam/dune-build-info","version": "opam:2.8.4","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/4e/4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac","archive:https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac"],"opam": {"name": "dune-build-info","version": "2.8.4","path": "esy.lock/opam/dune-build-info.2.8.4"}},"overrides": [],"dependencies": ["@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "@opam/dune@opam:2.8.4@ee414d6c" ]},"@opam/dune@opam:2.8.4@ee414d6c": {"id": "@opam/dune@opam:2.8.4@ee414d6c","name": "@opam/dune","version": "opam:2.8.4","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/4e/4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac","archive:https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz#sha256:4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac"],"opam": {"name": "dune","version": "2.8.4","path": "esy.lock/opam/dune.2.8.4"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/base-unix@opam:base@87d0b2eb","@opam/base-threads@opam:base@36803084","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/base-unix@opam:base@87d0b2eb","@opam/base-threads@opam:base@36803084"]},"@opam/dot-merlin-reader@opam:4.1@120afa42": {"id": "@opam/dot-merlin-reader@opam:4.1@120afa42","name": "@opam/dot-merlin-reader","version": "opam:4.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/14/14a36d6fb8646a5df4530420a7861722f1a4ee04753717947305e3676031e7cd#sha256:14a36d6fb8646a5df4530420a7861722f1a4ee04753717947305e3676031e7cd","archive:https://github.com/ocaml/merlin/releases/download/v4.1/dot-merlin-reader-v4.1.tbz#sha256:14a36d6fb8646a5df4530420a7861722f1a4ee04753717947305e3676031e7cd"],"opam": {"name": "dot-merlin-reader","version": "4.1","path": "esy.lock/opam/dot-merlin-reader.4.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/result@opam:1.5@6b753c82","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/dune@opam:2.8.4@ee414d6c", "@opam/csexp@opam:1.4.0@bd1cb034","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/yojson@opam:1.7.0@7056d985","@opam/result@opam:1.5@6b753c82","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/dune@opam:2.8.4@ee414d6c", "@opam/csexp@opam:1.4.0@bd1cb034"]},"@opam/ctypes-foreign@opam:0.4.0@6d218780": {"id": "@opam/ctypes-foreign@opam:0.4.0@6d218780","name": "@opam/ctypes-foreign","version": "opam:0.4.0","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "ctypes-foreign","version": "0.4.0","path": "esy.lock/opam/ctypes-foreign.0.4.0"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__ctypes_foreign_opam__c__0.4.0_opam_override"}],"dependencies": ["@opam/conf-libffi@opam:2.0.0@7c8981c5","@esy-ocaml/substs@0.0.1@d41d8cd9","@esy-ocaml/libffi@3.2.10@d41d8cd9"],"devDependencies": [ "@opam/conf-libffi@opam:2.0.0@7c8981c5" ]},"@opam/ctypes@opam:0.18.0@1be5c5e5": {"id": "@opam/ctypes@opam:0.18.0@1be5c5e5","name": "@opam/ctypes","version": "opam:0.18.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/5d/5d9ef3790fda7cd97a8cec08be4b5b61#md5:5d9ef3790fda7cd97a8cec08be4b5b61","archive:https://github.com/ocamllabs/ocaml-ctypes/archive/0.18.0.tar.gz#md5:5d9ef3790fda7cd97a8cec08be4b5b61"],"opam": {"name": "ctypes","version": "0.18.0","path": "esy.lock/opam/ctypes.0.18.0"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__ctypes_opam__c__0.18.0_opam_override"}],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/integers@opam:0.4.0@f7acfaeb","@opam/ctypes-foreign@opam:0.4.0@6d218780","@opam/bigarray-compat@opam:1.0.0@3a87ad65","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/integers@opam:0.4.0@f7acfaeb","@opam/bigarray-compat@opam:1.0.0@3a87ad65"]},"@opam/csexp@opam:1.4.0@bd1cb034": {"id": "@opam/csexp@opam:1.4.0@bd1cb034","name": "@opam/csexp","version": "opam:1.4.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/8e/8e3d6fca87f102a126dee8b72a2a0d146f10439c47218dfc149d51bf3edf364e#sha256:8e3d6fca87f102a126dee8b72a2a0d146f10439c47218dfc149d51bf3edf364e","archive:https://github.com/ocaml-dune/csexp/releases/download/1.4.0/csexp-1.4.0.tbz#sha256:8e3d6fca87f102a126dee8b72a2a0d146f10439c47218dfc149d51bf3edf364e"],"opam": {"name": "csexp","version": "1.4.0","path": "esy.lock/opam/csexp.1.4.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/result@opam:1.5@6b753c82","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/cppo@opam:1.6.7@c28ac3ae": {"id": "@opam/cppo@opam:1.6.7@c28ac3ae","name": "@opam/cppo","version": "opam:1.6.7","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/db/db553e3e6c206df09b1858c3aef5e21e56564d593642a3c78bcedb6af36f529d#sha256:db553e3e6c206df09b1858c3aef5e21e56564d593642a3c78bcedb6af36f529d","archive:https://github.com/ocaml-community/cppo/releases/download/v1.6.7/cppo-v1.6.7.tbz#sha256:db553e3e6c206df09b1858c3aef5e21e56564d593642a3c78bcedb6af36f529d"],"opam": {"name": "cppo","version": "1.6.7","path": "esy.lock/opam/cppo.1.6.7"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@opam/base-unix@opam:base@87d0b2eb","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@opam/base-unix@opam:base@87d0b2eb"]},"@opam/containers@opam:3.2@c4e3f662": {"id": "@opam/containers@opam:3.2@c4e3f662","name": "@opam/containers","version": "opam:3.2","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/14/14787fb6878a94dd728a0ef7e368ab89#md5:14787fb6878a94dd728a0ef7e368ab89","archive:https://github.com/c-cube/ocaml-containers/archive/v3.2.tar.gz#md5:14787fb6878a94dd728a0ef7e368ab89"],"opam": {"name": "containers","version": "3.2","path": "esy.lock/opam/containers.3.2"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c","@opam/base-unix@opam:base@87d0b2eb","@opam/base-threads@opam:base@36803084","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/seq@opam:base@d8d7de1d","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/conf-pkg-config@opam:1.3@93481236": {"id": "@opam/conf-pkg-config@opam:1.3@93481236","name": "@opam/conf-pkg-config","version": "opam:1.3","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "conf-pkg-config","version": "1.3","path": "esy.lock/opam/conf-pkg-config.1.3"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__conf_pkg_config_opam__c__1.3_opam_override"}],"dependencies": ["yarn-pkg-config@github:esy-ocaml/yarn-pkg-config#db3a0b63883606dd57c54a7158d560d6cba8cd79@d41d8cd9","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": []},"@opam/conf-m4@opam:1@196bf219": {"id": "@opam/conf-m4@opam:1@196bf219","name": "@opam/conf-m4","version": "opam:1","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "conf-m4","version": "1","path": "esy.lock/opam/conf-m4.1"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__conf_m4_opam__c__1_opam_override"}],"dependencies": ["esy-m4@github:esy-packages/esy-m4#c7cf0ac9221be2b1f9d90e83559ca08397a629e7@d41d8cd9","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": []},"@opam/conf-libopus@link:../esy-libopus/conf-libopus.opam": {"id": "@opam/conf-libopus@link:../esy-libopus/conf-libopus.opam","name": "@opam/conf-libopus","version": "link:../esy-libopus/conf-libopus.opam","source": {"type": "link","path": "../esy-libopus","manifest": "conf-libopus.opam"},"overrides": [{ "dependencies": { "esy-libopus": "../esy-libopus" } }],"dependencies": ["esy-libopus@archive:https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz#sha1:ed226536537861c9f0f1ef7ca79dffc225bc181b@a8705a59","@opam/conf-pkg-config@opam:1.3@93481236","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": []},"@opam/conf-libffi@opam:2.0.0@7c8981c5": {"id": "@opam/conf-libffi@opam:2.0.0@7c8981c5","name": "@opam/conf-libffi","version": "opam:2.0.0","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "conf-libffi","version": "2.0.0","path": "esy.lock/opam/conf-libffi.2.0.0"}},"overrides": [{"opamoverride":"esy.lock/overrides/opam__s__conf_libffi_opam__c__2.0.0_opam_override"}],"dependencies": ["esy-libffi@github:esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c@d41d8cd9","@opam/conf-pkg-config@opam:1.3@93481236","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": []},"@opam/conf-autoconf@github:esy-packages/esy-autoconf:package.json#fb93edf@d41d8cd9": {"id":"@opam/conf-autoconf@github:esy-packages/esy-autoconf:package.json#fb93edf@d41d8cd9","name": "@opam/conf-autoconf","version": "github:esy-packages/esy-autoconf:package.json#fb93edf","source": {"type": "install","source": [ "github:esy-packages/esy-autoconf:package.json#fb93edf" ]},"overrides": [],"dependencies": ["esy-help2man@github:esy-packages/esy-help2man#c8e6931d1dcf58a81bd801145a777fd3b115c443@d41d8cd9"],"devDependencies": []},"@opam/cmdliner@opam:1.0.4@93208aac": {"id": "@opam/cmdliner@opam:1.0.4@93208aac","name": "@opam/cmdliner","version": "opam:1.0.4","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/fe/fe2213d0bc63b1e10a2d0aa66d2fc8d9#md5:fe2213d0bc63b1e10a2d0aa66d2fc8d9","archive:http://erratique.ch/software/cmdliner/releases/cmdliner-1.0.4.tbz#md5:fe2213d0bc63b1e10a2d0aa66d2fc8d9"],"opam": {"name": "cmdliner","version": "1.0.4","path": "esy.lock/opam/cmdliner.1.0.4"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@opam/biniou@opam:1.2.1@d7570399": {"id": "@opam/biniou@opam:1.2.1@d7570399","name": "@opam/biniou","version": "opam:1.2.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/sha256/35/35546c68b1929a8e6d27a3b39ecd17b38303a0d47e65eb9d1480c2061ea84335#sha256:35546c68b1929a8e6d27a3b39ecd17b38303a0d47e65eb9d1480c2061ea84335","archive:https://github.com/mjambon/biniou/releases/download/1.2.1/biniou-1.2.1.tbz#sha256:35546c68b1929a8e6d27a3b39ecd17b38303a0d47e65eb9d1480c2061ea84335"],"opam": {"name": "biniou","version": "1.2.1","path": "esy.lock/opam/biniou.1.2.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/easy-format@opam:1.3.2@0484b3c4","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/bigarray-compat@opam:1.0.0@3a87ad65": {"id": "@opam/bigarray-compat@opam:1.0.0@3a87ad65","name": "@opam/bigarray-compat","version": "opam:1.0.0","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/1c/1cc7c25382a8900bada34aadfd66632e#md5:1cc7c25382a8900bada34aadfd66632e","archive:https://github.com/mirage/bigarray-compat/archive/v1.0.0.tar.gz#md5:1cc7c25382a8900bada34aadfd66632e"],"opam": {"name": "bigarray-compat","version": "1.0.0","path": "esy.lock/opam/bigarray-compat.1.0.0"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/base-unix@opam:base@87d0b2eb": {"id": "@opam/base-unix@opam:base@87d0b2eb","name": "@opam/base-unix","version": "opam:base","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "base-unix","version": "base","path": "esy.lock/opam/base-unix.base"}},"overrides": [],"dependencies": [ "@esy-ocaml/substs@0.0.1@d41d8cd9" ],"devDependencies": []},"@opam/base-threads@opam:base@36803084": {"id": "@opam/base-threads@opam:base@36803084","name": "@opam/base-threads","version": "opam:base","source": {"type": "install","source": [ "no-source:" ],"opam": {"name": "base-threads","version": "base","path": "esy.lock/opam/base-threads.base"}},"overrides": [],"dependencies": [ "@esy-ocaml/substs@0.0.1@d41d8cd9" ],"devDependencies": []},"@opam/base@opam:v0.14.1@d14008e2": {"id": "@opam/base@opam:v0.14.1@d14008e2","name": "@opam/base","version": "opam:v0.14.1","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/e4/e4419eae60f57e553b154856f0cacf42#md5:e4419eae60f57e553b154856f0cacf42","archive:https://github.com/janestreet/base/archive/v0.14.1.tar.gz#md5:e4419eae60f57e553b154856f0cacf42"],"opam": {"name": "base","version": "v0.14.1","path": "esy.lock/opam/base.v0.14.1"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/sexplib0@opam:v0.14.0@ddeb6438","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c", "@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/sexplib0@opam:v0.14.0@ddeb6438","@opam/dune-configurator@opam:2.8.4@5eab5258","@opam/dune@opam:2.8.4@ee414d6c"]},"@opam/astring@opam:0.8.5@1300cee8": {"id": "@opam/astring@opam:0.8.5@1300cee8","name": "@opam/astring","version": "opam:0.8.5","source": {"type": "install","source": ["archive:https://opam.ocaml.org/cache/md5/e1/e148907c24157d1df43bec89b58b3ec8#md5:e148907c24157d1df43bec89b58b3ec8","archive:https://erratique.ch/software/astring/releases/astring-0.8.5.tbz#md5:e148907c24157d1df43bec89b58b3ec8"],"opam": {"name": "astring","version": "0.8.5","path": "esy.lock/opam/astring.0.8.5"}},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/topkg@opam:1.0.3@e4e10f1c","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/ocamlbuild@opam:0.14.0@6ac75d03","@esy-ocaml/substs@0.0.1@d41d8cd9"],"devDependencies": [ "ocaml@4.11.2000@d41d8cd9" ]},"@esy-ocaml/substs@0.0.1@d41d8cd9": {"id": "@esy-ocaml/substs@0.0.1@d41d8cd9","name": "@esy-ocaml/substs","version": "0.0.1","source": {"type": "install","source": ["archive:https://registry.npmjs.org/@esy-ocaml/substs/-/substs-0.0.1.tgz#sha1:59ebdbbaedcda123fc7ed8fb2b302b7d819e9a46"]},"overrides": [],"dependencies": [],"devDependencies": []},"@esy-ocaml/libffi@3.2.10@d41d8cd9": {"id": "@esy-ocaml/libffi@3.2.10@d41d8cd9","name": "@esy-ocaml/libffi","version": "3.2.10","source": {"type": "install","source": ["archive:https://registry.npmjs.org/@esy-ocaml/libffi/-/libffi-3.2.10.tgz#sha1:72697f135ee228b94294ec32f0d5b0fa313de403"]},"overrides": [],"dependencies": [],"devDependencies": []},"@discopotty/opus@link-dev:./package.json": {"id": "@discopotty/opus@link-dev:./package.json","name": "@discopotty/opus","version": "link-dev:./package.json","source": {"type": "link-dev","path": ".","manifest": "package.json"},"overrides": [],"dependencies": ["ocaml@4.11.2000@d41d8cd9", "@opam/ppx_cstubs@opam:0.6.1.1@706c3a9f","@opam/ocamlfind@opam:1.8.1@b7dc3072","@opam/dune@opam:2.8.4@ee414d6c","@opam/ctypes-foreign@opam:0.4.0@6d218780","@opam/ctypes@opam:0.18.0@1be5c5e5","@opam/conf-libopus@link:../esy-libopus/conf-libopus.opam"],"devDependencies": ["@opam/odoc@opam:1.5.2@94f47c8b","@opam/ocamlformat@opam:0.17.0@643c4315","@opam/ocaml-lsp-server@opam:1.4.1@cd85c376","@opam/merlin@opam:4.1-411@2ac33a62"]}}}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"authors: ["The astring programmers"]homepage: "https://erratique.ch/software/astring"doc: "https://erratique.ch/software/astring/doc"dev-repo: "git+http://erratique.ch/repos/astring.git"bug-reports: "https://github.com/dbuenzli/astring/issues"tags: [ "string" "org:erratique" ]license: "ISC"depends: ["ocaml" {>= "4.05.0"}"ocamlfind" {build}"ocamlbuild" {build}"topkg" {build} ]build: [[ "ocaml" "pkg/pkg.ml" "build" "--pinned" "%{pinned}%" ]]synopsis: """Alternative String module for OCaml"""description: """\Astring exposes an alternative `String` module for OCaml. This moduletries to balance minimality and expressiveness for basic, index-free,string processing and provides types and functions for substrings,string sets and string maps.Remaining compatible with the OCaml `String` module is a non-goal. The`String` module exposed by Astring has exception safe functions,removes deprecated and rarely used functions, alters some signaturesand names, adds a few missing functions and fully exploits OCaml'snewfound string immutability.Astring depends only on the OCaml standard library. It is distributedunder the ISC license."""url {archive: "https://erratique.ch/software/astring/releases/astring-0.8.5.tbz"checksum: "e148907c24157d1df43bec89b58b3ec8"}
opam-version: "2.0"maintainer: "https://github.com/ocaml/opam-repository/issues"description: """Threads library distributed with the OCaml compiler"""
opam-version: "2.0"maintainer: "https://github.com/ocaml/opam-repository/issues"description: """Unix library distributed with the OCaml compiler"""
opam-version: "2.0"maintainer: "opensource@janestreet.com"authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]homepage: "https://github.com/janestreet/base"bug-reports: "https://github.com/janestreet/base/issues"dev-repo: "git+https://github.com/janestreet/base.git"doc: "https://ocaml.janestreet.com/ocaml-core/latest/doc/base/index.html"license: "MIT"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.08.0"}"sexplib0" {>= "v0.14" & < "v0.15"}"dune" {>= "2.0.0"}"dune-configurator"]synopsis: "Full standard library replacement for OCaml"description: "Full standard library replacement for OCamlBase is a complete and portable alternative to the OCaml standardlibrary. It provides all standard functionalities one would expectfrom a language standard library. It uses consistent conventionsacross all of its module.Base aims to be usable in any context. As a result system dependentfeatures such as I/O are not offered by Base. They are insteadprovided by companion libraries such as stdio:https://github.com/janestreet/stdio"url {src: "https://github.com/janestreet/base/archive/v0.14.1.tar.gz"checksum: "md5=e4419eae60f57e553b154856f0cacf42"}
opam-version: "2.0"synopsis: "Compatibility library to use Stdlib.Bigarray when possible"maintainer: "Lucas Pluvinage <lucas.pluvinage@gmail.com>"authors: "Lucas Pluvinage <lucas.pluvinage@gmail.com>"license: "ISC"homepage: "https://github.com/mirage/bigarray-compat"bug-reports: "https://github.com/mirage/bigarray-compat/issues"depends: ["ocaml" {>= "4.02.3"}"dune" {>= "1.0"}]build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]]dev-repo: "git+https://github.com/mirage/bigarray-compat.git"url {src: "https://github.com/mirage/bigarray-compat/archive/v1.0.0.tar.gz"checksum: ["md5=1cc7c25382a8900bada34aadfd66632e""sha512=c365fee15582aca35d7b05268cde29e54774ad7df7be56762b4aad78ca1409d4326ad3b34af0f1cc2c7b872837290a9cd9ff43b47987c03bba7bba32fe8a030f"]}
opam-version: "2.0"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}["dune" "build" "-p" name "@doc"] {with-doc}]maintainer: ["martin@mjambon.com"]authors: ["Martin Jambon"]bug-reports: "https://github.com/mjambon/biniou/issues"homepage: "https://github.com/mjambon/biniou"doc: "https://mjambon.github.io/biniou/"license: "BSD-3-Clause"dev-repo: "git+https://github.com/mjambon/biniou.git"synopsis:"Binary data format designed for speed, safety, ease of use and backward compatibility as protocols evolve"description: """Biniou (pronounced "be new") is a binary data format designed for speed, safety,ease of use and backward compatibility as protocols evolve. Biniou is vastlyequivalent to JSON in terms of functionality but allows implementations severaltimes faster (4 times faster than yojson), with 25-35% space savings.Biniou data can be decoded into human-readable form without knowledge of typedefinitions except for field and variant names which are represented by 31-bithashes. A program named bdump is provided for routine visualization of binioudata files.The program atdgen is used to derive OCaml-Biniou serializers and deserializersfrom type definitions.Biniou format specification: mjambon.github.io/atdgen-doc/biniou-format.txt"""depends: ["easy-format""dune" {>= "1.10"}"ocaml" {>= "4.02.3"}]url {src:"https://github.com/mjambon/biniou/releases/download/1.2.1/biniou-1.2.1.tbz"checksum: ["sha256=35546c68b1929a8e6d27a3b39ecd17b38303a0d47e65eb9d1480c2061ea84335""sha512=82670cc77bf3e869ee26e5fbe5a5affa45a22bc8b6c4bd7e85473912780e0111baca59b34a2c14feae3543ce6e239d7fddaeab24b686a65bfe642cdb91d27ebf"]}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"authors: ["Daniel Bünzli <daniel.buenzl i@erratique.ch>"]homepage: "http://erratique.ch/software/cmdliner"doc: "http://erratique.ch/software/cmdliner/doc/Cmdliner"dev-repo: "git+http://erratique.ch/repos/cmdliner.git"bug-reports: "https://github.com/dbuenzli/cmdliner/issues"tags: [ "cli" "system" "declarative" "org:erratique" ]license: "ISC"depends:[ "ocaml" {>= "4.03.0"} ]build: [[ make "all" "PREFIX=%{prefix}%" ]]install:[[make "install" "LIBDIR=%{_:lib}%" "DOCDIR=%{_:doc}%" ][make "install-doc" "LIBDIR=%{_:lib}%" "DOCDIR=%{_:doc}%" ]]synopsis: """Declarative definition of command line interfaces for OCaml"""description: """\Cmdliner allows the declarative definition of command line interfacesfor OCaml.It provides a simple and compositional mechanism to convert commandline arguments to OCaml values and pass them to your functions. Themodule automatically handles syntax errors, help messages and UNIX manpage generation. It supports programs with single or multiple commandsand respects most of the [POSIX][1] and [GNU][2] conventions.Cmdliner has no dependencies and is distributed under the ISC license.[1]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html[2]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html"""url {archive: "http://erratique.ch/software/cmdliner/releases/cmdliner-1.0.4.tbz"checksum: "fe2213d0bc63b1e10a2d0aa66d2fc8d9"}
opam-version: "2.0"maintainer: "blue-prawn"authors: ["Anthony Green"]homepage: "http://sourceware.org/libffi/"license: "MIT"build: ["pkg-config" "libffi"]depexts: [["libffi"] {os = "macos" & os-distribution = "homebrew"}["libffi"] {os = "macos" & os-distribution = "macports"}["libffi-dev"] {os-distribution = "alpine"}["libffi-dev"] {os-family = "debian"}["libffi-devel"] {os-distribution = "centos"}["libffi-devel"] {os-distribution = "fedora"}["libffi-devel"] {os-distribution = "mageia"}["libffi-devel"] {os-distribution = "ol"}["libffi-devel"] {os-family = "suse"}]synopsis: "Virtual package relying on libffi system installation"description: "This package can only install if libffi is installed on the system."depends: ["conf-pkg-config" {build}]bug-reports: "https://github.com/ocaml/opam-repository/issues"flags: conf
opam-version: "2.0"maintainer: "tim@gfxmonk.net"homepage: "http://www.gnu.org/software/m4/m4.html"bug-reports: "https://github.com/ocaml/opam-repository/issues"authors: "GNU Project"license: "GPL-3.0-only"build: [["sh" "-exc" "echo | m4"]]depexts: [["m4"] {os-family = "debian"}["m4"] {os-distribution = "fedora"}["m4"] {os-distribution = "rhel"}["m4"] {os-distribution = "centos"}["m4"] {os-distribution = "alpine"}["m4"] {os-distribution = "nixos"}["m4"] {os-family = "suse"}["m4"] {os-distribution = "ol"}["m4"] {os-distribution = "arch"}]synopsis: "Virtual package relying on m4"description:"This package can only install if the m4 binary is installed on the system."flags: conf
opam-version: "2.0"maintainer: "unixjunkie@sdf.org"authors: ["Francois Berenger"]homepage: "http://www.freedesktop.org/wiki/Software/pkg-config/"bug-reports: "https://github.com/ocaml/opam-repository/issues"license: "GPL-1.0-or-later"build: [["pkg-config" "--help"]]install: [["ln" "-s" "/usr/local/bin/pkgconf" "%{bin}%/pkg-config"] {os = "openbsd"}]remove: [["rm" "-f" "%{bin}%/pkg-config"] {os = "openbsd"}]post-messages: ["conf-pkg-config: A symlink to /usr/local/bin/pkgconf has been installed in the OPAM bin directory (%{bin}%) on your PATH as 'pkg-config'. This is necessary for correct operation." {os = "openbsd"}]depexts: [["pkg-config"] {os-family = "debian"}["pkgconf"] {os-distribution = "arch"}["pkgconfig"] {os-distribution = "fedora"}["pkgconfig"] {os-distribution = "centos" & os-version <= "7"}["pkgconfig"] {os-distribution = "mageia"}["pkgconfig"] {os-distribution = "rhel" & os-version <= "7"}["pkgconfig"] {os-distribution = "ol"}["pkgconf"] {os-distribution = "alpine"}["pkgconfig"] {os-distribution = "nixos"}["devel/pkgconf"] {os = "openbsd"}["pkg-config"] {os = "macos" & os-distribution = "homebrew"}["pkgconfig"] {os = "macos" & os-distribution = "macports"}["pkgconf"] {os = "freebsd"}["pkgconf-pkg-config"] {os-distribution = "rhel" & os-version >= "8"}["pkgconf-pkg-config"] {os-distribution = "centos" & os-version >= "8"}["pkg-config"] {os-distribution = "cygwinports"}]synopsis: "Virtual package relying on pkg-config installation"description: """This package can only install if the pkg-config package is installedon the system."""flags: conf
opam-version: "2.0"maintainer: "simon.cruanes.2007@m4x.org"synopsis: "A modular, clean and powerful extension of the OCaml standard library"build: [["dune" "build" "-p" name "-j" jobs]["dune" "build" "@doc" "-p" name ] {with-doc}["dune" "runtest" "-p" name "-j" jobs] {with-test & ocaml:version < "4.11"}]depends: ["ocaml" { >= "4.03.0" }"dune" { >= "1.1" }"dune-configurator""seq""qtest" { with-test }"qcheck" { with-test }"ounit" { with-test }"iter" { with-test }"gen" { with-test }"uutf" { with-test }"odoc" { with-doc }]depopts: ["base-unix""base-threads"]tags: [ "stdlib" "containers" "iterators" "list" "heap" "queue" ]homepage: "https://github.com/c-cube/ocaml-containers/"doc: "https://c-cube.github.io/ocaml-containers"dev-repo: "git+https://github.com/c-cube/ocaml-containers.git"bug-reports: "https://github.com/c-cube/ocaml-containers/issues/"authors: "Simon Cruanes"url {src: "https://github.com/c-cube/ocaml-containers/archive/v3.2.tar.gz"checksum: ["md5=14787fb6878a94dd728a0ef7e368ab89""sha512=9debbd79542fbe24e6b0ec5e0fb74077566663fa53b868aa381962653d65543a86606ed6703a75cf3e14962b66068747b237a88bb1eea15b6062665e294795ac"]}
opam-version: "2.0"maintainer: "martin@mjambon.com"authors: "Martin Jambon"license: "BSD-3-Clause"homepage: "https://github.com/ocaml-community/cppo"doc: "https://ocaml-community.github.io/cppo/"bug-reports: "https://github.com/ocaml-community/cppo/issues"depends: ["ocaml" {>= "4.02.3"}"dune" {>= "1.0"}"base-unix"]build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]dev-repo: "git+https://github.com/ocaml-community/cppo.git"synopsis: "Code preprocessor like cpp for OCaml"description: """Cppo is an equivalent of the C preprocessor for OCaml programs.It allows the definition of simple macros and file inclusion.Cppo is:* more OCaml-friendly than cpp* easy to learn without consulting a manual* reasonably fast* simple to install and to maintain"""x-commit-hash: "7d217864a5fdc4551699e248137a2f8b719d2078"url {src:"https://github.com/ocaml-community/cppo/releases/download/v1.6.7/cppo-v1.6.7.tbz"checksum: ["sha256=db553e3e6c206df09b1858c3aef5e21e56564d593642a3c78bcedb6af36f529d""sha512=9722b50fd23aaccf86816313333a3bf8fc7c6b4ef06b153e5e1e1aaf14670cf51a4aac52fb1b4a0e5531699c4047a1eff6c24c969f7e5063e78096c2195b5819"]}
opam-version: "2.0"synopsis: "Parsing and printing of S-expressions in Canonical form"description: """This library provides minimal support for Canonical S-expressions[1]. Canonical S-expressions are a binary encoding of S-expressionsthat is super simple and well suited for communication betweenprograms.This library only provides a few helpers for simple applications. Ifyou need more advanced support, such as parsing from more fancy inputsources, you should consider copying the code of this library givenhow simple parsing S-expressions in canonical form is.To avoid a dependency on a particular S-expression library, the onlymodule of this library is parameterised by the type of S-expressions.[1] https://en.wikipedia.org/wiki/Canonical_S-expressions"""maintainer: ["Jeremie Dimino <jeremie@dimino.org>"]authors: ["Quentin Hocquet <mefyl@gruntech.org>""Jane Street Group, LLC <opensource@janestreet.com>""Jeremie Dimino <jeremie@dimino.org>"]license: "MIT"homepage: "https://github.com/ocaml-dune/csexp"doc: "https://ocaml-dune.github.io/csexp/"bug-reports: "https://github.com/ocaml-dune/csexp/issues"depends: ["dune" {>= "1.11"}"ocaml" {>= "4.02.3"}"result" {>= "1.5"}]dev-repo: "git+https://github.com/ocaml-dune/csexp.git"build: [["dune" "subst"] {pinned}["dune""build""-p"name"-j"jobs"@install"# "@runtest" {with-test & ocaml:version >= "4.04"}"@doc" {with-doc}]]x-commit-hash: "0e1b2044c8d1ff187c27cec3e46d9cde14892650"url {src:"https://github.com/ocaml-dune/csexp/releases/download/1.4.0/csexp-1.4.0.tbz"checksum: ["sha256=8e3d6fca87f102a126dee8b72a2a0d146f10439c47218dfc149d51bf3edf364e""sha512=604a5094fbbf61f497b342ad0aa8ec25275b2a904cd0c1823fc40daa54a15796b360374ff495c0d8ca3b4c1e6723b2ce37e030857fae131222606de818fb8129"]}
opam-version: "2.0"maintainer: "yallop@gmail.com"homepage: "https://github.com/ocamllabs/ocaml-ctypes"dev-repo: "git+http://github.com/ocamllabs/ocaml-ctypes.git"bug-reports: "http://github.com/ocamllabs/ocaml-ctypes/issues"depends: ["conf-libffi" {>= "2.0.0"}]tags: ["org:ocamllabs" "org:mirage"]post-messages: ["This package requires libffi on your system" {failure}]synopsis: "Virtual package for enabling the ctypes.foreign subpackage."description: """`ctypes-foreign` is just a virtual OPAM package that determineswhether the foreign subpackage should built as part of ctypes.In order to actually get the ctypes package, you should also:opam install ctypes ctypes-foreignYou can verify the existence of the ocamlfind subpackage by:ocamlfind list | grep ctypesWhich should output something like:ctypes (version: 0.4.1)ctypes.foreign (version: 0.4.1)ctypes.foreign.base (version: 0.4.1)ctypes.foreign.threaded (version: 0.4.1)ctypes.foreign.unthreaded (version: 0.4.1)ctypes.stubs (version: 0.4.1)ctypes.top (version: 0.4.1)"""authors: "yallop@gmail.com"
opam-version: "2.0"maintainer: "yallop@gmail.com"homepage: "https://github.com/ocamllabs/ocaml-ctypes"doc: "http://ocamllabs.github.io/ocaml-ctypes"dev-repo: "git+http://github.com/ocamllabs/ocaml-ctypes.git"bug-reports: "http://github.com/ocamllabs/ocaml-ctypes/issues"license: "MIT"build: [[make "XEN=%{mirage-xen:enable}%" "libffi.config"]{ctypes-foreign:installed}["touch" "libffi.config"] {!ctypes-foreign:installed}[make "XEN=%{mirage-xen:enable}%" "ctypes-base" "ctypes-stubs"][make "XEN=%{mirage-xen:enable}%" "ctypes-foreign"]{ctypes-foreign:installed}[make "test"] {with-test}]install: [[make "install" "XEN=%{mirage-xen:enable}%"]]depends: ["ocaml" {>= "4.02.3"}"integers" { >= "0.3.0" }"ocamlfind" {build}"lwt" {with-test & >= "3.2.0"}"ctypes-foreign" {with-test}"ounit" {with-test}"conf-ncurses" {with-test}"bigarray-compat"]depopts: ["ctypes-foreign""mirage-xen"]tags: ["org:ocamllabs" "org:mirage"]synopsis: "Combinators for binding to C libraries without writing any C"description: """ctypes is a library for binding to C libraries using pure OCaml. The primaryaim is to make writing C extensions as straightforward as possible.The core of ctypes is a set of combinators for describing the structure of Ctypes -- numeric types, arrays, pointers, structs, unions and functions. Youcan use these combinators to describe the types of the functions that you wantto call, then bind directly to those functions -- all without writing orgenerating any C!To install the optional `ctypes.foreign` interface (which uses `libffi` toprovide dynamic access to foreign libraries), you will need to also installthe `ctypes-foreign` optional dependency:opam install ctypes ctypes-foreignThis will make the `ctypes.foreign` ocamlfind subpackage available."""authors: "yallop@gmail.com"url {src: "https://github.com/ocamllabs/ocaml-ctypes/archive/0.18.0.tar.gz"checksum: "md5=5d9ef3790fda7cd97a8cec08be4b5b61"}conflicts: ["mirage-xen" {>= "6.0.0"}]
opam-version: "2.0"maintainer: "defree@gmail.com"authors: "The Merlin team"synopsis: "Reads config files for merlin"homepage: "https://github.com/ocaml/merlin"bug-reports: "https://github.com/ocaml/merlin/issues"dev-repo: "git+https://github.com/ocaml/merlin.git"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.06.1" }"dune" {>= "2.7.0"}"yojson" {>= "1.6.0"}"ocamlfind" {>= "1.6.0"}"csexp" {>= "1.2.3"}"result" {>= "1.5"}]description:"Helper process: reads .merlin files and gives the normalized content to merlin"x-commit-hash: "ab02f60994c81166820791b5f465f467d752b8dc"url {src:"https://github.com/ocaml/merlin/releases/download/v4.1/dot-merlin-reader-v4.1.tbz"checksum: ["sha256=14a36d6fb8646a5df4530420a7861722f1a4ee04753717947305e3676031e7cd""sha512=65fd4ab08904c05651a7ef8971802ffaa428daa920765dbcf162e3c56e8047e4c9e4356daa45efccce7c73a586635c8f6cf8118fd3059789de9aff68579bd436"]}
opam-version: "2.0"synopsis: "Embed build informations inside executable"description: """The build-info library allows to access information about how theexecutable was built, such as the version of the project at which itwas built or the list of statically linked libraries with theirversions. It supports reporting the version from the version controlsystem during development to get an precise reference of when theexecutable was built."""maintainer: ["Jane Street Group, LLC <opensource@janestreet.com>"]authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]license: "MIT"homepage: "https://github.com/ocaml/dune"doc: "https://dune.readthedocs.io/"bug-reports: "https://github.com/ocaml/dune/issues"depends: ["dune" {>= "2.8"}"odoc" {with-doc}]dev-repo: "git+https://github.com/ocaml/dune.git"build: [["dune" "subst"] {dev}["dune""build""-p"name"-j"jobs"@install""@doc" {with-doc}]]x-commit-hash: "b6a3f66fb15378fc7170e94778f4d2c0b142ad92"url {src: "https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz"checksum: ["sha256=4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac""sha512=efc1834c4add40138a101734665a1f462c19fe76d1cbb457b1fc20f95991118a50b24d485fb98d39046e41bec03885a8dc071bf8add51083ac9780bff9f6668a"]}
opam-version: "2.0"synopsis: "Helper library for gathering system configuration"description: """dune-configurator is a small library that helps writing OCaml scripts thattest features available on the system, in order to generate config.hfiles for instance.Among other things, dune-configurator allows one to:- test if a C program compiles- query pkg-config- import #define from OCaml header files- generate config.h file"""maintainer: ["Jane Street Group, LLC <opensource@janestreet.com>"]authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]license: "MIT"homepage: "https://github.com/ocaml/dune"doc: "https://dune.readthedocs.io/"bug-reports: "https://github.com/ocaml/dune/issues"depends: ["dune" {>= "2.8"}"ocaml" {>= "4.03.0"}"result""csexp" {>= "1.3.0"}"odoc" {with-doc}]dev-repo: "git+https://github.com/ocaml/dune.git"build: [["dune" "subst"] {dev}["dune""build""-p"name"-j"jobs"@install""@doc" {with-doc}]]x-commit-hash: "b6a3f66fb15378fc7170e94778f4d2c0b142ad92"url {src: "https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz"checksum: ["sha256=4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac""sha512=efc1834c4add40138a101734665a1f462c19fe76d1cbb457b1fc20f95991118a50b24d485fb98d39046e41bec03885a8dc071bf8add51083ac9780bff9f6668a"]}
opam-version: "2.0"synopsis: "Fast, portable, and opinionated build system"description: """dune is a build system that was designed to simplify the release ofJane Street packages. It reads metadata from "dune" files following avery simple s-expression syntax.dune is fast, has very low-overhead, and supports parallel builds onall platforms. It has no system dependencies; all you need to builddune or packages using dune is OCaml. You don't need make or bashas long as the packages themselves don't use bash explicitly.dune supports multi-package development by simply dropping multiplerepositories into the same directory.It also supports multi-context builds, such as building againstseveral opam roots/switches simultaneously. This helps maintainingpackages across several versions of OCaml and gives cross-compilationfor free."""maintainer: ["Jane Street Group, LLC <opensource@janestreet.com>"]authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]license: "MIT"homepage: "https://github.com/ocaml/dune"doc: "https://dune.readthedocs.io/"bug-reports: "https://github.com/ocaml/dune/issues"conflicts: ["merlin" {< "3.4.0"}"ocaml-lsp-server" {< "1.3.0"}"dune-configurator" {< "2.3.0"}"odoc" {< "1.3.0"}"dune-release" {< "1.3.0"}"js_of_ocaml-compiler" {< "3.6.0"}"jbuilder" {= "transition"}]dev-repo: "git+https://github.com/ocaml/dune.git"build: [# opam 2 sets OPAM_SWITCH_PREFIX, so we don't need a hardcoded path["ocaml" "configure.ml" "--libdir" lib] {opam-version < "2"}["ocaml" "bootstrap.ml" "-j" jobs]["./dune.exe" "build" "-p" name "--profile" "dune-bootstrap" "-j" jobs]]depends: [# Please keep the lower bound in sync with .github/workflows/workflow.yml,# dune-project and min_ocaml_version in bootstrap.ml("ocaml" {>= "4.08"} | ("ocaml" {< "4.08~~"} & "ocamlfind-secondary"))"base-unix""base-threads"]x-commit-hash: "b6a3f66fb15378fc7170e94778f4d2c0b142ad92"url {src: "https://github.com/ocaml/dune/releases/download/2.8.4/dune-2.8.4.tbz"checksum: ["sha256=4e6420177584aabdc3b7b37aee3026b094b82bf5d7ed175344a68e321f72e8ac""sha512=efc1834c4add40138a101734665a1f462c19fe76d1cbb457b1fc20f95991118a50b24d485fb98d39046e41bec03885a8dc071bf8add51083ac9780bff9f6668a"]}
opam-version: "2.0"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}["dune" "build" "-p" name "@doc"] {with-doc}]maintainer: ["martin@mjambon.com" "rudi.grinberg@gmail.com"]authors: ["Martin Jambon"]bug-reports: "https://github.com/mjambon/easy-format/issues"homepage: "https://github.com/mjambon/easy-format"doc: "https://mjambon.github.io/easy-format/"license: "BSD-3-Clause"dev-repo: "git+https://github.com/mjambon/easy-format.git"synopsis:"High-level and functional interface to the Format module of the OCaml standard library"description: """This module offers a high-level and functional interface to the Format module ofthe OCaml standard library. It is a pretty-printing facility, i.e. it takes asinput some code represented as a tree and formats this code into the mostvisually satisfying result, breaking and indenting lines of code whereappropriate.Input data must be first modelled and converted into a tree using 3 kinds ofnodes:* atoms* lists* labelled nodesAtoms represent any text that is guaranteed to be printed as-is. Lists can modelany sequence of items such as arrays of data or lists of definitions that arelabelled with something like "int main", "let x =" or "x:"."""depends: ["dune" {>= "1.10"}"ocaml" {>= "4.02.3"}]url {src:"https://github.com/mjambon/easy-format/releases/download/1.3.2/easy-format-1.3.2.tbz"checksum: ["sha256=3440c2b882d537ae5e9011eb06abb53f5667e651ea4bb3b460ea8230fa8c1926""sha512=e39377a2ff020ceb9ac29e8515a89d9bdbc91dfcfa871c4e3baafa56753fac2896768e5d9822a050dc1e2ade43c8967afb69391a386c0a8ecd4e1f774e236135"]}
opam-version: "2.0"maintainer: "francois.pottier@inria.fr"authors: ["François Pottier <francois.pottier@inria.fr>"]homepage: "https://gitlab.inria.fr/fpottier/fix"dev-repo: "git+https://gitlab.inria.fr/fpottier/fix.git"bug-reports: "francois.pottier@inria.fr"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" { >= "4.03" }"dune" {>= "1.3" }]synopsis: "Facilities for memoization and fixed points"url {src:"https://gitlab.inria.fr/fpottier/fix/repository/20201120/archive.tar.gz"checksum: ["md5=7eb570b759635fe66f3556d2b1cc88e3""sha512=344dcc619f9e8b8a6c998775b6d2dab2ea5253e6a67abe4797f76dc5dd30bc776568abce1e90477422e9db447821579889737e3531c42139708f813e983ea5d4"]}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"authors: ["The fpath programmers"]homepage: "https://erratique.ch/software/fpath"doc: "https://erratique.ch/software/fpath/doc"dev-repo: "git+https://erratique.ch/repos/fpath.git"bug-reports: "https://github.com/dbuenzli/fpath/issues"tags: [ "file" "system" "path" "org:erratique" ]license: "ISC"depends: ["ocaml" {>= "4.03.0"}"ocamlfind" {build}"ocamlbuild" {build}"topkg" {build & >= "0.9.0"}"astring"]build: [["ocaml" "pkg/pkg.ml" "build""--dev-pkg=true" {dev} ]]synopsis: """File system paths for OCaml"""description: """\Fpath is an OCaml module for handling file system paths with POSIX orWindows conventions. Fpath processes paths without accessing the filesystem and is independent from any system library.Fpath depends on [Astring][astring] and is distributed under the ISClicense.[astring]: http://erratique.ch/software/astring"""url {archive: "https://erratique.ch/software/fpath/releases/fpath-0.7.3.tbz"checksum: "0740b530e8fed5b0adc5eee8463cfc2f"}
opam-version: "2.0"maintainer: "yallop@gmail.com"authors: ["Jeremy Yallop""Demi Obenour""Stephane Glondu""Andreas Hauptmann"]homepage: "https://github.com/ocamllabs/ocaml-integers"bug-reports: "https://github.com/ocamllabs/ocaml-integers/issues"dev-repo: "git+https://github.com/ocamllabs/ocaml-integers.git"license: "MIT"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]depends: ["ocaml" {>= "4.02"}"dune"]doc: "http://ocamllabs.github.io/ocaml-integers/api.docdir/"synopsis: "Various signed and unsigned integer types for OCaml"url {src: "https://github.com/ocamllabs/ocaml-integers/archive/0.4.0.tar.gz"checksum: "md5=c1492352e6525048790508c57aad93c3"}
opam-version: "2.0"maintainer: "francois.pottier@inria.fr"authors: ["François Pottier <francois.pottier@inria.fr>""Yann Régis-Gianas <yrg@pps.univ-paris-diderot.fr>"]homepage: "http://gitlab.inria.fr/fpottier/menhir"dev-repo: "git+https://gitlab.inria.fr/fpottier/menhir.git"bug-reports: "menhir@inria.fr"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.02.3"}"dune" { >= "2.2.0"}"menhirLib" {= version}"menhirSdk" {= version}]synopsis: "An LR(1) parser generator"url {src:"https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz"checksum: ["md5=1cbc71c0bc1f3ddc3e71d5c1f919fd1a""sha512=3c309fa2cc4ad7c6fba85107bd946a542894882fa39741496b150307e93455b717418f19e94b5dad06ab269f5c55e8dc25705c96c0a5092e623fa38f1ce43c7f"]}
opam-version: "2.0"maintainer: "francois.pottier@inria.fr"authors: ["François Pottier <francois.pottier@inria.fr>""Yann Régis-Gianas <yrg@pps.univ-paris-diderot.fr>"]homepage: "http://gitlab.inria.fr/fpottier/menhir"dev-repo: "git+https://gitlab.inria.fr/fpottier/menhir.git"bug-reports: "menhir@inria.fr"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" { >= "4.02.3" }"dune" { >= "2.0.0" }]conflicts: ["menhir" { != version }]synopsis: "Runtime support library for parsers generated by Menhir"url {src:"https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz"checksum: ["md5=1cbc71c0bc1f3ddc3e71d5c1f919fd1a""sha512=3c309fa2cc4ad7c6fba85107bd946a542894882fa39741496b150307e93455b717418f19e94b5dad06ab269f5c55e8dc25705c96c0a5092e623fa38f1ce43c7f"]}
opam-version: "2.0"maintainer: "francois.pottier@inria.fr"authors: ["François Pottier <francois.pottier@inria.fr>""Yann Régis-Gianas <yrg@pps.univ-paris-diderot.fr>"]homepage: "http://gitlab.inria.fr/fpottier/menhir"dev-repo: "git+https://gitlab.inria.fr/fpottier/menhir.git"bug-reports: "menhir@inria.fr"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" { >= "4.02.3" }"dune" { >= "2.0.0" }]conflicts: ["menhir" { != version }]synopsis: "Compile-time library for auxiliary tools related to Menhir"url {src:"https://gitlab.inria.fr/fpottier/menhir/repository/20210310/archive.tar.gz"checksum: ["md5=1cbc71c0bc1f3ddc3e71d5c1f919fd1a""sha512=3c309fa2cc4ad7c6fba85107bd946a542894882fa39741496b150307e93455b717418f19e94b5dad06ab269f5c55e8dc25705c96c0a5092e623fa38f1ce43c7f"]}
opam-version: "2.0"maintainer: "defree@gmail.com"authors: "The Merlin team"homepage: "https://github.com/ocaml/merlin"bug-reports: "https://github.com/ocaml/merlin/issues"dev-repo: "git+https://github.com/ocaml/merlin.git"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" "merlin,dot-merlin-reader" "-j" "1"] {with-test}]depends: ["ocaml" {>= "4.11" & < "4.12"}"dune" {>= "2.7.0"}"dot-merlin-reader" {>= "4.0"}"yojson" {>= "1.6.0"}"conf-jq" {with-test}"csexp" {>= "1.2.3"}"result" {>= "1.5"}"menhir" {dev}"menhirLib" {dev}"menhirSdk" {dev}]synopsis:"Editor helper, provides completion, typing and source browsing in Vim and Emacs"description:"Merlin is an assistant for editing OCaml code. It aims to provide the features available in modern IDEs: error reporting, auto completion, source browsing and much more."post-messages: ["merlin installed.Quick setup for VIM-------------------Append this to your .vimrc to add merlin to vim's runtime-path:let g:opamshare = substitute(system('opam var share'),'\\n$','','''')execute \"set rtp+=\" . g:opamshare . \"/merlin/vim\"Also run the following line in vim to index the documentation::execute \"helptags \" . g:opamshare . \"/merlin/vim/doc\"Quick setup for EMACS-------------------Add opam emacs directory to your load-path by appending this to your .emacs:(let ((opam-share (ignore-errors (car (process-lines \"opam\" \"config\" \"var\" \"share\")))))(when (and opam-share (file-directory-p opam-share));; Register Merlin(add-to-list 'load-path (expand-file-name \"emacs/site-lisp\" opam-share))(autoload 'merlin-mode \"merlin\" nil t nil);; Automatically start it in OCaml buffers(add-hook 'tuareg-mode-hook 'merlin-mode t)(add-hook 'caml-mode-hook 'merlin-mode t);; Use opam switch to lookup ocamlmerlin binary(setq merlin-command 'opam)))Take a look at https://github.com/ocaml/merlin for more informationQuick setup with opam-user-setup--------------------------------Opam-user-setup support Merlin.$ opam user-setup installshould take care of basic setup.See https://github.com/OCamlPro/opam-user-setup"{success & !user-setup:installed}]x-commit-hash: "0916b10c76025f7cb0855c67324f72e344046d77"url {src:"https://github.com/ocaml/merlin/releases/download/v4.1-411/merlin-v4.1-411.tbz"checksum: ["sha256=9e2e6fc799c93ce1f2c7181645eafa37f64e43ace062b69218e1c29ac459937d""sha512=6a2e2503d81b22b0cc292ca6853231e59c42a216acec0cb540d03791d201fe83641a3502e62660668ad5d30405698e2429efe072cfd38dc30229024267f7c0b8"]}
opam-version: "2.0"synopsis:"The legacy Num library for arbitrary-precision integer and rational arithmetic"maintainer: "Xavier Leroy <xavier.leroy@inria.fr>"authors: ["Valérie Ménissier-Morain" "Pierre Weis" "Xavier Leroy"]license: "LGPL-2.1-only with OCaml-LGPL-linking-exception"homepage: "https://github.com/ocaml/num/"bug-reports: "https://github.com/ocaml/num/issues"depends: ["ocaml" {>= "4.06.0"}"ocamlfind" {build & >= "1.7.3"}]conflicts: ["base-num"]build: makeinstall: [make"install" {!ocaml:preinstalled}"findlib-install" {ocaml:preinstalled}]dev-repo: "git+https://github.com/ocaml/num.git"url {src: "https://github.com/ocaml/num/archive/v1.4.tar.gz"checksum: ["md5=cda2b727e116a0b6a9c03902cc4b2415""sha512=0cc9be8ad95704bb683b4bf6698bada1ee9a40dc05924b72adc7b969685c33eeb68ccf174cc09f6a228c48c18fe94af06f28bebc086a24973a066da620db8e6f"]}
opam-version: "2.0"maintainer: "opensource@janestreet.com"authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]homepage: "https://github.com/janestreet/ocaml-compiler-libs"bug-reports: "https://github.com/janestreet/ocaml-compiler-libs/issues"dev-repo: "git+https://github.com/janestreet/ocaml-compiler-libs.git"license: "MIT"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.04.1"}"dune" {>= "1.5.1"}]synopsis: """OCaml compiler libraries repackaged"""description: """This packages exposes the OCaml compiler libraries repackages underthe toplevel names Ocaml_common, Ocaml_bytecomp, Ocaml_optcomp, ..."""x-commit-hash: "7f5d1d2931b96fb3ee6dd569a469b51f621a6dd4"url {src:"https://github.com/janestreet/ocaml-compiler-libs/releases/download/v0.12.3/ocaml-compiler-libs-v0.12.3.tbz"checksum: ["sha256=a8403531439c14bbda2d504ef93610fd29a8e9520fc700f21889d893a513e3c9""sha512=0bb03b38e93bab3274a8ade38d017808110bc02f2181a594d8775c68fdd465733393f0451dbbf8860e6b50b56c45671d2182637c0840d1d6574803ec18673972"]}
opam-version: "2.0"synopsis: "LSP Server for OCaml"description: "An LSP server for OCaml."maintainer: ["Rudi Grinberg <me@rgrinerg.com>"]authors: ["Andrey Popp <8mayday@gmail.com>""Rusty Key <iam@stfoo.ru>""Louis Roché <louis@louisroche.net>""Oleksiy Golovko <alexei.golovko@gmail.com>""Rudi Grinberg <me@rgrinberg.com>""Sacha Ayoun <sachaayoun@gmail.com>""cannorin <cannorin@gmail.com>"]license: "ISC"homepage: "https://github.com/ocaml/ocaml-lsp"bug-reports: "https://github.com/ocaml/ocaml-lsp/issues"depends: ["dune" {>= "2.5"}"yojson""stdlib-shims""ppx_yojson_conv_lib""dune-build-info""dot-merlin-reader""csexp" {>= "1.2.3"}"result" {>= "1.5"}"ocamlformat" {with-test}"ocamlfind" {>= "1.5.2"}"odoc" {with-doc}"ocaml" {>= "4.06" & < "4.12"}]dev-repo: "git+https://github.com/ocaml/ocaml-lsp.git"build: [["dune" "subst"] {dev}["dune""build""-j"jobs"ocaml-lsp-server.install""--release"]]x-commit-hash: "154ccd7142651807d40eb851969f318b873b7fb4"url {src:"https://github.com/ocaml/ocaml-lsp/releases/download/1.4.1/jsonrpc-1.4.1.tbz"checksum: ["sha256=cee8371e7048e24c90e916c373ef6f3aba6f474d8a5fcf507ab6650fd8575eeb""sha512=150ebf71d3484d3beec1a145877cf30d84581bd072dd20159e878ed07cc4fc647b019b98bb0c9fede839b87f7bd13de4a64b534c0760a2ec57d0e4a4deac6f0f"]}
opam-version: "2.0"maintainer: "frederic.bour@lakaban.net"authors: ["Frédéric Bour <frederic.bour@lakaban.net>""Jérémie Dimino <jeremie@dimino.org>"]license: "LGPL-2.1 with OCaml linking exception"homepage: "https://github.com/ocaml-ppx/ocaml-migrate-parsetree"bug-reports: "https://github.com/ocaml-ppx/ocaml-migrate-parsetree/issues"dev-repo: "git+https://github.com/ocaml-ppx/ocaml-migrate-parsetree.git"doc: "https://ocaml-ppx.github.io/ocaml-migrate-parsetree/"tags: [ "syntax" "org:ocamllabs" ]build: [["dune" "build" "-p" name "-j" jobs]]depends: ["dune" {>= "1.11"}"ocaml" {>= "4.02.3" & < "4.13"}]synopsis: "Convert OCaml parsetrees between different versions"description: """Convert OCaml parsetrees between different versionsThis library converts parsetrees, outcometree and ast mappers betweendifferent OCaml versions. High-level functions help making PPXrewriters independent of a compiler version."""x-commit-hash: "4a05cf7a00d84e5f827cc9ae9c75e5dc85126085"url {src:"https://github.com/ocaml-ppx/ocaml-migrate-parsetree/releases/download/v2.1.0/ocaml-migrate-parsetree-v2.1.0.tbz"checksum: ["sha256=387b788ee4c0537f1fe02c25e05f0335af424828fc6fe940acc0db5948a5a71f""sha512=6ac80face6b77531c8d89a77d7a246bd5d43da435c355f62c03c8b8e360e1d7e339c904709fd3dbc9aa340c86ada9a69d5ebcf97cbdb7bd51bec97f831741b99"]}
opam-version: "2.0"maintainer: "Anil Madhavapeddy <anil@recoil.org>"authors: "Anil Madhavapeddy <anil@recoil.org>"license: "ISC"tags: "org:ocamllabs"homepage: "https://github.com/ocurrent/ocaml-version"doc: "https://ocurrent.github.io/ocaml-version/doc"bug-reports: "https://github.com/ocurrent/ocaml-version/issues"depends: ["ocaml" {>= "4.07.0"}"dune""alcotest" {with-test}]build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]]dev-repo: "git+https://github.com/ocurrent/ocaml-version.git"synopsis: "Manipulate, parse and generate OCaml compiler version strings"description: """This library provides facilities to parse version numbers of the OCamlcompiler, and enumerates the various official OCaml releases and configurationvariants.OCaml version numbers are of the form `major.minor.patch+extra`, where the`patch` and `extra` fields are optional. This library offers the followingfunctionality:- Functions to parse and serialise OCaml compiler version numbers.- Enumeration of official OCaml compiler version releases.- Test compiler versions for a particular feature (e.g. the `bytes` type)- [opam](https://opam.ocaml.org) compiler switch enumeration.### Further information- **Discussion:** Post on <https://discuss.ocaml.org/> with the `ocaml` tag underthe Ecosystem category.- **Bugs:** <https://github.com/ocurrent/ocaml-version/issues>- **Docs:** <http://docs.mirage.io/ocaml-version>"""x-commit-hash: "eb14804dbf9424c27c8d14fce19b3243f80a69fa"url {src:"https://github.com/ocurrent/ocaml-version/releases/download/v3.1.0/ocaml-version-v3.1.0.tbz"checksum: ["sha256=ac7ba16a09d8f72212742f3936980fbfaebb698c7bbf625182af7d6b2c3cde5f""sha512=6e11823531f1f70b5d4b90ed9f2fcc22cbf83924a7a0ef40eebc4b80598db6acdaca97f1d379e01860513d5dda492f5bc4d944f0c1dd7df491b2f36a0f729bb5"]}
opam-version: "2.0"maintainer: "Gabriel Scherer <gabriel.scherer@gmail.com>"authors: ["Nicolas Pouillard" "Berke Durak"]homepage: "https://github.com/ocaml/ocamlbuild/"bug-reports: "https://github.com/ocaml/ocamlbuild/issues"license: "LGPL-2.1-only with OCaml-LGPL-linking-exception"doc: "https://github.com/ocaml/ocamlbuild/blob/master/manual/manual.adoc"dev-repo: "git+https://github.com/ocaml/ocamlbuild.git"build: [[make"-f""configure.make""all""OCAMLBUILD_PREFIX=%{prefix}%""OCAMLBUILD_BINDIR=%{bin}%""OCAMLBUILD_LIBDIR=%{lib}%""OCAMLBUILD_MANDIR=%{man}%""OCAML_NATIVE=%{ocaml:native}%""OCAML_NATIVE_TOOLS=%{ocaml:native}%"][make "check-if-preinstalled" "all" "opam-install"]]conflicts: ["base-ocamlbuild""ocamlfind" {< "1.6.2"}]synopsis:"OCamlbuild is a build system with builtin rules to easily build most OCaml projects."depends: ["ocaml" {>= "4.03"}]url {src: "https://github.com/ocaml/ocamlbuild/archive/0.14.0.tar.gz"checksum: "sha256=87b29ce96958096c0a1a8eeafeb6268077b2d11e1bf2b3de0f5ebc9cf8d42e78"}
#!/bin/shBINDIR=$(dirname "$(command -v ocamlc)")"$BINDIR/ocaml" -I "$OCAML_TOPLEVEL_PATH" "$@"
bin: ["src/findlib/ocamlfind" {"ocamlfind"}"?src/findlib/ocamlfind_opt" {"ocamlfind"}"?tools/safe_camlp4"]toplevel: ["src/findlib/topfind"]
opam-version: "2.0"synopsis: "A library manager for OCaml"maintainer: "Thomas Gazagnaire <thomas@gazagnaire.org>"authors: "Gerd Stolpmann <gerd@gerd-stolpmann.de>"homepage: "http://projects.camlcity.org/projects/findlib.html"bug-reports: "https://gitlab.camlcity.org/gerd/lib-findlib/issues"dev-repo: "git+https://gitlab.camlcity.org/gerd/lib-findlib.git"description: """Findlib is a library manager for OCaml. It provides a convention howto store libraries, and a file format ("META") to describe theproperties of libraries. There is also a tool (ocamlfind) forinterpreting the META files, so that it is very easy to use librariesin programs and scripts."""build: [["./configure""-bindir"bin"-sitelib"lib"-mandir"man"-config""%{lib}%/findlib.conf""-no-custom""-no-camlp4" {!ocaml:preinstalled & ocaml:version >= "4.02.0"}"-no-topfind" {ocaml:preinstalled}][make "all"][make "opt"] {ocaml:native}]install: [["./configure""-bindir"bin"-sitelib"lib"-mandir"man"-config""%{lib}%/findlib.conf""-no-custom""-no-camlp4" {!ocaml:preinstalled & ocaml:version >= "4.02.0"}"-no-topfind" {ocaml:preinstalled}][make "install"]["install" "-m" "0755" "ocaml-stub" "%{bin}%/ocaml"] {ocaml:preinstalled}]depends: ["ocaml" {>= "4.00.0" & < "4.13"}"conf-m4" {build}]extra-files: [["ocamlfind.install" "md5=06f2c282ab52d93aa6adeeadd82a2543"]["ocaml-stub" "md5=181f259c9e0bad9ef523e7d4abfdf87a"]]url {src: "http://download.camlcity.org/download/findlib-1.8.1.tar.gz"checksum: "md5=18ca650982c15536616dea0e422cbd8c"mirrors: "http://download2.camlcity.org/download/findlib-1.8.1.tar.gz"}depopts: ["graphics"]
opam-version: "2.0"synopsis: "Auto-formatter for OCaml code"description:"OCamlFormat is a tool to automatically format OCaml code in a uniform style."maintainer: ["OCamlFormat Team <ocamlformat-team@fb.com>"]authors: ["Josh Berdine <jjb@fb.com>"]license: "MIT"homepage: "https://github.com/ocaml-ppx/ocamlformat"bug-reports: "https://github.com/ocaml-ppx/ocamlformat/issues"depends: ["dune" {>= "2.7"}"ocaml" {>= "4.08" & < "4.13"}"ocaml-version""alcotest" {with-test}"base" {>= "v0.12.0" & < "v0.15"}"base-unix""cmdliner""dune-build-info""fix""fpath""menhir" {>= "20180528"}"menhirLib" {>= "20200624"}"menhirSdk" {>= "20200624"}"ocaml-migrate-parsetree" {>= "2.1.0"}"ocp-indent" {with-test}"odoc" {>= "1.4.2"}"ppxlib" {>= "0.22.0"}"re""stdio" {< "v0.15"}"uuseg" {>= "10.0.0"}"uutf" {>= "1.0.1"}]build: [["dune" "subst"] {dev}["dune""build""-p"name"-j"jobs"@install""@runtest" {with-test}"@doc" {with-doc}]]dev-repo: "git+https://github.com/ocaml-ppx/ocamlformat.git"x-commit-hash: "bfd6bbe95c614d1d982244c4fd0ba494275d2245"url {src:"https://github.com/ocaml-ppx/ocamlformat/releases/download/0.17.0/ocamlformat-0.17.0.tbz"checksum: ["sha256=68848b12e82dc1077a29f63d2777680e692b1a565276fcd00f06fb93cced3438""sha512=168ac7dee5a78954b273972b099681a4f2a6864b81c1dfe5ee5ff2f0ba79f150aeca8128b95dce4fd30d4d830906f02975d56b804dbb513fe0bb63c95d61030b"]}
opam-version: "2.0"homepage: "http://github.com/ocaml/odoc"doc: "https://ocaml.github.io/odoc/"bug-reports: "https://github.com/ocaml/odoc/issues"license: "ISC"authors: ["Thomas Refis <trefis@janestreet.com>""David Sheets <sheets@alum.mit.edu>""Leo White <leo@lpw25.net>""Anton Bachin <antonbachin@yahoo.com>""Jon Ludlam <jon@recoil.org>"]maintainer: "Anton Bachin <antonbachin@yahoo.com>"dev-repo: "git+https://github.com/ocaml/odoc.git"synopsis: "OCaml documentation generator"description: """Odoc is a documentation generator for OCaml. It reads doc comments,delimited with `(** ... *)`, and outputs HTML."""depends: ["astring""cmdliner""cppo" {build}"dune""fpath""ocaml" {>= "4.02.0" & < "4.13"}"result""tyxml" {>= "4.3.0"}"alcotest" {dev & >= "0.8.3"}"markup" {dev & >= "1.0.0"}"ocamlfind" {dev}"sexplib" {dev & >= "113.33.00"}"bisect_ppx" {dev & >= "1.3.0"}]build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]]x-commit-hash: "c0df8ce2171fa9645a41f371429aa3ddc16de5c1"url {src: "https://github.com/ocaml/odoc/releases/download/1.5.2/odoc-1.5.2.tbz"checksum: ["sha256=d24463f2660bc28c72cda001478360158e953721c9e23fb361ec4783113c4871""sha512=e6c83630325de422f31cda8f88c038d213969f8b98e989593c057658f3956c0855860c9bc38f61b6479929516ca95aee689ddfba3ad8c47d821c4fdf54524cf9"]}
opam-version: "2.0"maintainer: "andreashauptmann@t-online.de"authors: [ "andreashauptmann@t-online.de" ]license: "LGPL-2.1-or-later with OCaml-LGPL-linking-exception"homepage: "https://fdopen.github.io/ppx_cstubs/"dev-repo: "git+https://github.com/fdopen/ppx_cstubs.git"doc: "https://fdopen.github.io/ppx_cstubs/"bug-reports: "https://github.com/fdopen/ppx_cstubs/issues"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["bigarray-compat""ctypes" {>= "0.13.0" & < "0.19"}"integers""num""result""containers" {>= "2.2"}"cppo" {build & >= "1.3"}"ocaml" {>= "4.04.2" & < "4.13.0"}"ppxlib" {>= "0.22.0"}"ocamlfind" {>= "1.7.2"} # not only a build dependency, it depends on findlib.top"dune" {>= "1.6"}"re" {>= "1.7.2"}]synopsis: """Preprocessor for easier stub generation with ctypes"""description: """ppx_cstubs is a ppx-based preprocessor for stub generation withctypes. ppx_cstubs creates two files from a single ml file: a filewith c stub code and an OCaml file with all additional boilerplatecode."""url {src: "https://github.com/fdopen/ppx_cstubs/archive/0.6.1.1.tar.gz"checksum: ["md5=33e520e369da5630c697318f6f4ed26d""sha512=77f28fd93ba476ccad089029fb7c7254a4525ea2d61f4d0a74c69b8c771e2657929c16cfa334671ccead1c02743804fc3db7726fd3e47772f50dc4a16270435c"]}
opam-version: "2.0"maintainer: "jeremie@dimino.org"authors: ["Jérémie Dimino"]license: "BSD-3-Clause"homepage: "https://github.com/ocaml-ppx/ppx_derivers"bug-reports: "https://github.com/ocaml-ppx/ppx_derivers/issues"dev-repo: "git://github.com/ocaml-ppx/ppx_derivers.git"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml""dune"]synopsis: "Shared [@@deriving] plugin registry"description: """Ppx_derivers is a tiny package whose sole purpose is to allowppx_deriving and ppx_type_conv to inter-operate gracefully when linkedas part of the same ocaml-migrate-parsetree driver."""url {src: "https://github.com/ocaml-ppx/ppx_derivers/archive/1.2.1.tar.gz"checksum: "md5=5dc2bf130c1db3c731fe0fffc5648b41"}
opam-version: "2.0"maintainer: "opensource@janestreet.com"authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]homepage: "https://github.com/janestreet/ppx_yojson_conv_lib"bug-reports: "https://github.com/janestreet/ppx_yojson_conv_lib/issues"dev-repo: "git+https://github.com/janestreet/ppx_yojson_conv_lib.git"doc: "https://ocaml.janestreet.com/ocaml-core/latest/doc/ppx_yojson_conv_lib/index.html"license: "MIT"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.02.3"}"dune" {>= "2.0.0"}"yojson" {>= "1.7.0"}]synopsis: "Runtime lib for ppx_yojson_conv"description: "Part of the Jane Street's PPX rewriters collection."url {src: "https://ocaml.janestreet.com/ocaml-core/v0.14/files/ppx_yojson_conv_lib-v0.14.0.tar.gz"checksum: "md5=e23c5593a7211ad4fb09e26e9a74698a"}
opam-version: "2.0"synopsis: "Standard library for ppx rewriters"description: """Ppxlib is the standard library for ppx rewriters and other programsthat manipulate the in-memory reprensation of OCaml programs, a.k.athe "Parsetree".It also comes bundled with two ppx rewriters that are commonly used towrite tools that manipulate and/or generate Parsetree values;`ppxlib.metaquot` which allows to construct Parsetree values using theOCaml syntax directly and `ppxlib.traverse` which provides variousways of automatically traversing values of a given type, in particularallowing to inject a complex structured value into generated code."""maintainer: ["opensource@janestreet.com"]authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]license: "MIT"homepage: "https://github.com/ocaml-ppx/ppxlib"doc: "https://ocaml-ppx.github.io/ppxlib/"bug-reports: "https://github.com/ocaml-ppx/ppxlib/issues"depends: ["dune" {>= "2.7"}"ocaml" {>= "4.04.1" & < "4.13"}"ocaml-compiler-libs" {>= "v0.11.0"}"ocaml-migrate-parsetree" {>= "2.1.0"}"ppx_derivers" {>= "1.0"}"sexplib0""stdlib-shims""ocamlfind" {with-test}"re" {with-test & >= "1.9.0"}"cinaps" {with-test & >= "v0.12.1"}"base" {with-test}"stdio" {with-test}"odoc" {with-doc}]build: [["dune" "subst"] {dev}["dune""build""-p"name"-j"jobs"@install""@runtest" {with-test}"@doc" {with-doc}]]dev-repo: "git+https://github.com/ocaml-ppx/ppxlib.git"x-commit-hash: "06a2c9bdad8c1d3361a3d9430e9bf58476b08590"url {src:"https://github.com/ocaml-ppx/ppxlib/releases/download/0.22.0/ppxlib-0.22.0.tbz"checksum: ["sha256=3eeb91e03966662284a3222e612dee7f4fa2b7637c53d9572d2a74134bb96d7a""sha512=425051dff9df53579a6edd17369d66c10f87a78daeddf1691e50997990ed643e874fcc6a30112a4dacbfd2d0097a19445354e04cd920d9522f76c51cdbc7f1db"]}
opam-version: "2.0"maintainer: "rudi.grinberg@gmail.com"authors: ["Jerome Vouillon""Thomas Gazagnaire""Anil Madhavapeddy""Rudi Grinberg""Gabriel Radanne"]license: "LGPL-2.0-only with OCaml-LGPL-linking-exception"homepage: "https://github.com/ocaml/ocaml-re"bug-reports: "https://github.com/ocaml/ocaml-re/issues"dev-repo: "git+https://github.com/ocaml/ocaml-re.git"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]depends: ["ocaml" {>= "4.02"}"dune""ounit" {with-test}"seq"]synopsis: "RE is a regular expression library for OCaml"description: """Pure OCaml regular expressions with:* Perl-style regular expressions (module Re.Perl)* Posix extended regular expressions (module Re.Posix)* Emacs-style regular expressions (module Re.Emacs)* Shell-style file globbing (module Re.Glob)* Compatibility layer for OCaml's built-in Str module (module Re.Str)"""url {src:"https://github.com/ocaml/ocaml-re/releases/download/1.9.0/re-1.9.0.tbz"checksum: "md5=bddaed4f386a22cace7850c9c7dac296"}
opam-version: "2.0"maintainer: "opensource@janestreet.com"authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]homepage: "https://github.com/janestreet/result"dev-repo: "git+https://github.com/janestreet/result.git"bug-reports: "https://github.com/janestreet/result/issues"license: "BSD-3-Clause"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml""dune" {>= "1.0"}]synopsis: "Compatibility Result module"description: """Projects that want to use the new result type defined in OCaml >= 4.03while staying compatible with older version of OCaml should use theResult module defined in this library."""url {src:"https://github.com/janestreet/result/releases/download/1.5/result-1.5.tbz"checksum: "md5=1b82dec78849680b49ae9a8a365b831b"}
name="seq"version="[distributed with OCaml 4.07 or above]"description="dummy backward-compatibility package for iterators"requires=""
lib:["META.seq" {"META"}]
opam-version: "2.0"maintainer: " "authors: " "homepage: " "depends: ["ocaml" {>= "4.07.0"}]dev-repo: "git+https://github.com/ocaml/ocaml.git"bug-reports: "https://caml.inria.fr/mantis/main_page.php"synopsis:"Compatibility package for OCaml's standard iterator type starting from 4.07."extra-files: [["seq.install" "md5=026b31e1df290373198373d5aaa26e42"]["META.seq" "md5=b33c8a1a6c7ed797816ce27df4855107"]]
opam-version: "2.0"maintainer: "opensource@janestreet.com"authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]homepage: "https://github.com/janestreet/sexplib0"bug-reports: "https://github.com/janestreet/sexplib0/issues"dev-repo: "git+https://github.com/janestreet/sexplib0.git"doc: "https://ocaml.janestreet.com/ocaml-core/latest/doc/sexplib0/index.html"license: "MIT"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.04.2"}"dune" {>= "2.0.0"}]synopsis: "Library containing the definition of S-expressions and some base converters"description: "Part of Jane Street's Core libraryThe Core suite of libraries is an industrial strength alternative toOCaml's standard library that was developed by Jane Street, thelargest industrial user of OCaml."url {src: "https://ocaml.janestreet.com/ocaml-core/v0.14/files/sexplib0-v0.14.0.tar.gz"checksum: "md5=37aff0af8f8f6f759249475684aebdc4"}
opam-version: "2.0"maintainer: "opensource@janestreet.com"authors: ["Jane Street Group, LLC <opensource@janestreet.com>"]homepage: "https://github.com/janestreet/stdio"bug-reports: "https://github.com/janestreet/stdio/issues"dev-repo: "git+https://github.com/janestreet/stdio.git"doc: "https://ocaml.janestreet.com/ocaml-core/latest/doc/stdio/index.html"license: "MIT"build: [["dune" "build" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.04.2"}"base" {>= "v0.14" & < "v0.15"}"dune" {>= "2.0.0"}]synopsis: "Standard IO library for OCaml"description: "Stdio implements simple input/output functionalities for OCaml.It re-exports the input/output functions of the OCaml standardlibraries using a more consistent API."url {src: "https://ocaml.janestreet.com/ocaml-core/v0.14/files/stdio-v0.14.0.tar.gz"checksum: "md5=4cbdf15f0be88c3258aaeff9e04e00e9"}
opam-version: "2.0"maintainer: "The stdlib-shims programmers"authors: "The stdlib-shims programmers"homepage: "https://github.com/ocaml/stdlib-shims"doc: "https://ocaml.github.io/stdlib-shims/"dev-repo: "git+https://github.com/ocaml/stdlib-shims.git"bug-reports: "https://github.com/ocaml/stdlib-shims/issues"tags: ["stdlib" "compatibility" "org:ocaml"]license: ["typeof OCaml system"]depends: ["dune""ocaml" {>= "4.02.3"}]build: [ "dune" "build" "-p" name "-j" jobs ]synopsis: "Backport some of the new stdlib features to older compiler"description: """Backport some of the new stdlib features to older compiler,such as the Stdlib module.This allows projects that require compatibility with older compiler touse these new features in their code."""x-commit-hash: "fb6815e5d745f07fd567c11671149de6ef2e74c8"url {src:"https://github.com/ocaml/stdlib-shims/releases/download/0.3.0/stdlib-shims-0.3.0.tbz"checksum: ["sha256=babf72d3917b86f707885f0c5528e36c63fccb698f4b46cf2bab5c7ccdd6d84a""sha512=1151d7edc8923516e9a36995a3f8938d323aaade759ad349ed15d6d8501db61ffbe63277e97c4d86149cf371306ac23df0f581ec7e02611f58335126e1870980"]}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"authors: ["Daniel Bünzli <daniel.buenzl i@erratique.ch>"]homepage: "http://erratique.ch/software/topkg"doc: "http://erratique.ch/software/topkg/doc"license: "ISC"dev-repo: "git+http://erratique.ch/repos/topkg.git"bug-reports: "https://github.com/dbuenzli/topkg/issues"tags: ["packaging" "ocamlbuild" "org:erratique"]depends: ["ocaml" {>= "4.03.0"}"ocamlfind" {build & >= "1.6.1"}"ocamlbuild" ]build: [["ocaml" "pkg/pkg.ml" "build""--pkg-name" name"--dev-pkg" "%{pinned}%" ]]synopsis: """The transitory OCaml software packager"""description: """\Topkg is a packager for distributing OCaml software. It provides anAPI to describe the files a package installs in a given buildconfiguration and to specify information about the package'sdistribution, creation and publication procedures.The optional topkg-care package provides the `topkg` command line toolwhich helps with various aspects of a package's life cycle: creatingand linting a distribution, releasing it on the WWW, publish itsdocumentation, add it to the OCaml opam repository, etc.Topkg is distributed under the ISC license and has **no**dependencies. This is what your packages will need as a *build*dependency.Topkg-care is distributed under the ISC license it depends on[fmt][fmt], [logs][logs], [bos][bos], [cmdliner][cmdliner],[webbrowser][webbrowser] and `opam-format`.[fmt]: http://erratique.ch/software/fmt[logs]: http://erratique.ch/software/logs[bos]: http://erratique.ch/software/bos[cmdliner]: http://erratique.ch/software/cmdliner[webbrowser]: http://erratique.ch/software/webbrowser"""url {archive: "http://erratique.ch/software/topkg/releases/topkg-1.0.3.tbz"checksum: "e285f7a296d77ee7d831ba9a6bfb396f"}
opam-version: "2.0"maintainer: "dev@ocsigen.org"homepage: "https://github.com/ocsigen/tyxml/"bug-reports: "https://github.com/ocsigen/tyxml/issues"doc: "https://ocsigen.org/tyxml/manual/"dev-repo: "git+https://github.com/ocsigen/tyxml.git"license: "LGPL-2.1 with OCaml linking exception"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]["dune" "runtest" "-p" name "-j" jobs] {with-test}]depends: ["ocaml" {>= "4.02"}"dune""alcotest" {with-test}"seq""uutf" {>= "1.0.0"}"re" {>= "1.5.0"}]synopsis:"TyXML is a library for building correct HTML and SVG documents"description:"""TyXML provides a set of convenient combinators that uses the OCamltype system to ensure the validity of the generated documents. TyXMLcan be used with any representation of HTML and SVG: the textual one,provided directly by this package, or DOM trees (`js_of_ocaml-tyxml`)virtual DOM (`virtual-dom`) and reactive or replicated trees(`eliom`). You can also create your own representation and use it toinstantiate a new set of combinators.```ocamlopen Tyxmllet to_ocaml = Html.(a ~a:[a_href "ocaml.org"] [txt "OCaml!"])```"""authors: "The ocsigen team"url {src:"https://github.com/ocsigen/tyxml/releases/download/4.4.0/tyxml-4.4.0.tbz"checksum: ["sha256=516394dd4a5c31726997c51d66aa31cacb91e3c46d4e16c7699130e204042530""sha512=d5f2187f8410524cec7a14b28e8950837070eb0b6571b015dd06076c2841eb7ccaffa86d5d2307eaf1950ee62f9fb926477dac01c870d9c1a2f525853cb44d0c"]}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"authors: ["Daniel Bünzli <daniel.buenzl i@erratique.ch>"]homepage: "http://ocaml.org"doc: "https://ocaml.github.io/uchar/"dev-repo: "git+https://github.com/ocaml/uchar.git"bug-reports: "https://github.com/ocaml/uchar/issues"tags: [ "text" "character" "unicode" "compatibility" "org:ocaml.org" ]license: "typeof OCaml system"depends: ["ocaml" {>= "3.12.0"}"ocamlbuild" {build}]build: [["ocaml" "pkg/git.ml"]["ocaml""pkg/build.ml""native=%{ocaml:native}%""native-dynlink=%{ocaml:native-dynlink}%"]]synopsis: "Compatibility library for OCaml's Uchar module"description: """The `uchar` package provides a compatibility library for the[`Uchar`][1] module introduced in OCaml 4.03.The `uchar` package is distributed under the license of the OCamlcompiler. See [LICENSE](LICENSE) for details.[1]: http://caml.inria.fr/pub/docs/manual-ocaml/libref/Uchar.html"""url {src:"https://github.com/ocaml/uchar/releases/download/v0.0.2/uchar-0.0.2.tbz"checksum: "md5=c9ba2c738d264c420c642f7bb1cf4a36"}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"authors: [ "The uucp programmers" ]homepage: "https://erratique.ch/software/uucp"doc: "https://erratique.ch/software/uucp/doc/Uucp"dev-repo: "git+https://erratique.ch/repos/uucp.git"bug-reports: "https://github.com/dbuenzli/uucp/issues"tags: [ "unicode" "text" "character" "org:erratique" ]license: "ISC"depends: ["ocaml" {>= "4.03.0"}"ocamlfind" {build}"ocamlbuild" {build}"topkg" {build}"uucd" {with-test} # dev really"uunf" {with-test}"uutf" {with-test}]depopts: [ "uunf" "uutf" "cmdliner" ]conflicts: [ "uutf" {< "1.0.1"}"cmdliner" {< "1.0.0"} ]build: [["ocaml" "pkg/pkg.ml" "build""--dev-pkg" "%{pinned}%""--with-uutf" "%{uutf:installed}%""--with-uunf" "%{uunf:installed}%""--with-cmdliner" "%{cmdliner:installed}%"]]synopsis: """Unicode character properties for OCaml"""description: """\Uucp is an OCaml library providing efficient access to a selection ofcharacter properties of the [Unicode character database][1].Uucp is independent from any Unicode text data structure and has nodependencies. It is distributed under the ISC license.[1]: http://www.unicode.org/reports/tr44/"""url {archive: "https://erratique.ch/software/uucp/releases/uucp-13.0.0.tbz"checksum: "07e706249ddb2d02f0fa298804d3c739"}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"authors: ["The uuseg programmers"]homepage: "https://erratique.ch/software/uuseg"doc: "https://erratique.ch/software/uuseg"dev-repo: "git+https://erratique.ch/repos/uuseg.git"bug-reports: "https://github.com/dbuenzli/uuseg/issues"tags: [ "segmentation" "text" "unicode" "org:erratique" ]license: "ISC"depends: [ "ocaml" {>= "4.03.0"}"ocamlfind" {build}"ocamlbuild" {build}"topkg" {build}"uucp" {>= "13.0.0" & < "14.0.0"} ]depopts: [ "uutf""cmdliner""uutf" {with-test}"cmdliner" {with-test} ]conflicts: [ "uutf" {< "1.0.0"} ]build: [["ocaml" "pkg/pkg.ml" "build""--pinned" "%{pinned}%""--with-uutf" "%{uutf:installed}%""--with-cmdliner" "%{cmdliner:installed}%" ]]synopsis: """Unicode text segmentation for OCaml"""description: """\Uuseg is an OCaml library for segmenting Unicode text. It implementsthe locale independent [Unicode text segmentation algorithms][1] todetect grapheme cluster, word and sentence boundaries and the[Unicode line breaking algorithm][2] to detect line breakopportunities.The library is independent from any IO mechanism or Unicode text datastructure and it can process text without a complete in-memoryrepresentation.Uuseg depends on [Uucp](http://erratique.ch/software/uucp) andoptionally on [Uutf](http://erratique.ch/software/uutf) for support onOCaml UTF-X encoded strings. It is distributed under the ISC license.[1]: http://www.unicode.org/reports/tr29/[2]: http://www.unicode.org/reports/tr14/"""url {archive: "https://erratique.ch/software/uuseg/releases/uuseg-13.0.0.tbz"checksum: "a07a97fff61da604614ea8da0547ef6a"}
opam-version: "2.0"maintainer: "Daniel Bünzli <daniel.buenzl i@erratique.ch>"authors: ["Daniel Bünzli <daniel.buenzl i@erratique.ch>"]homepage: "http://erratique.ch/software/uutf"doc: "http://erratique.ch/software/uutf/doc/Uutf"dev-repo: "git+http://erratique.ch/repos/uutf.git"bug-reports: "https://github.com/dbuenzli/uutf/issues"tags: [ "unicode" "text" "utf-8" "utf-16" "codec" "org:erratique" ]license: "ISC"depends: ["ocaml" {>= "4.01.0"}"ocamlfind" {build}"ocamlbuild" {build}"topkg" {build}"uchar"]depopts: ["cmdliner"]conflicts: ["cmdliner" { < "0.9.6"} ]build: [["ocaml" "pkg/pkg.ml" "build""--pinned" "%{pinned}%""--with-cmdliner" "%{cmdliner:installed}%" ]]synopsis: """Non-blocking streaming Unicode codec for OCaml"""description: """\Uutf is a non-blocking streaming codec to decode and encode the UTF-8,UTF-16, UTF-16LE and UTF-16BE encoding schemes. It can efficientlywork character by character without blocking on IO. Decoders performcharacter position tracking and support newline normalization.Functions are also provided to fold over the characters of UTF encodedOCaml string values and to directly encode characters in OCamlBuffer.t values.Uutf has no dependency and is distributed under the ISC license."""url {archive: "http://erratique.ch/software/uutf/releases/uutf-1.0.2.tbz"checksum: "a7c542405a39630c689a82bd7ef2292c"}
opam-version: "2.0"maintainer: "martin@mjambon.com"authors: ["Martin Jambon"]homepage: "https://github.com/ocaml-community/yojson"bug-reports: "https://github.com/ocaml-community/yojson/issues"dev-repo: "git+https://github.com/ocaml-community/yojson.git"doc: "https://ocaml-community.github.io/yojson/"build: [["dune" "subst"] {pinned}["dune" "build" "-p" name "-j" jobs]]run-test: [["dune" "runtest" "-p" name "-j" jobs]]depends: ["ocaml" {>= "4.02.3"}"dune""cppo" {build}"easy-format""biniou" {>= "1.2.0"}"alcotest" {with-test & >= "0.8.5"}]synopsis:"Yojson is an optimized parsing and printing library for the JSON format"description: """Yojson is an optimized parsing and printing library for the JSON format.It addresses a few shortcomings of json-wheel including 2x speedup,polymorphic variants and optional syntax for tuples and variants.ydump is a pretty-printing command-line program provided with theyojson package.The program atdgen can be used to derive OCaml-JSON serializers anddeserializers from type definitions."""url {src:"https://github.com/ocaml-community/yojson/releases/download/1.7.0/yojson-1.7.0.tbz"checksum: "md5=b89d39ca3f8c532abe5f547ad3b8f84d"}
{"build": "true","dependencies": {"esy-libffi": "esy-ocaml/libffi#c61127dba57b18713039ab9c1892c9f2563e280c"}}
{"build": "true","dependencies": {"esy-m4": "esy-packages/esy-m4#c7cf0ac9221be2b1f9d90e83559ca08397a629e7"}}
{"build": [["pkg-config","--help"]],"dependencies": {"yarn-pkg-config": "esy-ocaml/yarn-pkg-config#db3a0b63883606dd57c54a7158d560d6cba8cd79"}}
{"dependencies": {"@esy-ocaml/libffi": "3.2.10"}}
{"exportedEnv": {"CAML_LD_LIBRARY_PATH": {"val": "#{self.lib / 'ctypes' : $CAML_LD_LIBRARY_PATH}","scope": "global"}}}
diff --git a/src/Makefile b/src/Makefileindex 8ad0e2c..d41d63c 100644--- a/src/Makefile+++ b/src/Makefile@@ -1,16 +1,16 @@-OCAMLC=ocamlc-OCAMLOPT=ocamlopt-OCAMLDEP=ocamldep-OCAMLMKLIB=ocamlmklib-OCAMLFIND=ocamlfind+OCAMLC=$(shell which ocamlc)+OCAMLOPT=$(shell which ocamlopt)+OCAMLDEP=$(shell which ocamldep)+OCAMLMKLIB=$(shell which ocamlmklib)+OCAMLFIND=$(shell which ocamlfind)INSTALL_DATA=install -m 644INSTALL_DLL=installINSTALL_DIR=install -dSTDLIBDIR=$(shell $(OCAMLC) -where)DESTDIR ?=-include $(STDLIBDIR)/Makefile.config+include $(STDLIBDIR)/Makefile.configifeq "$(filter i386 amd64 arm64 power,$(ARCH))" ""# Unsupported architectureBNG_ARCH=generic@@ -86,14 +86,14 @@ endifVERSION=$(shell sed -ne 's/^ *version *: *"\([^"]*\)".*$$/\1/p' ../num.opam)install:- $(INSTALL_DIR) $(DESTDIR)$(STDLIBDIR)+ $(INSTALL_DIR) $(LIBDIR)sed -e 's/%%VERSION%%/$(VERSION)/g' META.in > META$(OCAMLFIND) install num METArm -f META- $(INSTALL_DATA) $(TOINSTALL) $(DESTDIR)$(STDLIBDIR)+ $(INSTALL_DATA) $(TOINSTALL) $(LIBDIR)ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"- $(INSTALL_DIR) $(DESTDIR)$(STDLIBDIR)/stublibs- $(INSTALL_DLL) $(TOINSTALL_STUBS) $(DESTDIR)$(STDLIBDIR)/stublibs+ $(INSTALL_DIR) $(LIBDIR)/stublibs+ $(INSTALL_DLL) $(TOINSTALL_STUBS) $(LIBDIR)/stublibsendiffindlib-install:@@ -105,9 +105,9 @@ findlib-uninstall:$(OCAMLFIND) remove numuninstall: findlib-uninstall- cd $(DESTDIR)$(STDLIBDIR) && rm -f $(TOINSTALL)+ cd $(LIBDIR) && rm -f $(TOINSTALL)ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"- cd $(DESTDIR)$(STDLIBDIR)/stublibs && rm -f $(TOINSTALL_STUBS)+ cd $(LIBDIR)/stublibs && rm -f $(TOINSTALL_STUBS)endifclean:
{"buildsInSource": true,"build": [["make"]],"install": [["make","LIBDIR=#{self.install / 'lib'}","findlib-install"]],"exportedEnv": {"CAML_LD_LIBRARY_PATH": {"val": "#{self.install / 'lib' / 'num' : $CAML_LD_LIBRARY_PATH}","scope": "global"}},"dependencies": {"ocaml": "*","@opam/ocamlfind": "*"}}
--- ./Makefile+++ ./Makefile@@ -213,7 +213,7 @@rm -f man/ocamlbuild.1man/options_man.byte: src/ocamlbuild_pack.cmo- $(OCAMLC) $^ -I src man/options_man.ml -o man/options_man.byte+ $(OCAMLC) -I +unix unix.cma $^ -I src man/options_man.ml -o man/options_man.byteclean::rm -f man/options_man.cm*--- ./src/command.ml+++ ./src/command.ml@@ -148,9 +148,10 @@let self = string_of_command_spec_with_calls call_with_tags call_with_target resolve_virtuals inlet b = Buffer.create 256 in(* The best way to prevent bash from switching to its windows-style- * quote-handling is to prepend an empty string before the command name. *)+ * quote-handling is to prepend an empty string before the command name.+ * space seems to work, too - and the ouput is nicer *)if Sys.os_type = "Win32" then- Buffer.add_string b "''";+ Buffer.add_char b ' ';let first = ref true inlet put_space () =if !first then@@ -260,7 +261,7 @@let execute_many ?(quiet=false) ?(pretend=false) cmds =add_parallel_stat (List.length cmds);- let degraded = !*My_unix.is_degraded || Sys.os_type = "Win32" in+ let degraded = !*My_unix.is_degraded inlet jobs = !jobs inif jobs < 0 then invalid_arg "jobs < 0";let max_jobs = if jobs = 0 then None else Some jobs in--- ./src/findlib.ml+++ ./src/findlib.ml@@ -66,9 +66,6 @@(fun command -> lexer & Lexing.from_string & run_and_read command)command-let run_and_read command =- Printf.ksprintf run_and_read command-let rec query name =tryHashtbl.find packages name@@ -135,7 +132,8 @@with Not_found -> slet list () =- List.map before_space (split_nl & run_and_read "%s list" ocamlfind)+ let cmd = Shell.quote_filename_if_needed ocamlfind ^ " list" in+ List.map before_space (split_nl & run_and_read cmd)(* The closure algorithm is easy because the dependencies are already closedand sorted for each package. We only have to make the union. We could also--- ./src/main.ml+++ ./src/main.ml@@ -162,6 +162,9 @@Tags.mem "traverse" tags|| List.exists (Pathname.is_prefix path_name) !Options.include_dirs|| List.exists (Pathname.is_prefix path_name) target_dirs)+ && ((* beware: !Options.build_dir is an absolute directory *)+ Pathname.normalize !Options.build_dir+ <> Pathname.normalize (Pathname.pwd/path_name))endendend--- ./src/my_std.ml+++ ./src/my_std.ml@@ -271,13 +271,107 @@try Array.iter (fun x -> if x = basename then raise Exit) a; falsewith Exit -> true+let command_plain = function+| [| |] -> 0+| margv ->+ let rec waitpid a b =+ match Unix.waitpid a b with+ | exception (Unix.Unix_error(Unix.EINTR,_,_)) -> waitpid a b+ | x -> x+ in+ let pid = Unix.(create_process margv.(0) margv stdin stdout stderr) in+ let pid', process_status = waitpid [] pid in+ assert (pid = pid');+ match process_status with+ | Unix.WEXITED n -> n+ | Unix.WSIGNALED _ -> 2 (* like OCaml's uncaught exceptions *)+ | Unix.WSTOPPED _ -> 127++(* can't use Lexers because of circular dependency *)+let split_path_win str =+ let rec aux pos =+ try+ let i = String.index_from str pos ';' in+ let len = i - pos in+ if len = 0 then+ aux (succ i)+ else+ String.sub str pos (i - pos) :: aux (succ i)+ with Not_found | Invalid_argument _ ->+ let len = String.length str - pos in+ if len = 0 then [] else [String.sub str pos len]+ in+ aux 0++let windows_shell = lazy begin+ let rec iter = function+ | [] -> [| "bash.exe" ; "--norc" ; "--noprofile" |]+ | hd::tl ->+ let dash = Filename.concat hd "dash.exe" in+ if Sys.file_exists dash then [|dash|] else+ let bash = Filename.concat hd "bash.exe" in+ if Sys.file_exists bash = false then iter tl else+ (* if sh.exe and bash.exe exist in the same dir, choose sh.exe *)+ let sh = Filename.concat hd "sh.exe" in+ if Sys.file_exists sh then [|sh|] else [|bash ; "--norc" ; "--noprofile"|]+ in+ split_path_win (try Sys.getenv "PATH" with Not_found -> "") |> iter+end++let prep_windows_cmd cmd =+ (* workaround known ocaml bug, remove later *)+ if String.contains cmd '\t' && String.contains cmd ' ' = false then+ " " ^ cmd+ else+ cmd++let run_with_shell = function+| "" -> 0+| cmd ->+ let cmd = prep_windows_cmd cmd in+ let shell = Lazy.force windows_shell in+ let qlen = Filename.quote cmd |> String.length in+ (* old versions of dash had problems with bs *)+ try+ if qlen < 7_900 then+ command_plain (Array.append shell [| "-ec" ; cmd |])+ else begin+ (* it can still work, if the called command is a cygwin tool *)+ let ch_closed = ref false in+ let file_deleted = ref false in+ let fln,ch =+ Filename.open_temp_file+ ~mode:[Open_binary]+ "ocamlbuildtmp"+ ".sh"+ in+ try+ let f_slash = String.map ( fun x -> if x = '\\' then '/' else x ) fln in+ output_string ch cmd;+ ch_closed:= true;+ close_out ch;+ let ret = command_plain (Array.append shell [| "-e" ; f_slash |]) in+ file_deleted:= true;+ Sys.remove fln;+ ret+ with+ | x ->+ if !ch_closed = false then+ close_out_noerr ch;+ if !file_deleted = false then+ (try Sys.remove fln with _ -> ());+ raise x+ end+ with+ | (Unix.Unix_error _) as x ->+ (* Sys.command doesn't raise an exception, so run_with_shell also won't+ raise *)+ Printexc.to_string x ^ ":" ^ cmd |> prerr_endline;+ 1+let sys_command =- match Sys.os_type with- | "Win32" -> fun cmd ->- if cmd = "" then 0 else- let cmd = "bash --norc -c " ^ Filename.quote cmd in- Sys.command cmd- | _ -> fun cmd -> if cmd = "" then 0 else Sys.command cmd+ if Sys.win32 then run_with_shell+ else fun cmd -> if cmd = "" then 0 else Sys.command cmd(* FIXME warning fix and use Filename.concat *)let filename_concat x y =--- ./src/my_std.mli+++ ./src/my_std.mli@@ -69,3 +69,6 @@val split_ocaml_version : (int * int * int * string) option(** (major, minor, patchlevel, rest) *)++val windows_shell : string array Lazy.t+val prep_windows_cmd : string -> string--- ./src/ocamlbuild_executor.ml+++ ./src/ocamlbuild_executor.ml@@ -34,6 +34,8 @@job_stdin : out_channel;job_stderr : in_channel;job_buffer : Buffer.t;+ job_pid : int;+ job_tmp_file: string option;mutable job_dying : bool;};;@@ -76,6 +78,61 @@inloop 0;;++let open_process_full_win cmd env =+ let (in_read, in_write) = Unix.pipe () in+ let (out_read, out_write) = Unix.pipe () in+ let (err_read, err_write) = Unix.pipe () in+ Unix.set_close_on_exec in_read;+ Unix.set_close_on_exec out_write;+ Unix.set_close_on_exec err_read;+ let inchan = Unix.in_channel_of_descr in_read in+ let outchan = Unix.out_channel_of_descr out_write in+ let errchan = Unix.in_channel_of_descr err_read in+ let shell = Lazy.force Ocamlbuild_pack.My_std.windows_shell in+ let test_cmd =+ String.concat " " (List.map Filename.quote (Array.to_list shell)) ^+ "-ec " ^+ Filename.quote (Ocamlbuild_pack.My_std.prep_windows_cmd cmd) in+ let argv,tmp_file =+ if String.length test_cmd < 7_900 then+ Array.append+ shell+ [| "-ec" ; Ocamlbuild_pack.My_std.prep_windows_cmd cmd |],None+ else+ let fln,ch = Filename.open_temp_file ~mode:[Open_binary] "ocamlbuild" ".sh" in+ output_string ch (Ocamlbuild_pack.My_std.prep_windows_cmd cmd);+ close_out ch;+ let fln' = String.map (function '\\' -> '/' | c -> c) fln in+ Array.append+ shell+ [| "-c" ; fln' |], Some fln in+ let pid =+ Unix.create_process_env argv.(0) argv env out_read in_write err_write in+ Unix.close out_read;+ Unix.close in_write;+ Unix.close err_write;+ (pid, inchan, outchan, errchan,tmp_file)++let close_process_full_win (pid,inchan, outchan, errchan, tmp_file) =+ let delete tmp_file =+ match tmp_file with+ | None -> ()+ | Some x -> try Sys.remove x with Sys_error _ -> () in+ let tmp_file_deleted = ref false in+ try+ close_in inchan;+ close_out outchan;+ close_in errchan;+ let res = snd(Unix.waitpid [] pid) in+ tmp_file_deleted := true;+ delete tmp_file;+ res+ with+ | x when tmp_file <> None && !tmp_file_deleted = false ->+ delete tmp_file;+ raise x+(* ***)(*** execute *)(* XXX: Add test for non reentrancy *)@@ -130,10 +187,16 @@(*** add_job *)let add_job cmd rest result id =(*display begin fun oc -> fp oc "Job %a is %s\n%!" print_job_id id cmd; end;*)- let (stdout', stdin', stderr') = open_process_full cmd env in+ let (pid,stdout', stdin', stderr', tmp_file) =+ if Sys.win32 then open_process_full_win cmd env else+ let a,b,c = open_process_full cmd env in+ -1,a,b,c,None+ inincr jobs_active;- set_nonblock (doi stdout');- set_nonblock (doi stderr');+ if not Sys.win32 then (+ set_nonblock (doi stdout');+ set_nonblock (doi stderr');+ );let job ={ job_id = id;job_command = cmd;@@ -143,7 +206,9 @@job_stdin = stdin';job_stderr = stderr';job_buffer = Buffer.create 1024;- job_dying = false }+ job_dying = false;+ job_tmp_file = tmp_file;+ job_pid = pid }inoutputs := FDM.add (doi stdout') job (FDM.add (doi stderr') job !outputs);jobs := JS.add job !jobs;@@ -199,6 +264,7 @@tryread fd u 0 (Bytes.length u)with+ | Unix.Unix_error(Unix.EPIPE,_,_) when Sys.win32 -> 0| Unix.Unix_error(e,_,_) ->let msg = error_message e indisplay (fun oc -> fp oc@@ -241,14 +307,19 @@decr jobs_active;(* PR#5371: we would get EAGAIN below otherwise *)- clear_nonblock (doi job.job_stdout);- clear_nonblock (doi job.job_stderr);-+ if not Sys.win32 then (+ clear_nonblock (doi job.job_stdout);+ clear_nonblock (doi job.job_stderr);+ );do_read ~loop:true (doi job.job_stdout) job;do_read ~loop:true (doi job.job_stderr) job;outputs := FDM.remove (doi job.job_stdout) (FDM.remove (doi job.job_stderr) !outputs);jobs := JS.remove job !jobs;- let status = close_process_full (job.job_stdout, job.job_stdin, job.job_stderr) in+ let status =+ if Sys.win32 then+ close_process_full_win (job.job_pid, job.job_stdout, job.job_stdin, job.job_stderr, job.job_tmp_file)+ else+ close_process_full (job.job_stdout, job.job_stdin, job.job_stderr) inlet shown = ref false in--- ./src/ocamlbuild_unix_plugin.ml+++ ./src/ocamlbuild_unix_plugin.ml@@ -48,12 +48,22 @@endlet run_and_open s kont =+ let s_orig = s in+ let s =+ (* Be consistent! My_unix.run_and_open uses My_std.sys_command and+ sys_command uses bash. *)+ if Sys.win32 = false then s else+ let l = match Lazy.force My_std.windows_shell |> Array.to_list with+ | hd::tl -> (Filename.quote hd)::tl+ | _ -> assert false in+ "\"" ^ (String.concat " " l) ^ " -ec " ^ Filename.quote (" " ^ s) ^ "\""+ inlet ic = Unix.open_process_in s inlet close () =match Unix.close_process_in ic with| Unix.WEXITED 0 -> ()| Unix.WEXITED _ | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->- failwith (Printf.sprintf "Error while running: %s" s) in+ failwith (Printf.sprintf "Error while running: %s" s_orig) inlet res = trykont icwith e -> (close (); raise e)--- ./src/options.ml+++ ./src/options.ml@@ -174,11 +174,24 @@build_dir := Filename.concat (Sys.getcwd ()) selsebuild_dir := s++let slashify =+ if Sys.win32 then fun p -> String.map (function '\\' -> '/' | x -> x) p+ else fun p ->p++let sb () =+ match Sys.os_type with+ | "Win32" ->+ (try set_binary_mode_out stdout true with _ -> ());+ | _ -> ()++let spec = ref (let print_version () =+ sb ();Printf.printf "ocamlbuild %s\n%!" Ocamlbuild_config.version; raise Exit_OKin- let print_vnum () = print_endline Ocamlbuild_config.version; raise Exit_OK in+ let print_vnum () = sb (); print_endline Ocamlbuild_config.version; raise Exit_OK inArg.align["-version", Unit print_version , " Display the version";@@ -257,8 +270,8 @@"-build-dir", String set_build_dir, "<path> Set build directory (implies no-links)";"-install-lib-dir", Set_string Ocamlbuild_where.libdir, "<path> Set the install library directory";"-install-bin-dir", Set_string Ocamlbuild_where.bindir, "<path> Set the install binary directory";- "-where", Unit (fun () -> print_endline !Ocamlbuild_where.libdir; raise Exit_OK), " Display the install library directory";- "-which", String (fun cmd -> print_endline (find_tool cmd); raise Exit_OK), "<command> Display path to the tool command";+ "-where", Unit (fun () -> sb (); print_endline (slashify !Ocamlbuild_where.libdir); raise Exit_OK), " Display the install library directory";+ "-which", String (fun cmd -> sb (); print_endline (slashify (find_tool cmd)); raise Exit_OK), "<command> Display path to the tool command";"-ocamlc", set_cmd ocamlc, "<command> Set the OCaml bytecode compiler";"-plugin-ocamlc", set_cmd plugin_ocamlc, "<command> Set the OCaml bytecode compiler \used when building myocamlbuild.ml (only)";--- ./src/pathname.ml+++ ./src/pathname.ml@@ -84,6 +84,26 @@| x :: xs -> x :: normalize_list xslet normalize x =+ let x =+ if Sys.win32 = false then+ x+ else+ let len = String.length x in+ let b = Bytes.create len in+ for i = 0 to pred len do+ match x.[i] with+ | '\\' -> Bytes.set b i '/'+ | c -> Bytes.set b i c+ done;+ if len > 1 then (+ let c1 = Bytes.get b 0 in+ let c2 = Bytes.get b 1 in+ if c2 = ':' && c1 >= 'a' && c1 <= 'z' &&+ ( len = 2 || Bytes.get b 2 = '/') then+ Bytes.set b 0 (Char.uppercase_ascii c1)+ );+ Bytes.unsafe_to_string b+ inif Glob.eval not_normal_form_re x thenlet root, paths = split x injoin root (normalize_list paths)--- ./src/shell.ml+++ ./src/shell.ml@@ -24,12 +24,26 @@| 'a'..'z' | 'A'..'Z' | '0'..'9' | '.' | '-' | '/' | '_' | ':' | '@' | '+' | ',' -> loop (pos + 1)| _ -> false inloop 0++let generic_quote quotequote s =+ let l = String.length s in+ let b = Buffer.create (l + 20) in+ Buffer.add_char b '\'';+ for i = 0 to l - 1 do+ if s.[i] = '\''+ then Buffer.add_string b quotequote+ else Buffer.add_char b s.[i]+ done;+ Buffer.add_char b '\'';+ Buffer.contents b+let unix_quote = generic_quote "'\\''"+let quote_filename_if_needed s =if is_simple_filename s then s(* We should probably be using [Filename.unix_quote] except that function* isn't exported. Users on Windows will have to live with not being able to* install OCaml into c:\o'caml. Too bad. *)- else if Sys.os_type = "Win32" then Printf.sprintf "'%s'" s+ else if Sys.os_type = "Win32" then unix_quote selse Filename.quote slet chdir dir =reset_filesys_cache ();@@ -37,7 +51,7 @@let run args target =reset_readdir_cache ();let cmd = String.concat " " (List.map quote_filename_if_needed args) in- if !*My_unix.is_degraded || Sys.os_type = "Win32" then+ if !*My_unix.is_degraded thenbeginLog.event cmd target Tags.empty;let st = sys_command cmd in
{"build": [["bash","-c","#{os == 'windows' ? 'patch -p1 < ocamlbuild-0.14.0.patch' : 'true'}"],["make","-f","configure.make","all","OCAMLBUILD_PREFIX=#{self.install}","OCAMLBUILD_BINDIR=#{self.bin}","OCAMLBUILD_LIBDIR=#{self.lib}","OCAMLBUILD_MANDIR=#{self.man}","OCAMLBUILD_NATIVE=true","OCAMLBUILD_NATIVE_TOOLS=true"],["make","check-if-preinstalled","all","#{os == 'windows' ? 'install' : 'opam-install'}"]]}
--- ./Makefile+++ ./Makefile@@ -57,16 +57,16 @@cat findlib.conf.in | \$(SH) tools/patch '@SITELIB@' '$(OCAML_SITELIB)' >findlib.confif ./tools/cmd_from_same_dir ocamlc; then \- echo 'ocamlc="ocamlc.opt"' >>findlib.conf; \+ echo 'ocamlc="ocamlc.opt$(EXEC_SUFFIX)"' >>findlib.conf; \fiif ./tools/cmd_from_same_dir ocamlopt; then \- echo 'ocamlopt="ocamlopt.opt"' >>findlib.conf; \+ echo 'ocamlopt="ocamlopt.opt$(EXEC_SUFFIX)"' >>findlib.conf; \fiif ./tools/cmd_from_same_dir ocamldep; then \- echo 'ocamldep="ocamldep.opt"' >>findlib.conf; \+ echo 'ocamldep="ocamldep.opt$(EXEC_SUFFIX)"' >>findlib.conf; \fiif ./tools/cmd_from_same_dir ocamldoc; then \- echo 'ocamldoc="ocamldoc.opt"' >>findlib.conf; \+ echo 'ocamldoc="ocamldoc.opt$(EXEC_SUFFIX)"' >>findlib.conf; \fi.PHONY: install-doc--- ./src/findlib/findlib_config.mlp+++ ./src/findlib/findlib_config.mlp@@ -24,3 +24,5 @@| "MacOS" -> "" (* don't know *)| _ -> failwith "Unknown Sys.os_type";;++let exec_suffix = "@EXEC_SUFFIX@";;--- ./src/findlib/findlib.ml+++ ./src/findlib/findlib.ml@@ -28,15 +28,20 @@let conf_ldconf = ref "";;let conf_ignore_dups_in = ref ([] : string list);;-let ocamlc_default = "ocamlc";;-let ocamlopt_default = "ocamlopt";;-let ocamlcp_default = "ocamlcp";;-let ocamloptp_default = "ocamloptp";;-let ocamlmklib_default = "ocamlmklib";;-let ocamlmktop_default = "ocamlmktop";;-let ocamldep_default = "ocamldep";;-let ocamlbrowser_default = "ocamlbrowser";;-let ocamldoc_default = "ocamldoc";;+let add_exec str =+ match Findlib_config.exec_suffix with+ | "" -> str+ | a -> str ^ a ;;+let ocamlc_default = add_exec "ocamlc";;+let ocamlopt_default = add_exec "ocamlopt";;+let ocamlcp_default = add_exec "ocamlcp";;+let ocamloptp_default = add_exec "ocamloptp";;+let ocamlmklib_default = add_exec "ocamlmklib";;+let ocamlmktop_default = add_exec "ocamlmktop";;+let ocamldep_default = add_exec "ocamldep";;+let ocamlbrowser_default = add_exec "ocamlbrowser";;+let ocamldoc_default = add_exec "ocamldoc";;+let init_manually--- ./src/findlib/fl_package_base.ml+++ ./src/findlib/fl_package_base.ml@@ -133,7 +133,15 @@List.find (fun def -> def.def_var = "exists_if") p.package_defs inlet files = Fl_split.in_words def.def_value inList.exists- (fun file -> Sys.file_exists (Filename.concat d' file))+ (fun file ->+ let fln = Filename.concat d' file in+ let e = Sys.file_exists fln in+ (* necessary for ppx executables *)+ if e || Sys.os_type <> "Win32" || Filename.check_suffix fln ".exe" then+ e+ else+ Sys.file_exists (fln ^ ".exe")+ )fileswith Not_found -> true in--- ./src/findlib/fl_split.ml+++ ./src/findlib/fl_split.ml@@ -126,10 +126,17 @@| '/' | '\\' -> true| _ -> false inlet norm_dir_win() =- if l >= 1 && s.[0] = '/' then- Buffer.add_char b '\\' else Buffer.add_char b s.[0];- if l >= 2 && s.[1] = '/' then- Buffer.add_char b '\\' else Buffer.add_char b s.[1];+ if l >= 1 then (+ if s.[0] = '/' then+ Buffer.add_char b '\\'+ else+ Buffer.add_char b s.[0] ;+ if l >= 2 then+ if s.[1] = '/' then+ Buffer.add_char b '\\'+ else+ Buffer.add_char b s.[1];+ );for k = 2 to l - 1 dolet c = s.[k] inif is_slash c then (--- ./src/findlib/frontend.ml+++ ./src/findlib/frontend.ml@@ -31,10 +31,18 @@elseSys_error (arg ^ ": " ^ Unix.error_message code)+let is_win = Sys.os_type = "Win32"++let () =+ match Findlib_config.system with+ | "win32" | "win64" | "mingw" | "cygwin" | "mingw64" | "cygwin64" ->+ (try set_binary_mode_out stdout true with _ -> ());+ (try set_binary_mode_out stderr true with _ -> ());+ | _ -> ()let slashify s =match Findlib_config.system with- | "mingw" | "mingw64" | "cygwin" ->+ | "win32" | "win64" | "mingw" | "cygwin" | "mingw64" | "cygwin64" ->let b = Buffer.create 80 inString.iter(function@@ -49,7 +57,7 @@let out_path ?(prefix="") s =match Findlib_config.system with- | "mingw" | "mingw64" | "cygwin" ->+ | "win32" | "win64" | "mingw" | "mingw64" | "cygwin" ->let u = slashify s inprefix ^(if String.contains u ' ' then@@ -273,11 +281,9 @@let identify_dir d =- match Sys.os_type with- | "Win32" ->- failwith "identify_dir" (* not available *)- | _ ->- let s = Unix.stat d in+ if is_win then+ failwith "identify_dir"; (* not available *)+ let s = Unix.stat d in(s.Unix.st_dev, s.Unix.st_ino);;@@ -459,6 +465,96 @@)packages+let rewrite_cmd s =+ if s = "" || not is_win then+ s+ else+ let s =+ let l = String.length s in+ let b = Buffer.create l in+ for i = 0 to pred l do+ match s.[i] with+ | '/' -> Buffer.add_char b '\\'+ | x -> Buffer.add_char b x+ done;+ Buffer.contents b+ in+ if (Filename.is_implicit s && String.contains s '\\' = false) ||+ Filename.check_suffix (String.lowercase s) ".exe" then+ s+ else+ let s' = s ^ ".exe" in+ if Sys.file_exists s' then+ s'+ else+ s++let rewrite_cmd s =+ if s = "" || not is_win then s else+ let s =+ let l = String.length s in+ let b = Buffer.create l in+ for i = 0 to pred l do+ match s.[i] with+ | '/' -> Buffer.add_char b '\\'+ | x -> Buffer.add_char b x+ done;+ Buffer.contents b+ in+ if (Filename.is_implicit s && String.contains s '\\' = false) ||+ Filename.check_suffix (String.lowercase s) ".exe" then+ s+ else+ let s' = s ^ ".exe" in+ if Sys.file_exists s' then+ s'+ else+ s++let rewrite_pp cmd =+ if not is_win then cmd else+ let module T = struct exception Keep end in+ let is_whitespace = function+ | ' ' | '\011' | '\012' | '\n' | '\r' | '\t' -> true+ | _ -> false in+ (* characters that triggers special behaviour (cmd.exe, not unix shell) *)+ let is_unsafe_char = function+ | '(' | ')' | '%' | '!' | '^' | '<' | '>' | '&' -> true+ | _ -> false in+ let len = String.length cmd in+ let buf = Buffer.create (len + 4) in+ let buf_cmd = Buffer.create len in+ let rec iter_ws i =+ if i >= len then () else+ let cur = cmd.[i] in+ if is_whitespace cur then (+ Buffer.add_char buf cur;+ iter_ws (succ i)+ )+ else+ iter_cmd i+ and iter_cmd i =+ if i >= len then add_buf_cmd () else+ let cur = cmd.[i] in+ if is_unsafe_char cur || cur = '"' || cur = '\'' then+ raise T.Keep;+ if is_whitespace cur then (+ add_buf_cmd ();+ Buffer.add_substring buf cmd i (len - i)+ )+ else (+ Buffer.add_char buf_cmd cur;+ iter_cmd (succ i)+ )+ and add_buf_cmd () =+ if Buffer.length buf_cmd > 0 then+ Buffer.add_string buf (rewrite_cmd (Buffer.contents buf_cmd))+ in+ try+ iter_ws 0;+ Buffer.contents buf+ with+ | T.Keep -> cmdlet process_pp_spec syntax_preds packages pp_opts =(* Returns: pp_command *)@@ -549,7 +645,7 @@None -> []| Some cmd ->["-pp";- cmd ^ " " ^+ (rewrite_cmd cmd) ^ " " ^String.concat " " (List.map Filename.quote pp_i_options) ^ " " ^String.concat " " (List.map Filename.quote pp_archives) ^ " " ^String.concat " " (List.map Filename.quote pp_opts)]@@ -625,9 +721,11 @@intrylet preprocessor =+ rewrite_cmd (resolve_path~base ~explicit:true- (package_property predicates pname "ppx") in+ (package_property predicates pname "ppx") )+ in["-ppx"; String.concat " " (preprocessor :: options)]with Not_found -> [])@@ -895,6 +993,14 @@switch (e.g. -L<path> instead of -L <path>)*)+(* We may need to remove files on which we do not have complete control.+ On Windows, removing a read-only file fails so try to change the+ mode of the file first. *)+let remove_file fname =+ try Sys.remove fname+ with Sys_error _ when is_win ->+ (try Unix.chmod fname 0o666 with Unix.Unix_error _ -> ());+ Sys.remove fnamelet ocamlc which () =@@ -1022,9 +1128,12 @@"-intf",Arg.String (fun s -> pass_files := !pass_files @ [ Intf(slashify s) ]);-+"-pp",- Arg.String (fun s -> pp_specified := true; add_spec_fn "-pp" s);+ Arg.String (fun s -> pp_specified := true; add_spec_fn "-pp" (rewrite_pp s));++ "-ppx",+ Arg.String (fun s -> add_spec_fn "-ppx" (rewrite_pp s));"-thread",Arg.Unit (fun _ -> threads := threads_default);@@ -1237,7 +1346,7 @@withany ->close_out initl;- Sys.remove initl_file_name;+ remove_file initl_file_name;raise anyend;@@ -1245,9 +1354,9 @@at_exit(fun () ->let tr f x = try f x with _ -> () in- tr Sys.remove initl_file_name;- tr Sys.remove (Filename.chop_extension initl_file_name ^ ".cmi");- tr Sys.remove (Filename.chop_extension initl_file_name ^ ".cmo");+ tr remove_file initl_file_name;+ tr remove_file (Filename.chop_extension initl_file_name ^ ".cmi");+ tr remove_file (Filename.chop_extension initl_file_name ^ ".cmo"););let exclude_list = [ stdlibdir; threads_dir; vmthreads_dir ] in@@ -1493,7 +1602,9 @@[ "-v", Arg.Unit (fun () -> verbose := Verbose);"-pp", Arg.String (fun s ->pp_specified := true;- options := !options @ ["-pp"; s]);+ options := !options @ ["-pp"; rewrite_pp s]);+ "-ppx", Arg.String (fun s ->+ options := !options @ ["-ppx"; rewrite_pp s]);]))@@ -1672,7 +1783,9 @@Arg.String (fun s -> add_spec_fn "-I" (slashify (resolve_path s)));"-pp", Arg.String (fun s -> pp_specified := true;- add_spec_fn "-pp" s);+ add_spec_fn "-pp" (rewrite_pp s));+ "-ppx", Arg.String (fun s -> add_spec_fn "-ppx" (rewrite_pp s));+]))@@ -1830,7 +1943,10 @@output_string ch_out append;close_out ch_out;close_in ch_in;- Unix.utimes outpath s.Unix.st_mtime s.Unix.st_mtime;+ (try Unix.utimes outpath s.Unix.st_mtime s.Unix.st_mtime+ with Unix.Unix_error(e,_,_) ->+ prerr_endline("Warning: setting utimes for " ^ outpath+ ^ ": " ^ Unix.error_message e));prerr_endline("Installed " ^ outpath);with@@ -1882,6 +1998,8 @@Unix.openfile (Filename.concat dir owner_file) [Unix.O_RDONLY] 0 inlet f =Unix.in_channel_of_descr fd in+ if is_win then+ set_binary_mode_in f false;trylet line = input_line f inlet is_my_file = (line = pkg) in@@ -2208,7 +2326,7 @@let lines = read_ldconf !ldconf inlet dlldir_norm = Fl_split.norm_dir dlldir inlet dlldir_norm_lc = string_lowercase_ascii dlldir_norm in- let ci_filesys = (Sys.os_type = "Win32") in+ let ci_filesys = is_win inlet check_dir d =let d' = Fl_split.norm_dir d in(d' = dlldir_norm) ||@@ -2356,7 +2474,7 @@List.iter(fun file ->let absfile = Filename.concat dlldir file in- Sys.remove absfile;+ remove_file absfile;prerr_endline ("Removed " ^ absfile))dll_files@@ -2365,7 +2483,7 @@(* Remove the files from the package directory: *)if Sys.file_exists pkgdir then beginlet files = Sys.readdir pkgdir in- Array.iter (fun f -> Sys.remove (Filename.concat pkgdir f)) files;+ Array.iter (fun f -> remove_file (Filename.concat pkgdir f)) files;Unix.rmdir pkgdir;prerr_endline ("Removed " ^ pkgdir)end@@ -2415,7 +2533,9 @@let print_configuration() =+ let sl = slashify inlet dir s =+ let s = sl s inif Sys.file_exists s thenselse@@ -2453,27 +2573,27 @@if md = "" then "the corresponding package directories" else dir md);Printf.printf "The standard library is assumed to reside in:\n %s\n"- (Findlib.ocaml_stdlib());+ (sl (Findlib.ocaml_stdlib()));Printf.printf "The ld.conf file can be found here:\n %s\n"- (Findlib.ocaml_ldconf());+ (sl (Findlib.ocaml_ldconf()));flush stdout| Some "conf" ->- print_endline (Findlib.config_file())+ print_endline (sl (Findlib.config_file()))| Some "path" ->- List.iter print_endline (Findlib.search_path())+ List.iter ( fun x -> print_endline (sl x)) (Findlib.search_path())| Some "destdir" ->- print_endline (Findlib.default_location())+ print_endline ( sl (Findlib.default_location()))| Some "metadir" ->- print_endline (Findlib.meta_directory())+ print_endline ( sl (Findlib.meta_directory()))| Some "metapath" ->let mdir = Findlib.meta_directory() inlet ddir = Findlib.default_location() in- print_endline- (if mdir <> "" then mdir ^ "/META.%s" else ddir ^ "/%s/META")+ print_endline ( sl+ (if mdir <> "" then mdir ^ "/META.%s" else ddir ^ "/%s/META"))| Some "stdlib" ->- print_endline (Findlib.ocaml_stdlib())+ print_endline ( sl (Findlib.ocaml_stdlib()))| Some "ldconf" ->- print_endline (Findlib.ocaml_ldconf())+ print_endline ( sl (Findlib.ocaml_ldconf()))| _ ->assert false;;@@ -2481,7 +2601,7 @@let ocamlcall pkg cmd =let dir = package_directory pkg in- let path = Filename.concat dir cmd in+ let path = rewrite_cmd (Filename.concat dir cmd) inbegintry Unix.access path [ Unix.X_OK ]with@@ -2647,6 +2767,10 @@| Sys_error f ->prerr_endline ("ocamlfind: " ^ f);exit 2+ | Unix.Unix_error (e, fn, f) ->+ prerr_endline ("ocamlfind: " ^ fn ^ " " ^ f+ ^ ": " ^ Unix.error_message e);+ exit 2| Findlib.No_such_package(pkg,info) ->prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' not found" ^(if info <> "" then " - " ^ info else ""));--- ./src/findlib/Makefile+++ ./src/findlib/Makefile@@ -90,6 +90,7 @@cat findlib_config.mlp | \$(SH) $(TOP)/tools/patch '@CONFIGFILE@' '$(OCAMLFIND_CONF)' | \$(SH) $(TOP)/tools/patch '@STDLIB@' '$(OCAML_CORE_STDLIB)' | \+ $(SH) $(TOP)/tools/patch '@EXEC_SUFFIX@' '$(EXEC_SUFFIX)' | \sed -e 's;@AUTOLINK@;$(OCAML_AUTOLINK);g' \-e 's;@SYSTEM@;$(SYSTEM);g' \>findlib_config.ml
{"build": [["bash","-c","#{os == 'windows' ? 'patch -p1 < findlib-1.8.1.patch' : 'true'}"],["./configure","-bindir","#{self.bin}","-sitelib","#{self.lib}","-mandir","#{self.man}","-config","#{self.lib}/findlib.conf","-no-custom","-no-topfind"],["make","all"],["make","opt"]],"install": [["make","install"],["install","-m","0755","ocaml-stub","#{self.bin}/ocaml"],["mkdir","-p","#{self.toplevel}"],["install","-m","0644","src/findlib/topfind","#{self.toplevel}/topfind"]],"exportedEnv": {"OCAML_TOPLEVEL_PATH": {"val": "#{self.toplevel}","scope": "global"}}}
module C = Configurator.V1let () =C.main ~name:"opus-pkg-config" (fun c ->let default = { C.Pkg_config.libs = [ "-lopus" ]; cflags = [] } inlet conf =match C.Pkg_config.get c with| None -> default| Some pc -> (match C.Pkg_config.query pc ~package:"opus" with| None -> default| Some deps -> deps)inC.Flags.write_sexp "c_flags.sexp" conf.cflags;C.Flags.write_sexp "c_library_flags.sexp" conf.libs;C.Flags.write_lines "c_flags.lines" conf.cflags)
(executable(name discover)(libraries dune.configurator))
(rule(targets c_flags.sexp c_library_flags.sexp c_flags.lines)(deps(:discover config/discover.exe))(action(run %{discover})))(rule(targets opus.ml opus_stubs.c)(deps(:gen opus.c.ml)c_flags.lines)(action(chdir%{workspace_root}(run%{bin:ppx_cstubs}%{gen}-pkgctypes-o%{targets}--%{read-lines:c_flags.lines}))))(library(name opus)(public_name opus)(wrapped false)(private_modules(:standard \ opus))(libraries unix ctypes ctypes.foreign ppx_cstubs)(preprocess(pps ppx_cstubs.merlin))(foreign_stubs(language c)(names opus_stubs)(flags(:standard(:include c_flags.sexp))))(c_library_flags(:standard(:include c_library_flags.sexp))))
let%c () = header {|#include <opus.h>#include <opus_multistream.h>|}open Ctypesmodule C = structlet app_VOIP = [%c constant "OPUS_APPLICATION_VOIP" camlint]let app_AUDIO = [%c constant "OPUS_APPLICATION_AUDIO" camlint]let app_RESTRICTED_LOWEDELAY =[%c constant "OPUS_APPLICATION_RESTRICTED_LOWDELAY" camlint]let _AUTO = [%c constant "OPUS_AUTO" camlint]let signal_VOICE = [%c constant "OPUS_SIGNAL_VOICE" camlint]let signal_MUSIC = [%c constant "OPUS_SIGNAL_MUSIC" camlint]let br_MAX = [%c constant "OPUS_BITRATE_MAX" camlint]let ctl_SET_APPLICATION_REQUEST = [%c constant "OPUS_SET_APPLICATION_REQUEST" camlint]let ctl_GET_APPLICATION_REQUEST = [%c constant "OPUS_GET_APPLICATION_REQUEST" camlint]let ctl_SET_BITRATE_REQUEST = [%c constant "OPUS_SET_BITRATE_REQUEST" camlint]let ctl_GET_BITRATE_REQUEST = [%c constant "OPUS_GET_BITRATE_REQUEST" camlint]let ctl_SET_MAX_BANDWIDTH_REQUEST = [%c constant "OPUS_SET_MAX_BANDWIDTH_REQUEST" camlint]let ctl_GET_MAX_BANDWIDTH_REQUEST = [%c constant "OPUS_GET_MAX_BANDWIDTH_REQUEST" camlint]let ctl_SET_VBR_REQUEST = [%c constant "OPUS_SET_VBR_REQUEST" camlint]let ctl_GET_VBR_REQUEST = [%c constant "OPUS_GET_VBR_REQUEST" camlint]let ctl_SET_BANDWIDTH_REQUEST = [%c constant "OPUS_SET_BANDWIDTH_REQUEST" camlint]let ctl_GET_BANDWIDTH_REQUEST = [%c constant "OPUS_GET_BANDWIDTH_REQUEST" camlint]let ctl_SET_COMPLEXITY_REQUEST = [%c constant "OPUS_SET_COMPLEXITY_REQUEST" camlint]let ctl_GET_COMPLEXITY_REQUEST = [%c constant "OPUS_GET_COMPLEXITY_REQUEST" camlint]let ctl_SET_INBAND_FEC_REQUEST = [%c constant "OPUS_SET_INBAND_FEC_REQUEST" camlint]let ctl_GET_INBAND_FEC_REQUEST = [%c constant "OPUS_GET_INBAND_FEC_REQUEST" camlint]let ctl_SET_PACKET_LOSS_PERC_REQUEST = [%c constant "OPUS_SET_PACKET_LOSS_PERC_REQUEST" camlint]let ctl_GET_PACKET_LOSS_PERC_REQUEST = [%c constant "OPUS_GET_PACKET_LOSS_PERC_REQUEST" camlint]let ctl_SET_DTX_REQUEST = [%c constant "OPUS_SET_DTX_REQUEST" camlint]let ctl_GET_DTX_REQUEST = [%c constant "OPUS_GET_DTX_REQUEST" camlint]let ctl_SET_VBR_CONSTRAINT_REQUEST = [%c constant "OPUS_SET_VBR_CONSTRAINT_REQUEST" camlint]let ctl_GET_VBR_CONSTRAINT_REQUEST = [%c constant "OPUS_GET_VBR_CONSTRAINT_REQUEST" camlint]let ctl_SET_FORCE_CHANNELS_REQUEST = [%c constant "OPUS_SET_FORCE_CHANNELS_REQUEST" camlint]let ctl_GET_FORCE_CHANNELS_REQUEST = [%c constant "OPUS_GET_FORCE_CHANNELS_REQUEST" camlint]let ctl_SET_SIGNAL_REQUEST = [%c constant "OPUS_SET_SIGNAL_REQUEST" camlint]let ctl_GET_SIGNAL_REQUEST = [%c constant "OPUS_GET_SIGNAL_REQUEST" camlint]let ctl_GET_LOOKAHEAD_REQUEST = [%c constant "OPUS_GET_LOOKAHEAD_REQUEST" camlint]let ctl_RESET_STATE = [%c constant "OPUS_RESET_STATE" camlint]let ctl_GET_SAMPLE_RATE_REQUEST = [%c constant "OPUS_GET_SAMPLE_RATE_REQUEST" camlint]let ctl_GET_FINAL_RANGE_REQUEST = [%c constant "OPUS_GET_FINAL_RANGE_REQUEST" camlint]let ctl_GET_PITCH_REQUEST = [%c constant "OPUS_GET_PITCH_REQUEST" camlint]let ctl_SET_GAIN_REQUEST = [%c constant "OPUS_SET_GAIN_REQUEST" camlint]let ctl_GET_GAIN_REQUEST = [%c constant "OPUS_GET_GAIN_REQUEST" camlint]let ctl_SET_LSB_DEPTH_REQUEST = [%c constant "OPUS_SET_LSB_DEPTH_REQUEST" camlint]let ctl_GET_LSB_DEPTH_REQUEST = [%c constant "OPUS_GET_LSB_DEPTH_REQUEST" camlint]let ctl_GET_LAST_PACKET_DURATION_REQUEST = [%c constant "OPUS_GET_LAST_PACKET_DURATION_REQUEST" camlint]let ctl_SET_EXPERT_FRAME_DURATION_REQUEST = [%c constant "OPUS_SET_EXPERT_FRAME_DURATION_REQUEST" camlint]let ctl_GET_EXPERT_FRAME_DURATION_REQUEST = [%c constant "OPUS_GET_EXPERT_FRAME_DURATION_REQUEST" camlint]let ctl_SET_PREDICTION_DISABLED_REQUEST = [%c constant "OPUS_SET_PREDICTION_DISABLED_REQUEST" camlint]let ctl_GET_PREDICTION_DISABLED_REQUEST = [%c constant "OPUS_GET_PREDICTION_DISABLED_REQUEST" camlint]let ctl_SET_PHASE_INVERSION_DISABLED_REQUEST = [%c constant "OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST" camlint]let ctl_GET_PHASE_INVERSION_DISABLED_REQUEST = [%c constant "OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST" camlint]let ctl_GET_IN_DTX_REQUEST = [%c constant "OPUS_GET_IN_DTX_REQUEST" camlint]endmodule Error = structlet%c t = intlet _ALLOC_FAIL = [%c constant "OPUS_ALLOC_FAIL" camlint]let _INVALID_STATE = [%c constant "OPUS_INVALID_STATE" camlint]let _UNIMPLEMENTED = [%c constant "OPUS_UNIMPLEMENTED" camlint]let _INVALID_PACKET = [%c constant "OPUS_INVALID_PACKET" camlint]let _INTERNAL_ERROR = [%c constant "OPUS_INTERNAL_ERROR" camlint]let _BUFFER_TOO_SMALL = [%c constant "OPUS_BUFFER_TOO_SMALL" camlint]let _BAD_ARG = [%c constant "OPUS_BAD_ARG" camlint]let _OK = [%c constant "OPUS_OK" camlint]external to_string: t -> string = "opus_strerror"type t = [`Alloc_fail| `Invalid_state| `Unimplemented| `Invalid_packet| `Internal_error| `Buffer_too_small| `Bad_arg| `Unknown of int ]let of_int = function| e when e = _OK -> raise (Invalid_argument "not an error")| e when e = _ALLOC_FAIL -> `Alloc_fail| e when e = _INVALID_STATE -> `Invalid_state| e when e = _UNIMPLEMENTED -> `Unimplemented| e when e = _INVALID_PACKET -> `Invalid_packet| e when e = _INTERNAL_ERROR -> `Internal_error| e when e = _BUFFER_TOO_SMALL -> `Buffer_too_small| e when e = _BAD_ARG -> `Bad_arg| other -> `Unknown otherlet wrap_lazy fn = function| e when e = _OK -> Ok (fn ())| e when e = _ALLOC_FAIL -> Error `Alloc_fail| e when e = _INVALID_STATE -> Error `Invalid_state| e when e = _UNIMPLEMENTED -> Error `Unimplemented| e when e = _INVALID_PACKET -> Error `Invalid_packet| e when e = _INTERNAL_ERROR -> Error `Internal_error| e when e = _BUFFER_TOO_SMALL -> Error `Buffer_too_small| e when e = _BAD_ARG -> Error `Bad_arg| other -> Error (`Unknown other)let wrap a = wrap_lazy (fun () -> a)let to_string = function| `Alloc_fail -> to_string _ALLOC_FAIL| `Invalid_state -> to_string _INVALID_STATE| `Unimplemented -> to_string _UNIMPLEMENTED| `Invalid_packet -> to_string _INVALID_PACKET| `Internal_error -> to_string _INTERNAL_ERROR| `Buffer_too_small -> to_string _BUFFER_TOO_SMALL| `Bad_arg -> to_string _BAD_ARG| `Unknown other -> "unknown error: " ^ (string_of_int other)let show = to_stringlet pp fmt t = Format.fprintf fmt "%s" (show t)endtype nonrec 'a result = ('a, Error.t) resulttype 'a handle = unit ptrlet handle_t: 'a handle typ = ptr voidlet%c enc_handle: [`enc] handle typ = ptr voidlet%c dec_handle: [`dec] handle typ = ptr voidtype bandwidth = [| `Narrow| `Medium| `Wide| `Superwide| `Full]type framesize = [| `from_arg| `fs_2_5ms| `fs_5ms| `fs_10ms| `fs_20ms| `fs_40ms| `fs_60ms| `fs_80ms| `fs_100ms| `fs_120ms]type application =| Voip| Audio| Restricted_lowdelaymodule CTL = structexternal opus_encoder_ctl: enc_handle -> int32_t -> int32_t ptr -> Error.t = "opus_encoder_ctl"external opus_decoder_ctl: dec_handle -> int32_t -> int32_t ptr -> Error.t = "opus_decoder_ctl"type enc = [`enc]type dec = [`dec]type 'a both = [< `enc | `dec] as 'atype ('handle, 'res) t =(* generic *)| Reset_state: (_ both handle, unit) t| Get_final_range: (_ both handle, int) t| Get_bandwidth: (_ both handle, [`auto | bandwidth]) t| Get_sample_rate: (_ both handle, int) t| Set_phase_inversion_disabled: bool -> (_ both handle, unit) t| Get_phase_inversion_disabled: (_ both handle, bool) t| Get_in_DTX: (_ both handle, bool) t(* encoder *)| Set_complexity: int -> (enc handle, unit) t| Get_complexity: (enc handle, int) t| Set_bitrate: [`auto | `max | `bps of int] -> (enc handle, unit) t| Get_bitrate: (enc handle, [`auto | `max | `bps of int]) t| Set_VBR: bool -> (enc handle, unit) t| Get_VBR: (enc handle, bool) t| Set_VBR_constraint: bool -> (enc handle, unit) t| Get_VBR_constraint: (enc handle, bool) t| Set_force_channels: [`auto | `mono | `stereo] -> (enc handle, unit) t| Get_force_channels: (enc handle, [`auto | `mono | `stereo]) t| Set_max_bandwidth: bandwidth -> (enc handle, unit) t| Get_max_bandwidth: (enc handle, bandwidth) t| Set_bandwidth: [`auto | bandwidth] -> (enc handle, unit) t| Set_signal: [`auto | `voice | `music] -> (enc handle, unit) t| Get_signal: (enc handle, [`auto | `voice | `music]) t| Set_application: application -> (enc handle, unit) t| Get_application: (enc handle, application) t| Get_lookahead: (enc handle, int) t| Set_inband_FEC: bool -> (enc handle, unit) t| Get_inband_FEC: (enc handle, bool) t| Set_packet_loss_perc: int -> (enc handle, unit) t| Get_packet_loss_perc: (enc handle, int) t| Set_DTX: bool -> (enc handle, unit) t| Get_DTX: (enc handle, bool) t| Set_LSB_depth: int -> (enc handle, unit) t| Get_LSB_depth: (enc handle, int) t| Set_expert_frame_duration: framesize -> (enc handle, unit) t| Get_expert_frame_duration: (enc handle, framesize) t| Set_prediction_disabled: bool -> (enc handle, unit) t| Get_prediction_disabled: (enc handle, bool) t(* decoder *)let _code: type a b. (a, b) t -> int32 =fun t ->let o = match t with(* generic *)| Reset_state -> C.ctl_RESET_STATE| Get_final_range -> C.ctl_GET_FINAL_RANGE_REQUEST| Get_bandwidth -> C.ctl_GET_BANDWIDTH_REQUEST| Get_sample_rate -> C.ctl_GET_SAMPLE_RATE_REQUEST| Set_phase_inversion_disabled _ -> C.ctl_SET_PHASE_INVERSION_DISABLED_REQUEST| Get_phase_inversion_disabled -> C.ctl_GET_PHASE_INVERSION_DISABLED_REQUEST| Get_in_DTX -> C.ctl_GET_IN_DTX_REQUEST(* encoder *)| Set_complexity _ -> C.ctl_SET_COMPLEXITY_REQUEST| Get_complexity -> C.ctl_GET_COMPLEXITY_REQUEST| Set_bitrate _ -> C.ctl_SET_BITRATE_REQUEST| Get_bitrate -> C.ctl_GET_BITRATE_REQUEST| Set_VBR _ -> C.ctl_SET_VBR_REQUEST| Get_VBR -> C.ctl_GET_VBR_REQUEST| Set_VBR_constraint _ -> C.ctl_SET_VBR_CONSTRAINT_REQUEST| Get_VBR_constraint -> C.ctl_GET_VBR_CONSTRAINT_REQUEST| Set_force_channels _ -> C.ctl_SET_FORCE_CHANNELS_REQUEST| Get_force_channels -> C.ctl_GET_FORCE_CHANNELS_REQUEST| Set_max_bandwidth _ -> C.ctl_SET_MAX_BANDWIDTH_REQUEST| Get_max_bandwidth -> C.ctl_GET_MAX_BANDWIDTH_REQUEST| Set_bandwidth _ -> C.ctl_SET_BANDWIDTH_REQUEST| Set_signal _ -> C.ctl_SET_SIGNAL_REQUEST| Get_signal -> C.ctl_GET_SIGNAL_REQUEST| Set_application _ -> C.ctl_SET_APPLICATION_REQUEST| Get_application -> C.ctl_GET_APPLICATION_REQUEST| Get_lookahead -> C.ctl_GET_LOOKAHEAD_REQUEST| Set_inband_FEC _ -> C.ctl_SET_INBAND_FEC_REQUEST| Get_inband_FEC -> C.ctl_GET_INBAND_FEC_REQUEST| Set_packet_loss_perc _ -> C.ctl_SET_PACKET_LOSS_PERC_REQUEST| Get_packet_loss_perc -> C.ctl_GET_PACKET_LOSS_PERC_REQUEST| Set_DTX _ -> C.ctl_SET_DTX_REQUEST| Get_DTX -> C.ctl_GET_DTX_REQUEST| Set_LSB_depth _ -> C.ctl_SET_LSB_DEPTH_REQUEST| Get_LSB_depth -> C.ctl_GET_LSB_DEPTH_REQUEST| Set_expert_frame_duration _ -> C.ctl_SET_EXPERT_FRAME_DURATION_REQUEST| Get_expert_frame_duration -> C.ctl_GET_EXPERT_FRAME_DURATION_REQUEST| Set_prediction_disabled _ -> C.ctl_SET_PREDICTION_DISABLED_REQUEST| Get_prediction_disabled -> C.ctl_GET_PREDICTION_DISABLED_REQUESTinInt32.of_int olet request: type a b. ctl_fn:string -> a handle -> (a, b) t -> b result= fun ~ctl_fn handle req ->let code = _code req inmatch req with(* generic *)| Reset_state ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> returning int) infn handle code |> Error.wrap ()| Get_phase_inversion_disabled ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> ptr int32_t @-> returning int) inlet b = allocate int32_t 0l infn handle code b |> Error.wrap (match !@b with | 0l -> false | 1l -> true | _ -> assert false)(* encoder *)| Set_complexity c ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> int32_t @-> returning int) infn handle code (Int32.of_int c) |> Error.wrap ()| Get_complexity ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> ptr int32_t @-> returning int) inlet c = allocate int32_t 0l infn handle code c |> Error.wrap (Int32.to_int !@c)| Set_bitrate br ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> int32_t @-> returning int) inlet br = match br with| `auto -> C._AUTO| `max -> C.br_MAX| `bps br -> brinfn handle code (Int32.of_int br) |> Error.wrap ()| Get_bitrate ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> ptr int32_t @-> returning int) inlet br = allocate int32_t 0l infn handle code br |> Error.wrap_lazy (fun () ->match Int32.to_int !@br with| n when n = C._AUTO -> `auto| n when n = C.br_MAX -> `max| o -> `bps o)| Set_packet_loss_perc plp ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> int32_t @-> returning int) infn handle code (Int32.of_int plp) |> Error.wrap ()| Get_packet_loss_perc ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> ptr int32_t @-> returning int) inlet plp = allocate int32_t 0l infn handle code plp |> Error.wrap (Int32.to_int !@plp)| Set_signal s ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> int32_t @-> returning int) inlet s = match s with| `auto -> C._AUTO| `voice -> C.signal_VOICE| `music -> C.signal_MUSICinfn handle code (Int32.of_int s) |> Error.wrap ()| Get_signal ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> ptr int32_t @-> returning int) inlet s = allocate int32_t 0l infn handle code s|> Error.wrap_lazy (fun () ->match Int32.to_int !@s with| s when s = C._AUTO -> `auto| s when s = C.signal_VOICE -> `voice| s when s = C.signal_MUSIC -> `music| _ -> assert false)| Set_inband_FEC b ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> int32_t @-> returning int) infn handle code (Int32.of_int @@ Bool.to_int b) |> Error.wrap ()| Get_inband_FEC ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> ptr int32_t @-> returning int) inlet b = allocate int32_t 0l infn handle code b |> Error.wrap (match !@b with | 0l -> false | 1l -> true | _ -> assert false)| Set_LSB_depth d ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> int32_t @-> returning int) infn handle code (Int32.of_int d) |> Error.wrap ()| Get_LSB_depth ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> ptr int32_t @-> returning int) inlet d = allocate int32_t 0l infn handle code d |> Error.wrap (Int32.to_int !@d)| Set_DTX b ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> int32_t @-> returning int) infn handle code (Int32.of_int @@ Bool.to_int b) |> Error.wrap ()| Get_DTX ->let fn = Foreign.foreign ctl_fn (handle_t @-> int32_t @-> ptr int32_t @-> returning int) inlet b = allocate int32_t 0l infn handle code b |> Error.wrap (match !@b with | 0l -> false | 1l -> true | _ -> assert false)| _ -> assert falseendmodule BA = Bigarraymodule BA1 = Bigarray.Array1type bigstring = (char, BA.int8_unsigned_elt, BA.c_layout) BA1.ttype s16frame = (int, BA.int16_signed_elt, BA.c_layout) BA1.ttype f32frame = (int, BA.float32_elt, BA.c_layout) BA1.tmodule Encoder = structtype encoder = [`enc] handlelet%c t = ptr voidexternal opus_encoder_size: int -> int = "opus_encoder_get_size"external opus_encoder_init: t -> int32_t -> int -> int -> Error.t = "opus_encoder_init"external opus_encoder_create: int32_t -> int -> int -> Error.t ptr -> t = "opus_encoder_create"external opus_encoder_destroy: t -> void = "opus_encoder_destroy"external opus_encode: t -> pcm:int16_t ptr -> fs:int -> buf:uchar ptr -> max:int -> int = "opus_encode"external opus_encode_float: t -> pcm:float ptr -> fs:int -> buf:uchar ptr -> max:int -> int = "opus_encode_float"type t = {enc: enc;samplerate: int;channels: int;app: application;}and enc = | Own of encoder | C of encoder * gcand gc = unit ptrtype packet = [ `Packet of bigstring | `DTX ]let recommended_max_size = 4000let own = truelet _enc = function | Own e | C (e, _) -> elet create ?(samplerate=48000) ?(channels=`stereo) ?(application=Audio) () =let c = match channels with | `stereo -> 2 | `mono -> 1 inlet app = match application with| Voip -> C.app_VOIP| Audio -> C.app_AUDIO| Restricted_lowdelay -> C.app_RESTRICTED_LOWEDELAYinlet err, enc = match own with| false ->let err = allocate int (-1) inlet enc = opus_encoder_create Int32.(of_int samplerate) c app err inlet gc =allocate_n ~finalise:(fun _ -> opus_encoder_destroy enc)~count:0 voidin!@err, C (enc, gc)| true ->let enc =allocate_n ~count:(opus_encoder_size c) uchar|> coerce (ptr uchar) (ptr void)inlet err = opus_encoder_init enc Int32.(of_int samplerate) c app inerr, Own encinError.wrap enc err|> Result.map (fun enc -> {enc;samplerate;channels=c;app=application;})let size { channels; _ } = opus_encoder_size channelslet _encode_blit:type a b.t ->?pcm_off:int ->?duration:int ->(a, b, BA.c_layout) BA1.t ->?buf_off:int ->?max_size:int ->bigstring ->packet result =fun t ?(pcm_off=0) ?(duration=20) pcm?(buf_off=0) ?max_size buf ->let pcm = BA1.sub pcm pcm_off (BA1.dim pcm - pcm_off) inlet buf = BA1.sub buf buf_off (BA1.dim buf - buf_off) inlet max_size = match max_size with| Some size when size > (BA1.dim buf) ->raise (Invalid_argument "max_size is bigger than available buf space")| Some s -> s| None -> BA1.dim bufinlet fs = t.samplerate / 1000 * duration inif BA1.dim pcm < (fs * t.channels) thenraise (Invalid_argument "given pcm frame does not have enough samples");let buf_p =(bigarray_start array1 buf) |>coerce (ptr char) (ptr uchar)inlet len = match BA1.kind pcm with| BA.Int16_signed -> opus_encode (_enc t.enc) ~pcm:(bigarray_start array1 pcm) ~fs ~buf:buf_p ~max:max_size| BA.Float32 -> opus_encode_float (_enc t.enc) ~pcm:(bigarray_start array1 pcm) ~fs ~buf:buf_p ~max:max_size| _ ->print_endline "!!!FATAL!!! invalid opus pcm buffer type (must be s16 or f32)";exit (-1)inmatch len with| n when n < 0 -> Error (Error.of_int n)| n when n <= 2 -> Ok `DTX| n -> Ok (`Packet (BA1.sub buf 0 n))let encode_blit t ?pcm_off ?duration pcm ?buf_off ?max_size buf =_encode_blit t ?pcm_off ?duration pcm ?buf_off ?max_size buflet encode t ?off ?duration ?(max_size=recommended_max_size) pcm =let buf = BA1.create BA.char BA.c_layout max_size in_encode_blit t ?pcm_off:off ?duration pcm buflet encode_blit_float t ?pcm_off ?duration pcm ?buf_off ?max_size buf =_encode_blit t ?pcm_off ?duration pcm ?buf_off ?max_size buflet encode_float t ?off ?duration ?(max_size=recommended_max_size) pcm =let buf = BA1.create BA.char BA.c_layout max_size in_encode_blit t ?pcm_off:off ?duration pcm buflet ctl t req = CTL.request ~ctl_fn:"opus_encoder_ctl" (_enc t.enc) reqend
module Error: sigtype tval to_string: t -> stringval show: t -> stringval pp: Format.formatter -> t -> unitendtype nonrec 'a result = ('a, Error.t) resulttype 'a handletype bandwidth = [| `Narrow| `Medium| `Wide| `Superwide| `Full]type framesize = [| `from_arg| `fs_2_5ms| `fs_5ms| `fs_10ms| `fs_20ms| `fs_40ms| `fs_60ms| `fs_80ms| `fs_100ms| `fs_120ms]type application =| Voip| Audio| Restricted_lowdelaymodule CTL: sigtype enc = [`enc]type dec = [`dec]type 'a both = [< `enc | `dec] as 'atype ('handle, 'res) t =(* generic *)| Reset_state: (_ both handle, unit) t| Get_final_range: (_ both handle, int) t| Get_bandwidth: (_ both handle, [`auto | bandwidth]) t| Get_sample_rate: (_ both handle, int) t| Set_phase_inversion_disabled: bool -> (_ both handle, unit) t| Get_phase_inversion_disabled: (_ both handle, bool) t| Get_in_DTX: (_ both handle, bool) t(* encoder *)| Set_complexity: int -> (enc handle, unit) t| Get_complexity: (enc handle, int) t| Set_bitrate: [`auto | `max | `bps of int] -> (enc handle, unit) t| Get_bitrate: (enc handle, [`auto | `max | `bps of int]) t| Set_VBR: bool -> (enc handle, unit) t| Get_VBR: (enc handle, bool) t| Set_VBR_constraint: bool -> (enc handle, unit) t| Get_VBR_constraint: (enc handle, bool) t| Set_force_channels: [`auto | `mono | `stereo] -> (enc handle, unit) t| Get_force_channels: (enc handle, [`auto | `mono | `stereo]) t| Set_max_bandwidth: bandwidth -> (enc handle, unit) t| Get_max_bandwidth: (enc handle, bandwidth) t| Set_bandwidth: [`auto | bandwidth] -> (enc handle, unit) t| Set_signal: [`auto | `voice | `music] -> (enc handle, unit) t| Get_signal: (enc handle, [`auto | `voice | `music]) t| Set_application: application -> (enc handle, unit) t| Get_application: (enc handle, application) t| Get_lookahead: (enc handle, int) t| Set_inband_FEC: bool -> (enc handle, unit) t| Get_inband_FEC: (enc handle, bool) t| Set_packet_loss_perc: int -> (enc handle, unit) t| Get_packet_loss_perc: (enc handle, int) t| Set_DTX: bool -> (enc handle, unit) t| Get_DTX: (enc handle, bool) t| Set_LSB_depth: int -> (enc handle, unit) t| Get_LSB_depth: (enc handle, int) t| Set_expert_frame_duration: framesize -> (enc handle, unit) t| Get_expert_frame_duration: (enc handle, framesize) t| Set_prediction_disabled: bool -> (enc handle, unit) t| Get_prediction_disabled: (enc handle, bool) tendtype bigstring = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.ttype s16frame = (int, Bigarray.int16_signed_elt, Bigarray.c_layout) Bigarray.Array1.ttype f32frame = (int, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array1.tmodule Encoder: sigtype ttype packet = [ `Packet of bigstring | `DTX ]val recommended_max_size: intval create:?samplerate:int ->?channels:[`mono | `stereo] ->?application:application ->unit ->t resultval size: t -> intval encode_blit:t ->?pcm_off:int ->?duration:int ->s16frame ->?buf_off:int ->?max_size:int ->bigstring ->packet resultval encode:t ->?off:int ->?duration:int ->?max_size:int ->s16frame ->packet resultval encode_blit_float:t ->?pcm_off:int ->?duration:int ->f32frame ->?buf_off:int ->?max_size:int ->bigstring ->(packet) resultval encode_float:t ->?off:int ->?duration:int ->?max_size:int ->f32frame ->packet resultval ctl: t -> ([`enc] handle, 'a) CTL.t -> 'a resultend
{"name": "@discopotty/opus","version": "1.3.1","description": "OCaml libopus bindings","license": "BSD","esy": {"build": "dune build -p opus","buildDev":"dune build --promote-install-files --root . --only-package opus"},"dependencies": {"@opam/conf-libopus": "*","@opam/ctypes": "0.18.0",// FIXME wait for upstream (esy-opam-overrides)?"@opam/ctypes-foreign": "<0.18.0","@opam/dune": "2.8.4","@opam/ocamlfind": "<1.9.0","@opam/ppx_cstubs": "0.6.1.1","ocaml": "~4.11.0"},"devDependencies": {"@opam/merlin": "*","@opam/ocaml-lsp-server": "*","@opam/ocamlformat": "0.17.0","@opam/odoc": "*"},"resolutions": {"@opam/conf-pkg-config": "1.3","@opam/conf-libopus": {"source": "link:../esy-libopus/conf-libopus.opam","override": { "dependencies": { "esy-libopus": "../esy-libopus" } }}}}