coreon-core 0.1.0

Core abstractions for camel-rs: Exchange, Processor, Endpoint, Component, CamelContext.
Documentation
//! Message — payload + headers, the in/out of an Exchange.

use bytes::Bytes;
use std::collections::HashMap;
use std::sync::Arc;

/// Body variants carried by a Message.
///
/// `Custom` uses `Arc<dyn Any>` so arbitrary application types can flow
/// through the pipeline without the core knowing about them.
#[derive(Clone, Debug, Default)]
pub enum Body {
    #[default]
    Empty,
    Bytes(Bytes),
    Text(String),
    Custom(Arc<dyn std::any::Any + Send + Sync>),
}

impl Body {
    pub fn as_text(&self) -> Option<&str> {
        match self {
            Body::Text(s) => Some(s.as_str()),
            _ => None,
        }
    }

    pub fn as_bytes(&self) -> Option<&Bytes> {
        match self {
            Body::Bytes(b) => Some(b),
            _ => None,
        }
    }
}

impl From<String> for Body {
    fn from(s: String) -> Self {
        Body::Text(s)
    }
}

impl From<&str> for Body {
    fn from(s: &str) -> Self {
        Body::Text(s.to_owned())
    }
}

impl From<Bytes> for Body {
    fn from(b: Bytes) -> Self {
        Body::Bytes(b)
    }
}

impl From<Vec<u8>> for Body {
    fn from(v: Vec<u8>) -> Self {
        Body::Bytes(Bytes::from(v))
    }
}

/// Header values are string-typed for MVP. A future revision may widen
/// this to a tagged enum if performance/type-safety demands it.
pub type HeaderMap = HashMap<String, String>;

#[derive(Clone, Debug, Default)]
pub struct Message {
    pub headers: HeaderMap,
    pub body: Body,
}

impl Message {
    pub fn new(body: impl Into<Body>) -> Self {
        Self {
            headers: HeaderMap::new(),
            body: body.into(),
        }
    }

    pub fn with_header(mut self, k: impl Into<String>, v: impl Into<String>) -> Self {
        self.headers.insert(k.into(), v.into());
        self
    }

    pub fn header(&self, k: &str) -> Option<&str> {
        self.headers.get(k).map(|s| s.as_str())
    }
}