(* Decoded text. *)

type plain_text =
  string

(* Encoded text. *)

type cipher_text =
  string

(* An encoding dictionary. *)

type encoding_dictionary

(* A decoding dictionary. *)

type decoding_dictionary

(* An alphabet is a mapping of characters to integer frequencies. *)

type alphabet =
  (char, int) Hashtbl.t

(* Out of a string, one can build an alphabet. *)

val build_alphabet: plain_text -> alphabet

(* Out of an alphabet, one can build encoding and decoding dictionaries. *)

val build_dictionaries: alphabet -> encoding_dictionary * decoding_dictionary

(* The encoding dictionary allows encoding. *)

val encode: encoding_dictionary -> plain_text -> cipher_text

(* The decoding dictionary allows decoding. *)

val decode: decoding_dictionary -> cipher_text -> plain_text

(* A decoding dictionary can be written out to disk and read back,
   via the following two functions. *)

val write: decoding_dictionary -> string
val read:  string -> decoding_dictionary