Module Wiretype.Shape

What a description is: the representation Wiretype's combinators make, and everything that reads a description walks -- the decoder, the encoder, the schema printers, and anybody with a use of their own.

It is the library's API and its promise: a constructor added is a new version, so a walk that matches every case is told by the compiler. A description is built with the combinators in Wiretype; one built here directly is as good to read, since everything that reads one checks what it reads, and is trusted to be written as Wiretype.Object.finish would let it be: no member named twice in an object.

type about = {
  1. kind : string;
  2. doc : string;
}

What a description is called -- a component's name, where it is an object -- and what it is, for whoever documents it. Empty when it has neither. Each object Wiretype.Object.finish makes has a record of its own, and the schema and the writer tell objects apart by it; an object built here directly gets one of its own too.

type int_bounds = {
  1. min : int option;
  2. max : int option;
  3. multiple_of : int option;
}
type int64_bounds = {
  1. min : int64 option;
  2. max : int64 option;
  3. multiple_of : int64 option;
}
type number_bounds = {
  1. min : float option;
    (*

    at least

    *)
  2. max : float option;
    (*

    at most

    *)
  3. above : float option;
    (*

    greater than

    *)
  4. below : float option;
    (*

    less than

    *)
  5. multiple_of : float option;
}
type length = {
  1. min_length : int option;
  2. max_length : int option;
}

In code points, as JSON Schema counts a string's length.

type uuid_version =
  1. | V1
  2. | V2
  3. | V3
  4. | V4
  5. | V5
  6. | V6
  7. | V7
  8. | V8
    (*

    The versions RFC 9562 defines.

    *)
type format =
  1. | Date_time
    (*

    RFC 3339 date-time

    *)
  2. | Date
    (*

    RFC 3339 full-date

    *)
  3. | Duration
    (*

    ISO 8601, with no years or months

    *)
  4. | Uuid of uuid_version option
    (*

    RFC 9562, of one version where it names one

    *)
  5. | Base64
    (*

    RFC 4648 §4

    *)
  6. | Base64url
    (*

    RFC 4648 §5

    *)
  7. | Uri
    (*

    RFC 3986

    *)
  8. | Ipv4
  9. | Ipv6

What a string is written in, where a schema has a word for it.

type unknown =
  1. | Skip
  2. | Refuse

What an object does with a member it does not describe.

type access =
  1. | Read_write
    (*

    in requests and answers

    *)
  2. | Read_only
    (*

    in answers alone: the server's to give, never read

    *)
  3. | Write_only
    (*

    in requests alone, never written: a password

    *)

Which of a request and an answer a member is in, as OpenAPI's readOnly and writeOnly say.

type 'a enum = {
  1. words : (string * 'a) list;
  2. word : 'a -> string;
    (*

    the word a value is written as

    *)
}
type 'a t =
  1. | Null : 'a -> 'a t
    (*

    JSON null, read as the value

    *)
  2. | Bool : bool t
  3. | Int : int_bounds -> int t
  4. | Int64 : int64_bounds -> int64 t
  5. | Number : number_bounds -> float t
  6. | String : length -> string t
  7. | Enum : about * 'a enum -> 'a t
  8. | List : 'a elements -> 'a list t
  9. | Tuple : ('a, 'a) items -> 'a t
    (*

    a JSON array of exactly its items, each of its own description

    *)
  10. | Dict : ('k, 'v) dict -> ('k * 'v) list t
    (*

    a JSON object read as a map: its members, in the document's order

    *)
  11. | Nullable : 'a t -> 'a option t
    (*

    the description, or null

    *)
  12. | Object : about * 'o obj -> 'o t
  13. | Any : about * 'a any -> 'a t
  14. | Map : about * ('a, 'b) map -> 'b t
  15. | Value : Value.t t
    (*

    any JSON

    *)
  16. | Rec : 'a t Stdlib.Lazy.t -> 'a t
    (*

    a description of itself

    *)
