Skip to main content

synwire_core/messages/
traits.rs

1//! Trait for types convertible to a [`Message`].
2
3use crate::messages::Message;
4
5/// Trait for types that can be converted to a [`Message`].
6///
7/// This provides a uniform interface for accepting various types as messages,
8/// such as raw strings, tuples of (role, content), or `Message` values directly.
9///
10/// # Examples
11///
12/// ```
13/// use synwire_core::messages::{Message, MessageLike};
14///
15/// let msg: Message = "Hello".to_message();
16/// assert_eq!(msg.message_type(), "human");
17///
18/// let msg: Message = ("ai", "Hi there").to_message();
19/// assert_eq!(msg.message_type(), "ai");
20/// ```
21pub trait MessageLike {
22    /// Convert to a [`Message`].
23    fn to_message(&self) -> Message;
24}
25
26impl MessageLike for Message {
27    fn to_message(&self) -> Message {
28        self.clone()
29    }
30}
31
32impl MessageLike for &str {
33    fn to_message(&self) -> Message {
34        Message::human(*self)
35    }
36}
37
38impl MessageLike for String {
39    fn to_message(&self) -> Message {
40        Message::human(self)
41    }
42}
43
44impl MessageLike for (&str, &str) {
45    /// First element is role (`"human"`, `"user"`, `"ai"`, `"assistant"`, `"system"`),
46    /// second is content. Unrecognised roles default to human.
47    fn to_message(&self) -> Message {
48        match self.0 {
49            "ai" | "assistant" => Message::ai(self.1),
50            "system" => Message::system(self.1),
51            // "human", "user", or any unrecognised role defaults to human.
52            _ => Message::human(self.1),
53        }
54    }
55}
56
57#[cfg(test)]
58#[allow(clippy::unwrap_used)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_message_like_from_str() {
64        let msg = "Hello".to_message();
65        assert_eq!(msg.message_type(), "human");
66        assert_eq!(msg.content().as_text(), "Hello");
67    }
68
69    #[test]
70    fn test_message_like_from_string() {
71        let s = String::from("Hello");
72        let msg = s.to_message();
73        assert_eq!(msg.message_type(), "human");
74    }
75
76    #[test]
77    fn test_message_like_from_message() {
78        let original = Message::ai("Hi");
79        let msg = original.to_message();
80        assert_eq!(msg.message_type(), "ai");
81    }
82
83    #[test]
84    fn test_message_like_from_tuple_human() {
85        let msg = ("human", "Hello").to_message();
86        assert_eq!(msg.message_type(), "human");
87    }
88
89    #[test]
90    fn test_message_like_from_tuple_user() {
91        let msg = ("user", "Hello").to_message();
92        assert_eq!(msg.message_type(), "human");
93    }
94
95    #[test]
96    fn test_message_like_from_tuple_ai() {
97        let msg = ("ai", "Hi").to_message();
98        assert_eq!(msg.message_type(), "ai");
99    }
100
101    #[test]
102    fn test_message_like_from_tuple_assistant() {
103        let msg = ("assistant", "Hi").to_message();
104        assert_eq!(msg.message_type(), "ai");
105    }
106
107    #[test]
108    fn test_message_like_from_tuple_system() {
109        let msg = ("system", "Be helpful").to_message();
110        assert_eq!(msg.message_type(), "system");
111    }
112
113    #[test]
114    fn test_message_like_from_tuple_unknown_defaults_to_human() {
115        let msg = ("unknown_role", "Hello").to_message();
116        assert_eq!(msg.message_type(), "human");
117    }
118}