elicitation 0.8.0

Conversational elicitation of strongly-typed Rust values via MCP
Documentation
//! Integer type implementations using generic macros.

use crate::{
    ElicitCommunicator, ElicitIntrospect, ElicitResult, Elicitation, ElicitationPattern,
    PatternDetails, Prompt, TypeMetadata,
};

/// Macro to implement Elicitation for integer types using Default wrappers.
///
/// This macro generates Elicitation implementations that delegate to
/// the corresponding Default wrapper type (e.g., i8 -> I8Default).
macro_rules! impl_integer_elicit_via_wrapper {
    ($primitive:ty, $wrapper:ident, $style:ident) => {
        crate::default_style!($primitive => $style);

        impl Prompt for $primitive {
            fn prompt() -> Option<&'static str> {
                Some(concat!(
                    "Please enter a ",
                    stringify!($primitive),
                    " (between ",
                    stringify!(<$primitive>::MIN),
                    " and ",
                    stringify!(<$primitive>::MAX),
                    "):"
                ))
            }
        }

        impl Elicitation for $primitive {
            type Style = $style;

            #[tracing::instrument(skip(communicator), fields(type_name = stringify!($primitive)))]
            async fn elicit<C: ElicitCommunicator>(communicator: &C) -> ElicitResult<Self> {
                use crate::verification::types::$wrapper;

                tracing::debug!(concat!("Eliciting ", stringify!($primitive), " via ", stringify!($wrapper), " wrapper"));

                // Use verification wrapper internally
                let wrapper = $wrapper::elicit(communicator).await?;

                // Unwrap to primitive
                Ok(wrapper.into_inner())
            }
        }

        impl ElicitIntrospect for $primitive {
            fn pattern() -> ElicitationPattern {
                ElicitationPattern::Primitive
            }

            fn metadata() -> TypeMetadata {
                TypeMetadata {
                    type_name: stringify!($primitive),
                    description: <Self as Prompt>::prompt(),
                    details: PatternDetails::Primitive,
                }
            }
        }
    };
}

// Apply macro to all signed integer types
impl_integer_elicit_via_wrapper!(i8, I8Default, I8Style);
impl_integer_elicit_via_wrapper!(i16, I16Default, I16Style);
impl_integer_elicit_via_wrapper!(i32, I32Default, I32Style);
// i64 implementation below (already uses I64Default)
impl_integer_elicit_via_wrapper!(i128, I128Default, I128Style);
impl_integer_elicit_via_wrapper!(isize, IsizeDefault, IsizeStyle);

// i64 implementation using I64Default verification wrapper
crate::default_style!(i64 => I64Style);

impl Prompt for i64 {
    fn prompt() -> Option<&'static str> {
        Some("Please enter a i64 (between -9223372036854775808 and 9223372036854775807):")
    }
}

impl Elicitation for i64 {
    type Style = I64Style;

    #[tracing::instrument(skip(communicator), fields(type_name = "i64"))]
    async fn elicit<C: ElicitCommunicator>(communicator: &C) -> ElicitResult<Self> {
        use crate::verification::types::I64Default;

        tracing::debug!("Eliciting i64 via I64Default wrapper");

        // Use verification wrapper internally
        let wrapper = I64Default::elicit(communicator).await?;

        // Unwrap to primitive
        Ok(wrapper.into_inner())
    }
}

impl ElicitIntrospect for i64 {
    fn pattern() -> ElicitationPattern {
        ElicitationPattern::Primitive
    }

    fn metadata() -> TypeMetadata {
        TypeMetadata {
            type_name: "i64",
            description: Self::prompt(),
            details: PatternDetails::Primitive,
        }
    }
}

// Apply macro to all unsigned integer types
impl_integer_elicit_via_wrapper!(u8, U8Default, U8Style);
impl_integer_elicit_via_wrapper!(u16, U16Default, U16Style);
impl_integer_elicit_via_wrapper!(u32, U32Default, U32Style);
impl_integer_elicit_via_wrapper!(u64, U64Default, U64Style);
impl_integer_elicit_via_wrapper!(u128, U128Default, U128Style);
impl_integer_elicit_via_wrapper!(usize, UsizeDefault, UsizeStyle);