Skip to main content

roon_moo/
message.rs

1use std::collections::HashMap;
2
3use bytes::Bytes;
4
5/// MOO protocol verb indicating the message role in a request/response exchange.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum MooVerb {
8    /// Initiates a new request. Name is `<service>/<method>`.
9    Request,
10    /// Intermediate response — the request remains open.
11    Continue,
12    /// Final response — the request is closed.
13    Complete,
14}
15
16impl MooVerb {
17    pub fn as_str(&self) -> &'static str {
18        match self {
19            MooVerb::Request => "REQUEST",
20            MooVerb::Continue => "CONTINUE",
21            MooVerb::Complete => "COMPLETE",
22        }
23    }
24}
25
26/// The body of a MOO message, either parsed JSON or raw binary.
27#[derive(Debug, Clone, PartialEq)]
28pub enum MooBody {
29    Json(serde_json::Value),
30    Binary(Bytes),
31}
32
33/// A parsed MOO protocol message.
34#[derive(Debug, Clone)]
35pub struct MooMessage {
36    pub verb: MooVerb,
37    /// For REQUEST: `<service>/<method>`. For CONTINUE/COMPLETE: `<status>`.
38    pub name: String,
39    pub request_id: u32,
40    /// Headers other than Request-Id, Content-Length, and Content-Type.
41    pub headers: HashMap<String, String>,
42    pub body: Option<MooBody>,
43}
44
45impl MooMessage {
46    /// For REQUEST messages, extract the service name (everything before the last `/`).
47    pub fn service(&self) -> Option<&str> {
48        if self.verb != MooVerb::Request {
49            return None;
50        }
51        self.name.rfind('/').map(|i| &self.name[..i])
52    }
53
54    /// For REQUEST messages, extract the method name (everything after the last `/`).
55    pub fn method(&self) -> Option<&str> {
56        if self.verb != MooVerb::Request {
57            return None;
58        }
59        self.name.rfind('/').map(|i| &self.name[i + 1..])
60    }
61
62    /// Extract body as JSON value, if the body is JSON.
63    pub fn json_body(&self) -> Option<&serde_json::Value> {
64        match &self.body {
65            Some(MooBody::Json(v)) => Some(v),
66            _ => None,
67        }
68    }
69}