pub fn new(str: impl AsRef<[u8]>, persistent: bool) -> ZBox<Self> {
        let s = str.as_ref();
        // TODO: we should handle the special cases when length is either 0 or 1
        // see `zend_string_init_fast()` in `zend_string.h`
        unsafe {
            let ptr = ext_php_rs_zend_string_init(s.as_ptr().cast(), s.len(), persistent)
                .as_mut()
                .expect("Failed to allocate memory for new Zend string");
            ZBox::from_raw(ptr)
        }
    }
Creates a new Zend string from a slice of bytes.

# Parameters

* `str` - String content.
* `persistent` - Whether the string should persist through the request
boundary.

# Panics

Panics if the function was unable to allocate memory for the Zend
string.

# Safety

When passing `persistent` as `false`, the caller must ensure that the
object does not attempt to live after the request finishes. When a
request starts and finishes in PHP, the Zend heap is deallocated and a
new one is created, which would leave a dangling pointer in the
[`ZBox`].

# Example

```no_run
use ext_php_rs::types::ZendStr;

let s = ZendStr::new("Hello, world!", false);
let php = ZendStr::new([80, 72, 80], false);
```
src/types/string.rs