use rayon::iter::Either; use serde::{Deserialize, Serialize}; use uuid::Uuid; pub trait IntoStreamMessage { const MSG_NAME: &str; fn build(&self) -> serde_json::Value; fn get_id(&self) -> String; } /// Pre-flight metadata for streaming #[derive(Debug, Clone, Deserialize, Serialize)] pub struct StreamDataStart { /// Uuid v4, client must mapping later values with this stream id pub stream_id: String, /// Total amount items known pub total_size: usize, /// pub chunk_size: usize, /// referer for checking steps in debugging #[serde(rename = "ref")] #[serde(skip_serializing_if = "Option::is_none")] pub stream_ref: Option, } impl IntoStreamMessage for StreamDataStart { const MSG_NAME: &str = "stream_data_start"; fn build(&self) -> serde_json::Value { serde_json::json!({ "type": StreamDataStart::MSG_NAME, "payload": self.clone() }) } fn get_id(&self) -> String { self.stream_id.clone() } } impl StreamDataStart { pub fn new(total_size: usize, chunk_size: usize, stream_ref: Option) -> Self { Self { stream_id: Uuid::new_v4().to_string(), total_size, chunk_size, stream_ref, } } pub fn as_msg(&self) -> serde_json::Value { self.build() } } /// Data splited into chunks not exceeding expected size #[derive(Debug, Clone, Deserialize, Serialize)] pub struct StreamDataChunk { /// Uuid v4, client must mapping later values with this stream id pub stream_id: String, /// Actual index of first item in this chunk from full data pub start_idx: usize, /// Chunked data which splited into N items per chunk pub data: Vec, } impl IntoStreamMessage for StreamDataChunk where T: Serialize, { const MSG_NAME: &str = "stream_data_chunk"; fn build(&self) -> serde_json::Value { serde_json::json!({ "type": StreamDataChunk::::MSG_NAME, "payload": self }) } fn get_id(&self) -> String { self.stream_id.clone() } } impl StreamDataChunk where T: Serialize, { pub fn new(sid: &str, start_idx: usize, data: Vec) -> Self { Self { stream_id: sid.to_string(), start_idx, data, } } pub fn as_msg(&self) -> serde_json::Value { self.build() } } /// Close message for signaling end of streaming #[derive(Debug, Clone, Deserialize, Serialize)] pub struct StreamDataEnd { /// Uuid v4, client must mapping later values with this stream id pub stream_id: String, } impl IntoStreamMessage for StreamDataEnd { const MSG_NAME: &str = "stream_data_end"; fn build(&self) -> serde_json::Value { serde_json::json!({ "type": StreamDataEnd::MSG_NAME, "payload": self.clone() }) } fn get_id(&self) -> String { self.stream_id.clone() } } impl StreamDataEnd { pub fn new(sid: &str) -> Self { Self { stream_id: sid.to_string(), } } pub fn as_msg(&self) -> serde_json::Value { self.build() } } /// Extra data send along with previous sent chunks, /// must send before end msg. #[derive(Debug, Clone, Deserialize, Serialize)] pub struct StreamDataExtra { /// Uuid v4, client must mapping later values with this stream id pub exid: String, pub extp: String, pub payload: Vec, } impl IntoStreamMessage for StreamDataExtra where T: Serialize, { const MSG_NAME: &str = "stream_data_extra"; fn build(&self) -> serde_json::Value { serde_json::json!({ "type": StreamDataExtra::::MSG_NAME, "payload": self }) } fn get_id(&self) -> String { self.exid.clone() } } impl StreamDataExtra where T: Serialize + Clone, { pub fn new(exid: &str, extp: &str, data: Vec) -> Self { Self { exid: exid.to_string(), extp: extp.to_string(), payload: data.to_vec(), } } pub fn as_msg(&self) -> serde_json::Value { self.build() } }