packageppx_cstruct
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=9a78073392580e8349148fa3ab4b1b2e989dc9d30d07401b04c96b7c60f03e62
sha512=8d33fe6b3707a3994d0225cd33cadde0bb2ca834ef01096e3df33a08e4a8c6d02ebccddf558a73988b8a5595b65fdc10de61efbf872c6c9e55c719c7e19c463d
Description
Cstruct is a library and syntax extension to make it easier to access C-likestructures directly from OCaml. It supports both reading and writing to thesestructures, and they are accessed via theBigarray
module.
README
Cstruct - access C-like structures directly from OCaml
Cstruct is a library and syntax extension to make it easier to access C-like structures directly from OCaml. It supports both reading and writing to these structures, and they are accessed via theBigarray
module.
Installation
This repository provides several packages that can be installed via theopam package manager:
cstruct
: the core Cstruct librarycstruct-sexp
: serialisers into s-expression format of Cstructscstruct-unix
: provide Unix variations of the read/write functions using file descriptorscstruct-async
: provideAsync Pipe and Bigstring supportcstruct-lwt
: provideLwt variants of read/write functionsppx_cstruct
: aPPX syntax extension (see below)
The libraries depend on OCaml version 4.08.0 and later, since it provides appx extension point. The oldcamlp4 syntax extension is nolonger available; the last cstruct release which contained it was v1.9.0.
Local development
You can build the library viadune, usingmake
ordune build
directly. Since everything is built via dune, you can also place this repository within a wider dune workspace in order to make local modifications across repositories.
Documentation
A documentation of the last version ofcstruct
is availablehere.
Usage
PPX
The PPX processor is used by passing the OCaml source code through theppx_cstruct
binary. An example pcap description is:
[%%cstructtype pcap_header = { magic_number: uint32_t; (* magic number *) version_major: uint16_t; (* major version number *) version_minor: uint16_t; (* minor version number *) thiszone: uint32_t; (* GMT to local correction *) sigfigs: uint32_t; (* accuracy of timestamps *) snaplen: uint32_t; (* max length of captured packets, in octets *) network: uint32_t; (* data link type *)} [@@little_endian]][%%cstructtype pcap_packet = { ts_sec: uint32_t; (* timestamp seconds *) ts_usec: uint32_t; (* timestamp microseconds *) incl_len: uint32_t; (* number of octets of packet saved in file *) orig_len: uint32_t; (* actual length of packet *)} [@@little_endian]][%%cstructtype ethernet = { dst: uint8_t [@len 6]; src: uint8_t [@len 6]; ethertype: uint16_t;} [@@big_endian]][%%cstructtype ipv4 = { hlen_version: uint8_t; tos: uint8_t; len: uint16_t; id: uint16_t; off: uint16_t; ttl: uint8_t; proto: uint8_t; csum: uint16_t; src: uint8_t [@len 4]; dst: uint8_t [@len 4];} [@@big_endian]]
This auto-generates generates functions of the form below in theml
file:
let sizeof_pcap_packet = 16let get_pcap_packet_ts_sec v = Cstruct.LE.get_uint32 v 0let set_pcap_packet_ts_sec v x = Cstruct.LE.set_uint32 v 0 xlet get_pcap_packet_ts_usec v = Cstruct.LE.get_uint32 v 4let set_pcap_packet_ts_usec v x = Cstruct.LE.set_uint32 v 4 xlet get_pcap_packet_incl_len v = Cstruct.LE.get_uint32 v 8let set_pcap_packet_incl_len v x = Cstruct.LE.set_uint32 v 8 xlet get_pcap_packet_orig_len v = Cstruct.LE.get_uint32 v 12let set_pcap_packet_orig_len v x = Cstruct.LE.set_uint32 v 12 xlet sizeof_ethernet = 14let get_ethernet_dst src = Cstruct.sub src 0 6let copy_ethernet_dst src = Cstruct.copy src 0 6let set_ethernet_dst src srcoff dst = Cstruct.blit_from_string src srcoff dst 0 6let blit_ethernet_dst src srcoff dst = Cstruct.blit src srcoff dst 0 6let get_ethernet_src src = Cstruct.sub src 6 6let copy_ethernet_src src = Cstruct.copy src 6 6let set_ethernet_src src srcoff dst = Cstruct.blit_from_string src srcoff dst 6 6let blit_ethernet_src src srcoff dst = Cstruct.blit src srcoff dst 6 6let get_ethernet_ethertype v = Cstruct.BE.get_uint16 v 12let set_ethernet_ethertype v x = Cstruct.BE.set_uint16 v 12 x
Themli
file will have signatures of this form:
val sizeof_pcap_packet : intval get_pcap_packet_ts_sec : Cstruct.t -> Cstruct.uint32val set_pcap_packet_ts_sec : Cstruct.t -> Cstruct.uint32 -> unitval get_pcap_packet_ts_usec : Cstruct.t -> Cstruct.uint32val set_pcap_packet_ts_usec : Cstruct.t -> Cstruct.uint32 -> unitval get_pcap_packet_incl_len : Cstruct.t -> Cstruct.uint32val set_pcap_packet_incl_len : Cstruct.t -> Cstruct.uint32 -> unitval get_pcap_packet_orig_len : Cstruct.t -> Cstruct.uint32val set_pcap_packet_orig_len : Cstruct.t -> Cstruct.uint32 -> unitval hexdump_pcap_packet_to_buffer : Buffer.t -> pcap_packet -> unitval hexdump_pcap_packet : Cstruct.t -> unitval sizeof_ethernet : intval get_ethernet_dst : Cstruct.t -> Cstruct.tval copy_ethernet_dst : Cstruct.t -> stringval set_ethernet_dst : string -> int -> Cstruct.t -> unitval blit_ethernet_dst : Cstruct.t -> int -> Cstruct.t -> unitval get_ethernet_src : Cstruct.t -> Cstruct.tval copy_ethernet_src : Cstruct.t -> stringval set_ethernet_src : string -> int -> Cstruct.t -> unitval blit_ethernet_src : Cstruct.t -> int -> Cstruct.t -> unitval get_ethernet_ethertype : Cstruct.t -> Cstruct.uint16val set_ethernet_ethertype : Cstruct.t -> Cstruct.uint16 -> unitval hexdump_ethernet_to_buffer : Buffer.t -> Cstruct.t -> unitval hexdump_ethernet : Cstruct.t -> unit
Thehexdump
functions above are convenient pretty-printing functions to help you debug, and aren't intended to be high performance.
You can also declare C-like enums:
[%%cenumtype foo32 = | ONE32 | TWO32 [@id 0xfffffffel] | THREE32 [@@uint32_t]][%%cenumtype bar16 = | ONE [@id 1] | TWO | FOUR [@id 4] | FIVE [@@uint16_t]]
This generates signatures of the form:
type foo32 = | ONE32 | TWO32 | THREE32val int_to_foo32 : int32 -> foo32 optionval foo32_to_int : foo32 -> int32val foo32_to_string : foo32 -> stringval string_to_foo32 : string -> foo32 optionval compare_foo32 : foo32 -> foo32 -> inttype bar16 = | ONE | TWO | FOUR | FIVEval int_to_bar16 : int -> bar16 optionval bar16_to_int : bar16 -> intval bar16_to_string : bar16 -> stringval string_to_bar16 : string -> bar16 optionval compare_bar16 : bar16 -> bar16 -> int
Comparisons will be done relatively to the constructor ids.
You can also add a(sexp)
decorator to output s-expression convertors for use with thesexplib
library.
[%%cenumtype foo64 = | ONE64 | TWO64 | THREE64 [@@uint64_t] [@@sexp]]
Andsexp_of_foo64
andfoo64_of_sexp
functions will also be available. The representation of the Sexp is the string representation of the enum.
If you do use the sexp decorator, then you will also need to addsexplib
to the dependency list for your package (both in thedune
file and theopam
file).
Please see theppx_test/
directory for more in-depth examples.
Dependencies (5)
Dev Dependencies (7)
- lwt_ppx
>= "2.0.2" & with-test
- ocaml-migrate-parsetree
>= "2.1.0" & with-test
- cstruct-unix
with-test & = version
- cppo
with-test
- cstruct-sexp
with-test
- ppx_sexp_conv
with-test
- ounit
with-test
Used by (34)
- arp
= "0.2.1"
- awa
< "0.2.0"
- chamelon
- charrua
< "1.6.0"
- charrua-core
- charrua-server
>= "1.4.0" & < "1.6.0"
- dbase4
- dbf
- dns
< "4.0.0"
- ethernet
< "3.1.0"
- fat-filesystem
- frenetic
- learn-ocaml
- mbr-format
< "2.0.0"
- mirage-block-xen
< "2.1.3"
- mirage-profile
- mirage-qubes
>= "0.8.1" & < "0.9.5"
- nbd
>= "4.0.3"
- netchannel
- pcap-format
>= "0.5.2"
- protocol-9p
< "0.11.0"
- rawlink
- shared-block-ring
- shared-memory-ring
< "3.2.1"
- shared-memory-ring-lwt
< "3.2.1"
- ssh-agent
- tar
>= "1.0.0" & < "2.4.0"
- tcpip
< "3.4.2" | >= "6.1.0" & < "8.0.0"
- tls
< "0.17.0"
- vchan
< "6.0.2"
- vchan-unix
< "6.0.2"
- vchan-xen
< "6.0.2"
- vhd-format
- xenstore
>= "2.1.0" & < "2.3.0"
Conflicts
None