Skip to main content

oxihuman_export/
pdf_metadata_export.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! PDF metadata struct (no rendering, just metadata).
6
7#[derive(Debug, Clone)]
8pub struct PdfMetadata {
9    pub title: String,
10    pub author: String,
11    pub subject: String,
12    pub keywords: Vec<String>,
13    pub creator: String,
14    pub producer: String,
15    pub creation_date: String,
16    pub page_count: usize,
17}
18
19pub fn new_pdf_metadata(title: &str, author: &str) -> PdfMetadata {
20    PdfMetadata {
21        title: title.to_string(),
22        author: author.to_string(),
23        subject: String::new(),
24        keywords: Vec::new(),
25        creator: "OxiHuman".to_string(),
26        producer: "OxiHuman PDF".to_string(),
27        creation_date: String::new(),
28        page_count: 1,
29    }
30}
31
32pub fn pdf_add_keyword(meta: &mut PdfMetadata, kw: &str) {
33    meta.keywords.push(kw.to_string());
34}
35
36pub fn pdf_set_subject(meta: &mut PdfMetadata, subject: &str) {
37    meta.subject = subject.to_string();
38}
39
40pub fn pdf_set_page_count(meta: &mut PdfMetadata, n: usize) {
41    meta.page_count = n;
42}
43
44pub fn pdf_metadata_to_xmp(meta: &PdfMetadata) -> String {
45    format!(
46        "<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>\n\
47         <x:xmpmeta xmlns:x='adobe:ns:meta/'>\n\
48           <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n\
49             <rdf:Description>\n\
50               <dc:title>{}</dc:title>\n\
51               <dc:creator>{}</dc:creator>\n\
52             </rdf:Description>\n\
53           </rdf:RDF>\n\
54         </x:xmpmeta>\n\
55         <?xpacket end='w'?>",
56        meta.title, meta.author
57    )
58}
59
60pub fn pdf_metadata_to_info_dict(meta: &PdfMetadata) -> String {
61    format!(
62        "/Title ({})\n/Author ({})\n/Subject ({})\n/Keywords ({})\n/Creator ({})\n/Producer ({})",
63        meta.title,
64        meta.author,
65        meta.subject,
66        meta.keywords.join(", "),
67        meta.creator,
68        meta.producer
69    )
70}
71
72pub fn validate_pdf_metadata(meta: &PdfMetadata) -> bool {
73    !meta.title.is_empty() && !meta.author.is_empty() && meta.page_count > 0
74}
75
76pub fn pdf_keyword_count(meta: &PdfMetadata) -> usize {
77    meta.keywords.len()
78}
79
80pub fn default_pdf_metadata_for_body_report() -> PdfMetadata {
81    let mut m = new_pdf_metadata("Body Measurement Report", "OxiHuman");
82    pdf_set_subject(&mut m, "Human body measurements");
83    pdf_add_keyword(&mut m, "body");
84    pdf_add_keyword(&mut m, "measurement");
85    m
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_new_pdf_metadata() {
94        let m = new_pdf_metadata("T", "A");
95        assert_eq!(m.title, "T");
96        assert_eq!(m.author, "A");
97    }
98
99    #[test]
100    fn test_pdf_add_keyword() {
101        let mut m = new_pdf_metadata("T", "A");
102        pdf_add_keyword(&mut m, "kw");
103        assert_eq!(pdf_keyword_count(&m), 1);
104    }
105
106    #[test]
107    fn test_validate_pdf_metadata() {
108        let m = new_pdf_metadata("T", "A");
109        assert!(validate_pdf_metadata(&m));
110    }
111
112    #[test]
113    fn test_validate_empty_title_fails() {
114        let m = new_pdf_metadata("", "A");
115        assert!(!validate_pdf_metadata(&m));
116    }
117
118    #[test]
119    fn test_pdf_metadata_to_xmp() {
120        let m = new_pdf_metadata("Title", "Author");
121        let xmp = pdf_metadata_to_xmp(&m);
122        assert!(xmp.contains("Title"));
123    }
124
125    #[test]
126    fn test_pdf_metadata_to_info_dict() {
127        let m = new_pdf_metadata("T", "A");
128        let info = pdf_metadata_to_info_dict(&m);
129        assert!(info.contains("/Title"));
130    }
131
132    #[test]
133    fn test_pdf_set_page_count() {
134        let mut m = new_pdf_metadata("T", "A");
135        pdf_set_page_count(&mut m, 5);
136        assert_eq!(m.page_count, 5);
137    }
138
139    #[test]
140    fn test_default_pdf_metadata() {
141        let m = default_pdf_metadata_for_body_report();
142        assert!(pdf_keyword_count(&m) >= 2);
143    }
144}