use crate::Imported;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3::types::{PyInt, PyString};
mod bigint_py;
use bigint_py::BigInt;
mod biguint_py;
use biguint_py::BigUint;
mod errors;
impl TryFrom<&PyAny> for BigInt {
type Error = PyErr;
fn try_from(other: &PyAny) -> PyResult<BigInt> {
if let Ok(int) = other.downcast::<PyInt>() {
Ok(BigInt(int.to_string().as_str().parse()?))
} else if let Ok(string) = other.downcast::<PyString>() {
Ok(BigInt(string.to_str()?.parse()?))
} else if let Ok(int) = other.extract::<BigInt>() {
Ok(int)
} else if let Ok(int) = other.extract::<BigUint>() {
Ok(BigInt(crate::BigInt::from(int.0)))
} else if let Ok(float_64) = other.extract::<f64>() {
Ok(BigInt(float_64.try_into()?))
} else if let Ok(float_32) = other.extract::<f32>() {
Ok(BigInt(float_32.try_into()?))
} else {
Err(PyErr::new::<PyValueError, _>("Object of unsupported type"))
}
}
}
impl TryFrom<&PyAny> for BigUint {
type Error = PyErr;
fn try_from(other: &PyAny) -> PyResult<BigUint> {
match BigInt::try_from(other)? {
BigInt(crate::BigInt { sign: true, uint }) => Ok(BigUint(uint)),
_ => Err(PyErr::new::<PyValueError, _>(
"Cannot create BigUint from negative integer",
)),
}
}
}
impl crate::BigUint<u64> {
fn __int__(&self, py: Python<'_>) -> PyResult<PyObject> {
let mut py_obj = self.val[0].to_object(py);
for (i, val) in self.val.iter().enumerate().skip(1) {
let lhs = val
.to_object(py)
.call_method1(py, "__lshift__", (64 * i,))?;
py_obj = py_obj.call_method1(py, "__or__", (lhs,))?;
}
Ok(py_obj)
}
}
#[cfg(feature = "rand")]
#[pyfunction]
fn gen_random_biguint(n: usize) -> BigUint {
BigUint(crate::gen_random_biguint(n * 64))
}
#[pyfunction]
fn read_from_file(path: String, py: Python<'_>) -> PyResult<PyObject> {
Ok(match Imported::<u64>::read_from_file(&path)? {
Imported::Uint(uint) => BigUint(uint).into_py(py),
Imported::Int(int) => BigInt(int).into_py(py),
})
}
#[pymodule]
fn twibint(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<BigUint>()?;
m.add_class::<BigInt>()?;
#[cfg(feature = "rand")]
m.add_function(wrap_pyfunction!(gen_random_biguint, m)?)?;
m.add_function(wrap_pyfunction!(read_from_file, m)?)?;
return Ok(());
}