├── .gitignore ├── .ocamlformat ├── LICENSE.md ├── Makefile ├── coap-core.opam ├── coap-core ├── Coap_core.ml ├── Coap_core.mli ├── Coap_message.ml ├── Coap_request.ml ├── Coap_response.ml └── dune ├── coap-server-lwt.opam ├── coap-server-lwt ├── Coap_server_lwt.ml ├── Coap_server_lwt.mli └── dune ├── coap.opam ├── coap ├── Coap.ml ├── Coap.mli └── dune ├── default.nix ├── docs ├── coap-core │ ├── Coap_core │ │ ├── .dune-keep │ │ ├── Message │ │ │ └── index.html │ │ ├── Request │ │ │ └── index.html │ │ ├── Response │ │ │ └── index.html │ │ └── index.html │ ├── Coap_core__ │ │ ├── .dune-keep │ │ ├── Coap_message │ │ │ ├── Header │ │ │ │ └── index.html │ │ │ ├── Option │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── Coap_request │ │ │ └── index.html │ │ ├── Coap_response │ │ │ └── index.html │ │ └── index.html │ ├── Coap_core__Coap_message │ │ ├── .dune-keep │ │ ├── Header │ │ │ └── index.html │ │ ├── Option │ │ │ └── index.html │ │ └── index.html │ ├── Coap_core__Coap_request │ │ ├── .dune-keep │ │ └── index.html │ ├── Coap_core__Coap_response │ │ ├── .dune-keep │ │ └── index.html │ └── index.html ├── coap-server-lwt │ ├── Coap_server_lwt │ │ ├── .dune-keep │ │ └── index.html │ └── index.html ├── coap-server-unix │ ├── Coap_server_unix │ │ ├── .dune-keep │ │ └── index.html │ └── index.html ├── coap │ ├── Coap │ │ ├── .dune-keep │ │ ├── Message │ │ │ └── index.html │ │ ├── Request │ │ │ └── index.html │ │ ├── Response │ │ │ └── index.html │ │ ├── Server │ │ │ └── index.html │ │ └── index.html │ └── index.html ├── highlight.pack.js ├── index.html └── odoc.css ├── dune-project ├── esy.lock ├── .gitattributes ├── .gitignore ├── index.json ├── opam │ ├── astring.0.8.3 │ │ └── opam │ ├── base-bytes.base │ │ └── opam │ ├── base-threads.base │ │ └── opam │ ├── base-unix.base │ │ └── opam │ ├── bigarray-compat.1.0.0 │ │ └── opam │ ├── biniou.1.2.1 │ │ └── opam │ ├── cmdliner.1.0.4 │ │ └── opam │ ├── conf-m4.1 │ │ └── opam │ ├── cppo.1.6.6 │ │ └── opam │ ├── cstruct.5.1.1 │ │ └── opam │ ├── dune-configurator.2.5.0 │ │ └── opam │ ├── dune-private-libs.2.5.0 │ │ └── opam │ ├── dune.2.5.0 │ │ └── opam │ ├── easy-format.1.3.2 │ │ └── opam │ ├── fix.20200131 │ │ └── opam │ ├── fmt.0.8.8 │ │ └── opam │ ├── fpath.0.7.2 │ │ └── opam │ ├── lwt.5.2.0 │ │ └── opam │ ├── menhir.20200211 │ │ └── opam │ ├── menhirLib.20200211 │ │ └── opam │ ├── menhirSdk.20200211 │ │ └── opam │ ├── merlin.3.3.3 │ │ └── opam │ ├── mmap.1.1.0 │ │ └── opam │ ├── ocamlbuild.0.14.0 │ │ └── opam │ ├── ocamlfind.1.8.1 │ │ ├── files │ │ │ ├── ocaml-stub │ │ │ └── ocamlfind.install │ │ └── opam │ ├── ocplib-endian.1.1 │ │ └── opam │ ├── odoc.1.5.0 │ │ └── opam │ ├── ppx_yojson_conv_lib.v0.13.0 │ │ └── opam │ ├── re.1.9.0 │ │ └── opam │ ├── result.1.5 │ │ └── opam │ ├── seq.base │ │ ├── files │ │ │ ├── META.seq │ │ │ └── seq.install │ │ └── opam │ ├── stdint.0.6.0 │ │ └── opam │ ├── stdlib-shims.0.1.0 │ │ └── opam │ ├── topkg.1.0.1 │ │ └── opam │ ├── tyxml.4.4.0 │ │ └── opam │ ├── uchar.0.0.2 │ │ └── opam │ ├── uutf.1.0.2 │ │ └── opam │ └── yojson.1.7.0 │ │ └── opam └── overrides │ ├── opam__s__menhir_opam__c__20200211_opam_override │ └── package.json │ ├── opam__s__ocamlbuild_opam__c__0.14.0_opam_override │ ├── files │ │ └── ocamlbuild-0.14.0.patch │ └── package.json │ └── opam__s__ocamlfind_opam__c__1.8.1_opam_override │ ├── files │ └── findlib-1.8.1.patch │ └── package.json ├── examples ├── Coap_demo.ml └── dune ├── onix-lock.json ├── onix.mk └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | _esy 2 | _build 3 | _opam 4 | node_modules 5 | .merlin 6 | -------------------------------------------------------------------------------- /.ocamlformat: -------------------------------------------------------------------------------- 1 | version = 0.26.1 2 | profile = conventional 3 | 4 | ocaml-version = 4.08.0 5 | break-infix = fit-or-vertical 6 | parse-docstrings = true 7 | cases-exp-indent = 2 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Hyper Systems Ltd 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := build 2 | 3 | .PHONY: build 4 | build: 5 | dune build --root=. 6 | 7 | .PHONY: rebuild 8 | rebuild: 9 | dune build --root=. -w 10 | 11 | .PHONY: test 12 | test: 13 | dune build --root=. @runtest 14 | 15 | .PHONY: retest 16 | retest: 17 | dune build --root=. -w @runtest 18 | 19 | .PHONY: doc 20 | doc: 21 | dune build --root=. @doc 22 | 23 | .PHONY: redoc 24 | redoc: 25 | dune build --root=. -w @doc 26 | 27 | .PHONY: clean 28 | clean: 29 | dune clean --root=. 30 | -------------------------------------------------------------------------------- /coap-core.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | synopsis: "OCaml CoAP core library" 4 | description: """ 5 | 6 | Core CoAP parser and type definitions. 7 | 8 | This library should not be used directly by applications. Please install the 9 | `coap` package to start using a CoAP server or client. 10 | """ 11 | maintainer: ["Rizo I. " "Leo Soares "] 12 | authors: ["Rizo I. "] 13 | license: "ISC" 14 | homepage: "https://github.com/hyper-systems/ocaml-coap" 15 | doc: "https://hyper-systems.github.io/ocaml-coap" 16 | bug-reports: "https://github.com/hyper-systems/ocaml-coap/issues" 17 | depends: [ 18 | "ocaml" {>= "4.08.0"} 19 | "dune" {>= "3.13"} 20 | "fmt" {>= "0.9.0"} 21 | "cstruct" {>= "6.2.0"} 22 | "base-bigarray" 23 | "stdint" {>= "0.7.2"} 24 | "ocaml-lsp-server" {with-dev-setup} 25 | "ocamlformat" {with-dev-setup & >= "0.26.1"} 26 | "odoc" {with-doc & >= "2.4.1"} 27 | ] 28 | build: [ 29 | ["dune" "subst"] {dev} 30 | [ 31 | "dune" 32 | "build" 33 | "-p" 34 | name 35 | "-j" 36 | jobs 37 | "@install" 38 | "@runtest" {with-test} 39 | "@doc" {with-doc} 40 | ] 41 | ] 42 | dev-repo: "git+https://github.com/hyper-systems/ocaml-coap.git" 43 | -------------------------------------------------------------------------------- /coap-core/Coap_core.ml: -------------------------------------------------------------------------------- 1 | (* Coap errors *) 2 | 3 | type error = 4 | [ `Invalid_token_length | `Invalid_option_delta | `Invalid_option_length ] 5 | 6 | let pp_error formatter x = 7 | Format.fprintf formatter 8 | @@ 9 | match x with 10 | | `Invalid_token_length -> "@[Invalid@ token@ length@]" 11 | | `Invalid_option_delta -> "@[Invalid@ option@ delta@]" 12 | | `Invalid_option_length -> "@[Invalid@ option@ length@]" 13 | 14 | module Request = Coap_request 15 | module Response = Coap_response 16 | module Message = Coap_message 17 | -------------------------------------------------------------------------------- /coap-core/Coap_core.mli: -------------------------------------------------------------------------------- 1 | type error = 2 | [ `Invalid_token_length | `Invalid_option_delta | `Invalid_option_length ] 3 | 4 | val pp_error : Format.formatter -> error -> unit 5 | 6 | module Message : sig 7 | type t 8 | 9 | type buffer = 10 | (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t 11 | 12 | type kind = Confirmable | Nonconfirmable | Acknowledgement | Reset 13 | 14 | type code = 15 | | Empty 16 | | Request of [ `Get | `Post | `Put | `Delete ] 17 | | Response of 18 | [ (* 2XX *) 19 | `Created 20 | | `Deleted 21 | | `Valid 22 | | `Changed 23 | | `Content 24 | | (* 4XX *) 25 | `Bad_request 26 | | `Unauthorized 27 | | `Bad_option 28 | | `Forbidden 29 | | `Not_found 30 | | `Method_not_allowed 31 | | `Not_acceptable 32 | | `Precondition_failed 33 | | `Request_entity_too_large 34 | | `Unsupported_content_format 35 | | (* 5xx *) 36 | `Internal_server_error 37 | | `Not_implemented 38 | | `Bad_gateway 39 | | `Service_unavailable 40 | | `Gateway_timeout 41 | | `Proxying_not_supported ] 42 | 43 | val pp_code : Format.formatter -> code -> unit 44 | 45 | type content_format = 46 | [ `Text of [ `Plain ] 47 | | `Application of 48 | [ `Link_format | `Xml | `Octet_stream | `Exi | `Json | `Cbor ] ] 49 | 50 | type option = 51 | | If_match of string 52 | | Uri_host of string 53 | | Etag of string 54 | | If_none_match 55 | | Uri_port of int 56 | | Location_path of string 57 | | Uri_path of string 58 | | Content_format of content_format 59 | | Max_age of int 60 | | Uri_query of string 61 | | Accept of int 62 | | Location_query of string 63 | | Proxy_uri of string 64 | | Proxy_scheme of string 65 | | Size1 of int 66 | 67 | val make : 68 | ?version:int -> 69 | ?id:int -> 70 | ?token:string -> 71 | code:code -> 72 | ?kind:kind -> 73 | ?options:option list -> 74 | ?client_addr:string -> 75 | buffer -> 76 | t 77 | (** Coap message constructor. *) 78 | 79 | val version : t -> int 80 | val id : t -> int 81 | val kind : t -> kind 82 | val code : t -> code 83 | 84 | val token : t -> string 85 | (** Message token used to match a response with a request. 86 | 87 | Token values may be 0 to 8 bytes in length. *) 88 | 89 | val options : t -> option list 90 | 91 | val path : t -> string list 92 | (** Extract request path from message options. *) 93 | 94 | val client_addr : t -> string Stdlib.Option.t 95 | val with_client_addr : string Stdlib.Option.t -> t -> t 96 | val payload : t -> buffer 97 | val payload_length : t -> int 98 | val buffer_to_string : buffer -> string 99 | val buffer_of_string : string -> buffer 100 | val is_confirmable : t -> bool 101 | val decode : buffer -> (t, error) result 102 | val encode : t -> buffer 103 | val pp : Format.formatter -> t -> unit 104 | 105 | val max_size : int 106 | (** Maximum safe message size. 107 | 108 | https://tools.ietf.org/html/rfc7252#section-4.6 *) 109 | end 110 | 111 | module Request : sig end 112 | 113 | module Response : sig 114 | val not_found : 115 | ?version:int -> 116 | ?id:int -> 117 | ?token:string -> 118 | ?kind:Message.kind -> 119 | ?options:Message.option list -> 120 | Message.buffer -> 121 | Message.t 122 | 123 | val content : 124 | ?version:int -> 125 | ?id:int -> 126 | ?token:string -> 127 | ?kind:Message.kind -> 128 | ?options:Message.option list -> 129 | Message.buffer -> 130 | Message.t 131 | end 132 | -------------------------------------------------------------------------------- /coap-core/Coap_request.ml: -------------------------------------------------------------------------------- 1 | type t = { message : Coap_message.t; source : string } 2 | -------------------------------------------------------------------------------- /coap-core/Coap_response.ml: -------------------------------------------------------------------------------- 1 | let not_found ?version ?id ?token ?(kind = Coap_message.Acknowledgement) 2 | ?options payload = 3 | Coap_message.make ?version ?id ?token ~code:(Coap_message.Response `Not_found) 4 | ~kind ?options payload 5 | 6 | let content ?version ?id ?token ?(kind = Coap_message.Acknowledgement) ?options 7 | payload = 8 | Coap_message.make ?version ?id ?token ~code:(Coap_message.Response `Content) 9 | ~kind ?options payload 10 | 11 | let bad_request ?version ?id ?token ?(kind = Coap_message.Acknowledgement) 12 | ?options payload = 13 | Coap_message.make ?version ?id ?token 14 | ~code:(Coap_message.Response `Bad_request) ~kind ?options payload 15 | -------------------------------------------------------------------------------- /coap-core/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name Coap_core) 3 | (public_name coap-core) 4 | (modules Coap_core Coap_message Coap_request Coap_response) 5 | (libraries stdint fmt cstruct)) 6 | -------------------------------------------------------------------------------- /coap-server-lwt.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | synopsis: "OCaml CoAP core library" 4 | description: 5 | "Constrained Application Protocol (RFC 7252) implementation for OCaml." 6 | maintainer: ["Rizo I. " "Leo Soares "] 7 | authors: ["Rizo I. "] 8 | license: "ISC" 9 | homepage: "https://github.com/hyper-systems/ocaml-coap" 10 | doc: "https://hyper-systems.github.io/ocaml-coap" 11 | bug-reports: "https://github.com/hyper-systems/ocaml-coap/issues" 12 | depends: [ 13 | "ocaml" {>= "4.08.0"} 14 | "dune" {>= "3.13"} 15 | "coap-core" {= version} 16 | "fmt" {>= "0.9.0"} 17 | "cstruct" {>= "6.2.0"} 18 | "cstruct-lwt" {>= "6.2.0"} 19 | "stdint" {>= "0.7.2"} 20 | "lwt" {>= "5.7.0"} 21 | "ocaml-lsp-server" {with-dev-setup} 22 | "ocamlformat" {with-dev-setup & >= "0.26.1"} 23 | "odoc" {with-doc & >= "2.4.1"} 24 | ] 25 | build: [ 26 | ["dune" "subst"] {dev} 27 | [ 28 | "dune" 29 | "build" 30 | "-p" 31 | name 32 | "-j" 33 | jobs 34 | "@install" 35 | "@runtest" {with-test} 36 | "@doc" {with-doc} 37 | ] 38 | ] 39 | dev-repo: "git+https://github.com/hyper-systems/ocaml-coap.git" 40 | -------------------------------------------------------------------------------- /coap-server-lwt/Coap_server_lwt.ml: -------------------------------------------------------------------------------- 1 | let exn_udp_not_found = 2 | Failure 3 | "Could not find the `udp` protocol entry. Check your /etc/protocols file." 4 | 5 | let pp_inet_addr formatter addr = 6 | Format.pp_print_string formatter (Unix.string_of_inet_addr addr) 7 | 8 | let ( let* ) m f = Lwt.bind m f 9 | 10 | let log ?(channel = stderr) fmt = 11 | let f = Format.formatter_of_out_channel channel in 12 | Format.(kfprintf (fun f -> pp_print_newline f ()) f fmt) 13 | 14 | let max_coap_message_size = 1152 15 | 16 | let rec forever f = 17 | Lwt.catch 18 | (fun () -> 19 | let* () = f () in 20 | forever f) 21 | (fun exn -> 22 | log 23 | "[ERROR] Failure when processing client request: %s@.%s@.Resuming \ 24 | request processing..." 25 | (Printexc.to_string exn) 26 | (Printexc.get_backtrace ()); 27 | forever f) 28 | 29 | let start ?(addr = "127.0.0.1") ?(port = 5683) handler = 30 | let proto = 31 | try Unix.getprotobyname "udp" with Not_found -> raise exn_udp_not_found 32 | in 33 | 34 | let inet_addr, sockaddr = 35 | match Unix.gethostbyname addr with 36 | | { h_addr_list; _ } -> 37 | let inet_addr = Array.get h_addr_list 0 in 38 | let sockaddr = Unix.ADDR_INET (inet_addr, port) in 39 | (inet_addr, sockaddr) 40 | | exception Not_found -> 41 | let inet_addr = Unix.inet_addr_of_string addr in 42 | let sockaddr = Unix.ADDR_INET (inet_addr, port) in 43 | (inet_addr, sockaddr) 44 | in 45 | 46 | let socket = 47 | let domain = Unix.domain_of_sockaddr sockaddr in 48 | Lwt_unix.of_unix_file_descr 49 | (Unix.socket domain Unix.SOCK_DGRAM proto.Unix.p_proto) 50 | in 51 | 52 | let* () = Lwt_unix.bind socket sockaddr in 53 | 54 | log "[INFO] Coap.Server: Listening... addr=%a port=%d" pp_inet_addr inet_addr 55 | port; 56 | let req_cstruct = Cstruct.create max_coap_message_size in 57 | let process_request () = 58 | let* incoming = Lwt_cstruct.recvfrom socket req_cstruct [] in 59 | match incoming with 60 | | len, (Unix.ADDR_INET (client_addr, port) as client_sockaddr) -> 61 | let req_buffer = Cstruct.to_bigarray (Cstruct.sub req_cstruct 0 len) in 62 | let req_result = Coap_core.Message.decode req_buffer in 63 | let client_addr = Format.asprintf "%a:%d" pp_inet_addr client_addr port in 64 | let req_result = 65 | Result.map 66 | (Coap_core.Message.with_client_addr (Some client_addr)) 67 | req_result 68 | in 69 | let* res = handler req_result in 70 | let res_buffer = Coap_core.Message.encode res in 71 | let res_cstruct = Cstruct.of_bigarray res_buffer in 72 | let res_len = Cstruct.length res_cstruct in 73 | let* res_len_sent = 74 | Lwt_cstruct.sendto socket res_cstruct [] client_sockaddr 75 | in 76 | if res_len_sent <> res_len then 77 | log "[ERROR] Could not send response message@."; 78 | Lwt.return () 79 | | _ -> assert false 80 | in 81 | forever process_request 82 | -------------------------------------------------------------------------------- /coap-server-lwt/Coap_server_lwt.mli: -------------------------------------------------------------------------------- 1 | val start : 2 | ?addr:string -> 3 | ?port:int -> 4 | ((Coap_core.Message.t, Coap_core.error) result -> Coap_core.Message.t Lwt.t) -> 5 | unit Lwt.t 6 | -------------------------------------------------------------------------------- /coap-server-lwt/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name Coap_server_lwt) 3 | (public_name coap-server-lwt) 4 | (modules Coap_server_lwt) 5 | (libraries coap-core lwt.unix cstruct-lwt)) 6 | -------------------------------------------------------------------------------- /coap.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | synopsis: "OCaml CoAP core library" 4 | description: 5 | "Constrained Application Protocol (RFC 7252) implementation for OCaml." 6 | maintainer: ["Rizo I. " "Leo Soares "] 7 | authors: ["Rizo I. "] 8 | license: "ISC" 9 | homepage: "https://github.com/hyper-systems/ocaml-coap" 10 | doc: "https://hyper-systems.github.io/ocaml-coap" 11 | bug-reports: "https://github.com/hyper-systems/ocaml-coap/issues" 12 | depends: [ 13 | "ocaml" {>= "4.08.0"} 14 | "dune" {>= "3.13"} 15 | "coap-core" {= version} 16 | "coap-server-lwt" {= version} 17 | "fmt" {>= "0.9.0"} 18 | "cstruct" {>= "6.2.0"} 19 | "stdint" {>= "0.7.2"} 20 | "lwt" {>= "5.7.0"} 21 | "ocaml-lsp-server" {with-dev-setup} 22 | "ocamlformat" {with-dev-setup & >= "0.26.1"} 23 | "odoc" {with-doc & >= "2.4.1"} 24 | ] 25 | build: [ 26 | ["dune" "subst"] {dev} 27 | [ 28 | "dune" 29 | "build" 30 | "-p" 31 | name 32 | "-j" 33 | jobs 34 | "@install" 35 | "@runtest" {with-test} 36 | "@doc" {with-doc} 37 | ] 38 | ] 39 | dev-repo: "git+https://github.com/hyper-systems/ocaml-coap.git" 40 | -------------------------------------------------------------------------------- /coap/Coap.ml: -------------------------------------------------------------------------------- 1 | type error = Coap_core.error 2 | 3 | let pp_error = Coap_core.pp_error 4 | 5 | module Request = Coap_core.Request 6 | module Response = Coap_core.Response 7 | module Message = Coap_core.Message 8 | module Server = Coap_server_lwt 9 | -------------------------------------------------------------------------------- /coap/Coap.mli: -------------------------------------------------------------------------------- 1 | type error = 2 | [ `Invalid_token_length | `Invalid_option_delta | `Invalid_option_length ] 3 | 4 | val pp_error : Format.formatter -> error -> unit 5 | 6 | module Message : sig 7 | type t 8 | 9 | type buffer = 10 | (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t 11 | (** The type of bigarray buffers used to represent message payloads. 12 | 13 | Note: This type is compatible with Cstruct buffers. 14 | 15 | See: {!val:Coap.Message.Coap_core.Message.payload_to_buffer} *) 16 | 17 | type kind = Confirmable | Nonconfirmable | Acknowledgement | Reset 18 | 19 | type code = 20 | | Empty 21 | | Request of [ `Get | `Post | `Put | `Delete ] 22 | | Response of 23 | [ (* 2XX *) 24 | `Created 25 | | `Deleted 26 | | `Valid 27 | | `Changed 28 | | `Content 29 | | (* 4XX *) 30 | `Bad_request 31 | | `Unauthorized 32 | | `Bad_option 33 | | `Forbidden 34 | | `Not_found 35 | | `Method_not_allowed 36 | | `Not_acceptable 37 | | `Precondition_failed 38 | | `Request_entity_too_large 39 | | `Unsupported_content_format 40 | | (* 5xx *) 41 | `Internal_server_error 42 | | `Not_implemented 43 | | `Bad_gateway 44 | | `Service_unavailable 45 | | `Gateway_timeout 46 | | `Proxying_not_supported ] 47 | 48 | val pp_code : Format.formatter -> code -> unit 49 | 50 | type content_format = 51 | [ `Text of [ `Plain ] 52 | | `Application of 53 | [ `Link_format | `Xml | `Octet_stream | `Exi | `Json | `Cbor ] ] 54 | 55 | type option = 56 | | If_match of string 57 | | Uri_host of string 58 | | Etag of string 59 | | If_none_match 60 | | Uri_port of int 61 | | Location_path of string 62 | | Uri_path of string 63 | | Content_format of content_format 64 | | Max_age of int 65 | | Uri_query of string 66 | | Accept of int 67 | | Location_query of string 68 | | Proxy_uri of string 69 | | Proxy_scheme of string 70 | | Size1 of int 71 | 72 | val make : 73 | ?version:int -> 74 | ?id:int -> 75 | ?token:string -> 76 | code:code -> 77 | ?kind:kind -> 78 | ?options:option list -> 79 | ?client_addr:string -> 80 | buffer -> 81 | t 82 | (** Coap message constructor. *) 83 | 84 | val version : t -> int 85 | val id : t -> int 86 | val kind : t -> kind 87 | val code : t -> code 88 | 89 | val token : t -> string 90 | (** Message token used to match a response with a request. 91 | 92 | Token values may be 0 to 8 bytes in length. *) 93 | 94 | val options : t -> option list 95 | 96 | val path : t -> string list 97 | (** Extract request path from message options. *) 98 | 99 | val client_addr : t -> string Stdlib.Option.t 100 | val with_client_addr : string Stdlib.Option.t -> t -> t 101 | val payload : t -> buffer 102 | val payload_length : t -> int 103 | val buffer_to_string : buffer -> string 104 | val buffer_of_string : string -> buffer 105 | val is_confirmable : t -> bool 106 | val decode : buffer -> (t, error) result 107 | val encode : t -> buffer 108 | val pp : Format.formatter -> t -> unit 109 | 110 | val max_size : int 111 | (** Maximum safe message size. 112 | 113 | https://tools.ietf.org/html/rfc7252#section-4.6 *) 114 | end 115 | 116 | module Request : sig end 117 | 118 | module Response : sig 119 | val not_found : 120 | ?version:int -> 121 | ?id:int -> 122 | ?token:string -> 123 | ?kind:Message.kind -> 124 | ?options:Message.option list -> 125 | Message.buffer -> 126 | Message.t 127 | 128 | val content : 129 | ?version:int -> 130 | ?id:int -> 131 | ?token:string -> 132 | ?kind:Message.kind -> 133 | ?options:Message.option list -> 134 | Message.buffer -> 135 | Message.t 136 | end 137 | 138 | module Server : sig 139 | val start : 140 | ?addr:string -> 141 | ?port:int -> 142 | ((Message.t, error) result -> Message.t Lwt.t) -> 143 | unit Lwt.t 144 | (** [start ~addr ~port handler] starts the CoAP server in a Lwt thread 145 | listening for client requests on the provided IPv4 or IPv6 address/port 146 | and handling incoming requests with the [handler] function. *) 147 | end 148 | -------------------------------------------------------------------------------- /coap/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name Coap) 3 | (public_name coap) 4 | (libraries coap-core coap-server-lwt)) 5 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | let 2 | onix = import (builtins.fetchGit { 3 | url = "https://github.com/rizo/onix.git"; 4 | rev = "1a67fe51d4d1676f38088e635a00dfdae5bae70b"; 5 | }) { verbosity = "info"; }; 6 | 7 | in onix.env { 8 | path = ./.; 9 | vars = { 10 | "with-test" = true; 11 | "with-doc" = true; 12 | "with-dev-setup" = true; 13 | }; 14 | deps = { "ocaml-base-compiler" = "5.1.0"; }; 15 | } 16 | -------------------------------------------------------------------------------- /docs/coap-core/Coap_core/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyper-systems/ocaml-coap/9d345f9ab47248a1d9b02c498621dfd415677568/docs/coap-core/Coap_core/.dune-keep -------------------------------------------------------------------------------- /docs/coap-core/Coap_core/Message/index.html: -------------------------------------------------------------------------------- 1 | 2 | Message (coap-core.Coap_core.Message)

Module Coap_core.Message

type t
type kind =
| Confirmable
| Nonconfirmable
| Acknowledgement
| Reset
type code =
| Empty
| Request of [ `Get | `Post | `Put | `Delete ]
| Response of [ `Created | `Deleted | `Valid | `Changed | `Content | `Bad_request | `Unauthorized | `Bad_option | `Forbidden | `Not_found | `Method_not_allowed | `Not_acceptable | `Precondition_failed | `Request_entity_too_large | `Unsupported_content_format | `Internal_server_error | `Not_implemented | `Bad_gateway | `Service_unavailable | `Gateway_timeout | `Proxying_not_supported ]
val pp_code : Stdlib.Format.formatter -> code -> unit
type content_format = [
| `Text of [ `Plain ]
| `Application of [ `Link_format | `Xml | `Octet_stream | `Exi | `Json ]
]
type option =
| If_match of string
| Uri_host of string
| Etag of string
| If_none_match
| Uri_port of int
| Location_path of string
| Uri_path of string
| Content_format of content_format
| Max_age of int
| Uri_query of string
| Accept of int
| Location_query of string
| Proxy_uri of string
| Proxy_scheme of string
| Size1 of int
val make : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> code:code -> ?⁠kind:kind -> ?⁠options:option list -> string -> t

