Skip to main content

atomr_remote/serialization/
bincode_codec.rs

1//! Bincode v2 + serde codec helpers.
2
3use serde::{de::DeserializeOwned, Serialize};
4
5use super::{SerializeError, SerializerRegistry, BINCODE_SERIALIZER_ID, SYSTEM_SERIALIZER_ID};
6use crate::pdu::{AckInfo, AssociateInfo, DisassociateReason};
7
8pub fn bincode_encode<T: Serialize>(value: &T) -> Result<Vec<u8>, SerializeError> {
9    bincode::serde::encode_to_vec(value, bincode::config::standard())
10        .map_err(|e| SerializeError::Encode(e.to_string()))
11}
12
13pub fn bincode_decode<T: DeserializeOwned>(bytes: &[u8]) -> Result<T, SerializeError> {
14    let (v, _) = bincode::serde::decode_from_slice(bytes, bincode::config::standard())
15        .map_err(|e| SerializeError::Decode(e.to_string()))?;
16    Ok(v)
17}
18
19/// System control payloads use the same bincode codec but a reserved
20/// `serializer_id` of [`SYSTEM_SERIALIZER_ID`] so receivers can dispatch
21/// them on the system path without consulting the user manifest table.
22pub fn system_encode<T: Serialize>(value: &T) -> Result<Vec<u8>, SerializeError> {
23    bincode_encode(value)
24}
25
26pub fn system_decode<T: DeserializeOwned>(bytes: &[u8]) -> Result<T, SerializeError> {
27    bincode_decode(bytes)
28}
29
30/// Pre-register codecs for the protocol-level system payloads
31/// (`AssociateInfo`, `DisassociateReason`, `AckInfo`, plus the
32/// `RemoteSystemMsg` variants that travel as Payload PDUs).
33pub fn register_system_payloads(reg: &SerializerRegistry) {
34    use atomr_core::actor::RemoteSystemMsg;
35    use std::any::TypeId;
36    use std::sync::Arc;
37
38    use super::TypeCodec;
39
40    fn codec<T: Serialize + DeserializeOwned + Send + 'static>(id: u32) -> TypeCodec {
41        TypeCodec {
42            serializer_id: id,
43            manifest: std::any::type_name::<T>().to_string(),
44            type_id: TypeId::of::<T>(),
45            encode: Arc::new(|v: &dyn std::any::Any| {
46                let v = v
47                    .downcast_ref::<T>()
48                    .ok_or_else(|| SerializeError::Downcast(std::any::type_name::<T>().to_string()))?;
49                bincode_encode(v)
50            }),
51            decode: Arc::new(|b: &[u8]| {
52                let v: T = bincode_decode(b)?;
53                Ok(Box::new(v) as Box<dyn std::any::Any + Send>)
54            }),
55        }
56    }
57
58    reg.register_codec(codec::<AssociateInfo>(SYSTEM_SERIALIZER_ID));
59    reg.register_codec(codec::<DisassociateReason>(SYSTEM_SERIALIZER_ID));
60    reg.register_codec(codec::<AckInfo>(SYSTEM_SERIALIZER_ID));
61    reg.register_codec(codec::<RemoteSystemMsg>(SYSTEM_SERIALIZER_ID));
62
63    // Register a few common user types with bincode by default so trivial
64    // examples work without manual registration.
65    reg.register_codec(codec::<String>(BINCODE_SERIALIZER_ID));
66    reg.register_codec(codec::<Vec<u8>>(BINCODE_SERIALIZER_ID));
67    reg.register_codec(codec::<i64>(BINCODE_SERIALIZER_ID));
68    reg.register_codec(codec::<u64>(BINCODE_SERIALIZER_ID));
69    reg.register_codec(codec::<i32>(BINCODE_SERIALIZER_ID));
70    reg.register_codec(codec::<u32>(BINCODE_SERIALIZER_ID));
71    reg.register_codec(codec::<bool>(BINCODE_SERIALIZER_ID));
72}