<commit_before>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! YAML Deserialization
//!
//! This module provides YAML deserialization with the type `Deserializer`.

use std::collections::BTreeMap;
use std::io;
use std::str;

use yaml_rust::parser::{Parser, MarkedEventReceiver, Event as YamlEvent};
use yaml_rust::scanner::{Marker, TokenType, TScalarStyle};

use serde::de::{self, Deserialize, DeserializeSeed, Unexpected};

use super::error::{Error, Result};

pub struct Loader {
    events: Vec<(Event, Marker)>,
    /// Map from alias id to index in events.
    aliases: BTreeMap<usize, usize>,
}

impl MarkedEventReceiver for Loader {
    fn on_event(&mut self, event: &YamlEvent, marker: Marker) {
        let event = match *event {
            YamlEvent::Nothing
                | YamlEvent::StreamStart
                | YamlEvent::StreamEnd
                | YamlEvent::DocumentStart
                | YamlEvent::DocumentEnd => return,

            YamlEvent::Alias(id) => Event::Alias(id),
            YamlEvent::Scalar(ref value, style, id, ref tag) => {
                self.aliases.insert(id, self.events.len());
                Event::Scalar(value.clone(), style, tag.clone())
            }
            YamlEvent::SequenceStart(id) => {
                self.aliases.insert(id, self.events.len());
                Event::SequenceStart
            }
            YamlEvent::SequenceEnd => Event::SequenceEnd,
            YamlEvent::MappingStart(id) => {
                self.aliases.insert(id, self.events.len());
                Event::MappingStart
            }
            YamlEvent::MappingEnd => Event::MappingEnd,
        };
        self.events.push((event, marker));
    }
}

#[derive(Debug)]
enum Event {
    Alias(usize),
    Scalar(String, TScalarStyle, Option<TokenType>),
    SequenceStart,
    SequenceEnd,
    MappingStart,
    MappingEnd,
}

struct Deserializer<'a> {
    events: &'a [(Event, Marker)],
    /// Map from alias id to index in events.
    aliases: &'a BTreeMap<usize, usize>,
    pos: usize,
}

impl<'a> Deserializer<'a> {
    fn peek(&self) -> Result<&'a Event> {
        match self.events.get(self.pos) {
            Some(event) => Ok(&event.0),
            None => Err(Error::EndOfStream),
        }
    }

    fn next(&mut self) -> Result<&'a Event> {
        match self.events.get(self.pos) {
            Some(event) => {
                self.pos += 1;
                Ok(&event.0)
            }
            None => Err(Error::EndOfStream),
        }
    }

    fn jump(&self, id: usize) -> Result<Deserializer<'a>> {
        match self.aliases.get(&id) {
            Some(&pos) => {
                Ok(Deserializer {
                    events: self.events,
                    aliases: self.aliases,
                    pos: pos,
                })
            }
            None => Err(Error::AliasNotFound),
        }
    }
}

impl<'a> de::SeqVisitor for Deserializer<'a> {
    type Error = Error;

    fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
        where T: DeserializeSeed
    {
        match *self.peek()? {
            Event::SequenceEnd => Ok(None),
            _ => seed.deserialize(self).map(Some),
        }
    }
}

impl<'a> de::MapVisitor for Deserializer<'a> {
    type Error = Error;

    fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
        where K: DeserializeSeed
    {
        match *self.peek()? {
            Event::MappingEnd => Ok(None),
            _ => seed.deserialize(self).map(Some),
        }
    }

    fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
        where V: DeserializeSeed
    {
        seed.deserialize(self)
    }
}

struct VariantVisitor<'a: 'r, 'r> {
    de: &'r mut Deserializer<'a>,
}

impl<'a, 'r> de::EnumVisitor for VariantVisitor<'a, 'r> {
    type Error = Error;
    type Variant = VariantVisitor<'a, 'r>;

    fn visit_variant_seed<V>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self::Variant)>
        where V: DeserializeSeed
    {
        Ok((seed.deserialize(&mut *self.de)?, self))
    }
}

impl<'a, 'r> de::VariantVisitor for VariantVisitor<'a, 'r> {
    type Error = Error;

    fn visit_unit(self) -> Result<()> {
        Deserialize::deserialize(self.de)
    }

    fn visit_newtype_seed<T>(self, seed: T) -> Result<T::Value>
        where T: DeserializeSeed
    {
        seed.deserialize(self.de)
    }

    fn visit_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        de::Deserializer::deserialize(self.de, visitor)
    }

    fn visit_struct<V>(
        self,
        _fields: &'static [&'static str],
        visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor
    {
        de::Deserializer::deserialize(self.de, visitor)
    }
}

struct UnitVariantVisitor<'a: 'r, 'r> {
    de: &'r mut Deserializer<'a>,
}

impl<'a, 'r> de::EnumVisitor for UnitVariantVisitor<'a, 'r> {
    type Error = Error;
    type Variant = Self;

    fn visit_variant_seed<V>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self::Variant)>
        where V: DeserializeSeed
    {
        Ok((seed.deserialize(&mut *self.de)?, self))
    }
}

impl<'a, 'r> de::VariantVisitor for UnitVariantVisitor<'a, 'r> {
    type Error = Error;

    fn visit_unit(self) -> Result<()> {
        Ok(())
    }

    fn visit_newtype_seed<T>(self, _seed: T) -> Result<T::Value>
        where T: DeserializeSeed
    {
        Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"))
    }

    fn visit_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"))
    }

    fn visit_struct<V>(
        self,
        _fields: &'static [&'static str],
        _visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor
    {
        Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"))
    }
}

fn visit_str<V>(visitor: V, v: &str) -> Result<V::Value>
    where V: de::Visitor
{
    if v == "~" || v == "null" {
        return visitor.visit_unit();
    }
    if v == "true" {
        return visitor.visit_bool(true);
    }
    if v == "false" {
        return visitor.visit_bool(false);
    }
    if v.starts_with("0x") {
        if let Ok(n) = i64::from_str_radix(&v[2..], 16) {
            return visitor.visit_i64(n);
        }
    }
    if v.starts_with("0o") {
        if let Ok(n) = i64::from_str_radix(&v[2..], 8) {
            return visitor.visit_i64(n);
        }
    }
    if v.starts_with('+') {
        if let Ok(n) = v[1..].parse() {
            return visitor.visit_i64(n);
        }
    }
    if let Ok(n) = v.parse() {
        return visitor.visit_i64(n);
    }
    if let Ok(n) = v.parse() {
        return visitor.visit_f64(n);
    }
    visitor.visit_str(v)
}

impl<'a, 'r> de::Deserializer for &'r mut Deserializer<'a> {
    type Error = Error;

    fn deserialize<V>(self, visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        match *self.next()? {
            Event::Alias(i) => self.jump(i)?.deserialize(visitor),
            Event::Scalar(ref v, style, ref tag) => {
                if style != TScalarStyle::Plain {
                    visitor.visit_str(v)
                } else if let Some(TokenType::Tag(ref handle, ref suffix)) = *tag {
                    if handle == "!!" {
                        match suffix.as_ref() {
                            "bool" => {
                                match v.parse::<bool>() {
                                    Ok(v) => visitor.visit_bool(v),
                                    Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"a boolean")),
                                }
                            },
                            "int" => {
                                match v.parse::<i64>() {
                                    Ok(v) => visitor.visit_i64(v),
                                    Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"an integer")),
                                }
                            },
                            "float" => {
                                match v.parse::<f64>() {
                                    Ok(v) => visitor.visit_f64(v),
                                    Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"a float")),
                                }
                            },
                            "null" => {
                                match v.as_ref() {
                                    "~" | "null" => visitor.visit_unit(),
                                    _ => Err(de::Error::invalid_value(Unexpected::Str(v), &"null")),
                                }
                            }
                            _  => visitor.visit_str(v),
                        }
                    } else {
                        visitor.visit_str(v)
                    }
                } else {
                    visit_str(visitor, v)
                }
            }
            Event::SequenceStart => {
                let value = visitor.visit_seq(&mut *self)?;
                match *self.next()? {
                    Event::SequenceEnd => Ok(value),
                    _ => Err(de::Error::custom("remaining elements in sequence")), // FIXME
                }
            }
            Event::MappingStart => {
                let value = visitor.visit_map(&mut *self)?;
                match *self.next()? {
                    Event::MappingEnd => Ok(value),
                    _ => Err(de::Error::custom("remaining elements in map")), // FIXME
                }
            }
            Event::SequenceEnd | Event::MappingEnd => Err(Error::EndOfStream), // FIXME
        }
    }

    /// Parses `null` as None and any other values as `Some(...)`.
    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        let is_some = match *self.peek()? {
            Event::Alias(i) => return self.jump(i)?.deserialize_option(visitor),
            Event::Scalar(ref v, style, ref tag) => {
                if style != TScalarStyle::Plain {
                    true
                } else if let Some(TokenType::Tag(ref handle, ref suffix)) = *tag {
                    if handle == "!!" && suffix == "null" {
                        if v == "~" || v == "null" {
                            false
                        } else {
                            return Err(de::Error::custom("failed to parse null")); // FIXME
                        }
                    } else {
                        true
                    }
                } else {
                    v != "~" && v != "null"
                }
            }
            Event::SequenceStart | Event::MappingStart => true,
            Event::SequenceEnd | Event::MappingEnd => return Err(Error::EndOfStream), // FIXME
        };
        if is_some {
            visitor.visit_some(self)
        } else {
            self.pos += 1;
            visitor.visit_none()
        }
    }

    /// Parses a newtype struct as the underlying value.
    fn deserialize_newtype_struct<V>(
        self,
        _name: &str,
        visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor
    {
        visitor.visit_newtype_struct(self)
    }

    /// Parses an enum as a single key:value pair where the key identifies the
    /// variant and the value gives the content. A String will also parse correctly
    /// to a unit enum value.
    fn deserialize_enum<V>(
        self,
        name: &str,
        _variants: &'static [&'static str],
        visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor
    {
        match *self.peek()? {
            Event::MappingStart => {
                self.pos += 1;
                let value = visitor.visit_enum(VariantVisitor { de: self })?;
                match *self.next()? {
                    Event::MappingEnd => Ok(value),
                    _ => Err(Error::VariantMapWrongSize(name.to_owned(), 2)), // FIXME
                }
            }
            Event::Scalar(_, _, _) => {
                visitor.visit_enum(UnitVariantVisitor { de: self })
            }
            _ => Err(Error::VariantNotAMapOrString(name.to_owned())),
        }
    }

    forward_to_deserialize!{
        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
        seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
        struct_field tuple ignored_any
    }
}

