assetpack_core/
transform.rs1use 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}