getargs-derive-macros 0.1.0

Internal implementation detail of getargs-derive. Not meant for direct use; depend on getargs-derive instead.
Documentation
use super::RawContainer;
use crate::model::attr::{expected, parse_list, parse_string, reject_value, set_once};
use crate::model::field::Alias;
use proc_macro2::Span;
use syn::{Lit, meta::ParseNestedMeta};

pub(crate) fn validate_command_name(key: &str, name: &str, span: Span) -> syn::Result<()> {
    if name.is_empty() {
        return Err(syn::Error::new(span, format!("`{key}` cannot be empty")));
    }
    if name.starts_with('-') {
        return Err(syn::Error::new(
            span,
            format!("`{key}` cannot start with `-`, because it would be read as an option"),
        ));
    }
    if name.contains(char::is_whitespace) {
        return Err(syn::Error::new(
            span,
            format!("`{key}` cannot contain whitespace"),
        ));
    }
    Ok(())
}

fn to_alias(literal: Lit, key: &str, example: &str, visible: bool) -> syn::Result<Alias<String>> {
    match literal {
        Lit::Str(literal) => {
            let name = literal.value();
            validate_command_name(key, &name, literal.span())?;
            Ok(Alias {
                name,
                visible,
                span: literal.span(),
            })
        }
        other => Err(syn::Error::new(
            other.span(),
            expected(key, "string", example),
        )),
    }
}

fn single(
    meta: &ParseNestedMeta,
    raw: &mut RawContainer,
    key: &str,
    visible: bool,
) -> syn::Result<()> {
    let example = format!("{key} = \"name\"");
    let literal = parse_string(meta, key, &example)?;
    let alias = to_alias(Lit::Str(literal), key, &example, visible)?;
    raw.aliases.push(alias);
    Ok(())
}

fn multiple(
    meta: &ParseNestedMeta,
    raw: &mut RawContainer,
    key: &str,
    visible: bool,
) -> syn::Result<()> {
    let example = format!("{key} = [\"first\", \"second\"]");
    for literal in parse_list(meta, key, "string", &example)? {
        let alias = to_alias(literal, key, &example, visible)?;
        raw.aliases.push(alias);
    }
    Ok(())
}

pub(super) fn alias(meta: &ParseNestedMeta, raw: &mut RawContainer) -> syn::Result<()> {
    single(meta, raw, "alias", false)
}

pub(super) fn aliases(meta: &ParseNestedMeta, raw: &mut RawContainer) -> syn::Result<()> {
    multiple(meta, raw, "aliases", false)
}

pub(super) fn visible_alias(meta: &ParseNestedMeta, raw: &mut RawContainer) -> syn::Result<()> {
    single(meta, raw, "visible_alias", true)
}

pub(super) fn visible_aliases(meta: &ParseNestedMeta, raw: &mut RawContainer) -> syn::Result<()> {
    multiple(meta, raw, "visible_aliases", true)
}

pub(super) fn hide(meta: &ParseNestedMeta, raw: &mut RawContainer) -> syn::Result<()> {
    reject_value(meta, "hide")?;
    set_once(&mut raw.hide, (), meta)
}