Function magnus::scan_args::scan_args

source ·
pub fn scan_args<Req, Opt, Splat, Trail, Kw, Block>(
    args: &[Value]
) -> Result<Args<Req, Opt, Splat, Trail, Kw, Block>, Error>where
    Req: ScanArgsRequired,
    Opt: ScanArgsOpt,
    Splat: ScanArgsSplat,
    Trail: ScanArgsRequired,
    Kw: ScanArgsKw,
    Block: ScanArgsBlock,
Expand description

Retrieves arguments from a slice.

This function can be used to implement Ruby methods with more complex signatures, including optional arguments and ‘splats’.

The format of the arguments required is driven by the types in the return value. The stuct Args is returned but the types of its fields are determined by type parameters. The type () is used as a placeholder when a set of arguments is not required.

Examples

TCPServer::new’s argument handling. This is roughly equivalent to def new(hostname=nil, port).

use magnus::{define_class, error::Error, function, scan_args::scan_args, Object, Value};

fn tcp_svr_init(args: &[Value]) -> Result<Value, Error> {
    let args = scan_args(args)?;
    let _: () = args.required;
    let (hostname,): (Option<String>,) = args.optional;
    let _: () = args.splat;
    let (port,): (u16,) = args.trailing;
    let _: () = args.keywords;
    let _: () = args.block;

    // ...
}

let class = define_class("TCPServer", Default::default()).unwrap();
class.define_singleton_method("new", function!(tcp_svr_init, -1)).unwrap();

The same example as above, specifying the types slightly differently.

use magnus::{define_class, error::Error, function, scan_args::scan_args, Object, Value};

fn tcp_svr_init(args: &[Value]) -> Result<Value, Error> {
    let args = scan_args::<(), (Option<String>,), (), (u16,), (), ()>(args)?;
    let (hostname,) = args.optional;
    let (port,) = args.trailing;

    // ...
}

let class = define_class("TCPServer", Default::default()).unwrap();
class.define_singleton_method("new", function!(tcp_svr_init, -1)).unwrap();

Addrinfo::getaddrinfo’s argument handling. This is roughly equivalent to def getaddrinfo(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, timeout: nil).

use magnus::{
    define_class, error::Error, function, scan_args::{scan_args, get_kwargs}, Object, RHash, Symbol, Value,
};

fn getaddrinfo(args: &[Value]) -> Result<Value, Error> {
    let args = scan_args::<_, _, (), (), _, ()>(args)?;
    let (nodename, service): (String, u16) = args.required;
    let (family, socktype, protocol, flags): (
        Option<Symbol>,
        Option<Symbol>,
        Option<i64>,
        Option<i64>,
    ) = args.optional;
    let kw = get_kwargs::<_, (), (Option<usize>,), ()>(args.keywords, &[], &["timeout"])?;
    let (timeout,) = kw.optional;

    // ...
}

let class = define_class("Addrinfo", Default::default()).unwrap();
class.define_singleton_method("getaddrinfo", function!(getaddrinfo, -1)).unwrap();