pbrt

Runtime library for Protobuf tooling
README

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 depends on :

  • the OCaml compiler distribution (byte code/native compiler and ocamlbuild).

  • ppx_deriving_protobuf for the generated code runtime.

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

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

Install
Published
17 Aug 2022
Sources
2.3.0.tar.gz
md5=14cb15d70a4ab90f692e132cbf640b11
sha512=063a6a6a1c267ca3e965775f18e5362a58d7a0de92bcee90e57b6004fb79106c03ad1a4c04bd2d259e8d1d0461d2e2bd0b1c7862c58f763364d1cff62bba37a3
Dependencies
odoc
with-doc
dune
>= "2.0"
ocaml
>= "4.03.0"
Reverse Dependencies