Skip to content

Commit ccd36ca

Browse files
committed
AsBuffer
1 parent 8556955 commit ccd36ca

File tree

7 files changed

+698
-223
lines changed

7 files changed

+698
-223
lines changed

crates/vm/src/stdlib/ctypes.rs

Lines changed: 139 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
4545

4646
#[pymodule]
4747
pub(crate) mod _ctypes {
48-
use super::base::PyCSimple;
48+
use super::base::{CDataObject, PyCSimple};
4949
use crate::builtins::PyTypeRef;
5050
use crate::class::StaticType;
5151
use crate::convert::ToPyObject;
@@ -159,14 +159,15 @@ pub(crate) mod _ctypes {
159159
}
160160

161161
/// Get the size of a ctypes type from its type object
162+
#[allow(dead_code)]
162163
pub fn get_size_from_type(cls: &PyTypeRef, vm: &VirtualMachine) -> PyResult<usize> {
163164
// Try to get _type_ attribute for simple types
164-
if let Ok(type_attr) = cls.as_object().get_attr("_type_", vm) {
165-
if let Ok(s) = type_attr.str(vm) {
166-
let s = s.to_string();
167-
if s.len() == 1 && SIMPLE_TYPE_CHARS.contains(s.as_str()) {
168-
return Ok(get_size(&s));
169-
}
165+
if let Ok(type_attr) = cls.as_object().get_attr("_type_", vm)
166+
&& let Ok(s) = type_attr.str(vm)
167+
{
168+
let s = s.to_string();
169+
if s.len() == 1 && SIMPLE_TYPE_CHARS.contains(s.as_str()) {
170+
return Ok(get_size(&s));
170171
}
171172
}
172173
// Fall back to sizeof
@@ -180,138 +181,138 @@ pub(crate) mod _ctypes {
180181
vm: &VirtualMachine,
181182
) -> PyResult<PyObjectRef> {
182183
// Try to get _type_ attribute
183-
if let Ok(type_attr) = cls.as_object().get_attr("_type_", vm) {
184-
if let Ok(s) = type_attr.str(vm) {
185-
let ty = s.to_string();
186-
return match ty.as_str() {
187-
"c" => {
188-
// c_char - single byte
189-
Ok(vm.ctx.new_bytes(bytes.to_vec()).into())
190-
}
191-
"b" => {
192-
// c_byte - signed char
193-
let val = if !bytes.is_empty() { bytes[0] as i8 } else { 0 };
194-
Ok(vm.ctx.new_int(val).into())
195-
}
196-
"B" => {
197-
// c_ubyte - unsigned char
198-
let val = if !bytes.is_empty() { bytes[0] } else { 0 };
199-
Ok(vm.ctx.new_int(val).into())
200-
}
201-
"h" => {
202-
// c_short
203-
let val = if bytes.len() >= 2 {
204-
i16::from_ne_bytes([bytes[0], bytes[1]])
205-
} else {
206-
0
207-
};
208-
Ok(vm.ctx.new_int(val).into())
209-
}
210-
"H" => {
211-
// c_ushort
212-
let val = if bytes.len() >= 2 {
213-
u16::from_ne_bytes([bytes[0], bytes[1]])
214-
} else {
215-
0
216-
};
217-
Ok(vm.ctx.new_int(val).into())
218-
}
219-
"i" | "l" => {
220-
// c_int, c_long (assuming 32-bit)
221-
let val = if bytes.len() >= 4 {
222-
i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
184+
if let Ok(type_attr) = cls.as_object().get_attr("_type_", vm)
185+
&& let Ok(s) = type_attr.str(vm)
186+
{
187+
let ty = s.to_string();
188+
return match ty.as_str() {
189+
"c" => {
190+
// c_char - single byte
191+
Ok(vm.ctx.new_bytes(bytes.to_vec()).into())
192+
}
193+
"b" => {
194+
// c_byte - signed char
195+
let val = if !bytes.is_empty() { bytes[0] as i8 } else { 0 };
196+
Ok(vm.ctx.new_int(val).into())
197+
}
198+
"B" => {
199+
// c_ubyte - unsigned char
200+
let val = if !bytes.is_empty() { bytes[0] } else { 0 };
201+
Ok(vm.ctx.new_int(val).into())
202+
}
203+
"h" => {
204+
// c_short
205+
let val = if bytes.len() >= 2 {
206+
i16::from_ne_bytes([bytes[0], bytes[1]])
207+
} else {
208+
0
209+
};
210+
Ok(vm.ctx.new_int(val).into())
211+
}
212+
"H" => {
213+
// c_ushort
214+
let val = if bytes.len() >= 2 {
215+
u16::from_ne_bytes([bytes[0], bytes[1]])
216+
} else {
217+
0
218+
};
219+
Ok(vm.ctx.new_int(val).into())
220+
}
221+
"i" | "l" => {
222+
// c_int, c_long (assuming 32-bit)
223+
let val = if bytes.len() >= 4 {
224+
i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
225+
} else {
226+
0
227+
};
228+
Ok(vm.ctx.new_int(val).into())
229+
}
230+
"I" | "L" => {
231+
// c_uint, c_ulong (assuming 32-bit)
232+
let val = if bytes.len() >= 4 {
233+
u32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
234+
} else {
235+
0
236+
};
237+
Ok(vm.ctx.new_int(val).into())
238+
}
239+
"q" => {
240+
// c_longlong
241+
let val = if bytes.len() >= 8 {
242+
i64::from_ne_bytes([
243+
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6],
244+
bytes[7],
245+
])
246+
} else {
247+
0
248+
};
249+
Ok(vm.ctx.new_int(val).into())
250+
}
251+
"Q" => {
252+
// c_ulonglong
253+
let val = if bytes.len() >= 8 {
254+
u64::from_ne_bytes([
255+
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6],
256+
bytes[7],
257+
])
258+
} else {
259+
0
260+
};
261+
Ok(vm.ctx.new_int(val).into())
262+
}
263+
"f" => {
264+
// c_float
265+
let val = if bytes.len() >= 4 {
266+
f32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
267+
} else {
268+
0.0
269+
};
270+
Ok(vm.ctx.new_float(val as f64).into())
271+
}
272+
"d" | "g" => {
273+
// c_double
274+
let val = if bytes.len() >= 8 {
275+
f64::from_ne_bytes([
276+
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6],
277+
bytes[7],
278+
])
279+
} else {
280+
0.0
281+
};
282+
Ok(vm.ctx.new_float(val).into())
283+
}
284+
"?" => {
285+
// c_bool
286+
let val = !bytes.is_empty() && bytes[0] != 0;
287+
Ok(vm.ctx.new_bool(val).into())
288+
}
289+
"P" | "z" | "Z" => {
290+
// Pointer types - return as integer address
291+
let val = if bytes.len() >= mem::size_of::<usize>() {
292+
let mut arr = [0u8; 8];
293+
arr[..bytes.len().min(8)].copy_from_slice(&bytes[..bytes.len().min(8)]);
294+
usize::from_ne_bytes(arr)
295+
} else {
296+
0
297+
};
298+
Ok(vm.ctx.new_int(val).into())
299+
}
300+
"u" => {
301+
// c_wchar - wide character
302+
let val = if bytes.len() >= mem::size_of::<WideChar>() {
303+
let wc = if mem::size_of::<WideChar>() == 2 {
304+
u16::from_ne_bytes([bytes[0], bytes[1]]) as u32
223305
} else {
224-
0
225-
};
226-
Ok(vm.ctx.new_int(val).into())
227-
}
228-
"I" | "L" => {
229-
// c_uint, c_ulong (assuming 32-bit)
230-
let val = if bytes.len() >= 4 {
231306
u32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
232-
} else {
233-
0
234-
};
235-
Ok(vm.ctx.new_int(val).into())
236-
}
237-
"q" => {
238-
// c_longlong
239-
let val = if bytes.len() >= 8 {
240-
i64::from_ne_bytes([
241-
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5],
242-
bytes[6], bytes[7],
243-
])
244-
} else {
245-
0
246-
};
247-
Ok(vm.ctx.new_int(val).into())
248-
}
249-
"Q" => {
250-
// c_ulonglong
251-
let val = if bytes.len() >= 8 {
252-
u64::from_ne_bytes([
253-
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5],
254-
bytes[6], bytes[7],
255-
])
256-
} else {
257-
0
258-
};
259-
Ok(vm.ctx.new_int(val).into())
260-
}
261-
"f" => {
262-
// c_float
263-
let val = if bytes.len() >= 4 {
264-
f32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
265-
} else {
266-
0.0
267-
};
268-
Ok(vm.ctx.new_float(val as f64).into())
269-
}
270-
"d" | "g" => {
271-
// c_double
272-
let val = if bytes.len() >= 8 {
273-
f64::from_ne_bytes([
274-
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5],
275-
bytes[6], bytes[7],
276-
])
277-
} else {
278-
0.0
279-
};
280-
Ok(vm.ctx.new_float(val).into())
281-
}
282-
"?" => {
283-
// c_bool
284-
let val = !bytes.is_empty() && bytes[0] != 0;
285-
Ok(vm.ctx.new_bool(val).into())
286-
}
287-
"P" | "z" | "Z" => {
288-
// Pointer types - return as integer address
289-
let val = if bytes.len() >= mem::size_of::<usize>() {
290-
let mut arr = [0u8; 8];
291-
arr[..bytes.len().min(8)].copy_from_slice(&bytes[..bytes.len().min(8)]);
292-
usize::from_ne_bytes(arr)
293-
} else {
294-
0
295307
};
296-
Ok(vm.ctx.new_int(val).into())
297-
}
298-
"u" => {
299-
// c_wchar - wide character
300-
let val = if bytes.len() >= mem::size_of::<WideChar>() {
301-
let wc = if mem::size_of::<WideChar>() == 2 {
302-
u16::from_ne_bytes([bytes[0], bytes[1]]) as u32
303-
} else {
304-
u32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
305-
};
306-
char::from_u32(wc).unwrap_or('\0')
307-
} else {
308-
'\0'
309-
};
310-
Ok(vm.ctx.new_str(val.to_string()).into())
311-
}
312-
_ => Ok(vm.ctx.none()),
313-
};
314-
}
308+
char::from_u32(wc).unwrap_or('\0')
309+
} else {
310+
'\0'
311+
};
312+
Ok(vm.ctx.new_str(val.to_string()).into())
313+
}
314+
_ => Ok(vm.ctx.none()),
315+
};
315316
}
316317
// Default: return bytes as-is
317318
Ok(vm.ctx.new_bytes(bytes.to_vec()).into())
@@ -339,9 +340,11 @@ pub(crate) mod _ctypes {
339340
} else if !SIMPLE_TYPE_CHARS.contains(tp_str.as_str()) {
340341
Err(vm.new_attribute_error(format!("class must define a '_type_' attribute which must be\n a single character string containing one of {SIMPLE_TYPE_CHARS}, currently it is {tp_str}.")))
341342
} else {
343+
let size = get_size(&tp_str);
342344
Ok(PyCSimple {
343345
_type_: tp_str,
344346
value: AtomicCell::new(vm.ctx.none()),
347+
cdata: rustpython_common::lock::PyRwLock::new(CDataObject::new(size)),
345348
})
346349
}
347350
} else {

0 commit comments

Comments
 (0)