use serde::Serialize;
use super::Gen4;
use crate::games::{Game, GameId, json};
use crate::io::ByteSource;
use crate::{Error, Result};
const TABLES: [&str; 3] = ["species.json", "moves.json", "abilities.json"];
#[derive(Serialize)]
struct TextBank {
bank: usize,
name: Option<&'static str>,
messages: Vec<String>,
}
fn bank_stem(bank: usize, name: Option<&str>) -> String {
name.map_or_else(|| format!("{bank:04}"), str::to_owned)
}
impl<S: ByteSource> Game for Gen4<S> {
fn id(&self) -> GameId {
self.game
}
fn assets(&self) -> Result<Vec<String>> {
let text = self.text()?;
let banks =
(0..text.len()).map(|bank| format!("text/{}.json", bank_stem(bank, text.name(bank))));
let tables = TABLES.into_iter().map(str::to_owned);
let field = self.field_assets()?;
Ok(tables
.chain(banks)
.chain(self.sprite_assets()?)
.chain(field)
.chain(self.sound_assets()?)
.collect())
}
fn extract(&self, path: &str) -> Result<Vec<u8>> {
if let Some(asset) = self.extract_field(path) {
return asset;
}
match path {
"species.json" => json(self.species()?),
"moves.json" => json(self.moves()?),
"abilities.json" => json(self.abilities()?),
_ if path.starts_with("sprites/") => self.extract_sprite(path),
_ if path.starts_with("sound/") => self.extract_sound(path),
_ => {
let text = self.text()?;
let stem = path
.strip_prefix("text/")
.and_then(|file| file.strip_suffix(".json"));
let bank = stem
.and_then(|stem| text.find(stem).or_else(|| stem.parse().ok()))
.filter(|&bank| bank < text.len())
.ok_or_else(|| Error::NotFound(path.to_owned()))?;
json(&TextBank {
bank,
name: text.name(bank),
messages: text
.bank(bank)?
.iter()
.map(|message| message.markup())
.collect(),
})
}
}
}
}