/// Decodes a YAML value from a `&str`.
pub fn from_str<T>(s: &str) -> Result<T>
    where T: Deserialize
{
    let mut parser = Parser::new(s.chars());
    let mut loader = Loader {
        events: Vec::new(),
        aliases: BTreeMap::new(),
    };
    parser.load(&mut loader, true)?;
    if loader.events.is_empty() {
        Err(Error::EndOfStream)
    } else {
        let mut deserializer = Deserializer {
            events: &loader.events,
            aliases: &loader.aliases,
            pos: 0,
        };
        let t = Deserialize::deserialize(&mut deserializer)?;
        if deserializer.pos == loader.events.len() {
            Ok(t)
        } else {
            Err(Error::MoreThanOneDocument)
        }
    }
}

pub fn from_iter<I, T>(iter: I) -> Result<T>
    where I: Iterator<Item = io::Result<u8>>,
          T: Deserialize
{
    let bytes: Vec<u8> = try!(iter.collect());
    from_str(str::from_utf8(&bytes)?)
}

pub fn from_reader<R, T>(rdr: R) -> Result<T>
    where R: io::Read,
          T: Deserialize
{
    from_iter(rdr.bytes())
}

pub fn from_slice<T>(v: &[u8]) -> Result<T>
    where T: Deserialize
{
    from_iter(v.iter().map(|byte| Ok(*byte)))
}
<commit_msg>Clarify untagged string visitor<commit_after>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! YAML Deserialization
//!
//! This module provides YAML deserialization with the type `Deserializer`.

use std::collections::BTreeMap;
use std::io;
use std::str;

use yaml_rust::parser::{Parser, MarkedEventReceiver, Event as YamlEvent};
use yaml_rust::scanner::{Marker, TokenType, TScalarStyle};

use serde::de::{self, Deserialize, DeserializeSeed, Unexpected};

use super::error::{Error, Result};

pub struct Loader {
    events: Vec<(Event, Marker)>,
    /// Map from alias id to index in events.
    aliases: BTreeMap<usize, usize>,
}

impl MarkedEventReceiver for Loader {
    fn on_event(&mut self, event: &YamlEvent, marker: Marker) {
        let event = match *event {
            YamlEvent::Nothing
                | YamlEvent::StreamStart
                | YamlEvent::StreamEnd
                | YamlEvent::DocumentStart
                | YamlEvent::DocumentEnd => return,

            YamlEvent::Alias(id) => Event::Alias(id),
            YamlEvent::Scalar(ref value, style, id, ref tag) => {
                self.aliases.insert(id, self.events.len());
                Event::Scalar(value.clone(), style, tag.clone())
            }
            YamlEvent::SequenceStart(id) => {
                self.aliases.insert(id, self.events.len());
                Event::SequenceStart
            }
            YamlEvent::SequenceEnd => Event::SequenceEnd,
            YamlEvent::MappingStart(id) => {
                self.aliases.insert(id, self.events.len());
                Event::MappingStart
            }
            YamlEvent::MappingEnd => Event::MappingEnd,
        };
        self.events.push((event, marker));
    }
}

#[derive(Debug)]
enum Event {
    Alias(usize),
    Scalar(String, TScalarStyle, Option<TokenType>),
    SequenceStart,
    SequenceEnd,
    MappingStart,
    MappingEnd,
}

struct Deserializer<'a> {
    events: &'a [(Event, Marker)],
    /// Map from alias id to index in events.
    aliases: &'a BTreeMap<usize, usize>,
    pos: usize,
}

impl<'a> Deserializer<'a> {
    fn peek(&self) -> Result<&'a Event> {
        match self.events.get(self.pos) {
            Some(event) => Ok(&event.0),
            None => Err(Error::EndOfStream),
        }
    }

    fn next(&mut self) -> Result<&'a Event> {
        match self.events.get(self.pos) {
            Some(event) => {
                self.pos += 1;
                Ok(&event.0)
            }
            None => Err(Error::EndOfStream),
        }
    }

    fn jump(&self, id: usize) -> Result<Deserializer<'a>> {
        match self.aliases.get(&id) {
            Some(&pos) => {
                Ok(Deserializer {
                    events: self.events,
                    aliases: self.aliases,
                    pos: pos,
                })
            }
            None => Err(Error::AliasNotFound),
        }
    }
}

impl<'a> de::SeqVisitor for Deserializer<'a> {
    type Error = Error;

    fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
        where T: DeserializeSeed
    {
        match *self.peek()? {
            Event::SequenceEnd => Ok(None),
            _ => seed.deserialize(self).map(Some),
        }
    }
}

impl<'a> de::MapVisitor for Deserializer<'a> {
    type Error = Error;

    fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
        where K: DeserializeSeed
    {
        match *self.peek()? {
            Event::MappingEnd => Ok(None),
            _ => seed.deserialize(self).map(Some),
        }
    }

    fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
        where V: DeserializeSeed
    {
        seed.deserialize(self)
    }
}

struct VariantVisitor<'a: 'r, 'r> {
    de: &'r mut Deserializer<'a>,
}

impl<'a, 'r> de::EnumVisitor for VariantVisitor<'a, 'r> {
    type Error = Error;
    type Variant = VariantVisitor<'a, 'r>;

    fn visit_variant_seed<V>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self::Variant)>
        where V: DeserializeSeed
    {
        Ok((seed.deserialize(&mut *self.de)?, self))
    }
}

impl<'a, 'r> de::VariantVisitor for VariantVisitor<'a, 'r> {
    type Error = Error;

    fn visit_unit(self) -> Result<()> {
        Deserialize::deserialize(self.de)
    }

    fn visit_newtype_seed<T>(self, seed: T) -> Result<T::Value>
        where T: DeserializeSeed
    {
        seed.deserialize(self.de)
    }

    fn visit_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        de::Deserializer::deserialize(self.de, visitor)
    }

    fn visit_struct<V>(
        self,
        _fields: &'static [&'static str],
        visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor
    {
        de::Deserializer::deserialize(self.de, visitor)
    }
}

struct UnitVariantVisitor<'a: 'r, 'r> {
    de: &'r mut Deserializer<'a>,
}

impl<'a, 'r> de::EnumVisitor for UnitVariantVisitor<'a, 'r> {
    type Error = Error;
    type Variant = Self;

    fn visit_variant_seed<V>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self::Variant)>
        where V: DeserializeSeed
    {
        Ok((seed.deserialize(&mut *self.de)?, self))
    }
}

impl<'a, 'r> de::VariantVisitor for UnitVariantVisitor<'a, 'r> {
    type Error = Error;

    fn visit_unit(self) -> Result<()> {
        Ok(())
    }

    fn visit_newtype_seed<T>(self, _seed: T) -> Result<T::Value>
        where T: DeserializeSeed
    {
        Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"))
    }

    fn visit_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"))
    }

    fn visit_struct<V>(
        self,
        _fields: &'static [&'static str],
        _visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor
    {
        Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"))
    }
}

fn visit_untagged_str<V>(visitor: V, v: &str) -> Result<V::Value>
    where V: de::Visitor
{
    if v == "~" || v == "null" {
        return visitor.visit_unit();
    }
    if v == "true" {
        return visitor.visit_bool(true);
    }
    if v == "false" {
        return visitor.visit_bool(false);
    }
    if v.starts_with("0x") {
        if let Ok(n) = i64::from_str_radix(&v[2..], 16) {
            return visitor.visit_i64(n);
        }
    }
    if v.starts_with("0o") {
        if let Ok(n) = i64::from_str_radix(&v[2..], 8) {
            return visitor.visit_i64(n);
        }
    }
    if v.starts_with('+') {
        if let Ok(n) = v[1..].parse() {
            return visitor.visit_i64(n);
        }
    }
    if let Ok(n) = v.parse() {
        return visitor.visit_i64(n);
    }
    if let Ok(n) = v.parse() {
        return visitor.visit_f64(n);
    }
    visitor.visit_str(v)
}

impl<'a, 'r> de::Deserializer for &'r mut Deserializer<'a> {
    type Error = Error;

    fn deserialize<V>(self, visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        match *self.next()? {
            Event::Alias(i) => self.jump(i)?.deserialize(visitor),
            Event::Scalar(ref v, style, ref tag) => {
                if style != TScalarStyle::Plain {
                    visitor.visit_str(v)
                } else if let Some(TokenType::Tag(ref handle, ref suffix)) = *tag {
                    if handle == "!!" {
                        match suffix.as_ref() {
                            "bool" => {
                                match v.parse::<bool>() {
                                    Ok(v) => visitor.visit_bool(v),
                                    Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"a boolean")),
                                }
                            },
                            "int" => {
                                match v.parse::<i64>() {
                                    Ok(v) => visitor.visit_i64(v),
                                    Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"an integer")),
                                }
                            },
                            "float" => {
                                match v.parse::<f64>() {
                                    Ok(v) => visitor.visit_f64(v),
                                    Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"a float")),
                                }
                            },
                            "null" => {
                                match v.as_ref() {
                                    "~" | "null" => visitor.visit_unit(),
                                    _ => Err(de::Error::invalid_value(Unexpected::Str(v), &"null")),
                                }
                            }
                            _  => visitor.visit_str(v),
                        }
                    } else {
                        visitor.visit_str(v)
                    }
                } else {
                    visit_untagged_str(visitor, v)
                }
            }
            Event::SequenceStart => {
                let value = visitor.visit_seq(&mut *self)?;
                match *self.next()? {
                    Event::SequenceEnd => Ok(value),
                    _ => Err(de::Error::custom("remaining elements in sequence")), // FIXME
                }
            }
            Event::MappingStart => {
                let value = visitor.visit_map(&mut *self)?;
                match *self.next()? {
                    Event::MappingEnd => Ok(value),
                    _ => Err(de::Error::custom("remaining elements in map")), // FIXME
                }
            }
            Event::SequenceEnd | Event::MappingEnd => Err(Error::EndOfStream), // FIXME
        }
    }

    /// Parses `null` as None and any other values as `Some(...)`.
    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        let is_some = match *self.peek()? {
            Event::Alias(i) => return self.jump(i)?.deserialize_option(visitor),
            Event::Scalar(ref v, style, ref tag) => {
                if style != TScalarStyle::Plain {
                    true
                } else if let Some(TokenType::Tag(ref handle, ref suffix)) = *tag {
                    if handle == "!!" && suffix == "null" {
                        if v == "~" || v == "null" {
                            false
                        } else {
                            return Err(de::Error::custom("failed to parse null")); // FIXME
                        }
                    } else {
                        true
                    }
                } else {
                    v != "~" && v != "null"
                }
            }
            Event::SequenceStart | Event::MappingStart => true,
            Event::SequenceEnd | Event::MappingEnd => return Err(Error::EndOfStream), // FIXME
        };
        if is_some {
            visitor.visit_some(self)
        } else {
            self.pos += 1;
            visitor.visit_none()
        }
    }

    /// Parses a newtype struct as the underlying value.
    fn deserialize_newtype_struct<V>(
        self,
        _name: &str,
        visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor
    {
        visitor.visit_newtype_struct(self)
    }

    /// Parses an enum as a single key:value pair where the key identifies the
    /// variant and the value gives the content. A String will also parse correctly
    /// to a unit enum value.
    fn deserialize_enum<V>(
        self,
        name: &str,
        _variants: &'static [&'static str],
        visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor
    {
        match *self.peek()? {
            Event::MappingStart => {
                self.pos += 1;
                let value = visitor.visit_enum(VariantVisitor { de: self })?;
                match *self.next()? {
                    Event::MappingEnd => Ok(value),
                    _ => Err(Error::VariantMapWrongSize(name.to_owned(), 2)), // FIXME
                }
            }
            Event::Scalar(_, _, _) => {
                visitor.visit_enum(UnitVariantVisitor { de: self })
            }
            _ => Err(Error::VariantNotAMapOrString(name.to_owned())),
        }
    }

    forward_to_deserialize!{
        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
        seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
        struct_field tuple ignored_any
    }
}

