11use crate :: PyObject ;
22use crate :: object:: define_py_check;
33use crate :: pystate:: with_vm;
4- use core:: ffi:: { c_long, c_longlong, c_ulong, c_ulonglong} ;
4+ use core:: ffi:: { c_double , c_int , c_long, c_longlong, c_ulong, c_ulonglong, c_void } ;
55use rustpython_vm:: PyResult ;
6- use rustpython_vm:: builtins:: PyInt ;
6+ use rustpython_vm:: builtins:: { PyInt , try_f64_to_bigint } ;
77
88define_py_check ! ( fn PyLong_Check , types. int_type) ;
99define_py_check ! ( exact fn PyLong_CheckExact , types. int_type) ;
@@ -38,6 +38,36 @@ pub extern "C" fn PyLong_FromUnsignedLongLong(value: c_ulonglong) -> *mut PyObje
3838 with_vm ( |vm| vm. ctx . new_int ( value) )
3939}
4040
41+ #[ unsafe( no_mangle) ]
42+ pub extern "C" fn PyLong_FromDouble ( value : c_double ) -> * mut PyObject {
43+ with_vm ( |vm| Ok ( vm. ctx . new_bigint ( & try_f64_to_bigint ( value, vm) ?) ) )
44+ }
45+
46+ #[ unsafe( no_mangle) ]
47+ pub extern "C" fn PyLong_FromInt32 ( value : i32 ) -> * mut PyObject {
48+ with_vm ( |vm| vm. ctx . new_int ( value) )
49+ }
50+
51+ #[ unsafe( no_mangle) ]
52+ pub extern "C" fn PyLong_FromInt64 ( value : i64 ) -> * mut PyObject {
53+ with_vm ( |vm| vm. ctx . new_int ( value) )
54+ }
55+
56+ #[ unsafe( no_mangle) ]
57+ pub extern "C" fn PyLong_FromUInt32 ( value : u32 ) -> * mut PyObject {
58+ with_vm ( |vm| vm. ctx . new_int ( value) )
59+ }
60+
61+ #[ unsafe( no_mangle) ]
62+ pub extern "C" fn PyLong_FromUInt64 ( value : u64 ) -> * mut PyObject {
63+ with_vm ( |vm| vm. ctx . new_int ( value) )
64+ }
65+
66+ #[ unsafe( no_mangle) ]
67+ pub extern "C" fn PyLong_FromVoidPtr ( ptr : * mut c_void ) -> * mut PyObject {
68+ with_vm ( |vm| vm. ctx . new_int ( ptr as usize ) )
69+ }
70+
4171#[ unsafe( no_mangle) ]
4272pub unsafe extern "C" fn PyLong_AsLong ( obj : * mut PyObject ) -> c_long {
4373 with_vm :: < PyResult < c_long > , _ > ( |vm| {
@@ -50,6 +80,163 @@ pub unsafe extern "C" fn PyLong_AsLong(obj: *mut PyObject) -> c_long {
5080 } )
5181}
5282
83+ #[ unsafe( no_mangle) ]
84+ pub unsafe extern "C" fn PyLong_AsInt ( obj : * mut PyObject ) -> c_int {
85+ with_vm :: < PyResult < c_int > , _ > ( |vm| {
86+ unsafe { & * obj }
87+ . to_owned ( )
88+ . try_index ( vm) ?
89+ . as_bigint ( )
90+ . try_into ( )
91+ . map_err ( |_| vm. new_overflow_error ( "Python int too large to convert to C int" ) )
92+ } )
93+ }
94+
95+ #[ unsafe( no_mangle) ]
96+ pub unsafe extern "C" fn PyLong_AsInt32 ( obj : * mut PyObject , out : * mut i32 ) -> c_int {
97+ with_vm ( |vm| {
98+ let value: i32 = unsafe { & * obj }
99+ . to_owned ( )
100+ . try_index ( vm) ?
101+ . as_bigint ( )
102+ . try_into ( )
103+ . map_err ( |_| vm. new_overflow_error ( "Python int too large to convert to int32_t" ) ) ?;
104+ unsafe { * out = value } ;
105+ Ok ( ( ) )
106+ } )
107+ }
108+
109+ #[ unsafe( no_mangle) ]
110+ pub unsafe extern "C" fn PyLong_AsInt64 ( obj : * mut PyObject , out : * mut i64 ) -> c_int {
111+ with_vm ( |vm| {
112+ let value: i64 = unsafe { & * obj }
113+ . to_owned ( )
114+ . try_index ( vm) ?
115+ . as_bigint ( )
116+ . try_into ( )
117+ . map_err ( |_| vm. new_overflow_error ( "Python int too large to convert to int64_t" ) ) ?;
118+ unsafe { * out = value } ;
119+ Ok ( ( ) )
120+ } )
121+ }
122+
123+ #[ unsafe( no_mangle) ]
124+ pub unsafe extern "C" fn PyLong_AsLongLong ( obj : * mut PyObject ) -> c_longlong {
125+ with_vm :: < PyResult < c_longlong > , _ > ( |vm| {
126+ unsafe { & * obj }
127+ . to_owned ( )
128+ . try_index ( vm) ?
129+ . as_bigint ( )
130+ . try_into ( )
131+ . map_err ( |_| vm. new_overflow_error ( "Python int too large to convert to C long long" ) )
132+ } )
133+ }
134+
135+ #[ unsafe( no_mangle) ]
136+ pub unsafe extern "C" fn PyLong_AsSize_t ( obj : * mut PyObject ) -> usize {
137+ with_vm :: < PyResult < usize > , _ > ( |vm| {
138+ let value: usize = unsafe { & * obj }
139+ . to_owned ( )
140+ . try_index ( vm) ?
141+ . as_bigint ( )
142+ . try_into ( )
143+ . map_err ( |_| vm. new_overflow_error ( "Python int too large to convert to C size_t" ) ) ?;
144+ Ok ( value)
145+ } )
146+ }
147+
148+ #[ unsafe( no_mangle) ]
149+ pub unsafe extern "C" fn PyLong_AsSsize_t ( obj : * mut PyObject ) -> isize {
150+ with_vm :: < PyResult < isize > , _ > ( |vm| {
151+ unsafe { & * obj }
152+ . to_owned ( )
153+ . try_index ( vm) ?
154+ . as_bigint ( )
155+ . try_into ( )
156+ . map_err ( |_| vm. new_overflow_error ( "Python int too large to convert to C ssize_t" ) )
157+ } )
158+ }
159+
160+ #[ unsafe( no_mangle) ]
161+ pub unsafe extern "C" fn PyLong_AsUInt32 ( obj : * mut PyObject , out : * mut u32 ) -> c_int {
162+ with_vm ( |vm| {
163+ let value: u32 = unsafe { & * obj }
164+ . to_owned ( )
165+ . try_index ( vm) ?
166+ . as_bigint ( )
167+ . try_into ( )
168+ . map_err ( |_| vm. new_overflow_error ( "Python int too large to convert to uint32_t" ) ) ?;
169+ unsafe { * out = value } ;
170+ Ok ( ( ) )
171+ } )
172+ }
173+
174+ #[ unsafe( no_mangle) ]
175+ pub unsafe extern "C" fn PyLong_AsUInt64 ( obj : * mut PyObject , out : * mut u64 ) -> c_int {
176+ with_vm ( |vm| {
177+ let value: u64 = unsafe { & * obj }
178+ . to_owned ( )
179+ . try_index ( vm) ?
180+ . as_bigint ( )
181+ . try_into ( )
182+ . map_err ( |_| vm. new_overflow_error ( "Python int too large to convert to uint64_t" ) ) ?;
183+ unsafe { * out = value } ;
184+ Ok ( ( ) )
185+ } )
186+ }
187+
188+ #[ unsafe( no_mangle) ]
189+ pub unsafe extern "C" fn PyLong_AsUnsignedLong ( obj : * mut PyObject ) -> c_ulong {
190+ with_vm :: < PyResult < c_ulong > , _ > ( |vm| {
191+ unsafe { & * obj }
192+ . to_owned ( )
193+ . try_index ( vm) ?
194+ . as_bigint ( )
195+ . try_into ( )
196+ . map_err ( |_| {
197+ vm. new_overflow_error ( "Python int too large to convert to C unsigned long" )
198+ } )
199+ } )
200+ }
201+
202+ #[ unsafe( no_mangle) ]
203+ pub unsafe extern "C" fn PyLong_AsUnsignedLongMask ( obj : * mut PyObject ) -> c_ulong {
204+ with_vm :: < PyResult < c_ulong > , _ > ( |vm| {
205+ let int = unsafe { & * obj } . to_owned ( ) . try_index ( vm) ?;
206+ if const { c_ulong:: BITS == 32 } {
207+ Ok ( c_ulong:: from ( int. as_u32_mask ( ) ) )
208+ } else {
209+ Ok ( int. as_u64_mask ( ) as c_ulong )
210+ }
211+ } )
212+ }
213+
214+ #[ unsafe( no_mangle) ]
215+ pub unsafe extern "C" fn PyLong_AsUnsignedLongLongMask ( obj : * mut PyObject ) -> c_ulonglong {
216+ with_vm :: < PyResult < c_ulonglong > , _ > ( |vm| {
217+ let int = unsafe { & * obj } . to_owned ( ) . try_index ( vm) ?;
218+ Ok ( int. as_u64_mask ( ) )
219+ } )
220+ }
221+
222+ #[ unsafe( no_mangle) ]
223+ pub unsafe extern "C" fn PyLong_AsVoidPtr ( obj : * mut PyObject ) -> * mut c_void {
224+ with_vm ( |vm| {
225+ let value = unsafe { & * obj } . to_owned ( ) . try_index ( vm) ?;
226+
227+ let unsigned: Result < usize , _ > = value. as_bigint ( ) . try_into ( ) ;
228+ if let Ok ( v) = unsigned {
229+ return Ok ( v as * mut c_void ) ;
230+ }
231+ let signed: Result < isize , _ > = value. as_bigint ( ) . try_into ( ) ;
232+ if let Ok ( v) = signed {
233+ return Ok ( ( v as usize ) as * mut c_void ) ;
234+ }
235+
236+ Err ( vm. new_overflow_error ( "int too large to convert to pointer" ) )
237+ } )
238+ }
239+
53240#[ unsafe( no_mangle) ]
54241pub unsafe extern "C" fn PyLong_AsUnsignedLongLong ( obj : * mut PyObject ) -> c_ulonglong {
55242 with_vm :: < PyResult < c_ulonglong > , _ > ( |vm| {
@@ -86,4 +273,13 @@ mod tests {
86273 assert_eq ! ( number. extract:: <u64 >( ) . unwrap( ) , 123 ) ;
87274 } )
88275 }
276+
277+ #[ test]
278+ fn py_int_u128 ( ) {
279+ Python :: attach ( |py| {
280+ let value = 1u128 << 100 ;
281+ let number = PyInt :: new ( py, value) ;
282+ assert_eq ! ( number. extract:: <u128 >( ) . unwrap( ) , value) ;
283+ } )
284+ }
89285}
0 commit comments