33use crate :: common:: borrow:: { BorrowedValue , BorrowedValueMut } ;
44use crate :: common:: rc:: PyRc ;
55use crate :: PyThreadingConstraint ;
6- use crate :: { PyObjectRef , PyResult , TypeProtocol } ;
7- use crate :: { TryFromBorrowedObject , VirtualMachine } ;
8- use std:: { borrow:: Cow , fmt:: Debug , ops:: Deref } ;
6+ use crate :: { PyObjectRef , PyResult , TryFromBorrowedObject , TypeProtocol , VirtualMachine } ;
7+ use std:: { borrow:: Cow , fmt:: Debug } ;
98
10- pub trait PyBuffer : Debug + PyThreadingConstraint {
11- fn get_options ( & self ) -> & BufferOptions ;
9+ pub trait PyBufferInternal : Debug + PyThreadingConstraint {
1210 /// Get the full inner buffer of this memory. You probably want [`as_contiguous()`], as
1311 /// `obj_bytes` doesn't take into account the range a memoryview might operate on, among other
1412 /// footguns.
@@ -18,49 +16,84 @@ pub trait PyBuffer: Debug + PyThreadingConstraint {
1816 /// might operate on, among other footguns.
1917 fn obj_bytes_mut ( & self ) -> BorrowedValueMut < [ u8 ] > ;
2018 fn release ( & self ) ;
19+ // not included in PyBuffer protocol itself
20+ fn retain ( & self ) ;
21+ }
22+
23+ #[ derive( Debug ) ]
24+ pub struct PyBuffer {
25+ pub obj : PyObjectRef ,
26+ pub options : BufferOptions ,
27+ pub ( crate ) internal : PyRc < dyn PyBufferInternal > ,
28+ }
2129
22- fn as_contiguous ( & self ) -> Option < BorrowedValue < [ u8 ] > > {
23- if !self . get_options ( ) . contiguous {
30+ impl PyBuffer {
31+ pub fn new (
32+ obj : PyObjectRef ,
33+ buffer : impl PyBufferInternal + ' static ,
34+ options : BufferOptions ,
35+ ) -> Self {
36+ buffer. retain ( ) ;
37+ Self {
38+ obj,
39+ options,
40+ internal : PyRc :: new ( buffer) ,
41+ }
42+ }
43+ pub fn as_contiguous ( & self ) -> Option < BorrowedValue < [ u8 ] > > {
44+ if !self . options . contiguous {
2445 return None ;
2546 }
26- Some ( self . obj_bytes ( ) )
47+ Some ( self . internal . obj_bytes ( ) )
2748 }
2849
29- fn as_contiguous_mut ( & self ) -> Option < BorrowedValueMut < [ u8 ] > > {
30- if !self . get_options ( ) . contiguous {
50+ pub fn as_contiguous_mut ( & self ) -> Option < BorrowedValueMut < [ u8 ] > > {
51+ if !self . options . contiguous {
3152 return None ;
3253 }
33- Some ( self . obj_bytes_mut ( ) )
54+ Some ( self . internal . obj_bytes_mut ( ) )
3455 }
3556
36- fn to_contiguous ( & self ) -> Vec < u8 > {
37- self . obj_bytes ( ) . to_vec ( )
57+ pub fn to_contiguous ( & self ) -> Vec < u8 > {
58+ self . internal . obj_bytes ( ) . to_vec ( )
59+ }
60+
61+ pub fn clone_with_options ( & self , options : BufferOptions ) -> Self {
62+ self . internal . retain ( ) ;
63+ Self {
64+ obj : self . obj . clone ( ) ,
65+ options,
66+ internal : self . internal . clone ( ) ,
67+ }
3868 }
3969}
4070
4171#[ derive( Debug , Clone ) ]
4272pub struct BufferOptions {
43- pub readonly : bool ,
73+ // buf
4474 pub len : usize ,
75+ pub readonly : bool ,
4576 pub itemsize : usize ,
46- pub contiguous : bool ,
4777 pub format : Cow < ' static , str > ,
48- // TODO: support multiple dimension array
49- pub ndim : usize ,
78+ pub ndim : usize , // TODO: support multiple dimension array
5079 pub shape : Vec < usize > ,
5180 pub strides : Vec < isize > ,
81+ // suboffsets
82+
83+ // RustPython fields
84+ pub contiguous : bool ,
5285}
5386
5487impl BufferOptions {
5588 pub const DEFAULT : Self = BufferOptions {
56- readonly : true ,
5789 len : 0 ,
90+ readonly : true ,
5891 itemsize : 1 ,
59- contiguous : true ,
6092 format : Cow :: Borrowed ( "B" ) ,
6193 ndim : 1 ,
6294 shape : Vec :: new ( ) ,
6395 strides : Vec :: new ( ) ,
96+ contiguous : true ,
6497 } ;
6598}
6699
@@ -70,15 +103,12 @@ impl Default for BufferOptions {
70103 }
71104}
72105
73- #[ derive( Debug ) ]
74- pub struct PyBufferRef ( Box < dyn PyBuffer > ) ;
75-
76- impl TryFromBorrowedObject for PyBufferRef {
106+ impl TryFromBorrowedObject for PyBuffer {
77107 fn try_from_borrowed_object ( vm : & VirtualMachine , obj : & PyObjectRef ) -> PyResult < Self > {
78108 let obj_cls = obj. class ( ) ;
79109 for cls in obj_cls. iter_mro ( ) {
80110 if let Some ( f) = cls. slots . as_buffer . as_ref ( ) {
81- return f ( obj, vm) . map ( |x| PyBufferRef ( x ) ) ;
111+ return f ( obj, vm) ;
82112 }
83113 }
84114 Err ( vm. new_type_error ( format ! (
@@ -88,76 +118,18 @@ impl TryFromBorrowedObject for PyBufferRef {
88118 }
89119}
90120
91- impl Drop for PyBufferRef {
92- fn drop ( & mut self ) {
93- self . 0 . release ( ) ;
94- }
95- }
96-
97- impl Deref for PyBufferRef {
98- type Target = dyn PyBuffer ;
99-
100- fn deref ( & self ) -> & Self :: Target {
101- self . 0 . deref ( )
102- }
103- }
104-
105- impl PyBufferRef {
106- pub fn new ( buffer : impl PyBuffer + ' static ) -> Self {
107- Self ( Box :: new ( buffer) )
108- }
109-
110- pub fn into_rcbuf ( self ) -> RcBuffer {
111- // move self.0 out of self; PyBufferRef impls Drop so it's tricky
112- let this = std:: mem:: ManuallyDrop :: new ( self ) ;
113- let buf_box = unsafe { std:: ptr:: read ( & this. 0 ) } ;
114- RcBuffer ( buf_box. into ( ) )
115- }
116- }
117-
118- impl From < Box < dyn PyBuffer > > for PyBufferRef {
119- fn from ( buffer : Box < dyn PyBuffer > ) -> Self {
120- PyBufferRef ( buffer)
121- }
122- }
123-
124- #[ derive( Debug , Clone ) ]
125- pub struct RcBuffer ( PyRc < dyn PyBuffer > ) ;
126- impl Deref for RcBuffer {
127- type Target = dyn PyBuffer ;
128- fn deref ( & self ) -> & Self :: Target {
129- self . 0 . deref ( )
130- }
131- }
132-
133- impl Drop for RcBuffer {
121+ // What we actually want to implement is:
122+ // impl<T> Drop for T where T: PyBufferInternal
123+ // but it is not supported by Rust
124+ impl Drop for PyBuffer {
134125 fn drop ( & mut self ) {
135- // check if this is the last rc before the inner buffer gets dropped
136- if let Some ( buf) = PyRc :: get_mut ( & mut self . 0 ) {
137- buf. release ( )
138- }
126+ self . internal . release ( ) ;
139127 }
140128}
141129
142- impl PyBuffer for RcBuffer {
143- fn get_options ( & self ) -> & BufferOptions {
144- self . 0 . get_options ( )
145- }
146- fn obj_bytes ( & self ) -> BorrowedValue < [ u8 ] > {
147- self . 0 . obj_bytes ( )
148- }
149- fn obj_bytes_mut ( & self ) -> BorrowedValueMut < [ u8 ] > {
150- self . 0 . obj_bytes_mut ( )
151- }
152- fn release ( & self ) { }
153- fn as_contiguous ( & self ) -> Option < BorrowedValue < [ u8 ] > > {
154- self . 0 . as_contiguous ( )
155- }
156- fn as_contiguous_mut ( & self ) -> Option < BorrowedValueMut < [ u8 ] > > {
157- self . 0 . as_contiguous_mut ( )
158- }
159- fn to_contiguous ( & self ) -> Vec < u8 > {
160- self . 0 . to_contiguous ( )
130+ impl Clone for PyBuffer {
131+ fn clone ( & self ) -> Self {
132+ self . clone_with_options ( self . options . clone ( ) )
161133 }
162134}
163135
0 commit comments