pub mod float;
pub mod scramble;
mod hash;
pub(crate) mod read;
mod util;
mod write;
use byteorder::ByteOrder;
use scramble::ScrambleType;
use std::borrow::Borrow;
use std::io::{Cursor, Read, Seek, Write};
use std::ops::Range;
use crate::error::Result;
use crate::legacy::read::{LegacyBytes, LegacyReader};
use crate::legacy::write::FileWriter;
use crate::{LegacyTable, LegacyVersion};
pub(super) const HEADER_SIZE: usize = 64;
pub(super) const HEADER_SIZE_WII: usize = 32;
const COLUMN_NODE_SIZE: usize = 6;
const COLUMN_NODE_SIZE_WII: usize = 4;
pub use hash::HashTable as LegacyHashTable;
#[derive(Copy, Clone)]
pub struct LegacyWriteOptions {
pub(crate) hash_slots: usize,
pub(crate) scramble: bool,
pub(crate) scramble_key: Option<u16>,
}
#[derive(Debug)]
pub struct FileHeader {
pub table_count: usize,
file_size: usize,
table_offsets: Vec<usize>,
}
#[derive(Debug, Clone)]
pub struct TableHeader {
pub scramble_type: ScrambleType,
hashes: OffsetAndLen,
strings: OffsetAndLen,
offset_names: usize,
offset_rows: usize,
row_count: usize,
row_len: usize,
base_id: u16,
columns: Option<ColumnNodeInfo>,
}
#[derive(Debug, Clone, Copy)]
struct ColumnNodeInfo {
offset_columns: usize,
column_count: usize,
}
#[derive(Debug, Clone, Copy)]
struct OffsetAndLen {
offset: usize,
len: usize,
}
impl OffsetAndLen {
fn max_offset(&self) -> usize {
self.offset + self.len
}
fn range(&self) -> Range<usize> {
self.offset..self.offset + self.len
}
}
impl From<(usize, usize)> for OffsetAndLen {
fn from((offset, len): (usize, usize)) -> Self {
Self { offset, len }
}
}
pub fn from_reader<R: Read + Seek, E: ByteOrder>(
reader: R,
version: LegacyVersion,
) -> Result<LegacyReader<R, E>> {
LegacyReader::new(reader, version)
}
pub fn from_bytes<E: ByteOrder>(
bytes: &mut [u8],
version: LegacyVersion,
) -> Result<LegacyBytes<'_, E>> {
LegacyBytes::new(bytes, version)
}
pub fn from_bytes_copy<E: ByteOrder>(
bytes: &[u8],
version: LegacyVersion,
) -> Result<LegacyBytes<'_, E>> {
LegacyBytes::new_copy(bytes, version)
}
pub fn to_writer<'t, W: Write + Seek, E: ByteOrder + 'static>(
writer: W,
tables: impl IntoIterator<Item = impl Borrow<LegacyTable<'t>>>,
version: LegacyVersion,
) -> Result<()> {
to_writer_options::<W, E>(writer, tables, version, LegacyWriteOptions::new())
}
pub fn to_writer_options<'t, W: Write + Seek, E: ByteOrder + 'static>(
writer: W,
tables: impl IntoIterator<Item = impl Borrow<LegacyTable<'t>>>,
version: LegacyVersion,
opts: LegacyWriteOptions,
) -> Result<()> {
let mut writer = FileWriter::<W, E>::new(writer, version, opts);
writer.write_file(tables)
}
pub fn to_vec<'t, E: ByteOrder + 'static>(
tables: impl IntoIterator<Item = impl Borrow<LegacyTable<'t>>>,
version: LegacyVersion,
) -> Result<Vec<u8>> {
to_vec_options::<E>(tables, version, LegacyWriteOptions::new())
}
pub fn to_vec_options<'t, E: ByteOrder + 'static>(
tables: impl IntoIterator<Item = impl Borrow<LegacyTable<'t>>>,
version: LegacyVersion,
opts: LegacyWriteOptions,
) -> Result<Vec<u8>> {
let mut vec = Vec::new();
to_writer_options::<_, E>(Cursor::new(&mut vec), tables, version, opts)?;
Ok(vec)
}
impl LegacyWriteOptions {
pub const fn new() -> Self {
Self {
hash_slots: 61, scramble: false,
scramble_key: None, }
}
pub fn hash_slots(mut self, slots: usize) -> Self {
assert_ne!(0, slots);
self.hash_slots = slots;
self
}
pub fn scramble(mut self, scramble: bool) -> Self {
self.scramble = scramble;
self
}
pub fn scramble_key(mut self, scramble_key: u16) -> Self {
self.scramble_key = Some(scramble_key);
self
}
}
impl Default for LegacyWriteOptions {
fn default() -> Self {
Self::new()
}
}