convert teams from haskell list
authoralfadur
Tue, 19 May 2020 19:26:48 +0300
changeset 15576 3be9c98ae190
parent 15575 a2e78f5907cc
child 15577 7d4f552e317f
convert teams from haskell list
rust/hedgewars-server/src/server/demo.rs
rust/hedgewars-server/src/server/haskell.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<Self> {
-        let value = super::haskell::parse(&[]);
-        Ok(unimplemented!())
+    fn load(filename: String) -> io::Result<Self> {
+        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<Self> {
-        let datum = fs::File::open(file)?;
-        let mut reader = io::BufReader::new(datum);
+    fn load_hwd(filename: String) -> io::Result<Self> {
+        let file = fs::File::open(filename)?;
+        let mut reader = io::BufReader::new(file);
 
         #[inline]
         fn error<T>(cause: &str) -> io::Result<T> {
@@ -254,3 +267,70 @@
         })
     }
 }
+
+fn haskell_to_demo(value: HaskellValue) -> Option<Demo> {
+    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,
+    })
+}
--- 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<u8> {
+        match self {
+            HaskellValue::Number(value) => Some(*value),
+            _ => None,
+        }
+    }
+
+    pub fn into_number(self) -> Option<u8> {
+        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<String> {
+        match self {
+            HaskellValue::String(value) => Some(value),
+            _ => None,
+        }
+    }
+
+    pub fn into_list(self) -> Option<Vec<HaskellValue>> {
+        match self {
+            HaskellValue::List(items) => Some(items),
+            _ => None,
+        }
+    }
+
+    pub fn into_tuple(self) -> Option<Vec<HaskellValue>> {
+        match self {
+            HaskellValue::Tuple(items) => Some(items),
+            _ => None,
+        }
+    }
+
+    pub fn into_anon_struct(self) -> Option<(String, Vec<HaskellValue>)> {
+        match self {
+            HaskellValue::AnonStruct { name, fields } => Some((name, fields)),
+            _ => None,
+        }
+    }
+
+    pub fn into_struct(self) -> Option<(String, HashMap<String, HaskellValue>)> {
+        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, ", ")?;
         }