Skip to main content

telltale_language/ast/
message.rs

1//! Message type definitions for choreographic protocols
2
3use proc_macro2::{Ident, TokenStream};
4
5/// Message type with optional payload
6///
7/// Represents a message that can be sent between roles in a choreography.
8/// Messages have a name and an optional payload type.
9///
10/// # Examples
11///
12/// ```ignore
13/// use quote::{format_ident, quote};
14/// use telltale_runtime::MessageType;
15///
16/// // Simple message without payload
17/// let ping = MessageType {
18///     name: format_ident!("Ping"),
19///     type_annotation: None,
20///     payload: None,
21/// };
22///
23/// // Message with payload
24/// let request = MessageType {
25///     name: format_ident!("Request"),
26///     type_annotation: Some(quote! { String }),
27///     payload: Some(quote! { data }),
28/// };
29/// ```
30#[derive(Debug, Clone)]
31pub struct MessageType {
32    /// The name identifier of the message
33    pub name: Ident,
34    /// Optional type annotation for the message (e.g., `<String>`, `<i32, bool>`)
35    pub type_annotation: Option<TokenStream>,
36    /// Optional payload type (as token stream)
37    pub payload: Option<TokenStream>,
38}
39
40impl PartialEq for MessageType {
41    fn eq(&self, other: &Self) -> bool {
42        self.name == other.name
43            && self
44                .type_annotation
45                .as_ref()
46                .map(std::string::ToString::to_string)
47                == other
48                    .type_annotation
49                    .as_ref()
50                    .map(std::string::ToString::to_string)
51            && self.payload.as_ref().map(std::string::ToString::to_string)
52                == other.payload.as_ref().map(std::string::ToString::to_string)
53    }
54}
55
56impl Eq for MessageType {}
57
58impl std::hash::Hash for MessageType {
59    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
60        self.name.hash(state);
61        if let Some(ref type_annotation) = self.type_annotation {
62            type_annotation.to_string().hash(state);
63        }
64        if let Some(ref payload) = self.payload {
65            payload.to_string().hash(state);
66        }
67    }
68}
69
70impl MessageType {
71    /// Generate a Rust type identifier for this message
72    #[must_use]
73    pub fn to_ident(&self) -> Ident {
74        self.name.clone()
75    }
76}