Skip to main content

pyo3_ffi/compat/
py_3_15.rs

1#[cfg(all(Py_3_15, not(Py_LIMITED_API)))]
2pub use crate::PyBytesWriter;
3
4#[cfg(not(Py_LIMITED_API))]
5compat_function!(
6    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));
7
8    #[inline]
9    pub unsafe fn PyBytesWriter_Create(
10        size: crate::Py_ssize_t,
11    ) -> *mut PyBytesWriter {
12
13        if size < 0 {
14            crate::PyErr_SetString(crate::PyExc_ValueError, c"size must be >= 0".as_ptr() as *const _);
15            return std::ptr::null_mut();
16        }
17
18        let writer: *mut PyBytesWriter = crate::PyMem_Malloc(std::mem::size_of::<PyBytesWriter>()).cast();
19        if writer.is_null() {
20            crate::PyErr_NoMemory();
21            return std::ptr::null_mut();
22        }
23
24        (*writer).obj = std::ptr::null_mut();
25        (*writer).size = 0;
26
27        if size >=1 {
28            if _PyBytesWriter_Resize_impl(writer, size, 0) < 0 {
29                PyBytesWriter_Discard(writer);
30                return std::ptr::null_mut();
31            }
32
33            (*writer).size = size;
34        }
35
36        writer
37    }
38);
39
40#[cfg(not(Py_LIMITED_API))]
41compat_function!(
42    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));
43
44    #[inline]
45    pub unsafe fn PyBytesWriter_Discard(writer: *mut PyBytesWriter) -> () {
46        if writer.is_null() {
47            return;
48        }
49
50        crate::Py_XDECREF((*writer).obj);
51        crate::PyMem_Free(writer.cast());
52    }
53);
54
55#[cfg(not(Py_LIMITED_API))]
56compat_function!(
57    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));
58
59    #[inline]
60    pub unsafe fn PyBytesWriter_Finish(writer: *mut PyBytesWriter) -> *mut crate::PyObject {
61        PyBytesWriter_FinishWithSize(writer, (*writer).size)
62    }
63);
64
65#[cfg(not(Py_LIMITED_API))]
66compat_function!(
67    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));
68
69    #[inline]
70    pub unsafe fn PyBytesWriter_FinishWithSize(writer: *mut PyBytesWriter, size: crate::Py_ssize_t) -> *mut crate::PyObject {
71        let result = if size == 0 {
72            crate::PyBytes_FromStringAndSize(c"".as_ptr(), 0)
73        } else if (*writer).obj.is_null() {
74            crate::PyBytes_FromStringAndSize((*writer).small_buffer.as_ptr(), size)
75        } else {
76            if size != crate::PyBytes_Size((*writer).obj) && crate::_PyBytes_Resize(&mut (*writer).obj, size) < 0 {
77                    PyBytesWriter_Discard(writer);
78                    return std::ptr::null_mut();
79            }
80            std::mem::replace(&mut (*writer).obj, std::ptr::null_mut())
81        };
82
83        PyBytesWriter_Discard(writer);
84        result
85    }
86);
87
88#[cfg(not(Py_LIMITED_API))]
89compat_function!(
90    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));
91
92    #[inline]
93    pub unsafe fn PyBytesWriter_GetData(writer: *mut PyBytesWriter) -> *mut std::ffi::c_void {
94        if (*writer).obj.is_null() {
95            (*writer).small_buffer.as_ptr() as *mut _
96        } else {
97                crate::PyBytes_AS_STRING((*writer).obj) as *mut _
98        }
99    }
100);
101
102#[cfg(not(Py_LIMITED_API))]
103compat_function!(
104    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));
105
106    #[inline]
107    pub unsafe fn PyBytesWriter_GetSize(writer: *mut PyBytesWriter) -> crate::Py_ssize_t {
108        (*writer).size
109    }
110);
111
112#[cfg(not(Py_LIMITED_API))]
113compat_function!(
114    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));
115
116    #[inline]
117    pub unsafe fn PyBytesWriter_Resize(writer: *mut PyBytesWriter, size: crate::Py_ssize_t) -> std::ffi::c_int {
118        if size < 0 {
119            crate::PyErr_SetString(crate::PyExc_ValueError, c"size must be >= 0".as_ptr());
120            return -1;
121        }
122        if _PyBytesWriter_Resize_impl(writer, size, 1) < 0 {
123            return -1;
124        }
125        (*writer).size = size;
126        0
127    }
128);
129
130#[repr(C)]
131#[cfg(not(any(Py_3_15, Py_LIMITED_API)))]
132pub struct PyBytesWriter {
133    small_buffer: [std::ffi::c_char; 256],
134    obj: *mut crate::PyObject,
135    size: crate::Py_ssize_t,
136}
137
138#[inline]
139#[cfg(not(any(Py_3_15, Py_LIMITED_API)))]
140unsafe fn _PyBytesWriter_Resize_impl(
141    writer: *mut PyBytesWriter,
142    mut size: crate::Py_ssize_t,
143    resize: std::ffi::c_int,
144) -> std::ffi::c_int {
145    let overallocate = resize;
146    assert!(size >= 0);
147
148    let allocated = if (*writer).obj.is_null() {
149        std::mem::size_of_val(&(*writer).small_buffer) as _
150    } else {
151        crate::PyBytes_Size((*writer).obj)
152    };
153
154    if size <= allocated {
155        return 0;
156    }
157
158    if overallocate > 0 {
159        #[cfg(windows)]
160        if size <= (crate::PY_SSIZE_T_MAX - size / 2) {
161            size += size / 2;
162        }
163
164        #[cfg(not(windows))]
165        if size <= (crate::PY_SSIZE_T_MAX - size / 4) {
166            size += size / 4;
167        }
168    }
169
170    if !(*writer).obj.is_null() {
171        if crate::_PyBytes_Resize(&mut (*writer).obj, size) > 0 {
172            return -1;
173        }
174        assert!(!(*writer).obj.is_null())
175    } else {
176        (*writer).obj = crate::PyBytes_FromStringAndSize(std::ptr::null_mut(), size);
177        if (*writer).obj.is_null() {
178            return -1;
179        }
180
181        if resize > 0 {
182            assert!((size as usize) > std::mem::size_of_val(&(*writer).small_buffer));
183
184            std::ptr::copy_nonoverlapping(
185                (*writer).small_buffer.as_ptr(),
186                crate::PyBytes_AS_STRING((*writer).obj) as *mut _,
187                std::mem::size_of_val(&(*writer).small_buffer),
188            );
189        }
190    }
191
192    0
193}