Myrddin: libstd

Libstd Summary

This is a summary page listing all of the functions and types available in libstd, sorted by category. The library is a bit of a grab bag of functionality, but a good chunk of what is needed will be built in to the library.

Memory Allocation

Memory allocation is a function that nearly every program needs to be able to do. Myrddin's generics allow for relatively easy to use and typesafe functions for this to be written.

pkg std =
        generic mk  : (val : @a -> @a#)
        generic alloc   : (     -> @a#)
        generic zalloc  : (     -> @a#)
        generic free    : (v:@a#    -> void)
        generic slalloc : (len : size   -> @a[:])
        generic slzalloc    : (len : size   -> @a[:])
        generic slgrow  : (sl : @a[:]#, len : size  -> @a[:])
        generic slzgrow : (sl : @a[:]#, len : size  -> @a[:])
        generic slfree  : (sl : @a[:]   -> void)
        const bytealloc : (sz:size  -> byte#)
        const zbytealloc    : (sz:size  -> byte#)
        const bytefree  : (m:byte#, sz:size -> void)
;;

Common Traits

Myrddin provides a number of common traits. These traits are implemented on several types in the standard library. They are also available for implementation from outside the standard library.

pkg std =
        trait equatable @a =
                eq      : (a : @a, b : @a -> bool)
        ;;

        trait hashable @a =
                hash    : (a : @a -> uint64)
        ;;

        impl equatable @a[:]
        impl equatable @a :: integral,numeric @a
        impl equatable @a#

        impl hashable @a[:]
        impl hashable @a :: integral,numeric @a
        impl hashable @a#
;;

Error Handling

Myrddin provides a number of types and operations for propagating errors for later handling.

It also provides operations for throwing up your hands, setting yourself on fire, and screaming, if that's more appropriate.

pkg std =
        type option(@a) = union
                `Some @a
                `None
        ;;
        pkg std =
                type result(@a, @b) = union
                        `Ok @a
                        `Err @b
                ;;
        ;;

        $noret const fatalv : (fmt : byte[:], ap : valist# -> void)
        $noret const fatal  : (fmt : byte[:], args : ... -> void)
        const assert    : (cond : bool, fmt : byte[:], args : ... -> void)
        const suicide   : ( -> void)

        generic try : (v : result(@a, @b) -> @a)
        generic tryv : (v : result(@a, @b), d : @a -> @a)
        generic get : (v : option(@a) -> @a)
        generic getv : (v : option(@a), d : @a -> @a)
;;

OS Interfaces

The OS interfaces cover some portable primitives for handling processes and OS errors. It restricts itself to a set of portable wrappers for OS functionality.

For complete interfaces, the sys library is your friend, providing all OS functionality that can be provided.

pkg std =
        type sysinfo = struct
                system  : byte[:]
                version : byte[:]
                release : byte[:]
                arch    : byte[:]
                uname   : sys.utsname   /* storage */
        ;;

        type waitstatus = union
                `Wsuccess
                `Wfailure
                `Wsignalled
                `Waiterror
        ;;

        const Enone : errno
        const Erange    : errno
        const Ebadf : errno
        const Eexist    : errno
        const Einval    : errno
        const Efault    : errno
        const Eio   : errno
        const Emisc : errno

        const getsysinfo    : (si : sysinfo# -> void)
        const execvp    : (cmd : byte[:], args : byte[:][:] -> int64)
        const execvpe   : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
        const getenv    : (name : byte[:] -> option(byte[:]))
        const getenvv   : (name : byte[:], default : byte[:] -> byte[:])
        const getpid    : ( -> pid)
        const fork      : (-> pid)
        const exec      : (cmd : byte[:], args : byte[:][:] -> int64)
        const execve    : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
        const waitpid   : (pid:pid, loc:int32#, opt : int64 -> int64)
        const spork : (cmd : byte[:][:] -> result((pid, fd, fd), int))
        const sporkfd   : (cmd : byte[:][:], infd : fd, outfd : fd  -> result(pid, int))
        const exit  : (status:int -> void)
        const wait  : (pid : pid -> waitstatus)
;;

File Handling

Many programs do file i/o by default. This package provides a portable interface to the common subset that most programs need and most OSes provide.

pkg std =
        type dir = struct
        ;;

    /* well-known file descriptors */
    const In
    const Out
    const Err


        /* seek options */
        const Seekset   : whence 
        const Seekcur   : whence 
        const Seekend   : whence 

        /* open options */
        const Ordonly   : fdopt 
        const Owronly   : fdopt 
        const Ordwr     : fdopt 
        const Otrunc    : fdopt 
        const Ocreat    : fdopt 
        const Oappend   : fdopt 
        const Odir  : fdopt 

        /* directory handling */
        const diropen   : (p : byte[:] -> std.result(dir#, byte[:]))
        const dirread   : (d : dir# -> std.option(byte[:]))
        const dirclose  : (d : dir# -> void)
        const dirname   : (p : byte[:] -> byte[:])
        const mkdir : (path : byte[:], mode : int64 -> int64)
        const mkpath    : (p : byte[:] -> bool)
        const chdir : (path : byte[:] -> bool)

        /* file handling */
        const open  : (path : byte[:], opts : fdopt -> fd)
        const openmode  : (path : byte[:], opts : fdopt, mode : int64 -> fd)
        const close : (fd : fd -> int64)
        const creat : (path : byte[:], mode : int64 -> fd)
        const read  : (fd : fd, buf : byte[:] -> size)
        const write : (fd : fd, buf : byte[:] -> size)
        const seek  : (fd : fd, delta : off, whence : whence -> off)
        const pipe  : (fds : fd[2]# -> int64)
        const dup2  : (ofd : fd, nfd : fd -> fd)
        const remove    : (path : byte[:] -> bool)
        const unlink    : (path : byte[:] -> int)

        /* path manipulation */
        const basename  : (p : byte[:] -> byte[:])
        const pathcat   : (a : byte[:], b : byte[:] -> byte[:])
        const pathjoin  : (p : byte[:][:] -> byte[:])
        const pathnorm  : (p : byte[:] -> byte[:])
        const getcwd : (-> byte[:])

        /* file properties */
        const fmtime    : (f : byte[:]  -> option(time))
        const fsize : (f : byte[:]  -> option(off))
        const fexists   : (f : byte[:]  -> bool)
        const fisdir    : (f : byte[:]  -> bool)

        /* convenience functions */
        const slurp : (path : byte[:] -> result(byte[:], byte[:]))
        const fslurp : (path : fd -> result(byte[:], byte[:]))
        const blat : (path : byte[:], buf : byte[:], perm : int64 -> bool)
        const fblat : (f : fd, buf : byte[:] -> bool)
;;

Networking

The networking related functionality in libstd provides the ability to quickly and easily open file descriptors to a server, as well as to resolve servers and handle IP parsing.

Currently, there is a large hole in functionality for announcing and serving, where raw system specific network APIs neeed to be used from the sys library.

pkg std =
        type rectype = union
                `DnsA   /* host address */
                `DnsNS  /* authoritative name server */
                `DnsCNAME   /* canonical name for an alias */
                `DnsSOA /* marks the start of a zone of authority */
                `DnsWKS /* well known service description */
                `DnsPTR /* domain name pointer */
                `DnsHINFO   /* host information */
                `DnsMINFO   /* mailbox or mail list information */
                `DnsMX  /* mail exchange */
                `DnsTXT /* text strings */
                `DnsAAAA    /* ipv6 host address */
        ;;

        type resolveerr = union
                `Badhost
                `Badsrv
                `Badquery
                `Badresp
        ;;

        type hostinfo = struct
                fam : sys.sockfam
                stype   : sys.socktype
                ttl : uint32
                addr    : ipaddr
        ;;

        type ipaddr = union
                `Ipv4   byte[4]
                `Ipv6   byte[16]
        ;;

        /* network connections */
        const dial  : (dialstr : byte[:] -> result(fd, byte[:]))
        const resolve   : (host : byte[:]   -> result(hostinfo[:], resolveerr))
        const resolvemx : (host : byte[:]   -> result(hostinfo[:], resolveerr))
        const resolverec    : (host : byte[:], t : rectype  -> result(hostinfo[:], resolveerr))

        /* ip parsing */
        const ipparse   : (ip : byte[:] -> option(ipaddr))
        const ip4parse  : (ip : byte[:] -> option(ipaddr))
        const ip6parse  : (ip : byte[:] -> option(ipaddr))

        generic hosttonet   : (v : @a -> @a)
        generic nettohost   : (v : @a -> @a)
;;

Command Line Parsing

Simple command line parsing is offered, designed to meet the needs of most programs quickly and easily. There isn't much to say here.

pkg std =
        type optdef = struct
                argdesc : byte[:]   /* the description for the usage */
                minargs : std.size  /* the minimum number of positional args */
                maxargs : std.size  /* the maximum number of positional args (0 = unlimited) */
                noargs  : std.bool  /* whether we accept args at all */
                opts    : optdesc[:]    /* the description of the options */
        ;;
        type optdesc = struct
                opt : char
                arg : byte[:]
                desc    : byte[:]
                optional    : bool
        ;;
        type optparsed = struct
                opts    : (char, byte[:])[:]
                args    : byte[:][:]
        ;;

        const optparse  : (optargs : byte[:][:], def : optdef# -> optparsed)
        const optusage  : (prog : byte[:], def : optdef# -> void)
;;

Formatted Output

libstd supports a number of simple, easy to use formatting functions, which can provide a sane format for any type out of the box, but also support custom formatters for specific types, so that they can be pretty printed. Many of the builtin types, such as bigints, install custom formatters by default.

pkg std =
        /* output to file descriptors */
        const put   : (fmt : byte[:], args : ... -> size)
        const fput  : (fd : fd, fmt : byte[:], args : ... -> size)
        const putv  : (fmt : byte[:], ap : valist# -> size)
        const fputv : (fd : fd, fmt : byte[:], ap : valist# -> size)

        /* formatting values */
        const fmt   : (fmt : byte[:], args : ... -> byte[:])
        const fmtv  : (fmt : byte[:], ap : valist# -> byte[:])
        const bfmt  : (buf : byte[:], fmt : byte[:], args : ... -> byte[:])
        const bfmtv : (buf : byte[:], fmt : byte[:], ap : valist# -> byte[:])
        const sbfmt : (buf : strbuf#, fmt : byte[:], args : ... -> size)
        const sbfmtv    : (buf : strbuf#, fmt : byte[:], ap : valist# -> size)

        /* custom formatting */
        const fmtinstall    : (ty : byte[:], \
                fn : (sb : strbuf#, \
                        ap : valist#, \
                        opts : (byte[:],byte[:])[:] \
                        -> void), \
    optdesc : (byte[:], bool)[:] \
    -> void)
;;

Variadic Arguments

Myrddin supports variadic arguments for functions, and allows you to walk over them, similar to the varargs functions in C, but safer.

In addition, the Myrddin compiler generates type information for the types that are compiled into a program. This code provides a rather awkward API for iterating over them, and inspecting their values.

pkg std =
        type typedesc = union
                `Tynone

                /* atomic types */
                `Tyvoid
                `Tybool
                `Tychar

                `Tyint8
                `Tyint16
                `Tyint
                `Tyint32
                `Tyint64

                `Tybyte
                `Tyuint8
                `Tyuint16
                `Tyuint
                `Tyuint32
                `Tyuint64
                `Tyflt32
                `Tyflt64
                `Tyvalist

                /* compound types */
                `Typtr byte[:]
                `Tyfunc typecursor
                `Tyslice byte[:]
                `Tyarray (size, byte[:])

                /* aggregate types */
                `Tytuple    typecursor
                `Tystruct   typecursor
                `Tyunion    typecursor
                /* name info */
                `Tyname (byte[:], byte[:])
        ;;
        type typecursor = struct
                nelt    : size
                rem : byte[:]
                isnamed : bool
                isiter  : bool
        ;;
        type typeinfo = struct
                size    : size
                align   : size
        ;;
        generic typeof  : (v : @a -> byte[:])
        const typeenc   : (p : ...# -> typecursor)
        const typeenccursor : (e : byte[:] -> typecursor)
        const typedesc  : (e : byte[:] -> typedesc)
        const typeinfo  : (e : byte[:] -> typeinfo)
        const tcnext    : (t : typecursor# -> byte[:])
        const tcpeek    : (t : typecursor# -> byte[:])
        const ncpeek    : (t : typecursor# -> (byte[:], byte[:]))
        const ncnext    : (t : typecursor# -> (byte[:], byte[:]))

        const vastart   : (args : ...# -> valist)
        const vatype    : (ap : valist# -> byte[:])
        const vabytes   : (ap : valist# -> byte[:])
        const vaenter   : (ap : valist# -> valist)
        generic vanext  : (ap : valist# -> @a)
;;

Slice manipulation

Slices are used everywhere within Myrddin code, so clearly we have some functions to manipulate them. They're listed here. Boopity boopity boo.

pkg std =
        generic sleq    : (a : @a[:], b : @a[:] -> bool)
        generic slcp    : (a : @a[:], b : @a[:] -> void)
        generic slput   : (sl : @a[:], idx : size, elt : @a -> @a[:])
        generic slpush  : (sl : @a[:]#, elt : @a    -> @a[:])
        generic sldup   : (sl : @a[:] -> @a[:])
        generic slfill  : (sl : @a[:], v : @a   -> @a[:])
        generic sljoin  : (dst : @a[:]#, src : @a[:]    -> @a[:])
;;

Pledge

Pledge is a useful security feature.

const pledge    : (promise : byte[:], epromise : byte[:] -> result(void, errno))

String Manipulation

String manipulation also tends to show up in code sometimes. Here are some functions that do that. These are all unicode aware, and will not corrupt utf8 data.

pkg std =
        /* string buffers */
        type strbuf = struct
        ;;

        const mksb  : (-> strbuf#)
        const mkbufsb   : (buf : byte[:] -> strbuf#)
        const sbfin : (sb : strbuf# -> byte[:])
        const sbfree    : (sb : strbuf# -> void)
        const sbpeek    : (sb : strbuf# -> byte[:])
        const sbputc    : (sb : strbuf#, v : char -> bool)
        const sbputs    : (sb : strbuf#, v : byte[:] -> bool)
        const sbputb    : (sb : strbuf#, v : byte -> bool)
        const sbtrim    : (sb : strbuf#, len : size -> void)

        /* string searching */
        const strfind   : (haystack : byte[:], needle : byte[:] -> option(size))
        const strrfind  : (haystack : byte[:], needle : byte[:] -> option(size))
        const strhas    : (haystack : byte[:], needle : byte[:] -> bool)
        const hasprefix : (s : byte[:], pre : byte[:] -> bool)
        const hassuffix : (s : byte[:], suff : byte[:] -> bool)

        /* C strings */
        const cstrlen   : (buf : byte[:] -> size)
        const cstrconv  : (buf : byte[:] -> byte[:])
        const cstrconvp : (p : byte# -> byte[:])

        /* tokenizing and splitting */
        const strsplit  : (s : byte[:], delim : byte[:] -> byte[:][:])
        const strtok    : (s : byte[:] -> byte[:][:])

        /* string joining and stripping */
        const strcat    : (a : byte[:], b : byte[:] -> byte[:])
        const strjoin   : (strings : byte[:][:], delim : byte[:] -> byte[:])
        const strstrip  : (str : byte[:] -> byte[:])
        const strfstrip : (str : byte[:] -> byte[:])
        const strrstrip : (str : byte[:] -> byte[:])

        /* parsing numbers out of strings */
        generic intparsebase    : (s : byte[:], base : int -> option(@a)) :: integral,numeric @a
        generic intparse    : (s : byte[:]  -> option(@a)) :: integral,numeric @a
        generic charval : (c : char, base : int -> @a) :: integral,numeric @a
;;

Unicode

A bunch of predicates and conversions to handle unicode. This only provides simple functionality. For canonicalization, collation, and all of the other UAX algorithms, go look in.. oh, who am I kidding. I haven't had a chance to write them yet.

pkg std =
        const Badchar   : char 
        const Maxcharlen : size 
        const Maxcharval : char 

        /* utf8 information */
        const charlen   : (chr : char -> size)
        const encode    : (buf : byte[:], chr : char -> size)
        const decode    : (buf : byte[:] -> char)
        const striter   : (str : byte[:] -> (char, byte[:]))

        /* character class predicates */
        const isalpha   : (c : char -> bool)
        const isdigit   : (c : char -> bool)
        const isxdigit  : (c : char -> bool)
        const isnum : (c : char -> bool)
        const isalnum   : (c : char -> bool)
        const isspace   : (c : char -> bool)
        const isblank   : (c : char -> bool)
        const islower   : (c : char -> bool)
        const isupper   : (c : char -> bool)
        const istitle   : (c : char -> bool)

        /* character class conversions */
        const tolower   : (c : char -> char)
        const toupper   : (c : char -> char)
        const totitle   : (c : char -> char)
;;

Pervasive Data Structures

There are some data structures that basically every program seems to use: Sets, and hash tables. Libstd includes them for that reason.

pkg std =
        type bitset = struct
        ;;

        type htab(@k, @v) = struct
        ;;

    type htkviter(@k, @v)
    impl iterable htkviter

    type bsiter = struct
    impl iterable bsiter

        /* bit sets */
        const mkbs  : (-> bitset#)
        const bsdup : (bs : bitset# -> bitset#)
        const bsfree    : (bs : bitset# -> void)
        const bsmax : (a : bitset# -> size)
        const bscount   : (a : bitset# -> size)
        generic bsput   : (bs : bitset#, v : @a -> bool) :: integral,numeric @a
        generic bsdel   : (bs : bitset#, v : @a -> bool) :: integral,numeric @a
        generic bshas   : (bs : bitset#, v : @a -> bool) :: integral,numeric @a
        const bsdiff    : (a : bitset#, b : bitset# -> void)
        const bsintersect   : (a : bitset#, b : bitset# -> void)
        const bsunion   : (a : bitset#, b : bitset# -> void)
        const bseq  : (a : bitset#, b : bitset# -> bool)
        const bsissubset    : (a : bitset#, b : bitset# -> bool)
        const bsclear   : (bs : bitset# -> bitset#)
    const bybsvalue : (bs : bitset# -> bsiter)

        /* hash tables */
        generic mkht    : (-> htab(@k, @v)#) :: hashable,equatable @k
        generic htfree  : (ht : htab(@k, @v)# -> void) :: hashable,equatable @k
        generic htput   : (ht : htab(@k, @v)#, k : @k, v : @v -> void) :: hashable,equatable @k
        generic htdel   : (ht : htab(@k, @v)#, k : @k -> void) :: hashable,equatable @k
        generic htget   : (ht : htab(@k, @v)#, k : @k -> option(@v))  :: hashable,equatable @k
        generic htgetv  : (ht : htab(@k, @v)#, k : @k, fallback : @v-> @v) :: hashable,equatable @k
        generic hthas   : (ht : htab(@k, @v)#, k : @k -> bool)  :: hashable,equatable @k
        generic htkeys  : (ht : htab(@k, @v)# -> @k[:]) :: hashable,equatable @k
        generic byhtkeyvals : (ht : htab(@k, @v)# -> htkviter(@k, @v)) :: hashable,equatable @k
;;

Pervasive Algorithms

Many programs also use sorting and searching, so this is also provided by libstd. In addition, we package some useful comparison and hashing functions

pkg std =
        /* the result of a comparison */
        type order = union
                `Before
                `Equal
                `After
        ;;

        /* sorting and searching */
        generic sort    : (sl:@a[:], cmp:(a:@a, b:@a -> order) -> @a[:])
        generic lsearch : (sl : @t[:], val : @t, cmp : (a : @t, b : @t -> order) -> option(@idx)) :: integral,numeric @a
        generic bsearch : (sl : @t[:], val : @t, cmp : (a : @t, b : @t -> order) -> option(@idx)) :: integral,numeric @a
        generic swap    : (a : @a#, b : @a# -> void)

        /* prepackaged comparisons */
        generic numcmp  : (a : @a, b : @a -> order)
        const strcmp    : (a : byte[:], b : byte[:] -> order)
        const strncmp   : (a : byte[:], b : byte[:], n : size -> order)

        /* extrema and absolute values */
        generic min : (a : @a, b : @a  -> @a) :: numeric @a
        generic max : (a : @a, b : @a  -> @a) :: numeric @a
        generic clamp   : (a : @a, min : @a, max : @a -> @a) :: numeric @a
        generic abs : (a : @a -> @a) :: numeric @a
;;

Randomness

And of course, you can't go without being a little random at times.

pkg std =
        const mksrng    : (seed : uint32 -> rng#)
        const freerng   : (rng : rng# -> void)
        generic rand    : (lo : @a, hi : @a -> @a) :: numeric,integral @a
        generic rngrand : (rng : rng#, lo : @a, hi : @a -> @a) :: numeric,integral @a
        generic rngrandnum  : (rng : rng# -> @a) :: numeric,integral @a
        const rngrandbytes  : (rng : rng#, buf : byte[:]    -> size)
;;

Bigint Operations

While bigint usage in most programs is relatively rare, libstd needs them internally for handling floats, and several other widely used pieces of functionality also need them.

As they are a significant amount of code, I decided it made sense to expose them in the public API.

pkg std =
        type bigint = struct
        ;;

        generic mkbigint    : (v : @a -> bigint#) :: numeric,integral @a
        const bigfree   : (a : bigint# -> void)
        const bigdup    : (a : bigint# -> bigint#)
        const bigassign : (d : bigint#, s : bigint# -> bigint#)
        const bigmove   : (d : bigint#, s : bigint# -> bigint#)
        const bigparse  : (s : byte[:] -> option(bigint#))
        const bigclear  : (a : bigint# -> bigint#)
        const bigbfmt   : (b : byte[:], a : bigint#, base : int -> size)
        const bigtoint  : (a : bigint#  -> @a) :: numeric,integral @a
        const bigiszero : (a : bigint# -> bool)
        const bigeq : (a : bigint#, b : bigint# -> bool)
        const bigcmp    : (a : bigint#, b : bigint# -> order)
        const bigadd    : (a : bigint#, b : bigint# -> bigint#)
        const bigsub    : (a : bigint#, b : bigint# -> bigint#)
        const bigmul    : (a : bigint#, b : bigint# -> bigint#)
        const bigdiv    : (a : bigint#, b : bigint# -> bigint#)
        const bigmod    : (a : bigint#, b : bigint# -> bigint#)
        const bigdivmod : (a : bigint#, b : bigint# -> (bigint#, bigint#))
        const bigshl    : (a : bigint#, b : bigint# -> bigint#)
        const bigshr    : (a : bigint#, b : bigint# -> bigint#)
        const bigmodpow : (b : bigint#, e : bigint#, m : bigint# -> bigint#)
        const bigpow    : (a : bigint#, b : bigint# -> bigint#)
        generic bigeqi  : (a : bigint#, b : @a -> bool  :: numeric,integral @a
        generic bigaddi : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
        generic bigsubi : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
        generic bigmuli : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
        generic bigdivi : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
        generic bigshli : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
        generic bigshri : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
        const bigpowi   : (a : bigint#, b : uint64 -> bigint#)
;;

Closures

There are functions for heapifying closures, too.

pkg std =
        generic fndup   : (fn : @fn-> @fn) :: function @fn 
        generic fnfree  : (fn : @fn-> void) :: function @fn
        generic fnenvsz : (fn : @fn -> size)    :: function @fn
        generic fnbdup  : (fn : @fn, buf : byte[:] -> @fn)  :: function @fn
;;

Misc

Well, I said it was a grab bag. These don't really fit into any overarching category.

pkg std =
        generic KiB : @a :: integral,numeric @a 
        generic MiB : @a :: integral,numeric @a 
        generic GiB : @a :: integral,numeric @a 
        generic TiB : @a :: integral,numeric @a 
        generic PiB : @a :: integral,numeric @a 
        generic EiB : @a :: integral,numeric @a 
        generic ZiB : @a :: integral,numeric @a 
        generic YiB : @a :: integral,numeric @a 

        generic Sec  : @a :: integral,numeric @a
        generic Msec  : @a :: integral,numeric @a
        generic Usec  : @a :: integral,numeric @a

        /* time */
        const now   : (-> time)

        /* packing integers */
        generic putle64 : (buf : byte[:], v :  @a -> size) :: numeric,integral @a
        generic putbe64 : (buf : byte[:], v :  @a -> size) :: numeric,integral @a
        generic putle32 : (buf : byte[:], v :  @a -> size) :: numeric,integral @a
        generic putbe32 : (buf : byte[:], v :  @a -> size) :: numeric,integral @a
        generic putle16 : (buf : byte[:], v :  @a -> size) :: numeric,integral @a
        generic putbe16 : (buf : byte[:], v :  @a -> size) :: numeric,integral @a
        generic putle8  : (buf : byte[:], v :  @a -> size) :: numeric,integral @a
        generic putbe8  : (buf : byte[:], v :  @a -> size) :: numeric,integral @a

        /* unpacking integers */
        generic getle64 : (buf : byte[:]    -> @a) :: numeric,integral @a
        generic getbe64 : (buf : byte[:]    -> @a) :: numeric,integral @a
        generic getle32 : (buf : byte[:]    -> @a) :: numeric,integral @a
        generic getbe32 : (buf : byte[:]    -> @a) :: numeric,integral @a
        generic getle16 : (buf : byte[:]    -> @a) :: numeric,integral @a
        generic getbe16 : (buf : byte[:]    -> @a) :: numeric,integral @a
        generic getle8  : (buf : byte[:]    -> @a) :: numeric,integral @a
        generic getbe8  : (buf : byte[:]    -> @a) :: numeric,integral @a

        /* exploding and stitching floats */
        const flt64bits : (flt : flt64 -> uint64)
        const flt32bits : (flt : flt32 -> uint32)
        const flt64frombits : (bits : uint64 -> flt64)
        const flt32frombits : (bits : uint32 -> flt32)
        const flt64explode  : (flt : flt64 -> (bool, int64, uint64))
        const flt32explode  : (flt : flt32 -> (bool, int32, uint32))
        const flt64stitch   : (flt : flt64 -> (bool, int64, uint64))
        const flt32stitch   : (flt : flt32 -> (bool, int32, uint32))

;;