bsalib/
lib.rs

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}