Skip to main content

exiftool_rs/writer/
ps_writer.rs

1//! PostScript/EPS metadata writer.
2//! Modifies DSC comments in-place.
3
4use crate::error::{Error, Result};
5
6pub fn write_postscript(source: &[u8], changes: &[(&str, &str)]) -> Result<Vec<u8>> {
7    let mut offset = 0;
8
9    // DOS EPS binary header
10    if source.starts_with(&[0xC5, 0xD0, 0xD3, 0xC6]) && source.len() >= 12 {
11        offset = u32::from_le_bytes([source[4], source[5], source[6], source[7]]) as usize;
12    }
13
14    if offset + 4 > source.len() || (!source[offset..].starts_with(b"%!PS") && !source[offset..].starts_with(b"%!Ad")) {
15        return Err(Error::InvalidData("not a PostScript file".into()));
16    }
17
18    let text = String::from_utf8_lossy(source);
19    let mut result = text.to_string();
20
21    for &(key, value) in changes {
22        let dsc_key = match key.to_lowercase().as_str() {
23            "title" => "%%Title",
24            "creator" => "%%Creator",
25            "author" | "for" => "%%For",
26            "creationdate" | "createdate" => "%%CreationDate",
27            _ => continue,
28        };
29
30        // Find and replace existing DSC comment
31        if let Some(pos) = result.find(dsc_key) {
32            let line_end = result[pos..].find('\n').unwrap_or(result.len() - pos);
33            let old_line = &result[pos..pos + line_end];
34            let new_line = format!("{}: ({})", dsc_key, value);
35            result = result.replacen(old_line, &new_line, 1);
36        }
37    }
38
39    Ok(result.into_bytes())
40}