use byteorder::{
BigEndian,
ReadBytesExt,
WriteBytesExt,
};
use derive_more::{
Constructor,
Display,
From,
Into,
};
use lazy_static::lazy_static;
use regex::Regex;
use serde::{
Deserialize,
Serialize,
};
use std::{
collections::HashMap,
convert::TryFrom,
error::Error,
io::Cursor,
iter::Step,
mem::replace,
ops::RangeInclusive,
};
#[derive(
Clone,
Constructor,
Copy,
Debug,
Default,
Deserialize,
Display,
Eq,
From,
Hash,
Into,
Ord,
PartialEq,
PartialOrd,
Serialize,
)]
#[display(fmt = "{}", "self.name()")]
pub struct Point(u32);
impl Point {
const ZOD: Self = Point(0);
pub fn name(self) -> String {
let low = usize::try_from(self.0 & 0xFF).unwrap();
let rest = usize::try_from(self.0 >> 8).unwrap();
match self.class() {
Galaxy => syllables::SUFFIX_STRINGS[low].to_string(),
Star => {
String::new() + syllables::PREFIX_STRINGS[rest] + syllables::SUFFIX_STRINGS[low]
}
Planet => unimplemented!("planet name obfuscation cipher not implemented"),
}
}
pub fn class(self) -> PointClass {
if self.0 <= 0x0000_00FF {
Galaxy
} else if self.0 <= 0x0000_FFFF {
Star
} else {
Planet
}
}
pub fn children(self) -> RangeInclusive<Point> {
match self.class() {
Galaxy => Point(self.0 | 0x0000_0100)..=Point(self.0 | 0x0000_FF00),
Star => Point(self.0 | 0x0001_0000)..=Point(self.0 | 0xFFFF_0000),
Planet => self..=Point(0),
}
}
pub fn parent(self) -> Option<Point> {
match self.class() {
Galaxy => None,
Star => Some(Point(self.0 & 0x0000_00FF)),
Planet => Some(Point(self.0 & 0x0000_FFFF)),
}
}
}
impl Step for Point {
fn replace_one(&mut self) -> Self {
replace(self, Point(1))
}
fn replace_zero(&mut self) -> Self {
replace(self, Point(0))
}
fn add_one(&self) -> Self {
Point(self.0 + 1)
}
fn sub_one(&self) -> Self {
Point(self.0 - 1)
}
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
end.0
.checked_sub(start.0)
.and_then(|n| usize::try_from(n).ok())
}
fn add_usize(&self, n: usize) -> Option<Self> {
u32::try_from(n)
.ok()
.and_then(|n_as_u32| self.0.checked_add(n_as_u32).map(Point))
}
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum PointClass {
Galaxy,
Star,
Planet,
}
pub use self::PointClass::{
Galaxy,
Planet,
Star,
};
impl PointClass {
pub fn all(self) -> RangeInclusive<Point> {
match self {
PointClass::Galaxy => Point(0x00)..=Point(0xFF),
PointClass::Star => Point(0x01FF)..=Point(0xFFFF),
PointClass::Planet => Point(0x0001_FFFF)..=Point(0xFFFF_FFFF),
}
}
}
#[cfg(test)]
mod tests {
use crate::PointClass::*;
#[test]
fn test() {
for star in Star.all() {
println!("{}", star);
}
assert!(false);
}
static SOME_POINT_NAMES: &[(&str, u32, &[u8])] = &[
("~zod", 0x00, &[0x00]),
("~nec", 0x00, &[0x01]),
("~lyt", 0x80, &[0x80]),
("~fes", 0xFF, &[0xFF]),
("~marzod", 0x0100, &[0x01, 0x00]),
("~wanzod", 0x0300, &[0x03, 0x00]),
("~diglyt", 0xC180, &[0xC1, 0x80]),
("~fipfes", 0xFFFF, &[0xFF, 0xFF]),
("~dapnep-ronmyl", 0x0001_0000, &[0x01, 0x00, 0x00]),
("~bisdel-dovnym", 0x0026_0300, &[0x26, 0x30, 0x00]),
("~hidlur-litbyt", 0x007A_0300, &[0x7A, 0x03, 0x00]),
("~taswen-dabmyr", 0x00FF_FFFF, &[0xFF, 0xFF, 0xFF]),
("~diglyt-ladder", 0x2072_08B6, &[0x20, 0x72, 0x08, 0xB6]),
("~dozlyt-dozzod", 0x7151_6E75, &[0x71, 0x51, 0x6E, 0x75]),
("~digmes-siglyt", 0xD319_C180, &[0xD3, 0x19, 0xC1, 0x80]),
("~dostec-risfen", 0xFFFF_FFFF, &[0xFF, 0xFF, 0xFF, 0xFF]),
];
}
pub mod syllables {
use lazy_static::lazy_static;
use std::{
collections::HashMap,
convert::TryFrom,
str,
};
lazy_static! {
pub static ref PREFIX_BYTES: [&'static [u8; 3]; 0x100] = [
b"doz", b"mar", b"bin", b"wan", b"sam", b"lit", b"sig", b"hid", b"fid", b"lis", b"sog",
b"dir", b"wac", b"sab", b"wis", b"sib", b"rig", b"sol", b"dop", b"mod", b"fog", b"lid",
b"hop", b"dar", b"dor", b"lor", b"hod", b"fol", b"rin", b"tog", b"sil", b"mir", b"hol",
b"pas", b"lac", b"rov", b"liv", b"dal", b"sat", b"lib", b"tab", b"han", b"tic", b"pid",
b"tor", b"bol", b"fos", b"dot", b"los", b"dil", b"for", b"pil", b"ram", b"tir", b"win",
b"tad", b"bic", b"dif", b"roc", b"wid", b"bis", b"das", b"mid", b"lop", b"ril", b"nar",
b"dap", b"mol", b"san", b"loc", b"nov", b"sit", b"nid", b"tip", b"sic", b"rop", b"wit",
b"nat", b"pan", b"min", b"rit", b"pod", b"mot", b"tam", b"tol", b"sav", b"pos", b"nap",
b"nop", b"som", b"fin", b"fon", b"ban", b"mor", b"wor", b"sip", b"ron", b"nor", b"bot",
b"wic", b"soc", b"wat", b"dol", b"mag", b"pic", b"dav", b"bid", b"bal", b"tim", b"tas",
b"mal", b"lig", b"siv", b"tag", b"pad", b"sal", b"div", b"dac", b"tan", b"sid", b"fab",
b"tar", b"mon", b"ran", b"nis", b"wol", b"mis", b"pal", b"las", b"dis", b"map", b"rab",
b"tob", b"rol", b"lat", b"lon", b"nod", b"nav", b"fig", b"nom", b"nib", b"pag", b"sop",
b"ral", b"bil", b"had", b"doc", b"rid", b"moc", b"pac", b"rav", b"rip", b"fal", b"tod",
b"til", b"tin", b"hap", b"mic", b"fan", b"pat", b"tac", b"lab", b"mog", b"sim", b"son",
b"pin", b"lom", b"ric", b"tap", b"fir", b"has", b"bos", b"bat", b"poc", b"hac", b"tid",
b"hav", b"sap", b"lin", b"dib", b"hos", b"dab", b"bit", b"bar", b"rac", b"par", b"lod",
b"dos", b"bor", b"toc", b"hil", b"mac", b"tom", b"dig", b"fil", b"fas", b"mit", b"hob",
b"har", b"mig", b"hin", b"rad", b"mas", b"hal", b"rag", b"lag", b"fad", b"top", b"mop",
b"hab", b"nil", b"nos", b"mil", b"fop", b"fam", b"dat", b"nol", b"din", b"hat", b"nac",
b"ris", b"fot", b"rib", b"hoc", b"nim", b"lar", b"fit", b"wal", b"rap", b"sar", b"nal",
b"mos", b"lan", b"don", b"dan", b"lad", b"dov", b"riv", b"bac", b"pol", b"lap", b"tal",
b"pit", b"nam", b"bon", b"ros", b"ton", b"fod", b"pon", b"sov", b"noc", b"sor", b"lav",
b"mat", b"mip", b"fip",
];
pub static ref SUFFIX_BYTES: [&'static [u8; 3]; 0x100] = [
b"zod", b"nec", b"bud", b"wes", b"sev", b"per", b"sut", b"let", b"ful", b"pen", b"syt",
b"dur", b"wep", b"ser", b"wyl", b"sun", b"ryp", b"syx", b"dyr", b"nup", b"heb", b"peg",
b"lup", b"dep", b"dys", b"put", b"lug", b"hec", b"ryt", b"tyv", b"syd", b"nex", b"lun",
b"mep", b"lut", b"sep", b"pes", b"del", b"sul", b"ped", b"tem", b"led", b"tul", b"met",
b"wen", b"byn", b"hex", b"feb", b"pyl", b"dul", b"het", b"mev", b"rut", b"tyl", b"wyd",
b"tep", b"bes", b"dex", b"sef", b"wyc", b"bur", b"der", b"nep", b"pur", b"rys", b"reb",
b"den", b"nut", b"sub", b"pet", b"rul", b"syn", b"reg", b"tyd", b"sup", b"sem", b"wyn",
b"rec", b"meg", b"net", b"sec", b"mul", b"nym", b"tev", b"web", b"sum", b"mut", b"nyx",
b"rex", b"teb", b"fus", b"hep", b"ben", b"mus", b"wyx", b"sym", b"sel", b"ruc", b"dec",
b"wex", b"syr", b"wet", b"dyl", b"myn", b"mes", b"det", b"bet", b"bel", b"tux", b"tug",
b"myr", b"pel", b"syp", b"ter", b"meb", b"set", b"dut", b"deg", b"tex", b"sur", b"fel",
b"tud", b"nux", b"rux", b"ren", b"wyt", b"nub", b"med", b"lyt", b"dus", b"neb", b"rum",
b"tyn", b"seg", b"lyx", b"pun", b"res", b"red", b"fun", b"rev", b"ref", b"mec", b"ted",
b"rus", b"bex", b"leb", b"dux", b"ryn", b"num", b"pyx", b"ryg", b"ryx", b"fep", b"tyr",
b"tus", b"tyc", b"leg", b"nem", b"fer", b"mer", b"ten", b"lus", b"nus", b"syl", b"tec",
b"mex", b"pub", b"rym", b"tuc", b"fyl", b"lep", b"deb", b"ber", b"mug", b"hut", b"tun",
b"byl", b"sud", b"pem", b"dev", b"lur", b"def", b"bus", b"bep", b"run", b"mel", b"pex",
b"dyt", b"byt", b"typ", b"lev", b"myl", b"wed", b"duc", b"fur", b"fex", b"nul", b"luc",
b"len", b"ner", b"lex", b"rup", b"ned", b"lec", b"ryd", b"lyd", b"fen", b"wel", b"nyd",
b"hus", b"rel", b"rud", b"nes", b"hes", b"fet", b"des", b"ret", b"dun", b"ler", b"nyr",
b"seb", b"hul", b"ryl", b"lud", b"rem", b"lys", b"fyn", b"wer", b"ryc", b"sug", b"nys",
b"nyl", b"lyn", b"dyn", b"dem", b"lux", b"fed", b"sed", b"bec", b"mun", b"lyr", b"tes",
b"mud", b"nyt", b"byr", b"sen", b"weg", b"fyr", b"mur", b"tel", b"rep", b"teg", b"pec",
b"nel", b"nev", b"fes",
];
pub static ref PREFIX_BYTES_MAP: HashMap<&'static [u8; 3], u8> = {
let mut map = HashMap::<&'static [u8; 3], u8>::with_capacity(0x100);
for (i, bytes) in PREFIX_BYTES.iter().enumerate() {
map.insert(bytes, u8::try_from(i).unwrap());
}
map
};
pub static ref SUFFIX_BYTES_MAP: HashMap<&'static [u8; 3], u8> = {
let mut map = HashMap::<&'static [u8; 3], u8>::with_capacity(0x100);
for (i, bytes) in SUFFIX_BYTES.iter().enumerate() {
map.insert(bytes, u8::try_from(i).unwrap());
}
map
};
pub static ref BYTES_MAP: HashMap<&'static [u8; 3], u8> = {
let mut map = HashMap::<&'static [u8; 3], u8>::with_capacity(0x200);
map.extend(PREFIX_BYTES_MAP.iter());
map.extend(SUFFIX_BYTES_MAP.iter());
map
};
pub static ref PREFIX_STRINGS: [&'static str; 0x100] = {
let mut strings = [""; 0x100];
for (i, bytes) in PREFIX_BYTES.iter().enumerate() {
strings[i] = unsafe { str::from_utf8_unchecked(*bytes) };
}
strings
};
pub static ref SUFFIX_STRINGS: [&'static str; 0x100] = {
let mut strings = [""; 0x100];
for (i, bytes) in SUFFIX_BYTES.iter().enumerate() {
strings[i] = unsafe { str::from_utf8_unchecked(*bytes) };
}
strings
};
pub static ref PREFIX_STRINGS_MAP: HashMap<&'static str, u8> = {
let mut map = HashMap::<&'static str, u8>::with_capacity(0x100);
for (i, string) in PREFIX_STRINGS.iter().enumerate() {
map.insert(string, u8::try_from(i).unwrap());
}
map
};
pub static ref SUFFIX_STRINGS_MAP: HashMap<&'static str, u8> = {
let mut map = HashMap::<&'static str, u8>::with_capacity(0x100);
for (i, string) in SUFFIX_STRINGS.iter().enumerate() {
map.insert(string, u8::try_from(i).unwrap());
}
map
};
pub static ref STRINGS_MAP: HashMap<&'static str, u8> = {
let mut map = HashMap::<&'static str, u8>::with_capacity(0x200);
map.extend(PREFIX_STRINGS_MAP.iter());
map.extend(SUFFIX_STRINGS_MAP.iter());
map
};
}
}