Coap message constructor.

val version : t -> int
val id : t -> int
val kind : t -> kind
val code : t -> code
val token : t -> string

Message token used to match a response with a request.

Token values may be 0 to 8 bytes in length.

val options : t -> option list
val path : t -> string list

Extract request path from message options.

val payload : t -> string
val is_confirmable : t -> bool
val decode : string -> (terror) Stdlib.result
val encode : t -> string
val pp : Stdlib.Format.formatter -> t -> unit
val max_size : int

Maximum safe message size.

https://tools.ietf.org/html/rfc7252#section-4.6

-------------------------------------------------------------------------------- /docs/coap-core/Coap_core/Request/index.html: -------------------------------------------------------------------------------- 1 | 2 | Request (coap-core.Coap_core.Request)

Module Coap_core.Request

-------------------------------------------------------------------------------- /docs/coap-core/Coap_core/Response/index.html: -------------------------------------------------------------------------------- 1 | 2 | Response (coap-core.Coap_core.Response)

Module Coap_core.Response

val not_found : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Message.kind -> ?⁠options:Message.option list -> string -> Message.t
val content : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Message.kind -> ?⁠options:Message.option list -> string -> Message.t
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_core (coap-core.Coap_core)

Module Coap_core

type error = [
| `Invalid_token_length
| `Invalid_option_delta
| `Invalid_option_length
]
val pp_error : Stdlib.Format.formatter -> error -> unit
module Message : sig ... end
module Request : sig ... end
module Response : sig ... end
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyper-systems/ocaml-coap/9d345f9ab47248a1d9b02c498621dfd415677568/docs/coap-core/Coap_core__/.dune-keep -------------------------------------------------------------------------------- /docs/coap-core/Coap_core__/Coap_message/Header/index.html: -------------------------------------------------------------------------------- 1 | 2 | Header (coap-core.Coap_core__.Coap_message.Header)

Module Coap_message.Header

type t = int32
val make : version:int -> id:int -> token_length:int -> kind:kind -> code:code -> int32
val version : int32 -> int
val kind : int32 -> kind
val token_length : int32 -> int
val code : int32 -> code
val id : int32 -> int
val pp : Stdlib.Format.formatter -> int32 -> unit
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__/Coap_message/Option/index.html: -------------------------------------------------------------------------------- 1 | 2 | Option (coap-core.Coap_core__.Coap_message.Option)

Module Coap_message.Option

type t = option
val content_format_of_int : int -> [> `Application of [> `Exi | `Json | `Link_format | `Octet_stream | `Xml ] | `Text of [> `Plain ] ]
val content_format_to_int : [< `Application of [< `Exi | `Json | `Link_format | `Octet_stream | `Xml ] | `Text of [< `Plain ] ] -> int
val decode_int : Cstruct.t -> int -> Cstruct.uint8
val decode : int -> Cstruct.t -> int -> option
val encode_int : Cstruct.uint8 -> string
val encode : option -> int * string
val number : option -> int
val name : int -> string
val value_length : option -> int
val length : option -> int
val compare : option -> option -> int
val pp : Stdlib.Format.formatter -> option -> unit
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__/Coap_request/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_request (coap-core.Coap_core__.Coap_request)

Module Coap_core__.Coap_request

type t = {
message : Coap_core__.Coap_message.t;
source : string;
}
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__/Coap_response/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_response (coap-core.Coap_core__.Coap_response)

Module Coap_core__.Coap_response

val not_found : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Coap_core__.Coap_message.kind -> ?⁠options:Coap_core__.Coap_message.option list -> string -> Coap_core__.Coap_message.t
val content : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Coap_core__.Coap_message.kind -> ?⁠options:Coap_core__.Coap_message.option list -> string -> Coap_core__.Coap_message.t
val bad_request : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Coap_core__.Coap_message.kind -> ?⁠options:Coap_core__.Coap_message.option list -> string -> Coap_core__.Coap_message.t
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_core__ (coap-core.Coap_core__)

Module Coap_core__

module Coap_message : sig ... end
module Coap_request : sig ... end
module Coap_response : sig ... end
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__Coap_message/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyper-systems/ocaml-coap/9d345f9ab47248a1d9b02c498621dfd415677568/docs/coap-core/Coap_core__Coap_message/.dune-keep -------------------------------------------------------------------------------- /docs/coap-core/Coap_core__Coap_message/Header/index.html: -------------------------------------------------------------------------------- 1 | 2 | Header (coap-core.Coap_core__Coap_message.Header)

Module Coap_core__Coap_message.Header

type t = int32
val make : version:int -> id:int -> token_length:int -> kind:kind -> code:code -> int32
val version : int32 -> int
val kind : int32 -> kind
val token_length : int32 -> int
val code : int32 -> code
val id : int32 -> int
val pp : Stdlib.Format.formatter -> int32 -> unit
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__Coap_message/Option/index.html: -------------------------------------------------------------------------------- 1 | 2 | Option (coap-core.Coap_core__Coap_message.Option)

Module Coap_core__Coap_message.Option

type t = option
val content_format_of_int : int -> [> `Application of [> `Exi | `Json | `Link_format | `Octet_stream | `Xml ] | `Text of [> `Plain ] ]
val content_format_to_int : [< `Application of [< `Exi | `Json | `Link_format | `Octet_stream | `Xml ] | `Text of [< `Plain ] ] -> int
val decode_int : Cstruct.t -> int -> Cstruct.uint8
val decode : int -> Cstruct.t -> int -> option
val encode_int : Cstruct.uint8 -> string
val encode : option -> int * string
val number : option -> int
val name : int -> string
val value_length : option -> int
val length : option -> int
val compare : option -> option -> int
val pp : Stdlib.Format.formatter -> option -> unit
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__Coap_message/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_core__Coap_message (coap-core.Coap_core__Coap_message)

Module Coap_core__Coap_message

val let* : ('a'b) Stdlib.result -> ('a -> ('c'b) Stdlib.result) -> ('c'b) Stdlib.result
val return : 'a -> ('a'b) Stdlib.result
type kind =
| Confirmable
| Nonconfirmable
| Acknowledgement
| Reset
val pp_kind : Stdlib.Format.formatter -> kind -> unit
val kind_of_int : int -> kind
val kind_to_int : kind -> int
type code =
| Empty
| Request of [ `Get | `Post | `Put | `Delete ]
| Response of [ `Created | `Deleted | `Valid | `Changed | `Content | `Bad_request | `Unauthorized | `Bad_option | `Forbidden | `Not_found | `Method_not_allowed | `Not_acceptable | `Precondition_failed | `Request_entity_too_large | `Unsupported_content_format | `Internal_server_error | `Not_implemented | `Bad_gateway | `Service_unavailable | `Gateway_timeout | `Proxying_not_supported ]
val dump_request_kind : Stdlib.Format.formatter -> [< `Delete | `Get | `Post | `Put ] -> unit
val dump_response_kind : Stdlib.Format.formatter -> [< `Bad_gateway | `Bad_option | `Bad_request | `Changed | `Content | `Continue | `Created | `Deleted | `Forbidden | `Gateway_timeout | `Internal_server_error | `Method_not_allowed | `Not_acceptable | `Not_found | `Not_implemented | `Precondition_failed | `Proxying_not_supported | `Request_entity_incomplete | `Request_entity_too_large | `Service_unavailable | `Too_many_requests | `Unauthorized | `Unsupported_content_format | `Valid ] -> unit
val pp_code : Stdlib.Format.formatter -> code -> unit
type content_format = [
| `Text of [ `Plain ]
| `Application of [ `Link_format | `Xml | `Octet_stream | `Exi | `Json ]
]
module Header : sig ... end
type option =
| If_match of string
| Uri_host of string
| Etag of string
| If_none_match
| Uri_port of int
| Location_path of string
| Uri_path of string
| Content_format of content_format
| Max_age of int
| Uri_query of string
| Accept of int
| Location_query of string
| Proxy_uri of string
| Proxy_scheme of string
| Size1 of int
module Option : sig ... end
type t = {
header : Stdlib.Int32.t;
token : string;
options : option list;
payload : string;
}
val pp_options : Stdlib.Format.formatter -> option list -> unit
val version : t -> int
val kind : t -> kind
val code : t -> code
val id : t -> int
val token : t -> string
val options : t -> option list
val payload : t -> string
val path : t -> string list
val payload_marker : int
val header_length : int
val is_confirmable : t -> bool
val length : t -> int
val decode : string -> (t[> `Invalid_option_delta | `Invalid_option_length | `Invalid_token_length ]) Stdlib.result
val encode_header : Cstruct.t -> int -> Cstruct.uint32 -> int
val encode_token : Cstruct.t -> int -> string -> int
val encode_option_part : int -> int
val put_option_part : data:Cstruct.t -> i:int -> length:int -> int -> int
val encode_options : Cstruct.t -> int -> option list -> int
val encode_payload : Cstruct.t -> int -> string -> int
val encode : t -> string
val gen_id : unit -> int
val make : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> code:code -> ?⁠kind:kind -> ?⁠options:option list -> string -> t
val pp : Stdlib.Format.formatter -> t -> unit
val max_size : int
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__Coap_request/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyper-systems/ocaml-coap/9d345f9ab47248a1d9b02c498621dfd415677568/docs/coap-core/Coap_core__Coap_request/.dune-keep -------------------------------------------------------------------------------- /docs/coap-core/Coap_core__Coap_request/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_core__Coap_request (coap-core.Coap_core__Coap_request)

Module Coap_core__Coap_request

type t = {
message : Coap_core__.Coap_message.t;
source : string;
}
-------------------------------------------------------------------------------- /docs/coap-core/Coap_core__Coap_response/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyper-systems/ocaml-coap/9d345f9ab47248a1d9b02c498621dfd415677568/docs/coap-core/Coap_core__Coap_response/.dune-keep -------------------------------------------------------------------------------- /docs/coap-core/Coap_core__Coap_response/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_core__Coap_response (coap-core.Coap_core__Coap_response)

Module Coap_core__Coap_response

val not_found : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Coap_core__.Coap_message.kind -> ?⁠options:Coap_core__.Coap_message.option list -> string -> Coap_core__.Coap_message.t
val content : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Coap_core__.Coap_message.kind -> ?⁠options:Coap_core__.Coap_message.option list -> string -> Coap_core__.Coap_message.t
val bad_request : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Coap_core__.Coap_message.kind -> ?⁠options:Coap_core__.Coap_message.option list -> string -> Coap_core__.Coap_message.t
-------------------------------------------------------------------------------- /docs/coap-core/index.html: -------------------------------------------------------------------------------- 1 | 2 | index (coap-core.index)

coap-core index

Library coap-core

The entry point of this library is the module: Coap_core.

-------------------------------------------------------------------------------- /docs/coap-server-lwt/Coap_server_lwt/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyper-systems/ocaml-coap/9d345f9ab47248a1d9b02c498621dfd415677568/docs/coap-server-lwt/Coap_server_lwt/.dune-keep -------------------------------------------------------------------------------- /docs/coap-server-lwt/Coap_server_lwt/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_server_lwt (coap-server-lwt.Coap_server_lwt)

Module Coap_server_lwt

val start : ?⁠host:string -> ?⁠port:int -> ((Coap_core.Message.tCoap_core.error) Stdlib.result -> Coap_core.Message.t Lwt.t) -> 'a Lwt.t
-------------------------------------------------------------------------------- /docs/coap-server-lwt/index.html: -------------------------------------------------------------------------------- 1 | 2 | index (coap-server-lwt.index)

coap-server-lwt index

Library coap-server-lwt

The entry point of this library is the module: Coap_server_lwt.

-------------------------------------------------------------------------------- /docs/coap-server-unix/Coap_server_unix/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyper-systems/ocaml-coap/9d345f9ab47248a1d9b02c498621dfd415677568/docs/coap-server-unix/Coap_server_unix/.dune-keep -------------------------------------------------------------------------------- /docs/coap-server-unix/Coap_server_unix/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap_server_unix (coap-server-unix.Coap_server_unix)

Module Coap_server_unix

val start : ?⁠host:string -> ?⁠port:int -> ((Coap_core.Message.tCoap_core.error) Stdlib.result -> Coap_core.Message.t) -> unit
-------------------------------------------------------------------------------- /docs/coap-server-unix/index.html: -------------------------------------------------------------------------------- 1 | 2 | index (coap-server-unix.index)

coap-server-unix index

Library coap-server-unix

The entry point of this library is the module: Coap_server_unix.

-------------------------------------------------------------------------------- /docs/coap/Coap/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyper-systems/ocaml-coap/9d345f9ab47248a1d9b02c498621dfd415677568/docs/coap/Coap/.dune-keep -------------------------------------------------------------------------------- /docs/coap/Coap/Message/index.html: -------------------------------------------------------------------------------- 1 | 2 | Message (coap.Coap.Message)

Module Coap.Message

type t
type kind =
| Confirmable
| Nonconfirmable
| Acknowledgement
| Reset
type code =
| Empty
| Request of [ `Get | `Post | `Put | `Delete ]
| Response of [ `Created | `Deleted | `Valid | `Changed | `Content | `Bad_request | `Unauthorized | `Bad_option | `Forbidden | `Not_found | `Method_not_allowed | `Not_acceptable | `Precondition_failed | `Request_entity_too_large | `Unsupported_content_format | `Internal_server_error | `Not_implemented | `Bad_gateway | `Service_unavailable | `Gateway_timeout | `Proxying_not_supported ]
val pp_code : Stdlib.Format.formatter -> code -> unit
type content_format = [
| `Text of [ `Plain ]
| `Application of [ `Link_format | `Xml | `Octet_stream | `Exi | `Json ]
]
type option =
| If_match of string
| Uri_host of string
| Etag of string
| If_none_match
| Uri_port of int
| Location_path of string
| Uri_path of string
| Content_format of content_format
| Max_age of int
| Uri_query of string
| Accept of int
| Location_query of string
| Proxy_uri of string
| Proxy_scheme of string
| Size1 of int
val make : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> code:code -> ?⁠kind:kind -> ?⁠options:option list -> string -> t

Coap message constructor.

val version : t -> int
val id : t -> int
val kind : t -> kind
val code : t -> code
val token : t -> string

Message token used to match a response with a request.

Token values may be 0 to 8 bytes in length.

val options : t -> option list
val path : t -> string list

Extract request path from message options.

val payload : t -> string
val is_confirmable : t -> bool
val decode : string -> (terror) Stdlib.result
val encode : t -> string
val pp : Stdlib.Format.formatter -> t -> unit
val max_size : int

Maximum safe message size.

https://tools.ietf.org/html/rfc7252#section-4.6

-------------------------------------------------------------------------------- /docs/coap/Coap/Request/index.html: -------------------------------------------------------------------------------- 1 | 2 | Request (coap.Coap.Request)

Module Coap.Request

-------------------------------------------------------------------------------- /docs/coap/Coap/Response/index.html: -------------------------------------------------------------------------------- 1 | 2 | Response (coap.Coap.Response)

Module Coap.Response

val not_found : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Message.kind -> ?⁠options:Message.option list -> string -> Message.t
val content : ?⁠version:int -> ?⁠id:int -> ?⁠token:string -> ?⁠kind:Message.kind -> ?⁠options:Message.option list -> string -> Message.t
-------------------------------------------------------------------------------- /docs/coap/Coap/Server/index.html: -------------------------------------------------------------------------------- 1 | 2 | Server (coap.Coap.Server)

Module Coap.Server

val start : ?⁠host:string -> ?⁠port:int -> ((Coap_core.Message.tCoap_core.error) Stdlib.result -> Coap_core.Message.t Lwt.t) -> 'a Lwt.t
-------------------------------------------------------------------------------- /docs/coap/Coap/index.html: -------------------------------------------------------------------------------- 1 | 2 | Coap (coap.Coap)

Module Coap

type error = [
| `Invalid_token_length
| `Invalid_option_delta
| `Invalid_option_length
]
val pp_error : Stdlib.Format.formatter -> error -> unit
module Message : sig ... end
module Request : sig ... end
module Response : sig ... end
module Server : sig ... end
-------------------------------------------------------------------------------- /docs/coap/index.html: -------------------------------------------------------------------------------- 1 | 2 | index (coap.index)

coap index

Library coap

The entry point of this library is the module: Coap.

-------------------------------------------------------------------------------- /docs/highlight.pack.js: -------------------------------------------------------------------------------- 1 | /*! highlight.js v9.15.8 | BSD3 License | git.io/hljslicense */ 2 | !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(a){var f=[],u=Object.keys,N={},c={},n=/^(no-?highlight|plain|text)$/i,s=/\blang(?:uage)?-([\w-]+)\b/i,t=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,r={case_insensitive:"cI",lexemes:"l",contains:"c",keywords:"k",subLanguage:"sL",className:"cN",begin:"b",beginKeywords:"bK",end:"e",endsWithParent:"eW",illegal:"i",excludeBegin:"eB",excludeEnd:"eE",returnBegin:"rB",returnEnd:"rE",relevance:"r",variants:"v",IDENT_RE:"IR",UNDERSCORE_IDENT_RE:"UIR",NUMBER_RE:"NR",C_NUMBER_RE:"CNR",BINARY_NUMBER_RE:"BNR",RE_STARTERS_RE:"RSR",BACKSLASH_ESCAPE:"BE",APOS_STRING_MODE:"ASM",QUOTE_STRING_MODE:"QSM",PHRASAL_WORDS_MODE:"PWM",C_LINE_COMMENT_MODE:"CLCM",C_BLOCK_COMMENT_MODE:"CBCM",HASH_COMMENT_MODE:"HCM",NUMBER_MODE:"NM",C_NUMBER_MODE:"CNM",BINARY_NUMBER_MODE:"BNM",CSS_NUMBER_MODE:"CSSNM",REGEXP_MODE:"RM",TITLE_MODE:"TM",UNDERSCORE_TITLE_MODE:"UTM",COMMENT:"C",beginRe:"bR",endRe:"eR",illegalRe:"iR",lexemesRe:"lR",terminators:"t",terminator_end:"tE"},b="",h={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function _(e){return e.replace(/&/g,"&").replace(//g,">")}function E(e){return e.nodeName.toLowerCase()}function v(e,n){var t=e&&e.exec(n);return t&&0===t.index}function l(e){return n.test(e)}function g(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function R(e){var a=[];return function e(n,t){for(var r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?t+=r.nodeValue.length:1===r.nodeType&&(a.push({event:"start",offset:t,node:r}),t=e(r,t),E(r).match(/br|hr|img|input/)||a.push({event:"stop",offset:t,node:r}));return t}(e,0),a}function i(e){if(r&&!e.langApiRestored){for(var n in e.langApiRestored=!0,r)e[n]&&(e[r[n]]=e[n]);(e.c||[]).concat(e.v||[]).forEach(i)}}function m(o){function s(e){return e&&e.source||e}function c(e,n){return new RegExp(s(e),"m"+(o.cI?"i":"")+(n?"g":""))}!function n(t,e){if(!t.compiled){if(t.compiled=!0,t.k=t.k||t.bK,t.k){function r(t,e){o.cI&&(e=e.toLowerCase()),e.split(" ").forEach(function(e){var n=e.split("|");a[n[0]]=[t,n[1]?Number(n[1]):1]})}var a={};"string"==typeof t.k?r("keyword",t.k):u(t.k).forEach(function(e){r(e,t.k[e])}),t.k=a}t.lR=c(t.l||/\w+/,!0),e&&(t.bK&&(t.b="\\b("+t.bK.split(" ").join("|")+")\\b"),t.b||(t.b=/\B|\b/),t.bR=c(t.b),t.endSameAsBegin&&(t.e=t.b),t.e||t.eW||(t.e=/\B|\b/),t.e&&(t.eR=c(t.e)),t.tE=s(t.e)||"",t.eW&&e.tE&&(t.tE+=(t.e?"|":"")+e.tE)),t.i&&(t.iR=c(t.i)),null==t.r&&(t.r=1),t.c||(t.c=[]),t.c=Array.prototype.concat.apply([],t.c.map(function(e){return function(n){return n.v&&!n.cached_variants&&(n.cached_variants=n.v.map(function(e){return g(n,{v:null},e)})),n.cached_variants||n.eW&&[g(n)]||[n]}("self"===e?t:e)})),t.c.forEach(function(e){n(e,t)}),t.starts&&n(t.starts,e);var i=t.c.map(function(e){return e.bK?"\\.?(?:"+e.b+")\\.?":e.b}).concat([t.tE,t.i]).map(s).filter(Boolean);t.t=i.length?c(function(e,n){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i')+n+(t?"":b):n}function o(){E+=null!=l.sL?function(){var e="string"==typeof l.sL;if(e&&!N[l.sL])return _(g);var n=e?C(l.sL,g,!0,f[l.sL]):O(g,l.sL.length?l.sL:void 0);return 0")+'"');return g+=n,n.length||1}var s=B(e);if(!s)throw new Error('Unknown language: "'+e+'"');m(s);var a,l=t||s,f={},E="";for(a=l;a!==s;a=a.parent)a.cN&&(E=c(a.cN,"",!0)+E);var g="",R=0;try{for(var d,p,M=0;l.t.lastIndex=M,d=l.t.exec(n);)p=r(n.substring(M,d.index),d[0]),M=d.index+p;for(r(n.substr(M)),a=l;a.parent;a=a.parent)a.cN&&(E+=b);return{r:R,value:E,language:e,top:l}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{r:0,value:_(n)};throw e}}function O(t,e){e=e||h.languages||u(N);var r={r:0,value:_(t)},a=r;return e.filter(B).filter(M).forEach(function(e){var n=C(e,t,!1);n.language=e,n.r>a.r&&(a=n),n.r>r.r&&(a=r,r=n)}),a.language&&(r.second_best=a),r}function d(e){return h.tabReplace||h.useBR?e.replace(t,function(e,n){return h.useBR&&"\n"===e?"
":h.tabReplace?n.replace(/\t/g,h.tabReplace):""}):e}function o(e){var n,t,r,a,i,o=function(e){var n,t,r,a,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=s.exec(i))return B(t[1])?t[1]:"no-highlight";for(n=0,r=(i=i.split(/\s+/)).length;n/g,"\n"):n=e,i=n.textContent,r=o?C(o,i,!0):O(i),(t=R(n)).length&&((a=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=r.value,r.value=function(e,n,t){var r=0,a="",i=[];function o(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){a+=""}function s(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var l=o();if(a+=_(t.substring(r,l[0].offset)),r=l[0].offset,l===e){for(i.reverse().forEach(u);s(l.splice(0,1)[0]),(l=o())===e&&l.length&&l[0].offset===r;);i.reverse().forEach(c)}else"start"===l[0].event?i.push(l[0].node):i.pop(),s(l.splice(0,1)[0])}return a+_(t.substr(r))}(t,R(a),i)),r.value=d(r.value),e.innerHTML=r.value,e.className=function(e,n,t){var r=n?c[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}(e.className,o,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function p(){if(!p.called){p.called=!0;var e=document.querySelectorAll("pre code");f.forEach.call(e,o)}}function B(e){return e=(e||"").toLowerCase(),N[e]||N[c[e]]}function M(e){var n=B(e);return n&&!n.disableAutodetect}return a.highlight=C,a.highlightAuto=O,a.fixMarkup=d,a.highlightBlock=o,a.configure=function(e){h=g(h,e)},a.initHighlighting=p,a.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",p,!1),addEventListener("load",p,!1)},a.registerLanguage=function(n,e){var t=N[n]=e(a);i(t),t.aliases&&t.aliases.forEach(function(e){c[e]=n})},a.listLanguages=function(){return u(N)},a.getLanguage=B,a.autoDetection=M,a.inherit=g,a.IR=a.IDENT_RE="[a-zA-Z]\\w*",a.UIR=a.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",a.NR=a.NUMBER_RE="\\b\\d+(\\.\\d+)?",a.CNR=a.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",a.BNR=a.BINARY_NUMBER_RE="\\b(0b[01]+)",a.RSR=a.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",a.BE=a.BACKSLASH_ESCAPE={b:"\\\\[\\s\\S]",r:0},a.ASM=a.APOS_STRING_MODE={cN:"string",b:"'",e:"'",i:"\\n",c:[a.BE]},a.QSM=a.QUOTE_STRING_MODE={cN:"string",b:'"',e:'"',i:"\\n",c:[a.BE]},a.PWM=a.PHRASAL_WORDS_MODE={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},a.C=a.COMMENT=function(e,n,t){var r=a.inherit({cN:"comment",b:e,e:n,c:[]},t||{});return r.c.push(a.PWM),r.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),r},a.CLCM=a.C_LINE_COMMENT_MODE=a.C("//","$"),a.CBCM=a.C_BLOCK_COMMENT_MODE=a.C("/\\*","\\*/"),a.HCM=a.HASH_COMMENT_MODE=a.C("#","$"),a.NM=a.NUMBER_MODE={cN:"number",b:a.NR,r:0},a.CNM=a.C_NUMBER_MODE={cN:"number",b:a.CNR,r:0},a.BNM=a.BINARY_NUMBER_MODE={cN:"number",b:a.BNR,r:0},a.CSSNM=a.CSS_NUMBER_MODE={cN:"number",b:a.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},a.RM=a.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[a.BE,{b:/\[/,e:/\]/,r:0,c:[a.BE]}]},a.TM=a.TITLE_MODE={cN:"title",b:a.IR,r:0},a.UTM=a.UNDERSCORE_TITLE_MODE={cN:"title",b:a.UIR,r:0},a.METHOD_GUARD={b:"\\.\\s*"+a.UIR,r:0},a});hljs.registerLanguage("ocaml",function(e){return{aliases:["ml"],k:{keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value",built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref",literal:"true false"},i:/\/\/|>>/,l:"[a-z_]\\w*!?",c:[{cN:"literal",b:"\\[(\\|\\|)?\\]|\\(\\)",r:0},e.C("\\(\\*","\\*\\)",{c:["self"]}),{cN:"symbol",b:"'[A-Za-z_](?!')[\\w']*"},{cN:"type",b:"`[A-Z][\\w']*"},{cN:"type",b:"\\b[A-Z][\\w']*",r:0},{b:"[a-z_]\\w*'[\\w']*",r:0},e.inherit(e.ASM,{cN:"string",r:0}),e.inherit(e.QSM,{i:null}),{cN:"number",b:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",r:0},{b:/[-=]>/}]}});hljs.registerLanguage("reasonml",function(r){var e="~?[a-z$_][0-9a-zA-Z$_]*",a="`?[A-Z$_][0-9a-zA-Z$_]*",c="("+["||","&&","++","**","+.","*","/","*.","/.","...","|>"].map(function(r){return r.split("").map(function(r){return"\\"+r}).join("")}).join("|")+"|==|===)",n="\\s+"+c+"\\s+",t={keyword:"and as asr assert begin class constraint do done downto else end exception externalfor fun function functor if in include inherit initializerland lazy let lor lsl lsr lxor match method mod module mutable new nonrecobject of open or private rec sig struct then to try type val virtual when while with",built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 ref string unit ",literal:"true false"},i="\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",s={cN:"number",r:0,v:[{b:i},{b:"\\(\\-"+i+"\\)"}]},b={cN:"operator",r:0,b:c},o=[{cN:"identifier",r:0,b:e},b,s],l=[r.QSM,b,{cN:"module",b:"\\b"+a,rB:!0,e:".",c:[{cN:"identifier",b:a,r:0}]}],u=[{cN:"module",b:"\\b"+a,rB:!0,e:".",r:0,c:[{cN:"identifier",b:a,r:0}]}],_={cN:"function",r:0,k:t,v:[{b:"\\s(\\(\\.?.*?\\)|"+e+")\\s*=>",e:"\\s*=>",rB:!0,r:0,c:[{cN:"params",v:[{b:e},{b:"~?[a-z$_][0-9a-zA-Z$_]*(s*:s*[a-z$_][0-9a-z$_]*((s*('?[a-z$_][0-9a-z$_]*s*(,'?[a-z$_][0-9a-z$_]*)*)?s*))?)?(s*:s*[a-z$_][0-9a-z$_]*((s*('?[a-z$_][0-9a-z$_]*s*(,'?[a-z$_][0-9a-z$_]*)*)?s*))?)?"},{b:/\(\s*\)/}]}]},{b:"\\s\\(\\.?[^;\\|]*\\)\\s*=>",e:"\\s=>",rB:!0,r:0,c:[{cN:"params",r:0,v:[{b:e,e:"(,|\\n|\\))",r:0,c:[b,{cN:"typing",b:":",e:"(,|\\n)",rB:!0,r:0,c:u}]}]}]},{b:"\\(\\.\\s"+e+"\\)\\s*=>"}]};l.push(_);var N={cN:"constructor",b:a+"\\(",e:"\\)",i:"\\n",k:t,c:[r.QSM,b,{cN:"params",b:"\\b"+e}]},d={cN:"pattern-match",b:"\\|",rB:!0,k:t,e:"=>",r:0,c:[N,b,{r:0,cN:"constructor",b:a}]},z={cN:"module-access",k:t,rB:!0,v:[{b:"\\b("+a+"\\.)+"+e},{b:"\\b("+a+"\\.)+\\(",e:"\\)",rB:!0,c:[_,{b:"\\(",e:"\\)",skip:!0}].concat(l)},{b:"\\b("+a+"\\.)+{",e:"}"}],c:l};return u.push(z),{aliases:["re"],k:t,i:"(:\\-|:=|\\${|\\+=)",c:[r.C("/\\*","\\*/",{i:"^(\\#,\\/\\/)"}),{cN:"character",b:"'(\\\\[^']+|[^'])'",i:"\\n",r:0},r.QSM,{cN:"literal",b:"\\(\\)",r:0},{cN:"literal",b:"\\[\\|",e:"\\|\\]",r:0,c:o},{cN:"literal",b:"\\[",e:"\\]",r:0,c:o},N,{cN:"operator",b:n,i:"\\-\\->",r:0},s,r.CLCM,d,_,{cN:"module-def",b:"\\bmodule\\s+"+e+"\\s+"+a+"\\s+=\\s+{",e:"}",rB:!0,k:t,r:0,c:[{cN:"module",r:0,b:a},{b:"{",e:"}",skip:!0}].concat(l)},z]}}); -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | index 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |

OCaml package documentation

13 |
    14 |
  1. coap
  2. 15 |
  3. coap-core
  4. 16 |
  5. coap-server-lwt
  6. 17 |
  7. coap-server-unix
  8. 18 |
19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /docs/odoc.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* Copyright (c) 2016 The odoc contributors. All rights reserved. 3 | Distributed under the ISC license, see terms at the end of the file. 4 | odoc 1.5.0 */ 5 | 6 | /* Fonts */ 7 | @import url('https://fonts.googleapis.com/css?family=Fira+Mono:400,500'); 8 | @import url('https://fonts.googleapis.com/css?family=Noticia+Text:400,400i,700'); 9 | @import url('https://fonts.googleapis.com/css?family=Fira+Sans:400,400i,500,500i,600,600i,700,700i'); 10 | 11 | 12 | /* Reset a few things. */ 13 | 14 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { 15 | margin: 0; 16 | padding: 0; 17 | border: 0; 18 | font-size: inherit; 19 | font: inherit; 20 | line-height: inherit; 21 | vertical-align: baseline; 22 | text-align: inherit; 23 | color: inherit; 24 | background: transparent; 25 | } 26 | 27 | table { 28 | border-collapse: collapse; 29 | border-spacing: 0; 30 | } 31 | 32 | *, *:before, *:after { 33 | box-sizing: border-box; 34 | } 35 | 36 | html { 37 | font-size: 15px; 38 | } 39 | 40 | body { 41 | font-family: "Fira Sans", Helvetica, Arial, sans-serif; 42 | text-align: left; 43 | color: #333; 44 | background: #FFFFFF; 45 | } 46 | 47 | .content { 48 | max-width: 90ex; 49 | margin-left: calc(10vw + 20ex); 50 | margin-right: 4ex; 51 | margin-top: 20px; 52 | margin-bottom: 50px; 53 | font-family: "Noticia Text", Georgia, serif; 54 | line-height: 1.5; 55 | } 56 | 57 | .content>header { 58 | margin-bottom: 30px; 59 | } 60 | 61 | .content>header nav { 62 | font-family: "Fira Sans", Helvetica, Arial, sans-serif; 63 | } 64 | 65 | /* Basic markup elements */ 66 | 67 | b, strong { 68 | font-weight: 500; 69 | } 70 | 71 | i, em { 72 | font-style: italic; 73 | } 74 | 75 | sup { 76 | vertical-align: super; 77 | } 78 | 79 | sub { 80 | vertical-align: sub; 81 | } 82 | 83 | sup, sub { 84 | font-size: 12px; 85 | line-height: 0; 86 | margin-left: 0.2ex; 87 | } 88 | 89 | pre { 90 | margin-top: 0.8em; 91 | margin-bottom: 1.2em; 92 | } 93 | 94 | p, ul, ol { 95 | margin-top: 0.5em; 96 | margin-bottom: 1em; 97 | } 98 | ul, ol { 99 | list-style-position: outside 100 | } 101 | 102 | ul>li { 103 | margin-left: 22px; 104 | } 105 | 106 | ol>li { 107 | margin-left: 27.2px; 108 | } 109 | 110 | li>*:first-child { 111 | margin-top: 0 112 | } 113 | 114 | /* Text alignements, this should be forbidden. */ 115 | 116 | .left { 117 | text-align: left; 118 | } 119 | 120 | .right { 121 | text-align: right; 122 | } 123 | 124 | .center { 125 | text-align: center; 126 | } 127 | 128 | /* Links and anchors */ 129 | 130 | a { 131 | text-decoration: none; 132 | color: #2C5CBD; 133 | } 134 | 135 | a:hover { 136 | box-shadow: 0 1px 0 0 #2C5CBD; 137 | } 138 | 139 | /* Linked highlight */ 140 | *:target { 141 | background-color: rgba(187,239,253,0.3) !important; 142 | box-shadow: 0 0px 0 1px rgba(187,239,253,0.8) !important; 143 | border-radius: 1px; 144 | } 145 | 146 | *:hover>a.anchor { 147 | visibility: visible; 148 | } 149 | 150 | a.anchor:before { 151 | content: "#" 152 | } 153 | 154 | a.anchor:hover { 155 | box-shadow: none; 156 | text-decoration: none; 157 | color: #555; 158 | } 159 | 160 | a.anchor { 161 | visibility: hidden; 162 | position: absolute; 163 | /* top: 0px; */ 164 | /* margin-left: -3ex; */ 165 | margin-left: -1.3em; 166 | font-weight: normal; 167 | font-style: normal; 168 | padding-right: 0.4em; 169 | padding-left: 0.4em; 170 | /* To remain selectable */ 171 | color: #d5d5d5; 172 | } 173 | 174 | .spec > a.anchor { 175 | margin-left: -2.3em; 176 | padding-right: 0.9em; 177 | } 178 | 179 | .xref-unresolved { 180 | color: #2C5CBD; 181 | } 182 | .xref-unresolved:hover { 183 | box-shadow: 0 1px 0 0 #CC6666; 184 | } 185 | 186 | /* Section and document divisions. 187 | Until at least 4.03 many of the modules of the stdlib start at .h7, 188 | we restart the sequence there like h2 */ 189 | 190 | h1, h2, h3, h4, h5, h6, .h7, .h8, .h9, .h10 { 191 | font-family: "Fira Sans", Helvetica, Arial, sans-serif; 192 | font-weight: 400; 193 | margin: 0.5em 0 0.5em 0; 194 | padding-top: 0.1em; 195 | line-height: 1.2; 196 | overflow-wrap: break-word; 197 | } 198 | 199 | h1 { 200 | font-weight: 500; 201 | font-size: 2.441em; 202 | margin-top: 1.214em; 203 | } 204 | 205 | h1 { 206 | font-weight: 500; 207 | font-size: 1.953em; 208 | box-shadow: 0 1px 0 0 #ddd; 209 | } 210 | 211 | h2 { 212 | font-size: 1.563em; 213 | } 214 | 215 | h3 { 216 | font-size: 1.25em; 217 | } 218 | 219 | small, .font_small { 220 | font-size: 0.8em; 221 | } 222 | 223 | h1 code, h1 tt { 224 | font-size: inherit; 225 | font-weight: inherit; 226 | } 227 | 228 | h2 code, h2 tt { 229 | font-size: inherit; 230 | font-weight: inherit; 231 | } 232 | 233 | h3 code, h3 tt { 234 | font-size: inherit; 235 | font-weight: inherit; 236 | } 237 | 238 | h3 code, h3 tt { 239 | font-size: inherit; 240 | font-weight: inherit; 241 | } 242 | 243 | h4 { 244 | font-size: 1.12em; 245 | } 246 | 247 | 248 | /* Preformatted and code */ 249 | 250 | tt, code, pre { 251 | font-family: "Fira Mono", courier; 252 | font-weight: 400; 253 | } 254 | 255 | pre { 256 | padding: 0.1em; 257 | border: 1px solid #eee; 258 | border-radius: 5px; 259 | overflow-x: auto; 260 | } 261 | 262 | p code, li code { 263 | background-color: #f6f8fa; 264 | color: #0d2b3e; 265 | border-radius: 3px; 266 | padding: 0 0.3ex; 267 | } 268 | 269 | p a > code { 270 | color: #2C5CBD; 271 | } 272 | 273 | /* Code blocks (e.g. Examples) */ 274 | 275 | pre code { 276 | font-size: 0.893rem; 277 | } 278 | 279 | /* Code lexemes */ 280 | 281 | .keyword { 282 | font-weight: 500; 283 | } 284 | 285 | /* Module member specification */ 286 | 287 | .spec:not(.include), .spec.include details summary { 288 | background-color: #f6f8fa; 289 | border-radius: 3px; 290 | border-left: 4px solid #5c9cf5; 291 | border-right: 5px solid transparent; 292 | padding: 0.35em 0.5em; 293 | } 294 | 295 | .spec.include details summary:hover { 296 | background-color: #ebeff2; 297 | } 298 | 299 | dl, div.spec, .doc, aside { 300 | margin-bottom: 20px; 301 | } 302 | 303 | dl > dd { 304 | padding: 0.5em; 305 | } 306 | 307 | dd> :first-child { 308 | margin-top: 0; 309 | } 310 | 311 | dl:last-child, dd> :last-child, aside:last-child, article:last-child { 312 | margin-bottom: 0; 313 | } 314 | 315 | dt+dt { 316 | margin-top: 15px; 317 | } 318 | 319 | section+section, section > header + dl { 320 | margin-top: 25px; 321 | } 322 | 323 | .spec.type .variant { 324 | margin-left: 2ch; 325 | } 326 | .spec.type .variant p { 327 | margin: 0; 328 | font-style: italic; 329 | } 330 | .spec.type .record { 331 | margin-left: 2ch; 332 | } 333 | .spec.type .record p { 334 | margin: 0; 335 | font-style: italic; 336 | } 337 | 338 | div.def { 339 | margin-top: 0; 340 | text-indent: -2ex; 341 | padding-left: 2ex; 342 | } 343 | 344 | div.def+div.doc { 345 | margin-left: 1ex; 346 | margin-top: 2.5px 347 | } 348 | 349 | div.doc>*:first-child { 350 | margin-top: 0; 351 | } 352 | 353 | /* The elements other than heading should be wrapped in