1#![allow(incomplete_features)]
2#![feature(associated_type_defaults, wrapping_int_impl, specialization, arbitrary_enum_discriminant)]
3pub mod hash;
4pub mod archive;
5pub mod bin;
6pub mod str;
7pub mod magicnumber;
8pub mod version;
9pub mod v001;
10pub mod v10x;
11pub mod v103;
12pub mod v104;
13pub mod v105;
14
15use std::{
16 io::{Read, Seek, Write, Result, Error, ErrorKind},
17 fmt,
18};
19use thiserror::Error;
20use archive::{BsaDir, BsaFile};
21use bin::Readable;
22use version::{Version, Version10X};
23
24pub use {
25 v103::V103,
26 v104::V104,
27 v105::V105,
28};
29
30#[derive(Debug, Error)]
31#[error("Unsupported Version {0}")]
32struct UnsupportedVersion(pub Version);
33
34
35pub enum SomeBsaHeader {
36 V103(v103::Header),
37 V104(v104::Header),
38 V105(v105::Header),
39}
40impl fmt::Display for SomeBsaHeader {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 SomeBsaHeader::V103(header) => header.fmt(f),
44 SomeBsaHeader::V104(header) => header.fmt(f),
45 SomeBsaHeader::V105(header) => header.fmt(f),
46 }
47 }
48}
49
50pub enum SomeBsaReader<R> {
51 V103(v103::BsaReader<R>),
52 V104(v104::BsaReader<R>),
53 V105(v105::BsaReader<R>),
54}
55impl<R> fmt::Display for SomeBsaReader<R> {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match self {
58 SomeBsaReader::V103(bsa) => bsa.fmt(f),
59 SomeBsaReader::V104(bsa) => bsa.fmt(f),
60 SomeBsaReader::V105(bsa) => bsa.fmt(f),
61 }
62 }
63}
64impl<R: Read + Seek> SomeBsaReader<R> {
65 pub fn open(mut reader: R) -> Result<SomeBsaReader<R>> {
66 match Version::read(&mut reader, &())? {
67 Version::V10X(v) => match v {
68 Version10X::V103 => v103::BsaReader::open(reader)
69 .map(SomeBsaReader::V103),
70 Version10X::V104 => v104::BsaReader::open(reader)
71 .map(SomeBsaReader::V104),
72 Version10X::V105 => v105::BsaReader::open(reader)
73 .map(SomeBsaReader::V105),
74 },
75 v => Err(Error::new(ErrorKind::InvalidData, UnsupportedVersion(v))),
76 }
77 }
78}
79impl<R: Read + Seek> archive::BsaReader for SomeBsaReader<R> {
80 type Header = SomeBsaHeader;
81
82 fn version(&self) -> Version {
83 match self {
84 SomeBsaReader::V103(bsa) => bsa.version(),
85 SomeBsaReader::V104(bsa) => bsa.version(),
86 SomeBsaReader::V105(bsa) => bsa.version(),
87 }
88 }
89
90 fn header(&self) -> Self::Header {
91 match self {
92 SomeBsaReader::V103(bsa) => SomeBsaHeader::V103(bsa.header()),
93 SomeBsaReader::V104(bsa) => SomeBsaHeader::V104(bsa.header()),
94 SomeBsaReader::V105(bsa) => SomeBsaHeader::V105(bsa.header()),
95 }
96 }
97
98 fn read_dirs(&mut self) -> Result<Vec<BsaDir>> {
99 match self {
100 SomeBsaReader::V103(bsa) => bsa.read_dirs(),
101 SomeBsaReader::V104(bsa) => bsa.read_dirs(),
102 SomeBsaReader::V105(bsa) => bsa.read_dirs(),
103 }
104 }
105
106 fn extract<W: Write>(&mut self, file: &BsaFile, writer: W) -> Result<()> {
107 match self {
108 SomeBsaReader::V103(bsa) => bsa.extract(file, writer),
109 SomeBsaReader::V104(bsa) => bsa.extract(file, writer),
110 SomeBsaReader::V105(bsa) => bsa.extract(file, writer),
111 }
112 }
113}