Skip to main content

par2_rs/packet/
creator.rs

1use crate::error::{Par2Error, Result};
2
3const MAX_CREATOR_BYTES: usize = 100_000;
4
5/// Parsed Creator packet.
6///
7/// Contains an ASCII string identifying the application that created the PAR2 set.
8#[derive(Debug, Clone)]
9pub struct CreatorPacket {
10    /// The creator application identifier.
11    pub creator_id: String,
12}
13
14impl CreatorPacket {
15    /// Parse a Creator packet from its body (after the 64-byte header).
16    pub fn parse(body: &[u8]) -> Result<Self> {
17        if body.is_empty() {
18            return Err(Par2Error::InvalidCreatorPacket {
19                reason: "creator packet is empty".to_string(),
20            });
21        }
22        if body.len() > MAX_CREATOR_BYTES {
23            return Err(Par2Error::InvalidCreatorPacket {
24                reason: format!("creator payload too large: {} bytes", body.len()),
25            });
26        }
27        // Strip null padding from the end
28        let end = body.iter().position(|&b| b == 0).unwrap_or(body.len());
29        let creator_id = String::from_utf8_lossy(&body[..end]).into_owned();
30        Ok(CreatorPacket { creator_id })
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37
38    #[test]
39    fn parse_creator_with_null_padding() {
40        let body = b"par2cmdline version 0.8.1\x00\x00\x00";
41        let pkt = CreatorPacket::parse(body).unwrap();
42        assert_eq!(pkt.creator_id, "par2cmdline version 0.8.1");
43    }
44
45    #[test]
46    fn parse_creator_no_padding() {
47        let body = b"MyApp";
48        let pkt = CreatorPacket::parse(body).unwrap();
49        assert_eq!(pkt.creator_id, "MyApp");
50    }
51
52    #[test]
53    fn reject_empty_creator() {
54        let err = CreatorPacket::parse(b"").unwrap_err();
55        assert!(matches!(err, Par2Error::InvalidCreatorPacket { .. }));
56    }
57}