/// Decodes a YAML value from a `&str`.
pub fn from_str<T>(s: &str) -> Result<T>
    where T: Deserialize
{
    let mut parser = Parser::new(s.chars());
    let mut loader = Loader {
        events: Vec::new(),
        aliases: BTreeMap::new(),
    };
    parser.load(&mut loader, true)?;
    if loader.events.is_empty() {
        Err(Error::EndOfStream)
    } else {
        let mut deserializer = Deserializer {
            events: &loader.events,
            aliases: &loader.aliases,
            pos: 0,
        };
        let t = Deserialize::deserialize(&mut deserializer)?;
        if deserializer.pos == loader.events.len() {
            Ok(t)
        } else {
            Err(Error::MoreThanOneDocument)
        }
    }
}

pub fn from_iter<I, T>(iter: I) -> Result<T>
    where I: Iterator<Item = io::Result<u8>>,
          T: Deserialize
{
    let bytes: Vec<u8> = try!(iter.collect());
    from_str(str::from_utf8(&bytes)?)
}

pub fn from_reader<R, T>(rdr: R) -> Result<T>
    where R: io::Read,
          T: Deserialize
{
    from_iter(rdr.bytes())
}

pub fn from_slice<T>(v: &[u8]) -> Result<T>
    where T: Deserialize
{
    from_iter(v.iter().map(|byte| Ok(*byte)))
}
<|endoftext|>


<commit_before>use std::io::Read;

use common::Solution;

fn power_at(serial: i32, (x, y): (i32, i32)) -> i32 {
    let rack_id = x + 10;
    let mut power_level = rack_id * y;
    power_level += serial;
    power_level *= rack_id;
    power_level = (power_level % 1000) / 100;
    power_level - 5
}

#[derive(Default)]
pub struct Day11 {}

impl Day11 {
    pub fn new() -> Self {
        Default::default()
    }
}

impl Solution for Day11 {
    fn part1(&mut self, input: &mut Read) -> String {
        let mut data = String::new();
        input.read_to_string(&mut data).unwrap();
        let serial = data.trim().parse().unwrap();

        let mut best_coordinates: Option<(i32, i32)> = None;
        let mut best_result = 0;

        for y in 1..=298 {
            let mut running_sum = 0;
            let mut slide = [0i32;3];

            for x in 1..298 {
                let new_sum = (y..=(y+2)).map(|y| power_at(serial, (x, y))).sum();
                running_sum += new_sum;

                if x >= 3 {
                    running_sum -= slide[(x as usize) % 3];
                    if running_sum > best_result {
                        best_result = running_sum;
                        best_coordinates = Some((x - 2, y));
                    }
                }

                slide[(x as usize) % 3] = new_sum;
            }
        }

        let (x, y) = best_coordinates.unwrap();

        format!("{},{}", x, y)
    }

    fn part2(&mut self, _input: &mut Read) -> String {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_power_at() {
        assert_eq!(4, power_at(8, (3, 5)));
        assert_eq!(-5, power_at(57, (122, 79)));
        assert_eq!(0, power_at(39, (217, 196)));
        assert_eq!(4, power_at(71, (101, 153)));
    }

    #[test]
    fn sample_part1() {
        let mut instance = Day11::new();
        assert_eq!("33,45", instance.part1(&mut b"18".as_ref()));
        assert_eq!("21,61", instance.part1(&mut b"42".as_ref()));
    }
}
<commit_msg>Implement day 11 part 2.<commit_after>use std::io::Read;

use common::Solution;

fn power_at(serial: i32, (x, y): (i32, i32)) -> i32 {
    let rack_id = x + 10;
    let mut power_level = rack_id * y;
    power_level += serial;
    power_level *= rack_id;
    power_level = (power_level % 1000) / 100;
    power_level - 5
}

#[derive(Default)]
pub struct Day11 {}

impl Day11 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_serial(&self, input: &mut Read) -> i32 {
        let mut data = String::new();
        input.read_to_string(&mut data).unwrap();
        data.trim().parse().unwrap()
    }

    fn best(&self, serial: i32, size: i32) -> (i32, i32, i32) {
        let mut best_coordinates: Option<(i32, i32)> = None;
        let mut best_result = 0;

        let mut slide = vec![0i32;size as usize];
        let mut running_sum = 0;
        for y in 1..=(301 - size) {
            for x in 1..=300 {
                let new_sum = (y..(y+size)).map(|y| power_at(serial, (x, y))).sum();
                running_sum -= slide[(x % size) as usize];
                running_sum += new_sum;
                slide[(x % size) as usize] = new_sum;

                if x >= size {
                    if running_sum > best_result {
                        best_result = running_sum;
                        best_coordinates = Some((x + 1 - size, y));
                    }
                }
            }
        }

        let (x, y) = best_coordinates.unwrap();

        (x, y, best_result)
    }
}

impl Solution for Day11 {
    fn part1(&mut self, input: &mut Read) -> String {
        let serial = self.read_serial(input);
        let (x, y, _) = self.best(serial, 3);

        format!("{},{}", x, y)
    }

    fn part2(&mut self, input: &mut Read) -> String {
        let serial = self.read_serial(input);
        let mut best_result = 0;
        let mut best_option = None;
        for size in 1..=300 {
            let (x, y, result) = self.best(serial, size);
            if result > best_result {
                best_result = result;
                best_option = Some((x, y, size));
            } else if result < best_result {
                break;
            }
        }
        let (x, y, size) = best_option.unwrap();
        format!("{},{},{}", x, y, size)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_power_at() {
        assert_eq!(4, power_at(8, (3, 5)));
        assert_eq!(-5, power_at(57, (122, 79)));
        assert_eq!(0, power_at(39, (217, 196)));
        assert_eq!(4, power_at(71, (101, 153)));
    }

    #[test]
    fn sample_part1() {
        let mut instance = Day11::new();
        assert_eq!("33,45", instance.part1(&mut b"18".as_ref()));
        assert_eq!("21,61", instance.part1(&mut b"42".as_ref()));
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day11::new();
        assert_eq!("90,269,16", instance.part2(&mut b"18".as_ref()));
        assert_eq!("232,251,12", instance.part2(&mut b"42".as_ref()));
    }
}
<|endoftext|>


<commit_before>use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use common::Solution;

type Coordinate = (usize, usize);

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Direction {
    North,
    South,
    West,
    East,
}

impl Direction {
    pub fn from_char(c: char) -> Self {
        match c {
            '^' => Direction::North,
            '<' => Direction::West,
            '>' => Direction::East,
            'v' => Direction::South,
            _ => panic!("Invalid direction {}", c),
        }
    }
    pub fn clockwise(&self) -> Self {
        match self {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::North,
        }
    }

    pub fn counter_clockwise(&self) -> Self {
        return self.clockwise().clockwise().clockwise();
    }

    pub fn run(&self, pos: Coordinate) -> Coordinate {
        let (x, y) = pos;
        match self {
            Direction::North => (x, y - 1),
            Direction::South => (x, y + 1),
            Direction::West => (x - 1, y),
            Direction::East => (x + 1, y),
        }
    }
}

#[derive(Default, Debug)]
pub struct Day13 {
    grid: Vec<Vec<char>>,
    carts: Vec<(Coordinate, Direction, usize, bool)>,
}

impl Day13 {
    pub fn new() -> Self {
        Default::default()
    }

    fn alive(&self) -> usize {
        self.carts.iter().filter(|(_, _, _, x)| *x).count()
    }

    fn read_input(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        for (y, line) in reader.lines().enumerate() {
            let line = line.unwrap();
            let mut current = Vec::new();
            for (x, c) in line.chars().enumerate() {
                match c {
                    '^' | 'v' => {
                        current.push('|');
                        let direction = Direction::from_char(c);
                        self.carts.push(((x, y), direction, 0, true));
                    }
                    '>' | '<' => {
                        current.push('-');
                        let direction = Direction::from_char(c);
                        self.carts.push(((x, y), direction, 0, true));
                    }
                    other => current.push(other),
                }
            }
            self.grid.push(current);
        }
    }

    fn simulate(&mut self) -> Option<Coordinate> {
        let mut collision = None;
        self.carts.sort_unstable_by_key(|&((x, y), _, _ , _)| (y, x));
        for i in 0..self.carts.len() {
            {
                let (coordinate, direction, turns, alive) = self.carts.get_mut(i).unwrap();
                if !*alive {
                    continue;
                }
                *coordinate = direction.run(*coordinate);
                let &mut (x, y) = coordinate;
                *direction = match self.grid[y][x] {
                    '|' | '-' => *direction,
                    '+' => {
                        let new_dir = match turns {
                            0 => direction.counter_clockwise(),
                            1 => *direction,
                            2 => direction.clockwise(),
                            _ => unreachable!(),
                        };

                        *turns = (*turns + 1) % 3;
                        new_dir
                    },
                    '/' => match *direction {
                        Direction::North | Direction::South => direction.clockwise(),
                        Direction::West | Direction::East => direction.counter_clockwise(),
                    },
                    '\\' => match *direction {
                        Direction::North | Direction::South => direction.counter_clockwise(),
                        Direction::West | Direction::East => direction.clockwise(),
                    },
                    val => panic!("Invalid tile to be on: {}", val),
                };
            }
            for j in 0..self.carts.len() {
                if i == j {
                    continue;
                }
                if !self.carts[i].3 {
                    break;
                }
                if !self.carts[j].3 {
                    continue;
                }

                if self.carts[i].0 == self.carts[j].0 {
                    self.carts[i].3 = false;
                    self.carts[j].3 = false;
                    collision = Some(self.carts[i].0);
                }
            }
        }

        collision
    }
}

impl Solution for Day13 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        let mut collision = None;
        while collision == None {
            collision = self.simulate();
        }
        let (x, y) = collision.unwrap();
        format!("{},{}", x, y)
    }

    fn part2(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        while self.alive() > 1 {
            self.simulate();
        }

        for &((x, y), _, _, alive) in &self.carts {
            if alive {
                return format!("{},{}", x, y)
            }
        }
        unreachable!()
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day13::Day13;
    use day13::Direction;

    const SAMPLE1_INPUT: &[u8] = include_bytes!("samples/13.1.txt");
    const SAMPLE2_INPUT: &[u8] = include_bytes!("samples/13.2.txt");

    #[test]
    fn test_turning() {
        assert_eq!(Direction::East, Direction::South.counter_clockwise());
    }

    #[test]
    fn sample_part1() {
        let mut instance = Day13::new();
        assert_eq!("7,3", instance.part1(&mut SAMPLE1_INPUT))
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day13::new();
        assert_eq!("6,4", instance.part2(&mut SAMPLE2_INPUT))
    }
}
<commit_msg>Slightly cleaned up by using structs.<commit_after>use std::cmp::Ordering;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use common::Solution;

