use std::ptr::NonNull;
use libperl_sys::{PerlInterpreter, SV};
use crate::Perl;
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Sv(NonNull<SV>);
impl Sv {
#[inline]
pub unsafe fn from_raw_unchecked(p: *mut SV) -> Self {
debug_assert!(!p.is_null(), "Sv::from_raw_unchecked received a null pointer");
Sv(unsafe { NonNull::new_unchecked(p) })
}
#[inline]
pub fn from_raw(p: *mut SV) -> Option<Self> {
NonNull::new(p).map(Sv)
}
#[inline]
pub fn as_ptr(&self) -> *mut SV {
self.0.as_ptr()
}
#[inline]
pub fn new_iv(perl: &Perl, v: crate::IV) -> Sv {
unsafe {
let raw = crate::thx_call!(perl, Perl_newSViv, v);
let raw = crate::thx_call!(perl, Perl_sv_2mortal, raw);
Sv::from_raw_unchecked(raw)
}
}
#[inline]
pub fn new_uv(perl: &Perl, v: crate::UV) -> Sv {
unsafe {
let raw = crate::thx_call!(perl, Perl_newSVuv, v);
let raw = crate::thx_call!(perl, Perl_sv_2mortal, raw);
Sv::from_raw_unchecked(raw)
}
}
#[inline]
pub fn new_nv(perl: &Perl, v: crate::NV) -> Sv {
unsafe {
let raw = crate::thx_call!(perl, Perl_newSVnv, v);
let raw = crate::thx_call!(perl, Perl_sv_2mortal, raw);
Sv::from_raw_unchecked(raw)
}
}
#[inline]
pub fn iv(&self, perl: &Perl) -> crate::IV {
unsafe { crate::thx_call!(perl, SvIV, self.0.as_ptr()) }
}
#[inline]
pub fn uv(&self, perl: &Perl) -> crate::UV {
unsafe { crate::thx_call!(perl, SvUV, self.0.as_ptr()) }
}
#[inline]
pub fn nv(&self, perl: &Perl) -> crate::NV {
unsafe { crate::thx_call!(perl, SvNV, self.0.as_ptr()) }
}
#[inline]
pub fn pv<'a>(&'a self, perl: &Perl) -> &'a [u8] {
let mut len: libperl_sys::STRLEN = 0;
let ptr = unsafe {
crate::thx_call!(
perl,
Perl_sv_2pv_flags,
self.0.as_ptr(),
&mut len,
libperl_sys::SV_GMAGIC as _,
)
};
if ptr.is_null() {
return &[];
}
unsafe { ::core::slice::from_raw_parts(ptr as *const u8, len as usize) }
}
pub fn new_pv(perl: &Perl, s: &str) -> Sv {
let bytes = s.as_bytes();
unsafe {
let raw = crate::thx_call!(
perl,
Perl_newSVpvn,
bytes.as_ptr() as *const ::core::ffi::c_char,
bytes.len() as _,
);
let cur: i64 = (*raw).sv_flags as i64;
(*raw).sv_flags = (cur | (libperl_sys::SVf_UTF8 as i64)) as _;
let raw = crate::thx_call!(perl, Perl_sv_2mortal, raw);
Sv::from_raw_unchecked(raw)
}
}
}
#[inline]
pub unsafe fn sv_refcnt_inc(sv: *mut SV) -> *mut SV {
if !sv.is_null() {
unsafe { (*sv).sv_refcnt = (*sv).sv_refcnt.wrapping_add(1); }
}
sv
}
#[cfg(perl_useithreads)]
#[inline]
pub fn sv_undef_ptr(my_perl: *mut PerlInterpreter) -> *mut SV {
unsafe { &raw mut (*my_perl).Isv_undef as *mut SV }
}
#[cfg(not(perl_useithreads))]
#[inline]
pub fn sv_undef_ptr(_my_perl: *mut PerlInterpreter) -> *mut SV {
unsafe { &raw mut libperl_sys::PL_sv_immortals[1] as *mut SV }
}