pyo3_ffi/compat/
py_3_15.rs1#[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}