package ocaml-protoc
Install
Dune Dependency
Authors
Maintainers
Sources
md5=8a294e86c6202b8ec8016e71d19264cb
sha512=67020bef50b59c6590c1b25d85a75d6e19d6cd37d42b87c94aef798bff51a45f38fe7024b4c67d71c22c13d3f2776bec83acd77794a518f1c4a7eddfc30b6d0b
README.md.html
ocaml-protoc
Introduction
⇨ ocaml-protoc
compiles protobuf message files into OCaml types along with serialization functions for a variety of encodings.
⇨ ocaml-protoc
supports both proto syntax 2 and 3 as well as binary and JSON encodings.
⇨ ocaml-protoc
supports JavaScript object encoding through the BuckleScript compiler. See here for complete example.
A simple example
Write in
example.proto
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
repeated string phone = 4;
}
Run:
❯ ocaml-protoc -binary -ml_out ./ example.proto
.. Generating example_types.mli
.. Generating example_types.ml
.. Generating example_pb.mli
.. Generating example_pb.ml
example_types.mli:
(** example.proto Generated Types *)
(** {2 Types} *)
type person = {
name : string;
id : int32;
email : string;
phone : string list;
}
(** {2 Default values} *)
val default_person :
?name:string ->
?id:int32 ->
?email:string ->
?phone:string list ->
unit ->
person
(** [default_person ()] is the default value for type [person] *)
example_pb.mli:
(** {2 Protobuf Encoding} *)
val encode_person : Example_types.person -> Pbrt.Encoder.t -> unit
(** [encode_person v encoder] encodes [v] with the given [encoder] *)
(** {2 Protobuf Decoding} *)
val decode_person : Pbrt.Decoder.t -> Example_types.person
(** [decode_person decoder] decodes a [person] value from [decoder] *)
in
main.ml
, write the following to encode a person value and save it to a file:
let () =
(* Create OCaml value of generated type *)
let person = Example_types.({
name = "John Doe";
id = 1234l;
email = Some "jdoe@example.com";
phone = ["123-456-7890"];
}) in
(* Create a Protobuf encoder and encode value *)
let encoder = Pbrt.Encoder.create () in
Example_pb.encode_person person encoder;
(* Output the protobuf message to a file *)
let oc = open_out "myfile" in
output_bytes oc (Pbrt.Encoder.to_bytes encoder);
close_out oc
then in the same
main.ml
append the following to read from the same file:
let () =
(* Read bytes from the file *)
let bytes =
let ic = open_in "myfile" in
let len = in_channel_length ic in
let bytes = Bytes.create len in
really_input ic bytes 0 len;
close_in ic;
bytes
in
(* Decode the person and Pretty-print it *)
Example_pb.decode_person (Pbrt.Decoder.of_bytes bytes)
:heavy_exclamation_mark: Int32 vs int
OCaml users will immediately point to the use of int32
type in the generated code which might not be the most convenient choice. One can modify this behavior using custom extensions.
Install & Build
Prerequesite
ocaml-protoc
only depends on
the OCaml compiler distribution (byte code/native compiler).
dune
stdlib-shims
Intall from OPAM
❯ opam install ocaml-protoc
Or from source
❯ mkdir -p tmp/bin
❯ export PREFIX=`pwd`/tmp
❯ make install
Build your program
Using ocamlfind one can build the program above with the following:
❯ ocamlfind ocamlopt -linkpkg -package ocaml-protoc \
-o example \
example_types.mli example_types.ml \
example_types.mli example_types.ml \
main.ml
🏁 You can now run the example
❯ ./example
Runtime library
The generated code depends on the opam package "pbrt", defining a module Pbrt
.
Online documentation here
All Generated Files and Encodings:
file name | Command line switch | Description | Runtime |
---|---|---|---|
<name>_types.{ml|mli} | Type definition along with a constructor function to conveniently create values of that type | ||
<name>_pb.{ml|mli} | -binary | Binary encodings | ocaml-protoc |
<name>_yojson.{ml|mli} | -yojson | JSON encoding using the widely popular yojson library | ocaml-protoc-yojson |
<name>_bs.{ml|mli} | -bs | BuckleScript encoding using the BuckleScript core binding to JS json library | bs-ocaml-protoc-json |
<name>_pp.{ml|mli} | -pp | pretty printing functions based on the Format module. | ocaml-protoc |
Protobuf <-> OCaml mapping
see here.
Compiler Internals
see here
Protobuf Extensions
see here
Benchmarking
see here