Dispatch based on array enum type

Currently I have the following:

fn make_fields(items: &[Item]) -> syn::Fields {
    if items.iter().any(|item| matches!(item, Item::Named(_))) {
        syn::Fields::Named(make_named_fields(items))
    } else {
        syn::Fields::Unnamed(make_unnamed_fields(items.iter().map(|item| match item {
            Item::Unnamed(item) => item,
            Item::Named(_) => unreachable!(),
        })))
    }
}

It feels like there should be a better solution that doesn't need the unreachable!. But I'm not sure if the "Err on first that fails a mapping" then "unify Ok and Err by two different maps" operation is available and better (I couldn't find one, anyway).

Full context: this could probably be done with a fold.

fn make_fields(items: &[Item]) -> syn::Fields {
    if items.iter().any(|item| matches!(item, Item::Named(_))) {
        syn::Fields::Named(make_named_fields(items.iter()))
    } else {
        syn::Fields::Unnamed(make_unnamed_fields(items.iter().map(|item| match item {
            Item::Unnamed(item) => item,
            Item::Named(_) => unreachable!(),
        })))
    }
}

fn make_named_fields<'a>(items: impl Iterator<Item = &'a Item>) -> syn::FieldsNamed {
    syn::FieldsNamed {
        brace_token: Default::default(),
        named: items
            .map(|item| match item {
                Item::Named(item) => syn::Field {
                    attrs: vec![],
                    vis: parse_quote!(pub),
                    ident: Some(item.name.clone()),
                    colon_token: Some(Default::default()),
                    ty: make_type(&item.item),
                },
                Item::Unnamed(item) => syn::Field {
                    attrs: vec![],
                    vis: syn::Visibility::Inherited,
                    ident: Some(new_uuidv4_ident()),
                    colon_token: Some(Default::default()),
                    ty: make_type(item),
                },
            })
            .collect(),
    }
}

fn make_unnamed_fields<'a>(items: impl Iterator<Item = &'a UnnamedItem>) -> syn::FieldsUnnamed {
    syn::FieldsUnnamed {
        paren_token: Default::default(),
        unnamed: items
            .map(|item| syn::Field {
                attrs: vec![],
                vis: parse_quote!(pub),
                ident: None,
                colon_token: None,
                ty: make_type(item),
            })
            .collect(),
    }
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.