1use crate::error::Error;
4use crate::varint::read_varint;
5
6#[derive(Debug, Clone, PartialEq)]
8pub struct CryptoFrame {
9 pub offset: u64,
11 pub data: Vec<u8>,
13}
14
15pub fn parse_crypto_frames(decrypted: &[u8]) -> Result<Vec<CryptoFrame>, Error> {
27 let mut cursor = 0;
28 let mut frames = Vec::new();
29
30 while cursor < decrypted.len() {
31 let (frame_type, len) = read_varint(&decrypted[cursor..])?;
32 cursor += len;
33
34 match frame_type {
35 0x06 => {
36 let (offset, off_len) =
37 read_varint(decrypted.get(cursor..).ok_or(Error::TruncatedFrame {
38 offset: cursor as u64,
39 })?)?;
40 cursor += off_len;
41
42 let (length, len_len) =
43 read_varint(decrypted.get(cursor..).ok_or(Error::TruncatedFrame {
44 offset: cursor as u64,
45 })?)?;
46 cursor += len_len;
47 let length = length as usize;
48
49 if cursor + length > decrypted.len() {
50 return Err(Error::TruncatedFrame { offset });
51 }
52
53 let data = decrypted[cursor..cursor + length].to_vec();
54 frames.push(CryptoFrame { offset, data });
55 cursor += length;
56 }
57 0x00 | 0x01 => {}
58 _ => break,
59 }
60 }
61
62 Ok(frames)
63}
64
65#[must_use]
71pub fn reassemble_crypto_stream(frames: &[CryptoFrame]) -> Vec<u8> {
72 let mut sorted: Vec<&CryptoFrame> = frames.iter().collect();
73 sorted.sort_by_key(|f| f.offset);
74
75 let mut stream = Vec::new();
76 let mut next_offset: u64 = 0;
77
78 for frame in sorted {
79 if frame.offset == next_offset {
80 stream.extend_from_slice(&frame.data);
81 next_offset += frame.data.len() as u64;
82 } else if frame.offset < next_offset {
83 let skip = (next_offset - frame.offset) as usize;
84 if skip < frame.data.len() {
85 stream.extend_from_slice(&frame.data[skip..]);
86 next_offset += (frame.data.len() - skip) as u64;
87 }
88 } else {
89 break;
90 }
91 }
92
93 stream
94}