Core_kernel Hashtbl binable example

Is there an example of using Core_kernel Hashtbl.Make_binable functor and using the resulting binable hashtbl to serializing it to bytes?

I guess you could use Bin_prot.Writer.to_bytes with the generated bin_writer to serialize a value to a bytes. If you are planning to use this to communicate between multiple processes though, I would recommend using the bin_prot serializers in combination with something more fully-featured like Async.Rpc.

Where is the module Bin_prot.Writer defined? I can’t seem to find it at https://github.com/janestreet/bin_prot. Is this perhpas replaced by Common.blit* functions?

Here’s something that I’ve used before:

open! Core

module H = Hashtbl.Make_binable(Int)

let write_binary file value_size value_writer table =
    let size = H.bin_size_t value_size table in
    let bs = Core.Bigstring.create size in
    H.bin_write_t value_writer ~pos:0 bs table |> ignore;
    let fd = Unix.openfile ~mode:[O_WRONLY; O_CREAT; O_TRUNC] file in
    Core.Bigstring.write fd bs |> ignore;
    Unix.close fd

let read_binary file read_value =
    let file_size fd =
        let pos = Unix.lseek fd Int64.zero ~mode:SEEK_CUR in
        let bytes = Unix.lseek fd Int64.zero ~mode:SEEK_END in
        let _ = Unix.lseek fd pos ~mode:SEEK_SET in
        bytes
    in
    let fd = Unix.openfile ~mode:[O_RDONLY] file in
    let size = file_size fd in
    let bs = Core.Bigstring.create Int64.(to_int_exn size) in
    Core.Bigstring.read fd bs |> ignore;
    Unix.close fd;
    let pos_ref = ref 0 in
    H.bin_read_t read_value bs ~pos_ref
;;

let run() =
    let table = H.create() in
    H.set table ~key:10 ~data:"Hello";
    H.set table ~key:20 ~data:"Awesome";
    write_binary "table.bin" String.bin_size_t String.bin_write_t table;
    let table = read_binary "table.bin" String.bin_read_t in
    H.iteri table ~f:(fun ~key ~data ->
        Printf.printf "Key %d - Value %s\n" key data
    )

When run:

$ _build/default/bin/main.exe 
Key 10 - Value Hello
Key 20 - Value Awesome
1 Like

Example using Bin_prot helper methods:

module H = Hashtbl.Make_binable(Int)

let run() =
    let table = H.create() in
    H.set table ~key:10 ~data:"Hello";
    H.set table ~key:20 ~data:"Awesome";

    let bytes = Bin_prot.Writer.to_bytes H.(bin_writer_t String.bin_writer_t) table in

    Out_channel.with_file "table.bin" ~f:(fun chan ->
        Out_channel.output_bytes chan bytes
    ) |> ignore;
    
    let table = In_channel.with_file "table.bin" ~f:(fun chan ->
        let bytes = In_channel.input_all chan in
        let buf = Bin_prot.Common.create_buf String.(length bytes) in
        Bin_prot.Common.blit_string_buf bytes buf ~len:String.(length bytes);
        let pos_ref = ref 0 in
        H.bin_read_t String.bin_read_t buf ~pos_ref
    ) in

    H.iteri table ~f:(fun ~key ~data ->
        Printf.printf "Key %d - Value %s\n" key data
    )
1 Like

Ah, it’s actually defined in Core_kernel, which extends the Bin_prot module. See https://github.com/janestreet/core_kernel/blob/master/src/core_bin_prot.ml.

1 Like