use crate::message::{Msg, MsgFlags};
use std::sync::atomic::{AtomicUsize, Ordering};
type FramingOp = fn(&mut Vec<Msg>);
fn noop(_: &mut Vec<Msg>) {}
#[derive(Debug)]
pub(crate) struct FramingLatch {
mode: AtomicUsize,
encoders: [FramingOp; 2],
decoders: [FramingOp; 2],
}
impl FramingLatch {
pub fn new(auto_encode: FramingOp, auto_decode: FramingOp) -> Self {
Self {
mode: AtomicUsize::new(0),
encoders: [auto_encode, noop],
decoders: [auto_decode, noop],
}
}
#[inline(always)]
pub fn encode(&self, frames: &mut Vec<Msg>) {
let idx = self.mode.load(Ordering::Acquire);
(self.encoders[idx & 1])(frames);
}
#[inline(always)]
pub fn decode(&self, frames: &mut Vec<Msg>) {
let idx = self.mode.load(Ordering::Acquire);
(self.decoders[idx & 1])(frames);
}
pub fn set_manual(&self) -> bool {
self
.mode
.compare_exchange(0, 1, Ordering::Release, Ordering::Relaxed)
.is_ok()
}
pub fn is_manual(&self) -> bool {
self.mode.load(Ordering::Acquire) == 1
}
}
pub(crate) fn router_auto_encode(frames: &mut Vec<Msg>) {
let mut delimiter = Msg::new();
if frames.len() > 1 {
delimiter.set_flags(MsgFlags::MORE);
}
if !frames.is_empty() {
let current_flags = frames[0].flags();
frames[0].set_flags(current_flags | MsgFlags::MORE);
}
if !frames.is_empty() {
frames.insert(1, delimiter);
}
}
pub(crate) fn router_auto_decode(frames: &mut Vec<Msg>) {
if frames.len() > 1 {
frames.remove(1);
}
}
pub(crate) fn dealer_auto_encode(frames: &mut Vec<Msg>) {
let mut delimiter = Msg::new();
if !frames.is_empty() {
delimiter.set_flags(MsgFlags::MORE);
}
frames.insert(0, delimiter);
}
pub(crate) fn dealer_auto_decode(frames: &mut Vec<Msg>) {
if !frames.is_empty() {
frames.remove(0);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_router_auto_encode() {
let mut frames = vec![Msg::from_static(b"Identity"), Msg::from_static(b"Payload")];
router_auto_encode(&mut frames);
assert_eq!(frames.len(), 3);
assert_eq!(frames[0].data().unwrap(), b"Identity");
assert!(frames[0].is_more());
assert_eq!(frames[1].size(), 0); assert!(frames[1].is_more());
assert_eq!(frames[2].data().unwrap(), b"Payload");
assert!(!frames[2].is_more());
let mut frames = vec![Msg::from_static(b"Identity")];
router_auto_encode(&mut frames);
assert_eq!(frames.len(), 2);
assert_eq!(frames[0].data().unwrap(), b"Identity");
assert!(frames[0].is_more());
assert_eq!(frames[1].size(), 0); assert!(!frames[1].is_more()); }
#[test]
fn test_dealer_auto_encode() {
let mut frames = vec![Msg::from_static(b"Payload")];
dealer_auto_encode(&mut frames);
assert_eq!(frames.len(), 2);
assert_eq!(frames[0].size(), 0); assert!(frames[0].is_more());
assert_eq!(frames[1].data().unwrap(), b"Payload");
assert!(!frames[1].is_more());
let mut frames = vec![];
dealer_auto_encode(&mut frames);
assert_eq!(frames.len(), 1);
assert_eq!(frames[0].size(), 0);
assert!(!frames[0].is_more());
}
}