#pragma once
#include <uv.h>
#include <panda/unievent/util.h>
#include <panda/unievent/error.h>
#include <panda/unievent/backend/HandleImpl.h>
namespace
panda {
namespace
unievent {
namespace
backend {
namespace
uv {
static
inline
void
uvx_strict (
int
err) {
if
(err)
throw
Error(uvx_error(err)); }
static
inline
std::error_code uvx_ce (
int
err) {
return
err ? uvx_error(err) : std::error_code(); }
template
<
class
T = HandleImpl*,
class
X>
static
inline
T get_handle (X* uvhp) {
return
static_cast
<T>(
reinterpret_cast
<HandleImpl*>(uvhp->data));
}
template
<
class
T = RequestImpl*,
class
X>
static
inline
T get_request (X* uvrp) {
return
static_cast
<T>(
reinterpret_cast
<RequestImpl*>(uvrp->data));
}
static
inline
void
uvx_buf_alloc (string& buf, uv_buf_t* uvbuf) {
char
* ptr = buf.shared_buf();
auto
cap = buf.shared_capacity();
size_t
align = (
size_t
(ptr) + cap) %
sizeof
(
void
*);
cap -= align;
auto
availcap = cap -
sizeof
(string);
new
((string*)(ptr + availcap)) string(buf);
uvbuf->base = ptr;
uvbuf->len = availcap;
}
static
inline
string uvx_detach_buf (
const
uv_buf_t* uvbuf) {
if
(!uvbuf->base)
return
{};
auto
buf_ptr = (string*)(uvbuf->base + uvbuf->len);
string ret = *buf_ptr;
buf_ptr->~string();
return
ret;
}
#define UVX_FILL_BUFS(bufs, uvbufs) \
auto
uvbufs = (uv_buf_t*)alloca(
sizeof
(uv_buf_t)*bufs.size()); \
uv_buf_t* ptr = uvbufs; \
for
(
const
auto
& str : bufs) { \
ptr->base = (
char
*)str.data(); \
ptr->len = str.length(); \
++ptr; \
}
template
<
class
Handle,
class
Func>
static
inline
expected<net::SockAddr, std::error_code> uvx_sockaddr (Handle uvhp, Func&& f) {
net::SockAddr ret;
int
err;
ret.assign_foreign([&](
auto
ptr,
auto
size_ptr){
err = f(uvhp, ptr, (
int
*)size_ptr);
return
!err;
});
if
(err) {
return
make_unexpected(uvx_ce(err));
}
return
ret;
}
static
inline
expected<fh_t, std::error_code> uvx_fileno (
const
uv_handle_t* p) {
uv_os_fd_t fd;
int
err = uv_fileno(p, &fd);
if
(err)
return
make_unexpected(uvx_error(err));
return
{fd};
}
static
inline
expected<
int
, std::error_code> uvx_recv_buffer_size (
const
uv_handle_t* p) {
int
ret = 0;
auto
err = uvx_ce(uv_recv_buffer_size((uv_handle_t*)p, &ret));
if
(err) {
return
make_unexpected(err);
}
else
{
return
ret;
}
}
static
inline
std::error_code uvx_recv_buffer_size (uv_handle_t* p,
int
value) {
return
uvx_ce(uv_recv_buffer_size(p, &value));
}
static
inline
expected<
int
, std::error_code> uvx_send_buffer_size (
const
uv_handle_t* p) {
int
ret = 0;
auto
err = uvx_ce(uv_send_buffer_size((uv_handle_t*)p, &ret));
if
(err) {
return
make_unexpected(err);
}
else
{
return
ret;
}
}
static
inline
std::error_code uvx_send_buffer_size (uv_handle_t* p,
int
value) {
return
uvx_ce(uv_send_buffer_size(p, &value));
}
}}}}