# HG changeset patch # User alfadur # Date 1589905608 -10800 # Node ID 3be9c98ae190bd969d59c14582b58e5481c09b3e # Parent a2e78f5907ccabe971038eae734f84cc5afa046e convert teams from haskell list diff -r a2e78f5907cc -r 3be9c98ae190 rust/hedgewars-server/src/server/demo.rs --- a/rust/hedgewars-server/src/server/demo.rs Tue May 19 02:25:24 2020 +0300 +++ b/rust/hedgewars-server/src/server/demo.rs Tue May 19 19:26:48 2020 +0300 @@ -1,5 +1,7 @@ -use crate::core::types::{GameCfg, TeamInfo}; - +use crate::{ + core::types::{GameCfg, HedgehogInfo, TeamInfo}, + server::haskell::HaskellValue, +}; use std::{ fs, io::{self, BufReader, Read, Write}, @@ -17,14 +19,25 @@ Ok(unimplemented!()) } - fn load(file: String) -> io::Result { - let value = super::haskell::parse(&[]); - Ok(unimplemented!()) + fn load(filename: String) -> io::Result { + let mut file = fs::File::open(filename)?; + let mut bytes = vec![]; + file.read_to_end(&mut bytes)?; + match super::haskell::parse(&bytes[..]) { + Ok((_, value)) => haskell_to_demo(value).ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "Invalid demo structure", + )), + Err(_) => Err(io::Error::new( + io::ErrorKind::InvalidData, + "Unable to parse file", + )), + } } - fn load_hwd(file: String) -> io::Result { - let datum = fs::File::open(file)?; - let mut reader = io::BufReader::new(datum); + fn load_hwd(filename: String) -> io::Result { + let file = fs::File::open(filename)?; + let mut reader = io::BufReader::new(file); #[inline] fn error(cause: &str) -> io::Result { @@ -254,3 +267,70 @@ }) } } + +fn haskell_to_demo(value: HaskellValue) -> Option { + use HaskellValue::*; + let mut lists = value.into_tuple()?; + let mut lists_iter = lists.drain(..); + + let teams_list = lists_iter.next()?.into_list()?; + let map_config = lists_iter.next()?.into_list()?; + let game_config = lists_iter.next()?.into_list()?; + let engine_messages = lists_iter.next()?.into_list()?; + + let mut teams = Vec::with_capacity(teams_list.len()); + + for team in teams_list { + let (_, mut fields) = team.into_struct()?; + + let mut team_info = TeamInfo::default(); + for (name, value) in fields.drain() { + match &name[..] { + "teamowner" => team_info.owner = value.into_string()?, + "teamname" => team_info.name = value.into_string()?, + "teamcolor" => team_info.color = u8::from_str(&value.into_string()?).ok()?, + "teamgrave" => team_info.grave = value.into_string()?, + "teamfort" => team_info.fort = value.into_string()?, + "teamvoicepack" => team_info.voice_pack = value.into_string()?, + "teamflag" => team_info.flag = value.into_string()?, + "difficulty" => team_info.difficulty = value.into_number()?, + "hhnum" => team_info.hedgehogs_number = value.into_number()?, + "hedgehogs" => { + for (index, hog) in value + .into_list()? + .drain(..) + .enumerate() + .take(team_info.hedgehogs.len()) + { + let (_, mut fields) = hog.into_anon_struct()?; + let mut fields_iter = fields.drain(..); + team_info.hedgehogs[index] = HedgehogInfo { + name: fields_iter.next()?.into_string()?, + hat: fields_iter.next()?.into_string()?, + } + } + } + _ => (), + } + } + teams.push(team_info) + } + + let mut config = Vec::with_capacity(map_config.len() + game_config.len()); + + for item in map_config {} + + for item in game_config {} + + let mut messages = Vec::with_capacity(engine_messages.len()); + + for message in engine_messages { + messages.push(message.into_string()?); + } + + Some(Demo { + teams, + config, + messages, + }) +} diff -r a2e78f5907cc -r 3be9c98ae190 rust/hedgewars-server/src/server/haskell.rs --- a/rust/hedgewars-server/src/server/haskell.rs Tue May 19 02:25:24 2020 +0300 +++ b/rust/hedgewars-server/src/server/haskell.rs Tue May 19 19:26:48 2020 +0300 @@ -30,6 +30,64 @@ }, } +impl HaskellValue { + pub fn to_number(&self) -> Option { + match self { + HaskellValue::Number(value) => Some(*value), + _ => None, + } + } + + pub fn into_number(self) -> Option { + match self { + HaskellValue::Number(value) => Some(value), + _ => None, + } + } + + pub fn to_string(&self) -> Option<&str> { + match self { + HaskellValue::String(value) => Some(value), + _ => None, + } + } + + pub fn into_string(self) -> Option { + match self { + HaskellValue::String(value) => Some(value), + _ => None, + } + } + + pub fn into_list(self) -> Option> { + match self { + HaskellValue::List(items) => Some(items), + _ => None, + } + } + + pub fn into_tuple(self) -> Option> { + match self { + HaskellValue::Tuple(items) => Some(items), + _ => None, + } + } + + pub fn into_anon_struct(self) -> Option<(String, Vec)> { + match self { + HaskellValue::AnonStruct { name, fields } => Some((name, fields)), + _ => None, + } + } + + pub fn into_struct(self) -> Option<(String, HashMap)> { + match self { + HaskellValue::Struct { name, fields } => Some((name, fields)), + _ => None, + } + } +} + fn write_sequence( f: &mut Formatter<'_>, brackets: &[u8; 2], @@ -37,7 +95,7 @@ ) -> Result<(), Error> { write!(f, "{}", brackets[0] as char)?; while let Some(value) = items.next() { - write!(f, "{}", value); + write!(f, "{}", value)?; if !items.as_slice().is_empty() { write!(f, ", ")?; }