Skip to content

Commit 5ddb678

Browse files
committed
Add memory::RcBuffer
1 parent 374a956 commit 5ddb678

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

vm/src/builtins/memory.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::bytesinner::bytes_to_hex;
99
use crate::common::borrow::{BorrowedValue, BorrowedValueMut};
1010
use crate::common::hash::PyHash;
1111
use crate::common::lock::OnceCell;
12+
use crate::common::rc::PyRc;
1213
use crate::function::OptionalArg;
1314
use crate::pyobject::{
1415
Either, IdProtocol, IntoPyObject, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef,
@@ -41,12 +42,55 @@ impl BufferRef {
4142
pub fn new(buffer: impl Buffer + 'static) -> Self {
4243
Self(Box::new(buffer))
4344
}
45+
pub fn into_rcbuf(self) -> RcBuffer {
46+
// move self.0 out of self; BufferRef impls Drop so it's tricky
47+
let this = std::mem::ManuallyDrop::new(self);
48+
let buf_box = unsafe { std::ptr::read(&this.0) };
49+
RcBuffer(buf_box.into())
50+
}
4451
}
4552
impl From<Box<dyn Buffer>> for BufferRef {
4653
fn from(buffer: Box<dyn Buffer>) -> Self {
4754
BufferRef(buffer)
4855
}
4956
}
57+
#[derive(Debug, Clone)]
58+
pub struct RcBuffer(PyRc<dyn Buffer>);
59+
impl Deref for RcBuffer {
60+
type Target = dyn Buffer;
61+
fn deref(&self) -> &Self::Target {
62+
self.0.deref()
63+
}
64+
}
65+
impl Drop for RcBuffer {
66+
fn drop(&mut self) {
67+
// check if this is the last rc before the inner buffer gets dropped
68+
if let Some(buf) = PyRc::get_mut(&mut self.0) {
69+
buf.release()
70+
}
71+
}
72+
}
73+
impl Buffer for RcBuffer {
74+
fn get_options(&self) -> BorrowedValue<BufferOptions> {
75+
self.0.get_options()
76+
}
77+
fn obj_bytes(&self) -> BorrowedValue<[u8]> {
78+
self.0.obj_bytes()
79+
}
80+
fn obj_bytes_mut(&self) -> BorrowedValueMut<[u8]> {
81+
self.0.obj_bytes_mut()
82+
}
83+
fn release(&self) {}
84+
fn as_contiguous(&self) -> Option<BorrowedValue<[u8]>> {
85+
self.0.as_contiguous()
86+
}
87+
fn as_contiguous_mut(&self) -> Option<BorrowedValueMut<[u8]>> {
88+
self.0.as_contiguous_mut()
89+
}
90+
fn to_contiguous(&self) -> Vec<u8> {
91+
self.0.to_contiguous()
92+
}
93+
}
5094

5195
pub trait Buffer: Debug + PyThreadingConstraint {
5296
fn get_options(&self) -> BorrowedValue<BufferOptions>;
@@ -168,6 +212,29 @@ impl PyMemoryView {
168212
})
169213
}
170214

215+
pub fn from_buffer_range(
216+
obj: PyObjectRef,
217+
buffer: BufferRef,
218+
range: std::ops::Range<usize>,
219+
vm: &VirtualMachine,
220+
) -> PyResult<Self> {
221+
let options = buffer.get_options().clone();
222+
let itemsize = options.itemsize;
223+
let format_spec = Self::parse_format(&options.format, vm)?;
224+
Ok(PyMemoryView {
225+
obj,
226+
buffer,
227+
options,
228+
released: AtomicCell::new(false),
229+
start: range.start * itemsize,
230+
stop: range.end * itemsize,
231+
step: 1,
232+
exports: AtomicCell::new(0),
233+
format_spec,
234+
hash: OnceCell::new(),
235+
})
236+
}
237+
171238
pub fn try_bytes<F, R>(&self, vm: &VirtualMachine, f: F) -> PyResult<R>
172239
where
173240
F: FnOnce(&[u8]) -> R,

0 commit comments

Comments
 (0)