use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ForwardedQuery {
pub user_id: u32,
pub client_id: u128,
pub correlation: Option<String>,
#[serde(with = "crate::encoding::bin_bytes")]
pub query_envelope: Vec<u8>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ForwardedCommand {
pub user_id: u32,
pub client_id: u128,
pub correlation: Option<String>,
#[serde(default)]
pub read_all: bool,
pub command_code: u32,
#[serde(with = "crate::encoding::bin_bytes")]
pub payload: Vec<u8>,
}
#[cfg(all(test, feature = "cbor"))]
mod tests {
use super::*;
use crate::framing::{decode_named, encode_named};
fn contains_byte_string(frame: &[u8], len: u8, fill: u8) -> bool {
let head = 0x40 | len; let mut want = vec![head];
want.extend(std::iter::repeat_n(fill, len as usize));
frame.windows(want.len()).any(|w| w == want.as_slice())
}
#[test]
fn given_forwarded_query_when_encoded_then_envelope_rides_as_a_byte_string() {
let frame = encode_named(&ForwardedQuery {
user_id: 7,
client_id: 42,
correlation: Some("conv-1".to_owned()),
query_envelope: vec![0x90; 5],
})
.expect("encodes");
assert!(
contains_byte_string(&frame, 5, 0x90),
"query_envelope must encode as a CBOR byte string, got {frame:02x?}"
);
}
#[test]
fn given_forwarded_command_when_encoded_then_payload_rides_as_a_byte_string() {
let frame = encode_named(&ForwardedCommand {
user_id: 7,
client_id: 42,
correlation: None,
read_all: true,
command_code: 1_000_000,
payload: vec![0x90; 5],
})
.expect("encodes");
assert!(
contains_byte_string(&frame, 5, 0x90),
"payload must encode as a CBOR byte string, got {frame:02x?}"
);
}
#[test]
fn given_forwarded_frames_when_round_tripped_then_should_preserve_fields() {
let query = ForwardedQuery {
user_id: 1,
client_id: u128::MAX,
correlation: Some("c".to_owned()),
query_envelope: vec![0xff, 0x00, 0x18, 0x7f],
};
let back: ForwardedQuery =
decode_named(&encode_named(&query).expect("encodes")).expect("decodes");
assert_eq!(back, query);
let command = ForwardedCommand {
user_id: 2,
client_id: 9,
correlation: None,
read_all: false,
command_code: 42,
payload: vec![0xde, 0xad, 0xbe, 0xef],
};
let back: ForwardedCommand =
decode_named(&encode_named(&command).expect("encodes")).expect("decodes");
assert_eq!(back, command);
}
}