use crate::types::User;
use serde::de::{Deserialize, Deserializer, Error, Visitor};
use std::fmt::{self, Formatter};
#[derive(Debug, PartialEq, Clone)]
pub struct Text {
pub value: String,
pub entities: Vec<Entity>,
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum EntityKind {
Mention,
Hashtag,
Cashtag,
BotCommand,
Url,
Email,
PhoneNumber,
Bold,
Italic,
Code,
Pre,
TextLink(String),
TextMention(User),
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct Entity {
pub kind: EntityKind,
pub offset: usize,
pub length: usize,
}
const OFFSET: &str = "offset";
const LENGTH: &str = "length";
const URL: &str = "url";
const USER: &str = "user";
const TYPE: &str = "type";
const MENTION: &str = "mention";
const HASHTAG: &str = "hashtag";
const CASHTAG: &str = "cashtag";
const BOT_COMMAND: &str = "bot_command";
const EMAIL: &str = "email";
const PHONE_NUMBER: &str = "phone_number";
const BOLD: &str = "bold";
const ITALIC: &str = "italic";
const CODE: &str = "code";
const PRE: &str = "pre";
const TEXT_LINK: &str = "text_link";
const TEXT_MENTION: &str = "text_mention";
struct EntityVisitor;
impl<'v> Visitor<'v> for EntityVisitor {
type Value = Entity;
fn expecting(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "struct Entity")
}
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where
V: serde::de::MapAccess<'v>,
{
let mut kind: Option<String> = None;
let mut offset = None;
let mut length = None;
let mut url = None;
let mut user = None;
while let Some(key) = map.next_key()? {
match key {
OFFSET => offset = Some(map.next_value()?),
LENGTH => length = Some(map.next_value()?),
URL => url = Some(map.next_value()?),
USER => user = Some(map.next_value()?),
TYPE => kind = Some(map.next_value()?),
_ => {
let _ = map.next_value::<serde_json::Value>();
}
}
}
let kind = kind.ok_or_else(|| serde::de::Error::missing_field(TYPE))?;
let kind = match kind.as_str() {
TEXT_MENTION => EntityKind::TextMention(
user.ok_or_else(|| serde::de::Error::missing_field(USER))?,
),
TEXT_LINK => EntityKind::TextLink(
url.ok_or_else(|| serde::de::Error::missing_field(URL))?,
),
MENTION => EntityKind::Mention,
HASHTAG => EntityKind::Hashtag,
CASHTAG => EntityKind::Cashtag,
BOT_COMMAND => EntityKind::BotCommand,
URL => EntityKind::Url,
EMAIL => EntityKind::Email,
PHONE_NUMBER => EntityKind::PhoneNumber,
BOLD => EntityKind::Bold,
ITALIC => EntityKind::Italic,
CODE => EntityKind::Code,
PRE => EntityKind::Pre,
_ => {
return Err(Error::unknown_variant(
&kind,
&[
MENTION,
HASHTAG,
CASHTAG,
BOT_COMMAND,
URL,
EMAIL,
PHONE_NUMBER,
BOLD,
ITALIC,
CODE,
PRE,
TEXT_LINK,
TEXT_MENTION,
],
))
}
};
Ok(Entity {
kind,
offset: offset.ok_or_else(|| Error::missing_field(OFFSET))?,
length: length.ok_or_else(|| Error::missing_field(LENGTH))?,
})
}
}
impl<'de> Deserialize<'de> for Entity {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
d.deserialize_struct(
"Entity",
&[TYPE, OFFSET, LENGTH, URL, USER],
EntityVisitor,
)
}
}