3
3
use crate :: common:: borrow:: { BorrowedValue , BorrowedValueMut } ;
4
4
use crate :: common:: rc:: PyRc ;
5
5
use 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 } ;
9
8
10
- pub trait PyBuffer : Debug + PyThreadingConstraint {
11
- fn get_options ( & self ) -> & BufferOptions ;
9
+ pub trait PyBufferInternal : Debug + PyThreadingConstraint {
12
10
/// Get the full inner buffer of this memory. You probably want [`as_contiguous()`], as
13
11
/// `obj_bytes` doesn't take into account the range a memoryview might operate on, among other
14
12
/// footguns.
@@ -18,49 +16,84 @@ pub trait PyBuffer: Debug + PyThreadingConstraint {
18
16
/// might operate on, among other footguns.
19
17
fn obj_bytes_mut ( & self ) -> BorrowedValueMut < [ u8 ] > ;
20
18
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
+ }
21
29
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 {
24
45
return None ;
25
46
}
26
- Some ( self . obj_bytes ( ) )
47
+ Some ( self . internal . obj_bytes ( ) )
27
48
}
28
49
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 {
31
52
return None ;
32
53
}
33
- Some ( self . obj_bytes_mut ( ) )
54
+ Some ( self . internal . obj_bytes_mut ( ) )
34
55
}
35
56
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
+ }
38
68
}
39
69
}
40
70
41
71
#[ derive( Debug , Clone ) ]
42
72
pub struct BufferOptions {
43
- pub readonly : bool ,
73
+ // buf
44
74
pub len : usize ,
75
+ pub readonly : bool ,
45
76
pub itemsize : usize ,
46
- pub contiguous : bool ,
47
77
pub format : Cow < ' static , str > ,
48
- // TODO: support multiple dimension array
49
- pub ndim : usize ,
78
+ pub ndim : usize , // TODO: support multiple dimension array
50
79
pub shape : Vec < usize > ,
51
80
pub strides : Vec < isize > ,
81
+ // suboffsets
82
+
83
+ // RustPython fields
84
+ pub contiguous : bool ,
52
85
}
53
86
54
87
impl BufferOptions {
55
88
pub const DEFAULT : Self = BufferOptions {
56
- readonly : true ,
57
89
len : 0 ,
90
+ readonly : true ,
58
91
itemsize : 1 ,
59
- contiguous : true ,
60
92
format : Cow :: Borrowed ( "B" ) ,
61
93
ndim : 1 ,
62
94
shape : Vec :: new ( ) ,
63
95
strides : Vec :: new ( ) ,
96
+ contiguous : true ,
64
97
} ;
65
98
}
66
99
@@ -70,15 +103,12 @@ impl Default for BufferOptions {
70
103
}
71
104
}
72
105
73
- #[ derive( Debug ) ]
74
- pub struct PyBufferRef ( Box < dyn PyBuffer > ) ;
75
-
76
- impl TryFromBorrowedObject for PyBufferRef {
106
+ impl TryFromBorrowedObject for PyBuffer {
77
107
fn try_from_borrowed_object ( vm : & VirtualMachine , obj : & PyObjectRef ) -> PyResult < Self > {
78
108
let obj_cls = obj. class ( ) ;
79
109
for cls in obj_cls. iter_mro ( ) {
80
110
if let Some ( f) = cls. slots . as_buffer . as_ref ( ) {
81
- return f ( obj, vm) . map ( |x| PyBufferRef ( x ) ) ;
111
+ return f ( obj, vm) ;
82
112
}
83
113
}
84
114
Err ( vm. new_type_error ( format ! (
@@ -88,76 +118,18 @@ impl TryFromBorrowedObject for PyBufferRef {
88
118
}
89
119
}
90
120
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 {
134
125
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 ( ) ;
139
127
}
140
128
}
141
129
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 ( ) )
161
133
}
162
134
}
163
135
0 commit comments