TryFromBorrowedObject for ints

This commit is contained in:
Jeong YunWon
2021-08-12 05:53:56 +09:00
parent 9d99ea9376
commit 5ff0e4e5de
10 changed files with 57 additions and 32 deletions

View File

@@ -19,8 +19,9 @@ use crate::slots::{Comparable, Hashable, PyComparisonOp};
use crate::VirtualMachine;
use crate::{bytesinner::PyBytesInner, byteslike::try_bytes_like};
use crate::{
IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue, PyClassImpl, PyComparisonValue,
PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
try_value_from_borrowed_object, IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue,
PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
TryFromBorrowedObject, TypeProtocol,
};
use rustpython_common::hash;
@@ -101,10 +102,11 @@ where
macro_rules! impl_try_from_object_int {
($(($t:ty, $to_prim:ident),)*) => {$(
impl TryFromObject for $t {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let int = PyIntRef::try_from_object(vm, obj)?;
try_to_primitive(&int.value, vm)
impl TryFromBorrowedObject for $t {
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Self> {
try_value_from_borrowed_object(vm, obj, |int: &PyInt| {
try_to_primitive(int.as_bigint(), vm)
})
}
}
)*};

View File

@@ -13,7 +13,7 @@ mod decl {
use crate::builtins::code::PyCodeRef;
use crate::builtins::dict::PyDictRef;
use crate::builtins::function::{PyCellRef, PyFunctionRef};
use crate::builtins::int::PyIntRef;
use crate::builtins::int::{self, PyIntRef};
use crate::builtins::iter::{PyCallableIterator, PySequenceIterator};
use crate::builtins::list::{PyList, SortOptions};
use crate::builtins::pybool::IntoPyBool;
@@ -161,7 +161,7 @@ mod decl {
let flags = args
.flags
.map_or(Ok(0), |v| i32::try_from_object(vm, v.into_object()))?;
.map_or(Ok(0), |v| int::try_to_primitive(v.as_bigint(), vm))?;
if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() {
#[cfg(not(feature = "rustpython-compiler"))]

View File

@@ -6,8 +6,8 @@ use super::pystr::PyStrRef;
use crate::function::OptionalArg;
use crate::vm::VirtualMachine;
use crate::{
IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, TryFromObject,
TypeProtocol,
IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, TryFromBorrowedObject,
TryFromObject, TypeProtocol,
};
impl IntoPyObject for bool {
@@ -16,10 +16,10 @@ impl IntoPyObject for bool {
}
}
impl TryFromObject for bool {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
impl TryFromBorrowedObject for bool {
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<bool> {
if obj.isinstance(&vm.ctx.types.int_type) {
Ok(get_value(&obj))
Ok(get_value(obj))
} else {
Err(vm.new_type_error(format!("Expected type bool, not {}", obj.class().name)))
}

View File

@@ -408,6 +408,28 @@ impl Default for PyContext {
}
}
pub(crate) fn try_value_from_borrowed_object<T, F, R>(
vm: &VirtualMachine,
obj: &PyObjectRef,
f: F,
) -> PyResult<R>
where
T: PyValue,
F: Fn(&T) -> PyResult<R>,
{
let class = T::class(vm);
let special;
let py_ref = if obj.isinstance(class) {
obj.downcast_ref()
.ok_or_else(|| pyref_payload_error(vm, class, obj))?
} else {
special = T::special_retrieve(vm, obj)
.unwrap_or_else(|| Err(pyref_type_error(vm, class, obj)))?;
&special
};
f(py_ref)
}
impl<T> TryFromObject for PyRef<T>
where
T: PyValue,
@@ -435,7 +457,8 @@ fn pyref_payload_error(
&*obj.borrow().class().name,
))
}
fn pyref_type_error(
pub(crate) fn pyref_type_error(
vm: &VirtualMachine,
class: &PyTypeRef,
obj: impl std::borrow::Borrow<PyObjectRef>,

View File

@@ -11,7 +11,7 @@ mod _codecs {
use crate::exceptions::PyBaseExceptionRef;
use crate::function::FuncArgs;
use crate::VirtualMachine;
use crate::{IdProtocol, PyObjectRef, PyResult, TryFromObject};
use crate::{IdProtocol, PyObjectRef, PyResult, TryFromBorrowedObject};
#[pyfunction]
fn register(search_function: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
@@ -156,7 +156,7 @@ mod _codecs {
.ok_or_else(tuple_err)?
.clone();
let restart =
isize::try_from_object(vm, restart.clone()).map_err(|_| tuple_err())?;
isize::try_from_borrowed_object(vm, restart).map_err(|_| tuple_err())?;
let restart = if restart < 0 {
// will still be out of bounds if it underflows ¯\_(ツ)_/¯
data.len().wrapping_sub(restart.unsigned_abs())

View File

@@ -30,7 +30,7 @@ use crate::utils::Either;
use crate::vm::{ReprGuard, VirtualMachine};
use crate::{
IntoPyObject, ItemProtocol, PyObjectRef, PyRef, PyResult, PyStructSequence, PyValue,
StaticType, TryFromObject, TypeProtocol,
StaticType, TryFromBorrowedObject, TryFromObject, TypeProtocol,
};
#[cfg(unix)]
@@ -1654,7 +1654,7 @@ mod _os {
#[pyfunction]
fn truncate(path: PyObjectRef, length: Offset, vm: &VirtualMachine) -> PyResult<()> {
if let Ok(fd) = i32::try_from_object(vm, path.clone()) {
if let Ok(fd) = i32::try_from_borrowed_object(vm, &path) {
return ftruncate(fd, length, vm);
}
let path = PyPathLike::try_from_object(vm, path)?;
@@ -2867,7 +2867,7 @@ mod posix {
"Each file_actions element must be a non-empty tuple".to_owned(),
)
})?;
let id = i32::try_from_object(vm, id.clone())?;
let id = i32::try_from_borrowed_object(vm, id)?;
let id = PosixSpawnFileActionIdentifier::try_from(id).map_err(|_| {
vm.new_type_error("Unknown file_actions identifier".to_owned())
})?;

View File

@@ -5,7 +5,7 @@ mod resource {
use super::super::os;
use crate::exceptions::IntoPyException;
use crate::VirtualMachine;
use crate::{IntoPyObject, PyObjectRef, PyResult, PyStructSequence, TryFromObject};
use crate::{IntoPyObject, PyObjectRef, PyResult, PyStructSequence, TryFromBorrowedObject};
use std::{io, mem};
cfg_if::cfg_if! {
@@ -111,9 +111,9 @@ mod resource {
}
struct Limits(libc::rlimit);
impl TryFromObject for Limits {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let seq = vm.extract_elements::<libc::rlim_t>(&obj)?;
impl TryFromBorrowedObject for Limits {
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Self> {
let seq = vm.extract_elements::<libc::rlim_t>(obj)?;
match *seq {
[cur, max] => Ok(Self(libc::rlimit {
rlim_cur: cur & RLIM_INFINITY,

View File

@@ -1,5 +1,5 @@
use crate::vm::VirtualMachine;
use crate::{PyObjectRef, PyResult, TryFromObject};
use crate::{PyObjectRef, PyResult, TryFromBorrowedObject, TryFromObject};
use std::{io, mem};
pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef {
@@ -72,7 +72,7 @@ struct Selectable {
impl TryFromObject for Selectable {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let fno = RawFd::try_from_object(vm, obj.clone()).or_else(|_| {
let fno = RawFd::try_from_borrowed_object(vm, &obj).or_else(|_| {
let meth = vm.get_method_or_type_error(obj.clone(), "fileno", || {
"select arg must be an int or object with a fileno() method".to_owned()
})?;

View File

@@ -1,6 +1,6 @@
use crate::exceptions::IntoPyException;
use crate::vm::{VirtualMachine, NSIG};
use crate::{PyObjectRef, PyResult, TryFromObject};
use crate::{PyObjectRef, PyResult, TryFromBorrowedObject};
use std::sync::atomic::{self, AtomicBool, Ordering};
@@ -81,7 +81,7 @@ fn _signal_signal(
.as_deref()
.ok_or_else(|| vm.new_value_error("signal only works in main thread".to_owned()))?;
let sig_handler = match usize::try_from_object(vm, handler.clone()).ok() {
let sig_handler = match usize::try_from_borrowed_object(vm, &handler).ok() {
Some(SIG_DFL) => SIG_DFL,
Some(SIG_IGN) => SIG_IGN,
None if vm.is_callable(&handler) => run_signal as libc::sighandler_t,

View File

@@ -21,8 +21,8 @@ use crate::function::{FuncArgs, OptionalArg, OptionalOption};
use crate::utils::Either;
use crate::VirtualMachine;
use crate::{
IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, StaticType, TryFromObject,
TypeProtocol,
IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, StaticType,
TryFromBorrowedObject, TryFromObject, TypeProtocol,
};
#[cfg(unix)]
@@ -970,7 +970,7 @@ impl TryFromObject for Address {
impl Address {
fn from_tuple(tuple: &[PyObjectRef], vm: &VirtualMachine) -> PyResult<Self> {
let host = PyStrRef::try_from_object(vm, tuple[0].clone())?;
let port = i32::try_from_object(vm, tuple[1].clone())?;
let port = i32::try_from_borrowed_object(vm, &tuple[1])?;
let port = port
.to_u16()
.ok_or_else(|| vm.new_overflow_error("port must be 0-65535.".to_owned()))?;
@@ -980,12 +980,12 @@ impl Address {
let addr = Address::from_tuple(tuple, vm)?;
let flowinfo = tuple
.get(2)
.map(|obj| u32::try_from_object(vm, obj.clone()))
.map(|obj| u32::try_from_borrowed_object(vm, obj))
.transpose()?
.unwrap_or(0);
let scopeid = tuple
.get(3)
.map(|obj| u32::try_from_object(vm, obj.clone()))
.map(|obj| u32::try_from_borrowed_object(vm, obj))
.transpose()?
.unwrap_or(0);
if flowinfo > 0xfffff {