1mod decode;
2mod error;
3mod layout;
4
5pub use decode::*;
6use error::*;
7pub use layout::*;
8
9use std::collections::HashMap;
10use std::convert::TryFrom;
11use std::io::Cursor;
12
13impl TryFrom<(&ReliableCommand, &mut Cursor<&[u8]>)> for Message {
14 type Error = PhotonDecodeError;
15
16 fn try_from(message: (&ReliableCommand, &mut Cursor<&[u8]>)) -> Result<Self, Self::Error> {
17 let (command, cursor) = message;
18 let _: u8 = cursor.decode()?;
19 let msg_type: u8 = cursor.decode()?;
20 match msg_type {
21 2 => {
22 let v = cursor.decode().map_err(|e| e.extend("Request".into()))?;
23 Ok(Message::Request(v))
24 }
25 3 => {
26 let v = cursor.decode().map_err(|e| e.extend("Response".into()))?;
27 Ok(Message::Response(v))
28 }
29 4 => {
30 let v = cursor.decode().map_err(|e| e.extend("Event".into()))?;
31 Ok(Message::Event(v))
32 }
33 _ => {
34 let msg_header_len = 2;
35 cursor.set_position(cursor.position() + command.msg_len as u64 - msg_header_len);
36 Err(PhotonDecodeError::from(format!(
37 "Unknown message ({:#X})",
38 msg_type
39 )))
40 }
41 }
42 }
43}
44
45pub struct Photon {
46 fragments: HashMap<u32, Vec<ReliableFragment>>,
47}
48
49impl Photon {
50 pub fn new() -> Self {
51 Self {
52 fragments: HashMap::new(),
53 }
54 }
55
56 pub fn try_decode(
57 &mut self,
58 payload: &[u8],
59 ) -> PhotonDecodeResult<Vec<PhotonDecodeResult<Message>>> {
60 let mut cursor = Cursor::new(payload);
61 Ok(
62 (0..Decode::<PhotonHeader>::decode(&mut cursor)?.command_count)
63 .into_iter()
64 .map(|_| {
65 Decode::<Command>::decode(&mut cursor).map_or_else(
66 |e| Some(Err(e)),
67 |command| match command {
68 Command::SendReliable(c) | Command::SendUnreliable(c) => Some(
69 Message::try_from((&c, &mut cursor))
70 .map_err(|e| e.extend("SendReliable".into())),
71 ),
72 Command::SendReliableFragment(fragment) => {
73 self.fragments
74 .entry(fragment.sequence_number)
75 .or_insert(vec![])
76 .push(fragment.clone());
77 self.decode_reliable_fragment(&fragment).map(|msg| {
78 self.fragments.remove(&fragment.sequence_number).unwrap();
79 msg.map_err(|e| e.extend("Fragment".into()))
80 })
81 }
82 _ => None,
83 },
84 )
85 })
86 .filter_map(|v| v)
87 .collect(),
88 )
89 }
90
91 pub fn decode(&mut self, payload: &[u8]) -> Vec<Message> {
92 if let Ok(messages) = self.try_decode(payload) {
93 return messages.into_iter().filter_map(Result::ok).collect();
94 }
95 vec![]
96 }
97
98 fn decode_reliable_fragment(
99 &mut self,
100 fragment: &ReliableFragment,
101 ) -> Option<PhotonDecodeResult<Message>> {
102 if let Some(fragments) = self.fragments.get(&fragment.sequence_number) {
103 if fragments.len() == fragment.fragment_count as usize {
104 let mut buf = Vec::<u8>::new();
105 for fragment in fragments {
106 buf.extend(fragment.payload.iter());
107 }
108 let mut c = Cursor::new(&buf[..]);
109 return Some(Message::try_from((&fragment.reliable_command, &mut c)));
110 }
111 }
112 None
113 }
114}