use crate::host::error::*;
use crate::host::filter::*;
use crate::host::scene::*;
use crate::host::scene_context::*;
use crate::host::scene_message::*;
use crate::host::stream_target::*;
use crate::host::stream_id::*;
use crate::host::subprogram_id::*;
use crate::host::programs::*;
use futures::prelude::*;
use futures::stream;
use once_cell::sync::{Lazy};
use serde::*;
use serde::ser::{Error as SeError};
use serde::de::{Error as DeError};
use std::any::*;
use std::collections::{HashMap};
use std::marker::{PhantomData};
use std::ops::{Deref};
use std::sync::*;
static SERIALIZABLE_MESSAGE_TYPE_NAMES: Lazy<RwLock<HashMap<TypeId, String>>> = Lazy::new(|| RwLock::new(HashMap::new()));
static TYPE_ID_FOR_NAME: Lazy<RwLock<HashMap<String, TypeId>>> = Lazy::new(|| RwLock::new(HashMap::new()));
static STREAM_ID_FOR_SERIALIZABLE_TYPE: Lazy<RwLock<HashMap<String, StreamId>>> = Lazy::new(|| RwLock::new(HashMap::new()));
static STREAM_ID_FOR_RUST_TYPE: Lazy<RwLock<HashMap<String, StreamId>>> = Lazy::new(|| RwLock::new(HashMap::new()));
static SEND_DESERIALIZED: Lazy<RwLock<HashMap<(TypeId, TypeId), Arc<dyn Send + Sync + Fn(StreamTarget, &SceneContext) -> Result<Box<dyn Send + Any>, ConnectionError>>>>> = Lazy::new(|| RwLock::new(HashMap::new()));
static TYPED_SERIALIZERS: Lazy<RwLock<HashMap<(TypeId, TypeId), Arc<dyn Send + Sync + Any>>>> = Lazy::new(|| RwLock::new(HashMap::new()));
static FILTERS_FOR_TYPE: Lazy<Mutex<HashMap<(TypeId, TypeId), Vec<FilterHandle>>>> = Lazy::new(|| Mutex::new(HashMap::new()));
#[cfg(any(feature="postcard", target_family="wasm"))]
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct GuestMessage(pub Vec<u8>);
#[derive(Debug, PartialEq)]
pub struct SerializedMessage<TSerializedType>(pub TSerializedType, pub TypeId);
impl<TSerializedType> SceneMessage for SerializedMessage<TSerializedType>
where
TSerializedType: 'static + Send + Unpin,
{
fn serializable() -> bool { false }
#[inline]
fn message_type_name() -> String { format!("flo_scene::SerializedMessage<{}>", std::any::type_name::<TSerializedType>()) }
}
impl<TSerializedType> Serialize for SerializedMessage<TSerializedType> {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
where
S: Serializer
{
Err(S::Error::custom("SerializedMessage cannot be serialized"))
}
}
impl<'a, TSerializedType> Deserialize<'a> for SerializedMessage<TSerializedType> {
fn deserialize<D>(_: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>
{
Err(D::Error::custom("SerializedMessage cannot be serialized"))
}
}
pub fn install_serializable_type<TMessageType, TSerializedType>(
serialize: impl 'static + Send + Sync + Fn(TMessageType) -> Result<TSerializedType, SceneSendError<TMessageType>>,
deserialize: impl 'static + Send + Sync + Fn(&TSerializedType) -> Result<TMessageType, SceneSendError<()>>) -> Result<(), &'static str>
where
TSerializedType: 'static + Send,
TMessageType: 'static + SceneMessage,
{
let type_name = TMessageType::message_type_name();
{
let mut type_for_name = (*TYPE_ID_FOR_NAME).write().unwrap();
if let Some(existing_type_id) = type_for_name.get(&type_name) {
if existing_type_id != &TypeId::of::<TMessageType>() {
return Err("Serialization type name has been used by another type");
}
} else {
type_for_name.insert(type_name.clone(), TypeId::of::<TMessageType>());
}
}
{
let mut type_names = (*SERIALIZABLE_MESSAGE_TYPE_NAMES).write().unwrap();
if let Some(existing_type_name) = type_names.get(&TypeId::of::<TMessageType>()) {
if existing_type_name != &type_name {
return Err("Serialization type has already been assigned a different name");
}
} else {
type_names.insert(TypeId::of::<TMessageType>(), type_name.clone());
}
}
let typed_serializer = move |input: TMessageType| -> Result<SerializedMessage<TSerializedType>, TMessageType> {
match serialize(input) {
Ok(val) => Ok(SerializedMessage(val, TypeId::of::<TMessageType>())),
Err(err) => Err(err.to_message().unwrap())
}
};
let deserialize = Arc::new(deserialize);
let typed_deserialize = Arc::clone(&deserialize);
let typed_deserializer = move |input: SerializedMessage<TSerializedType>| -> Result<TMessageType, SerializedMessage<TSerializedType>> {
use std::mem;
let val = typed_deserialize(&input.0);
match val {
Ok(val) => Ok(val),
Err(_) => {
mem::drop(val);
Err(input)
},
}
};
let send_deserialized_stream = move |target: StreamTarget, context: &SceneContext| -> Result<Box<dyn Send + Any>, ConnectionError> {
let deserialize = Arc::clone(&deserialize);
let target = context.send::<TMessageType>(target)?;
let deserialized_target = target
.sink_map_err(|_| SceneSendError::<TSerializedType>::ErrorAfterDeserialization) .with(move |msg| future::ready(match deserialize(&msg) {
Ok(result) => Ok(result),
Err(_) => Err(SceneSendError::ErrorAfterDeserialization)
}));
let boxed_target: Box<dyn Send + Unpin + Sink<TSerializedType, Error=SceneSendError::<TSerializedType>>> = Box::new(deserialized_target);
Ok(Box::new(boxed_target))
};
let typed_serializer: Box<dyn Send + Sync + Fn(TMessageType) -> Result<SerializedMessage<TSerializedType>, TMessageType>> = Box::new(typed_serializer);
let typed_deserializer: Box<dyn Send + Sync + Fn(SerializedMessage<TSerializedType>) -> Result<TMessageType, SerializedMessage<TSerializedType>>> = Box::new(typed_deserializer);
let typed_serializer: Arc<dyn Send + Sync + Any> = Arc::new(typed_serializer);
let typed_deserializer: Arc<dyn Send + Sync + Any> = Arc::new(typed_deserializer);
{
let mut typed_serializers = (*TYPED_SERIALIZERS).write().unwrap();
typed_serializers.insert((TypeId::of::<TMessageType>(), TypeId::of::<SerializedMessage<TSerializedType>>()), typed_serializer);
typed_serializers.insert((TypeId::of::<SerializedMessage<TSerializedType>>(), TypeId::of::<TMessageType>()), typed_deserializer);
}
{
(*STREAM_ID_FOR_SERIALIZABLE_TYPE).write().unwrap().insert(type_name.clone(), StreamId::with_message_type::<TMessageType>());
(*STREAM_ID_FOR_RUST_TYPE).write().unwrap().insert(std::any::type_name::<TMessageType>().into(), StreamId::with_message_type::<TMessageType>());
}
{
let mut send_deserialized = (*SEND_DESERIALIZED).write().unwrap();
send_deserialized.insert((TypeId::of::<TSerializedType>(), TypeId::of::<TMessageType>()), Arc::new(send_deserialized_stream));
}
Ok(())
}
pub fn serialization_function<TSourceType, TTargetType>() -> Result<Arc<impl 'static + Send + Fn(TSourceType) -> Result<TTargetType, TSourceType>>, &'static str>
where
TSourceType: 'static + SceneMessage,
TTargetType: 'static + SceneMessage,
{
let typed_serializer = (*TYPED_SERIALIZERS).read().unwrap().get(&(TypeId::of::<TSourceType>(), TypeId::of::<TTargetType>())).cloned();
let typed_serializer = if let Some(typed_serializer) = typed_serializer { Ok(typed_serializer) } else { Err("The requested serializers are not installed") }?;
let typed_serializer = if let Ok(typed_serializer) = typed_serializer.downcast::<Box<dyn Send + Sync + Fn(TSourceType) -> Result<TTargetType, TSourceType>>>() {
Ok(typed_serializer)
} else {
Err("Could not properly resolve the type of the requested serializer")
}?;
Ok(typed_serializer)
}
pub fn serializer_filter<TSourceType, TTargetType>() -> Result<Vec<FilterHandle>, &'static str>
where
TSourceType: 'static + SceneMessage,
TTargetType: 'static + SceneMessage,
{
let mut filters_for_type = (*FILTERS_FOR_TYPE).lock().unwrap();
let message_type = (TypeId::of::<TSourceType>(), TypeId::of::<TTargetType>());
if let Some(filter) = filters_for_type.get(&message_type) {
Ok(filter.clone())
} else {
let typed_serializer = (*TYPED_SERIALIZERS).read().unwrap().get(&(TypeId::of::<TSourceType>(), TypeId::of::<TTargetType>())).cloned();
let typed_serializer = if let Some(typed_serializer) = typed_serializer { Ok(typed_serializer) } else { Err("The requested serializers are not installed") }?;
let typed_serializer = if let Ok(typed_serializer) = typed_serializer.downcast::<Box<dyn Send + Sync + Fn(TSourceType) -> Result<TTargetType, TSourceType>>>() {
Ok(typed_serializer)
} else {
Err("Could not properly resolve the type of the requested serializer")
}?;
let raw_type_serializer = typed_serializer.clone();
let filter_raw_type = FilterHandle::for_filter(move |input_messages| {
let raw_type_serializer = Arc::clone(&raw_type_serializer);
input_messages.flat_map(move |msg| stream::iter((*raw_type_serializer)(msg).ok()))
});
let query_type_serializer = typed_serializer.clone();
let filter_query_responses = FilterHandle::for_filter(move |input_messages| {
let query_type_serializer = Arc::clone(&query_type_serializer);
input_messages.map(move |response: QueryResponse<TSourceType>| {
let query_type_serializer = Arc::clone(&query_type_serializer);
let responses = response.flat_map(move |msg| stream::iter((*query_type_serializer)(msg).ok()));
QueryResponse::with_stream(responses.boxed())
})
});
filters_for_type.insert(message_type, vec![filter_raw_type.clone(), filter_query_responses.clone()]);
Ok(vec![filter_raw_type, filter_query_responses])
}
}
pub struct SceneWithSerializer<'a, TSerializer>(&'a Scene, PhantomData<TSerializer>);
impl Scene {
pub fn with_serializer<TSerializedType>(&self) -> SceneWithSerializer<'_, TSerializedType>
where
TSerializedType: 'static + Send + Unpin,
{
SceneWithSerializer(self, PhantomData)
}
}
pub enum SerializedStreamTarget {
SubProgram(SubProgramId),
Stream(StreamId)
}
impl From<StreamId> for SerializedStreamTarget {
fn from(stream: StreamId) -> Self {
SerializedStreamTarget::Stream(stream)
}
}
impl From<SubProgramId> for SerializedStreamTarget {
fn from(program: SubProgramId) -> Self {
SerializedStreamTarget::SubProgram(program)
}
}
impl SceneContext {
pub fn send_serialized<TMessageType>(&self, target: impl Into<SerializedStreamTarget>) -> Result<impl Sink<TMessageType, Error=SceneSendError<TMessageType>>, ConnectionError>
where
TMessageType: 'static + Send + Unpin + Serialize,
{
match target.into() {
SerializedStreamTarget::Stream(stream_id) => {
let send_deserialized = (*SEND_DESERIALIZED).read().unwrap()
.get(&(TypeId::of::<TMessageType>(), stream_id.message_type())).cloned();
let send_deserialized = if let Some(send_deserialized) = send_deserialized { Ok(send_deserialized) } else { Err(ConnectionError::TargetCannotDeserialize) }?;
let deserializer_sink = send_deserialized(StreamTarget::Any, self)?;
let deserializer_sink = deserializer_sink.downcast::<Box<dyn Send + Unpin + Sink<TMessageType, Error=SceneSendError::<TMessageType>>>>();
deserializer_sink.map(|val| *val).or_else(|_| Err(ConnectionError::UnexpectedConnectionType))
}
SerializedStreamTarget::SubProgram(subprogram_id) => {
let stream_id = if let Some(core) = self.scene_core().upgrade() {
let program = core.lock().unwrap().get_sub_program(subprogram_id);
let program = program.ok_or_else(|| ConnectionError::SubProgramNotRunning)?;
let stream_id = program.lock().unwrap().input_stream_id.clone();
Ok(stream_id)
} else {
Err(ConnectionError::SubProgramNotRunning)
}?;
let target = self.send::<SerializedMessage<TMessageType>>(subprogram_id)?;
let target = target
.sink_map_err(|_| SceneSendError::<TMessageType>::ErrorAfterDeserialization) .with(move |msg|
future::ready(Ok(SerializedMessage(msg, stream_id.message_type()))));
let target: Box<dyn Send + Unpin + Sink<TMessageType, Error=SceneSendError::<TMessageType>>> = Box::new(target);
Ok(target)
}
}
}
}
impl<'a, TSerializer> Deref for SceneWithSerializer<'a, TSerializer> {
type Target = Scene;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl StreamId {
pub fn serialization_type_name(&self) -> Option<String> {
(*SERIALIZABLE_MESSAGE_TYPE_NAMES).read().unwrap().get(&self.message_type()).cloned()
}
pub fn with_serialization_type(type_name: impl Into<String>) -> Option<Self> {
(*STREAM_ID_FOR_SERIALIZABLE_TYPE).read().unwrap().get(&type_name.into()).cloned()
}
pub fn with_rust_type(type_name: impl Into<String>) -> Option<Self> {
(*STREAM_ID_FOR_RUST_TYPE).read().unwrap().get(&type_name.into()).cloned()
}
}