<commit_before>//! Automatically generated rust module for 'perftest_data.proto' file

#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]

use std::io::{Read, Write};
use quick_protobuf::{MessageRead, MessageWrite, Reader, Writer, Result};
use quick_protobuf::sizeofs::*;

#[derive(Debug, Default, PartialEq, Clone)]
pub struct Test1 {
    pub value: Option<i32>,
}

impl MessageRead for Test1 {
    fn from_reader<R: Read>(mut r: &mut Reader<R>) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag() {
                Ok(8) => msg.value = Some(r.read_int32()?),
                Ok(t) => { r.read_unknown(t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for Test1 {
    fn get_size(&self) -> usize {
        self.value.as_ref().map_or(0, |m| 1 + sizeof_int32(*m))
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        if let Some(ref s) = self.value { r.write_int32_with_tag(8, *s)?; }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestRepeatedBool {
    pub values: Vec<bool>,
}

impl MessageRead for TestRepeatedBool {
    fn from_reader<R: Read>(mut r: &mut Reader<R>) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag() {
                Ok(8) => msg.values.push(r.read_bool()?),
                Ok(t) => { r.read_unknown(t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestRepeatedBool {
    fn get_size(&self) -> usize {
        self.values.iter().map(|s| 1 + sizeof_bool(*s)).sum::<usize>()
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        for s in &self.values { r.write_bool_with_tag(8, *s)? }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestRepeatedPackedInt32 {
    pub values: Vec<i32>,
}

impl MessageRead for TestRepeatedPackedInt32 {
    fn from_reader<R: Read>(mut r: &mut Reader<R>) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag() {
                Ok(10) => msg.values = r.read_packed_repeated_field(|r| r.read_int32())?,
                Ok(t) => { r.read_unknown(t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestRepeatedPackedInt32 {
    fn get_size(&self) -> usize {
        if self.values.is_empty() { 0 } else { 1 + sizeof_var_length(self.values.iter().map(|s| sizeof_int32(*s)).sum::<usize>()) }
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        r.write_packed_repeated_field_with_tag(10, &self.values, |r, m| r.write_int32(*m), &|m| sizeof_int32(*m))?;
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestRepeatedMessages {
    pub messages1: Vec<TestRepeatedMessages>,
    pub messages2: Vec<TestRepeatedMessages>,
    pub messages3: Vec<TestRepeatedMessages>,
}

impl MessageRead for TestRepeatedMessages {
    fn from_reader<R: Read>(mut r: &mut Reader<R>) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag() {
                Ok(10) => msg.messages1.push(r.read_message()?),
                Ok(18) => msg.messages2.push(r.read_message()?),
                Ok(26) => msg.messages3.push(r.read_message()?),
                Ok(t) => { r.read_unknown(t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestRepeatedMessages {
    fn get_size(&self) -> usize {
        self.messages1.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.messages2.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.messages3.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        for s in &self.messages1 { r.write_message_with_tag(10, s)? }
        for s in &self.messages2 { r.write_message_with_tag(18, s)? }
        for s in &self.messages3 { r.write_message_with_tag(26, s)? }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestOptionalMessages {
    pub message1: Option<Box<TestOptionalMessages>>,
    pub message2: Option<Box<TestOptionalMessages>>,
    pub message3: Option<Box<TestOptionalMessages>>,
}

impl MessageRead for TestOptionalMessages {
    fn from_reader<R: Read>(mut r: &mut Reader<R>) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag() {
                Ok(10) => msg.message1 = Some(Box::new(r.read_message()?)),
                Ok(18) => msg.message2 = Some(Box::new(r.read_message()?)),
                Ok(26) => msg.message3 = Some(Box::new(r.read_message()?)),
                Ok(t) => { r.read_unknown(t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestOptionalMessages {
    fn get_size(&self) -> usize {
        self.message1.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.get_size()))
        + self.message2.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.get_size()))
        + self.message3.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.get_size()))
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        if let Some(ref s) = self.message1 { r.write_message_with_tag(10, &**s)?; }
        if let Some(ref s) = self.message2 { r.write_message_with_tag(18, &**s)?; }
        if let Some(ref s) = self.message3 { r.write_message_with_tag(26, &**s)?; }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestStrings {
    pub s1: Option<String>,
    pub s2: Option<String>,
    pub s3: Option<String>,
}

impl MessageRead for TestStrings {
    fn from_reader<R: Read>(mut r: &mut Reader<R>) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag() {
                Ok(10) => msg.s1 = Some(r.read_string()?),
                Ok(18) => msg.s2 = Some(r.read_string()?),
                Ok(26) => msg.s3 = Some(r.read_string()?),
                Ok(t) => { r.read_unknown(t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestStrings {
    fn get_size(&self) -> usize {
        self.s1.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.len()))
        + self.s2.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.len()))
        + self.s3.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.len()))
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        if let Some(ref s) = self.s1 { r.write_string_with_tag(10, s)?; }
        if let Some(ref s) = self.s2 { r.write_string_with_tag(18, s)?; }
        if let Some(ref s) = self.s3 { r.write_string_with_tag(26, s)?; }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestBytes {
    pub b1: Option<Vec<u8>>,
}

impl MessageRead for TestBytes {
    fn from_reader<R: Read>(mut r: &mut Reader<R>) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag() {
                Ok(10) => msg.b1 = Some(r.read_bytes()?),
                Ok(t) => { r.read_unknown(t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestBytes {
    fn get_size(&self) -> usize {
        self.b1.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.len()))
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        if let Some(ref s) = self.b1 { r.write_bytes_with_tag(10, s)?; }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct PerftestData {
    pub test1: Vec<Test1>,
    pub test_repeated_bool: Vec<TestRepeatedBool>,
    pub test_repeated_messages: Vec<TestRepeatedMessages>,
    pub test_optional_messages: Vec<TestOptionalMessages>,
    pub test_strings: Vec<TestStrings>,
    pub test_repeated_packed_int32: Vec<TestRepeatedPackedInt32>,
    pub test_small_bytearrays: Vec<TestBytes>,
    pub test_large_bytearrays: Vec<TestBytes>,
}

impl MessageRead for PerftestData {
    fn from_reader<R: Read>(mut r: &mut Reader<R>) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag() {
                Ok(10) => msg.test1.push(r.read_message()?),
                Ok(18) => msg.test_repeated_bool.push(r.read_message()?),
                Ok(26) => msg.test_repeated_messages.push(r.read_message()?),
                Ok(34) => msg.test_optional_messages.push(r.read_message()?),
                Ok(42) => msg.test_strings.push(r.read_message()?),
                Ok(50) => msg.test_repeated_packed_int32.push(r.read_message()?),
                Ok(58) => msg.test_small_bytearrays.push(r.read_message()?),
                Ok(66) => msg.test_large_bytearrays.push(r.read_message()?),
                Ok(t) => { r.read_unknown(t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for PerftestData {
    fn get_size(&self) -> usize {
        self.test1.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_repeated_bool.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_repeated_messages.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_optional_messages.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_strings.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_repeated_packed_int32.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_small_bytearrays.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_large_bytearrays.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        for s in &self.test1 { r.write_message_with_tag(10, s)? }
        for s in &self.test_repeated_bool { r.write_message_with_tag(18, s)? }
        for s in &self.test_repeated_messages { r.write_message_with_tag(26, s)? }
        for s in &self.test_optional_messages { r.write_message_with_tag(34, s)? }
        for s in &self.test_strings { r.write_message_with_tag(42, s)? }
        for s in &self.test_repeated_packed_int32 { r.write_message_with_tag(50, s)? }
        for s in &self.test_small_bytearrays { r.write_message_with_tag(58, s)? }
        for s in &self.test_large_bytearrays { r.write_message_with_tag(66, s)? }
        Ok(())
    }
}
<commit_msg>regenerate messages<commit_after>//! Automatically generated rust module for 'perftest_data.proto' file

#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]

use std::io::{Write};
use std::borrow::Cow;
use quick_protobuf::{MessageWrite, Reader, Writer, Result};
use quick_protobuf::sizeofs::*;

#[derive(Debug, Default, PartialEq, Clone)]
pub struct Test1 {
    pub value: Option<i32>,
}

impl Test1 {
    pub fn from_reader(r: &mut Reader, bytes: &[u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(8) => msg.value = Some(r.read_int32(bytes)?),
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for Test1 {
    fn get_size(&self) -> usize {
        self.value.as_ref().map_or(0, |m| 1 + sizeof_int32(*m))
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        if let Some(ref s) = self.value { r.write_int32_with_tag(8, *s)?; }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestRepeatedBool {
    pub values: Vec<bool>,
}

impl TestRepeatedBool {
    pub fn from_reader(r: &mut Reader, bytes: &[u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(8) => msg.values.push(r.read_bool(bytes)?),
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestRepeatedBool {
    fn get_size(&self) -> usize {
        self.values.iter().map(|s| 1 + sizeof_bool(*s)).sum::<usize>()
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        for s in &self.values { r.write_bool_with_tag(8, *s)? }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestRepeatedPackedInt32 {
    pub values: Vec<i32>,
}

impl TestRepeatedPackedInt32 {
    pub fn from_reader(r: &mut Reader, bytes: &[u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(10) => msg.values = r.read_packed(bytes, |r, bytes| r.read_int32(bytes))?,
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestRepeatedPackedInt32 {
    fn get_size(&self) -> usize {
        if self.values.is_empty() { 0 } else { 1 + sizeof_var_length(self.values.iter().map(|s| sizeof_int32(*s)).sum::<usize>()) }
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        r.write_packed_repeated_field_with_tag(10, &self.values, |r, m| r.write_int32(*m), &|m| sizeof_int32(*m))?;
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestRepeatedMessages {
    pub messages1: Vec<TestRepeatedMessages>,
    pub messages2: Vec<TestRepeatedMessages>,
    pub messages3: Vec<TestRepeatedMessages>,
}

impl TestRepeatedMessages {
    pub fn from_reader(r: &mut Reader, bytes: &[u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(10) => msg.messages1.push(r.read_message(bytes, TestRepeatedMessages::from_reader)?),
                Ok(18) => msg.messages2.push(r.read_message(bytes, TestRepeatedMessages::from_reader)?),
                Ok(26) => msg.messages3.push(r.read_message(bytes, TestRepeatedMessages::from_reader)?),
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestRepeatedMessages {
    fn get_size(&self) -> usize {
        self.messages1.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.messages2.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.messages3.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        for s in &self.messages1 { r.write_message_with_tag(10, s)? }
        for s in &self.messages2 { r.write_message_with_tag(18, s)? }
        for s in &self.messages3 { r.write_message_with_tag(26, s)? }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestOptionalMessages {
    pub message1: Option<Box<TestOptionalMessages>>,
    pub message2: Option<Box<TestOptionalMessages>>,
    pub message3: Option<Box<TestOptionalMessages>>,
}

impl TestOptionalMessages {
    pub fn from_reader(r: &mut Reader, bytes: &[u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(10) => msg.message1 = Some(Box::new(r.read_message(bytes, TestOptionalMessages::from_reader)?)),
                Ok(18) => msg.message2 = Some(Box::new(r.read_message(bytes, TestOptionalMessages::from_reader)?)),
                Ok(26) => msg.message3 = Some(Box::new(r.read_message(bytes, TestOptionalMessages::from_reader)?)),
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for TestOptionalMessages {
    fn get_size(&self) -> usize {
        self.message1.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.get_size()))
        + self.message2.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.get_size()))
        + self.message3.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.get_size()))
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        if let Some(ref s) = self.message1 { r.write_message_with_tag(10, &**s)?; }
        if let Some(ref s) = self.message2 { r.write_message_with_tag(18, &**s)?; }
        if let Some(ref s) = self.message3 { r.write_message_with_tag(26, &**s)?; }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestStrings<'a> {
    pub s1: Option<Cow<'a, str>>,
    pub s2: Option<Cow<'a, str>>,
    pub s3: Option<Cow<'a, str>>,
}

impl<'a> TestStrings<'a> {
    pub fn from_reader(r: &mut Reader, bytes: &'a [u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(10) => msg.s1 = Some(Cow::Borrowed(r.read_string(bytes)?)),
                Ok(18) => msg.s2 = Some(Cow::Borrowed(r.read_string(bytes)?)),
                Ok(26) => msg.s3 = Some(Cow::Borrowed(r.read_string(bytes)?)),
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl<'a> MessageWrite for TestStrings<'a> {
    fn get_size(&self) -> usize {
        self.s1.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.len()))
        + self.s2.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.len()))
        + self.s3.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.len()))
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        if let Some(ref s) = self.s1 { r.write_string_with_tag(10, s)?; }
        if let Some(ref s) = self.s2 { r.write_string_with_tag(18, s)?; }
        if let Some(ref s) = self.s3 { r.write_string_with_tag(26, s)?; }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestBytes<'a> {
    pub b1: Option<Cow<'a, [u8]>>,
}

impl<'a> TestBytes<'a> {
    pub fn from_reader(r: &mut Reader, bytes: &'a [u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(10) => msg.b1 = Some(Cow::Borrowed(r.read_bytes(bytes)?)),
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl<'a> MessageWrite for TestBytes<'a> {
    fn get_size(&self) -> usize {
        self.b1.as_ref().map_or(0, |m| 1 + sizeof_var_length(m.len()))
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        if let Some(ref s) = self.b1 { r.write_bytes_with_tag(10, s)?; }
        Ok(())
    }
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct PerftestData<'a> {
    pub test1: Vec<Test1>,
    pub test_repeated_bool: Vec<TestRepeatedBool>,
    pub test_repeated_messages: Vec<TestRepeatedMessages>,
    pub test_optional_messages: Vec<TestOptionalMessages>,
    pub test_strings: Vec<TestStrings<'a>>,
    pub test_repeated_packed_int32: Vec<TestRepeatedPackedInt32>,
    pub test_small_bytearrays: Vec<TestBytes<'a>>,
    pub test_large_bytearrays: Vec<TestBytes<'a>>,
}

impl<'a> PerftestData<'a> {
    pub fn from_reader(r: &mut Reader, bytes: &'a [u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(10) => msg.test1.push(r.read_message(bytes, Test1::from_reader)?),
                Ok(18) => msg.test_repeated_bool.push(r.read_message(bytes, TestRepeatedBool::from_reader)?),
                Ok(26) => msg.test_repeated_messages.push(r.read_message(bytes, TestRepeatedMessages::from_reader)?),
                Ok(34) => msg.test_optional_messages.push(r.read_message(bytes, TestOptionalMessages::from_reader)?),
                Ok(42) => msg.test_strings.push(r.read_message(bytes, TestStrings::from_reader)?),
                Ok(50) => msg.test_repeated_packed_int32.push(r.read_message(bytes, TestRepeatedPackedInt32::from_reader)?),
                Ok(58) => msg.test_small_bytearrays.push(r.read_message(bytes, TestBytes::from_reader)?),
                Ok(66) => msg.test_large_bytearrays.push(r.read_message(bytes, TestBytes::from_reader)?),
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl<'a> MessageWrite for PerftestData<'a> {
    fn get_size(&self) -> usize {
        self.test1.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_repeated_bool.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_repeated_messages.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_optional_messages.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_strings.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_repeated_packed_int32.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_small_bytearrays.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
        + self.test_large_bytearrays.iter().map(|s| 1 + sizeof_var_length(s.get_size())).sum::<usize>()
    }

    fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> {
        for s in &self.test1 { r.write_message_with_tag(10, s)? }
        for s in &self.test_repeated_bool { r.write_message_with_tag(18, s)? }
        for s in &self.test_repeated_messages { r.write_message_with_tag(26, s)? }
        for s in &self.test_optional_messages { r.write_message_with_tag(34, s)? }
        for s in &self.test_strings { r.write_message_with_tag(42, s)? }
        for s in &self.test_repeated_packed_int32 { r.write_message_with_tag(50, s)? }
        for s in &self.test_small_bytearrays { r.write_message_with_tag(58, s)? }
        for s in &self.test_large_bytearrays { r.write_message_with_tag(66, s)? }
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// https://tools.ietf.org/html/rfc7049

use std::collections::BTreeMap;

pub enum DataItem<'a> {
    #[allow(dead_code)]
    UnsignedInteger(u64),
    ByteString(&'a [u8]),
    TextString(&'a str),
    Array(Vec<DataItem<'a>>),
    Map(Vec<(DataItem<'a>, DataItem<'a>)>),
}

impl<'a> DataItem<'a> {
    pub fn serialize(&self) -> Vec<u8> {
        let mut result = Vec::new();
        self.append_binary_to(&mut result);
        result
    }
    fn append_binary_to(&self, output: &mut Vec<u8>) {
        use DataItem::*;
        match self {
            UnsignedInteger(x) => append_integer(output, 0, *x),
            ByteString(bytes) => {
                append_integer(output, 2, bytes.len() as u64);
                output.extend_from_slice(bytes);
            },
            TextString(text) => {
                append_integer(output, 3, text.len() as u64);
                output.extend_from_slice(text.as_bytes());
            },
            Array(items) => {
                append_integer(output, 4, items.len() as u64);
                for item in items {
                    item.append_binary_to(output);
                }
            },
            Map(entries) => {
                let mut map = BTreeMap::<Vec<u8>, Vec<u8>>::new();
                for (key, value) in entries {
                    map.insert(key.serialize(), value.serialize());
                }
                append_integer(output, 5, map.len() as u64);
                for (mut key, mut value) in map.into_iter() {
                    output.append(&mut key);
                    output.append(&mut value);
                }
            },
        }
    }
}

fn append_integer(output: &mut Vec<u8>, major_type: u8, data: u64) {
    let major_type = major_type << 5;
    match data {
        0..=23 => {
            output.push(major_type | (data as u8));
        },
        24..=0xff => {
            output.push(major_type | 24);
            output.push(data as u8);
        },
        0x100..=0xffff => {
            output.push(major_type | 25);
            output.extend_from_slice(&(data as u16).to_be_bytes());
        },
        0x10000..=0xffffffff => {
            output.push(major_type | 26);
            output.extend_from_slice(&(data as u32).to_be_bytes());
        },
        0x100000000..=0xffffffffffffffff => {
            output.push(major_type | 27);
            output.extend_from_slice(&data.to_be_bytes());
        },
    };
}

#[cfg(test)]
mod tests {
    use super::*;
    fn from_hex(input: &str) -> Vec<u8> {
        (0..input.len()).step_by(2).map(|i| {
            u8::from_str_radix(&input[i..i + 2], 16).unwrap()
        }).collect()
    }
    #[test]
    fn it_works() {
        assert_eq!(
            DataItem::UnsignedInteger(0).serialize(),
            from_hex("00"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(23).serialize(),
            from_hex("17"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(24).serialize(),
            from_hex("1818"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(100).serialize(),
            from_hex("1864"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(1000).serialize(),
            from_hex("1903e8"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(1000000).serialize(),
            from_hex("1a000f4240"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(1000000000000).serialize(),
            from_hex("1b000000e8d4a51000"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(18446744073709551615).serialize(),
            from_hex("1bffffffffffffffff"),
        );
        assert_eq!(
            DataItem::ByteString(&[1, 2, 3, 4]).serialize(),
            from_hex("4401020304"),
        );
        assert_eq!(
            DataItem::TextString("IETF").serialize(),
            from_hex("6449455446"),
        );
        assert_eq!(
            DataItem::Map(vec![]).serialize(),
            from_hex("a0"),
        );
        assert_eq!(
            DataItem::Map(vec![
                (DataItem::UnsignedInteger(1), DataItem::UnsignedInteger(2)),
                (DataItem::UnsignedInteger(3), DataItem::UnsignedInteger(4)),
            ]).serialize(),
            from_hex("a201020304"),
        );
    }
}
<commit_msg>Add test cases for cbor map key sorting (#24)<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// https://tools.ietf.org/html/rfc7049

use std::collections::BTreeMap;

pub enum DataItem<'a> {
    #[allow(dead_code)]
    UnsignedInteger(u64),
    ByteString(&'a [u8]),
    TextString(&'a str),
    Array(Vec<DataItem<'a>>),
    Map(Vec<(DataItem<'a>, DataItem<'a>)>),
}

impl<'a> DataItem<'a> {
    pub fn serialize(&self) -> Vec<u8> {
        let mut result = Vec::new();
        self.append_binary_to(&mut result);
        result
    }
    fn append_binary_to(&self, output: &mut Vec<u8>) {
        use DataItem::*;
        match self {
            UnsignedInteger(x) => append_integer(output, 0, *x),
            ByteString(bytes) => {
                append_integer(output, 2, bytes.len() as u64);
                output.extend_from_slice(bytes);
            },
            TextString(text) => {
                append_integer(output, 3, text.len() as u64);
                output.extend_from_slice(text.as_bytes());
            },
            Array(items) => {
                append_integer(output, 4, items.len() as u64);
                for item in items {
                    item.append_binary_to(output);
                }
            },
            Map(entries) => {
                let mut map = BTreeMap::<Vec<u8>, Vec<u8>>::new();
                for (key, value) in entries {
                    map.insert(key.serialize(), value.serialize());
                }
                append_integer(output, 5, map.len() as u64);
                for (mut key, mut value) in map.into_iter() {
                    output.append(&mut key);
                    output.append(&mut value);
                }
            },
        }
    }
}

fn append_integer(output: &mut Vec<u8>, major_type: u8, data: u64) {
    let major_type = major_type << 5;
    match data {
        0..=23 => {
            output.push(major_type | (data as u8));
        },
        24..=0xff => {
            output.push(major_type | 24);
            output.push(data as u8);
        },
        0x100..=0xffff => {
            output.push(major_type | 25);
            output.extend_from_slice(&(data as u16).to_be_bytes());
        },
        0x10000..=0xffffffff => {
            output.push(major_type | 26);
            output.extend_from_slice(&(data as u32).to_be_bytes());
        },
        0x100000000..=0xffffffffffffffff => {
            output.push(major_type | 27);
            output.extend_from_slice(&data.to_be_bytes());
        },
    };
}

#[cfg(test)]
mod tests {
    use super::*;
    fn from_hex(input: &str) -> Vec<u8> {
        (0..input.len()).step_by(2).map(|i| {
            u8::from_str_radix(&input[i..i + 2], 16).unwrap()
        }).collect()
    }
    #[test]
    fn it_works() {
        assert_eq!(
            DataItem::UnsignedInteger(0).serialize(),
            from_hex("00"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(23).serialize(),
            from_hex("17"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(24).serialize(),
            from_hex("1818"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(100).serialize(),
            from_hex("1864"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(1000).serialize(),
            from_hex("1903e8"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(1000000).serialize(),
            from_hex("1a000f4240"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(1000000000000).serialize(),
            from_hex("1b000000e8d4a51000"),
        );
        assert_eq!(
            DataItem::UnsignedInteger(18446744073709551615).serialize(),
            from_hex("1bffffffffffffffff"),
        );
        assert_eq!(
            DataItem::ByteString(&[1, 2, 3, 4]).serialize(),
            from_hex("4401020304"),
        );
        assert_eq!(
            DataItem::TextString("IETF").serialize(),
            from_hex("6449455446"),
        );
        assert_eq!(
            DataItem::Map(vec![]).serialize(),
            from_hex("a0"),
        );
        assert_eq!(
            DataItem::Map(vec![
                (DataItem::UnsignedInteger(1), DataItem::UnsignedInteger(2)),
                (DataItem::UnsignedInteger(3), DataItem::UnsignedInteger(4)),
            ]).serialize(),
            from_hex("a201020304"),
        );
    }
    #[test]
    fn map_keys_are_sorted() {
        use DataItem::*;
        assert_eq!(
            Map(vec![
              (UnsignedInteger(2), UnsignedInteger(5)),
              (UnsignedInteger(1), UnsignedInteger(6)),
            ]).serialize(),
            from_hex("a201060205"),
        );
        // Although "AA" is lexicographically less than "B", the CBOR format
        // of the string is prefixed with the string length, hence "B" is less
        // than "AA".
        assert_eq!(
            Map(vec![
              (TextString("AA"), UnsignedInteger(6)),
              (TextString("B"), UnsignedInteger(5)),
            ]).serialize(),
            from_hex("a261420562414106"),
        );
    }
}
<|endoftext|>


<commit_before>// Syntax: master_server [ip address (0.0.0.0 by default)]
// This was created for HaloMD.

// If the server does not respond in at least this many seconds, it will be dropped from the list.
const DROP_TIME : i64 = 60;

// Blacklist for blocking IPs. Separate with newlines. Any line that starts with a # is ignored.
// Blacklisting IPs ignores heartbeat and keepalive packets from an IP address.
// That means that servers that are banned will not be immediately removed, but will time out, instead.
const BLACKLIST_FILE : &'static str = "blacklist.txt";

// Read the blacklist every x amount of seconds.
const BLACKLIST_UPDATE_TIME : u32 = 60;

// Note: The master server must have TCP 29920 open and UDP 27900 open.
const BROADCAST_PORT_UDP : u16 = 27900;
const SERVER_LIST_PORT_TCP : u16 = 29920;

// Opcode info from game packets
const OPCODE_INDEX : usize = 0;
const OPCODE_AND_HANDSHAKE_LENGTH : usize = 5;

// Broadcast packet type opcodes.
const KEEPALIVE : u8 = 8;
const HEARTBEAT : u8 = 3;

use std::net::{UdpSocket,TcpListener,SocketAddr};
use std::net::SocketAddr::{V4,V6};
use std::io::{Write,BufReader,BufRead};
use std::env;
use std::fs::File;
use std::thread;
use std::sync::{Arc, Mutex};

extern crate time;
use time::{SteadyTime,Duration};

mod halo_server;
use halo_server::HaloServer;

mod heartbeat_packet;
use heartbeat_packet::{HeartbeatPacket,GAMEEXITED};

trait IPString {
    fn ip_string(&self) -> String;
}

impl IPString for SocketAddr {
    fn ip_string(&self) -> String {
        match *self {
            V4(ipv4) => ipv4.ip().to_string(),
            V6(ipv6) => "[".to_string() + &ipv6.ip().to_string() + "]"
        }
    }
}

fn main() {
    let count = env::args().count();
    let ip = if count == 2 {
        let j : Vec<_> = env::args().collect();
        j[1].to_string()
    }
    else if count == 1 {
        "0.0.0.0".to_string()
    }
    else {
        println!("Only one argument is allowed: the IP to bind to.");
        return;
    };

    // We need to bind on two different ports. If it failed to bind (invalid IP, port is taken), then we must make sure this is known.
    let halo_socket = match UdpSocket::bind((&ip as &str,BROADCAST_PORT_UDP)) {
        Err(error) => {
            println!("Error creating a UDP socket at {}:{}. {}.",ip,BROADCAST_PORT_UDP,error);
            return;
        },
        Ok(halo_socket) => halo_socket
    };

    let client_socket = match TcpListener::bind((&ip as &str,SERVER_LIST_PORT_TCP)) {
        Err(error) => {
            println!("Error listening to TCP at {}:{}. {}.",ip,SERVER_LIST_PORT_TCP,error);
            return;
        },
        Ok(client_socket) => client_socket
    };

    // Mutex for thread safety.
    let servers_halo: Vec<HaloServer> = Vec::new();
    let servers_mut_udp = Arc::new(Mutex::new(servers_halo));
    let servers_mut_tcp = servers_mut_udp.clone();
    let servers_mut_destruction = servers_mut_udp.clone();

    // Destruction thread. This will remove servers that have not broadcasted their presence in a while.
    thread::spawn(move || {
        loop {
            thread::sleep_ms(10 * 1000);
            let mut servers = servers_mut_destruction.lock().unwrap();
            let timenow = SteadyTime::now();
            servers.retain(|x| x.last_alive + Duration::seconds(DROP_TIME) > timenow);
        }
    });

    // Blacklist mutex. Concurrency needs to be safe, my friend.
    let blacklist: Option<Vec<String>> = None;
    let blacklist_update = Arc::new(Mutex::new(blacklist));
    let blacklist_udp = blacklist_update.clone();

    // Blacklist read thread.
    thread::spawn(move || {
        let valid_line = |x: &str| -> bool { x.trim().len() > 0 && !x.starts_with("#") };
        loop {
            // Placed in a block so blacklist is unlocked before sleeping to prevent threads from being locked for too long.
            {
                let mut blacklist_ref = blacklist_update.lock().unwrap();
                *blacklist_ref =
                    File::open(BLACKLIST_FILE).
                    map(|file|
                        BufReader::new(&file).lines().
                        filter_map(|line| line.ok().and_then(|x| if valid_line(&x) { Some(x) } else { None })).
                        collect()
                    ).ok();
            }
            thread::sleep_ms(BLACKLIST_UPDATE_TIME * 1000);
        }
    });

    // TCP server thread. This is for the HaloMD application.
    thread::spawn(move || {
        loop {
            for stream in client_socket.incoming() {
                let mut client = match stream {
                    Err(_) => continue,
                    Ok(the_stream) => the_stream
                };
                // Unwrap the IP.
                let ip = match client.peer_addr() {
                    Err(_) => continue,
                    Ok(ip) => ip.ip_string()
                };

                let mut ips = String::new();

                // Make servers_ref go out of scope to unlock it for other threads, since we don't need it.
                {
                    let servers_ref = servers_mut_tcp.lock().unwrap();
                    let servers = (*servers_ref).iter();

                    for j in servers {
                        ips.push_str(&(j.to_string()));
                        ips.push('\n');
                    }
                }

                // Some number placed after the requester's IP. If you ask me, the source code was abducted by aliens, and this is a tracking number. Regardless, it's needed.
                ips.push_str(&ip);
                ips.push_str(":49149:3425");

                // We may be here a while. Just in case...
                thread::spawn( move || {
                    let _ = client.write_all(ips.as_bytes());
                });
            }
        }
    });

    // UDP server is run on the main thread. Servers broadcast their presence here.

    let mut buffer = [0; 2048];
    loop {
        let (length, source) = match halo_socket.recv_from(&mut buffer) {
            Err(_) => continue,
            Ok(x) => x
        };
        if length <= OPCODE_INDEX {
            continue;
        }

        if buffer[OPCODE_INDEX] != KEEPALIVE && buffer[OPCODE_INDEX] != HEARTBEAT {
            continue;
        }

        let client_ip = source.ip_string();

        let blacklist_ref = blacklist_udp.lock().unwrap();
        if (*blacklist_ref).as_ref().map(|blacklist| blacklist.contains(&client_ip)).unwrap_or(false) {
            continue;
        }

        // Heartbeat packet. These contain null-terminated C strings and are ordered in key1[0]value1[0]key2[0]value2[0]key3[0]value3[0] where [0] is a byte equal to 0x00.
        if buffer[OPCODE_INDEX] == HEARTBEAT && length > OPCODE_AND_HANDSHAKE_LENGTH {

            let mut servers = servers_mut_udp.lock().unwrap();

            match HeartbeatPacket::from_buffer(&buffer[OPCODE_AND_HANDSHAKE_LENGTH..length]) {
                None => {},
                Some(packet) => {
                    let updatetime = SteadyTime::now();
                    match servers.iter_mut().position(|x| x.ip == client_ip && x.port == packet.localport) {
                        None => {
                            (*servers).push(HaloServer { ip:client_ip, port: packet.localport, last_alive: updatetime });
                        }
                        Some(k) => {
                            servers[k].last_alive = updatetime;
                            if packet.statechanged == GAMEEXITED {
                                servers.remove(k);
                            }
                        }
                    };
                }
            };
        }

        // Keepalive packet. We need to rely on the origin's port for this, unfortunately. This may mean that the source port is incorrect if the port was changed with NAT.
        else if buffer[OPCODE_INDEX] == KEEPALIVE {
            let mut servers_ref = servers_mut_udp.lock().unwrap();
            let servers = (*servers_ref).iter_mut();

            for i in servers {
                if i.ip == client_ip && i.port == source.port() {
                    i.last_alive = SteadyTime::now();
                    break;
                }
            }
        }
    }
}
<commit_msg>Add comment about lack of polling/lightweight threads<commit_after>// Syntax: master_server [ip address (0.0.0.0 by default)]
// This was created for HaloMD.

// If the server does not respond in at least this many seconds, it will be dropped from the list.
const DROP_TIME : i64 = 60;

// Blacklist for blocking IPs. Separate with newlines. Any line that starts with a # is ignored.
// Blacklisting IPs ignores heartbeat and keepalive packets from an IP address.
// That means that servers that are banned will not be immediately removed, but will time out, instead.
const BLACKLIST_FILE : &'static str = "blacklist.txt";

// Read the blacklist every x amount of seconds.
const BLACKLIST_UPDATE_TIME : u32 = 60;

// Note: The master server must have TCP 29920 open and UDP 27900 open.
const BROADCAST_PORT_UDP : u16 = 27900;
const SERVER_LIST_PORT_TCP : u16 = 29920;

// Opcode info from game packets
const OPCODE_INDEX : usize = 0;
const OPCODE_AND_HANDSHAKE_LENGTH : usize = 5;

// Broadcast packet type opcodes.
const KEEPALIVE : u8 = 8;
const HEARTBEAT : u8 = 3;

use std::net::{UdpSocket,TcpListener,SocketAddr};
use std::net::SocketAddr::{V4,V6};
use std::io::{Write,BufReader,BufRead};
use std::env;
use std::fs::File;
use std::thread;
use std::sync::{Arc, Mutex};

extern crate time;
use time::{SteadyTime,Duration};

mod halo_server;
use halo_server::HaloServer;

mod heartbeat_packet;
use heartbeat_packet::{HeartbeatPacket,GAMEEXITED};

trait IPString {
    fn ip_string(&self) -> String;
}

impl IPString for SocketAddr {
    fn ip_string(&self) -> String {
        match *self {
            V4(ipv4) => ipv4.ip().to_string(),
            V6(ipv6) => "[".to_string() + &ipv6.ip().to_string() + "]"
        }
    }
}

fn main() {
    let count = env::args().count();
    let ip = if count == 2 {
        let j : Vec<_> = env::args().collect();
        j[1].to_string()
    }
    else if count == 1 {
        "0.0.0.0".to_string()
    }
    else {
        println!("Only one argument is allowed: the IP to bind to.");
        return;
    };

    // We need to bind on two different ports. If it failed to bind (invalid IP, port is taken), then we must make sure this is known.
    let halo_socket = match UdpSocket::bind((&ip as &str,BROADCAST_PORT_UDP)) {
        Err(error) => {
            println!("Error creating a UDP socket at {}:{}. {}.",ip,BROADCAST_PORT_UDP,error);
            return;
        },
        Ok(halo_socket) => halo_socket
    };

    let client_socket = match TcpListener::bind((&ip as &str,SERVER_LIST_PORT_TCP)) {
        Err(error) => {
            println!("Error listening to TCP at {}:{}. {}.",ip,SERVER_LIST_PORT_TCP,error);
            return;
        },
        Ok(client_socket) => client_socket
    };

    // Mutex for thread safety.
    let servers_halo: Vec<HaloServer> = Vec::new();
    let servers_mut_udp = Arc::new(Mutex::new(servers_halo));
    let servers_mut_tcp = servers_mut_udp.clone();
    let servers_mut_destruction = servers_mut_udp.clone();

    // Destruction thread. This will remove servers that have not broadcasted their presence in a while.
    thread::spawn(move || {
        loop {
            thread::sleep_ms(10 * 1000);
            let mut servers = servers_mut_destruction.lock().unwrap();
            let timenow = SteadyTime::now();
            servers.retain(|x| x.last_alive + Duration::seconds(DROP_TIME) > timenow);
        }
    });

    // Blacklist mutex. Concurrency needs to be safe, my friend.
    let blacklist: Option<Vec<String>> = None;
    let blacklist_update = Arc::new(Mutex::new(blacklist));
    let blacklist_udp = blacklist_update.clone();

    // Blacklist read thread.
    thread::spawn(move || {
        let valid_line = |x: &str| -> bool { x.trim().len() > 0 && !x.starts_with("#") };
        loop {
            // Placed in a block so blacklist is unlocked before sleeping to prevent threads from being locked for too long.
            {
                let mut blacklist_ref = blacklist_update.lock().unwrap();
                *blacklist_ref =
                    File::open(BLACKLIST_FILE).
                    map(|file|
                        BufReader::new(&file).lines().
                        filter_map(|line| line.ok().and_then(|x| if valid_line(&x) { Some(x) } else { None })).
                        collect()
                    ).ok();
            }
            thread::sleep_ms(BLACKLIST_UPDATE_TIME * 1000);
        }
    });

    // TCP server thread. This is for the HaloMD application.
    thread::spawn(move || {
        loop {
            for stream in client_socket.incoming() {
                let mut client = match stream {
                    Err(_) => continue,
                    Ok(the_stream) => the_stream
                };
                // Unwrap the IP.
                let ip = match client.peer_addr() {
                    Err(_) => continue,
                    Ok(ip) => ip.ip_string()
                };

                let mut ips = String::new();

                // Make servers_ref go out of scope to unlock it for other threads, since we don't need it.
                {
                    let servers_ref = servers_mut_tcp.lock().unwrap();
                    let servers = (*servers_ref).iter();

                    for j in servers {
                        ips.push_str(&(j.to_string()));
                        ips.push('\n');
                    }
                }

                // Some number placed after the requester's IP. If you ask me, the source code was abducted by aliens, and this is a tracking number. Regardless, it's needed.
                ips.push_str(&ip);
                ips.push_str(":49149:3425");

                // We may be here a while. Just in case...
                // May want to consider some lightweight thread library in the future, or some non-blocking polling mechanism
                thread::spawn( move || {
                    let _ = client.write_all(ips.as_bytes());
                });
            }
        }
    });

    // UDP server is run on the main thread. Servers broadcast their presence here.

    let mut buffer = [0; 2048];
    loop {
        let (length, source) = match halo_socket.recv_from(&mut buffer) {
            Err(_) => continue,
            Ok(x) => x
        };
        if length <= OPCODE_INDEX {
            continue;
        }

        if buffer[OPCODE_INDEX] != KEEPALIVE && buffer[OPCODE_INDEX] != HEARTBEAT {
            continue;
        }

        let client_ip = source.ip_string();

        let blacklist_ref = blacklist_udp.lock().unwrap();
        if (*blacklist_ref).as_ref().map(|blacklist| blacklist.contains(&client_ip)).unwrap_or(false) {
            continue;
        }

        // Heartbeat packet. These contain null-terminated C strings and are ordered in key1[0]value1[0]key2[0]value2[0]key3[0]value3[0] where [0] is a byte equal to 0x00.
        if buffer[OPCODE_INDEX] == HEARTBEAT && length > OPCODE_AND_HANDSHAKE_LENGTH {

            let mut servers = servers_mut_udp.lock().unwrap();

            match HeartbeatPacket::from_buffer(&buffer[OPCODE_AND_HANDSHAKE_LENGTH..length]) {
                None => {},
                Some(packet) => {
                    let updatetime = SteadyTime::now();
                    match servers.iter_mut().position(|x| x.ip == client_ip && x.port == packet.localport) {
                        None => {
                            (*servers).push(HaloServer { ip:client_ip, port: packet.localport, last_alive: updatetime });
                        }
                        Some(k) => {
                            servers[k].last_alive = updatetime;
                            if packet.statechanged == GAMEEXITED {
                                servers.remove(k);
                            }
                        }
                    };
                }
            };
        }

        // Keepalive packet. We need to rely on the origin's port for this, unfortunately. This may mean that the source port is incorrect if the port was changed with NAT.
        else if buffer[OPCODE_INDEX] == KEEPALIVE {
            let mut servers_ref = servers_mut_udp.lock().unwrap();
            let servers = (*servers_ref).iter_mut();

            for i in servers {
                if i.ip == client_ip && i.port == source.port() {
                    i.last_alive = SteadyTime::now();
                    break;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use extra::json;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;

fn build_hex_mesh(&geom: &Geom) -> ~[Vec3<GLfloat>] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new() {
    let pos3d = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      let data = &mut vertex_data;
      data.push(pos3d + vertex);
      data.push(pos3d + next_vertex);
      data.push(pos3d + Vec3::zero());
    }
  }
  vertex_data
}

pub struct Visualizer {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: Option<glfw::Window>,
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "OpenGL",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

#[deriving(Decodable)]
struct Size2<T> {
  x: T,
  y: T,
}

fn read_win_size(config_path: &str) -> Vec2<int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<int> = Decodable::decode(&mut decoder);
  Vec2{x: size.x, y: size.y}
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: Some(win),
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_models();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let position_attr = glh::get_attr(self.program, "position");
    gl::EnableVertexAttribArray(position_attr);
    glh::vertex_attrib_pointer(position_attr);
    let map_vertex_data = build_hex_mesh(&self.geom);
    self.map_mesh.init(map_vertex_data);
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.init(unit_obj.build());
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_unit_at(&self, pos: Vec2<i32>) {
    let world_pos = self.geom.map_pos_to_world_pos(pos);
    let m = glh::tr(self.camera.mat(), world_pos);
    glh::uniform_mat4f(self.mat_id, &m);
    self.unit_mesh.draw(self.program);
  }

  fn draw_units(&self) {
    self.draw_unit_at(Vec2{x: 0, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 0});
    self.draw_unit_at(Vec2{x: 2, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 1});
    if !self.selected_tile_pos.is_none() {
      let p = self.selected_tile_pos.unwrap();
      self.draw_unit_at(p);
    }
  }

  fn draw_map(&self) {
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Vec2<f32>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += self.mouse_pos.x - pos.x;
      self.camera.x_angle += self.mouse_pos.y - pos.y;
    }
    self.mouse_pos = pos;
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent]{
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as f32, y: y as f32};
        self.handle_cursor_pos_event(p);
      },
      glfw::SizeEvent(w, h) => {
        gl::Viewport(0, 0, w, h);
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn close_window(&mut self) {
    // destroy glfw::Window before terminating glfw
    self.win = None;
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
    self.close_window();
    glfw::terminate();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Visualizer: Changed window title to Marauder<commit_after>// See LICENSE file for copyright and license details.

use extra::json;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;

fn build_hex_mesh(&geom: &Geom) -> ~[Vec3<GLfloat>] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new() {
    let pos3d = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      let data = &mut vertex_data;
      data.push(pos3d + vertex);
      data.push(pos3d + next_vertex);
      data.push(pos3d + Vec3::zero());
    }
  }
  vertex_data
}

pub struct Visualizer {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: Option<glfw::Window>,
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "Marauder",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

#[deriving(Decodable)]
struct Size2<T> {
  x: T,
  y: T,
}

fn read_win_size(config_path: &str) -> Vec2<int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<int> = Decodable::decode(&mut decoder);
  Vec2{x: size.x, y: size.y}
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: Some(win),
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_models();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let position_attr = glh::get_attr(self.program, "position");
    gl::EnableVertexAttribArray(position_attr);
    glh::vertex_attrib_pointer(position_attr);
    let map_vertex_data = build_hex_mesh(&self.geom);
    self.map_mesh.init(map_vertex_data);
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.init(unit_obj.build());
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_unit_at(&self, pos: Vec2<i32>) {
    let world_pos = self.geom.map_pos_to_world_pos(pos);
    let m = glh::tr(self.camera.mat(), world_pos);
    glh::uniform_mat4f(self.mat_id, &m);
    self.unit_mesh.draw(self.program);
  }

  fn draw_units(&self) {
    self.draw_unit_at(Vec2{x: 0, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 0});
    self.draw_unit_at(Vec2{x: 2, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 1});
    if !self.selected_tile_pos.is_none() {
      let p = self.selected_tile_pos.unwrap();
      self.draw_unit_at(p);
    }
  }

  fn draw_map(&self) {
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Vec2<f32>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += self.mouse_pos.x - pos.x;
      self.camera.x_angle += self.mouse_pos.y - pos.y;
    }
    self.mouse_pos = pos;
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent]{
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as f32, y: y as f32};
        self.handle_cursor_pos_event(p);
      },
      glfw::SizeEvent(w, h) => {
        gl::Viewport(0, 0, w, h);
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn close_window(&mut self) {
    // destroy glfw::Window before terminating glfw
    self.win = None;
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
    self.close_window();
    glfw::terminate();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>use std::io::Write;
use inflector::Inflector;
use botocore::{Operation, Service, Shape, ShapeType, Member};

use super::xml_payload_parser;
use super::{IoResult, FileWriter, GenerateProtocol, error_type_name, capitalize_first, generate_field_name};

pub struct QueryGenerator;

impl GenerateProtocol for QueryGenerator {
    fn generate_methods(&self, writer: &mut FileWriter, service: &Service) -> IoResult {
        for (operation_name, operation) in service.operations.iter() {
            writeln!(writer,
                "
                {documentation}
                {method_signature} {{
                    let mut request = SignedRequest::new(\"{http_method}\", \"{endpoint_prefix}\", self.region, \"{request_uri}\");
                    let mut params = Params::new();

                    params.put(\"Action\", \"{operation_name}\");
                    params.put(\"Version\", \"{api_version}\");
                    {serialize_input}
                    request.set_params(params);

                    request.sign(&try!(self.credentials_provider.credentials()));
                    let response = try!(self.dispatcher.dispatch(&request));
                    match response.status {{
                        StatusCode::Ok => {{
                            {parse_payload}
                            Ok(result)
                        }}
                        _ => {{
                            Err({error_type}::from_body(&response.body))
                        }}
                    }}
                }}
                ",
                api_version = &service.metadata.api_version,
                documentation = generate_documentation(operation),
                error_type = error_type_name(operation_name),
                http_method = &operation.http.method,
                endpoint_prefix = &service.metadata.endpoint_prefix,
                parse_payload = xml_payload_parser::generate_response_parser(service, operation, false),
                method_signature = generate_method_signature(operation_name, operation),
                operation_name = &operation.name,
                request_uri = &operation.http.request_uri,
                serialize_input = generate_method_input_serialization(operation)
            )?;
        }
        Ok(())
    }

    fn generate_prelude(&self, writer: &mut FileWriter,_service: &Service) -> IoResult {
        writeln!(writer,
            "use std::str::FromStr;
            use xml::EventReader;
            use xml::reader::ParserConfig;
            use param::{{Params, ServiceParams}};
            use signature::SignedRequest;
            use xml::reader::XmlEvent;
            use xmlutil::{{Next, Peek, XmlParseError, XmlResponse}};
            use xmlutil::{{characters, end_element, start_element, skip_tree, peek_at_name}};
            use xmlerror::*;

            enum DeserializerNext {{
                Close,
                Skip,
                Element(String),
        }}")
    }

    fn generate_struct_attributes(&self,
                                  _struct_name: &str,
                                  _serialized: bool,
                                  deserialized: bool)
                                  -> String {
        xml_payload_parser::generate_struct_attributes(deserialized)
    }

    fn generate_serializer(&self, name: &str, shape: &Shape, service: &Service) -> Option<String> {
        if shape.is_primitive() {
           return None;
        }

        Some(
            format!("
            /// Serialize `{name}` contents to a `SignedRequest`.
            struct {name}Serializer;
            impl {name}Serializer {{
                {serializer_signature} {{
                    {serializer_body}
                }}
            }}
            ",
            name = name,
            serializer_signature = generate_serializer_signature(name, shape),
            serializer_body = generate_serializer_body(service, shape)
            )
        )
    }

    fn generate_deserializer(&self, name: &str, shape: &Shape, service: &Service) -> Option<String> {
        Some(xml_payload_parser::generate_deserializer(name, shape, service))
    }

    fn timestamp_type(&self) -> &'static str {
        "String"
    }
}

pub fn generate_method_input_serialization(operation: &Operation) -> String {
    if operation.input.is_some() {
        format!(
            "{input_type}Serializer::serialize(&mut params, \"\", &input);",
            input_type = operation.input.as_ref().unwrap().shape,
        )
    } else {
        String::new()
    }
}

fn generate_serializer_body(service: &Service, shape: &Shape) -> String {
    match shape.shape_type {
        ShapeType::List => generate_list_serializer(service, shape),
        ShapeType::Map => generate_map_serializer(service, shape),
        ShapeType::Structure => generate_struct_serializer(service, shape),
        _ => "".to_owned(),
    }
}

fn generate_serializer_signature(name: &str, shape: &Shape) -> String {
    if shape.shape_type == ShapeType::Structure && shape.members.as_ref().unwrap().is_empty() {
        format!("fn serialize(_params: &mut Params, name: &str, _obj: &{})",
                name)
    } else {
        format!("fn serialize(params: &mut Params, name: &str, obj: &{})",
                name)
    }
}

fn generate_list_serializer(service: &Service, shape: &Shape) -> String {

    let member_shape = service.shape_for_member(shape.member.as_ref().unwrap()).unwrap();
    let primitive = member_shape.is_primitive();

    let mut parts = Vec::new();

    let lmf = list_member_format(service);

    parts.push(format!("for (index, obj) in obj.iter().enumerate() {{
                    let key = format!(\"{list_member_format}\", name, index+1);",
                       list_member_format = lmf));

    if primitive {
        parts.push(format!("params.put(&key, {});",
                           serialize_primitive_expression(&member_shape.shape_type, "obj")));
    } else {
        parts.push(format!("{}Serializer::serialize(params, &key, obj);",
                           shape.member_type()));
    }

    parts.push("}".to_owned());
    parts.join("\n")
}

fn list_member_format(service: &Service) -> String {
    match &service.metadata.protocol[..] {
        "ec2" => "{}.{}".to_owned(),
        "query" => "{}.member.{}".to_owned(),
        _ => panic!("Unsupported protocol"),
    }
}

fn generate_map_serializer(service: &Service, shape: &Shape) -> String {
    let mut parts = Vec::new();

    // the key is always a string type
    parts.push(format!("for (index, (key, value)) in obj.iter().enumerate() {{
            let prefix = format!(\"{{}}.{{}}\", name, index+1);
            params.put(&format!(\"{{}}.{{}}\", prefix, \"{key_name}\"), &key);",
            key_name = key_name(service, shape),
        ));

    let value_shape = service.shape_for_value(shape.value.as_ref().unwrap()).unwrap();
    let primitive_value = value_shape.is_primitive();

    if primitive_value {
        parts.push(format!("params.put(&key, {});",
                           serialize_primitive_expression(&value_shape.shape_type, "value")));
    } else {
        parts.push(format!("{value_type}Serializer::serialize(
                    params,
                    &format!(\"{{}}.{{}}\", prefix, \"{value_name}\"),
                    value,
                );",
                           value_type = shape.value_type(),
                           value_name = value_name(service, shape)))
    }

    parts.push("}".to_owned());
    parts.join("\n")
}

fn key_name(service: &Service, shape: &Shape) -> String {
    let key_name = shape.key
        .as_ref()
        .expect("Key undefined")
        .location_name
        .as_ref()
        .expect("Key location undefined");
    capitalize_if_ec2(service, key_name)
}

fn value_name(service: &Service, shape: &Shape) -> String {
    let value_name = shape.value
        .as_ref()
        .expect("Value undefined")
        .location_name
        .as_ref()
        .expect("Value location undefined");
    capitalize_if_ec2(service, value_name)
}

fn member_location(service: &Service, member: &Member, default: &str) -> String {
    let member_location = member.location_name.clone().unwrap_or_else(|| default.to_owned());
    capitalize_if_ec2(service, &member_location)
}

fn capitalize_if_ec2(service: &Service, name: &str) -> String {
    match &service.metadata.protocol[..] {
        "ec2" => capitalize_first(name),
        _ => name.to_owned(),
    }
}

fn generate_struct_serializer(service: &Service, shape: &Shape) -> String {
    format!(
        "let mut prefix = name.to_string();
        if prefix != \"\" {{
            prefix.push_str(\".\");
        }}

        {struct_field_serializers}
        ",
        struct_field_serializers = generate_struct_field_serializers(service, shape),
    )
}

fn generate_struct_field_serializers(service: &Service, shape: &Shape) -> String {
    shape.members
        .as_ref()
        .unwrap()
        .iter()
        .map(|(member_name, member)| {
            let primitive = service.shape_for_member(member).unwrap().is_primitive();

            if shape.required(member_name) {
                if primitive {
                    required_primitive_field_serializer(service, member_name, member)
                } else {
                    required_complex_field_serializer(service, member_name, member)
                }
            } else if primitive {
                optional_primitive_field_serializer(service, member_name, member)
            } else {
                optional_complex_field_serializer(service, member_name, member)
            }
        })
        .collect::<Vec<String>>()
        .join("\n")
}

fn optional_primitive_field_serializer(service: &Service,
                                       member_name: &str,
                                       member: &Member)
                                       -> String {
    let member_shape = service.shape_for_member(member).unwrap();
    let expression = serialize_primitive_expression(&member_shape.shape_type, "field_value");

    format!("if let Some(ref field_value) = obj.{field_name} {{
                params.put(&format!(\"{{}}{{}}\", prefix, \"{tag_name}\"), {expression});
            }}",
            field_name = generate_field_name(member_name),
            expression = expression,
            tag_name = member_location(service, member, member_name))
}

fn required_primitive_field_serializer(service: &Service,
                                       member_name: &str,
                                       member: &Member)
                                       -> String {
    let member_shape = service.shape_for_member(member).unwrap();
    let expression = serialize_primitive_expression(&member_shape.shape_type,
                                                    &format!("obj.{}",
                                                             generate_field_name(member_name)));

    format!("params.put(&format!(\"{{}}{{}}\", prefix, \"{tag_name}\"), {expression});",
            expression = expression,
            tag_name = member_location(service, member, member_name))
}

fn serialize_primitive_expression(shape_type: &ShapeType, var_name: &str) -> String {
    match *shape_type {
        ShapeType::String | ShapeType::Timestamp => format!("&{}", var_name),
        ShapeType::Integer | ShapeType::Double | ShapeType::Long | ShapeType::Boolean => {
            format!("&{}.to_string()", var_name)
        }
        ShapeType::Blob => format!("::std::str::from_utf8(&{}).unwrap()", var_name),
        shape_type => panic!("Unknown primitive shape type: {:?}", shape_type),
    }
}

fn required_complex_field_serializer(service: &Service,
                                     member_name: &str,
                                     member: &Member)
                                     -> String {
    format!("{member_shape}Serializer::serialize(
                params,
                &format!(\"{{}}{{}}\", prefix, \"{tag_name}\"),
                &obj.{field_name},
            );",
            field_name = generate_field_name(member_name),
            member_shape = member.shape,
            tag_name = member_location(service, member, member_name))
}

fn optional_complex_field_serializer(service: &Service,
                                     member_name: &str,
                                     member: &Member)
                                     -> String {
    format!("if let Some(ref field_value) = obj.{field_name} {{
                {member_shape_name}Serializer::serialize(
                    params,
                    &format!(\"{{}}{{}}\", prefix, \"{tag_name}\"),
                    field_value,
                );
            }}",
            field_name = generate_field_name(member_name),
            member_shape_name = member.shape,
            tag_name = member_location(service, member, member_name))
}

fn generate_documentation(operation: &Operation) -> String {
    match operation.documentation {
        Some(ref docs) => {
            format!("#[doc=\"{}\"]",
                    docs.replace("\\", "\\\\").replace("\"", "\\\""))
        }
        None => "".to_owned(),
    }
}

fn generate_method_signature(operation_name: &str, operation: &Operation) -> String {
    if operation.input.is_some() {
        format!(
            "pub fn {operation_name}(&self, input: &{input_type}) -> Result<{output_type}, {error_type}>",
            input_type = operation.input.as_ref().unwrap().shape,
            operation_name = operation.name.to_snake_case(),
            output_type = &operation.output_shape_or("()"),
            error_type = error_type_name(operation_name),
        )
    } else {
        format!(
            "pub fn {operation_name}(&self) -> Result<{output_type}, {error_type}>",
            operation_name = operation.name.to_snake_case(),
            output_type = &operation.output_shape_or("()"),
            error_type = error_type_name(operation_name),
        )
    }
}
<commit_msg>fall back to default values of 'key' and 'value' for map keys and values if none is specified<commit_after>use std::io::Write;
use inflector::Inflector;
use botocore::{Operation, Service, Shape, ShapeType, Member};

use super::xml_payload_parser;
use super::{IoResult, FileWriter, GenerateProtocol, error_type_name, capitalize_first, generate_field_name};

pub struct QueryGenerator;

impl GenerateProtocol for QueryGenerator {
    fn generate_methods(&self, writer: &mut FileWriter, service: &Service) -> IoResult {
        for (operation_name, operation) in service.operations.iter() {
            writeln!(writer,
                "
                {documentation}
                {method_signature} {{
                    let mut request = SignedRequest::new(\"{http_method}\", \"{endpoint_prefix}\", self.region, \"{request_uri}\");
                    let mut params = Params::new();

                    params.put(\"Action\", \"{operation_name}\");
                    params.put(\"Version\", \"{api_version}\");
                    {serialize_input}
                    request.set_params(params);

                    request.sign(&try!(self.credentials_provider.credentials()));
                    let response = try!(self.dispatcher.dispatch(&request));
                    match response.status {{
                        StatusCode::Ok => {{
                            {parse_payload}
                            Ok(result)
                        }}
                        _ => {{
                            Err({error_type}::from_body(&response.body))
                        }}
                    }}
                }}
                ",
                api_version = &service.metadata.api_version,
                documentation = generate_documentation(operation),
                error_type = error_type_name(operation_name),
                http_method = &operation.http.method,
                endpoint_prefix = &service.metadata.endpoint_prefix,
                parse_payload = xml_payload_parser::generate_response_parser(service, operation, false),
                method_signature = generate_method_signature(operation_name, operation),
                operation_name = &operation.name,
                request_uri = &operation.http.request_uri,
                serialize_input = generate_method_input_serialization(operation)
            )?;
        }
        Ok(())
    }

    fn generate_prelude(&self, writer: &mut FileWriter,_service: &Service) -> IoResult {
        writeln!(writer,
            "use std::str::FromStr;
            use xml::EventReader;
            use xml::reader::ParserConfig;
            use param::{{Params, ServiceParams}};
            use signature::SignedRequest;
            use xml::reader::XmlEvent;
            use xmlutil::{{Next, Peek, XmlParseError, XmlResponse}};
            use xmlutil::{{characters, end_element, start_element, skip_tree, peek_at_name}};
            use xmlerror::*;

            enum DeserializerNext {{
                Close,
                Skip,
                Element(String),
        }}")
    }

    fn generate_struct_attributes(&self,
                                  _struct_name: &str,
                                  _serialized: bool,
                                  deserialized: bool)
                                  -> String {
        xml_payload_parser::generate_struct_attributes(deserialized)
    }

    fn generate_serializer(&self, name: &str, shape: &Shape, service: &Service) -> Option<String> {
        if shape.is_primitive() {
           return None;
        }

        Some(
            format!("
            /// Serialize `{name}` contents to a `SignedRequest`.
            struct {name}Serializer;
            impl {name}Serializer {{
                {serializer_signature} {{
                    {serializer_body}
                }}
            }}
            ",
            name = name,
            serializer_signature = generate_serializer_signature(name, shape),
            serializer_body = generate_serializer_body(service, shape)
            )
        )
    }

    fn generate_deserializer(&self, name: &str, shape: &Shape, service: &Service) -> Option<String> {
        Some(xml_payload_parser::generate_deserializer(name, shape, service))
    }

    fn timestamp_type(&self) -> &'static str {
        "String"
    }
}

pub fn generate_method_input_serialization(operation: &Operation) -> String {
    if operation.input.is_some() {
        format!(
            "{input_type}Serializer::serialize(&mut params, \"\", &input);",
            input_type = operation.input.as_ref().unwrap().shape,
        )
    } else {
        String::new()
    }
}

fn generate_serializer_body(service: &Service, shape: &Shape) -> String {
    match shape.shape_type {
        ShapeType::List => generate_list_serializer(service, shape),
        ShapeType::Map => generate_map_serializer(service, shape),
        ShapeType::Structure => generate_struct_serializer(service, shape),
        _ => "".to_owned(),
    }
}

fn generate_serializer_signature(name: &str, shape: &Shape) -> String {
    if shape.shape_type == ShapeType::Structure && shape.members.as_ref().unwrap().is_empty() {
        format!("fn serialize(_params: &mut Params, name: &str, _obj: &{})",
                name)
    } else {
        format!("fn serialize(params: &mut Params, name: &str, obj: &{})",
                name)
    }
}

fn generate_list_serializer(service: &Service, shape: &Shape) -> String {

    let member_shape = service.shape_for_member(shape.member.as_ref().unwrap()).unwrap();
    let primitive = member_shape.is_primitive();

    let mut parts = Vec::new();

    let lmf = list_member_format(service);

    parts.push(format!("for (index, obj) in obj.iter().enumerate() {{
                    let key = format!(\"{list_member_format}\", name, index+1);",
                       list_member_format = lmf));

    if primitive {
        parts.push(format!("params.put(&key, {});",
                           serialize_primitive_expression(&member_shape.shape_type, "obj")));
    } else {
        parts.push(format!("{}Serializer::serialize(params, &key, obj);",
                           shape.member_type()));
    }

    parts.push("}".to_owned());
    parts.join("\n")
}

fn list_member_format(service: &Service) -> String {
    match &service.metadata.protocol[..] {
        "ec2" => "{}.{}".to_owned(),
        "query" => "{}.member.{}".to_owned(),
        _ => panic!("Unsupported protocol"),
    }
}

fn generate_map_serializer(service: &Service, shape: &Shape) -> String {
    let mut parts = Vec::new();

    // the key is always a string type
    parts.push(format!("for (index, (key, value)) in obj.iter().enumerate() {{
            let prefix = format!(\"{{}}.{{}}\", name, index+1);
            params.put(&format!(\"{{}}.{{}}\", prefix, \"{key_name}\"), &key);",
            key_name = key_name(service, shape),
        ));

    let value_shape = service.shape_for_value(shape.value.as_ref().unwrap()).unwrap();
    let primitive_value = value_shape.is_primitive();

    if primitive_value {
        parts.push(format!("params.put(&key, {});",
                           serialize_primitive_expression(&value_shape.shape_type, "value")));
    } else {
        parts.push(format!("{value_type}Serializer::serialize(
                    params,
                    &format!(\"{{}}.{{}}\", prefix, \"{value_name}\"),
                    value,
                );",
                           value_type = shape.value_type(),
                           value_name = value_name(service, shape)))
    }

    parts.push("}".to_owned());
    parts.join("\n")
}

fn key_name(service: &Service, shape: &Shape) -> String {
    let key_name = shape.key
        .as_ref()
        .expect("Key undefined")
        .location_name
        .as_ref()
        .map(String::as_ref)
        .unwrap_or_else(|| "key");
    capitalize_if_ec2(service, key_name)
}

fn value_name(service: &Service, shape: &Shape) -> String {
    let value_name = shape.value
        .as_ref()
        .expect("Value undefined")
        .location_name
        .as_ref()
        .map(String::as_ref)
        .unwrap_or_else(|| "value");
    capitalize_if_ec2(service, value_name)
}

fn member_location(service: &Service, member: &Member, default: &str) -> String {
    let member_location = member.location_name.clone().unwrap_or_else(|| default.to_owned());
    capitalize_if_ec2(service, &member_location)
}

fn capitalize_if_ec2(service: &Service, name: &str) -> String {
    match &service.metadata.protocol[..] {
        "ec2" => capitalize_first(name),
        _ => name.to_owned(),
    }
}

fn generate_struct_serializer(service: &Service, shape: &Shape) -> String {
    format!(
        "let mut prefix = name.to_string();
        if prefix != \"\" {{
            prefix.push_str(\".\");
        }}

        {struct_field_serializers}
        ",
        struct_field_serializers = generate_struct_field_serializers(service, shape),
    )
}

fn generate_struct_field_serializers(service: &Service, shape: &Shape) -> String {
    shape.members
        .as_ref()
        .unwrap()
        .iter()
        .map(|(member_name, member)| {
            let primitive = service.shape_for_member(member).unwrap().is_primitive();

            if shape.required(member_name) {
                if primitive {
                    required_primitive_field_serializer(service, member_name, member)
                } else {
                    required_complex_field_serializer(service, member_name, member)
                }
            } else if primitive {
                optional_primitive_field_serializer(service, member_name, member)
            } else {
                optional_complex_field_serializer(service, member_name, member)
            }
        })
        .collect::<Vec<String>>()
        .join("\n")
}

fn optional_primitive_field_serializer(service: &Service,
                                       member_name: &str,
                                       member: &Member)
                                       -> String {
    let member_shape = service.shape_for_member(member).unwrap();
    let expression = serialize_primitive_expression(&member_shape.shape_type, "field_value");

    format!("if let Some(ref field_value) = obj.{field_name} {{
                params.put(&format!(\"{{}}{{}}\", prefix, \"{tag_name}\"), {expression});
            }}",
            field_name = generate_field_name(member_name),
            expression = expression,
            tag_name = member_location(service, member, member_name))
}

fn required_primitive_field_serializer(service: &Service,
                                       member_name: &str,
                                       member: &Member)
                                       -> String {
    let member_shape = service.shape_for_member(member).unwrap();
    let expression = serialize_primitive_expression(&member_shape.shape_type,
                                                    &format!("obj.{}",
                                                             generate_field_name(member_name)));

    format!("params.put(&format!(\"{{}}{{}}\", prefix, \"{tag_name}\"), {expression});",
            expression = expression,
            tag_name = member_location(service, member, member_name))
}

fn serialize_primitive_expression(shape_type: &ShapeType, var_name: &str) -> String {
    match *shape_type {
        ShapeType::String | ShapeType::Timestamp => format!("&{}", var_name),
        ShapeType::Integer | ShapeType::Double | ShapeType::Long | ShapeType::Boolean => {
            format!("&{}.to_string()", var_name)
        }
        ShapeType::Blob => format!("::std::str::from_utf8(&{}).unwrap()", var_name),
        shape_type => panic!("Unknown primitive shape type: {:?}", shape_type),
    }
}

fn required_complex_field_serializer(service: &Service,
                                     member_name: &str,
                                     member: &Member)
                                     -> String {
    format!("{member_shape}Serializer::serialize(
                params,
                &format!(\"{{}}{{}}\", prefix, \"{tag_name}\"),
                &obj.{field_name},
            );",
            field_name = generate_field_name(member_name),
            member_shape = member.shape,
            tag_name = member_location(service, member, member_name))
}

fn optional_complex_field_serializer(service: &Service,
                                     member_name: &str,
                                     member: &Member)
                                     -> String {
    format!("if let Some(ref field_value) = obj.{field_name} {{
                {member_shape_name}Serializer::serialize(
                    params,
                    &format!(\"{{}}{{}}\", prefix, \"{tag_name}\"),
                    field_value,
                );
            }}",
            field_name = generate_field_name(member_name),
            member_shape_name = member.shape,
            tag_name = member_location(service, member, member_name))
}

fn generate_documentation(operation: &Operation) -> String {
    match operation.documentation {
        Some(ref docs) => {
            format!("#[doc=\"{}\"]",
                    docs.replace("\\", "\\\\").replace("\"", "\\\""))
        }
        None => "".to_owned(),
    }
}

fn generate_method_signature(operation_name: &str, operation: &Operation) -> String {
    if operation.input.is_some() {
        format!(
            "pub fn {operation_name}(&self, input: &{input_type}) -> Result<{output_type}, {error_type}>",
            input_type = operation.input.as_ref().unwrap().shape,
            operation_name = operation.name.to_snake_case(),
            output_type = &operation.output_shape_or("()"),
            error_type = error_type_name(operation_name),
        )
    } else {
        format!(
            "pub fn {operation_name}(&self) -> Result<{output_type}, {error_type}>",
            operation_name = operation.name.to_snake_case(),
            output_type = &operation.output_shape_or("()"),
            error_type = error_type_name(operation_name),
        )
    }
}
<|endoftext|>