use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use std::ops::Add;
use crate::error::MessageError;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Segment {
#[serde(alias = "type")]
pub kind: String,
pub data: Value,
}
impl Segment {
pub fn new(type_: &str, data: Value) -> Self {
Segment {
kind: type_.to_string(),
data,
}
}
}
impl PartialEq for Segment {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind && self.data == other.data
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Message(Vec<Segment>);
impl From<Vec<Segment>> for Message {
fn from(v: Vec<Segment>) -> Self {
Message(v)
}
}
impl From<Message> for Vec<Segment> {
fn from(v: Message) -> Self {
v.0
}
}
impl From<&str> for Message {
fn from(v: &str) -> Self {
Message(vec![Segment {
kind: "text".to_string(),
data: json!({
"text":v,
}),
}])
}
}
impl From<String> for Message {
fn from(v: String) -> Self {
Message(vec![Segment {
kind: "text".to_string(),
data: json!({
"text":v,
}),
}])
}
}
impl From<&String> for Message {
fn from(v: &String) -> Self {
Message(vec![Segment {
kind: "text".to_string(),
data: json!({
"text":v,
}),
}])
}
}
impl PartialEq for Message {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Add for Message {
type Output = Message;
fn add(mut self, rhs: Self) -> Self::Output {
for seg in rhs.into_iter() {
self.push(seg);
}
self
}
}
impl Message {
pub fn iter(&self) -> std::slice::Iter<'_, Segment> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Segment> {
self.0.iter_mut()
}
}
impl IntoIterator for Message {
type Item = Segment;
type IntoIter = std::vec::IntoIter<Segment>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl std::ops::Index<usize> for Message {
type Output = Segment;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl std::ops::IndexMut<usize> for Message {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}
impl Message {
pub fn push(&mut self, s: Segment) {
self.0.push(s);
}
pub fn from_value(v: Value) -> Result<Message, MessageError> {
if let Some(v) = v.as_array() {
match Message::from_vec_segment_value(v.clone()) {
Ok(msg) => return Ok(msg),
Err(err) => return Err(MessageError::ParseError(err.to_string())),
};
}
if let Some(v) = v.as_str() {
return Ok(Message::from(v));
}
Err(MessageError::ParseError(
"Message::from_value only accept array".to_string(),
))
}
pub fn from_vec_segment_value(v: Vec<Value>) -> Result<Message, serde_json::Error> {
let segments: Result<Vec<Segment>, serde_json::Error> = v
.into_iter()
.map(|value| {
let segment: Segment = serde_json::from_value(value)?;
Ok(segment)
})
.collect();
match segments {
Ok(segments) => Ok(Message(segments)),
Err(err) => Err(err),
}
}
pub fn to_human_string(&self) -> String {
let mut result = String::new();
for item in self.iter() {
match item.kind.as_str() {
"text" => {
if let Some(text_data) = item.data.get("text")
&& let Some(text_str) = text_data.as_str()
{
result.push_str(text_str);
}
}
_ => {
result.push_str(&format!("[{}]", item.kind));
}
}
}
result
}
pub fn get_from_index(&self, index: usize) -> Option<&Segment> {
self.0.get(index)
}
pub fn get_mut_from_index(&mut self, index: usize) -> Option<&mut Segment> {
self.0.get_mut(index)
}
}
impl Message {
pub fn new() -> Message {
Default::default()
}
pub fn contains(&self, s: &str) -> bool {
self.iter().any(|item| item.kind == s)
}
pub fn get(&self, s: &str) -> Vec<Segment> {
self.iter().filter(|item| item.kind == s).cloned().collect()
}
}
#[test]
fn check_msg() {
let msg: Message = Message::from_value(json!(
[
{
"type":"text",
"data":{
"text":"Some msg"
}
},
{
"type":"face",
"data":{
"id":"0"
}
},
]
))
.expect("Failed to parse msg json");
let text_value: Segment = serde_json::from_value(json!({
"type":"text",
"data":{
"text":"Some msg"
}
}))
.expect("Failed to parse text segment");
let face_value: Segment = serde_json::from_value(json!({
"type":"face",
"data":{
"id":"0"
}
}))
.expect("Failed to parse face segment");
assert_eq!(msg.get("text")[0], text_value);
assert_eq!(msg.get("face")[0], face_value);
let msg1: Message = Message::from("Hi");
let msg2: Message = Message::from_value(json!(
[
{
"type":"text",
"data":{
"text":"Some msg"
}
}
]
))
.expect("Failed to parse msg2 json");
assert!(msg1.contains("text"));
assert!(msg2.contains("text"));
}