1 //! Module containing the [`Scalar`] and [`Mortal`] types.
3 use std
::convert
::TryInto
;
6 use bitflags
::bitflags
;
8 use crate::ffi
::{self, SV}
;
12 /// An owned reference to a perl value.
14 /// This keeps a reference to a value which lives in the perl interpreter.
15 /// This derefs to a `ScalarRef` which implements most of the basic functionality common to all
16 /// `SV` related types.
18 pub struct Scalar(*mut SV
);
21 /// Turn this into a "mortal" value. This will move this value's owned reference onto the
22 /// mortal stack to be cleaned up after the next perl statement if no more references exist.
24 /// (To be garbage collected after this perl-statement.)
25 pub fn into_mortal(self) -> Mortal
{
26 Mortal(unsafe { ffi::RSPL_sv_2mortal(self.into_raw()) }
)
29 /// Turn this into a raw `SV` transferring control of one reference count.
30 pub fn into_raw(self) -> *mut SV
{
32 core
::mem
::forget(self);
36 /// Create a wrapping `Scalar` from an `SV` pointer. The `Scalar` takes over the owned
37 /// reference from the passed `SV`, which means it must not be a mortal reference.
41 /// This does not change the value's reference count, it is assumed that we're taking ownership
44 /// The caller must ensure that it is safe to decrease the reference count later on, or use
45 /// `into_raw()` instead of letting the `Scalar` get dropped.
46 pub unsafe fn from_raw_move(ptr
: *mut SV
) -> Self {
50 /// Increase the reference count on an `SV` pointer.
54 /// The caller may still need to decrease the reference count for the `ptr` source value.
55 pub unsafe fn from_raw_ref(ptr
: *mut SV
) -> Self {
56 Self::from_raw_move(ffi
::RSPL_SvREFCNT_inc(ptr
))
59 /// Create a reference to `PL_sv_undef`.
60 pub fn new_undef() -> Self {
61 unsafe { Self::from_raw_ref(ffi::RSPL_get_undef()) }
64 /// Create a reference to `PL_sv_yes`.
65 pub fn new_yes() -> Self {
66 unsafe { Self::from_raw_ref(ffi::RSPL_get_yes()) }
69 /// Create a reference to `PL_sv_no`.
70 pub fn new_no() -> Self {
71 unsafe { Self::from_raw_ref(ffi::RSPL_get_no()) }
74 /// Create a new integer value:
75 pub fn new_int(v
: isize) -> Self {
76 unsafe { Self::from_raw_move(ffi::RSPL_newSViv(v)) }
79 /// Create a new unsigned integer value:
80 pub fn new_uint(v
: usize) -> Self {
81 unsafe { Self::from_raw_move(ffi::RSPL_newSVuv(v)) }
84 /// Create a new floating point value.
85 pub fn new_float(v
: f64) -> Self {
86 unsafe { Self::from_raw_move(ffi::RSPL_newSVnv(v)) }
89 /// Create a new string value.
90 pub fn new_string(s
: &str) -> Self {
91 Self::new_bytes(s
.as_bytes())
94 /// Create a new byte string.
95 pub fn new_bytes(s
: &[u8]) -> Self {
97 Self::from_raw_move(ffi
::RSPL_newSVpvn(
98 s
.as_ptr() as *const libc
::c_char
,
99 s
.len() as libc
::size_t
,
104 /// Convenience method to create a new raw pointer value. Note that pointers are stored as
105 /// arbitrary "byte strings" and any such byte string value can be interpreted as a raw pointer.
106 pub fn new_pointer
<T
>(s
: *mut T
) -> Self {
107 Self::new_bytes(&(s
as usize).to_ne_bytes())
111 impl Drop
for Scalar
{
114 ffi
::RSPL_SvREFCNT_dec(self.sv());
119 impl core
::ops
::Deref
for Scalar
{
120 type Target
= ScalarRef
;
122 fn deref(&self) -> &Self::Target
{
123 unsafe { &*(self.0 as *mut ScalarRef) }
127 impl core
::ops
::DerefMut
for Scalar
{
128 fn deref_mut(&mut self) -> &mut Self::Target
{
129 unsafe { &mut *(self.0 as *mut ScalarRef) }
133 /// A value which has been pushed to perl's "mortal stack".
135 pub struct Mortal(*mut SV
);
138 /// Get the inner value.
139 pub fn into_raw(self) -> *mut SV
{
144 impl core
::ops
::Deref
for Mortal
{
145 type Target
= ScalarRef
;
147 fn deref(&self) -> &Self::Target
{
148 unsafe { &*(self.0 as *mut ScalarRef) }
152 impl core
::ops
::DerefMut
for Mortal
{
153 fn deref_mut(&mut self) -> &mut Self::Target
{
154 unsafe { &mut *(self.0 as *mut ScalarRef) }
158 pub struct ScalarRef
;
161 /// Represents the types a `Value` can contain. Values can usually contain multiple scalar types
162 /// at once and it is unclear which is the "true" type, so we can only check whether a value
163 /// contains something, not what it is originally meant to be!
165 /// NOTE: The values must be the same as in our c glue code!
166 pub struct Flags
: u8 {
173 /// While scalar types aren't clearly different from another, complex types are, so we do
174 /// distinguish between these:
175 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
185 pub(crate) fn sv(&self) -> *mut SV
{
186 self as *const ScalarRef
as *const SV
as *mut SV
189 /// Get some information about the value's type.
190 pub fn ty(&self) -> Type
{
192 if ffi
::RSPL_is_reference(self.sv()) {
195 let flags
= ffi
::RSPL_type_flags(self.sv());
197 panic
!("bad C type returned");
198 } else if flags
!= 0 {
199 Type
::Scalar(Flags
::from_bits(flags
as u8).unwrap())
200 } else if ffi
::RSPL_is_array(self.sv()) {
202 } else if ffi
::RSPL_is_hash(self.sv()) {
205 Type
::Other(ffi
::RSPL_svtype(self.sv()) as u8)
211 /// Dereference this reference.
212 pub fn dereference(&self) -> Option
<Scalar
> {
213 let ptr
= unsafe { ffi::RSPL_dereference(self.sv()) }
;
217 Some(unsafe { Scalar::from_raw_ref(ptr) }
)
221 /// Coerce to a double value. (perlxs SvNV).
222 pub fn nv(&self) -> f64 {
223 unsafe { ffi::RSPL_SvNV(self.sv()) }
226 /// Coerce to an integer value. (perlxs SvIV).
227 pub fn iv(&self) -> isize {
228 unsafe { ffi::RSPL_SvIV(self.sv()) }
231 /// Coerce to an utf8 string value. (perlxs SvPVutf8)
232 pub fn pv_utf8(&self) -> &str {
234 let mut len
: libc
::size_t
= 0;
235 let ptr
= ffi
::RSPL_SvPVutf8(self.sv(), &mut len
) as *const u8;
236 std
::str::from_utf8_unchecked(std
::slice
::from_raw_parts(ptr
, len
))
240 /// Coerce to a string without utf8 encoding. (perlxs SvPV)
241 pub fn pv_string_bytes(&self) -> &[u8] {
243 let mut len
: libc
::size_t
= 0;
244 let ptr
= ffi
::RSPL_SvPV(self.sv(), &mut len
) as *const u8;
245 std
::slice
::from_raw_parts(ptr
, len
)
249 /// Coerce to a byte-string. (perlxs SvPVbyte)
250 pub fn pv_bytes(&self) -> &[u8] {
252 let mut len
: libc
::size_t
= 0;
253 let ptr
= ffi
::RSPL_SvPVbyte(self.sv(), &mut len
) as *const u8;
254 std
::slice
::from_raw_parts(ptr
, len
)
258 /// Interpret the byte string as a raw pointer.
259 pub fn pv_raw
<T
>(&self) -> Result
<*mut T
, Error
> {
260 let bytes
= self.pv_bytes();
262 let bytes
: [u8; mem
::size_of
::<usize>()] = bytes
264 .map_err(|err
| Error(format
!("invalid value for pointer: {}", err
)))?
;
266 Ok(usize::from_ne_bytes(bytes
) as *mut T
)
269 /// Interpret the byte string as a pointer and return it as a reference for convenience.
273 /// The user is responsible for making sure the underlying pointer is correct.
274 pub unsafe fn pv_ref
<T
>(&self) -> Result
<&T
, Error
> {
275 self.pv_raw().map(|p
| unsafe { &*p }
)
278 /// Interpret the byte string as a pointer and return it as a mutable reference for
283 /// The user is responsible for making sure the underlying pointer is correct.
284 pub unsafe fn pv_mut_ref
<T
>(&self) -> Result
<&mut T
, Error
> {
285 self.pv_raw().map(|p
| unsafe { &mut *p }
)
288 /// Create another owned reference to this value.
289 pub fn clone_ref(&self) -> Scalar
{
290 unsafe { Scalar::from_raw_ref(self.sv()) }
293 /// Convenience check for SVt_NULL
294 pub fn is_undef(&self) -> bool
{
295 0 == unsafe { ffi::RSPL_type_flags(self.sv()) }
298 /// Turn this into a `Value`.
299 pub fn into_value(self) -> Value
{
300 Value
::from_scalar(self.clone_ref())
304 impl std
::fmt
::Debug
for Scalar
{
305 fn fmt(&self, f
: &mut std
::fmt
::Formatter
) -> std
::fmt
::Result
{
306 let this
: &ScalarRef
= &self;
307 std
::fmt
::Debug
::fmt(this
, f
)
311 impl std
::fmt
::Debug
for ScalarRef
{
312 fn fmt(&self, f
: &mut std
::fmt
::Formatter
) -> std
::fmt
::Result
{
315 Type
::Scalar(flags
) => {
316 if flags
.intersects(Flags
::STRING
) {
317 Debug
::fmt(self.pv_utf8(), f
)
318 } else if flags
.intersects(Flags
::INTEGER
) {
319 write
!(f
, "{}", self.iv())
320 } else if flags
.intersects(Flags
::DOUBLE
) {
321 write
!(f
, "{}", self.nv())
323 write
!(f
, "<unhandled scalar>")
326 Type
::Reference
=> write
!(f
, "<*REFERENCE>"),
327 Type
::Array
=> write
!(f
, "<*ARRAY>"),
328 Type
::Hash
=> write
!(f
, "<*HASH>"),
329 Type
::Other(_
) => write
!(f
, "<*PERLTYPE>"),
334 impl serde
::Serialize
for Scalar
{
335 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
337 S
: serde
::Serializer
,
339 use serde
::ser
::Error
;
342 Type
::Scalar(flags
) => {
343 if flags
.contains(Flags
::STRING
) {
344 serializer
.serialize_str(self.pv_utf8())
345 } else if flags
.contains(Flags
::DOUBLE
) {
346 serializer
.serialize_f64(self.nv())
347 } else if flags
.contains(Flags
::INTEGER
) {
348 serializer
.serialize_i64(self.iv() as i64)
350 serializer
.serialize_unit()
353 Type
::Other(_
) => Err(S
::Error
::custom(
354 "cannot deserialize weird magic perl values",
357 // These are impossible as they are all handled by different Value enum types:
358 Type
::Reference
=> Value
::from(
360 .ok_or_else(|| S
::Error
::custom("failed to dereference perl value"))?
,
362 .serialize(serializer
),
364 let this
= unsafe { crate::Array::from_raw_ref(self.sv() as *mut ffi::AV) }
;
365 this
.serialize(serializer
)
368 let this
= unsafe { crate::Hash::from_raw_ref(self.sv() as *mut ffi::HV) }
;
369 this
.serialize(serializer
)