type Coordinate = (usize, usize);

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Direction {
    North,
    South,
    West,
    East,
}

impl Direction {
    pub fn from_char(c: char) -> Self {
        match c {
            '^' => Direction::North,
            '<' => Direction::West,
            '>' => Direction::East,
            'v' => Direction::South,
            _ => panic!("Invalid direction {}", c),
        }
    }
    pub fn clockwise(&self) -> Self {
        match self {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::North,
        }
    }

    pub fn counter_clockwise(&self) -> Self {
        return self.clockwise().clockwise().clockwise();
    }

    pub fn run(&self, pos: Coordinate) -> Coordinate {
        let (x, y) = pos;
        match self {
            Direction::North => (x, y - 1),
            Direction::South => (x, y + 1),
            Direction::West => (x - 1, y),
            Direction::East => (x + 1, y),
        }
    }
}

#[derive(Copy, Clone, Eq, PartialEq)]
struct Cart {
    coordinate: Coordinate,
    direction: Direction,
    turns: u8,
    alive: bool,
}

impl Cart {
    pub fn new(coordinate: Coordinate, direction: Direction) -> Self {
        Cart {
            coordinate,
            direction,
            turns: 0,
            alive: true,
        }
    }
}

impl Ord for Cart {
    fn cmp(&self, other: &Self) -> Ordering {
        let (sx, sy) = self.coordinate;
        let (ox, oy) = other.coordinate;

        (sy, sx).cmp(&(oy, ox))
    }
}

impl PartialOrd for Cart {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Default)]
pub struct Day13 {
    grid: Vec<Vec<char>>,
    carts: Vec<Cart>,
}

impl Day13 {
    pub fn new() -> Self {
        Default::default()
    }

    fn alive(&self) -> usize {
        self.carts.iter().filter(|x| x.alive).count()
    }

    fn read_input(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        for (y, line) in reader.lines().enumerate() {
            let line = line.unwrap();
            let mut current = Vec::new();
            for (x, c) in line.chars().enumerate() {
                match c {
                    '^' | 'v' => {
                        current.push('|');
                        let direction = Direction::from_char(c);
                        self.carts.push(Cart::new((x, y), direction));
                    }
                    '>' | '<' => {
                        current.push('-');
                        let direction = Direction::from_char(c);
                        self.carts.push(Cart::new((x, y), direction));
                    }
                    other => current.push(other),
                }
            }
            self.grid.push(current);
        }
    }

    fn simulate(&mut self) -> Option<Coordinate> {
        let mut collision = None;
        self.carts.sort_unstable();
        for i in 0..self.carts.len() {
            if !self.carts[i].alive {
                continue;
            }
            let current_direction = self.carts[i].direction;

            self.carts[i].coordinate = current_direction.run(self.carts[i].coordinate);
            let (x, y) = self.carts[i].coordinate;
            let current_direction = self.carts[i].direction;
            self.carts[i].direction = match self.grid[y][x] {
                '|' | '-' => current_direction,
                '+' => {
                    let turns = self.carts[i].turns;
                    let new_dir = match turns {
                        0 => current_direction.counter_clockwise(),
                        1 => current_direction,
                        2 => current_direction.clockwise(),
                        _ => unreachable!(),
                    };

                    self.carts[i].turns = (turns + 1) % 3;
                    new_dir
                }
                '/' => match current_direction {
                    Direction::North | Direction::South => current_direction.clockwise(),
                    Direction::West | Direction::East => current_direction.counter_clockwise(),
                },
                '\\' => match current_direction {
                    Direction::North | Direction::South => current_direction.counter_clockwise(),
                    Direction::West | Direction::East => current_direction.clockwise(),
                },
                val => panic!("Invalid tile to be on: {}", val),
            };

            for j in 0..self.carts.len() {
                if i == j {
                    continue;
                }
                if !self.carts[i].alive {
                    break;
                }
                if !self.carts[j].alive {
                    continue;
                }

                if self.carts[i].coordinate == self.carts[j].coordinate {
                    self.carts[i].alive = false;
                    self.carts[j].alive = false;
                    collision = Some(self.carts[i].coordinate);
                }
            }
        }

        collision
    }
}

