Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 46 additions & 11 deletions crates/vm/src/stdlib/ctypes/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
types::{AsBuffer, AsNumber, AsSequence, Constructor, Initializer},
};
use num_traits::{Signed, ToPrimitive};
use std::borrow::Cow;

/// Get itemsize from a PEP 3118 format string
/// Extracts the type code (last char after endianness prefix) and returns its size
Expand Down Expand Up @@ -430,6 +431,18 @@ impl Constructor for PyCArray {
}
}

impl Initializer for PyCArray {
type Args = FuncArgs;

fn init(zelf: PyRef<Self>, args: Self::Args, vm: &VirtualMachine) -> PyResult<()> {
// Re-initialize array elements when __init__ is called
for (i, value) in args.args.iter().enumerate() {
PyCArray::setitem_by_index(&zelf, i as isize, value.clone(), vm)?;
}
Ok(())
}
}

impl AsSequence for PyCArray {
fn as_sequence() -> &'static PySequenceMethods {
use std::sync::LazyLock;
Expand Down Expand Up @@ -457,7 +470,7 @@ impl AsSequence for PyCArray {

#[pyclass(
flags(BASETYPE, IMMUTABLETYPE),
with(Constructor, AsSequence, AsBuffer)
with(Constructor, Initializer, AsSequence, AsBuffer)
)]
impl PyCArray {
#[pyclassmethod]
Expand Down Expand Up @@ -868,16 +881,38 @@ impl PyCArray {
};

let mut buffer = buffer_lock.write();
Self::write_element_to_buffer(
buffer.to_mut(),
final_offset,
element_size,
type_code.as_deref(),
&value,
zelf,
index,
vm,
)

// For shared memory (Cow::Borrowed), we need to write directly to the memory
// For owned memory (Cow::Owned), we can write to the owned buffer
match &mut *buffer {
Cow::Borrowed(slice) => {
// SAFETY: For from_buffer, the slice points to writable shared memory.
// Python's from_buffer requires writable buffer, so this is safe.
let ptr = slice.as_ptr() as *mut u8;
let len = slice.len();
let owned_slice = unsafe { std::slice::from_raw_parts_mut(ptr, len) };
Self::write_element_to_buffer(
owned_slice,
final_offset,
element_size,
type_code.as_deref(),
&value,
zelf,
index,
vm,
)
}
Cow::Owned(vec) => Self::write_element_to_buffer(
vec,
final_offset,
element_size,
type_code.as_deref(),
&value,
zelf,
index,
vm,
),
}
}

// Array_subscript
Expand Down
36 changes: 34 additions & 2 deletions crates/vm/src/stdlib/ctypes/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,18 @@ impl Constructor for PyCSimple {
}
}

impl Initializer for PyCSimple {
type Args = (OptionalArg,);

fn init(zelf: PyRef<Self>, args: Self::Args, vm: &VirtualMachine) -> PyResult<()> {
// If an argument is provided, update the value
if let Some(value) = args.0.into_option() {
PyCSimple::set_value(zelf.into(), value, vm)?;
}
Ok(())
}
}

// Simple_repr
impl Representable for PyCSimple {
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
Expand All @@ -1111,7 +1123,10 @@ impl Representable for PyCSimple {
}
}

#[pyclass(flags(BASETYPE), with(Constructor, AsBuffer, AsNumber, Representable))]
#[pyclass(
flags(BASETYPE),
with(Constructor, Initializer, AsBuffer, AsNumber, Representable)
)]
impl PyCSimple {
#[pygetset]
fn _b0_(&self) -> Option<PyObjectRef> {
Expand Down Expand Up @@ -1278,7 +1293,24 @@ impl PyCSimple {

// Update buffer when value changes
let buffer_bytes = value_to_bytes_endian(&type_code, &content, swapped, vm);
*zelf.0.buffer.write() = std::borrow::Cow::Owned(buffer_bytes);

// If the buffer is borrowed (from shared memory), write in-place
// Otherwise replace with new owned buffer
let mut buffer = zelf.0.buffer.write();
match &mut *buffer {
Cow::Borrowed(slice) => {
// SAFETY: For from_buffer, the slice points to writable shared memory.
// Python's from_buffer requires writable buffer, so this is safe.
let ptr = slice.as_ptr() as *mut u8;
let len = slice.len().min(buffer_bytes.len());
unsafe {
std::ptr::copy_nonoverlapping(buffer_bytes.as_ptr(), ptr, len);
}
}
Cow::Owned(vec) => {
vec.copy_from_slice(&buffer_bytes);
}
}

// For c_char_p (type "z"), c_wchar_p (type "Z"), and py_object (type "O"),
// keep the reference in _objects
Expand Down
Loading