diff --git a/Cargo.toml b/Cargo.toml index ae11ba6f9..095fa0e87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ parking_lot = { version = "0.12.3", features = ["arc_lock"] } cfg-if = "1.0" once_cell = "1.21" anyhow = { version = "1", optional = true } +smartstring = { version = "1", optional = true } ext-php-rs-derive = { version = "=0.11.6", path = "./crates/macros" } [dev-dependencies] @@ -49,6 +50,7 @@ default = ["enum", "runtime"] closure = [] embed = [] anyhow = ["dep:anyhow"] +smartstring = ["dep:smartstring"] enum = [] runtime = ["bindgen/runtime"] static = ["bindgen/static"] diff --git a/src/types/string.rs b/src/types/string/mod.rs similarity index 99% rename from src/types/string.rs rename to src/types/string/mod.rs index fd88ccd3c..ebbc19a6f 100644 --- a/src/types/string.rs +++ b/src/types/string/mod.rs @@ -1,6 +1,9 @@ //! Represents a string in the PHP world. Similar to a C string, but is //! reference counted and contains the length of the string. +#[cfg(feature = "smartstring")] +mod smartstring_impl; + use std::{ borrow::Cow, convert::TryFrom, diff --git a/src/types/string/smartstring_impl.rs b/src/types/string/smartstring_impl.rs new file mode 100644 index 000000000..8db43235e --- /dev/null +++ b/src/types/string/smartstring_impl.rs @@ -0,0 +1,50 @@ +use super::{DataType, FromZval, IntoZval, Result, Zval}; +use smartstring::{LazyCompact, SmartString}; + +impl IntoZval for SmartString { + const TYPE: DataType = DataType::String; + const NULLABLE: bool = false; + + fn set_zval(self, zv: &mut Zval, persistent: bool) -> Result<()> { + zv.set_string(self.as_str(), persistent) + } +} + +impl FromZval<'_> for SmartString { + const TYPE: DataType = DataType::String; + + fn from_zval(zval: &Zval) -> Option { + zval.str().map(SmartString::from) + } +} + +#[cfg(test)] +#[cfg(feature = "embed")] +mod tests { + use super::*; + use crate::convert::FromZval; + use crate::embed::Embed; + + #[test] + fn test_smartstring_from_zval() { + Embed::run(|| { + let result = Embed::eval("'hello smartstring';"); + assert!(result.is_ok()); + + let zval = result.as_ref().unwrap(); + let smart: Option> = FromZval::from_zval(zval); + assert_eq!(smart, Some(SmartString::from("hello smartstring"))); + }); + } + + #[test] + fn test_smartstring_into_zval() { + Embed::run(|| { + let smart: SmartString = SmartString::from("test string"); + let zval = smart.into_zval(false).unwrap(); + + assert!(zval.is_string()); + assert_eq!(zval.str(), Some("test string")); + }); + } +}