impl Solution for Day13 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        let mut collision = None;
        while collision == None {
            collision = self.simulate();
        }
        let (x, y) = collision.unwrap();
        format!("{},{}", x, y)
    }

    fn part2(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        while self.alive() > 1 {
            self.simulate();
        }

        for cart in &self.carts {
            if cart.alive {
                let (x, y) = cart.coordinate;
                return format!("{},{}", x, y);
            }
        }
        unreachable!()
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day13::Day13;
    use day13::Direction;

    const SAMPLE1_INPUT: &[u8] = include_bytes!("samples/13.1.txt");
    const SAMPLE2_INPUT: &[u8] = include_bytes!("samples/13.2.txt");

    #[test]
    fn test_turning() {
        assert_eq!(Direction::East, Direction::South.counter_clockwise());
    }

    #[test]
    fn sample_part1() {
        let mut instance = Day13::new();
        assert_eq!("7,3", instance.part1(&mut SAMPLE1_INPUT))
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day13::new();
        assert_eq!("6,4", instance.part2(&mut SAMPLE2_INPUT))
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod std;

use std::net::tcp::TcpSocketBuf;

use core::io::{ReaderUtil,WriterUtil};

enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

priv fn parse_data(len: uint, io: @io::Reader) -> Result {
  let res =
      if (len > 0) {
      let bytes = io.read_bytes(len as uint);
      fail_unless!(bytes.len() == len);
      Data(bytes)
  } else {
      Data(~[])
  };
  fail_unless!(io.read_char() == '\r');
  fail_unless!(io.read_char() == '\n');
  return res;
}

priv fn parse_list(len: uint, io: @io::Reader) -> Result {
  let mut list: ~[Result] = ~[];
    for len.times {
    let v =
        match io.read_char() {
        '$' => parse_bulk(io),
        ':' => parse_int(io),
         _ => fail!()
    };
    list.push(v);
    }
  return List(list);
}

priv fn chop(s: ~str) -> ~str {
  s.slice(0, s.len() - 1).to_owned()
}

priv fn parse_bulk(io: @io::Reader) -> Result {
    match int::from_str(chop(io.read_line())) {
    None => fail!(),
    Some(-1) => Nil,
    Some(len) if len >= 0 => parse_data(len as uint, io),
    Some(_) => fail!()
    }
}

priv fn parse_multi(io: @io::Reader) -> Result {
    match int::from_str(chop(io.read_line())) {
    None => fail!(),
    Some(-1) => Nil,
    Some(0) => List(~[]),
    Some(len) if len >= 0 => parse_list(len as uint, io),
    Some(_) => fail!()
    }
}

priv fn parse_int(io: @io::Reader) -> Result {
    match int::from_str(chop(io.read_line())) {
    None => fail!(),
    Some(i) => Int(i)
    }
}

priv fn parse_response(io: @io::Reader) -> Result {
    match io.read_char() {
    '$' => parse_bulk(io),
    '*' => parse_multi(io),
    '+' => Status(chop(io.read_line())),
    '-' => Error(chop(io.read_line())),
    ':' => parse_int(io),
    _ => fail!()
    }
}

priv fn cmd_to_str(cmd: ~[~str]) -> ~str {
  let mut res = ~"*";
  str::push_str(&mut res, cmd.len().to_str());
  str::push_str(&mut res, "\r\n");
    for cmd.each |s| {
    str::push_str(&mut res, str::concat(~[~"$", s.len().to_str(), ~"\r\n",
                                          copy *s, ~"\r\n"]));
    }
  res
}

fn query(cmd: ~[~str], sb: TcpSocketBuf) -> Result {
  let cmd = cmd_to_str(cmd);
  //io::println(cmd);
  sb.write_str(cmd);
  let res = parse_response(@sb as @io::Reader);
  //io::println(fmt!("%?", res));
  res
}

fn query2(cmd: ~[~str]) -> Result {
  let _cmd = cmd_to_str(cmd);
    do io::with_str_reader(~"$3\r\nXXX\r\n") |sb| {
    let res = parse_response(@sb as @io::Reader);
    io::println(fmt!("%?", res));
    res
    }
}

fn main() {
}
<commit_msg>Oh, cool, I xfailed the wrong test, neat<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// xfail-test
extern mod std;

use std::net::tcp::TcpSocketBuf;

use core::io::{ReaderUtil,WriterUtil};

enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

priv fn parse_data(len: uint, io: @io::Reader) -> Result {
  let res =
      if (len > 0) {
      let bytes = io.read_bytes(len as uint);
      fail_unless!(bytes.len() == len);
      Data(bytes)
  } else {
      Data(~[])
  };
  fail_unless!(io.read_char() == '\r');
  fail_unless!(io.read_char() == '\n');
  return res;
}

priv fn parse_list(len: uint, io: @io::Reader) -> Result {
  let mut list: ~[Result] = ~[];
    for len.times {
    let v =
        match io.read_char() {
        '$' => parse_bulk(io),
        ':' => parse_int(io),
         _ => fail!()
    };
    list.push(v);
    }
  return List(list);
}

priv fn chop(s: ~str) -> ~str {
  s.slice(0, s.len() - 1).to_owned()
}

priv fn parse_bulk(io: @io::Reader) -> Result {
    match int::from_str(chop(io.read_line())) {
    None => fail!(),
    Some(-1) => Nil,
    Some(len) if len >= 0 => parse_data(len as uint, io),
    Some(_) => fail!()
    }
}

priv fn parse_multi(io: @io::Reader) -> Result {
    match int::from_str(chop(io.read_line())) {
    None => fail!(),
    Some(-1) => Nil,
    Some(0) => List(~[]),
    Some(len) if len >= 0 => parse_list(len as uint, io),
    Some(_) => fail!()
    }
}

priv fn parse_int(io: @io::Reader) -> Result {
    match int::from_str(chop(io.read_line())) {
    None => fail!(),
    Some(i) => Int(i)
    }
}

priv fn parse_response(io: @io::Reader) -> Result {
    match io.read_char() {
    '$' => parse_bulk(io),
    '*' => parse_multi(io),
    '+' => Status(chop(io.read_line())),
    '-' => Error(chop(io.read_line())),
    ':' => parse_int(io),
    _ => fail!()
    }
}

priv fn cmd_to_str(cmd: ~[~str]) -> ~str {
  let mut res = ~"*";
  str::push_str(&mut res, cmd.len().to_str());
  str::push_str(&mut res, "\r\n");
    for cmd.each |s| {
    str::push_str(&mut res, str::concat(~[~"$", s.len().to_str(), ~"\r\n",
                                          copy *s, ~"\r\n"]));
    }
  res
}

fn query(cmd: ~[~str], sb: TcpSocketBuf) -> Result {
  let cmd = cmd_to_str(cmd);
  //io::println(cmd);
  sb.write_str(cmd);
  let res = parse_response(@sb as @io::Reader);
  //io::println(fmt!("%?", res));
  res
}

fn query2(cmd: ~[~str]) -> Result {
  let _cmd = cmd_to_str(cmd);
    do io::with_str_reader(~"$3\r\nXXX\r\n") |sb| {
    let res = parse_response(@sb as @io::Reader);
    io::println(fmt!("%?", res));
    res
    }
}

fn main() {
}
<|endoftext|>


<commit_before>use role_playing_game::*;

#[test]
fn test_reviving_dead_player() {
    let dead_player = Player {
        health: 0,
        mana: Some(0),
        level: 34,
    };
    let revived_player = dead_player
        .revive()
        .expect("reviving a dead player must return Some(player)");
    assert_eq!(revived_player.health, 100);
    assert_eq!(revived_player.mana, Some(100));
    assert_eq!(revived_player.level, dead_player.level);
}

#[test]
#[ignore]
fn test_reviving_alive_player() {
    let alive_player = Player {
        health: 1,
        mana: None,
        level: 8,
    };
    assert!(alive_player.revive().is_none());
}

#[test]
#[ignore]
fn test_cast_spell_with_enough_mana() {
    const HEALTH: u32 = 99;
    const MANA: u32 = 100;
    const LEVEL: u32 = 100;
    const MANA_COST: u32 = 3;

    let mut accomplished_wizard = Player {
        health: HEALTH,
        mana: Some(MANA),
        level: LEVEL,
    };

    assert_eq!(accomplished_wizard.cast_spell(MANA_COST), MANA_COST * 2);
    assert_eq!(accomplished_wizard.health, HEALTH);
    assert_eq!(accomplished_wizard.mana, Some(MANA - MANA_COST));
    assert_eq!(accomplished_wizard.level, LEVEL);
}

#[test]
#[ignore]
fn test_cast_spell_with_insufficient_mana() {
    let mut no_mana_wizard = Player {
        health: 56,
        mana: Some(2),
        level: 22,
    };

    // we want to clone so we can compare before-and-after effects of casting the spell,
    // but we don't want to introduce that concept to the student yet, so we have to do it manually
    let clone = Player { ..no_mana_wizard };

    assert_eq!(no_mana_wizard.cast_spell(3), 0);
    assert_eq!(no_mana_wizard.health, clone.health);
    assert_eq!(no_mana_wizard.mana, clone.mana);
    assert_eq!(no_mana_wizard.level, clone.level);
}

#[test]
#[ignore]
fn test_cast_spell_with_no_mana_pool() {
    const MANA_COST: u32 = 10;

    let mut underleveled_player = Player {
        health: 87,
        mana: None,
        level: 6,
    };

    let clone = Player {
        ..underleveled_player
    };

    assert_eq!(underleveled_player.cast_spell(MANA_COST), 0);
    assert_eq!(underleveled_player.health, clone.health - MANA_COST);
    assert_eq!(underleveled_player.mana, clone.mana);
    assert_eq!(underleveled_player.level, clone.level);
}

#[test]
#[ignore]
fn test_cast_large_spell_with_no_mana_pool() {
    const MANA_COST: u32 = 30;

    let mut underleveled_player = Player {
        health: 20,
        mana: None,
        level: 6,
    };

    assert_eq!(underleveled_player.cast_spell(MANA_COST), 0);
    assert_eq!(underleveled_player.health, 0);
    assert_eq!(underleveled_player.mana, None);
    assert_eq!(underleveled_player.level, 6);
}
<commit_msg>add tests (#1364)<commit_after>use role_playing_game::*;

#[test]
fn test_reviving_dead_player() {
    let dead_player = Player {
        health: 0,
        mana: Some(0),
        level: 34,
    };
    let revived_player = dead_player
        .revive()
        .expect("reviving a dead player must return Some(player)");
    assert_eq!(revived_player.health, 100);
    assert_eq!(revived_player.mana, Some(100));
    assert_eq!(revived_player.level, dead_player.level);
}

#[test]
#[ignore]
fn test_reviving_dead_level9_player() {
    let dead_player = Player {
        health: 0,
        mana: Some(0),
        level: 9,
    };
    let revived_player = dead_player
        .revive()
        .expect("reviving a dead player must return Some(player)");
    assert_eq!(revived_player.health, 100);
    assert_eq!(revived_player.mana, None);
    assert_eq!(revived_player.level, dead_player.level);
}

#[test]
#[ignore]
fn test_reviving_dead_level10_player() {
    let dead_player = Player {
        health: 0,
        mana: Some(0),
        level: 10,
    };
    let revived_player = dead_player
        .revive()
        .expect("reviving a dead player must return Some(player)");
    assert_eq!(revived_player.health, 100);
    assert_eq!(revived_player.mana, Some(100));
    assert_eq!(revived_player.level, dead_player.level);
}

#[test]
#[ignore]
fn test_reviving_alive_player() {
    let alive_player = Player {
        health: 1,
        mana: None,
        level: 8,
    };
    assert!(alive_player.revive().is_none());
}

#[test]
#[ignore]
fn test_cast_spell_with_enough_mana() {
    const HEALTH: u32 = 99;
    const MANA: u32 = 100;
    const LEVEL: u32 = 100;
    const MANA_COST: u32 = 3;

    let mut accomplished_wizard = Player {
        health: HEALTH,
        mana: Some(MANA),
        level: LEVEL,
    };

    assert_eq!(accomplished_wizard.cast_spell(MANA_COST), MANA_COST * 2);
    assert_eq!(accomplished_wizard.health, HEALTH);
    assert_eq!(accomplished_wizard.mana, Some(MANA - MANA_COST));
    assert_eq!(accomplished_wizard.level, LEVEL);
}

#[test]
#[ignore]
fn test_cast_spell_with_insufficient_mana() {
    let mut no_mana_wizard = Player {
        health: 56,
        mana: Some(2),
        level: 22,
    };

    // we want to clone so we can compare before-and-after effects of casting the spell,
    // but we don't want to introduce that concept to the student yet, so we have to do it manually
    let clone = Player { ..no_mana_wizard };

    assert_eq!(no_mana_wizard.cast_spell(3), 0);
    assert_eq!(no_mana_wizard.health, clone.health);
    assert_eq!(no_mana_wizard.mana, clone.mana);
    assert_eq!(no_mana_wizard.level, clone.level);
}

#[test]
#[ignore]
fn test_cast_spell_with_no_mana_pool() {
    const MANA_COST: u32 = 10;

    let mut underleveled_player = Player {
        health: 87,
        mana: None,
        level: 6,
    };

    let clone = Player {
        ..underleveled_player
    };

    assert_eq!(underleveled_player.cast_spell(MANA_COST), 0);
    assert_eq!(underleveled_player.health, clone.health - MANA_COST);
    assert_eq!(underleveled_player.mana, clone.mana);
    assert_eq!(underleveled_player.level, clone.level);
}

#[test]
#[ignore]
fn test_cast_large_spell_with_no_mana_pool() {
    const MANA_COST: u32 = 30;

    let mut underleveled_player = Player {
        health: 20,
        mana: None,
        level: 6,
    };

    assert_eq!(underleveled_player.cast_spell(MANA_COST), 0);
    assert_eq!(underleveled_player.health, 0);
    assert_eq!(underleveled_player.mana, None);
    assert_eq!(underleveled_player.level, 6);
}
<|endoftext|>


<commit_before>#[link(name = "bob", vers = "1.0")];
#[crate_type = "lib"];

extern mod std;

mod bob;

#[test]
fn test_statement() {
    assert_eq!("Whatever.", bob::reply("Tom-ay-to, tom-aaaah-to."));
}

#[test]
fn test_shouting() {
    assert_eq!("Woah, chill out!", bob::reply("WATCH OUT!"));
}

#[test]
fn test_exclaiming() {
    assert_eq!("Whatever.", bob::reply("Let's go make out behind the gym!"));
}

#[test]
fn test_asking() {
    assert_eq!("Sure.", bob::reply("Does this cryogenic chamber make me look fat?"));
}

#[test]
fn test_shout_numbers() {
    assert_eq!("Woah, chill out!", bob::reply("1, 2, 3 GO!"));
}

#[test]
fn test_shout_weird_characters() {
    assert_eq!("Woah, chill out!", bob::reply("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"));
}

#[test]
fn test_shout_without_punctuation() {
    assert_eq!("Woah, chill out!", bob::reply("I HATE YOU"));
}

#[test]
fn test_shout_without_question_mark() {
    assert_eq!("Whatever.", bob::reply("Ending with ? means a question."));
}

#[test]
fn test_silent_treatment() {
    assert_eq!("Fine. Be that way.", bob::reply(""));
}

<commit_msg>Rust: Bob: Re-add unit test skips<commit_after>#[link(name = "bob", vers = "1.0")];
#[crate_type = "lib"];

extern mod std;

mod bob;

#[test]
#[should_fail]
fn test_statement() {
    assert_eq!("Whatever.", bob::reply("Tom-ay-to, tom-aaaah-to."));
}

#[test]
#[should_fail]
fn test_shouting() {
    assert_eq!("Woah, chill out!", bob::reply("WATCH OUT!"));
}

#[test]
#[should_fail]
fn test_exclaiming() {
    assert_eq!("Whatever.", bob::reply("Let's go make out behind the gym!"));
}

#[test]
#[should_fail]
fn test_asking() {
    assert_eq!("Sure.", bob::reply("Does this cryogenic chamber make me look fat?"));
}

#[test]
#[should_fail]
fn test_shout_numbers() {
    assert_eq!("Woah, chill out!", bob::reply("1, 2, 3 GO!"));
}

#[test]
#[should_fail]
fn test_shout_weird_characters() {
    assert_eq!("Woah, chill out!", bob::reply("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"));
}

#[test]
#[should_fail]
fn test_shout_without_punctuation() {
    assert_eq!("Woah, chill out!", bob::reply("I HATE YOU"));
}

#[test]
#[should_fail]
fn test_shout_without_question_mark() {
    assert_eq!("Whatever.", bob::reply("Ending with ? means a question."));
}

#[test]
#[should_fail]
fn test_silent_treatment() {
    assert_eq!("Fine. Be that way.", bob::reply(""));
}

<|endoftext|>


<commit_before>#![feature(portable_simd, platform_intrinsics)]
use std::simd::*;

fn simd_ops_f32() {
    let a = f32x4::splat(10.0);
    let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
    assert_eq!(-b, f32x4::from_array([-1.0, -2.0, -3.0, 4.0]));
    assert_eq!(a + b, f32x4::from_array([11.0, 12.0, 13.0, 6.0]));
    assert_eq!(a - b, f32x4::from_array([9.0, 8.0, 7.0, 14.0]));
    assert_eq!(a * b, f32x4::from_array([10.0, 20.0, 30.0, -40.0]));
    assert_eq!(b / a, f32x4::from_array([0.1, 0.2, 0.3, -0.4]));
    assert_eq!(a / f32x4::splat(2.0), f32x4::splat(5.0));
    assert_eq!(a % b, f32x4::from_array([0.0, 0.0, 1.0, 2.0]));
    assert_eq!(b.abs(), f32x4::from_array([1.0, 2.0, 3.0, 4.0]));

    // FIXME use Mask::from_array once simd_cast is implemented.
    assert_eq!(a.lanes_eq(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([0, -1, 0, 0])));
    assert_eq!(a.lanes_ne(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([-1, 0, -1, -1])));
    assert_eq!(a.lanes_le(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([0, -1, -1, 0])));
    assert_eq!(a.lanes_lt(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([0, 0, -1, 0])));
    assert_eq!(a.lanes_ge(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([-1, -1, 0, -1])));
    assert_eq!(a.lanes_gt(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([-1, 0, 0, -1])));
}

fn simd_ops_f64() {
    let a = f64x4::splat(10.0);
    let b = f64x4::from_array([1.0, 2.0, 3.0, -4.0]);
    assert_eq!(-b, f64x4::from_array([-1.0, -2.0, -3.0, 4.0]));
    assert_eq!(a + b, f64x4::from_array([11.0, 12.0, 13.0, 6.0]));
    assert_eq!(a - b, f64x4::from_array([9.0, 8.0, 7.0, 14.0]));
    assert_eq!(a * b, f64x4::from_array([10.0, 20.0, 30.0, -40.0]));
    assert_eq!(b / a, f64x4::from_array([0.1, 0.2, 0.3, -0.4]));
    assert_eq!(a / f64x4::splat(2.0), f64x4::splat(5.0));
    assert_eq!(a % b, f64x4::from_array([0.0, 0.0, 1.0, 2.0]));
    assert_eq!(b.abs(), f64x4::from_array([1.0, 2.0, 3.0, 4.0]));

    // FIXME use Mask::from_array once simd_cast is implemented.
    assert_eq!(a.lanes_eq(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([0, -1, 0, 0])));
    assert_eq!(a.lanes_ne(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([-1, 0, -1, -1])));
    assert_eq!(a.lanes_le(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([0, -1, -1, 0])));
    assert_eq!(a.lanes_lt(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([0, 0, -1, 0])));
    assert_eq!(a.lanes_ge(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([-1, -1, 0, -1])));
    assert_eq!(a.lanes_gt(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([-1, 0, 0, -1])));
}

fn simd_ops_i32() {
    let a = i32x4::splat(10);
    let b = i32x4::from_array([1, 2, 3, -4]);
    assert_eq!(-b, i32x4::from_array([-1, -2, -3, 4]));
    assert_eq!(a + b, i32x4::from_array([11, 12, 13, 6]));
    assert_eq!(a - b, i32x4::from_array([9, 8, 7, 14]));
    assert_eq!(a * b, i32x4::from_array([10, 20, 30, -40]));
    assert_eq!(a / b, i32x4::from_array([10, 5, 3, -2]));
    assert_eq!(a / i32x4::splat(2), i32x4::splat(5));
    assert_eq!(i32x2::splat(i32::MIN) / i32x2::splat(-1), i32x2::splat(i32::MIN));
    assert_eq!(a % b, i32x4::from_array([0, 0, 1, 2]));
    assert_eq!(i32x2::splat(i32::MIN) % i32x2::splat(-1), i32x2::splat(0));
    assert_eq!(b << i32x4::splat(2), i32x4::from_array([4, 8, 12, -16]));
    assert_eq!(b >> i32x4::splat(1), i32x4::from_array([0, 1, 1, -2]));
    assert_eq!(b & i32x4::splat(2), i32x4::from_array([0, 2, 2, 0]));
    assert_eq!(b | i32x4::splat(2), i32x4::from_array([3, 2, 3, -2]));
    assert_eq!(b ^ i32x4::splat(2), i32x4::from_array([3, 0, 1, -2]));

    // FIXME use Mask::from_array once simd_cast is implemented.
    assert_eq!(a.lanes_eq(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([0, -1, 0, 0])));
    assert_eq!(a.lanes_ne(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([-1, 0, -1, -1])));
    assert_eq!(a.lanes_le(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([0, -1, -1, 0])));
    assert_eq!(a.lanes_lt(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([0, 0, -1, 0])));
    assert_eq!(a.lanes_ge(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([-1, -1, 0, -1])));
    assert_eq!(a.lanes_gt(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([-1, 0, 0, -1])));

    assert_eq!(a.horizontal_and(), 10);
    assert_eq!(b.horizontal_and(), 0);
    assert_eq!(a.horizontal_or(), 10);
    assert_eq!(b.horizontal_or(), -1);
    assert_eq!(a.horizontal_xor(), 0);
    assert_eq!(b.horizontal_xor(), -4);
    assert_eq!(a.horizontal_sum(), 40);
    assert_eq!(b.horizontal_sum(), 2);
    assert_eq!(a.horizontal_product(), 100*100);
    assert_eq!(b.horizontal_product(), 6*-4);
}

fn simd_intrinsics() {
    extern "platform-intrinsic" {
        fn simd_eq<T, U>(x: T, y: T) -> U;
        fn simd_reduce_any<T>(x: T) -> bool;
        fn simd_reduce_all<T>(x: T) -> bool;
        fn simd_select<M, T>(m: M, yes: T, no: T) -> T;
    }
    unsafe {
        // Make sure simd_eq returns all-1 for `true`
        let a = i32x4::splat(10);
        let b = i32x4::from_array([1, 2, 10, 4]);
        let c: i32x4 = simd_eq(a, b);
        assert_eq!(c, i32x4::from_array([0, 0, -1, 0]));

        assert!(!simd_reduce_any(i32x4::splat(0)));
        assert!(simd_reduce_any(i32x4::splat(-1)));
        assert!(simd_reduce_any(i32x2::from_array([0, -1])));
        assert!(!simd_reduce_all(i32x4::splat(0)));
        assert!(simd_reduce_all(i32x4::splat(-1)));
        assert!(!simd_reduce_all(i32x2::from_array([0, -1])));

        assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), a, b), i32x4::from_array([1, 10, 10, 4]));
        assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), b, a), i32x4::from_array([10, 2, 10, 10]));
    }
}

