nativeshell 0.1.16

NativeShell Rust package
Documentation
use std::marker::PhantomData;

use crate::shell::{BinaryMessengerReply, Context, ContextRef, EngineHandle, EngineManager};

use super::MessageCodec;

pub struct MessageChannel<V>
where
    V: 'static,
{
    context: Context,
    channel_name: String,
    engine_handle: EngineHandle,
    _data: PhantomData<V>,
}

impl<V> MessageChannel<V> {
    pub fn new<F>(
        context: &ContextRef,
        engine_handle: EngineHandle,
        channel_name: &str,
        codec: &'static dyn MessageCodec<V>,
        callback: F,
    ) -> Self
    where
        F: Fn(V, MessageReply<V>) + 'static,
    {
        Self::new_with_engine_manager(
            context.weak(),
            engine_handle,
            channel_name,
            codec,
            callback,
            &context.engine_manager.borrow(),
        )
    }

    pub fn new_with_engine_manager<F>(
        context: Context,
        engine_handle: EngineHandle,
        channel_name: &str,
        codec: &'static dyn MessageCodec<V>,
        callback: F,
        engine_manager: &EngineManager,
    ) -> Self
    where
        F: Fn(V, MessageReply<V>) + 'static,
    {
        let res = MessageChannel {
            context,
            channel_name: channel_name.into(),
            engine_handle,
            _data: PhantomData {},
        };

        let engine = engine_manager.get_engine(engine_handle);
        if let Some(engine) = engine {
            let codec = codec;
            engine
                .binary_messenger()
                .register_channel_handler(channel_name, move |data, reply| {
                    let message = codec.decode_message(data).unwrap();
                    let reply = MessageReply { reply, codec };
                    callback(message, reply);
                });
        }
        res
    }
}

//
//
//

pub struct MessageReply<V>
where
    V: 'static,
{
    reply: BinaryMessengerReply,
    codec: &'static dyn MessageCodec<V>,
}

impl<V> MessageReply<V> {
    pub fn send(self, value: V) {
        let encoded = self.codec.encode_message(&value);
        self.reply.send(&encoded);
    }
}

impl<V> Drop for MessageChannel<V> {
    fn drop(&mut self) {
        if let Some(context) = self.context.get() {
            let engine_manager = context.engine_manager.borrow();
            let engine = engine_manager.get_engine(self.engine_handle);
            if let Some(engine) = engine {
                engine
                    .binary_messenger()
                    .unregister_channel_handler(&self.channel_name);
            }
        }
    }
}