sig
  type ('a, 'b) result = [ `Error of '| `Ok of 'a ]
  module type OUTPUT_MODEL =
    sig
      type ('a, 'b, 'c) thread
      type ('a, 'b, 'c) channel
      val return : '-> ('a, 'b, 'c) Api.OUTPUT_MODEL.thread
      val bind :
        ('a, 'b, 'c) Api.OUTPUT_MODEL.thread ->
        ('-> ('d, 'b, 'c) Api.OUTPUT_MODEL.thread) ->
        ('d, 'b, 'c) Api.OUTPUT_MODEL.thread
      val output :
        ('a, 'b, 'c) Api.OUTPUT_MODEL.channel ->
        String.t -> (unit, 'e, 'f) Api.OUTPUT_MODEL.thread
    end
  module type BASIC_CHARACTER =
    sig
      type t
      val of_native_char : char -> Api.BASIC_CHARACTER.t option
      val of_int : int -> Api.BASIC_CHARACTER.t option
      val to_int : Api.BASIC_CHARACTER.t -> int
      val size : Api.BASIC_CHARACTER.t -> int
      val write_to_native_bytes :
        Api.BASIC_CHARACTER.t ->
        buf:Bytes.t -> index:int -> (int, [> `out_of_bounds ]) Api.result
      val to_native_string : Api.BASIC_CHARACTER.t -> String.t
      val read_from_native_string :
        buf:String.t -> index:int -> (Api.BASIC_CHARACTER.t * int) option
      val to_string_hum : Api.BASIC_CHARACTER.t -> String.t
      val compare : Api.BASIC_CHARACTER.t -> Api.BASIC_CHARACTER.t -> int
      val is_whitespace : Api.BASIC_CHARACTER.t -> bool
    end
  module type NATIVE_CONVERSIONS =
    sig
      type t
      val of_native_string :
        string ->
        (Api.NATIVE_CONVERSIONS.t, [> `wrong_char_at of int ]) Api.result
      val of_native_substring :
        string ->
        offset:int ->
        length:int ->
        (Api.NATIVE_CONVERSIONS.t,
         [> `out_of_bounds | `wrong_char_at of int ])
        Api.result
      val to_native_string : Api.NATIVE_CONVERSIONS.t -> string
    end
  module type BASIC_STRING =
    sig
      type character
      type t
      val max_string_length : int option
      val empty : Api.BASIC_STRING.t
      val is_empty : Api.BASIC_STRING.t -> bool
      val make : int -> Api.BASIC_STRING.character -> Api.BASIC_STRING.t
      val length : Api.BASIC_STRING.t -> int
      val of_character : Api.BASIC_STRING.character -> Api.BASIC_STRING.t
      val of_character_list :
        Api.BASIC_STRING.character list -> Api.BASIC_STRING.t
      val to_character_list :
        Api.BASIC_STRING.t -> Api.BASIC_STRING.character list
      val get :
        Api.BASIC_STRING.t -> index:int -> Api.BASIC_STRING.character option
      val set :
        Api.BASIC_STRING.t ->
        index:int ->
        v:Api.BASIC_STRING.character -> Api.BASIC_STRING.t option
      val get_exn :
        Api.BASIC_STRING.t -> index:int -> Api.BASIC_STRING.character
      val set_exn :
        Api.BASIC_STRING.t ->
        index:int -> v:Api.BASIC_STRING.character -> Api.BASIC_STRING.t
      val concat :
        ?sep:Api.BASIC_STRING.t ->
        Api.BASIC_STRING.t list -> Api.BASIC_STRING.t
      val of_native_string : string -> (t, [> `wrong_char_at of int ]) result
      val of_native_substring :
        string ->
        offset:int ->
        length:int -> (t, [> `out_of_bounds | `wrong_char_at of int ]) result
      val to_native_string : t -> string
      val to_string_hum : Api.BASIC_STRING.t -> string
      val fold :
        Api.BASIC_STRING.t ->
        init:'-> f:('-> Api.BASIC_STRING.character -> 'a) -> 'a
      val foldi :
        Api.BASIC_STRING.t ->
        init:'-> f:(int -> '-> Api.BASIC_STRING.character -> 'a) -> 'a
      val fold2_exn :
        Api.BASIC_STRING.t ->
        Api.BASIC_STRING.t ->
        init:'->
        f:('->
           Api.BASIC_STRING.character -> Api.BASIC_STRING.character -> 'a) ->
        'a
      val compare : Api.BASIC_STRING.t -> Api.BASIC_STRING.t -> int
      val sub :
        Api.BASIC_STRING.t ->
        index:int -> length:int -> Api.BASIC_STRING.t option
      val sub_exn :
        Api.BASIC_STRING.t -> index:int -> length:int -> Api.BASIC_STRING.t
      val slice :
        ?start:int ->
        ?finish:int -> Api.BASIC_STRING.t -> Api.BASIC_STRING.t option
      val slice_exn :
        ?start:int -> ?finish:int -> Api.BASIC_STRING.t -> Api.BASIC_STRING.t
      val is_prefix : Api.BASIC_STRING.t -> prefix:Api.BASIC_STRING.t -> bool
      val is_suffix : Api.BASIC_STRING.t -> suffix:Api.BASIC_STRING.t -> bool
      val chop_prefix_exn :
        Api.BASIC_STRING.t -> prefix:Api.BASIC_STRING.t -> Api.BASIC_STRING.t
      val chop_prefix :
        Api.BASIC_STRING.t ->
        prefix:Api.BASIC_STRING.t -> Api.BASIC_STRING.t option
      val chop_suffix_exn :
        Api.BASIC_STRING.t -> suffix:Api.BASIC_STRING.t -> Api.BASIC_STRING.t
      val chop_suffix :
        Api.BASIC_STRING.t ->
        suffix:Api.BASIC_STRING.t -> Api.BASIC_STRING.t option
      val split_at :
        Api.BASIC_STRING.t ->
        index:int -> Api.BASIC_STRING.t * Api.BASIC_STRING.t
      val take : Api.BASIC_STRING.t -> index:int -> Api.BASIC_STRING.t
      val drop : Api.BASIC_STRING.t -> index:int -> Api.BASIC_STRING.t
      val compare_substring :
        Api.BASIC_STRING.t * int * int ->
        Api.BASIC_STRING.t * int * int -> int
      val compare_substring_strict :
        Api.BASIC_STRING.t * int * int ->
        Api.BASIC_STRING.t * int * int -> int option
      val iter :
        Api.BASIC_STRING.t -> f:(Api.BASIC_STRING.character -> unit) -> unit
      val iteri :
        Api.BASIC_STRING.t ->
        f:(int -> Api.BASIC_STRING.character -> unit) -> unit
      val iter_reverse :
        Api.BASIC_STRING.t -> f:(Api.BASIC_STRING.character -> unit) -> unit
      val rev : Api.BASIC_STRING.t -> Api.BASIC_STRING.t
      val map :
        Api.BASIC_STRING.t ->
        f:(Api.BASIC_STRING.character -> Api.BASIC_STRING.character) ->
        Api.BASIC_STRING.t
      val mapi :
        Api.BASIC_STRING.t ->
        f:(int -> Api.BASIC_STRING.character -> Api.BASIC_STRING.character) ->
        Api.BASIC_STRING.t
      val map2_exn :
        Api.BASIC_STRING.t ->
        Api.BASIC_STRING.t ->
        f:(Api.BASIC_STRING.character ->
           Api.BASIC_STRING.character -> Api.BASIC_STRING.character) ->
        Api.BASIC_STRING.t
      val for_all :
        Api.BASIC_STRING.t -> f:(Api.BASIC_STRING.character -> bool) -> bool
      val exists :
        Api.BASIC_STRING.t -> f:(Api.BASIC_STRING.character -> bool) -> bool
      val take_while :
        Api.BASIC_STRING.t ->
        f:(Api.BASIC_STRING.character -> bool) -> Api.BASIC_STRING.t
      val take_while_with_index :
        Api.BASIC_STRING.t ->
        f:(int -> Api.BASIC_STRING.character -> bool) -> Api.BASIC_STRING.t
      val index_of_character :
        Api.BASIC_STRING.t ->
        ?from:int -> Api.BASIC_STRING.character -> int option
      val index_of_character_reverse :
        Api.BASIC_STRING.t ->
        ?from:int -> Api.BASIC_STRING.character -> int option
      val index_of_string :
        ?from:int ->
        ?sub_index:int ->
        ?sub_length:int ->
        Api.BASIC_STRING.t -> sub:Api.BASIC_STRING.t -> int option
      val index_of_string_reverse :
        ?from:int ->
        ?sub_index:int ->
        ?sub_length:int ->
        Api.BASIC_STRING.t -> sub:Api.BASIC_STRING.t -> int option
      val find :
        ?from:int ->
        ?length:int ->
        Api.BASIC_STRING.t ->
        f:(Api.BASIC_STRING.character -> bool) -> int option
      val find_reverse :
        ?from:int ->
        ?length:int ->
        Api.BASIC_STRING.t ->
        f:(Api.BASIC_STRING.character -> bool) -> int option
      val filter_map :
        ?from:int ->
        ?length:int ->
        Api.BASIC_STRING.t ->
        f:(Api.BASIC_STRING.character -> Api.BASIC_STRING.character option) ->
        Api.BASIC_STRING.t
      val filter :
        ?from:int ->
        ?length:int ->
        Api.BASIC_STRING.t ->
        f:(Api.BASIC_STRING.character -> bool) -> Api.BASIC_STRING.t
      val split :
        Api.BASIC_STRING.t ->
        on:[ `Character of Api.BASIC_STRING.character
           | `String of Api.BASIC_STRING.t ] ->
        Api.BASIC_STRING.t list
      val strip :
        ?on:[ `Both | `Left | `Right ] ->
        ?whitespace:(Api.BASIC_STRING.character -> bool) ->
        Api.BASIC_STRING.t -> Api.BASIC_STRING.t
      module Make_output :
        functor (Model : OUTPUT_MODEL->
          sig
            val output :
              ('a, 'b, 'c) Model.channel ->
              Api.BASIC_STRING.t -> (unit, 'e, 'f) Model.thread
          end
    end
  module type UNSAFELY_MUTABLE =
    sig
      type t
      type character
      val mutate :
        Api.UNSAFELY_MUTABLE.t ->
        index:int ->
        Api.UNSAFELY_MUTABLE.character ->
        (unit, [> `out_of_bounds ]) Api.result
      val mutate_exn :
        Api.UNSAFELY_MUTABLE.t ->
        index:int -> Api.UNSAFELY_MUTABLE.character -> unit
      val blit :
        src:Api.UNSAFELY_MUTABLE.t ->
        src_index:int ->
        dst:Api.UNSAFELY_MUTABLE.t ->
        dst_index:int -> length:int -> (unit, [> `out_of_bounds ]) Api.result
      val blit_exn :
        src:Api.UNSAFELY_MUTABLE.t ->
        src_index:int ->
        dst:Api.UNSAFELY_MUTABLE.t -> dst_index:int -> length:int -> unit
    end
  module type NATIVE_CHARACTER =
    sig
      type t = char
      val of_native_char : char -> char option
      val of_int : int -> char option
      val to_int : char -> int
      val size : char -> int
      val write_to_native_bytes :
        char -> buf:Bytes.t -> index:int -> (int, [> `out_of_bounds ]) result
      val to_native_string : char -> String.t
      val read_from_native_string :
        buf:String.t -> index:int -> (char * int) option
      val to_string_hum : char -> String.t
      val compare : char -> char -> int
      val is_whitespace : char -> bool
    end
  module type NATIVE_STRING =
    sig
      type character = char
      type t = string
      val max_string_length : int option
      val empty : string
      val is_empty : string -> bool
      val make : int -> char -> string
      val length : string -> int
      val of_character : char -> string
      val of_character_list : char list -> string
      val to_character_list : string -> char list
      val get : string -> index:int -> char option
      val set : string -> index:int -> v:char -> string option
      val get_exn : string -> index:int -> char
      val set_exn : string -> index:int -> v:char -> string
      val concat : ?sep:string -> string list -> string
      val of_native_string :
        string -> (string, [> `wrong_char_at of int ]) result
      val of_native_substring :
        string ->
        offset:int ->
        length:int ->
        (string, [> `out_of_bounds | `wrong_char_at of int ]) result
      val to_native_string : string -> string
      val to_string_hum : string -> string
      val fold : string -> init:'-> f:('-> char -> 'a) -> 'a
      val foldi : string -> init:'-> f:(int -> '-> char -> 'a) -> 'a
      val fold2_exn :
        string -> string -> init:'-> f:('-> char -> char -> 'a) -> 'a
      val compare : string -> string -> int
      val sub : string -> index:int -> length:int -> string option
      val sub_exn : string -> index:int -> length:int -> string
      val slice : ?start:int -> ?finish:int -> string -> string option
      val slice_exn : ?start:int -> ?finish:int -> string -> string
      val is_prefix : string -> prefix:string -> bool
      val is_suffix : string -> suffix:string -> bool
      val chop_prefix_exn : string -> prefix:string -> string
      val chop_prefix : string -> prefix:string -> string option
      val chop_suffix_exn : string -> suffix:string -> string
      val chop_suffix : string -> suffix:string -> string option
      val split_at : string -> index:int -> string * string
      val take : string -> index:int -> string
      val drop : string -> index:int -> string
      val compare_substring : string * int * int -> string * int * int -> int
      val compare_substring_strict :
        string * int * int -> string * int * int -> int option
      val iter : string -> f:(char -> unit) -> unit
      val iteri : string -> f:(int -> char -> unit) -> unit
      val iter_reverse : string -> f:(char -> unit) -> unit
      val rev : string -> string
      val map : string -> f:(char -> char) -> string
      val mapi : string -> f:(int -> char -> char) -> string
      val map2_exn : string -> string -> f:(char -> char -> char) -> string
      val for_all : string -> f:(char -> bool) -> bool
      val exists : string -> f:(char -> bool) -> bool
      val take_while : string -> f:(char -> bool) -> string
      val take_while_with_index : string -> f:(int -> char -> bool) -> string
      val index_of_character : string -> ?from:int -> char -> int option
      val index_of_character_reverse :
        string -> ?from:int -> char -> int option
      val index_of_string :
        ?from:int ->
        ?sub_index:int ->
        ?sub_length:int -> string -> sub:string -> int option
      val index_of_string_reverse :
        ?from:int ->
        ?sub_index:int ->
        ?sub_length:int -> string -> sub:string -> int option
      val find :
        ?from:int -> ?length:int -> string -> f:(char -> bool) -> int option
      val find_reverse :
        ?from:int -> ?length:int -> string -> f:(char -> bool) -> int option
      val filter_map :
        ?from:int ->
        ?length:int -> string -> f:(char -> char option) -> string
      val filter :
        ?from:int -> ?length:int -> string -> f:(char -> bool) -> string
      val split :
        string ->
        on:[ `Character of char | `String of string ] -> string list
      val strip :
        ?on:[ `Both | `Left | `Right ] ->
        ?whitespace:(char -> bool) -> string -> string
      module Make_output :
        functor (Model : OUTPUT_MODEL->
          sig
            val output :
              ('a, 'b, 'c) Model.channel ->
              string -> (unit, 'e, 'f) Model.thread
          end
    end
  module type NATIVE_BYTES =
    sig
      type character = char
      type t = bytes
      val max_string_length : int option
      val empty : bytes
      val is_empty : bytes -> bool
      val make : int -> char -> bytes
      val length : bytes -> int
      val of_character : char -> bytes
      val of_character_list : char list -> bytes
      val to_character_list : bytes -> char list
      val get : bytes -> index:int -> char option
      val set : bytes -> index:int -> v:char -> bytes option
      val get_exn : bytes -> index:int -> char
      val set_exn : bytes -> index:int -> v:char -> bytes
      val concat : ?sep:bytes -> bytes list -> bytes
      val of_native_string :
        string -> (bytes, [> `wrong_char_at of int ]) result
      val of_native_substring :
        string ->
        offset:int ->
        length:int ->
        (bytes, [> `out_of_bounds | `wrong_char_at of int ]) result
      val to_native_string : bytes -> string
      val to_string_hum : bytes -> string
      val fold : bytes -> init:'-> f:('-> char -> 'a) -> 'a
      val foldi : bytes -> init:'-> f:(int -> '-> char -> 'a) -> 'a
      val fold2_exn :
        bytes -> bytes -> init:'-> f:('-> char -> char -> 'a) -> 'a
      val compare : bytes -> bytes -> int
      val sub : bytes -> index:int -> length:int -> bytes option
      val sub_exn : bytes -> index:int -> length:int -> bytes
      val slice : ?start:int -> ?finish:int -> bytes -> bytes option
      val slice_exn : ?start:int -> ?finish:int -> bytes -> bytes
      val is_prefix : bytes -> prefix:bytes -> bool
      val is_suffix : bytes -> suffix:bytes -> bool
      val chop_prefix_exn : bytes -> prefix:bytes -> bytes
      val chop_prefix : bytes -> prefix:bytes -> bytes option
      val chop_suffix_exn : bytes -> suffix:bytes -> bytes
      val chop_suffix : bytes -> suffix:bytes -> bytes option
      val split_at : bytes -> index:int -> bytes * bytes
      val take : bytes -> index:int -> bytes
      val drop : bytes -> index:int -> bytes
      val compare_substring : bytes * int * int -> bytes * int * int -> int
      val compare_substring_strict :
        bytes * int * int -> bytes * int * int -> int option
      val iter : bytes -> f:(char -> unit) -> unit
      val iteri : bytes -> f:(int -> char -> unit) -> unit
      val iter_reverse : bytes -> f:(char -> unit) -> unit
      val rev : bytes -> bytes
      val map : bytes -> f:(char -> char) -> bytes
      val mapi : bytes -> f:(int -> char -> char) -> bytes
      val map2_exn : bytes -> bytes -> f:(char -> char -> char) -> bytes
      val for_all : bytes -> f:(char -> bool) -> bool
      val exists : bytes -> f:(char -> bool) -> bool
      val take_while : bytes -> f:(char -> bool) -> bytes
      val take_while_with_index : bytes -> f:(int -> char -> bool) -> bytes
      val index_of_character : bytes -> ?from:int -> char -> int option
      val index_of_character_reverse :
        bytes -> ?from:int -> char -> int option
      val index_of_string :
        ?from:int ->
        ?sub_index:int -> ?sub_length:int -> bytes -> sub:bytes -> int option
      val index_of_string_reverse :
        ?from:int ->
        ?sub_index:int -> ?sub_length:int -> bytes -> sub:bytes -> int option
      val find :
        ?from:int -> ?length:int -> bytes -> f:(char -> bool) -> int option
      val find_reverse :
        ?from:int -> ?length:int -> bytes -> f:(char -> bool) -> int option
      val filter_map :
        ?from:int -> ?length:int -> bytes -> f:(char -> char option) -> bytes
      val filter :
        ?from:int -> ?length:int -> bytes -> f:(char -> bool) -> bytes
      val split :
        bytes -> on:[ `Character of char | `String of bytes ] -> bytes list
      val strip :
        ?on:[ `Both | `Left | `Right ] ->
        ?whitespace:(char -> bool) -> bytes -> bytes
      module Make_output :
        functor (Model : OUTPUT_MODEL->
          sig
            val output :
              ('a, 'b, 'c) Model.channel ->
              bytes -> (unit, 'e, 'f) Model.thread
          end
      val mutate :
        bytes -> index:int -> char -> (unit, [> `out_of_bounds ]) result
      val mutate_exn : bytes -> index:int -> char -> unit
      val blit :
        src:bytes ->
        src_index:int ->
        dst:bytes ->
        dst_index:int -> length:int -> (unit, [> `out_of_bounds ]) result
      val blit_exn :
        src:bytes ->
        src_index:int -> dst:bytes -> dst_index:int -> length:int -> unit
    end
  module type MINIMALISTIC_MUTABLE_STRING =
    sig
      type character
      type t
      val empty : Api.MINIMALISTIC_MUTABLE_STRING.t
      val max_string_length : int option
      val make :
        int ->
        Api.MINIMALISTIC_MUTABLE_STRING.character ->
        Api.MINIMALISTIC_MUTABLE_STRING.t
      val length : Api.MINIMALISTIC_MUTABLE_STRING.t -> int
      val compare :
        Api.MINIMALISTIC_MUTABLE_STRING.t ->
        Api.MINIMALISTIC_MUTABLE_STRING.t -> int
      val compare_char :
        Api.MINIMALISTIC_MUTABLE_STRING.character ->
        Api.MINIMALISTIC_MUTABLE_STRING.character -> int
      val get :
        Api.MINIMALISTIC_MUTABLE_STRING.t ->
        int -> Api.MINIMALISTIC_MUTABLE_STRING.character
      val set :
        Api.MINIMALISTIC_MUTABLE_STRING.t ->
        int -> Api.MINIMALISTIC_MUTABLE_STRING.character -> unit
      val blit :
        src:Api.MINIMALISTIC_MUTABLE_STRING.t ->
        src_pos:int ->
        dst:Api.MINIMALISTIC_MUTABLE_STRING.t ->
        dst_pos:int -> len:int -> unit
      val is_whitespace : Api.MINIMALISTIC_MUTABLE_STRING.character -> bool
      val of_native_string : string -> (t, [> `wrong_char_at of int ]) result
      val of_native_substring :
        string ->
        offset:int ->
        length:int -> (t, [> `out_of_bounds | `wrong_char_at of int ]) result
      val to_native_string : t -> string
    end
end