@@ -10,14 +10,13 @@ pub(crate) use _interpqueues::{
1010#[ pymodule]
1111pub ( crate ) mod _interpqueues {
1212 use crate :: {
13- AsObject , Py , PyObject , PyPayload , PyResult , VirtualMachine ,
13+ AsObject , Py , PyObject , PyObjectRef , PyPayload , PyResult , VirtualMachine ,
1414 builtins:: { PyBaseExceptionRef , PyModule , PyType , PyTypeRef } ,
15- function:: { ArgSpec , FuncArgs } ,
15+ function:: OptionalArg ,
1616 types:: Constructor ,
1717 vm:: crossinterp:: { Fallback , SharedValue , UnboundOp } ,
1818 } ;
1919 use alloc:: { collections:: BTreeMap , collections:: VecDeque , sync:: Arc } ;
20- use core:: cell:: Cell ;
2120 use num_traits:: { Signed , ToPrimitive } ;
2221 use parking_lot:: Mutex ;
2322 use std:: sync:: OnceLock ;
@@ -339,23 +338,11 @@ pub(crate) mod _interpqueues {
339338 Err ( vm. new_overflow_error ( format ! ( "max queue ID is {}, got {repr}" , i64 :: MAX ) ) )
340339 }
341340
342- fn qid_arg ( args : & FuncArgs , func : & ' static str , vm : & VirtualMachine ) -> PyResult < i64 > {
343- let qid = Cell :: new ( None ) ;
344- ArgSpec {
345- fname : func,
346- keywords : & [ "qid" ] ,
347- required : 1 ,
348- max_positional : 1 ,
341+ fn optional_int_arg ( arg : & OptionalArg < PyObjectRef > , vm : & VirtualMachine ) -> PyResult < i32 > {
342+ match arg {
343+ OptionalArg :: Present ( obj) => int_arg ( obj, vm) ,
344+ OptionalArg :: Missing => Ok ( -1 ) ,
349345 }
350- . parse_with (
351- args,
352- |_, obj, vm| {
353- qid. set ( Some ( parse_qid ( obj, vm) ?) ) ;
354- Ok ( ( ) )
355- } ,
356- vm,
357- ) ?;
358- Ok ( qid. get ( ) . unwrap ( ) )
359346 }
360347
361348 #[ expect( clippy:: unnecessary_wraps, reason = "Needs to comply with a signature" ) ]
@@ -365,39 +352,58 @@ pub(crate) mod _interpqueues {
365352 Ok ( ( ) )
366353 }
367354
355+ // Keep the original inputs alive while applying the queue-specific converters.
356+ #[ derive( FromArgs ) ]
357+ struct QueueIdArgs {
358+ #[ pyarg( any) ]
359+ qid : PyObjectRef ,
360+ }
361+
362+ #[ derive( FromArgs ) ]
363+ struct CreateArgs {
364+ #[ pyarg( any) ]
365+ maxsize : PyObjectRef ,
366+ #[ pyarg( any, optional, py_default = "-1" ) ]
367+ unboundop : OptionalArg < PyObjectRef > ,
368+ #[ pyarg( any, optional, py_default = "-1" ) ]
369+ fallback : OptionalArg < PyObjectRef > ,
370+ }
371+
372+ #[ derive( FromArgs ) ]
373+ struct PutArgs {
374+ #[ pyarg( any) ]
375+ qid : PyObjectRef ,
376+ #[ pyarg( any) ]
377+ obj : PyObjectRef ,
378+ #[ pyarg( any, optional, py_default = "-1" ) ]
379+ unboundop : OptionalArg < PyObjectRef > ,
380+ #[ pyarg( any, optional, py_default = "-1" ) ]
381+ fallback : OptionalArg < PyObjectRef > ,
382+ }
383+
384+ #[ derive( FromArgs ) ]
385+ struct RegisterHeapTypesArgs {
386+ #[ pyarg( any) ]
387+ queuetype : PyObjectRef ,
388+ #[ pyarg( any) ]
389+ emptyerror : PyObjectRef ,
390+ #[ pyarg( any) ]
391+ fullerror : PyObjectRef ,
392+ }
393+
368394 #[ pyfunction]
369- fn create ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < i64 > {
370- let maxsize = Cell :: new ( None ) ;
371- let unboundarg = Cell :: new ( None ) ;
372- let fallbackarg = Cell :: new ( None ) ;
373- ArgSpec {
374- fname : "create" ,
375- keywords : & [ "maxsize" , "unboundop" , "fallback" ] ,
376- required : 1 ,
377- max_positional : 3 ,
378- }
379- . parse_with (
380- & args,
381- |i, obj, vm| {
382- match i {
383- 0 => maxsize. set ( Some ( ssize_arg ( obj, vm) ?) ) ,
384- 1 => unboundarg. set ( Some ( int_arg ( obj, vm) ?) ) ,
385- 2 => fallbackarg. set ( Some ( int_arg ( obj, vm) ?) ) ,
386- _ => unreachable ! ( ) ,
387- }
388- Ok ( ( ) )
389- } ,
390- vm,
391- ) ?;
392- let unboundop = resolve_unboundop ( unboundarg. get ( ) . unwrap_or ( -1 ) , UnboundOp :: Replace , vm) ?;
393- let fallback =
394- resolve_fallback ( fallbackarg. get ( ) . unwrap_or ( -1 ) , Fallback :: Full . as_i32 ( ) , vm) ?;
395- queue_create ( maxsize. get ( ) . unwrap ( ) , unboundop, fallback) . map_err ( |err| err. into_py ( -1 , vm) )
395+ fn create ( args : CreateArgs , vm : & VirtualMachine ) -> PyResult < i64 > {
396+ let maxsize = ssize_arg ( & args. maxsize , vm) ?;
397+ let unboundarg = optional_int_arg ( & args. unboundop , vm) ?;
398+ let fallbackarg = optional_int_arg ( & args. fallback , vm) ?;
399+ let unboundop = resolve_unboundop ( unboundarg, UnboundOp :: Replace , vm) ?;
400+ let fallback = resolve_fallback ( fallbackarg, Fallback :: Full . as_i32 ( ) , vm) ?;
401+ queue_create ( maxsize, unboundop, fallback) . map_err ( |err| err. into_py ( -1 , vm) )
396402 }
397403
398404 #[ pyfunction]
399- fn destroy ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
400- let qid = qid_arg ( & args, "destroy" , vm) ?;
405+ fn destroy ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
406+ let qid = parse_qid ( & args. qid , vm) ?;
401407 queue_destroy ( qid) . map_err ( |err| err. into_py ( qid, vm) )
402408 }
403409
@@ -429,33 +435,10 @@ pub(crate) mod _interpqueues {
429435 }
430436
431437 #[ pyfunction]
432- fn put ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
433- let qid = Cell :: new ( None ) ;
434- let unboundarg = Cell :: new ( None ) ;
435- let fallbackarg = Cell :: new ( None ) ;
436- let parsed = ArgSpec {
437- fname : "put" ,
438- keywords : & [ "qid" , "obj" , "unboundop" , "fallback" ] ,
439- required : 2 ,
440- max_positional : 4 ,
441- }
442- . parse_with (
443- & args,
444- |i, obj, vm| {
445- match i {
446- 0 => qid. set ( Some ( parse_qid ( obj, vm) ?) ) ,
447- 2 => unboundarg. set ( Some ( int_arg ( obj, vm) ?) ) ,
448- 3 => fallbackarg. set ( Some ( int_arg ( obj, vm) ?) ) ,
449- _ => { }
450- }
451- Ok ( ( ) )
452- } ,
453- vm,
454- ) ?;
455- let qid = qid. get ( ) . unwrap ( ) ;
456- let obj = parsed[ 1 ] . as_deref ( ) . unwrap ( ) ;
457- let unboundarg = unboundarg. get ( ) . unwrap_or ( -1 ) ;
458- let fallbackarg = fallbackarg. get ( ) . unwrap_or ( -1 ) ;
438+ fn put ( args : PutArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
439+ let qid = parse_qid ( & args. qid , vm) ?;
440+ let unboundarg = optional_int_arg ( & args. unboundop , vm) ?;
441+ let fallbackarg = optional_int_arg ( & args. fallback , vm) ?;
459442 // The queue is only consulted when one of the arguments needs its default.
460443 let ( default_unboundop, default_fallback) = if unboundarg < 0 || fallbackarg < 0 {
461444 let ( unboundop, fallback) = queue_defaults ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
@@ -465,7 +448,7 @@ pub(crate) mod _interpqueues {
465448 } ;
466449 let unboundop = resolve_unboundop ( unboundarg, default_unboundop, vm) ?;
467450 let fallback = resolve_fallback ( fallbackarg, default_fallback, vm) ?;
468- let value = SharedValue :: from_object ( obj, fallback, vm) ?;
451+ let value = SharedValue :: from_object ( & args . obj , fallback, vm) ?;
469452 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
470453 let mut state = queue. lock ( ) ;
471454 if !state. alive {
@@ -484,8 +467,8 @@ pub(crate) mod _interpqueues {
484467 }
485468
486469 #[ pyfunction]
487- fn get ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
488- let qid = qid_arg ( & args, "get" , vm) ?;
470+ fn get ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult {
471+ let qid = parse_qid ( & args. qid , vm) ?;
489472 let item = {
490473 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
491474 let mut state = queue. lock ( ) ;
@@ -511,20 +494,20 @@ pub(crate) mod _interpqueues {
511494 }
512495
513496 #[ pyfunction]
514- fn bind ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
515- let qid = qid_arg ( & args, "bind" , vm) ?;
497+ fn bind ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
498+ let qid = parse_qid ( & args. qid , vm) ?;
516499 queue_bind ( qid) . map_err ( |err| err. into_py ( qid, vm) )
517500 }
518501
519502 #[ pyfunction]
520- fn release ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
521- let qid = qid_arg ( & args, "release" , vm) ?;
503+ fn release ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
504+ let qid = parse_qid ( & args. qid , vm) ?;
522505 queue_release ( qid) . map_err ( |err| err. into_py ( qid, vm) )
523506 }
524507
525508 #[ pyfunction]
526- fn get_maxsize ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < isize > {
527- let qid = qid_arg ( & args, "get_maxsize" , vm) ?;
509+ fn get_maxsize ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < isize > {
510+ let qid = parse_qid ( & args. qid , vm) ?;
528511 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
529512 let state = queue. lock ( ) ;
530513 if !state. alive {
@@ -534,8 +517,8 @@ pub(crate) mod _interpqueues {
534517 }
535518
536519 #[ pyfunction]
537- fn get_queue_defaults ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
538- let qid = qid_arg ( & args, "get_queue_defaults" , vm) ?;
520+ fn get_queue_defaults ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult {
521+ let qid = parse_qid ( & args. qid , vm) ?;
539522 let ( unboundop, fallback) = queue_defaults ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
540523 Ok ( vm
541524 . ctx
@@ -547,8 +530,8 @@ pub(crate) mod _interpqueues {
547530 }
548531
549532 #[ pyfunction]
550- fn is_full ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < bool > {
551- let qid = qid_arg ( & args, "is_full" , vm) ?;
533+ fn is_full ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < bool > {
534+ let qid = parse_qid ( & args. qid , vm) ?;
552535 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
553536 let state = queue. lock ( ) ;
554537 if !state. alive {
@@ -558,8 +541,8 @@ pub(crate) mod _interpqueues {
558541 }
559542
560543 #[ pyfunction]
561- fn get_count ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < usize > {
562- let qid = qid_arg ( & args, "get_count" , vm) ?;
544+ fn get_count ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < usize > {
545+ let qid = parse_qid ( & args. qid , vm) ?;
563546 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
564547 let state = queue. lock ( ) ;
565548 if !state. alive {
@@ -569,29 +552,19 @@ pub(crate) mod _interpqueues {
569552 }
570553
571554 #[ pyfunction]
572- fn _register_heap_types ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
573- let parsed = ArgSpec {
574- fname : "_register_heap_types" ,
575- keywords : & [ "queuetype" , "emptyerror" , "fullerror" ] ,
576- required : 3 ,
577- max_positional : 3 ,
578- }
579- . parse ( & args, vm) ?;
580- let queue = parsed[ 0 ]
581- . clone ( )
582- . unwrap ( )
555+ fn _register_heap_types ( args : RegisterHeapTypesArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
556+ let queue = args
557+ . queuetype
583558 . downcast :: < PyType > ( )
584559 . map_err ( |_| vm. new_type_error ( "expected a type for 'queuetype'" ) ) ?;
585- let empty = parsed[ 1 ]
586- . clone ( )
587- . unwrap ( )
560+ let empty = args
561+ . emptyerror
588562 . downcast :: < PyType > ( )
589563 . ok ( )
590564 . filter ( |ty| ty. fast_issubclass ( vm. ctx . exceptions . base_exception_type ) )
591565 . ok_or_else ( || vm. new_type_error ( "expected an exception type for 'emptyerror'" ) ) ?;
592- let full = parsed[ 2 ]
593- . clone ( )
594- . unwrap ( )
566+ let full = args
567+ . fullerror
595568 . downcast :: < PyType > ( )
596569 . ok ( )
597570 . filter ( |ty| ty. fast_issubclass ( vm. ctx . exceptions . base_exception_type ) )
0 commit comments