rusty_typesh/
lib.rs

1//! Type pattern matching system for Rust.
2//! 
3//! This crate provides a flexible type pattern matching system that allows:
4//! - Runtime type checking and matching
5//! - Pattern matching with custom handlers
6//! - Both macro-based and manual matching approaches
7//! 
8//! # Examples
9//! ```
10//! use rusty_typesh::type_match;
11//! 
12//! let value = 42i32;
13//! let result = type_match!(
14//!     value,
15//!     i32 => |x: &i32| format!("Got integer: {}", x),
16//!     String => |x: &String| format!("Got string: {}", x)
17//! );
18//! assert_eq!(result, Some("Got integer: 42".to_string()));
19//! ```
20
21mod macros;
22
23use std::any::TypeId;
24
25/// A trait for implementing type pattern matching behavior.
26/// 
27/// This trait is used to define how types should be matched against patterns.
28/// Implementors must provide a `matches()` method that determines if a type
29/// matches the pattern.
30pub trait TypePattern<T: 'static> {
31    /// Returns true if the type matches this pattern
32    fn matches(&self) -> bool;
33}
34
35/// A concrete type matcher implementation.
36/// 
37/// TypeMatcher provides runtime type checking capabilities by storing
38/// and comparing TypeIds.
39/// 
40/// # Type Parameters
41/// * `U` - The type to match against
42pub struct TypeMatcher<U: 'static> {
43    /// The TypeId of the type to match
44    type_id: TypeId,
45    /// PhantomData to handle the generic type parameter
46    _phantom: std::marker::PhantomData<U>,
47}
48
49impl<U: 'static> TypeMatcher<U> {
50    /// Creates a new TypeMatcher for the given type.
51    /// 
52    /// # Examples
53    /// ```
54    /// use rusty_typesh::TypeMatcher;
55    /// let matcher = TypeMatcher::<i32>::new();
56    /// ```
57    pub fn new() -> Self {
58        Self {
59            type_id: TypeId::of::<U>(),
60            _phantom: std::marker::PhantomData,
61        }
62    }
63}
64
65impl<T: 'static, U: 'static> TypePattern<T> for TypeMatcher<U> {
66    fn matches(&self) -> bool {
67        TypeId::of::<T>() == self.type_id
68    }
69}
70
71/// Matches a value against a series of type patterns and handlers.
72/// 
73/// # Type Parameters
74/// * `T` - The type of the value to match
75/// * `R` - The return type of the pattern handlers
76/// 
77/// # Arguments
78/// * `value` - The value to match against patterns
79/// * `patterns` - A slice of tuples containing patterns and their handlers
80/// 
81/// # Returns
82/// * `Some(R)` if a pattern matches and its handler succeeds
83/// * `None` if no pattern matches
84pub fn match_type<T: 'static, R>(
85    value: &T,
86    patterns: &[(Box<dyn TypePattern<T>>, Box<dyn Fn(&T) -> R>)],
87) -> Option<R> {
88    for (pattern, handler) in patterns {
89        if pattern.matches() {
90            return Some(handler(value));
91        }
92    }
93    None
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    #[test]
101    fn test_basic_type_matching() {
102        let value = 42i32;
103        let patterns = vec![
104            (
105                Box::new(TypeMatcher::<i32>::new()) as Box<dyn TypePattern<i32>>,
106                Box::new(|x: &i32| format!("Integer: {}", x)) as Box<dyn Fn(&i32) -> String>,
107            ),
108            (
109                Box::new(TypeMatcher::<i32>::new()) as Box<dyn TypePattern<i32>>,
110                Box::new(|x: &i32| format!("String length: {}", x.to_string().len())) as Box<dyn Fn(&i32) -> String>,
111            ),
112        ];
113
114        let result = match_type(&value, &patterns);
115        assert_eq!(result, Some("Integer: 42".to_string()));
116    }
117}