1- use crate :: ffi_ptr_ext:: FfiPtrExt ;
2- use crate :: py_result_ext:: PyResultExt ;
31use crate :: types:: PyBytes ;
4- use crate :: { ffi, Bound , PyErr , PyResult , Python } ;
5- use pyo3_ffi:: compat:: {
6- PyBytesWriter_Create , PyBytesWriter_Discard , PyBytesWriter_Finish , PyBytesWriter_GetData ,
7- PyBytesWriter_GetSize , PyBytesWriter_Grow , PyBytesWriter_WriteBytes ,
8- _PyBytesWriter_GetAllocated,
2+ #[ cfg( not( Py_LIMITED_API ) ) ]
3+ use crate :: {
4+ ffi:: {
5+ self ,
6+ compat:: {
7+ PyBytesWriter_Create , PyBytesWriter_Discard , PyBytesWriter_Finish ,
8+ PyBytesWriter_GetData , PyBytesWriter_GetSize , PyBytesWriter_Grow ,
9+ PyBytesWriter_WriteBytes , _PyBytesWriter_GetAllocated,
10+ } ,
11+ } ,
12+ ffi_ptr_ext:: FfiPtrExt ,
13+ py_result_ext:: PyResultExt ,
914} ;
15+ use crate :: { Bound , IntoPyObject , PyErr , PyResult , Python } ;
1016use std:: io:: IoSlice ;
11- use std :: ptr ;
12- use std:: ptr:: NonNull ;
17+ # [ cfg ( not ( Py_LIMITED_API ) ) ]
18+ use std:: ptr:: { self , NonNull } ;
1319
1420pub struct PyBytesWriter < ' py > {
1521 python : Python < ' py > ,
22+ #[ cfg( not( Py_LIMITED_API ) ) ]
1623 writer : NonNull < ffi:: PyBytesWriter > ,
24+ #[ cfg( Py_LIMITED_API ) ]
25+ buffer : Vec < u8 > ,
1726}
1827
1928impl < ' py > PyBytesWriter < ' py > {
@@ -24,51 +33,97 @@ impl<'py> PyBytesWriter<'py> {
2433
2534 #[ inline]
2635 pub fn with_capacity ( py : Python < ' py > , capacity : usize ) -> PyResult < Self > {
27- match NonNull :: new ( unsafe { PyBytesWriter_Create ( capacity as _ ) } ) {
28- Some ( ptr) => Ok ( PyBytesWriter {
36+ #[ cfg( not( Py_LIMITED_API ) ) ]
37+ {
38+ NonNull :: new ( unsafe { PyBytesWriter_Create ( capacity as _ ) } )
39+ . map ( |writer| PyBytesWriter { python : py, writer } )
40+ . ok_or_else ( || PyErr :: fetch ( py) )
41+ }
42+
43+ #[ cfg( Py_LIMITED_API ) ]
44+ {
45+ Ok ( PyBytesWriter {
2946 python : py,
30- writer : ptr,
31- } ) ,
32- None => Err ( PyErr :: fetch ( py) ) ,
47+ buffer : Vec :: with_capacity ( capacity) ,
48+ } )
3349 }
3450 }
3551
3652 #[ inline]
3753 pub fn capacity ( & self ) -> usize {
38- unsafe { _PyBytesWriter_GetAllocated ( self . writer . as_ptr ( ) ) as _ }
54+ #[ cfg( not( Py_LIMITED_API ) ) ]
55+ unsafe {
56+ _PyBytesWriter_GetAllocated ( self . writer . as_ptr ( ) ) as _
57+ }
58+
59+ #[ cfg( Py_LIMITED_API ) ]
60+ {
61+ self . buffer . capacity ( )
62+ }
3963 }
4064
4165 #[ inline]
4266 pub fn len ( & self ) -> usize {
43- unsafe { PyBytesWriter_GetSize ( self . writer . as_ptr ( ) ) as _ }
67+ #[ cfg( not( Py_LIMITED_API ) ) ]
68+ unsafe {
69+ PyBytesWriter_GetSize ( self . writer . as_ptr ( ) ) as _
70+ }
71+
72+ #[ cfg( Py_LIMITED_API ) ]
73+ {
74+ self . buffer . len ( )
75+ }
4476 }
4577
4678 #[ inline]
79+ #[ cfg( not( Py_LIMITED_API ) ) ]
4780 fn as_mut_ptr ( & mut self ) -> * mut u8 {
4881 unsafe { PyBytesWriter_GetData ( self . writer . as_ptr ( ) ) as _ }
4982 }
5083}
5184
52- impl < ' py > TryInto < Bound < ' py , PyBytes > > for PyBytesWriter < ' py > {
85+ #[ cfg( not( Py_LIMITED_API ) ) ]
86+ impl < ' py > TryFrom < PyBytesWriter < ' py > > for Bound < ' py , PyBytes > {
5387 type Error = PyErr ;
5488
5589 #[ inline]
56- fn try_into ( self ) -> PyResult < Bound < ' py , PyBytes > > {
90+ fn try_from ( value : PyBytesWriter < ' py > ) -> Result < Self , Self :: Error > {
5791 unsafe {
58- PyBytesWriter_Finish ( self . writer . as_ptr ( ) )
59- . assume_owned_or_err ( self . python )
92+ PyBytesWriter_Finish ( value . writer . as_ptr ( ) )
93+ . assume_owned_or_err ( value . python )
6094 . cast_into_unchecked ( )
6195 }
6296 }
6397}
6498
99+ #[ cfg( Py_LIMITED_API ) ]
100+ impl < ' py > From < PyBytesWriter < ' py > > for Bound < ' py , PyBytes > {
101+ #[ inline]
102+ fn from ( writer : PyBytesWriter < ' py > ) -> Self {
103+ PyBytes :: new ( writer. python , & writer. buffer )
104+ }
105+ }
106+
107+ impl < ' py > IntoPyObject < ' py > for PyBytesWriter < ' py > {
108+ type Target = PyBytes ;
109+ type Output = Bound < ' py , PyBytes > ;
110+ type Error = PyErr ;
111+
112+ #[ inline]
113+ fn into_pyobject ( self , _py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
114+ self . try_into ( ) . map_err ( Into :: into)
115+ }
116+ }
117+
118+ #[ cfg( not( Py_LIMITED_API ) ) ]
65119impl < ' py > Drop for PyBytesWriter < ' py > {
66120 #[ inline]
67121 fn drop ( & mut self ) {
68122 unsafe { PyBytesWriter_Discard ( self . writer . as_ptr ( ) ) }
69123 }
70124}
71125
126+ #[ cfg( not( Py_LIMITED_API ) ) ]
72127impl std:: io:: Write for PyBytesWriter < ' _ > {
73128 #[ inline]
74129 fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
@@ -114,6 +169,34 @@ impl std::io::Write for PyBytesWriter<'_> {
114169 }
115170}
116171
172+ #[ cfg( Py_LIMITED_API ) ]
173+ impl std:: io:: Write for PyBytesWriter < ' _ > {
174+ #[ inline]
175+ fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
176+ self . buffer . write ( buf)
177+ }
178+
179+ #[ inline]
180+ fn write_vectored ( & mut self , bufs : & [ IoSlice < ' _ > ] ) -> std:: io:: Result < usize > {
181+ self . buffer . write_vectored ( bufs)
182+ }
183+
184+ #[ inline]
185+ fn flush ( & mut self ) -> std:: io:: Result < ( ) > {
186+ self . buffer . flush ( )
187+ }
188+
189+ #[ inline]
190+ fn write_all ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < ( ) > {
191+ self . buffer . write_all ( buf)
192+ }
193+
194+ #[ inline]
195+ fn write_fmt ( & mut self , args : std:: fmt:: Arguments < ' _ > ) -> std:: io:: Result < ( ) > {
196+ self . buffer . write_fmt ( args)
197+ }
198+ }
199+
117200#[ cfg( test) ]
118201mod tests {
119202 use super :: * ;
@@ -122,7 +205,7 @@ mod tests {
122205 #[ test]
123206 fn test_io_write ( ) {
124207 Python :: attach ( |py| {
125- let buf: [ u8 ; _ ] = [ 1 , 2 , 3 , 4 ] ;
208+ let buf = [ 1 , 2 , 3 , 4 ] ;
126209 let mut writer = PyBytesWriter :: new ( py) . unwrap ( ) ;
127210 writer. write ( & buf) . unwrap ( ) ;
128211 let bytes: Bound < ' _ , PyBytes > = writer. try_into ( ) . unwrap ( ) ;
0 commit comments