omf/omf1/
converter.rs

1use std::io::{Read, Seek, Write};
2
3use crate::{
4    error::Error,
5    file::{Compression, Limits, ReadAt},
6    validate::Problems,
7};
8
9use super::reader::Omf1Reader;
10
11/// Returns true if the file looks more like OMF1 than OMF2.
12///
13/// Does not guarantee that the file will load. Returns an error in file read fails.
14pub fn detect(read: &mut impl Read) -> Result<bool, Error> {
15    const PREFIX: [u8; 8] = [0x84, 0x83, 0x82, 0x81, b'O', b'M', b'F', b'-'];
16    let mut prefix = [0; PREFIX.len()];
17    read.read_exact(&mut prefix)?;
18    Ok(prefix == PREFIX)
19}
20
21/// Returns true if the path looks more like OMF1 than OMF2.
22///
23/// Does not guarantee that the file will load. Returns an error in file open or read fails.
24#[cfg(not(target_family = "wasm"))]
25pub fn detect_open(path: &std::path::Path) -> Result<bool, Error> {
26    detect(&mut std::fs::File::open(path)?)
27}
28
29/// Converts a OMF1 files to OMF2.
30///
31/// This object allows you to set up the desired parameters then convert one or more files.
32#[derive(Debug, Default)]
33pub struct Converter {
34    limits: Limits,
35    compression: Compression,
36}
37
38impl Converter {
39    /// Creates a new default converter.
40    pub fn new() -> Self {
41        Self::default()
42    }
43
44    /// Returns the current limits.
45    pub fn limits(&self) -> Limits {
46        self.limits
47    }
48
49    /// Set the limits to use during conversion.
50    pub fn set_limits(&mut self, limits: Limits) {
51        self.limits = limits;
52    }
53
54    /// Returns the current compression level.
55    pub fn compression(&self) -> Compression {
56        self.compression
57    }
58
59    /// Set the compression level to use when writing.
60    pub fn set_compression(&mut self, compression: Compression) {
61        self.compression = compression;
62    }
63
64    /// Runs a conversion from one open file to another file.
65    ///
66    /// `input` must support read and seek, while `output` must support write.
67    /// On success the validation warnings are returned.
68    ///
69    /// May be called more than once to convert multiple files with the same parameters.
70    pub fn convert(
71        &self,
72        input: impl ReadAt + 'static,
73        output: impl Write + Seek + Send,
74    ) -> Result<Problems, Error> {
75        let reader = Omf1Reader::new(input, self.limits.json_bytes)?;
76        let mut writer = crate::file::Writer::new(output)?;
77        writer.set_compression(self.compression);
78        let project = reader.project()?.convert(&reader, &mut writer)?;
79        writer.finish(project).map(|(_, p)| p)
80    }
81
82    /// Runs a conversion from one filename to another.
83    ///
84    /// The output file will be created if it does not exist, and truncated if it does.
85    /// On success the validation warnings are returned.
86    ///
87    /// May be called more than once to convert multiple files with the same parameters.
88    #[cfg(not(target_family = "wasm"))]
89    pub fn convert_open(
90        &self,
91        input_path: impl AsRef<std::path::Path>,
92        output_path: impl AsRef<std::path::Path>,
93    ) -> Result<Problems, Error> {
94        let input = std::fs::File::open(input_path)?;
95        let output = std::fs::OpenOptions::new()
96            .write(true)
97            .create(true)
98            .truncate(true)
99            .open(output_path)?;
100        self.convert(input, output)
101    }
102}