package ocaml-protoc

  1. Overview
  2. Docs
Pure OCaml compiler for .proto files

Install

Dune Dependency

Authors

Maintainers

Sources

ocaml-protoc-3.0.2.tbz
sha256=eb3ca953610cc0766b2a89dcb201d49372949458b7d3cb826e15a5ab35205fec
sha512=8db991f12d3a02f226fb7cf3e99ca02d907497d8b4f48f1393d396594868e25a9fa0e4a3e73322bda8d65e690754b73d2523abf8236e47b77fc0c059f2244e3a

Description

Tags

protoc protobuf codegen

Published: 14 Feb 2024

README

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.mli
.. Generating example.ml
  • example.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] *)

(** {2 Protobuf Encoding} *)

val encode_pb_person : person -> Pbrt.Encoder.t -> unit
(** [encode_pb_person v encoder] encodes [v] with the given [encoder] *)


(** {2 Protobuf Decoding} *)

val decode_pb_person : Pbrt.Decoder.t -> person
(** [decode_pb_person decoder] decodes a [person] binary 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.({ 
    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.encode_pb_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.decode_pb_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 for the compiler itself

  • a C99 compiler for the runtime library's stubs

Intall from OPAM

$ opam install ocaml-protoc

Or from source

$ mkdir -p tmp/bin
$ export PREFIX=`pwd`/tmp
$ make install

Build your program

Using dune, the program can be compiled with:

(executable
  (name main)
  (modules main example)
  (libraries pbrt))

More manually, the program can be built directly using ocamlfind:

$ ocamlfind ocamlopt -linkpkg -package pbrt \
    -o example \
    example.mli example.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:

Command line switch Description Runtime
Type definition along with a default constructor function to conveniently create values of that type
--make make constructor functions
--binary Binary encodings pbrt
--yojson JSON encoding using the widely popular yojson library pbrt_yojson
--bs BuckleScript encoding using the BuckleScript core binding to JS json library bs-ocaml-protoc-json
--pp pretty printing functions based on the Format module. pbrt
--services RPC definitions. pbrt_services

Protobuf <-> OCaml mapping

see here.

Compiler Internals

see here

Protobuf Extensions

see here

Benchmarking

see here

Dependencies (3)

  1. ocaml >= "4.08"
  2. pbrt = version
  3. dune >= "2.0"

Dev Dependencies (3)

  1. pbrt_services = version & with-test
  2. pbrt_yojson = version & with-test
  3. odoc with-doc

Conflicts

None