Skip to main content

assetpack_core/
transform.rs

1use std::{collections::HashMap, fmt, io, sync::Arc};
2
3use crate::{Error, Result};
4
5pub const TRANSFORM_ID_NONE: u16 = 0;
6pub const TRANSFORM_ID_PRECOMP2: u16 = 1;
7pub const TRANSFORM_ID_PRECOMP2_ZSTD: u16 = 2;
8pub const TRANSFORM_ID_PRECOMP2_LZMA: u16 = 3;
9pub const TRANSFORM_VERSION_NONE: u16 = 0;
10pub const TRANSFORM_VERSION_PRECOMP2: u16 = 1;
11pub const TRANSFORM_VERSION_PRECOMP2_ZSTD: u16 = 1;
12pub const TRANSFORM_VERSION_PRECOMP2_LZMA: u16 = 1;
13
14pub trait TransformDecoder: Send + Sync {
15  fn id(&self) -> u16;
16  fn version(&self) -> u16;
17  fn decode(&self, input: &mut dyn io::BufRead, output: &mut dyn io::Write) -> Result<()>;
18}
19
20struct NoneDecoder;
21
22impl TransformDecoder for NoneDecoder {
23  fn id(&self) -> u16 {
24    TRANSFORM_ID_NONE
25  }
26
27  fn version(&self) -> u16 {
28    TRANSFORM_VERSION_NONE
29  }
30
31  fn decode(&self, input: &mut dyn io::BufRead, output: &mut dyn io::Write) -> Result<()> {
32    io::copy(input, output)?;
33    Ok(())
34  }
35}
36
37#[derive(Clone)]
38pub struct TransformDecoderRegistry {
39  decoders: HashMap<(u16, u16), Arc<dyn TransformDecoder>>,
40}
41
42impl TransformDecoderRegistry {
43  pub fn new(decoders: impl IntoIterator<Item = Arc<dyn TransformDecoder>>) -> Result<Self> {
44    let mut registry = Self { decoders: HashMap::new() };
45    registry.insert(Arc::new(NoneDecoder))?;
46    for decoder in decoders {
47      registry.insert(decoder)?;
48    }
49    Ok(registry)
50  }
51
52  fn insert(&mut self, decoder: Arc<dyn TransformDecoder>) -> Result<()> {
53    let key = (decoder.id(), decoder.version());
54    if self.decoders.insert(key, decoder).is_some() {
55      return Err(Error::DuplicateTransformDecoder { id: key.0, version: key.1 });
56    }
57    Ok(())
58  }
59
60  pub fn get(&self, id: u16, version: u16) -> Result<&dyn TransformDecoder> {
61    self
62      .decoders
63      .get(&(id, version))
64      .map(Arc::as_ref)
65      .ok_or(Error::UnsupportedTransform { id, version })
66  }
67}
68
69impl Default for TransformDecoderRegistry {
70  fn default() -> Self {
71    Self::new([]).expect("the built-in NONE decoder is unique")
72  }
73}
74
75impl fmt::Debug for TransformDecoderRegistry {
76  fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
77    let mut keys = self.decoders.keys().copied().collect::<Vec<_>>();
78    keys.sort_unstable();
79    formatter
80      .debug_struct("TransformDecoderRegistry")
81      .field("transform_versions", &keys)
82      .finish()
83  }
84}
85
86#[cfg(test)]
87mod tests {
88  use std::io::{BufRead, Write};
89
90  use super::*;
91
92  struct TestDecoder(u16, u16);
93
94  impl TransformDecoder for TestDecoder {
95    fn id(&self) -> u16 {
96      self.0
97    }
98
99    fn version(&self) -> u16 {
100      self.1
101    }
102
103    fn decode(&self, _input: &mut dyn BufRead, _output: &mut dyn Write) -> Result<()> {
104      Ok(())
105    }
106  }
107
108  #[test]
109  fn lookup_uses_exact_id_and_version() {
110    let registry = TransformDecoderRegistry::new([Arc::new(TestDecoder(7, 3)) as Arc<dyn TransformDecoder>]).unwrap();
111    assert_eq!((registry.get(0, 0).unwrap().id(), registry.get(0, 0).unwrap().version()), (0, 0));
112    assert_eq!((registry.get(7, 3).unwrap().id(), registry.get(7, 3).unwrap().version()), (7, 3));
113    for (id, version) in [(8, 3), (7, 4)] {
114      assert!(matches!(
115        registry.get(id, version),
116        Err(Error::UnsupportedTransform { id: actual_id, version: actual_version })
117          if actual_id == id && actual_version == version
118      ));
119    }
120  }
121
122  #[test]
123  fn duplicate_pairs_are_rejected() {
124    let result = TransformDecoderRegistry::new([
125      Arc::new(TestDecoder(7, 3)) as Arc<dyn TransformDecoder>,
126      Arc::new(TestDecoder(7, 3)) as Arc<dyn TransformDecoder>,
127    ]);
128    assert!(matches!(result, Err(Error::DuplicateTransformDecoder { id: 7, version: 3 })));
129  }
130}