fn main() {
    simd_ops_f32();
    simd_ops_f64();
    simd_ops_i32();
    simd_intrinsics();
}
<commit_msg>also test f32/f64 simd_reduce<commit_after>#![feature(portable_simd, platform_intrinsics)]
use std::simd::*;

fn simd_ops_f32() {
    let a = f32x4::splat(10.0);
    let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
    assert_eq!(-b, f32x4::from_array([-1.0, -2.0, -3.0, 4.0]));
    assert_eq!(a + b, f32x4::from_array([11.0, 12.0, 13.0, 6.0]));
    assert_eq!(a - b, f32x4::from_array([9.0, 8.0, 7.0, 14.0]));
    assert_eq!(a * b, f32x4::from_array([10.0, 20.0, 30.0, -40.0]));
    assert_eq!(b / a, f32x4::from_array([0.1, 0.2, 0.3, -0.4]));
    assert_eq!(a / f32x4::splat(2.0), f32x4::splat(5.0));
    assert_eq!(a % b, f32x4::from_array([0.0, 0.0, 1.0, 2.0]));
    assert_eq!(b.abs(), f32x4::from_array([1.0, 2.0, 3.0, 4.0]));

    // FIXME use Mask::from_array once simd_cast is implemented.
    assert_eq!(a.lanes_eq(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([0, -1, 0, 0])));
    assert_eq!(a.lanes_ne(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([-1, 0, -1, -1])));
    assert_eq!(a.lanes_le(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([0, -1, -1, 0])));
    assert_eq!(a.lanes_lt(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([0, 0, -1, 0])));
    assert_eq!(a.lanes_ge(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([-1, -1, 0, -1])));
    assert_eq!(a.lanes_gt(f32x4::splat(5.0)*b), Mask::from_int(i32x4::from_array([-1, 0, 0, -1])));

    assert_eq!(a.horizontal_sum(), 40.0);
    assert_eq!(b.horizontal_sum(), 2.0);
    assert_eq!(a.horizontal_product(), 100.0*100.0);
    assert_eq!(b.horizontal_product(), -24.0);
}

fn simd_ops_f64() {
    let a = f64x4::splat(10.0);
    let b = f64x4::from_array([1.0, 2.0, 3.0, -4.0]);
    assert_eq!(-b, f64x4::from_array([-1.0, -2.0, -3.0, 4.0]));
    assert_eq!(a + b, f64x4::from_array([11.0, 12.0, 13.0, 6.0]));
    assert_eq!(a - b, f64x4::from_array([9.0, 8.0, 7.0, 14.0]));
    assert_eq!(a * b, f64x4::from_array([10.0, 20.0, 30.0, -40.0]));
    assert_eq!(b / a, f64x4::from_array([0.1, 0.2, 0.3, -0.4]));
    assert_eq!(a / f64x4::splat(2.0), f64x4::splat(5.0));
    assert_eq!(a % b, f64x4::from_array([0.0, 0.0, 1.0, 2.0]));
    assert_eq!(b.abs(), f64x4::from_array([1.0, 2.0, 3.0, 4.0]));

    // FIXME use Mask::from_array once simd_cast is implemented.
    assert_eq!(a.lanes_eq(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([0, -1, 0, 0])));
    assert_eq!(a.lanes_ne(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([-1, 0, -1, -1])));
    assert_eq!(a.lanes_le(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([0, -1, -1, 0])));
    assert_eq!(a.lanes_lt(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([0, 0, -1, 0])));
    assert_eq!(a.lanes_ge(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([-1, -1, 0, -1])));
    assert_eq!(a.lanes_gt(f64x4::splat(5.0)*b), Mask::from_int(i64x4::from_array([-1, 0, 0, -1])));

    assert_eq!(a.horizontal_sum(), 40.0);
    assert_eq!(b.horizontal_sum(), 2.0);
    assert_eq!(a.horizontal_product(), 100.0*100.0);
    assert_eq!(b.horizontal_product(), -24.0);
}

