ext_php_rs/zend/
streams.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use std::ptr::{self, NonNull};

use crate::{
    error::Error,
    ffi::{
        php_register_url_stream_wrapper, php_register_url_stream_wrapper_volatile, php_stream,
        php_stream_context, php_stream_locate_url_wrapper, php_stream_wrapper,
        php_stream_wrapper_ops, php_unregister_url_stream_wrapper,
        php_unregister_url_stream_wrapper_volatile, zend_string,
    },
    types::ZendStr,
};

pub type StreamWrapper = php_stream_wrapper;

pub type StreamOpener = unsafe extern "C" fn(
    *mut StreamWrapper,
    *const std::ffi::c_char,
    *const std::ffi::c_char,
    i32,
    *mut *mut zend_string,
    *mut php_stream_context,
    i32,
    *const std::ffi::c_char,
    u32,
    *const std::ffi::c_char,
    u32,
) -> *mut Stream;

impl StreamWrapper {
    pub fn get(name: &str) -> Option<&Self> {
        unsafe {
            let result = php_stream_locate_url_wrapper(name.as_ptr().cast(), ptr::null_mut(), 0);
            Some(NonNull::new(result)?.as_ref())
        }
    }

    pub fn get_mut(name: &str) -> Option<&mut Self> {
        unsafe {
            let result = php_stream_locate_url_wrapper(name.as_ptr().cast(), ptr::null_mut(), 0);
            Some(NonNull::new(result)?.as_mut())
        }
    }

    pub fn register(self, name: &str) -> Result<Self, Error> {
        // We have to convert it to a static so owned streamwrapper doesn't get dropped.
        let copy = Box::new(self);
        let copy = Box::leak(copy);
        let name = std::ffi::CString::new(name).expect("Could not create C string for name!");
        let result = unsafe { php_register_url_stream_wrapper(name.as_ptr(), copy) };
        if result == 0 {
            Ok(*copy)
        } else {
            Err(Error::StreamWrapperRegistrationFailure)
        }
    }

    pub fn register_volatile(self, name: &str) -> Result<Self, Error> {
        // We have to convert it to a static so owned streamwrapper doesn't get dropped.
        let copy = Box::new(self);
        let copy = Box::leak(copy);
        let name = ZendStr::new(name, false);
        let result =
            unsafe { php_register_url_stream_wrapper_volatile((*name).as_ptr() as _, copy) };
        if result == 0 {
            Ok(*copy)
        } else {
            Err(Error::StreamWrapperRegistrationFailure)
        }
    }

    pub fn unregister(name: &str) -> Result<(), Error> {
        let name = std::ffi::CString::new(name).expect("Could not create C string for name!");
        match unsafe { php_unregister_url_stream_wrapper(name.as_ptr()) } {
            0 => Ok(()),
            _ => Err(Error::StreamWrapperUnregistrationFailure),
        }
    }

    pub fn unregister_volatile(name: &str) -> Result<(), Error> {
        let name = ZendStr::new(name, false);
        match unsafe { php_unregister_url_stream_wrapper_volatile((*name).as_ptr() as _) } {
            0 => Ok(()),
            _ => Err(Error::StreamWrapperUnregistrationFailure),
        }
    }

    pub fn wops(&self) -> &php_stream_wrapper_ops {
        unsafe { &*self.wops }
    }

    pub fn wops_mut(&mut self) -> &mut php_stream_wrapper_ops {
        unsafe { &mut *(self.wops as *mut php_stream_wrapper_ops) }
    }
}

pub type Stream = php_stream;

pub type StreamWrapperOps = php_stream_wrapper_ops;

impl StreamWrapperOps {}