1 //! Module containing the [`Scalar`] and [`Mortal`] types.
3 use std
::marker
::PhantomData
;
6 use bitflags
::bitflags
;
8 use crate::error
::MagicError
;
9 use crate::ffi
::{self, SV}
;
10 use crate::magic
::{Leakable, MagicSpec, MagicValue}
;
12 use crate::{Error, Value}
;
14 /// An owned reference to a perl value.
16 /// This keeps a reference to a value which lives in the perl interpreter.
17 /// This derefs to a [`ScalarRef`] which implements most of the basic functionality common to all
18 /// [`SV`] related types.
20 pub struct Scalar(*mut SV
);
23 /// Turn this into a "mortal" value. This will move this value's owned reference onto the
24 /// mortal stack to be cleaned up after the next perl statement if no more references exist.
26 /// (To be garbage collected after this perl-statement.)
27 pub fn into_mortal(self) -> Mortal
{
28 Mortal(unsafe { ffi::RSPL_sv_2mortal(self.into_raw()) }
)
31 /// Turn this into a raw [`SV`] transferring control of one reference count.
32 pub fn into_raw(self) -> *mut SV
{
34 core
::mem
::forget(self);
38 /// Create a wrapping [`Scalar`] from an [`SV`] pointer. The [`Scalar`] takes over the owned
39 /// reference from the passed [`SV`], which means it must not be a mortal reference.
43 /// This does not change the value's reference count, it is assumed that we're taking ownership
46 /// The caller must ensure that it is safe to decrease the reference count later on, or use
47 /// [`into_raw()`](Scalar::into_raw) instead of letting the [`Scalar`] get dropped.
48 pub unsafe fn from_raw_move(ptr
: *mut SV
) -> Self {
52 /// Increase the reference count on an [`SV`] pointer.
56 /// The caller may still need to decrease the reference count for the `ptr` source value.
57 pub unsafe fn from_raw_ref(ptr
: *mut SV
) -> Self {
58 unsafe { Self::from_raw_move(ffi::RSPL_SvREFCNT_inc(ptr)) }
61 /// Create a reference to `PL_sv_undef`.
62 pub fn new_undef() -> Self {
63 unsafe { Self::from_raw_ref(ffi::RSPL_get_undef()) }
66 /// Create a reference to `PL_sv_yes`.
67 pub fn new_yes() -> Self {
68 unsafe { Self::from_raw_ref(ffi::RSPL_get_yes()) }
71 /// Create a reference to `PL_sv_no`.
72 pub fn new_no() -> Self {
73 unsafe { Self::from_raw_ref(ffi::RSPL_get_no()) }
76 /// Create a new integer value:
77 pub fn new_int(v
: isize) -> Self {
78 unsafe { Self::from_raw_move(ffi::RSPL_newSViv(v)) }
81 /// Create a new unsigned integer value:
82 pub fn new_uint(v
: usize) -> Self {
83 unsafe { Self::from_raw_move(ffi::RSPL_newSVuv(v)) }
86 /// Create a new floating point value.
87 pub fn new_float(v
: f64) -> Self {
88 unsafe { Self::from_raw_move(ffi::RSPL_newSVnv(v)) }
91 /// Create a new string value.
92 pub fn new_string(s
: &str) -> Self {
93 if s
.as_bytes().iter().any(|&b
| b
>= 0x80) {
95 Self::from_raw_move(ffi
::RSPL_newSVpvn_utf8(
96 s
.as_bytes().as_ptr() as *const libc
::c_char
,
97 s
.as_bytes().len() as libc
::size_t
,
101 Self::new_bytes(s
.as_bytes())
105 /// Create a new byte string.
106 pub fn new_bytes(s
: &[u8]) -> Self {
108 Self::from_raw_move(ffi
::RSPL_newSVpvn(
109 s
.as_ptr() as *const libc
::c_char
,
110 s
.len() as libc
::size_t
,
115 /// Convenience method to create a new raw pointer value. Note that pointers are stored as
116 /// arbitrary "byte strings" and any such byte string value can be interpreted as a raw pointer.
117 pub fn new_pointer
<T
>(s
: *mut T
) -> Self {
118 Self::new_bytes(&(s
as usize).to_ne_bytes())
122 impl Clone
for Scalar
{
124 fn clone(&self) -> Self {
125 unsafe { Self::from_raw_ref(self.sv()) }
129 impl Drop
for Scalar
{
132 ffi
::RSPL_SvREFCNT_dec(self.sv());
137 impl core
::ops
::Deref
for Scalar
{
138 type Target
= ScalarRef
;
140 fn deref(&self) -> &Self::Target
{
141 unsafe { &*(self.0 as *mut ScalarRef) }
145 impl core
::ops
::DerefMut
for Scalar
{
146 fn deref_mut(&mut self) -> &mut Self::Target
{
147 unsafe { &mut *(self.0 as *mut ScalarRef) }
151 /// A value which has been pushed to perl's "mortal stack".
153 pub struct Mortal(*mut SV
);
156 /// Get the inner value.
157 pub fn into_raw(self) -> *mut SV
{
162 impl core
::ops
::Deref
for Mortal
{
163 type Target
= ScalarRef
;
165 fn deref(&self) -> &Self::Target
{
166 unsafe { &*(self.0 as *mut ScalarRef) }
170 impl core
::ops
::DerefMut
for Mortal
{
171 fn deref_mut(&mut self) -> &mut Self::Target
{
172 unsafe { &mut *(self.0 as *mut ScalarRef) }
176 /// A reference to a perl value. This is a pre reference type and cannot be constructed manually.
177 /// It is meant to provide methods common to `Value`, `Scalar`, `Array`, `Hash`, as these are all
178 /// scalar values under the hood.
179 pub struct ScalarRef(PhantomData
<()>);
182 /// Represents the types a `Value` can contain. Values can usually contain multiple scalar types
183 /// at once and it is unclear which is the "true" type, so we can only check whether a value
184 /// contains something, not what it is originally meant to be!
186 /// NOTE: The values must be the same as in our c glue code!
187 pub struct Flags
: u8 {
194 /// While scalar types aren't clearly different from another, complex types are, so we do
195 /// distinguish between these:
196 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
206 pub(crate) fn sv(&self) -> *mut SV
{
207 self as *const ScalarRef
as *const SV
as *mut SV
210 /// Get the raw `*mut SV` value for this.
212 /// This does not affect the reference count of this value. This is up to the user.
213 pub fn as_raw(&self) -> *mut SV
{
217 fn get_type(sv
: *mut SV
) -> Type
{
219 if !ffi
::RSPL_is_defined(sv
) {
220 return Type
::Scalar(Flags
::empty());
224 if ffi
::RSPL_is_reference(sv
) {
225 return Type
::Reference
;
226 } else if ffi
::RSPL_is_array(sv
) {
228 } else if ffi
::RSPL_is_hash(sv
) {
232 // Scalars have flags:
233 let flags
= ffi
::RSPL_type_flags(sv
);
235 return Type
::Scalar(Flags
::from_bits_truncate(flags
as u8));
238 let ty
= ffi
::RSPL_svtype(sv
);
241 Type
::Scalar(Flags
::empty())
242 } else if ty
== ffi
::RSPL_PVLV() {
243 // We don't support all kinds of magic, but some lvalues are simple:
244 // Try to GET the value and then check for definedness.
245 ffi
::RSPL_SvGETMAGIC(sv
);
246 if !ffi
::RSPL_SvOK(sv
) {
247 // This happens when the value points to a non-existing hash element we could
248 // auto-vivify, but we won't:
249 return Type
::Scalar(Flags
::empty());
252 // Otherwise we just try to "recurse", which will work for substrings.
253 Self::get_type(ffi
::RSPL_LvTARG(sv
))
255 Type
::Other(ty
as u8)
260 /// Get some information about the value's type.
261 pub fn ty(&self) -> Type
{
262 Self::get_type(self.sv())
265 /// Dereference this reference.
266 pub fn dereference(&self) -> Option
<Scalar
> {
267 let ptr
= unsafe { ffi::RSPL_dereference(self.sv()) }
;
271 Some(unsafe { Scalar::from_raw_ref(ptr) }
)
275 /// Coerce to a double value. (perlxs `SvNV`).
276 pub fn nv(&self) -> f64 {
277 unsafe { ffi::RSPL_SvNV(self.sv()) }
280 /// Coerce to an integer value. (perlxs `SvIV`).
281 pub fn iv(&self) -> isize {
282 unsafe { ffi::RSPL_SvIV(self.sv()) }
285 /// Coerce to an utf8 string value. (perlxs `SvPVutf8`)
286 pub fn pv_string_utf8(&self) -> &str {
288 let mut len
: libc
::size_t
= 0;
289 let ptr
= ffi
::RSPL_SvPVutf8(self.sv(), &mut len
) as *const u8;
290 std
::str::from_utf8_unchecked(std
::slice
::from_raw_parts(ptr
, len
))
294 /// Coerce to a string without utf8 encoding. (perlxs `SvPV`)
295 pub fn pv_bytes(&self) -> &[u8] {
297 let mut len
: libc
::size_t
= 0;
298 let ptr
= ffi
::RSPL_SvPV(self.sv(), &mut len
) as *const u8;
299 std
::slice
::from_raw_parts(ptr
, len
)
303 /// Coerce to a byte-string, downgrading from utf-8. (perlxs `SvPVbyte`)
305 /// May fail if there are values which don't fit into bytes in the contained utf-8 string, in
306 /// which case `None` is returned.
307 pub fn pv_utf8_to_bytes(&self) -> Option
<&[u8]> {
309 let mut len
: libc
::size_t
= 0;
310 let ptr
= ffi
::RSPL_SvPVbyte(self.sv(), &mut len
) as *const u8;
314 Some(std
::slice
::from_raw_parts(ptr
, len
))
318 /// Interpret the byte string as a raw pointer.
319 pub fn pv_raw
<T
>(&self) -> Result
<*mut T
, Error
> {
320 let bytes
= self.pv_bytes();
322 let bytes
: [u8; mem
::size_of
::<usize>()] = bytes
324 .map_err(|err
| Error(format
!("invalid value for pointer: {}", err
)))?
;
326 Ok(usize::from_ne_bytes(bytes
) as *mut T
)
329 /// Interpret the byte string as a pointer and return it as a reference for convenience.
333 /// The user is responsible for making sure the underlying pointer is correct.
334 pub unsafe fn pv_ref
<T
>(&self) -> Result
<&T
, Error
> {
335 self.pv_raw().map(|p
| unsafe { &*p }
)
338 /// Interpret the byte string as a pointer and return it as a mutable reference for
343 /// The user is responsible for making sure the underlying pointer is correct.
344 pub unsafe fn pv_mut_ref
<T
>(&self) -> Result
<&mut T
, Error
> {
345 self.pv_raw().map(|p
| unsafe { &mut *p }
)
348 /// Create another owned reference to this value.
349 pub fn clone_ref(&self) -> Scalar
{
350 unsafe { Scalar::from_raw_ref(self.sv()) }
353 /// Convenience check for `SVt_NULL`
354 pub fn is_undef(&self) -> bool
{
355 0 == unsafe { ffi::RSPL_type_flags(self.sv()) }
358 // FIXME: self consuming on a phantom type... this can probably not be useful
359 /// Turn this into a [`Value`].
360 pub fn into_value(self) -> Value
{
361 Value
::from_scalar(self.clone_ref())
364 /// Get the reference type for this value. (Similar to `ref` in perl).
366 /// If `blessed` is true and the value is a blessed reference, the package name will be
367 /// returned, otherwise the scalar type (`"SCALAR"`, `"ARRAY"`, ...) will be returned.
368 pub fn reftype(&self, blessed
: bool
) -> &'
static str {
369 let ptr
= unsafe { ffi::RSPL_sv_reftype(self.sv(), if blessed { 1 }
else { 0 }
) };
375 std
::ffi
::CStr
::from_ptr(ptr
)
377 .unwrap_or("<NON-UTF8-CLASSNAME>")
382 /// Check whether this value is a substring.
383 pub fn is_substr(&self) -> bool
{
386 Some(ffi
::RSPL_PERL_MAGIC_substr()),
387 Some(&*ffi
::RSPL_vtbl_substr()),
393 /// Create a substring from a string.
394 pub fn substr
<I
>(&self, index
: I
) -> Result
<Scalar
, Error
>
396 I
: std
::slice
::SliceIndex
<[u8], Output
= [u8]>,
398 let bytes
= self.pv_bytes();
399 let slice
: &[u8] = bytes
401 .ok_or_else(|| Error
::new("substr with out of bounds range"))?
;
402 let start
= unsafe { slice.as_ptr().offset_from(bytes.as_ptr()) }
;
403 let start
= usize::try_from(start
).map_err(|_
| Error
::new("bad substr index"))?
;
406 Scalar
::from_raw_move(ffi
::RSPL_substr(
407 ffi
::RSPL_SvREFCNT_inc(self.sv()),
414 /// Try to produce a substring from an existing "base" value and a `&str`.
416 /// Returns `None` if `substr` is not part of `value`.
417 pub fn substr_from_str_slice(value
: &ScalarRef
, substr
: &str) -> Result
<Option
<Scalar
>, Error
> {
418 let value_bytes
= value
.pv_bytes();
419 let value_beg
= value_bytes
.as_ptr() as usize;
420 let value_end
= value_beg
+ value_bytes
.len();
421 let value_range
= value_beg
..value_end
;
423 let str_bytes
= substr
.as_bytes();
424 let str_beg
= str_bytes
.as_ptr() as usize;
425 let str_end
= str_beg
+ str_bytes
.len();
426 if !value_range
.contains(&str_beg
) || !value_range
.contains(&str_end
) {
430 // we just checked the ranges:
431 let start
= unsafe { str_bytes.as_ptr().offset_from(value_bytes.as_ptr()) as usize }
;
433 Scalar
::from_raw_move(ffi
::RSPL_substr(
434 ffi
::RSPL_SvREFCNT_inc(value
.sv()),
441 /// Attach magic to this value.
445 /// The passed `vtbl` must stay valid for as long as the perl value exists.
446 /// It is up to the user to make sure `how` has a valid value. Passing `None` will create a
447 /// magic value of type `PERL_MAGIC_ext` for convenience (recommended).
448 pub unsafe fn add_raw_magic(
450 obj
: Option
<&ScalarRef
>,
451 how
: Option
<libc
::c_int
>,
452 vtbl
: Option
<&ffi
::MGVTBL
>,
453 name
: *const libc
::c_char
,
456 let _magic_ptr
= unsafe {
457 ffi
::RSPL_sv_magicext(
459 obj
.map(Self::sv
).unwrap_or(std
::ptr
::null_mut()),
460 how
.unwrap_or_else(|| ffi
::RSPL_PERL_MAGIC_ext()),
468 /// Remove attached magic.
470 /// If `ty` is `None`, a `PERL_MAGIC_ext` magic will be removed.
474 /// It is up to the user that doing this will not crash the perl interpreter.
475 pub unsafe fn remove_raw_magic(&self, ty
: Option
<libc
::c_int
>, vtbl
: Option
<&ffi
::MGVTBL
>) {
477 ffi
::RSPL_sv_unmagicext(
479 ty
.unwrap_or_else(|| ffi
::RSPL_PERL_MAGIC_ext()),
485 /// Find a magic value, if present.
487 /// If `ty` is `None`, a `PERL_MAGIC_ext` magic will be searched for.
488 pub fn find_raw_magic(
490 ty
: Option
<libc
::c_int
>,
491 vtbl
: Option
<&ffi
::MGVTBL
>,
492 ) -> Option
<&ffi
::MAGIC
> {
494 ffi
::RSPL_mg_findext(
496 ty
.unwrap_or_else(|| ffi
::RSPL_PERL_MAGIC_ext()),
503 /// Attach a magic tag to this value. This is a more convenient alternative to using
504 /// [`add_raw_magic`](ScalarRef::add_raw_magic()) manually.
505 pub fn add_magic
<T
: Leakable
>(&self, spec
: MagicValue
<'_
, '_
, '
static, T
>) {
510 Some(spec
.spec
.vtbl
),
511 spec
.ptr
.map(Leakable
::leak
).unwrap_or(std
::ptr
::null()),
517 /// Find a magic value attached to this perl value.
521 /// It is up to the user to ensure the correct types are used in the provided `MagicSpec`.
522 pub fn find_magic
<'a
, 's
, 'm
, T
: Leakable
>(
524 spec
: &'m MagicSpec
<'
static, '
static, T
>,
525 ) -> Option
<&'a T
::Pointee
> {
526 match self.find_raw_magic(spec
.how
, Some(spec
.vtbl
)) {
530 mg
.vtbl().map(|v
| v
as *const _
),
531 Some(spec
.vtbl
as *const _
),
532 "Perl_mg_findext misbehaved horribly",
540 /// Remove a magic tag from this value previously added via
541 /// [`add_magic`](ScalarRef::add_magic()) and potentially reclaim the contained value of type
544 /// When using a "default" magic tag via [`MagicTag::DEFAULT`](crate::magic::MagicTag::DEFAULT)
545 /// such as when using the [`declare_magic!`](crate::declare_magic!) macro, removing the magic
546 /// implicitly causes perl call the `free` method, therefore in this case this method returns
549 /// In case the magic was not found, [`MagicError::NotFound("")`] is returned.
551 /// This does not need to include the object and type information.
552 pub fn remove_magic
<T
: Leakable
>(
554 spec
: &MagicSpec
<'
static, '
static, T
>,
555 ) -> Result
<Option
<T
>, MagicError
> {
556 let this
= match self.find_raw_magic(spec
.how
, Some(spec
.vtbl
)) {
557 None
=> Err(MagicError
::NotFound("")),
560 mg
.vtbl().map(|v
| v
as *const _
),
561 Some(spec
.vtbl
as *const _
),
562 "Perl_mg_findext misbehaved horribly",
566 // We assume that a 'free' callback takes care of reclaiming the value!
567 Some(v
) if v
.free
.is_some() => None
,
568 _
=> T
::get_ref(mg
.ptr()).map(|m
| unsafe { T::reclaim(m) }
),
574 self.remove_raw_magic(spec
.how
, Some(spec
.vtbl
));
580 impl std
::fmt
::Debug
for Scalar
{
581 fn fmt(&self, f
: &mut std
::fmt
::Formatter
) -> std
::fmt
::Result
{
582 let this
: &ScalarRef
= self;
583 std
::fmt
::Debug
::fmt(this
, f
)
587 impl std
::fmt
::Debug
for ScalarRef
{
588 fn fmt(&self, f
: &mut std
::fmt
::Formatter
) -> std
::fmt
::Result
{
591 Type
::Scalar(flags
) => {
592 if flags
.intersects(Flags
::STRING
) {
593 Debug
::fmt(self.pv_string_utf8(), f
)
594 } else if flags
.intersects(Flags
::INTEGER
) {
595 write
!(f
, "{}", self.iv())
596 } else if flags
.intersects(Flags
::DOUBLE
) {
597 write
!(f
, "{}", self.nv())
599 write
!(f
, "<unhandled scalar>")
602 Type
::Reference
=> write
!(f
, "<*REFERENCE>"),
603 Type
::Array
=> write
!(f
, "<*ARRAY>"),
604 Type
::Hash
=> write
!(f
, "<*HASH>"),
605 Type
::Other(_
) => write
!(f
, "<*PERLTYPE>"),
610 impl serde
::Serialize
for Scalar
{
611 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
613 S
: serde
::Serializer
,
615 use serde
::ser
::Error
;
617 if raw_value
::is_enabled() {
618 return raw_value
::serialize_raw(self, serializer
);
622 Type
::Scalar(flags
) => {
623 if flags
.contains(Flags
::STRING
) {
624 serializer
.serialize_str(self.pv_string_utf8())
625 } else if flags
.contains(Flags
::DOUBLE
) {
626 serializer
.serialize_f64(self.nv())
627 } else if flags
.contains(Flags
::INTEGER
) {
628 serializer
.serialize_i64(self.iv() as i64)
629 } else if flags
.is_empty() {
630 serializer
.serialize_none()
632 serializer
.serialize_unit()
635 Type
::Other(other
) => Err(S
::Error
::custom(format
!(
636 "cannot serialize weird magic perl values ({})",
640 // These are impossible as they are all handled by different Value enum types:
641 Type
::Reference
=> Value
::from(
643 .ok_or_else(|| S
::Error
::custom("failed to dereference perl value"))?
,
645 .serialize(serializer
),
647 let this
= unsafe { crate::Array::from_raw_ref(self.sv() as *mut ffi::AV) }
;
648 this
.serialize(serializer
)
651 let this
= unsafe { crate::Hash::from_raw_ref(self.sv() as *mut ffi::HV) }
;
652 this
.serialize(serializer
)