#include "sockaddr.h"
namespace xs { namespace net {
using panda::net::SockAddr;
static PERL_ITHREADS_LOCAL HV* s1 = gv_stashpvs("Net::SockAddr::Inet4", GV_ADD);
static PERL_ITHREADS_LOCAL HV* s2 = gv_stashpvs("Net::SockAddr::Inet6", GV_ADD);
static PERL_ITHREADS_LOCAL HV* s3 = gv_stashpvs("Net::SockAddr::Unix", GV_ADD);
SockAddr* _in_sockaddr_ptr (SV* arg) {
if (!sv_defined(arg)) return nullptr;
if (!Sv(arg).is_object_ref()) throw "invalid sockaddr";
return (panda::net::SockAddr*)SvPVX(SvRV(arg));
}
SockAddr _in_sockaddr (SV* arg) {
if (!sv_defined(arg)) return {};
if (Sv(arg).is_object_ref()) return *_in_sockaddr_ptr(arg);
if (!SvPOK(arg) || SvCUR(arg) < sizeof(panda::net::sa_family_t)) throw "invalid sockaddr";
size_t sz = (size_t)SvCUR(arg);
auto sa = (const sockaddr*)SvPVX(arg);
return SockAddr(sa, sz);
}
Sv _create_sockaddr (const panda::net::SockAddr& var) {
Stash stash;
size_t sz = var.length();
switch (var.family()) {
case AF_UNSPEC : return Sv::undef;
case AF_INET : stash = s1; break;
case AF_INET6 : stash = s2; break;
#ifndef _WIN32
case AF_UNIX : stash = s3; break;
#endif
default: throw "invalid sockaddr family";
}
auto base = Simple(panda::string_view(reinterpret_cast<const char*>(&var), sz));
return stash.bless(base).ref();
}
}}