ext_php_rs/zend/
streams.rs

1use std::ptr::{self, NonNull};
2
3use crate::{
4    error::Error,
5    ffi::{
6        php_register_url_stream_wrapper, php_register_url_stream_wrapper_volatile, php_stream,
7        php_stream_context, php_stream_locate_url_wrapper, php_stream_wrapper,
8        php_stream_wrapper_ops, php_unregister_url_stream_wrapper,
9        php_unregister_url_stream_wrapper_volatile, zend_string,
10    },
11    types::ZendStr,
12};
13
14pub type StreamWrapper = php_stream_wrapper;
15
16pub type StreamOpener = unsafe extern "C" fn(
17    *mut StreamWrapper,
18    *const std::ffi::c_char,
19    *const std::ffi::c_char,
20    i32,
21    *mut *mut zend_string,
22    *mut php_stream_context,
23    i32,
24    *const std::ffi::c_char,
25    u32,
26    *const std::ffi::c_char,
27    u32,
28) -> *mut Stream;
29
30impl StreamWrapper {
31    pub fn get(name: &str) -> Option<&Self> {
32        unsafe {
33            let result = php_stream_locate_url_wrapper(name.as_ptr().cast(), ptr::null_mut(), 0);
34            Some(NonNull::new(result)?.as_ref())
35        }
36    }
37
38    pub fn get_mut(name: &str) -> Option<&mut Self> {
39        unsafe {
40            let result = php_stream_locate_url_wrapper(name.as_ptr().cast(), ptr::null_mut(), 0);
41            Some(NonNull::new(result)?.as_mut())
42        }
43    }
44
45    pub fn register(self, name: &str) -> Result<Self, Error> {
46        // We have to convert it to a static so owned streamwrapper doesn't get dropped.
47        let copy = Box::new(self);
48        let copy = Box::leak(copy);
49        let name = std::ffi::CString::new(name).expect("Could not create C string for name!");
50        let result = unsafe { php_register_url_stream_wrapper(name.as_ptr(), copy) };
51        if result == 0 {
52            Ok(*copy)
53        } else {
54            Err(Error::StreamWrapperRegistrationFailure)
55        }
56    }
57
58    pub fn register_volatile(self, name: &str) -> Result<Self, Error> {
59        // We have to convert it to a static so owned streamwrapper doesn't get dropped.
60        let copy = Box::new(self);
61        let copy = Box::leak(copy);
62        let name = ZendStr::new(name, false);
63        let result =
64            unsafe { php_register_url_stream_wrapper_volatile((*name).as_ptr() as _, copy) };
65        if result == 0 {
66            Ok(*copy)
67        } else {
68            Err(Error::StreamWrapperRegistrationFailure)
69        }
70    }
71
72    pub fn unregister(name: &str) -> Result<(), Error> {
73        let name = std::ffi::CString::new(name).expect("Could not create C string for name!");
74        match unsafe { php_unregister_url_stream_wrapper(name.as_ptr()) } {
75            0 => Ok(()),
76            _ => Err(Error::StreamWrapperUnregistrationFailure),
77        }
78    }
79
80    pub fn unregister_volatile(name: &str) -> Result<(), Error> {
81        let name = ZendStr::new(name, false);
82        match unsafe { php_unregister_url_stream_wrapper_volatile((*name).as_ptr() as _) } {
83            0 => Ok(()),
84            _ => Err(Error::StreamWrapperUnregistrationFailure),
85        }
86    }
87
88    pub fn wops(&self) -> &php_stream_wrapper_ops {
89        unsafe { &*self.wops }
90    }
91
92    pub fn wops_mut(&mut self) -> &mut php_stream_wrapper_ops {
93        unsafe { &mut *(self.wops as *mut php_stream_wrapper_ops) }
94    }
95}
96
97pub type Stream = php_stream;
98
99pub type StreamWrapperOps = php_stream_wrapper_ops;
100
101impl StreamWrapperOps {}