Files
zomq/zmq.odin
T

165 lines
3.7 KiB
Odin

package zmq
import "core:c"
import "core:os"
import "core:strings"
foreign import lib "system:zmq"
Context :: distinct rawptr
Socket :: distinct rawptr
@(default_calling_convention = "c", link_prefix = "zmq_")
foreign lib {
// TODO: Try to access errno directly
errno :: proc() -> c.int ---
ctx_new :: proc() -> Context ---
@(link_name = "zmq_ctx_term")
_ctx_term :: proc(ctx: Context) -> c.int ---
@(link_name = "zmq_socket")
_socket :: proc(ctx: Context, type: Socket_Type) -> Socket ---
@(link_name = "zmq_close")
_close :: proc(s: Socket) -> c.int ---
@(link_name = "zmq_bind")
_bind :: proc(s: Socket, addr: cstring) -> c.int ---
@(link_name = "zmq_connect")
_connect :: proc(s: Socket, addr: cstring) -> c.int ---
@(link_name = "zmq_send")
_send :: proc(s: Socket, buf: rawptr, len: c.size_t, flags: Flags) -> c.int ---
@(link_name = "zmq_send_const")
_send_const :: proc(s: Socket, buf: rawptr, len: c.size_t, flags: Flags) -> c.int ---
@(link_name = "zmq_recv")
_recv :: proc(s: Socket, buf: rawptr, len: c.size_t, flags: Flags) -> c.int ---
@(link_name = "zmq_strerror")
_strerror :: proc(errnum: c.int) -> cstring ---
@(link_name = "zmq_version")
_version :: proc(major, minor, patch: ^c.int) ---
}
Socket_Type :: enum c.int {
PAIR = 0,
PUB = 1,
SUB = 2,
REQ = 3,
REP = 4,
DEALER = 5,
ROUTER = 6,
PULL = 7,
PUSH = 8,
XPUB = 9,
XSUB = 10,
STREAM = 11,
}
Flag :: enum c.int {
DONTWAIT = 1,
SNDMORE = 2,
}
Flags :: bit_set[Flag;c.int]
NoBlock :: Flags{.DONTWAIT}
Error :: union #shared_nil {
os.Platform_Error,
ZMQ_Error,
}
strerror :: proc(e: Error) -> cstring {
switch v in e {
case os.Platform_Error:
return _strerror(c.int(v))
case ZMQ_Error:
return _strerror(denormalize_from_zmq(c.int(v)))
case:
return _strerror(0)
}
}
version :: proc() -> (major, minor, patch: int) {
ma, mi, pa: c.int = 0, 0, 0
_version(&ma, &mi, &pa)
return int(ma), int(mi), int(pa)
}
ctx_term :: proc(ctx: Context) -> Error {
return _ctx_term(ctx) == 0 ? nil : last_error()
}
socket :: proc(ctx: Context, type: Socket_Type) -> (s: Socket, err: Error) {
s = _socket(ctx, type)
if s == nil {
err = last_error()
}
return s, err
}
close :: proc(s: Socket) -> Error {
return _close(s) == 0 ? nil : last_error()
}
bind :: proc(s: Socket, addr: string, allocator := context.temp_allocator) -> Error {
c := strings.clone_to_cstring(addr, allocator)
return _bind(s, c) == 0 ? nil : last_error()
}
connect :: proc(s: Socket, addr: string, allocator := context.temp_allocator) -> Error {
c := strings.clone_to_cstring(addr, allocator)
return _connect(s, c) == 0 ? nil : last_error()
}
send :: proc {
send_bytes,
send_string,
}
send_bytes :: proc(s: Socket, buf: []u8, flags: Flags = {}) -> (int, Error) {
n := _send(s, rawptr(&buf[0]), c.size_t(len(buf)), flags)
if n < 0 {
return -1, last_error()
}
return int(n), nil
}
send_string :: proc(s: Socket, buf: string, flags: Flags = {}) -> (int, Error) {
return send_bytes(s, transmute([]u8)buf, flags)
}
send_const :: proc {
send_const_string,
send_const_bytes,
}
send_const_string :: proc(s: Socket, $str: string, flags: Flags = {}) -> (int, Error) {
n := _send_const(s, rawptr($str), len($str), flags)
if n < 0 {
return -1, last_error()
}
return int(n), nil
}
// buf must have @(rodata) or global lifetime.
send_const_bytes :: proc(s: Socket, buf: []byte, flags: Flags = {}) -> (int, Error) {
n := _send_const(s, rawptr(&buf[0]), len(buf), flags)
if n < 0 {
return -1, last_error()
}
return int(n), nil
}
recv :: proc(s: Socket, buf: []u8, flags: Flags = Flags{}) -> (int, Error) {
n := _recv(s, rawptr(&buf[0]), c.size_t(len(buf)), flags)
if n < 0 {
return -1, last_error()
}
return int(n), nil
}