Skip to content

Commit 0b801cc

Browse files
committed
Add objint::try_to_primitive
1 parent 6ed0100 commit 0b801cc

File tree

3 files changed

+19
-18
lines changed

3 files changed

+19
-18
lines changed

vm/src/obj/objint.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
use std::convert::TryFrom;
12
use std::fmt;
23
use std::mem::size_of;
34

45
use bstr::ByteSlice;
56
use num_bigint::{BigInt, BigUint, Sign};
67
use num_integer::Integer;
7-
use num_traits::{One, Pow, Signed, ToPrimitive, Zero};
8+
use num_traits::{One, Pow, PrimInt, Signed, ToPrimitive, Zero};
89

910
use super::objbool::IntoPyBool;
1011
use super::objbytearray::PyByteArray;
@@ -92,20 +93,24 @@ macro_rules! impl_into_pyobject_int {
9293

9394
impl_into_pyobject_int!(isize i8 i16 i32 i64 usize u8 u16 u32 u64 BigInt);
9495

96+
pub fn try_to_primitive<'a, I>(i: &'a BigInt, vm: &VirtualMachine) -> PyResult<I>
97+
where
98+
I: PrimInt + TryFrom<&'a BigInt>,
99+
{
100+
I::try_from(i).map_err(|_| {
101+
vm.new_overflow_error(format!(
102+
"Python int too large to convert to Rust {}",
103+
std::any::type_name::<I>()
104+
))
105+
})
106+
}
107+
95108
macro_rules! impl_try_from_object_int {
96109
($(($t:ty, $to_prim:ident),)*) => {$(
97110
impl TryFromObject for $t {
98111
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
99112
let int = PyIntRef::try_from_object(vm, obj)?;
100-
match int.value.$to_prim() {
101-
Some(value) => Ok(value),
102-
None => Err(
103-
vm.new_overflow_error(concat!(
104-
"Int value cannot fit into Rust ",
105-
stringify!($t)
106-
).to_owned())
107-
),
108-
}
113+
try_to_primitive(&int.value, vm)
109114
}
110115
}
111116
)*};

vm/src/obj/objiter.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
*/
44

55
use crossbeam_utils::atomic::AtomicCell;
6-
use num_traits::{Signed, ToPrimitive};
6+
use num_traits::Signed;
77

8-
use super::objint::PyInt;
8+
use super::objint::{self, PyInt};
99
use super::objsequence;
1010
use super::objtype::{self, PyClassRef};
1111
use crate::exceptions::PyBaseExceptionRef;
@@ -143,9 +143,7 @@ pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult<Option<us
143143
if result.is_negative() {
144144
return Err(vm.new_value_error("__length_hint__() should return >= 0".to_owned()));
145145
}
146-
let hint = result.to_usize().ok_or_else(|| {
147-
vm.new_value_error("Python int too large to convert to Rust usize".to_owned())
148-
})?;
146+
let hint = objint::try_to_primitive(result, vm)?;
149147
Ok(Some(hint))
150148
}
151149

vm/src/stdlib/io.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,9 +1052,7 @@ fn text_io_wrapper_write(
10521052
let bytes = obj.borrow_value().to_owned().into_bytes();
10531053

10541054
let len = vm.call_method(&raw, "write", vec![vm.ctx.new_bytes(bytes.clone())])?;
1055-
let len = objint::get_value(&len)
1056-
.to_usize()
1057-
.ok_or_else(|| vm.new_overflow_error("int to large to convert to Rust usize".to_owned()))?;
1055+
let len = objint::try_to_primitive(objint::get_value(&len), vm)?;
10581056

10591057
// returns the count of unicode code points written
10601058
let len = from_utf8(&bytes[..len])

0 commit comments

Comments
 (0)