Skip to main content

hadris_cd/
options.rs

1//! Configuration options for hybrid CD/DVD image creation
2
3use hadris_iso::boot::options::BootOptions;
4pub use hadris_iso::joliet::JolietLevel;
5use hadris_iso::rrip::RripOptions;
6use hadris_iso::write::options::{BaseIsoLevel, HybridBootOptions};
7use hadris_udf::UdfRevision;
8
9/// Options for creating a hybrid ISO+UDF image
10#[derive(Debug, Clone)]
11pub struct OpticalImageOptions {
12    /// Volume identifier (used by both ISO and UDF)
13    pub volume_id: String,
14    /// Sector size (almost always 2048)
15    pub sector_size: usize,
16    /// ISO 9660 options
17    pub iso: IsoOptions,
18    /// UDF options
19    pub udf: UdfOptions,
20    /// El-Torito boot options
21    pub boot: Option<BootOptions>,
22    /// Hybrid boot options (MBR/GPT for USB booting)
23    pub hybrid_boot: Option<HybridBootOptions>,
24}
25
26impl Default for OpticalImageOptions {
27    fn default() -> Self {
28        Self {
29            volume_id: String::from("CDROM"),
30            sector_size: 2048,
31            iso: IsoOptions::default(),
32            udf: UdfOptions::default(),
33            boot: None,
34            hybrid_boot: None,
35        }
36    }
37}
38
39impl OpticalImageOptions {
40    /// Set the volume ID
41    pub fn volume_id(mut self, id: impl Into<String>) -> Self {
42        self.volume_id = id.into();
43        self
44    }
45
46    /// Set the Joliet level used for Windows-compatible long filenames.
47    pub fn joliet(mut self, level: JolietLevel) -> Self {
48        self.iso.joliet = Some(level);
49        self
50    }
51
52    /// Set Rock Ridge options.
53    pub fn rock_ridge(mut self, options: RripOptions) -> Self {
54        self.iso.rock_ridge = Some(options);
55        self
56    }
57
58    /// Set boot options.
59    pub fn boot(mut self, boot: BootOptions) -> Self {
60        self.boot = Some(boot);
61        self
62    }
63
64    /// Set hybrid boot options for USB booting.
65    pub fn hybrid_boot(mut self, hybrid: HybridBootOptions) -> Self {
66        self.hybrid_boot = Some(hybrid);
67        self
68    }
69
70    /// Disable UDF (create ISO-only image)
71    pub fn iso_only(mut self) -> Self {
72        self.udf.enabled = false;
73        self
74    }
75
76    /// Disable ISO (create UDF-only image)
77    pub fn udf_only(mut self) -> Self {
78        self.iso.enabled = false;
79        self
80    }
81}
82
83/// ISO 9660 specific options
84#[derive(Debug, Clone)]
85pub struct IsoOptions {
86    /// Enable ISO 9660 (default: true)
87    pub enabled: bool,
88    /// Base ISO level (L1 = 8.3, L2 = 30 chars)
89    pub level: BaseIsoLevel,
90    /// Enable ISO 9660:1999 (Level 3, long filenames)
91    pub long_filenames: bool,
92    /// Joliet extension (Windows long filenames)
93    pub joliet: Option<JolietLevel>,
94    /// Rock Ridge extension (POSIX attributes)
95    pub rock_ridge: Option<RripOptions>,
96}
97
98impl Default for IsoOptions {
99    fn default() -> Self {
100        Self {
101            enabled: true,
102            level: BaseIsoLevel::Level2 {
103                supports_lowercase: false,
104                supports_rrip: false,
105            },
106            long_filenames: true,
107            joliet: Some(JolietLevel::Level3),
108            rock_ridge: None,
109        }
110    }
111}
112
113/// UDF specific options
114#[derive(Debug, Clone)]
115pub struct UdfOptions {
116    /// Enable UDF (default: true)
117    pub enabled: bool,
118    /// UDF revision
119    pub revision: UdfRevision,
120}
121
122impl Default for UdfOptions {
123    fn default() -> Self {
124        Self {
125            enabled: true,
126            revision: UdfRevision::V1_02,
127        }
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134
135    #[test]
136    fn test_default_options() {
137        let opts = OpticalImageOptions::default();
138        assert_eq!(opts.volume_id, "CDROM");
139        assert_eq!(opts.sector_size, 2048);
140        assert!(opts.iso.enabled);
141        assert!(opts.udf.enabled);
142    }
143
144    #[test]
145    fn test_builder_pattern() {
146        let opts = OpticalImageOptions::default()
147            .volume_id("MY_DISC")
148            .joliet(JolietLevel::Level3)
149            .rock_ridge(RripOptions::default());
150
151        assert_eq!(opts.volume_id, "MY_DISC");
152        assert!(opts.iso.joliet.is_some());
153        assert!(opts.iso.rock_ridge.is_some());
154    }
155}