use chumsky::IterParser as _;
use chumsky::Parser;
use chumsky::prelude::{any, choice, just};
#[derive(Debug, Clone, PartialEq)]
pub enum AvatarMessage {
Chat {
volume: sl_types::chat::ChatVolume,
message: String,
},
Emote {
volume: sl_types::chat::ChatVolume,
message: String,
},
CameOnline,
WentOffline,
EnteredArea {
area: sl_types::radar::Area,
distance: Option<sl_types::map::Distance>,
},
LeftArea {
area: sl_types::radar::Area,
},
}
fn avatar_chat_message_parser<'src>()
-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
{
any()
.repeated()
.collect::<String>()
.try_map(|s, _span: chumsky::span::SimpleSpan| {
let (v, s) = sl_types::chat::ChatVolume::volume_and_message(s.to_string());
Ok(AvatarMessage::Chat {
volume: v,
message: s,
})
})
}
fn avatar_emote_message_parser<'src>()
-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
{
just("/me ")
.ignore_then(any().repeated().collect::<String>())
.try_map(|s, _span: chumsky::span::SimpleSpan| {
let (v, s) = sl_types::chat::ChatVolume::volume_and_message(s);
Ok(AvatarMessage::Emote {
volume: v,
message: s,
})
})
}
#[must_use]
pub fn avatar_came_online_message_parser<'src>()
-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
{
just("is online.").map(|_| AvatarMessage::CameOnline)
}
#[must_use]
pub fn avatar_went_offline_message_parser<'src>()
-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
{
just("is offline.").map(|_| AvatarMessage::WentOffline)
}
#[must_use]
pub fn avatar_entered_area_message_parser<'src>()
-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
{
just("entered ")
.ignore_then(sl_types::radar::area_parser())
.then(
just(" (")
.ignore_then(sl_types::map::distance_parser())
.then_ignore(just(")"))
.or_not(),
)
.then_ignore(just("."))
.try_map(|(area, distance), _span: chumsky::span::SimpleSpan| {
Ok(AvatarMessage::EnteredArea { area, distance })
})
}
#[must_use]
pub fn avatar_left_area_message_parser<'src>()
-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
{
just("left ")
.ignore_then(sl_types::radar::area_parser())
.then_ignore(just("."))
.try_map(|area, _span: chumsky::span::SimpleSpan| Ok(AvatarMessage::LeftArea { area }))
}
#[must_use]
pub fn avatar_message_parser<'src>()
-> impl Parser<'src, &'src str, AvatarMessage, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
{
choice([
avatar_came_online_message_parser().boxed(),
avatar_went_offline_message_parser().boxed(),
avatar_entered_area_message_parser().boxed(),
avatar_left_area_message_parser().boxed(),
avatar_emote_message_parser().boxed(),
avatar_chat_message_parser().boxed(),
])
}