Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ec89736

Browse files
committedJul 19, 2024
replace proc macros with matching macros use macro_metavar_expr feature
1 parent 3e9e373 commit ec89736

File tree

2 files changed

+56
-51
lines changed

2 files changed

+56
-51
lines changed
 

‎Cargo.toml

+1-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
[package]
22
name = "zips"
33
description = "macro for zipping more than just 2 instances of Option<T>"
4-
version = "0.1.1"
4+
version = "0.1.2"
55
edition = "2021"
66
author = "Carter Canedy"
77
email = "cartercanedy42@gmail.com"
88
repository = "https://github.com/cartercanedy/zips"
99
license = "MIT"
1010
license-file="LICENSE.txt"
11-
12-
[lib]
13-
proc-macro = true
14-
15-
[dependencies]
16-
syn = { version = "2.0.71", default-features = false, features = ["parsing", "derive", "proc-macro", "printing"] }
17-
quote = "1.0.36"
18-
proc-macro2 = "1.0.86"

‎src/lib.rs

+55-42
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,68 @@
11
// Copyright (c) 2024 Carter Canedy <cartercanedy42@gmail.com>
22

3-
use {
4-
proc_macro::TokenStream,
5-
syn::{parse_macro_input, Expr, Token},
6-
syn::parse::{Parse, ParseStream},
7-
syn::punctuated::Punctuated,
8-
quote::quote,
9-
};
3+
#![feature(macro_metavar_expr)]
104

11-
struct ZipArgs {
12-
args: Punctuated<Expr, Token![,]>
13-
}
5+
/// Zips multiple instances of Option<T> into a single instance of Option<(T [, T...])>. Will
6+
/// either be Some if all arguments are some, or None if one of the instances is None.
7+
///
8+
/// ## Usage:
9+
/// ```
10+
/// let zipped_some = zip!(Some(1), Some(2));
11+
/// assert_eq!(zipped_some, Some((1, 2)));
12+
///
13+
/// let zipped_none = zip!(Some(1), None);
14+
/// assert_eq!(zipped_none, None);
15+
/// ```
16+
#[macro_export]
17+
macro_rules! zip {
18+
($($args:expr),+) => ({
19+
let mut ok = true;
20+
$(
21+
let arg${index()} = $args;
22+
if arg${index()}.is_none() {
23+
ok = false;
24+
}
25+
)+
1426

15-
impl Parse for ZipArgs {
16-
fn parse(input: ParseStream) -> syn::Result<Self> {
17-
Ok(Self {
18-
args: Punctuated::<Expr, Token![,]>::parse_terminated(input)?
19-
})
20-
}
27+
if ok {
28+
Some(($(arg${index()}.unwrap(),)+))
29+
} else {
30+
None
31+
}
32+
});
2133
}
2234

23-
/// Expands into a single `Option<(T [, T...])>::Some((...))` instance if all arguments
24-
/// are instances of `Option<T>::Some(T)`, else expands to `Option<(T [, T...])>::None`
35+
/// Zips an arbitrary number of `Result<T>` into a single instance of `Option<(T [, T...])>`. If
36+
/// any arguments are `Err`, `None` is returned. Otherwise, `Some` is returned.
2537
///
26-
/// Usage:
38+
/// ## Usage:
2739
/// ```
28-
/// use zips::zip;
40+
/// let i: Result<i32, String> = Ok(1);
41+
/// let j: Result<usize, String> = Ok(0usize);
42+
/// let k: Result<usize, String> = Err("I'm an error");
43+
///
44+
/// // zipped_ok: Option<(i32, usize)>
45+
/// let zipped_ok = zip_result!(i, j);
46+
/// assert_eq!(zipped_ok, Some(1, 0usize));
2947
///
30-
/// fn main() -> () {
31-
/// let zipped = zip!(Some(0), Some(1));
32-
/// assert_eq!(zipped, Some(0, 1));
33-
/// }
48+
/// // zipped_err: Option<(i32, usize, usize)>
49+
/// let zipped_err = zip_result!(i, j, k);
50+
/// assert_eq!(zipped_err, None);
3451
/// ```
35-
#[proc_macro]
36-
pub fn zip(input: TokenStream) -> TokenStream {
37-
let ZipArgs { args } = parse_macro_input!(input as ZipArgs);
38-
let arg_names: Vec<_> =
39-
(0..args.len())
40-
.map(|i| syn::Ident::new(&format!("arg{i}"), proc_macro2::Span::call_site()))
41-
.collect();
42-
43-
let args = args.into_iter();
44-
45-
quote! {
46-
{
47-
#(let #arg_names = #args;)*
48-
if #(#arg_names.is_some() &&)* true {
49-
Some((#(#arg_names.unwrap()),*))
50-
} else {
51-
None
52+
#[macro_export]
53+
macro_rules! zip_result {
54+
($($args:expr),+) => ({
55+
let mut ok = true;
56+
$(
57+
if $args.is_err() {
58+
ok = false;
5259
}
60+
)+
61+
62+
if ok {
63+
Some(($($args.ok().unwrap(),)+))
64+
} else {
65+
None
5366
}
54-
}.into()
67+
});
5568
}

0 commit comments

Comments
 (0)
Please sign in to comment.