fn simd_ops_i32() {
    let a = i32x4::splat(10);
    let b = i32x4::from_array([1, 2, 3, -4]);
    assert_eq!(-b, i32x4::from_array([-1, -2, -3, 4]));
    assert_eq!(a + b, i32x4::from_array([11, 12, 13, 6]));
    assert_eq!(a - b, i32x4::from_array([9, 8, 7, 14]));
    assert_eq!(a * b, i32x4::from_array([10, 20, 30, -40]));
    assert_eq!(a / b, i32x4::from_array([10, 5, 3, -2]));
    assert_eq!(a / i32x4::splat(2), i32x4::splat(5));
    assert_eq!(i32x2::splat(i32::MIN) / i32x2::splat(-1), i32x2::splat(i32::MIN));
    assert_eq!(a % b, i32x4::from_array([0, 0, 1, 2]));
    assert_eq!(i32x2::splat(i32::MIN) % i32x2::splat(-1), i32x2::splat(0));
    assert_eq!(b << i32x4::splat(2), i32x4::from_array([4, 8, 12, -16]));
    assert_eq!(b >> i32x4::splat(1), i32x4::from_array([0, 1, 1, -2]));
    assert_eq!(b & i32x4::splat(2), i32x4::from_array([0, 2, 2, 0]));
    assert_eq!(b | i32x4::splat(2), i32x4::from_array([3, 2, 3, -2]));
    assert_eq!(b ^ i32x4::splat(2), i32x4::from_array([3, 0, 1, -2]));

    // FIXME use Mask::from_array once simd_cast is implemented.
    assert_eq!(a.lanes_eq(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([0, -1, 0, 0])));
    assert_eq!(a.lanes_ne(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([-1, 0, -1, -1])));
    assert_eq!(a.lanes_le(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([0, -1, -1, 0])));
    assert_eq!(a.lanes_lt(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([0, 0, -1, 0])));
    assert_eq!(a.lanes_ge(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([-1, -1, 0, -1])));
    assert_eq!(a.lanes_gt(i32x4::splat(5)*b), Mask::from_int(i32x4::from_array([-1, 0, 0, -1])));

    assert_eq!(a.horizontal_and(), 10);
    assert_eq!(b.horizontal_and(), 0);
    assert_eq!(a.horizontal_or(), 10);
    assert_eq!(b.horizontal_or(), -1);
    assert_eq!(a.horizontal_xor(), 0);
    assert_eq!(b.horizontal_xor(), -4);
    assert_eq!(a.horizontal_sum(), 40);
    assert_eq!(b.horizontal_sum(), 2);
    assert_eq!(a.horizontal_product(), 100*100);
    assert_eq!(b.horizontal_product(), -24);
}

fn simd_intrinsics() {
    extern "platform-intrinsic" {
        fn simd_eq<T, U>(x: T, y: T) -> U;
        fn simd_reduce_any<T>(x: T) -> bool;
        fn simd_reduce_all<T>(x: T) -> bool;
        fn simd_select<M, T>(m: M, yes: T, no: T) -> T;
    }
    unsafe {
        // Make sure simd_eq returns all-1 for `true`
        let a = i32x4::splat(10);
        let b = i32x4::from_array([1, 2, 10, 4]);
        let c: i32x4 = simd_eq(a, b);
        assert_eq!(c, i32x4::from_array([0, 0, -1, 0]));

        assert!(!simd_reduce_any(i32x4::splat(0)));
        assert!(simd_reduce_any(i32x4::splat(-1)));
        assert!(simd_reduce_any(i32x2::from_array([0, -1])));
        assert!(!simd_reduce_all(i32x4::splat(0)));
        assert!(simd_reduce_all(i32x4::splat(-1)));
        assert!(!simd_reduce_all(i32x2::from_array([0, -1])));

        assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), a, b), i32x4::from_array([1, 10, 10, 4]));
        assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), b, a), i32x4::from_array([10, 2, 10, 10]));
    }
}

fn main() {
    simd_ops_f32();
    simd_ops_f64();
    simd_ops_i32();
    simd_intrinsics();
}
<|endoftext|>


<commit_before>extern crate num_traits;
#[macro_use]
extern crate log;

pub mod math;
pub mod world;
<commit_msg>Add a short root module documentation<commit_after>//! Functionality used by both the plantex server and the plantex client.
//!
//! - the `math` module reexports everything from the `cgmath` crate and
//!   defines a few own type
//! - the world module is all about saving and managing the game world
//!
extern crate num_traits;
#[macro_use]
extern crate log;

pub mod math;
pub mod world;
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate rand;

const RAND_BENCH_N: u64 = 1000;

use test::{black_box, Bencher};

use rand::{SeedableRng, SmallRng, Rng, thread_rng};
use rand::seq::*;

#[bench]
fn misc_gen_bool(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut accum = true;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.gen_bool(0.18);
        }
        black_box(accum);
    })
}

#[bench]
fn misc_gen_bool_var(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut p = 0.18;
        let mut accum = true;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.gen_bool(p);
            p += 0.0001;
        }
        black_box(accum);
    })
}

#[bench]
fn misc_shuffle_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &mut [usize] = &mut [1; 100];
    b.iter(|| {
        rng.shuffle(x);
        black_box(&x);
    })
}

#[bench]
fn misc_sample_iter_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        black_box(sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e));
    })
}

#[bench]
fn misc_sample_slice_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        black_box(sample_slice(&mut rng, x, 10));
    })
}

#[bench]
fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        black_box(sample_slice_ref(&mut rng, x, 10));
    })
}

macro_rules! sample_indices {
    ($name:ident, $amount:expr, $length:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
            b.iter(|| {
                black_box(sample_indices(&mut rng, $length, $amount));
            })
        }
    }
}

sample_indices!(misc_sample_indices_10_of_1k, 10, 1000);
sample_indices!(misc_sample_indices_50_of_1k, 50, 1000);
sample_indices!(misc_sample_indices_100_of_1k, 100, 1000);
<commit_msg>Add iterator benchmarks<commit_after>#![feature(test)]

extern crate test;
extern crate rand;

const RAND_BENCH_N: u64 = 1000;

use test::{black_box, Bencher};

use rand::{SeedableRng, SmallRng, Rng, thread_rng};
use rand::seq::*;

#[bench]
fn misc_gen_bool(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut accum = true;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.gen_bool(0.18);
        }
        black_box(accum);
    })
}

#[bench]
fn misc_gen_bool_var(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let mut p = 0.18;
        let mut accum = true;
        for _ in 0..::RAND_BENCH_N {
            accum ^= rng.gen_bool(p);
            p += 0.0001;
        }
        black_box(accum);
    })
}

#[bench]
fn misc_shuffle_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &mut [usize] = &mut [1; 100];
    b.iter(|| {
        rng.shuffle(x);
        black_box(&x);
    })
}

#[bench]
fn misc_sample_iter_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        black_box(sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e));
    })
}

#[bench]
fn misc_sample_slice_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        black_box(sample_slice(&mut rng, x, 10));
    })
}

#[bench]
fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        black_box(sample_slice_ref(&mut rng, x, 10));
    })
}

macro_rules! sample_indices {
    ($name:ident, $amount:expr, $length:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
            b.iter(|| {
                black_box(sample_indices(&mut rng, $length, $amount));
            })
        }
    }
}

sample_indices!(misc_sample_indices_10_of_1k, 10, 1000);
sample_indices!(misc_sample_indices_50_of_1k, 50, 1000);
sample_indices!(misc_sample_indices_100_of_1k, 100, 1000);

#[bench]
fn gen_1k_iter_repeat(b: &mut Bencher) {
    use std::iter;
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = iter::repeat(()).map(|()| rng.gen()).take(128).collect();
        black_box(v);
    });
    b.bytes = 1024;
}

#[bench]
#[allow(deprecated)]
fn gen_1k_gen_iter(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = rng.gen_iter().take(128).collect();
        black_box(v);
    });
    b.bytes = 1024;
}

#[bench]
fn gen_1k_sample_iter(b: &mut Bencher) {
    use rand::distributions::{Distribution, Uniform};
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    b.iter(|| {
        let v: Vec<u64> = Uniform.sample_iter(&mut rng).take(128).collect();
        black_box(v);
    });
    b.bytes = 1024;
}

#[bench]
fn gen_1k_fill(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    let mut buf = [0u64; 128];
    b.iter(|| {
        rng.fill(&mut buf[..]);
        black_box(buf);
    });
    b.bytes = 1024;
}
<|endoftext|>


<commit_before>//! Data structure serialization related stuff for RPC
//!
//! Defines all necessary rpc serialization data structures,
//! which includes `tt` related data and some task messages.
//! Although adding `Serialize` and `Deserialize` traits to `tt` directly seems
//! to be much easier, we deliberately duplicate `tt` structs with `#[serde(with = "XXDef")]`
//! for separation of code responsibility.

use std::path::PathBuf;

use serde::{Deserialize, Serialize};
use tt::{
    Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, SmolStr, Spacing, Subtree, TokenId,
    TokenTree,
};

#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub struct ListMacrosTask {
    pub lib: PathBuf,
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub enum ProcMacroKind {
    CustomDerive,
    FuncLike,
    Attr,
}

#[derive(Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct ListMacrosResult {
    pub macros: Vec<(String, ProcMacroKind)>,
}

#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub struct ExpansionTask {
    /// Argument of macro call.
    ///
    /// In custom derive this will be a struct or enum; in attribute-like macro - underlying
    /// item; in function-like macro - the macro body.
    #[serde(with = "SubtreeDef")]
    pub macro_body: Subtree,

    /// Name of macro to expand.
    ///
    /// In custom derive this is the name of the derived trait (`Serialize`, `Getters`, etc.).
    /// In attribute-like and function-like macros - single name of macro itself (`show_streams`).
    pub macro_name: String,

    /// Possible attributes for the attribute-like macros.
    #[serde(with = "opt_subtree_def")]
    pub attributes: Option<Subtree>,

    pub lib: PathBuf,

    /// Environment variables to set during macro expansion.
    pub env: Vec<(String, String)>,
}

#[derive(Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct ExpansionResult {
    #[serde(with = "SubtreeDef")]
    pub expansion: Subtree,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "DelimiterKind")]
enum DelimiterKindDef {
    Parenthesis,
    Brace,
    Bracket,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "TokenId")]
struct TokenIdDef(u32);

#[derive(Serialize, Deserialize)]
#[serde(remote = "Delimiter")]
struct DelimiterDef {
    #[serde(with = "TokenIdDef")]
    id: TokenId,
    #[serde(with = "DelimiterKindDef")]
    kind: DelimiterKind,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Subtree")]
struct SubtreeDef {
    #[serde(default, with = "opt_delimiter_def")]
    delimiter: Option<Delimiter>,
    #[serde(with = "vec_token_tree")]
    token_trees: Vec<TokenTree>,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "TokenTree")]
