forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtupleobject.rs
More file actions
122 lines (109 loc) · 3.3 KB
/
Copy pathtupleobject.rs
File metadata and controls
122 lines (109 loc) · 3.3 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
use crate::PyObject;
use crate::object::define_py_check;
use crate::pystate::with_vm;
use core::ffi::c_int;
use core::slice;
use rustpython_vm::PyResult;
use rustpython_vm::builtins::PyTuple;
use rustpython_vm::sliceable::SliceableSequenceOp;
define_py_check!(fn PyTuple_Check, types.tuple_type);
define_py_check!(exact fn PyTuple_CheckExact, types.tuple_type);
#[unsafe(no_mangle)]
pub extern "C" fn PyTuple_New(len: isize) -> *mut PyObject {
with_vm(|vm| {
if len == 0 {
return Ok(vm.ctx.empty_tuple.to_owned());
}
Err(vm.new_not_implemented_error(
"PyTuple_New for non zero sized tuples is not supported, use PyTuple_FromArray instead",
))
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn PyTuple_FromArray(
array: *const *mut PyObject,
size: isize,
) -> *mut PyObject {
with_vm(|vm| {
let size = size
.try_into()
.map_err(|_| vm.new_system_error("negative size passed to Tuple_FromArray"))?;
let slice = unsafe { slice::from_raw_parts(array, size) };
let elements = slice
.iter()
.map(|ptr| unsafe { &**ptr }.to_owned())
.collect::<Vec<_>>();
Ok(vm.new_tuple(elements))
})
}
#[unsafe(no_mangle)]
pub extern "C" fn PyTuple_SetItem(
_tuple: *mut PyObject,
_pos: isize,
_value: *mut PyObject,
) -> c_int {
with_vm::<PyResult<()>, _>(
|vm| Err(vm.new_not_implemented_error("Tuple objects are immutable")),
)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn PyTuple_Size(tuple: *mut PyObject) -> isize {
with_vm(|vm| {
let tuple = unsafe { &*tuple }.try_downcast_ref::<PyTuple>(vm)?;
Ok(tuple.__len__())
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn PyTuple_GetItem(tuple: *mut PyObject, pos: isize) -> *mut PyObject {
with_vm(|vm| {
let tuple = unsafe { &*tuple }.try_downcast_ref::<PyTuple>(vm)?;
let result: &PyObject = pos
.try_into()
.ok()
.and_then(|index: usize| tuple.get(index))
.ok_or_else(|| vm.new_index_error("tuple index out of range"))?;
Ok(result.as_raw())
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn PyTuple_GetSlice(
tuple: *mut PyObject,
low: isize,
high: isize,
) -> *mut PyObject {
with_vm(|vm| {
let tuple = unsafe { &*tuple }.try_downcast_ref::<PyTuple>(vm)?;
let len = tuple.__len__() as isize;
let low = low.clamp(0, len);
let high = high.clamp(low, len);
let slice = tuple.do_slice(low as usize..high as usize);
Ok(vm.ctx.new_tuple(slice))
})
}
#[cfg(false)]
mod tests {
use pyo3::prelude::*;
use pyo3::types::PyTuple;
#[test]
fn test_empty_tuple() {
Python::attach(|py| {
let tuple = PyTuple::empty(py);
assert_eq!(tuple.len(), 0);
})
}
#[test]
fn test_tuple_into_python() {
Python::attach(|py| {
let tuple = (1, 2, 3).into_pyobject(py).unwrap();
assert_eq!(tuple.len(), 3);
})
}
#[test]
fn test_tuple_get_slice() {
Python::attach(|py| {
let tuple = (1, 2, 3).into_pyobject(py).unwrap();
let slice = tuple.get_slice(1, 2);
assert_eq!(slice.extract::<(u32,)>().unwrap(), (2,));
})
}
}