1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::data::error_info::ErrorInfo;
use crate::data::{Hold, Literal, Memory, Message, MSG};
use crate::parser::ExitCondition;

use core::ops::Add;
use std::sync::mpsc;

////////////////////////////////////////////////////////////////////////////////
// DATA STRUCTURE
////////////////////////////////////////////////////////////////////////////////

#[derive(Debug, Clone)]
pub struct MessageData {
    pub memories: Option<Vec<Memory>>,
    pub messages: Vec<Message>,
    pub hold: Option<Hold>,
    pub exit_condition: Option<ExitCondition>,
}

////////////////////////////////////////////////////////////////////////////////
// TRAIT FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

impl Default for MessageData {
    fn default() -> Self {
        Self {
            memories: None,
            messages: Vec::new(),
            hold: None,
            exit_condition: None,
        }
    }
}

impl Add<MessageData> for MessageData {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        Self {
            memories: match (self.memories, other.memories) {
                (Some(memory), None) => Some(memory),
                (None, Some(new_memory)) => Some(new_memory),
                (Some(memory), Some(new_memory)) => Some([&memory[..], &new_memory[..]].concat()),
                _ => None,
            },
            messages: [&self.messages[..], &other.messages[..]].concat(),
            hold: self.hold,
            exit_condition: match (&self.exit_condition, &other.exit_condition) {
                (Some(exit_condition), None) => Some(exit_condition.to_owned()),
                (None, Some(exit_condition)) => Some(exit_condition.to_owned()),
                (Some(exit_condition), Some(_)) => Some(exit_condition.to_owned()),
                _ => None,
            },
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// STATIC FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

impl MessageData {
    pub fn error_to_message(
        result: Result<Self, ErrorInfo>,
        sender: &Option<mpsc::Sender<MSG>>,
    ) -> Self {
        match result {
            Ok(message_data) => message_data,
            Err(err) => {
                let json_msg = serde_json::json!({"error": err.format_error()});

                MSG::send(
                    sender,
                    MSG::Error(Message {
                        content_type: "error".to_owned(),
                        content: json_msg.clone(),
                    }),
                );

                Self {
                    memories: None,
                    messages: vec![Message {
                        content_type: "error".to_owned(),
                        content: json_msg,
                    }],
                    hold: None,
                    exit_condition: Some(ExitCondition::Error),
                }
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// METHOD FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

impl MessageData {
    pub fn add_message(mut self, message: Message) -> Self {
        self.messages.push(message);
        self
    }

    pub fn add_to_memory(&mut self, key: &str, value: Literal) {
        let content_type = &value.content_type;

        if let Some(ref mut vec) = self.memories {
            vec.push(Memory {
                key: key.to_owned(),
                value: value.primitive.format_mem(content_type, true),
            });
        } else {
            self.memories = Some(vec![Memory {
                key: key.to_owned(),
                value: value.primitive.format_mem(content_type, true),
            }])
        };
    }
}