enum TokenTreeDef {
    #[serde(with = "LeafDef")]
    Leaf(Leaf),
    #[serde(with = "SubtreeDef")]
    Subtree(Subtree),
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Leaf")]
enum LeafDef {
    #[serde(with = "LiteralDef")]
    Literal(Literal),
    #[serde(with = "PunctDef")]
    Punct(Punct),
    #[serde(with = "IdentDef")]
    Ident(Ident),
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Literal")]
struct LiteralDef {
    text: SmolStr,
    #[serde(with = "TokenIdDef")]
    id: TokenId,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Punct")]
struct PunctDef {
    char: char,
    #[serde(with = "SpacingDef")]
    spacing: Spacing,
    #[serde(with = "TokenIdDef")]
    id: TokenId,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Spacing")]
enum SpacingDef {
    Alone,
    Joint,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Ident")]
struct IdentDef {
    text: SmolStr,
    #[serde(with = "TokenIdDef")]
    id: TokenId,
}

mod opt_delimiter_def {
    use super::{Delimiter, DelimiterDef};
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub(super) fn serialize<S>(value: &Option<Delimiter>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        #[derive(Serialize)]
        struct Helper<'a>(#[serde(with = "DelimiterDef")] &'a Delimiter);
        value.as_ref().map(Helper).serialize(serializer)
    }

    pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Option<Delimiter>, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        struct Helper(#[serde(with = "DelimiterDef")] Delimiter);
        let helper = Option::deserialize(deserializer)?;
        Ok(helper.map(|Helper(external)| external))
    }
}

mod opt_subtree_def {
    use super::{Subtree, SubtreeDef};
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub(super) fn serialize<S>(value: &Option<Subtree>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        #[derive(Serialize)]
        struct Helper<'a>(#[serde(with = "SubtreeDef")] &'a Subtree);
        value.as_ref().map(Helper).serialize(serializer)
    }

    pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Option<Subtree>, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        struct Helper(#[serde(with = "SubtreeDef")] Subtree);
        let helper = Option::deserialize(deserializer)?;
        Ok(helper.map(|Helper(external)| external))
    }
}

mod vec_token_tree {
    use super::{TokenTree, TokenTreeDef};
    use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};

    pub(super) fn serialize<S>(value: &Vec<TokenTree>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        #[derive(Serialize)]
        struct Helper<'a>(#[serde(with = "TokenTreeDef")] &'a TokenTree);

        let items: Vec<_> = value.iter().map(Helper).collect();
        let mut seq = serializer.serialize_seq(Some(items.len()))?;
        for element in items {
            seq.serialize_element(&element)?;
        }
        seq.end()
    }

    pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<TokenTree>, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        struct Helper(#[serde(with = "TokenTreeDef")] TokenTree);

        let helper = Vec::deserialize(deserializer)?;
        Ok(helper.into_iter().map(|Helper(external)| external).collect())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn fixture_token_tree() -> Subtree {
        let mut subtree = Subtree::default();
        subtree
            .token_trees
            .push(TokenTree::Leaf(Ident { text: "struct".into(), id: TokenId(0) }.into()));
        subtree
            .token_trees
            .push(TokenTree::Leaf(Ident { text: "Foo".into(), id: TokenId(1) }.into()));
        subtree.token_trees.push(TokenTree::Subtree(Subtree {
            delimiter: Some(Delimiter { id: TokenId(2), kind: DelimiterKind::Brace }),
            token_trees: vec![],
        }));
        subtree
    }

    #[test]
    fn test_proc_macro_rpc_works() {
        let tt = fixture_token_tree();
        let task = ExpansionTask {
            macro_body: tt.clone(),
            macro_name: Default::default(),
            attributes: None,
            lib: Default::default(),
            env: Default::default(),
        };

        let json = serde_json::to_string(&task).unwrap();
        let back: ExpansionTask = serde_json::from_str(&json).unwrap();

        assert_eq!(task.macro_body, back.macro_body);

        let result = ExpansionResult { expansion: tt };
        let json = serde_json::to_string(&result).unwrap();
        let back: ExpansionResult = serde_json::from_str(&json).unwrap();

        assert_eq!(result, back);
    }
}
<commit_msg>Trim down IPC json size<commit_after>//! Data structure serialization related stuff for RPC
//!
//! Defines all necessary rpc serialization data structures,
//! which includes `tt` related data and some task messages.
//! Although adding `Serialize` and `Deserialize` traits to `tt` directly seems
//! to be much easier, we deliberately duplicate `tt` structs with `#[serde(with = "XXDef")]`
//! for separation of code responsibility.

use std::path::PathBuf;

use serde::{Deserialize, Serialize};
use tt::{
    Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, SmolStr, Spacing, Subtree, TokenId,
    TokenTree,
};

#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub struct ListMacrosTask {
    pub lib: PathBuf,
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub enum ProcMacroKind {
    CustomDerive,
    FuncLike,
    Attr,
}

#[derive(Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct ListMacrosResult {
    pub macros: Vec<(String, ProcMacroKind)>,
}

#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub struct ExpansionTask {
    /// Argument of macro call.
    ///
    /// In custom derive this will be a struct or enum; in attribute-like macro - underlying
    /// item; in function-like macro - the macro body.
    #[serde(with = "SubtreeDef")]
    pub macro_body: Subtree,

    /// Name of macro to expand.
    ///
    /// In custom derive this is the name of the derived trait (`Serialize`, `Getters`, etc.).
    /// In attribute-like and function-like macros - single name of macro itself (`show_streams`).
    pub macro_name: String,

    /// Possible attributes for the attribute-like macros.
    #[serde(with = "opt_subtree_def")]
    pub attributes: Option<Subtree>,

    pub lib: PathBuf,

    /// Environment variables to set during macro expansion.
    pub env: Vec<(String, String)>,
}

#[derive(Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct ExpansionResult {
    #[serde(with = "SubtreeDef")]
    pub expansion: Subtree,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "DelimiterKind")]
enum DelimiterKindDef {
    Parenthesis,
    Brace,
    Bracket,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "TokenId")]
struct TokenIdDef(u32);

#[derive(Serialize, Deserialize)]
#[serde(remote = "Delimiter")]
struct DelimiterDef {
    #[serde(
        with = "TokenIdDef",
        default = "tt::TokenId::unspecified",
        skip_serializing_if = "token_id_def::skip_if"
    )]
    id: TokenId,
    #[serde(with = "DelimiterKindDef")]
    kind: DelimiterKind,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Subtree")]
struct SubtreeDef {
    #[serde(default, with = "opt_delimiter_def")]
    delimiter: Option<Delimiter>,
    #[serde(with = "vec_token_tree")]
    token_trees: Vec<TokenTree>,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "TokenTree")]
enum TokenTreeDef {
    #[serde(with = "LeafDef")]
    Leaf(Leaf),
    #[serde(with = "SubtreeDef")]
    Subtree(Subtree),
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Leaf")]
enum LeafDef {
    #[serde(with = "LiteralDef")]
    Literal(Literal),
    #[serde(with = "PunctDef")]
    Punct(Punct),
    #[serde(with = "IdentDef")]
    Ident(Ident),
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Literal")]
struct LiteralDef {
    text: SmolStr,
    #[serde(
        with = "TokenIdDef",
        default = "tt::TokenId::unspecified",
        skip_serializing_if = "token_id_def::skip_if"
    )]
    id: TokenId,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Punct")]
struct PunctDef {
    char: char,
    #[serde(with = "SpacingDef")]
    spacing: Spacing,
    #[serde(
        with = "TokenIdDef",
        default = "tt::TokenId::unspecified",
        skip_serializing_if = "token_id_def::skip_if"
    )]
    id: TokenId,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Spacing")]
enum SpacingDef {
    Alone,
    Joint,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "Ident")]
struct IdentDef {
    text: SmolStr,
    #[serde(
        with = "TokenIdDef",
        default = "tt::TokenId::unspecified",
        skip_serializing_if = "token_id_def::skip_if"
    )]
    id: TokenId,
}

mod token_id_def {
    pub(super) fn skip_if(value: &tt::TokenId) -> bool {
        *value == tt::TokenId::unspecified()
    }
}

mod opt_delimiter_def {
    use super::{Delimiter, DelimiterDef};
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub(super) fn serialize<S>(value: &Option<Delimiter>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        #[derive(Serialize)]
        struct Helper<'a>(#[serde(with = "DelimiterDef")] &'a Delimiter);
        value.as_ref().map(Helper).serialize(serializer)
    }

    pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Option<Delimiter>, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        struct Helper(#[serde(with = "DelimiterDef")] Delimiter);
        let helper = Option::deserialize(deserializer)?;
        Ok(helper.map(|Helper(external)| external))
    }
}

mod opt_subtree_def {
    use super::{Subtree, SubtreeDef};
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub(super) fn serialize<S>(value: &Option<Subtree>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        #[derive(Serialize)]
        struct Helper<'a>(#[serde(with = "SubtreeDef")] &'a Subtree);
        value.as_ref().map(Helper).serialize(serializer)
    }

    pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Option<Subtree>, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        struct Helper(#[serde(with = "SubtreeDef")] Subtree);
        let helper = Option::deserialize(deserializer)?;
        Ok(helper.map(|Helper(external)| external))
    }
}

mod vec_token_tree {
    use super::{TokenTree, TokenTreeDef};
    use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};

    pub(super) fn serialize<S>(value: &Vec<TokenTree>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        #[derive(Serialize)]
        struct Helper<'a>(#[serde(with = "TokenTreeDef")] &'a TokenTree);

        let items: Vec<_> = value.iter().map(Helper).collect();
        let mut seq = serializer.serialize_seq(Some(items.len()))?;
        for element in items {
            seq.serialize_element(&element)?;
        }
        seq.end()
    }

    pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<TokenTree>, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        struct Helper(#[serde(with = "TokenTreeDef")] TokenTree);

        let helper = Vec::deserialize(deserializer)?;
        Ok(helper.into_iter().map(|Helper(external)| external).collect())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn fixture_token_tree() -> Subtree {
        let mut subtree = Subtree::default();
        subtree
            .token_trees
            .push(TokenTree::Leaf(Ident { text: "struct".into(), id: TokenId(0) }.into()));
        subtree
            .token_trees
            .push(TokenTree::Leaf(Ident { text: "Foo".into(), id: TokenId(1) }.into()));
        subtree.token_trees.push(TokenTree::Subtree(Subtree {
            delimiter: Some(Delimiter { id: TokenId(2), kind: DelimiterKind::Brace }),
            token_trees: vec![],
        }));
        subtree
    }

    #[test]
    fn test_proc_macro_rpc_works() {
        let tt = fixture_token_tree();
        let task = ExpansionTask {
            macro_body: tt.clone(),
            macro_name: Default::default(),
            attributes: None,
            lib: Default::default(),
            env: Default::default(),
        };

        let json = serde_json::to_string(&task).unwrap();
        let back: ExpansionTask = serde_json::from_str(&json).unwrap();

        assert_eq!(task.macro_body, back.macro_body);

        let result = ExpansionResult { expansion: tt };
        let json = serde_json::to_string(&result).unwrap();
        let back: ExpansionResult = serde_json::from_str(&json).unwrap();

        assert_eq!(result, back);
    }
}
<|endoftext|>