sb3_decoder/decoder/
decoder_builder.rs

1//! A builder for creating a Decoder from either a file or in-memory bytes.
2//!
3//! # Example
4//! ```no_run
5//! # use sb3_decoder::prelude::*;
6//! let builder = DecoderBuilder::new()
7//!     .use_file("path/to/project.sb3");
8//!
9//! let decoder = match builder.build() {
10//!     Ok(decoder) => decoder,
11//!     Err(e) => panic!("Failed to build decoder: {}", e),
12//! };
13//! ```
14
15use std::path::PathBuf;
16
17use crate::{decoder::Decoder, error::BuilderError};
18
19/// Represents the source of the .sb3 data.
20enum Source {
21    /// No source specified.
22    None,
23
24    /// Source from a file path.
25    File(PathBuf),
26
27    /// Source from in-memory bytes.
28    Memory(Vec<u8>),
29}
30
31/// A builder for creating a [`Decoder`] from either a file or in-memory bytes.
32///
33/// # Example
34/// ```no_run
35/// # use sb3_decoder::prelude::*;
36/// let builder = DecoderBuilder::new()
37///     .use_file("path/to/project.sb3");
38///
39/// let decoder = match builder.build() {
40///     Ok(decoder) => decoder,
41///     Err(e) => panic!("Failed to build decoder: {}", e),
42/// };
43/// ```
44pub struct DecoderBuilder {
45    source: Source,
46}
47
48impl Default for DecoderBuilder {
49    fn default() -> Self {
50        Self::new()
51    }
52}
53
54impl DecoderBuilder {
55    /// Creates a new [`DecoderBuilder`] instance with no source specified.
56    pub fn new() -> Self {
57        Self {
58            source: Source::None,
59        }
60    }
61
62    /// Specifies the source as a file path.
63    ///
64    /// # Example
65    /// ```no_run
66    /// # use sb3_decoder::prelude::*;
67    /// let builder = DecoderBuilder::new()
68    ///     .use_file("path/to/project.sb3");
69    /// ```
70    pub fn use_file(mut self, path: impl Into<PathBuf>) -> Self {
71        self.source = Source::File(path.into());
72        self
73    }
74
75    /// Specifies the source as in-memory bytes.
76    ///
77    /// # Example
78    /// ```no_run
79    /// # use sb3_decoder::prelude::*;
80    /// let builder = DecoderBuilder::new()
81    /// #   .use_bytes(&[]); /*
82    ///     .use_bytes(include_bytes!("path/to/project.sb3"));
83    /// # */
84    /// ```
85    pub fn use_bytes(mut self, bytes: &[u8]) -> Self {
86        self.source = Source::Memory(bytes.to_vec());
87        self
88    }
89
90    /// Builds the [`Decoder`] from the specified source.
91    ///
92    /// # Example
93    /// ```no_run
94    /// # use sb3_decoder::prelude::*;
95    /// # let builder = DecoderBuilder::new()
96    /// #     .use_file("path/to/project.sb3");
97    /// let decoder = match builder.build() {
98    ///   Ok(decoder) => decoder,
99    ///   Err(e) => panic!("Failed to build decoder: {}", e),
100    /// };
101    /// ```
102    ///
103    /// # Errors
104    /// Returns [`BuilderError::FileRead`] if there is an error reading the file.  
105    /// Returns [`BuilderError::NoSource`] if no source was specified.  
106    /// Returns [`BuilderError::Decode`] if there is an error creating the decoder.
107    pub fn build(self) -> Result<Decoder, BuilderError> {
108        let bytes = match self.source {
109            Source::File(path) => std::fs::read(path)?,
110            Source::Memory(data) => data,
111            Source::None => return Err(BuilderError::NoSource),
112        };
113
114        Ok(Decoder::new(bytes)?)
115    }
116}