@@ -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 ;
@@ -337,23 +336,11 @@ pub(crate) mod _interpqueues {
337336 Err ( vm. new_overflow_error ( format ! ( "max queue ID is {}, got {repr}" , i64 :: MAX ) ) )
338337 }
339338
340- fn qid_arg ( args : & FuncArgs , func : & ' static str , vm : & VirtualMachine ) -> PyResult < i64 > {
341- let qid = Cell :: new ( None ) ;
342- ArgSpec {
343- fname : func,
344- keywords : & [ "qid" ] ,
345- required : 1 ,
346- max_positional : 1 ,
339+ fn optional_int_arg ( arg : & OptionalArg < PyObjectRef > , vm : & VirtualMachine ) -> PyResult < i32 > {
340+ match arg {
341+ OptionalArg :: Present ( obj) => int_arg ( obj, vm) ,
342+ OptionalArg :: Missing => Ok ( -1 ) ,
347343 }
348- . parse_with (
349- args,
350- |_, obj, vm| {
351- qid. set ( Some ( parse_qid ( obj, vm) ?) ) ;
352- Ok ( ( ) )
353- } ,
354- vm,
355- ) ?;
356- Ok ( qid. get ( ) . unwrap ( ) )
357344 }
358345
359346 #[ expect( clippy:: unnecessary_wraps, reason = "Needs to comply with a signature" ) ]
@@ -363,39 +350,58 @@ pub(crate) mod _interpqueues {
363350 Ok ( ( ) )
364351 }
365352
353+ // Keep the original inputs alive while applying the queue-specific converters.
354+ #[ derive( FromArgs ) ]
355+ struct QueueIdArgs {
356+ #[ pyarg( any) ]
357+ qid : PyObjectRef ,
358+ }
359+
360+ #[ derive( FromArgs ) ]
361+ struct CreateArgs {
362+ #[ pyarg( any) ]
363+ maxsize : PyObjectRef ,
364+ #[ pyarg( any, optional, py_default = "-1" ) ]
365+ unboundop : OptionalArg < PyObjectRef > ,
366+ #[ pyarg( any, optional, py_default = "-1" ) ]
367+ fallback : OptionalArg < PyObjectRef > ,
368+ }
369+
370+ #[ derive( FromArgs ) ]
371+ struct PutArgs {
372+ #[ pyarg( any) ]
373+ qid : PyObjectRef ,
374+ #[ pyarg( any) ]
375+ obj : PyObjectRef ,
376+ #[ pyarg( any, optional, py_default = "-1" ) ]
377+ unboundop : OptionalArg < PyObjectRef > ,
378+ #[ pyarg( any, optional, py_default = "-1" ) ]
379+ fallback : OptionalArg < PyObjectRef > ,
380+ }
381+
382+ #[ derive( FromArgs ) ]
383+ struct RegisterHeapTypesArgs {
384+ #[ pyarg( any) ]
385+ queuetype : PyObjectRef ,
386+ #[ pyarg( any) ]
387+ emptyerror : PyObjectRef ,
388+ #[ pyarg( any) ]
389+ fullerror : PyObjectRef ,
390+ }
391+
366392 #[ pyfunction]
367- fn create ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < i64 > {
368- let maxsize = Cell :: new ( None ) ;
369- let unboundarg = Cell :: new ( None ) ;
370- let fallbackarg = Cell :: new ( None ) ;
371- ArgSpec {
372- fname : "create" ,
373- keywords : & [ "maxsize" , "unboundop" , "fallback" ] ,
374- required : 1 ,
375- max_positional : 3 ,
376- }
377- . parse_with (
378- & args,
379- |i, obj, vm| {
380- match i {
381- 0 => maxsize. set ( Some ( ssize_arg ( obj, vm) ?) ) ,
382- 1 => unboundarg. set ( Some ( int_arg ( obj, vm) ?) ) ,
383- 2 => fallbackarg. set ( Some ( int_arg ( obj, vm) ?) ) ,
384- _ => unreachable ! ( ) ,
385- }
386- Ok ( ( ) )
387- } ,
388- vm,
389- ) ?;
390- let unboundop = resolve_unboundop ( unboundarg. get ( ) . unwrap_or ( -1 ) , UnboundOp :: Replace , vm) ?;
391- let fallback =
392- resolve_fallback ( fallbackarg. get ( ) . unwrap_or ( -1 ) , Fallback :: Full . as_i32 ( ) , vm) ?;
393- queue_create ( maxsize. get ( ) . unwrap ( ) , unboundop, fallback) . map_err ( |err| err. into_py ( -1 , vm) )
393+ fn create ( args : CreateArgs , vm : & VirtualMachine ) -> PyResult < i64 > {
394+ let maxsize = ssize_arg ( & args. maxsize , vm) ?;
395+ let unboundarg = optional_int_arg ( & args. unboundop , vm) ?;
396+ let fallbackarg = optional_int_arg ( & args. fallback , vm) ?;
397+ let unboundop = resolve_unboundop ( unboundarg, UnboundOp :: Replace , vm) ?;
398+ let fallback = resolve_fallback ( fallbackarg, Fallback :: Full . as_i32 ( ) , vm) ?;
399+ queue_create ( maxsize, unboundop, fallback) . map_err ( |err| err. into_py ( -1 , vm) )
394400 }
395401
396402 #[ pyfunction]
397- fn destroy ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
398- let qid = qid_arg ( & args, "destroy" , vm) ?;
403+ fn destroy ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
404+ let qid = parse_qid ( & args. qid , vm) ?;
399405 queue_destroy ( qid) . map_err ( |err| err. into_py ( qid, vm) )
400406 }
401407
@@ -427,33 +433,10 @@ pub(crate) mod _interpqueues {
427433 }
428434
429435 #[ pyfunction]
430- fn put ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
431- let qid = Cell :: new ( None ) ;
432- let unboundarg = Cell :: new ( None ) ;
433- let fallbackarg = Cell :: new ( None ) ;
434- let parsed = ArgSpec {
435- fname : "put" ,
436- keywords : & [ "qid" , "obj" , "unboundop" , "fallback" ] ,
437- required : 2 ,
438- max_positional : 4 ,
439- }
440- . parse_with (
441- & args,
442- |i, obj, vm| {
443- match i {
444- 0 => qid. set ( Some ( parse_qid ( obj, vm) ?) ) ,
445- 2 => unboundarg. set ( Some ( int_arg ( obj, vm) ?) ) ,
446- 3 => fallbackarg. set ( Some ( int_arg ( obj, vm) ?) ) ,
447- _ => { }
448- }
449- Ok ( ( ) )
450- } ,
451- vm,
452- ) ?;
453- let qid = qid. get ( ) . unwrap ( ) ;
454- let obj = parsed[ 1 ] . as_deref ( ) . unwrap ( ) ;
455- let unboundarg = unboundarg. get ( ) . unwrap_or ( -1 ) ;
456- let fallbackarg = fallbackarg. get ( ) . unwrap_or ( -1 ) ;
436+ fn put ( args : PutArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
437+ let qid = parse_qid ( & args. qid , vm) ?;
438+ let unboundarg = optional_int_arg ( & args. unboundop , vm) ?;
439+ let fallbackarg = optional_int_arg ( & args. fallback , vm) ?;
457440 // The queue is only consulted when one of the arguments needs its default.
458441 let ( default_unboundop, default_fallback) = if unboundarg < 0 || fallbackarg < 0 {
459442 let ( unboundop, fallback) = queue_defaults ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
@@ -463,7 +446,7 @@ pub(crate) mod _interpqueues {
463446 } ;
464447 let unboundop = resolve_unboundop ( unboundarg, default_unboundop, vm) ?;
465448 let fallback = resolve_fallback ( fallbackarg, default_fallback, vm) ?;
466- let value = SharedValue :: from_object ( obj, fallback, vm) ?;
449+ let value = SharedValue :: from_object ( & args . obj , fallback, vm) ?;
467450 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
468451 let mut state = queue. lock ( ) ;
469452 if !state. alive {
@@ -482,8 +465,8 @@ pub(crate) mod _interpqueues {
482465 }
483466
484467 #[ pyfunction]
485- fn get ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
486- let qid = qid_arg ( & args, "get" , vm) ?;
468+ fn get ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult {
469+ let qid = parse_qid ( & args. qid , vm) ?;
487470 let item = {
488471 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
489472 let mut state = queue. lock ( ) ;
@@ -509,20 +492,20 @@ pub(crate) mod _interpqueues {
509492 }
510493
511494 #[ pyfunction]
512- fn bind ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
513- let qid = qid_arg ( & args, "bind" , vm) ?;
495+ fn bind ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
496+ let qid = parse_qid ( & args. qid , vm) ?;
514497 queue_bind ( qid) . map_err ( |err| err. into_py ( qid, vm) )
515498 }
516499
517500 #[ pyfunction]
518- fn release ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
519- let qid = qid_arg ( & args, "release" , vm) ?;
501+ fn release ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
502+ let qid = parse_qid ( & args. qid , vm) ?;
520503 queue_release ( qid) . map_err ( |err| err. into_py ( qid, vm) )
521504 }
522505
523506 #[ pyfunction]
524- fn get_maxsize ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < isize > {
525- let qid = qid_arg ( & args, "get_maxsize" , vm) ?;
507+ fn get_maxsize ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < isize > {
508+ let qid = parse_qid ( & args. qid , vm) ?;
526509 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
527510 let state = queue. lock ( ) ;
528511 if !state. alive {
@@ -532,8 +515,8 @@ pub(crate) mod _interpqueues {
532515 }
533516
534517 #[ pyfunction]
535- fn get_queue_defaults ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
536- let qid = qid_arg ( & args, "get_queue_defaults" , vm) ?;
518+ fn get_queue_defaults ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult {
519+ let qid = parse_qid ( & args. qid , vm) ?;
537520 let ( unboundop, fallback) = queue_defaults ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
538521 Ok ( vm
539522 . ctx
@@ -545,8 +528,8 @@ pub(crate) mod _interpqueues {
545528 }
546529
547530 #[ pyfunction]
548- fn is_full ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < bool > {
549- let qid = qid_arg ( & args, "is_full" , vm) ?;
531+ fn is_full ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < bool > {
532+ let qid = parse_qid ( & args. qid , vm) ?;
550533 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
551534 let state = queue. lock ( ) ;
552535 if !state. alive {
@@ -556,8 +539,8 @@ pub(crate) mod _interpqueues {
556539 }
557540
558541 #[ pyfunction]
559- fn get_count ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < usize > {
560- let qid = qid_arg ( & args, "get_count" , vm) ?;
542+ fn get_count ( args : QueueIdArgs , vm : & VirtualMachine ) -> PyResult < usize > {
543+ let qid = parse_qid ( & args. qid , vm) ?;
561544 let queue = queue_lookup ( qid) . map_err ( |err| err. into_py ( qid, vm) ) ?;
562545 let state = queue. lock ( ) ;
563546 if !state. alive {
@@ -567,29 +550,19 @@ pub(crate) mod _interpqueues {
567550 }
568551
569552 #[ pyfunction]
570- fn _register_heap_types ( args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
571- let parsed = ArgSpec {
572- fname : "_register_heap_types" ,
573- keywords : & [ "queuetype" , "emptyerror" , "fullerror" ] ,
574- required : 3 ,
575- max_positional : 3 ,
576- }
577- . parse ( & args, vm) ?;
578- let queue = parsed[ 0 ]
579- . clone ( )
580- . unwrap ( )
553+ fn _register_heap_types ( args : RegisterHeapTypesArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
554+ let queue = args
555+ . queuetype
581556 . downcast :: < PyType > ( )
582557 . map_err ( |_| vm. new_type_error ( "expected a type for 'queuetype'" ) ) ?;
583- let empty = parsed[ 1 ]
584- . clone ( )
585- . unwrap ( )
558+ let empty = args
559+ . emptyerror
586560 . downcast :: < PyType > ( )
587561 . ok ( )
588562 . filter ( |ty| ty. fast_issubclass ( vm. ctx . exceptions . base_exception_type ) )
589563 . ok_or_else ( || vm. new_type_error ( "expected an exception type for 'emptyerror'" ) ) ?;
590- let full = parsed[ 2 ]
591- . clone ( )
592- . unwrap ( )
564+ let full = args
565+ . fullerror
593566 . downcast :: < PyType > ( )
594567 . ok ( )
595568 . filter ( |ty| ty. fast_issubclass ( vm. ctx . exceptions . base_exception_type ) )
0 commit comments