Skip to main content

hadris_cd/
options.rs

1//! Configuration options for hybrid CD/DVD image creation
2
3use hadris_iso::boot::options::BootOptions;
4use 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 CdOptions {
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 CdOptions {
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 CdOptions {
40    /// Create options with a volume ID
41    pub fn with_volume_id(volume_id: impl Into<String>) -> Self {
42        Self {
43            volume_id: volume_id.into(),
44            ..Default::default()
45        }
46    }
47
48    /// Set the volume ID
49    pub fn volume_id(mut self, id: impl Into<String>) -> Self {
50        self.volume_id = id.into();
51        self
52    }
53
54    /// Enable Joliet support (Windows long filenames)
55    pub fn with_joliet(mut self) -> Self {
56        self.iso.joliet = Some(JolietLevel::Level3);
57        self
58    }
59
60    /// Enable Rock Ridge support (POSIX filenames and permissions)
61    pub fn with_rock_ridge(mut self) -> Self {
62        self.iso.rock_ridge = Some(RripOptions::default());
63        self
64    }
65
66    /// Set boot options
67    pub fn with_boot(mut self, boot: BootOptions) -> Self {
68        self.boot = Some(boot);
69        self
70    }
71
72    /// Set hybrid boot options (for USB booting)
73    pub fn with_hybrid_boot(mut self, hybrid: HybridBootOptions) -> Self {
74        self.hybrid_boot = Some(hybrid);
75        self
76    }
77
78    /// Disable UDF (create ISO-only image)
79    pub fn iso_only(mut self) -> Self {
80        self.udf.enabled = false;
81        self
82    }
83
84    /// Disable ISO (create UDF-only image)
85    pub fn udf_only(mut self) -> Self {
86        self.iso.enabled = false;
87        self
88    }
89}
90
91/// ISO 9660 specific options
92#[derive(Debug, Clone)]
93pub struct IsoOptions {
94    /// Enable ISO 9660 (default: true)
95    pub enabled: bool,
96    /// Base ISO level (L1 = 8.3, L2 = 30 chars)
97    pub level: BaseIsoLevel,
98    /// Enable ISO 9660:1999 (Level 3, long filenames)
99    pub long_filenames: bool,
100    /// Joliet extension (Windows long filenames)
101    pub joliet: Option<JolietLevel>,
102    /// Rock Ridge extension (POSIX attributes)
103    pub rock_ridge: Option<RripOptions>,
104}
105
106impl Default for IsoOptions {
107    fn default() -> Self {
108        Self {
109            enabled: true,
110            level: BaseIsoLevel::Level2 {
111                supports_lowercase: false,
112                supports_rrip: false,
113            },
114            long_filenames: true,
115            joliet: Some(JolietLevel::Level3),
116            rock_ridge: None,
117        }
118    }
119}
120
121/// UDF specific options
122#[derive(Debug, Clone)]
123pub struct UdfOptions {
124    /// Enable UDF (default: true)
125    pub enabled: bool,
126    /// UDF revision
127    pub revision: UdfRevision,
128}
129
130impl Default for UdfOptions {
131    fn default() -> Self {
132        Self {
133            enabled: true,
134            revision: UdfRevision::V1_02,
135        }
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn test_default_options() {
145        let opts = CdOptions::default();
146        assert_eq!(opts.volume_id, "CDROM");
147        assert_eq!(opts.sector_size, 2048);
148        assert!(opts.iso.enabled);
149        assert!(opts.udf.enabled);
150    }
151
152    #[test]
153    fn test_builder_pattern() {
154        let opts = CdOptions::with_volume_id("MY_DISC")
155            .with_joliet()
156            .with_rock_ridge();
157
158        assert_eq!(opts.volume_id, "MY_DISC");
159        assert!(opts.iso.joliet.is_some());
160        assert!(opts.iso.rock_ridge.is_some());
161    }
162}