forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuffer.rs
More file actions
167 lines (147 loc) · 4.43 KB
/
buffer.rs
File metadata and controls
167 lines (147 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! Buffer protocol
use crate::common::borrow::{BorrowedValue, BorrowedValueMut};
use crate::common::rc::PyRc;
use crate::PyThreadingConstraint;
use crate::{PyObjectRef, PyResult, TypeProtocol};
use crate::{TryFromBorrowedObject, VirtualMachine};
use std::{borrow::Cow, fmt::Debug, ops::Deref};
pub trait PyBuffer: Debug + PyThreadingConstraint {
fn get_options(&self) -> &BufferOptions;
/// Get the full inner buffer of this memory. You probably want [`as_contiguous()`], as
/// `obj_bytes` doesn't take into account the range a memoryview might operate on, among other
/// footguns.
fn obj_bytes(&self) -> BorrowedValue<[u8]>;
/// Get the full inner buffer of this memory, mutably. You probably want
/// [`as_contiguous_mut()`], as `obj_bytes` doesn't take into account the range a memoryview
/// might operate on, among other footguns.
fn obj_bytes_mut(&self) -> BorrowedValueMut<[u8]>;
fn release(&self);
fn as_contiguous(&self) -> Option<BorrowedValue<[u8]>> {
if !self.get_options().contiguous {
return None;
}
Some(self.obj_bytes())
}
fn as_contiguous_mut(&self) -> Option<BorrowedValueMut<[u8]>> {
if !self.get_options().contiguous {
return None;
}
Some(self.obj_bytes_mut())
}
fn to_contiguous(&self) -> Vec<u8> {
self.obj_bytes().to_vec()
}
}
#[derive(Debug, Clone)]
pub struct BufferOptions {
pub readonly: bool,
pub len: usize,
pub itemsize: usize,
pub contiguous: bool,
pub format: Cow<'static, str>,
// TODO: support multiple dimension array
pub ndim: usize,
pub shape: Vec<usize>,
pub strides: Vec<isize>,
}
impl BufferOptions {
pub const DEFAULT: Self = BufferOptions {
readonly: true,
len: 0,
itemsize: 1,
contiguous: true,
format: Cow::Borrowed("B"),
ndim: 1,
shape: Vec::new(),
strides: Vec::new(),
};
}
impl Default for BufferOptions {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(Debug)]
pub struct PyBufferRef(Box<dyn PyBuffer>);
impl TryFromBorrowedObject for PyBufferRef {
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Self> {
let obj_cls = obj.class();
for cls in obj_cls.iter_mro() {
if let Some(f) = cls.slots.as_buffer.as_ref() {
return f(obj, vm).map(|x| PyBufferRef(x));
}
}
Err(vm.new_type_error(format!(
"a bytes-like object is required, not '{}'",
obj_cls.name
)))
}
}
impl Drop for PyBufferRef {
fn drop(&mut self) {
self.0.release();
}
}
impl Deref for PyBufferRef {
type Target = dyn PyBuffer;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl PyBufferRef {
pub fn new(buffer: impl PyBuffer + 'static) -> Self {
Self(Box::new(buffer))
}
pub fn into_rcbuf(self) -> RcBuffer {
// move self.0 out of self; PyBufferRef impls Drop so it's tricky
let this = std::mem::ManuallyDrop::new(self);
let buf_box = unsafe { std::ptr::read(&this.0) };
RcBuffer(buf_box.into())
}
}
impl From<Box<dyn PyBuffer>> for PyBufferRef {
fn from(buffer: Box<dyn PyBuffer>) -> Self {
PyBufferRef(buffer)
}
}
#[derive(Debug, Clone)]
pub struct RcBuffer(PyRc<dyn PyBuffer>);
impl Deref for RcBuffer {
type Target = dyn PyBuffer;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl Drop for RcBuffer {
fn drop(&mut self) {
// check if this is the last rc before the inner buffer gets dropped
if let Some(buf) = PyRc::get_mut(&mut self.0) {
buf.release()
}
}
}
impl PyBuffer for RcBuffer {
fn get_options(&self) -> &BufferOptions {
self.0.get_options()
}
fn obj_bytes(&self) -> BorrowedValue<[u8]> {
self.0.obj_bytes()
}
fn obj_bytes_mut(&self) -> BorrowedValueMut<[u8]> {
self.0.obj_bytes_mut()
}
fn release(&self) {}
fn as_contiguous(&self) -> Option<BorrowedValue<[u8]>> {
self.0.as_contiguous()
}
fn as_contiguous_mut(&self) -> Option<BorrowedValueMut<[u8]>> {
self.0.as_contiguous_mut()
}
fn to_contiguous(&self) -> Vec<u8> {
self.0.to_contiguous()
}
}
pub(crate) trait ResizeGuard<'a> {
type Resizable: 'a;
fn try_resizable(&'a self, vm: &VirtualMachine) -> PyResult<Self::Resizable>;
}