Files
multiverse/xcom-ultra/xcu-prism/src/lib.rs
T

44 lines
2.6 KiB
Rust

#![deny(warnings)]
#![allow(dead_code)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-prism -- Color Protocol Quantum Packet Splitting
#[derive(Debug)] pub enum PrismError { InvalidShard(String), MissingShard(String), ReassemblyFailed(String) }
impl std::fmt::Display for PrismError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::InvalidShard(e)|Self::MissingShard(e)|Self::ReassemblyFailed(e) => write!(f, "{e}") } } }
impl std::error::Error for PrismError {}
#[derive(Debug, Clone, Copy, PartialEq)] pub enum ColorChannel { Red, Green, Blue, UV, IR }
#[derive(Debug, Clone)] pub struct PrismShard { pub channel: ColorChannel, pub seq: usize, pub total: usize, pub data: Vec<u8> }
pub struct PrismSplitter;
impl PrismSplitter {
pub fn split(payload: &[u8], channels: &[ColorChannel]) -> Result<Vec<PrismShard>, PrismError> {
if channels.is_empty() { return Err(PrismError::InvalidShard("No channels".into())); }
let n = channels.len();
let mut shards: Vec<PrismShard> = channels.iter().map(|c| PrismShard { channel: *c, seq: 0, total: n, data: Vec::new() }).collect();
for (i, byte) in payload.iter().enumerate() { shards[i % n].data.push(*byte); }
for (i, s) in shards.iter_mut().enumerate() { s.seq = i; }
Ok(shards)
}
pub fn reassemble(shards: &[PrismShard]) -> Result<Vec<u8>, PrismError> {
if shards.is_empty() { return Err(PrismError::MissingShard("Empty".into())); }
let total = shards[0].total;
if shards.len() != total { return Err(PrismError::MissingShard(format!("Got {} need {}", shards.len(), total))); }
let mut sorted: Vec<&PrismShard> = shards.iter().collect();
sorted.sort_by_key(|s| s.seq);
let max_len = sorted.iter().map(|s| s.data.len()).max().unwrap_or(0);
let mut result = Vec::new();
for i in 0..max_len { for s in &sorted { if i < s.data.len() { result.push(s.data[i]); } } }
Ok(result)
}
}
#[cfg(test)] mod tests {
use super::*;
#[test] fn test_split_reassemble() {
let data = b"Hello PrismSplit!";
let channels = vec![ColorChannel::Red, ColorChannel::Green, ColorChannel::Blue];
let shards = PrismSplitter::split(data, &channels).unwrap();
assert_eq!(shards.len(), 3);
let rebuilt = PrismSplitter::reassemble(&shards).unwrap();
assert_eq!(rebuilt, data);
}
#[test] fn test_missing_shard() { let s = vec![PrismShard { channel: ColorChannel::Red, seq: 0, total: 3, data: vec![1] }]; assert!(PrismSplitter::reassemble(&s).is_err()); }
}