and 'a elements = {
  1. elt : 'a t;
  2. min_items : int option;
  3. max_items : int option;
}
and ('k, 'v) dict = {
  1. key : 'k t;
    (*

    a member's name, read as the JSON string it is written as, and written as one

    *)
  2. value : 'v t;
  3. min_properties : int option;
  4. max_properties : int option;
}
and ('t, 'f) items =
  1. | Items : 'f -> ('t, 'f) items
  2. | Item : ('t, 'a -> 'f) items * ('t, 'a) item -> ('t, 'f) items

What a tuple is made of, in order: a function, and each item it is applied to, as an object is its members.

and ('t, 'a) item = {
  1. described : 'a t;
  2. part : 't -> 'a;
    (*

    the item of a value

    *)
}
and 'o obj = {
  1. unknown : unknown;
  2. fields : ('o, 'o) fields;
}

An object: the function that builds its value, applied to its members.

and ('o, 'f) fields =
  1. | Build : 'f -> ('o, 'f) fields
  2. | Unread : ('o, 'f) fields
    (*

    an object that is written and never read: an answer to somebody else's server

    *)
  3. | Mem : ('o, 'a -> 'f) fields * ('o, 'a) mem -> ('o, 'f) fields
  4. | Cases : ('o, 'c -> 'f) fields * ('o, 'c) cases -> ('o, 'f) fields
    (*

    the members that depend on one member's value: a union by its tag

    *)

What an object is made of, in the order it was declared: a function, and each member it is applied to.

and ('o, 'a) mem = {
  1. name : string;
  2. field : string option;
    (*

    the OCaml field it is in, where a printer of OCaml should name it so

    *)
  3. doc : string;
  4. shape : 'a t;
  5. absent : 'a option;
    (*

    what it reads as when left out; required if none

    *)
  6. omit : ('a -> bool) option;
    (*

    whether a value is written by leaving it out

    *)
  7. get : ('o -> 'a) option;
    (*

    the member of a value; none reads only

    *)
  8. opt : bool;
    (*

    made by Wiretype.Object.opt_mem: null or absent is None, and None is left out

    *)
  9. access : access;
  10. deprecated : bool;
  11. examples : 'a list;
}
and ('o, 'c) cases =
  1. | Tagged : {
    1. name : string;
      (*

      the tag's member

      *)
    2. doc : string;
    3. shape : 'tag t;
    4. absent : 'tag option;
      (*

      the tag a value with none is read as

      *)
    5. omit : ('tag -> bool) option;
    6. enc : ('o -> 'c) option;
    7. enc_case : 'c -> ('c, 'tag) case_value;
    8. cases : ('c, 'tag) case list;
    } -> ('o, 'c) cases
and ('c, 'tag) case =
  1. | Case : ('c, 'k, 'tag) case_map -> ('c, 'tag) case
and ('c, 'k, 'tag) case_map = {
  1. tag : 'tag;
  2. case_about : about;
    (*

    the case's object's

    *)
  3. obj : 'k obj;
    (*

    the members this case adds

    *)
  4. build : ('k -> 'c) option;
    (*

    none where the case is written and never read

    *)
}
and ('c, 'tag) case_value =
  1. | Case_value : ('c, 'k, 'tag) case_map * 'k -> ('c, 'tag) case_value
and 'a any = {
  1. null : 'a t option;
  2. bool : 'a t option;
  3. number : 'a t option;
  4. string : 'a t option;
  5. array : 'a t option;
  6. object_ : 'a t option;
  7. pick : ('a -> 'a t) option;
    (*

    the description a value is written by

    *)
}

A value that is one of several JSON sorts, a description per sort.

and ('a, 'b) map = {
  1. format : format option;
  2. inner : 'a t;
  3. parse : ('a -> ('b, string) Stdlib.result) option;
    (*

    Error is a sentence for a person: what is wrong with the value

    *)
  4. print : ('b -> ('a, string) Stdlib.result) option;
}

A description of another type, over inner: a kind -- an instant, an id -- or a plain change of type. A direction left out is one it is never used in.