Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fixed more errors
Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
  • Loading branch information
arihant2math committed Jan 23, 2025
commit 6e515a6ab2b8e3bf7083dd6016745614c760c165
106 changes: 56 additions & 50 deletions vm/src/stdlib/ctypes/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,22 @@ use super::{
pointer::PyCPointer,
primitive::{new_simple_type, PyCSimple},
};
use crate::builtins::{
slice::PySlice,
PyBytes, PyInt, PyList, PyRange, PyStr, PyType, PyTypeRef,
};
use crate::builtins::{slice::PySlice, PyBytes, PyInt, PyList, PyRange, PyStr, PyType, PyTypeRef};
use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard};
use crate::function::{Either, OptionalArg};
use crate::sliceable::SequenceIndex;
use crate::stdlib::ctypes::basics::{
default_from_param, generic_get_buffer, get_size, BorrowValue as BorrowValueCData,
BorrowValueMut, PyCData, PyCDataFunctions, PyCDataMethods, PyCDataSequenceMethods, RawBuffer,
};
use crate::{AsObject, Py, PyObjectRef, PyRef, PyResult, TryFromObject, VirtualMachine};
use crate::{AsObject, Context, Py, PyObjectRef, PyRef, PyResult, TryFromObject, VirtualMachine};
use rustpython_vm::object::PyPayload;
use num_traits::Signed;
use std::convert::TryInto;
use std::fmt;
use widestring::WideCString;
use crate::class::StaticType;
use crate::convert::IntoObject;
use crate::convert::{IntoObject, ToPyObject};
use crate::protocol::{PyBuffer, PyIter};
use crate::types::AsBuffer;

