Skip to main content

sl_chat_log_parser/
avatar_messages.rs

1//! Avatar related messages (those sent by an avatar as well as some system messages about an avatar like coming online or entering chat range)
2
3use chumsky::IterParser as _;
4use chumsky::Parser;
5use chumsky::prelude::{any, choice, just};
6
7/// represents a Second Life avatar related message
8#[derive(Debug, Clone, PartialEq)]
9pub enum AvatarMessage {
10    /// a message about the avatar whispering, saying or shouting something
11    Chat {
12        /// how "loud" the message was (whisper, say, shout or region say)
13        volume: sl_types::chat::ChatVolume,
14        /// the chat message
15        message: String,
16    },
17    /// an emote (chat message starting with /me in the log)
18    Emote {
19        /// how "loud" the message was (whisper, say, shout or region say)
20        volume: sl_types::chat::ChatVolume,
21        /// the chat message without the /me
22        message: String,
23    },
24    /// a message about an avatar coming online
25    CameOnline,
26    /// a message about an avatar going offline
27    WentOffline,
28    /// a message about an avatar entering an area of significance
29    EnteredArea {
30        /// the area of significance
31        area: sl_types::radar::Area,
32        /// the distance where the avatar entered the area
33        distance: Option<sl_types::map::Distance>,
34    },
35    /// a message about an avatar leaving an area of significance
36    LeftArea {
37        /// the area of significance
38        area: sl_types::radar::Area,
39    },
40}
41
42/// parse a Second Life avatar chat message
43///
44/// # Errors
45///
46/// returns an error if the parser fails
47fn avatar_chat_message_parser<'src>()
48-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
49{
50    any()
51        .repeated()
52        .collect::<String>()
53        .try_map(|s, _span: chumsky::span::SimpleSpan| {
54            let (v, s) = sl_types::chat::ChatVolume::volume_and_message(s.to_string());
55            Ok(AvatarMessage::Chat {
56                volume: v,
57                message: s,
58            })
59        })
60}
61
62/// parse a Second Life avatar emote message
63///
64/// # Errors
65///
66/// returns an error if the parser fails
67fn avatar_emote_message_parser<'src>()
68-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
69{
70    just("/me ")
71        .ignore_then(any().repeated().collect::<String>())
72        .try_map(|s, _span: chumsky::span::SimpleSpan| {
73            let (v, s) = sl_types::chat::ChatVolume::volume_and_message(s);
74            Ok(AvatarMessage::Emote {
75                volume: v,
76                message: s,
77            })
78        })
79}
80
81/// parse a message about an avatar coming online
82///
83/// # Errors
84///
85/// returns an error if the parser fails
86#[must_use]
87pub fn avatar_came_online_message_parser<'src>()
88-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
89{
90    just("is online.").map(|_| AvatarMessage::CameOnline)
91}
92
93/// parse a message about an avatar going offline
94///
95/// # Errors
96///
97/// returns an error if the parser fails
98#[must_use]
99pub fn avatar_went_offline_message_parser<'src>()
100-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
101{
102    just("is offline.").map(|_| AvatarMessage::WentOffline)
103}
104
105/// parse a message about an avatar entering an area of significance
106///
107/// # Errors
108///
109/// returns an error if the parser fails
110#[must_use]
111pub fn avatar_entered_area_message_parser<'src>()
112-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
113{
114    just("entered ")
115        .ignore_then(sl_types::radar::area_parser())
116        .then(
117            just(" (")
118                .ignore_then(sl_types::map::distance_parser())
119                .then_ignore(just(")"))
120                .or_not(),
121        )
122        .then_ignore(just("."))
123        .try_map(|(area, distance), _span: chumsky::span::SimpleSpan| {
124            Ok(AvatarMessage::EnteredArea { area, distance })
125        })
126}
127
128/// parse a message about an avatar leaving an area of significance
129///
130/// # Errors
131///
132/// returns an error if the parser fails
133#[must_use]
134pub fn avatar_left_area_message_parser<'src>()
135-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
136{
137    just("left ")
138        .ignore_then(sl_types::radar::area_parser())
139        .then_ignore(just("."))
140        .try_map(|area, _span: chumsky::span::SimpleSpan| Ok(AvatarMessage::LeftArea { area }))
141}
142
143/// parse a Second Life avatar message
144///
145/// # Errors
146///
147/// returns an error if the parser fails
148#[must_use]
149pub fn avatar_message_parser<'src>()
150-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
151{
152    choice([
153        avatar_came_online_message_parser().boxed(),
154        avatar_went_offline_message_parser().boxed(),
155        avatar_entered_area_message_parser().boxed(),
156        avatar_left_area_message_parser().boxed(),
157        avatar_emote_message_parser().boxed(),
158        avatar_chat_message_parser().boxed(),
159    ])
160}