Skip to main content

ppt_rs/parts/
base.rs

1//! Base part trait and types
2//!
3//! Defines the common interface for all package parts.
4
5use crate::exc::PptxError;
6
7/// Content types for package parts
8#[derive(Debug, Clone, PartialEq)]
9pub enum ContentType {
10    Presentation,
11    Slide,
12    SlideLayout,
13    SlideMaster,
14    Theme,
15    NotesSlide,
16    NotesMaster,
17    Image(String), // format: png, jpeg, gif, etc.
18    Media(String), // format: mp4, mp3, etc.
19    Chart,
20    Table,
21    CoreProperties,
22    ExtendedProperties,
23    ContentTypes,
24    Relationships,
25    Xml,
26}
27
28impl ContentType {
29    /// Get the MIME type string
30    pub fn mime_type(&self) -> &'static str {
31        match self {
32            ContentType::Presentation => {
33                "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"
34            }
35            ContentType::Slide => {
36                "application/vnd.openxmlformats-officedocument.presentationml.slide+xml"
37            }
38            ContentType::SlideLayout => {
39                "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"
40            }
41            ContentType::SlideMaster => {
42                "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"
43            }
44            ContentType::Theme => "application/vnd.openxmlformats-officedocument.theme+xml",
45            ContentType::NotesSlide => {
46                "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml"
47            }
48            ContentType::NotesMaster => {
49                "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml"
50            }
51            ContentType::Image(fmt) => match fmt.as_str() {
52                "png" => "image/png",
53                "jpeg" | "jpg" => "image/jpeg",
54                "gif" => "image/gif",
55                "bmp" => "image/bmp",
56                "tiff" => "image/tiff",
57                "svg" => "image/svg+xml",
58                _ => "application/octet-stream",
59            },
60            ContentType::Media(fmt) => match fmt.as_str() {
61                "mp4" => "video/mp4",
62                "webm" => "video/webm",
63                "avi" => "video/x-msvideo",
64                "wmv" => "video/x-ms-wmv",
65                "mov" => "video/quicktime",
66                "mp3" => "audio/mpeg",
67                "wav" => "audio/wav",
68                "wma" => "audio/x-ms-wma",
69                "m4a" => "audio/mp4",
70                "ogg" => "audio/ogg",
71                _ => "application/octet-stream",
72            },
73            ContentType::Chart => {
74                "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"
75            }
76            ContentType::Table => {
77                "application/vnd.openxmlformats-officedocument.drawingml.table+xml"
78            }
79            ContentType::CoreProperties => {
80                "application/vnd.openxmlformats-package.core-properties+xml"
81            }
82            ContentType::ExtendedProperties => {
83                "application/vnd.openxmlformats-officedocument.extended-properties+xml"
84            }
85            ContentType::ContentTypes => "application/vnd.openxmlformats-package.content-types+xml",
86            ContentType::Relationships => {
87                "application/vnd.openxmlformats-package.relationships+xml"
88            }
89            ContentType::Xml => "application/xml",
90        }
91    }
92}
93
94/// Part types in a PPTX package
95#[derive(Debug, Clone, Copy, PartialEq)]
96pub enum PartType {
97    Presentation,
98    Slide,
99    SlideLayout,
100    SlideMaster,
101    Theme,
102    NotesSlide,
103    NotesMaster,
104    Image,
105    Media,
106    Chart,
107    Table,
108    CoreProperties,
109    ExtendedProperties,
110    ContentTypes,
111    Relationships,
112}
113
114impl PartType {
115    /// Get the relationship type URI
116    pub fn relationship_type(&self) -> &'static str {
117        match self {
118            PartType::Presentation => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
119            PartType::Slide => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide",
120            PartType::SlideLayout => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout",
121            PartType::SlideMaster => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster",
122            PartType::Theme => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
123            PartType::NotesSlide => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide",
124            PartType::NotesMaster => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster",
125            PartType::Image => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
126            PartType::Media => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/media",
127            PartType::Chart => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
128            PartType::Table => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table",
129            PartType::CoreProperties => "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
130            PartType::ExtendedProperties => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
131            PartType::ContentTypes => "http://schemas.openxmlformats.org/package/2006/content-types",
132            PartType::Relationships => "http://schemas.openxmlformats.org/package/2006/relationships",
133        }
134    }
135}
136
137/// Trait for package parts
138pub trait Part {
139    /// Get the part path within the package
140    fn path(&self) -> &str;
141
142    /// Get the part type
143    fn part_type(&self) -> PartType;
144
145    /// Get the content type
146    fn content_type(&self) -> ContentType;
147
148    /// Generate XML content for this part
149    fn to_xml(&self) -> Result<String, PptxError>;
150
151    /// Parse XML content into this part
152    fn from_xml(xml: &str) -> Result<Self, PptxError>
153    where
154        Self: Sized;
155}
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160
161    #[test]
162    fn test_content_type_mime() {
163        assert_eq!(
164            ContentType::Slide.mime_type(),
165            "application/vnd.openxmlformats-officedocument.presentationml.slide+xml"
166        );
167        assert_eq!(
168            ContentType::Image("png".to_string()).mime_type(),
169            "image/png"
170        );
171        assert_eq!(
172            ContentType::Image("jpeg".to_string()).mime_type(),
173            "image/jpeg"
174        );
175    }
176
177    #[test]
178    fn test_part_type_relationship() {
179        assert!(PartType::Slide.relationship_type().contains("/slide"));
180        assert!(PartType::Image.relationship_type().contains("/image"));
181    }
182}