Expand Down Expand Up @@ -85,15 +82,16 @@ pub fn make_array_with_length(
})?;
let length = length as usize;
let _type_ = vm
.get_attribute(outer_type.clone(), "_type_")
// TODO: original was get_attribute
.get_attribute_opt(outer_type.clone(), "_type_")
.map_err(|_| vm.new_type_error("_type_ must have storage info".to_string()))?;
let itemsize = get_size(_type_.downcast::<PyStr>().unwrap().to_string().as_str());
let itemsize = get_size(_type_.unwrap().downcast::<PyStr>().unwrap().to_string().as_str());
let capacity = length
.checked_mul(itemsize)
.ok_or_else(|| vm.new_overflow_error("array too large".to_string()))?;
// FIXME change this initialization
Ok(PyCArray {
_type_: new_simple_type(Either::A(&outer_type), vm)?.into_ref(vm),
_type_: new_simple_type(Either::A(&outer_type), vm)?.into_ref(&vm.ctx),
_length_: length,
_buffer: PyRwLock::new(RawBuffer {
inner: Vec::with_capacity(capacity).as_mut_ptr(),
Expand All @@ -111,20 +109,22 @@ fn set_array_value(
obj: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
let self_cls = zelf.clone_class();
let self_cls = zelf.class().clone();

if !self_cls.issubclass(PyCData::static_type()) {
// TODO: ensure fast_issubclass is the right thing to use
if !self_cls.fast_issubclass(PyCData::static_type()) {
return Err(vm.new_type_error("not a ctype instance".to_string()));
}

let obj_cls = obj.clone_class();
let obj_cls = obj.clone().class();

if !obj_cls.issubclass(PyCData::static_type()) {
// TODO: ensure fast_issubclass is the right thing to use
if !obj_cls.fast_issubclass(PyCData::static_type()) {
// TODO: Fill here
}

if vm.isinstance(&obj, &self_cls)? {
let o_buffer = PyBuffer::try_from_object(vm, &obj)?;
if obj.is_instance(self_cls.as_ref(), vm)? {
let o_buffer = PyBuffer::try_from_object(vm, obj)?;
let src_buffer = o_buffer.obj_bytes();

assert!(dst_buffer.len() == size && src_buffer.len() >= size);
Expand All @@ -137,7 +137,7 @@ fn set_array_value(
} else {
return Err(vm.new_type_error(format!(
"incompatible types, {} instance instead of {} instance",
obj_cls.name, self_cls.name
obj_cls.name(), self_cls.name()
)));
}

Expand All @@ -150,13 +150,13 @@ fn array_get_slice_params(
vm: &VirtualMachine,
) -> PyResult<(isize, isize, isize)> {
if let Some(ref len) = length {
let indices = vm.get_method(slice.as_object().clone(), "indices").unwrap().unwrap();
let indices = vm.get_method(slice.to_pyobject(vm), "indices").unwrap()?;
let tuple = vm.invoke(&indices, (len.clone(),))?;

let (start, stop, step) = (
tuple.get_item(0, vm)?,
tuple.get_item(1, vm)?,
tuple.get_item(2, vm)?,
tuple.get_item(&0, vm)?,
tuple.get_item(&1, vm)?,
tuple.get_item(&2, vm)?,
);

Ok((
Expand Down Expand Up @@ -193,17 +193,17 @@ fn array_slice_getitem<'a>(
vm: &'a VirtualMachine,
) -> PyResult {
let length = vm
.get_attribute(zelf.clone(), "_length_")
.map(|c_l| usize::try_from_object(vm, c_l))??;
.get_attribute_opt(zelf.clone(), "_length_")
.map(|c_l| usize::try_from_object(vm, c_l.unwrap()))??;

let tp = vm.get_attribute(zelf, "_type_")?.downcast::<PyStr>().unwrap().to_string();
let tp = vm.get_attribute_opt(zelf, "_type_")?.unwrap().downcast::<PyStr>().unwrap().to_string();
let _type_ = tp.as_str();
let (step, start, stop) = array_get_slice_params(slice, &Some(vm.ctx.new_int(length)), vm)?;
let (step, start, stop) = array_get_slice_params(slice, &Some(vm.ctx.new_int(length).to_pyobject(&vm)), vm)?;

let _range = PyRange {
start: PyInt::from(start).into_ref(vm),
stop: PyInt::from(stop).into_ref(vm),
step: PyInt::from(step).into_ref(vm),
start: PyInt::from(start).into_ref(&vm.ctx),
stop: PyInt::from(stop).into_ref(&vm.ctx),
step: PyInt::from(step).into_ref(&vm.ctx),
};

let mut obj_vec = Vec::new();
Expand Down Expand Up @@ -246,9 +246,9 @@ fn array_slice_setitem(
}

let _range = PyRange {
start: PyInt::from(start).into_ref(vm),
stop: PyInt::from(stop).into_ref(vm),
step: PyInt::from(step).into_ref(vm),
start: PyInt::from(start).into_ref(&vm.ctx),
stop: PyInt::from(stop).into_ref(&vm.ctx),
step: PyInt::from(step).into_ref(&vm.ctx),
};

//FIXME: this function should be called for pointer too (length should be None),
Expand All @@ -259,7 +259,7 @@ fn array_slice_setitem(
for (i, curr) in PyIter::try_from_object(vm,_range.into_object(vm))?.iter(vm)?.enumerate() {
let idx = fix_index(isize::try_from_object(vm, curr?)?, size, vm)? as usize;
let offset = idx * size;
let item = obj.get_item(i, vm)?;
let item = obj.get_item(&i, vm)?;
let buffer_slice = &mut buffer_bytes[offset..offset + size];

set_array_value(&zelf, buffer_slice, idx, size, item, vm)?;
Expand All @@ -284,9 +284,9 @@ fn fix_index(index: isize, length: usize, vm: &VirtualMachine) -> PyResult<isize
}

#[pyclass(module = "_ctypes", name = "PyCArrayType", base = "PyType")]
#[derive(PyPayload)]
pub struct PyCArrayMeta {}

#[derive(PyPayload)]
#[pyclass(
module = "_ctypes",
name = "Array",
Expand Down Expand Up @@ -328,6 +328,12 @@ impl<'a> BorrowValueMut<'a> for PyCArray {
}
}

impl PyPayload for PyCArray {
fn class(ctx: &Context) -> &'static Py<PyType> {
todo!()
}
}

impl AsBuffer for PyCArray {
fn as_buffer(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyBuffer> {
generic_get_buffer::<Self>(zelf, vm)
Expand All @@ -341,9 +347,9 @@ impl PyCDataMethods for PyCArrayMeta {
vm: &VirtualMachine,
) -> PyResult<PyObjectRef> {
let mut value = value;
let cls = zelf.clone_class();
let cls = zelf.class().clone();

if vm.isinstance(&value, &cls)? {
if value.is_instance(&cls.into(), vm)? {
return Ok(value);
}

Expand All @@ -353,8 +359,8 @@ impl PyCDataMethods for PyCArrayMeta {

let value_len = vm.obj_len(&value)?;

if let Ok(tp) = vm.get_attribute(zelf.as_object().clone(), "_type_") {
let _type = tp.downcast::<PyCSimple>().unwrap();
if let Ok(tp) = vm.get_attribute_opt(zelf.as_object().clone(), "_type_") {
let _type = tp.unwrap().downcast::<PyCSimple>().unwrap();

if _type._type_.as_str() == "c" {
if vm.isinstance(&value, &vm.ctx.types.bytes_type).is_ok() {
Expand All @@ -364,7 +370,7 @@ impl PyCDataMethods for PyCArrayMeta {
value = make_array_with_length(cls.clone(), length, vm)?.as_object().clone();
} else if vm.isinstance(&value, &cls).is_err() {
return Err(
vm.new_type_error(format!("expected bytes, {} found", value.class().name))
vm.new_type_error(format!("expected bytes, {} found", value.class().name()))
);
}
} else if _type._type_.as_str() == "u" {
Expand All @@ -376,13 +382,13 @@ impl PyCDataMethods for PyCArrayMeta {
} else if vm.isinstance(&value, &cls).is_err() {
return Err(vm.new_type_error(format!(
"expected unicode string, {} found",
value.class().name
value.class().name()
)));
}
}
}

if vm.isinstance(&value, &vm.ctx.types.tuple_type).is_ok() {
if value.is_instance(&vm.ctx.types.tuple_type, &vm).is_ok() {
if value_len > length {
return Err(vm.new_runtime_error("Invalid length".to_string()));
}
Expand All @@ -396,20 +402,20 @@ impl PyCDataMethods for PyCArrayMeta {
#[pyclass(with(PyCDataMethods), flags(BASETYPE))]
impl PyCArrayMeta {
#[pyslot]
fn tp_new(cls: PyTypeRef, vm: &VirtualMachine) -> PyResult {
fn slot_new(cls: PyTypeRef, vm: &VirtualMachine) -> PyResult {
let length_obj = vm
.get_attribute(cls.as_object().to_owned(), "_length_")
.get_attribute_opt(cls.as_object().to_owned(), "_length_")
.map_err(|_| {
vm.new_attribute_error("class must define a '_length_' attribute".to_string())
})?;
let length_int = length_obj.downcast_exact::<PyInt>(vm).map_err(|_| {
let length_int = length_obj.unwrap().downcast_exact::<PyInt>(vm).map_err(|_| {
vm.new_type_error("The '_length_' attribute must be an integer".to_string())
})?;
let length: usize = if length_int.as_bigint().is_negative() {
Err(vm.new_value_error("The '_length_' attribute must not be negative".to_string()))
} else {
Ok(
try_to_primitive(length_int.as_bigint(), vm).map_err(|_| {
PyInt::try_to_primitive(&length_int, vm).map_err(|_| {
vm.new_overflow_error("The '_length_' attribute is too large".to_owned())
})?,
)
Expand All @@ -419,7 +425,7 @@ impl PyCArrayMeta {
}
}

#[pyclass(flags(BASETYPE), with(BufferProtocol, PyCDataFunctions))]
#[pyclass(flags(BASETYPE), with(AsBuffer, PyCDataFunctions))]
impl PyCArray {
#[pymethod(magic)]
pub fn init(zelf: PyRef<Self>, value: OptionalArg, vm: &VirtualMachine) -> PyResult<()> {
Expand Down Expand Up @@ -459,7 +465,7 @@ impl PyCArray {
vm.new_pyobj(
unsafe {
if cfg!(windows) {
WideCString::from_vec_with_nul_unchecked(
WideCString::from_vec_unchecked(
buffer
.obj_bytes()
.chunks_exact(2)
Expand All @@ -470,7 +476,7 @@ impl PyCArray {
.collect::<Vec<u32>>(),
)
} else {
WideCString::from_vec_with_nul_unchecked(
WideCString::from_vec_unchecked(
buffer
.obj_bytes()
.chunks(4)
Expand Down Expand Up @@ -517,7 +523,7 @@ impl PyCArray {
let value = value.downcast_exact::<PyBytes>(vm).map_err(|value| {
vm.new_value_error(format!(
"bytes expected instead of {} instance",
value.class().name
value.class().name()
))
})?;
let wide_bytes = value.to_vec();
Expand All @@ -536,10 +542,10 @@ impl PyCArray {
let value = value.downcast_exact::<PyStr>(vm).map_err(|value| {
vm.new_value_error(format!(
"unicode string expected instead of {} instance",
value.class().name
value.class().name()
))
})?;
let wide_str = unsafe { WideCString::from_str_with_nul_unchecked(value.to_string()) };
let wide_str = unsafe { WideCString::from_str_unchecked(value.to_string()) };

let wide_str_len = wide_str.len();

Expand Down Expand Up @@ -581,7 +587,7 @@ impl PyCArray {

#[pygetset(magic, setter)]
fn set_raw(zelf: PyRef<Self>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
let my_buffer = PyBuffer::try_from_object(vm, zelf)?;
let my_buffer = PyBuffer::try_from_object(vm, zelf.into())?;
let my_size = my_buffer.get_options().len;

let new_value = PyBuffer::try_from_object(vm, &value)?;
Expand Down
43 changes: 5 additions & 38 deletions vm/src/stdlib/ctypes/basics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ use widestring::WideChar;

use crate::builtins::int::PyInt;
use crate::builtins::pystr::PyStrRef;
use crate::common::borrow::{BorrowedValue, BorrowedValueMut};
use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard};
use crate::function::OptionalArg;
use crate::{PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine};
use crate::{AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine};

use crate::stdlib::ctypes::array::make_array_with_length;
use crate::stdlib::ctypes::dll::dlsym;
Expand Down Expand Up @@ -40,8 +39,8 @@ pub fn get_size(ty: &str) -> usize {
}

fn at_address(cls: &PyTypeRef, buf: usize, vm: &VirtualMachine) -> PyResult<RawBuffer> {
match vm.get_attribute(cls.as_object().to_owned(), "__abstract__") {
Ok(attr) => match bool::try_from_object(vm, attr) {
match vm.get_attribute_opt(cls.as_object().to_owned(), "__abstract__") {
Ok(attr) => match bool::try_from_object(vm, attr.unwrap()) {
Ok(false) => {
let len = vm
.get_attribute(cls.as_object().to_owned(), "_length_")
Expand Down Expand Up @@ -279,11 +278,6 @@ where
if let Ok(_buffer) = buffer.downcast_exact::<RawBuffer>(vm) {
Ok(Box::new(PyCBuffer::<T> {
data: zelf.clone(),
options: BufferOptions {
readonly: false,
len: _buffer.size,
..Default::default()
},
}))
} else {
Err(vm.new_attribute_error("_buffer attribute should be RawBuffer".to_string()))
Expand Down Expand Up @@ -314,44 +308,17 @@ impl<'a> BorrowValueMut<'a> for PyCData {
}

impl AsBuffer for PyCData {
fn as_buffer(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyBuffer> {
fn as_buffer(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyBuffer> {
generic_get_buffer::<Self>(zelf, vm)
}
}

// This trait will be used by all types
impl<T> Buffer for PyCBuffer<T>
where
for<'a> T: PyPayload + fmt::Debug + BorrowValue<'a> + BorrowValueMut<'a>,
{
fn obj_bytes(&self) -> BorrowedValue<[u8]> {
PyRwLockReadGuard::map(self.data.borrow_value(), |x| unsafe {
slice::from_raw_parts(x.inner, x.size)
})
.into()
}

fn obj_bytes_mut(&self) -> BorrowedValueMut<[u8]> {
PyRwLockWriteGuard::map(self.data.borrow_value_mut(), |x| unsafe {
slice::from_raw_parts_mut(x.inner, x.size)
})
.into()
}

fn release(&self) {}

fn get_options(&self) -> &BufferOptions {
&self.options
}
}

#[derive(Debug)]
pub struct PyCBuffer<T>
where
for<'a> T: PyPayload + fmt::Debug + BorrowValue<'a> + BorrowValueMut<'a>,
{
pub data: PyRef<T>,
pub options: BufferOptions,
}

// FIXME: Change this implementation
Expand Down Expand Up @@ -397,7 +364,7 @@ impl PyCData {
}
}

#[pyclass(flags(BASETYPE), with(BufferProtocol))]
#[pyclass(flags(BASETYPE), with(AsBuffer))]
impl PyCData {
// PyCData_methods
#[pymethod(magic)]
Expand Down
Loading