pgs 0.1.0

A library for structuring save files from the Birdiesoft classic game Pokémon Simulator.
Documentation
//! A library for structuring save files from the Birdiesoft classic game [Pokémon Simulator](http://birdiesoft.dk/software.php?id=2).
//!
//! All of the information in this has been reverse engineered. It only handles version 2 of the PGS (PokeGameSave) format and will panic if it tries to do version 1 or any other file.
//!
//! This library doesn't try to do any verification of your data, so you should look at the doumentation of this library to see what the valid details should be.

/// A structure for pokemon data.
///
/// Maximum values:
/// * `pokedex`: 386
/// * `level`: 100
#[derive(Debug)]
pub struct Pokemon {
	pub pokedex: u16,
	pub level: u8,
	pub experience: u32,
}

/// A structure for the PGS format.
///
/// Maximum values:
/// * `leaders_beaten`: 25
///
/// Required lengths:
/// * `beaten_flags`: 5
/// * `pokedex`: 386
/// * `items`: 6
///
/// Maximum lengths:
/// * `pokemon`: 10,000
#[derive(Debug)]
pub struct PGSv2 {
	pub name: String,
	pub beaten_flags: Vec<bool>,
	pub leaders_beaten: u8,
	pub money: u32,
	pub wins: u32,
	pub losses: u32,
	pub fights: u32,
	pub catches: u32,
	pub items: Vec<u32>,
	pub pokedex: Vec<bool>,
	pub pokemon: Vec<Pokemon>,
}

/// Converts a borrowed string of a PGS save file (which is in plain text) to a PGSv2 structure.
///
/// Blank pokemon values in the save file will terminate the search for more pokemon and return the file. Destructure will automatically fix this and put the valid amount of padding back.
///
/// Only accepts version 2 PGS save files, those starting with `VERSION2SAVEFILEIDENTIFIER`.
pub fn structure(save: &str) -> PGSv2 {
	let y = save.to_string();
	let x = y.split("\r\n");
	let mut i = 0;
	let mut name = "".to_string();
	let mut flags: Vec<bool> = vec![];
	let mut leaders_beaten: u8 = 0;
	let mut money: u32 = 0;
	let mut wins: u32 = 0;
	let mut losses: u32 = 0;
	let mut fights: u32 = 0;
	let mut catches: u32 = 0;
	let mut items: Vec<u32> = vec![];
	let mut pokedex: Vec<bool> = vec![];
	let mut pokemon: Vec<Pokemon> = vec![];
	let mut tmpdex: u16 = 0;
	let mut tmplvl: u8 = 0;
	let mut tmpexp: u32 = 0;
	'outer: for s in x {
		if i == 0 && s != "VERSION2SAVEFILEIDENTIFIER" { panic!("Not a valid save file!"); }
		if i == 1 { name = s.to_string(); }
		if i >= 2 && 6 >= i {
			if s == "TRUE".to_string() {
				flags.push(true);
			} else {
				flags.push(false);
			}
		}
		if i == 7 { leaders_beaten = s.parse::<u8>().unwrap(); }
		if i == 8 { money = s.parse::<u32>().unwrap(); }
		if i == 9 { wins = s.parse::<u32>().unwrap(); }
		if i == 10 { losses = s.parse::<u32>().unwrap(); }
		if i == 11 { fights = s.parse::<u32>().unwrap(); }
		if i == 12 { catches = s.parse::<u32>().unwrap(); }
		if i >= 13 && 18 >= i {
			let val = s.parse::<u32>().unwrap();
			items.push(val);
		}
		if i >= 19 && 404 >= i {
			if s == "TRUE".to_string() {
				pokedex.push(true);
			} else {
				pokedex.push(false);
			}
		}
		if i > 404 {
			if tmpdex == 0 {
				tmpdex = s.parse::<u16>().unwrap();
				if tmpdex == 0 {
					break 'outer;
				}
			} else if tmplvl == 0 {
				tmplvl = s.parse::<u8>().unwrap();
			} else if tmpexp == 0 {
				tmpexp = s.parse::<u32>().unwrap();
				let pkmn = Pokemon { pokedex: tmpdex, level: tmplvl, experience: tmpexp };
				tmpdex = 0;
				tmplvl = 0;
				tmpexp = 0;
				pokemon.push(pkmn);
			}
		}
		i = i + 1;
	}
	let pgs = PGSv2 { name: name, beaten_flags: flags, leaders_beaten: leaders_beaten, money: money, wins: wins, losses: losses, fights: fights, catches: catches, items: items, pokedex: pokedex, pokemon: pokemon };
	return pgs
}

fn append(x: String, y: String) -> String {
	let z = format!("{}{}\r\n", x, y);
	return z
}

/// Turns a PGSv2 structure back into a String.
///
/// Useful for destructuring a modified save and then saving it to a .pgs file.
pub fn destructure(pgs: PGSv2) -> String {
	let mut x = "VERSION2SAVEFILEIDENTIFIER\r\n".to_string();
	let mut a = 0;
	x = append(x, pgs.name);
	for flag in pgs.beaten_flags {
		let y;
		if flag == false {
			y = "FALSE".to_string();
		} else {
			y = "TRUE".to_string();
		}
		x = append(x, y);
	}
	x = append(x, pgs.leaders_beaten.to_string());
	x = append(x, pgs.money.to_string());
	x = append(x, pgs.wins.to_string());
	x = append(x, pgs.losses.to_string());
	x = append(x, pgs.fights.to_string());
	x = append(x, pgs.catches.to_string());
	for item in pgs.items {
		x = append(x, item.to_string());
	}
	for pokex in pgs.pokedex {
		let y;
		if pokex == false {
			y = "FALSE".to_string();
		} else {
			y = "TRUE".to_string();
		}
		x = append(x, y);
	}
	for pkmn in pgs.pokemon {
		x = append(x, pkmn.pokedex.to_string());
		x = append(x, pkmn.level.to_string());
		x = append(x, pkmn.experience.to_string());
	}
	let a = x.to_owned();
	let z = a.split("\r\n");
	let y: Vec<&str> = z.collect();
	let mut i: i64 = 30404 - y.len() as i64;
	while i > 0 {
		x = append(x, "0\r\n0\r\n0".to_string());
		i = i - 3;
	}
	return x
}