use super::Reasoner;
use crate::{
entity::RCTask,
global::ClockTime,
storage::{Memory, TaskBuffer},
util::Serial,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize)]
pub(super) struct ReasonerStatusStorage {
pub memory: Memory,
pub derivation_datas: TaskBuffer,
pub clock: ClockTime,
pub stamp_current_serial: ClockTime,
pub task_current_serial: Serial,
}
#[derive(Debug, Clone, Copy, Serialize)]
pub(super) struct ReasonerStatusStorageRef<'s> {
pub memory: &'s Memory,
pub derivation_datas: &'s TaskBuffer,
pub clock: ClockTime,
pub stamp_current_serial: ClockTime,
pub task_current_serial: Serial,
}
impl ReasonerStatusStorage {
fn unify_all_task_rcs(&mut self) {
let memory_refs = self.memory.all_task_rcs();
let derivation_datas_refs = self.derivation_datas.iter_mut_task_rcs();
let refs = memory_refs.chain(derivation_datas_refs);
RCTask::unify_rcs(refs);
}
}
impl Reasoner {
#[must_use]
pub fn load_memory(&mut self, mut memory: Memory) -> Memory {
std::mem::swap(&mut memory, &mut self.memory);
memory
}
#[must_use]
fn load_derivation_datas(&mut self, mut derivation_datas: TaskBuffer) -> TaskBuffer {
std::mem::swap(&mut derivation_datas, &mut self.task_buffer);
derivation_datas
}
#[must_use]
fn load_status(&mut self, status: ReasonerStatusStorage) -> ReasonerStatusStorage {
let ReasonerStatusStorage {
memory,
derivation_datas,
clock,
stamp_current_serial,
task_current_serial,
} = status;
let memory = self.load_memory(memory);
let derivation_datas = self.load_derivation_datas(derivation_datas);
let clock_old = self.time();
self.set_time(clock);
let stamp_current_serial_old = self.stamp_current_serial();
self.set_stamp_current_serial(stamp_current_serial);
let task_current_serial_old = self.task_current_serial();
self.set_task_current_serial(task_current_serial);
ReasonerStatusStorage {
memory,
derivation_datas,
clock: clock_old,
stamp_current_serial: stamp_current_serial_old,
task_current_serial: task_current_serial_old,
}
}
}
impl Reasoner {
pub fn serialize_memory<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.memory.serialize(serializer)
}
pub fn load_from_deserialized_memory<'de, D>(&mut self, deserializer: D) -> Result<(), D::Error>
where
D: serde::Deserializer<'de>,
{
let memory = Memory::deserialize(deserializer)?;
let _ = self.load_memory(memory);
Ok(())
}
pub fn serialize_status<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let storage_ref = ReasonerStatusStorageRef {
memory: &self.memory,
derivation_datas: &self.task_buffer,
clock: self.time(),
stamp_current_serial: self.stamp_current_serial(),
task_current_serial: self.task_current_serial(),
};
storage_ref.serialize(serializer)
}
pub fn load_from_deserialized_status<'de, D>(&mut self, deserializer: D) -> Result<(), D::Error>
where
D: serde::Deserializer<'de>,
{
let mut status = ReasonerStatusStorage::deserialize(deserializer)?;
status.unify_all_task_rcs();
let _ = self.load_status(status);
Ok(())
}
}
#[cfg(test)]
pub mod test_util_ser_de {
use super::*;
use crate::{
assert_eq_try, ok,
storage::{tests_memory::*, tests_task_buffer::*},
util::AResult,
};
impl GetMemory for Reasoner {
fn get_memory(&self) -> &Memory {
&self.memory
}
}
impl GetMemory for ReasonerStatusStorage {
fn get_memory(&self) -> &Memory {
&self.memory
}
}
impl GetMemory for ReasonerStatusStorageRef<'_> {
fn get_memory(&self) -> &Memory {
self.memory
}
}
pub trait GetReasoner {
fn get_reasoner(&self) -> &Reasoner;
}
impl GetReasoner for Reasoner {
fn get_reasoner(&self) -> &Reasoner {
self
}
}
pub fn status_synced(reasoner: &impl GetReasoner) {
let reasoner = reasoner.get_reasoner();
memory_synced(&reasoner.memory);
reasoner.task_buffer.iter_task_rcs().for_each(rc_synced);
}
pub fn status_consistent<R1: GetReasoner, R2: GetReasoner>(a: &R1, b: &R2) -> AResult {
let [a, b] = [a.get_reasoner(), b.get_reasoner()];
memory_consistent(&a.memory, &b.memory)?;
task_buffer_consistent(&a.task_buffer, &b.task_buffer)?;
assert_eq_try!(
a.time(),
b.time(),
"系统时钟不一致:{} != {}",
a.time(),
b.time()
);
assert_eq_try!(
a.stamp_current_serial(),
b.stamp_current_serial(),
"系统时间戳序列号不一致"
);
ok!()
}
}