<commit_before>use std::{fmt, path::Path};

use crate::build::chromeos::keymap::CHROMEOS_KEYS;
use async_trait::async_trait;
use indexmap::IndexMap;
use language_tags::LanguageTag;
use pahkat_client::types::repo::Index;
use serde::{Deserialize, Serialize};
use serde_json::{json, to_string_pretty};

use crate::{
    build::BuildStep,
    bundle::{
        layout::{chrome::ChromeOsKbdLayer, Transform},
        KbdgenBundle,
    },
    util::split_keys,
};

const KEYBOARD_TEMPLATE: &str = include_str!("../../../resources/template-chromeos-keyboard.js");

#[derive(Serialize, Deserialize)]
pub struct ChromeOsBackground {
    template: String,
    descriptor: IndexMap<LanguageTag, ChromeOsDescriptor>,
}

impl fmt::Display for ChromeOsBackground {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}\n", self.template)?;
        write!(f, "\n")?;
        write!(
            f,
            "const descriptor = {}\n",
            to_string_pretty(&self.descriptor).map_err(|err| fmt::Error)?
        )?;
        write!(f, "\nKeyboard.install(descriptor)")?;

        Ok(())
    }
}

#[derive(Serialize, Deserialize)]
pub struct ChromeOsDescriptor {
    pub dead_keys: IndexMap<ChromeOsKbdLayer, Vec<String>>,
    pub transforms: IndexMap<String, IndexMap<String, String>>,
    pub layers: IndexMap<ChromeOsKbdLayer, IndexMap<String, String>>,
}

impl fmt::Display for ChromeOsDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}",
            to_string_pretty(&self.dead_keys).map_err(|err| fmt::Error)?
        )?;
        write!(
            f,
            "{}",
            to_string_pretty(&self.transforms).map_err(|err| fmt::Error)?
        )?;

        Ok(())
    }
}

pub struct GenerateChromeOs;

#[async_trait(?Send)]
impl BuildStep for GenerateChromeOs {
    async fn build(&self, bundle: &KbdgenBundle, output_path: &Path) {
        let background_file_path = output_path.join("background.js");

        let template = KEYBOARD_TEMPLATE.clone();

        let mut descriptor = IndexMap::new();

        let mut json_transforms: IndexMap<String, IndexMap<String, String>>;
        // layout information is to be aggregated into a descriptor and then appended
        // to the end of the template
        for (language_tag, layout) in &bundle.layouts {
            if let Some(chromeos_target) = &layout.chrome_os {
                let mut dead_keys = IndexMap::new();
                if let Some(temp_dead_keys)  = &chromeos_target.dead_keys {
                    for (key, value) in temp_dead_keys {
                        dead_keys.insert(key.clone(), value.to_vec());
                    }
                }
                if let Some(layout_transforms) = &layout.transforms {
                    let layout_file_path = bundle
                        .path
                        .join("layouts")
                        .join(format!("{}.yaml", layout.language_tag));

                    let yaml_file = std::fs::File::open(&layout_file_path).unwrap();
                    let original_layout_yaml: serde_yaml::Value =
                        serde_yaml::from_reader(yaml_file).unwrap();

                    let owning_transform = *&original_layout_yaml.get("transforms").unwrap();

                    json_transforms = serde_yaml::from_value(owning_transform.clone()).unwrap();
                } else {
                    json_transforms = IndexMap::new();
                }

                let layers = &chromeos_target.primary.layers;

                let mut modifiers = IndexMap::new();
                for (layer_name, key_map) in layers {
                    let key_map: Vec<String> = split_keys(&key_map);

                    tracing::debug!(
                        "iso len: {}; keymap len: {}",
                        CHROMEOS_KEYS.len(),
                        key_map.len()
                    );
                    if CHROMEOS_KEYS.len() > key_map.len() {
                        panic!(
                            r#"Provided layer does not have enough keys, expected {} keys but got {}, in {}:{}:{}:{:?}: \n{:?}"#,
                            CHROMEOS_KEYS.len(),
                            key_map.len(),
                            language_tag.to_string(),
                            "Windows",
                            "Primary",
                            layer_name,
                            key_map
                        );
                    }

                    let mut keys = IndexMap::new();
                    for (cursor, (_iso_key, key_name)) in CHROMEOS_KEYS.iter().enumerate() {
                        keys.insert(key_name.clone(), key_map[cursor].clone());
                    }

                    modifiers.insert(layer_name.clone(), keys);
                }

                descriptor.insert(
                    language_tag.clone(),
                    ChromeOsDescriptor {
                        dead_keys: dead_keys,
                        transforms: json_transforms,
                        layers: modifiers,
                    },
                );
            }
        }

        let background = ChromeOsBackground {
            template: template.to_string(),
            descriptor,
        };

        std::fs::write(
            output_path.join(background_file_path),
            background.to_string(),
        )
        .unwrap();
    }
}
<commit_msg>rename vars in chromeos generation<commit_after>use std::{fmt, path::Path};

use crate::build::chromeos::keymap::CHROMEOS_KEYS;
use async_trait::async_trait;
use indexmap::IndexMap;
use language_tags::LanguageTag;
use pahkat_client::types::repo::Index;
use serde::{Deserialize, Serialize};
use serde_json::{json, to_string_pretty};

use crate::{
    build::BuildStep,
    bundle::{
        layout::{chrome::ChromeOsKbdLayer, Transform},
        KbdgenBundle,
    },
    util::split_keys,
};

const KEYBOARD_TEMPLATE: &str = include_str!("../../../resources/template-chromeos-keyboard.js");

#[derive(Serialize, Deserialize)]
pub struct ChromeOsBackground {
    template: String,
    descriptor: IndexMap<LanguageTag, ChromeOsDescriptor>,
}

impl fmt::Display for ChromeOsBackground {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}\n", self.template)?;
        write!(f, "\n")?;
        write!(
            f,
            "const descriptor = {}\n",
            to_string_pretty(&self.descriptor).map_err(|err| fmt::Error)?
        )?;
        write!(f, "\nKeyboard.install(descriptor)")?;

        Ok(())
    }
}

#[derive(Serialize, Deserialize)]
pub struct ChromeOsDescriptor {
    pub dead_keys: IndexMap<ChromeOsKbdLayer, Vec<String>>,
    pub transforms: IndexMap<String, IndexMap<String, String>>,
    pub layers: IndexMap<ChromeOsKbdLayer, IndexMap<String, String>>,
}

impl fmt::Display for ChromeOsDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}",
            to_string_pretty(&self.dead_keys).map_err(|err| fmt::Error)?
        )?;
        write!(
            f,
            "{}",
            to_string_pretty(&self.transforms).map_err(|err| fmt::Error)?
        )?;

        Ok(())
    }
}

pub struct GenerateChromeOs;

#[async_trait(?Send)]
impl BuildStep for GenerateChromeOs {
    async fn build(&self, bundle: &KbdgenBundle, output_path: &Path) {
        let background_file_path = output_path.join("background.js");

        let template = KEYBOARD_TEMPLATE.clone();

        let mut descriptor = IndexMap::new();

        let mut json_transforms: IndexMap<String, IndexMap<String, String>>;
        // layout information is to be aggregated into a descriptor and then appended
        // to the end of the template
        for (language_tag, layout) in &bundle.layouts {
            if let Some(chromeos_target) = &layout.chrome_os {
                let mut json_dead_keys = IndexMap::new();
                if let Some(dead_keys)  = &chromeos_target.dead_keys {
                    for (dead_key_name, dead_key_list) in dead_keys {
                        json_dead_keys.insert(dead_key_name.clone(), dead_key_list.to_vec());
                    }
                }
                if let Some(layout_transforms) = &layout.transforms {
                    let layout_file_path = bundle
                        .path
                        .join("layouts")
                        .join(format!("{}.yaml", layout.language_tag));

                    let yaml_file = std::fs::File::open(&layout_file_path).unwrap();
                    let original_layout_yaml: serde_yaml::Value =
                        serde_yaml::from_reader(yaml_file).unwrap();

                    let owning_transform = *&original_layout_yaml.get("transforms").unwrap();

                    json_transforms = serde_yaml::from_value(owning_transform.clone()).unwrap();
                } else {
                    json_transforms = IndexMap::new();
                }

                let layers = &chromeos_target.primary.layers;

                let mut json_layers = IndexMap::new();
                for (layer_name, key_map) in layers {
                    let key_map: Vec<String> = split_keys(&key_map);

                    tracing::debug!(
                        "iso len: {}; keymap len: {}",
                        CHROMEOS_KEYS.len(),
                        key_map.len()
                    );
                    if CHROMEOS_KEYS.len() > key_map.len() {
                        panic!(
                            r#"Provided layer does not have enough keys, expected {} keys but got {}, in {}:{}:{}:{:?}: \n{:?}"#,
                            CHROMEOS_KEYS.len(),
                            key_map.len(),
                            language_tag.to_string(),
                            "Windows",
                            "Primary",
                            layer_name,
                            key_map
                        );
                    }

                    let mut modifiers = IndexMap::new();
                    for (cursor, (_iso_key, modifier_name)) in CHROMEOS_KEYS.iter().enumerate() {
                        modifiers.insert(modifier_name.clone(), key_map[cursor].clone());
                    }

                    json_layers.insert(layer_name.clone(), modifiers);
                }

                descriptor.insert(
                    language_tag.clone(),
                    ChromeOsDescriptor {
                        dead_keys: json_dead_keys,
                        transforms: json_transforms,
                        layers: json_layers,
                    },
                );
            }
        }

        let background = ChromeOsBackground {
            template: template.to_string(),
            descriptor,
        };

        std::fs::write(
            output_path.join(background_file_path),
            background.to_string(),
        )
        .unwrap();
    }
}
<|endoftext|>


<commit_before>//!
//! Planner and Optimizer

extern crate common;
extern crate plan;

use common::err::Result;
use common::session::Session;
use common::plugin::{FuncRegistry, TypeRegistry};
use plan::LogicalPlan;

pub struct LogicalOptimizer;

impl LogicalOptimizer
{
  pub fn new() -> LogicalOptimizer
  {
    LogicalOptimizer
  }

  #[allow(unused_variables)]
  pub fn optimize(&self,
  	type_registry: &TypeRegistry,
  	func_registry: &FuncRegistry,
  	session: &Session, plan: &LogicalPlan) -> Result<LogicalPlan> {
    let x = (*plan).clone();
    Ok(x)
  }
}<commit_msg>Reformat optimizer module.<commit_after>//! Planner and Optimizer

extern crate common;
extern crate plan;

use common::err::Result;
use common::session::Session;
use common::plugin::{FuncRegistry, TypeRegistry};
use plan::LogicalPlan;

pub struct LogicalOptimizer;

impl LogicalOptimizer {
  pub fn new() -> LogicalOptimizer {
    LogicalOptimizer
  }

  #[allow(unused_variables)]
  pub fn optimize(&self,
                  type_registry: &TypeRegistry,
                  func_registry: &FuncRegistry,
                  session: &Session,
                  plan: &LogicalPlan)
                  -> Result<LogicalPlan> {
    let x = (*plan).clone();
    Ok(x)
  }
}
<|endoftext|>


<commit_before>//! Data structures and implementations for union-of-patterns.

use std::mem;
use std::cmp::Ordering;
use std::iter::FromIterator;

use itertools::Itertools;

use util::set::{self, IsSubsetOf};
use super::{Anchor, Atom, Element, Repetition, Sequence};
#[cfg(feature = "pattern_class")]
use super::Class;

use super::{Reduce, flatten_and_reduce};

// To hide the implementation details, we wrap the type alias in
// a private submodule.
mod union_impl {
    use super::super::Element;
    pub type Inner<T> = Vec<Element<T>>;
}

/// Union of patterns.
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Union<T: Atom>(union_impl::Inner<T>);

impl<T: Atom> Union<T> {
    /// Create a new union from the given vector.
    pub fn new(v: Vec<Element<T>>) -> Self {
        if v.len() < 2 {
            panic!("Unions must have at least two members");
        }
        Union(v)
    }

    /// Fetch an iterator over the members of the union
    #[inline]
    pub fn iter<'a>(&'a self) -> impl Iterator<Item=&'a Element<T>> {
        self.0.iter()
    }

    /// Get the number of members in the union
    #[inline(always)]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Transforms each contained atom using the supplied function or closure
    /// to produce a new sequence.
    pub fn map_atoms<U, F>(self, f: F) -> Union<U>
        where F: Fn(T) -> U,
              U: Atom
    {
        self.0.into_iter().map(|elt| elt.map_atoms(&f)).collect()
    }

    #[inline(always)]
    fn into_inner(self) -> union_impl::Inner<T> {
        self.0
    }
}

impl<T: Atom> Reduce for Union<T> {
    type Output = Option<Element<T>>;

    /// Flatten the union and apply implementation-defined optimizations.
    fn reduce(mut self) -> Self::Output {
        if self.0.is_empty() { None }
        else {
            flatten_and_reduce(&mut self.0, Element::Wildcard,
                               |elt| match elt { &Element::Union(ref u) => Some(u.len()), _ => None },
                               |elt| match elt { Element::Union(u) => u.into_inner(), _ => unreachable!() });

            let mut reduced = self.0.clone().into_iter()
                .sorted_by(|a, b| { if a.is_subset_of(b) || b.is_subset_of(a) { Ordering::Equal }
                                    else { a.cmp(b) } })
                .into_iter()
                .coalesce(|a, b| { if a.is_subset_of(&b) { Ok(b) }
                                   else if b.is_subset_of(&a) { Ok(a) }
                                   else { Err((a, b)) } })
                .collect();
            mem::swap(&mut self.0, &mut reduced);
            Some(Element::Union(self))
        }
    }
}

impl<T: Atom> set::Contains<T> for Union<T> {
    fn contains(&self, atom: T) -> bool {
        self.0.iter().any(|m| m.contains(atom))
    }
}

impl<T: Atom> FromIterator<Element<T>> for Union<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item=Element<T>>
    {
        Union::new(iter.into_iter().collect())
    }
}

// ----------------------------------------------------------------
apply_attrs! {
    cfg(feature = "regex") => {
        use regex_syntax;
        use char_iter;
        use super::ByteOrChar;

        macro_rules! impl_union_from {
            ($T: ty, $from: ty, $map_input: ident => $map_expr: expr) => {
                impl From<$from> for Union<$T> {
                    fn from(c: $from) -> Self {
                        Union::from_iter(c.into_iter().flat_map(|$map_input| $map_expr))
                    }
                }
            };
        }

        impl_union_from!(char, regex_syntax::CharClass, cr => char_iter::new(cr.start, cr.end).map(|c| c.into()));
        impl_union_from!(u8, regex_syntax::ByteClass, cr => (cr.start...cr.end).map(|c| c.into()));
        impl_union_from!(ByteOrChar, regex_syntax::CharClass, cr => char_iter::new(cr.start, cr.end).map(|c| c.into()));
        impl_union_from!(ByteOrChar, regex_syntax::ByteClass, cr => (cr.start...cr.end).map(|c| c.into()));
    }
}

// ----------------------------------------------------------------
impl<T: Atom> set::IsSubsetOf<Sequence<T>> for Union<T> {
    /// A union is a subset of a sequence S if it consists entirely of
    /// sequences whose elements are subsets of the corresponding element in S.
    fn is_subset_of(&self, seq: &Sequence<T>) -> bool {
        self.iter().all(|m| match m {
            &Element::Sequence(ref member_seq) =>
                seq.len() == member_seq.len() &&
                seq.iter().zip(member_seq.iter()).all(|(seq_elt, member_seq_elt)| member_seq_elt.is_subset_of(seq_elt)),
            _ => false })
    }
}

macro_rules! is_subset_if_all_members_are_subsets {
    ($T: ident,$Other: ty, $name: ident; $doc: expr) => {
        impl<$T: Atom> set::IsSubsetOf<$Other> for Union<$T> {
            #[doc = $doc]
            fn is_subset_of(&self, $name: &$Other) -> bool {
                self.iter().all(|m| m.is_subset_of($name))
            }
        }
    };
}

// This one should never happen, but we'll happily support whatever brain-dead
// comparisons you want to try!
is_subset_if_all_members_are_subsets! {
    T, T, atom;
    "A union is a subset of an atom if all members are subsets of that atom"}

// Also unlikely.
is_subset_if_all_members_are_subsets! {
    T, Anchor<T>, anchor;
    "A union is a subset of an anchor if all members of the union are subsets of the anchor"}

is_subset_if_all_members_are_subsets! {
    T, Repetition<T>, repetition;
    "A union is a subset of a repetition if all members of the union are subsets of the repetition"}

#[cfg(feature = "pattern_class")]
is_subset_if_all_members_are_subsets! {
    T, Class<T>, class;
    "A union is a subset of a class of atoms if all members of the union are subsets of the class"}

is_subset_if_all_members_are_subsets! {
    T, Union<T>, union;
    "A union is a subset of another union if all members of the former are subsets of the latter"}

impl<T: Atom> set::IsSubsetOf<Element<T>> for Union<T> {
    fn is_subset_of(&self, elt: &Element<T>) -> bool {
        match elt {
            &Element::Tagged{ref element, ..} => self.is_subset_of(&**element),
            #[cfg(feature = "pattern_class")]
            &Element::Class(ref c) => self.is_subset_of(c),
            &Element::Sequence(ref s) => self.is_subset_of(s),
            &Element::Repeat(ref r) => self.is_subset_of(r),
            &Element::Union(ref u) => self.is_subset_of(u),
            &Element::Atom(atom) => self.is_subset_of(&atom),
            &Element::Anchor(ref a) => self.is_subset_of(a),

            // A union is a subset of a wildcard if all members are
            // also subsets.
            &Element::Wildcard => self.iter().all(|m| m.is_subset_of(&Element::Wildcard)),

            &Element::Not(ref element) => ! self.is_subset_of(&**element),
        }
    }
}
<commit_msg>pattern/union: handle empty and unit-length results in Reduce impl<commit_after>//! Data structures and implementations for union-of-patterns.

use std::mem;
use std::cmp::Ordering;
use std::iter::FromIterator;

use itertools::Itertools;

use util::set::{self, IsSubsetOf};
use super::{Anchor, Atom, Element, Repetition, Sequence};
#[cfg(feature = "pattern_class")]
use super::Class;

use super::{Reduce, flatten_and_reduce};

// To hide the implementation details, we wrap the type alias in
// a private submodule.
mod union_impl {
    use super::super::Element;
    pub type Inner<T> = Vec<Element<T>>;
}

/// Union of patterns.
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Union<T: Atom>(union_impl::Inner<T>);

impl<T: Atom> Union<T> {
    /// Create a new union from the given vector.
    pub fn new(v: Vec<Element<T>>) -> Self {
        if v.len() < 2 {
            panic!("Unions must have at least two members");
        }
        Union(v)
    }

    /// Fetch an iterator over the members of the union
    #[inline]
    pub fn iter<'a>(&'a self) -> impl Iterator<Item=&'a Element<T>> {
        self.0.iter()
    }

    /// Get the number of members in the union
    #[inline(always)]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Transforms each contained atom using the supplied function or closure
    /// to produce a new sequence.
    pub fn map_atoms<U, F>(self, f: F) -> Union<U>
        where F: Fn(T) -> U,
              U: Atom
    {
        self.0.into_iter().map(|elt| elt.map_atoms(&f)).collect()
    }

    #[inline(always)]
    fn into_inner(self) -> union_impl::Inner<T> {
        self.0
    }
}

impl<T: Atom> Reduce for Union<T> {
    type Output = Option<Element<T>>;

    /// Flatten the union and apply implementation-defined optimizations.
    fn reduce(mut self) -> Self::Output {
        if self.0.is_empty() { None }
        else {
            // Reduce all child elements and flatten unions into self.
            flatten_and_reduce(&mut self.0, Element::Wildcard,
                               |elt| match elt { &Element::Union(ref u) => Some(u.len()), _ => None },
                               |elt| match elt { Element::Union(u) => u.into_inner(), _ => unreachable!() });

            // Remove elements that are subsets of others.
            let mut reduced = self.0.clone().into_iter()
                .sorted_by(|a, b| { if a.is_subset_of(b) || b.is_subset_of(a) { Ordering::Equal }
                                    else { a.cmp(b) } })
                .into_iter()
                .coalesce(|a, b| { if a.is_subset_of(&b) { Ok(b) }
                                   else if b.is_subset_of(&a) { Ok(a) }
                                   else { Err((a, b)) } })
                .collect::<Vec<_>>();

            match reduced.len() {
                0 => None,
                1 => Some(reduced.swap_remove(0)),
                _ => {
                    mem::swap(&mut self.0, &mut reduced);
                    Some(Element::Union(self))
                }
            }
        }
    }
}

impl<T: Atom> set::Contains<T> for Union<T> {
    fn contains(&self, atom: T) -> bool {
        self.0.iter().any(|m| m.contains(atom))
    }
}

impl<T: Atom> FromIterator<Element<T>> for Union<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item=Element<T>>
    {
        Union::new(iter.into_iter().collect())
    }
}

// ----------------------------------------------------------------
apply_attrs! {
    cfg(feature = "regex") => {
        use regex_syntax;
        use char_iter;
        use super::ByteOrChar;

        macro_rules! impl_union_from {
            ($T: ty, $from: ty, $map_input: ident => $map_expr: expr) => {
                impl From<$from> for Union<$T> {
                    fn from(c: $from) -> Self {
                        Union::from_iter(c.into_iter().flat_map(|$map_input| $map_expr))
                    }
                }
            };
        }

        impl_union_from!(char, regex_syntax::CharClass, cr => char_iter::new(cr.start, cr.end).map(|c| c.into()));
        impl_union_from!(u8, regex_syntax::ByteClass, cr => (cr.start...cr.end).map(|c| c.into()));
        impl_union_from!(ByteOrChar, regex_syntax::CharClass, cr => char_iter::new(cr.start, cr.end).map(|c| c.into()));
        impl_union_from!(ByteOrChar, regex_syntax::ByteClass, cr => (cr.start...cr.end).map(|c| c.into()));
    }
}

// ----------------------------------------------------------------
impl<T: Atom> set::IsSubsetOf<Sequence<T>> for Union<T> {
    /// A union is a subset of a sequence S if it consists entirely of
    /// sequences whose elements are subsets of the corresponding element in S.
    fn is_subset_of(&self, seq: &Sequence<T>) -> bool {
        self.iter().all(|m| match m {
            &Element::Sequence(ref member_seq) =>
                seq.len() == member_seq.len() &&
                seq.iter().zip(member_seq.iter()).all(|(seq_elt, member_seq_elt)| member_seq_elt.is_subset_of(seq_elt)),
            _ => false })
    }
}

macro_rules! is_subset_if_all_members_are_subsets {
    ($T: ident,$Other: ty, $name: ident; $doc: expr) => {
        impl<$T: Atom> set::IsSubsetOf<$Other> for Union<$T> {
            #[doc = $doc]
            fn is_subset_of(&self, $name: &$Other) -> bool {
                self.iter().all(|m| m.is_subset_of($name))
            }
        }
    };
}

// This one should never happen, but we'll happily support whatever brain-dead
// comparisons you want to try!
is_subset_if_all_members_are_subsets! {
    T, T, atom;
    "A union is a subset of an atom if all members are subsets of that atom"}

// Also unlikely.
is_subset_if_all_members_are_subsets! {
    T, Anchor<T>, anchor;
    "A union is a subset of an anchor if all members of the union are subsets of the anchor"}

is_subset_if_all_members_are_subsets! {
    T, Repetition<T>, repetition;
    "A union is a subset of a repetition if all members of the union are subsets of the repetition"}

#[cfg(feature = "pattern_class")]
is_subset_if_all_members_are_subsets! {
    T, Class<T>, class;
    "A union is a subset of a class of atoms if all members of the union are subsets of the class"}

is_subset_if_all_members_are_subsets! {
    T, Union<T>, union;
    "A union is a subset of another union if all members of the former are subsets of the latter"}

impl<T: Atom> set::IsSubsetOf<Element<T>> for Union<T> {
    fn is_subset_of(&self, elt: &Element<T>) -> bool {
        match elt {
            &Element::Tagged{ref element, ..} => self.is_subset_of(&**element),
            #[cfg(feature = "pattern_class")]
            &Element::Class(ref c) => self.is_subset_of(c),
            &Element::Sequence(ref s) => self.is_subset_of(s),
            &Element::Repeat(ref r) => self.is_subset_of(r),
            &Element::Union(ref u) => self.is_subset_of(u),
            &Element::Atom(atom) => self.is_subset_of(&atom),
            &Element::Anchor(ref a) => self.is_subset_of(a),

            // A union is a subset of a wildcard if all members are
            // also subsets.
            &Element::Wildcard => self.iter().all(|m| m.is_subset_of(&Element::Wildcard)),

            &Element::Not(ref element) => ! self.is_subset_of(&**element),
        }
    }
}
<|endoftext|>


<commit_before>use std::str;
use std::thread;
use std::sync::Mutex;
use std::cell::RefCell;
use std::time::{Duration,Instant};
use std::iter::repeat;
use std::collections::BTreeMap;
use std::collections::VecDeque;
use std::fmt::Arguments;
use std::net::SocketAddr;
use mio::net::UdpSocket;
use std::io::{self,BufWriter,Write,Error,ErrorKind};
use nom::HexDisplay;
use hdrhistogram::Histogram;
use sozu_command::buffer::Buffer;
use sozu_command::messages::{FilteredData,MetricsData,Percentiles,BackendMetricsData,FilteredTimeSerie};

mod network_drain;
mod local_drain;

use self::network_drain::NetworkDrain;
use self::local_drain::LocalDrain;

thread_local! {
  pub static METRICS: RefCell<Aggregator> = RefCell::new(Aggregator::new(String::from("sozu")));
}

#[derive(Debug,Clone,PartialEq)]
pub enum MetricData {
  Gauge(usize),
  GaugeAdd(i64),
  Count(i64),
  Time(usize),
}

impl MetricData {
  fn is_time(&self) -> bool {
    match self {
      &MetricData::Time(_) => true,
      _ => false,
    }
  }

  fn update(&mut self, key: &'static str, m: MetricData) {
    match (self, m) {
      (&mut MetricData::Gauge(ref mut v1), MetricData::Gauge(v2)) => {
        *v1 = v2;
      },
      (&mut MetricData::Gauge(ref mut v1), MetricData::GaugeAdd(v2)) => {
        debug_assert!(*v1 as i64 + v2 >= 0, "metric {} underflow: previous value: {}, adding: {}", key, v1, v2);
        let res = *v1 as i64 + v2;
        *v1 = if res >= 0 {
          res as usize
        } else {
          error!("metric {} underflow: previous value: {}, adding: {}", key, v1, v2);
          0
        }
      },
      (&mut MetricData::Count(ref mut v1), MetricData::Count(v2)) => {
        *v1 += v2;
      },
      (s,m) => panic!("tried to update metric {} of value {:?} with an incompatible metric: {:?}", key, s, m)
    }
  }
}

#[derive(Debug,Clone)]
pub struct StoredMetricData {
  last_sent: Instant,
  data:      MetricData,
}

impl StoredMetricData {
  pub fn new(last_sent: Instant, data: MetricData) -> StoredMetricData {
    StoredMetricData {
      last_sent: last_sent,
      data: if let MetricData::GaugeAdd(v) = data {
        MetricData::Gauge(v as usize)
      } else { data }
    }
  }
}

pub fn setup<H: AsRef<str>, O: Into<String>>(host: H, port: u16, origin: O, use_tagged_metrics: bool, prefix: Option<String>) {
  use std::net::ToSocketAddrs;
  let metrics_socket = udp_bind();

  debug!("setting up metrics: local address = {:#?}", metrics_socket.local_addr());
  let metrics_host   = (host.as_ref(), port).to_socket_addrs().expect("could not parse address").next().expect("could not get first address");

  METRICS.with(|metrics| {
    if let Some(p) = prefix {
      (*metrics.borrow_mut()).set_up_prefix(p);
    }
    (*metrics.borrow_mut()).set_up_remote(metrics_socket, metrics_host);
    (*metrics.borrow_mut()).set_up_origin(origin.into());
    (*metrics.borrow_mut()).set_up_tagged_metrics(use_tagged_metrics);
  });
}

pub trait Subscriber {
  fn receive_metric(&mut self, label: &'static str, app_id: Option<&str>, backend_id: Option<&str>, metric: MetricData);
}

pub struct Aggregator {
  prefix:  String,
  network: Option<NetworkDrain>,
  local:   LocalDrain,
}

impl Aggregator {
  pub fn new(prefix: String) -> Aggregator {
    Aggregator {
      prefix: prefix.clone(),
      network: None,
      local: LocalDrain::new(prefix),
    }
  }

  pub fn set_up_prefix(&mut self, prefix: String) {
    self.prefix = prefix;
  }

  pub fn set_up_remote(&mut self, socket: UdpSocket, addr: SocketAddr) {
    self.network = Some(NetworkDrain::new(self.prefix.clone(), socket, addr));
  }

  pub fn set_up_origin(&mut self, origin: String) {
    self.network.as_mut().map(|n| n.origin = origin);
  }

  pub fn set_up_tagged_metrics(&mut self, tagged: bool) {
    self.network.as_mut().map(|n| n.use_tagged_metrics = tagged);
  }

  pub fn socket(&self) -> Option<&UdpSocket> {
    self.network.as_ref().map(|n| &n.remote.get_ref().socket)
  }

  pub fn count_add(&mut self, key: &'static str, count_value: i64) {
    self.receive_metric(key, None, None, MetricData::Count(count_value));
  }

  pub fn set_gauge(&mut self, key: &'static str, gauge_value: usize) {
    self.receive_metric(key, None, None, MetricData::Gauge(gauge_value));
  }

  pub fn gauge_add(&mut self, key: &'static str, gauge_value: i64) {
    self.receive_metric(key, None, None, MetricData::GaugeAdd(gauge_value));
  }

  pub fn writable(&mut self) {
    if let Some(ref mut net) = self.network.as_mut() {
      net.writable();
    }
  }

  pub fn send_data(&mut self) {
    if let Some(ref mut net) = self.network.as_mut() {
      net.send_data();
    }
  }

  pub fn dump_metrics_data(&mut self) -> MetricsData {
    self.local.dump_metrics_data()
  }

  pub fn dump_process_data(&mut self) -> BTreeMap<String, FilteredData> {
    self.local.dump_process_data()
  }
}

impl Subscriber for Aggregator {
  fn receive_metric(&mut self, label: &'static str, app_id: Option<&str>, backend_id: Option<&str>, metric: MetricData) {
    if let Some(ref mut net) = self.network.as_mut() {
      net.receive_metric(label, app_id, backend_id, metric.clone());
    }
    self.local.receive_metric(label, app_id, backend_id, metric.clone());
  }
}

#[derive(Debug,Clone,PartialEq)]
pub struct MetricLine {
  label:      &'static str,
  app_id:     Option<String>,
  backend_id: Option<String>,
  /// in milliseconds
  duration:   usize,
}

pub struct MetricSocket {
  pub addr:   SocketAddr,
  pub socket: UdpSocket,
}

impl Write for MetricSocket {
  fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
    self.socket.send_to(buf, &self.addr)
  }

  fn flush(&mut self) -> io::Result<()> {
    Ok(())
  }
}

pub fn udp_bind() -> UdpSocket {
  UdpSocket::bind(&("0.0.0.0:0".parse().unwrap())).expect("could not parse address")
}

#[macro_export]
macro_rules! count (
  ($key:expr, $value: expr) => ({
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).count_add($key, v);
    });
  })
);

#[macro_export]
macro_rules! incr (
  ($key:expr) => (count!($key, 1);)
);

#[macro_export]
macro_rules! decr (
  ($key:expr) => (count!($key, -1);)
);

#[macro_export]
macro_rules! gauge (
  ($key:expr, $value: expr) => {
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).set_gauge($key, v);
    });
  }
);

#[macro_export]
macro_rules! gauge_add (
  ($key:expr, $value: expr) => {
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).gauge_add($key, v);
    });
  }
);

#[macro_export]
macro_rules! time (
  ($key:expr, $value: expr) => {
    use std::time::Instant;
    use $crate::network::metrics::{MetricData,Subscriber};
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      let ref mut m = *metrics.borrow_mut();
      let app: &str = $app_id;

      m.receive_metric($key, None, None, MetricData::Time($value as usize));
    });
  };
  ($key:expr, $app_id:expr, $value: expr) => {
    use std::time::Instant;
    use $crate::network::metrics::{MetricData,Subscriber};
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      let ref mut m = *metrics.borrow_mut();
      let app: &str = $app_id;

      m.receive_metric($key, Some(app), None, MetricData::Time($value as usize));
    });
  }
);

#[macro_export]
macro_rules! record_backend_metrics (
  ($app_id:expr, $backend_id:expr, $response_time: expr, $bin: expr, $bout: expr) => {
    use std::time::Instant;
    use $crate::network::metrics::{MetricData,Subscriber};
    $crate::network::metrics::METRICS.with(|metrics| {
      let ref mut m = *metrics.borrow_mut();
      let app_id: &str = $app_id.as_str();
      let backend_id: &str = $backend_id;

      m.receive_metric("bytes_in", Some(app_id), Some(backend_id), MetricData::Count($bin as i64));
      m.receive_metric("bytes_out", Some(app_id), Some(backend_id), MetricData::Count($bout as i64));
      m.receive_metric("response_time", Some(app_id), Some(backend_id), MetricData::Time($response_time as usize));
    });
  }
);

<commit_msg>correctly wrap gauge metrics macros<commit_after>use std::str;
use std::thread;
use std::sync::Mutex;
use std::cell::RefCell;
use std::time::{Duration,Instant};
use std::iter::repeat;
use std::collections::BTreeMap;
use std::collections::VecDeque;
use std::fmt::Arguments;
use std::net::SocketAddr;
use mio::net::UdpSocket;
use std::io::{self,BufWriter,Write,Error,ErrorKind};
use nom::HexDisplay;
use hdrhistogram::Histogram;
use sozu_command::buffer::Buffer;
use sozu_command::messages::{FilteredData,MetricsData,Percentiles,BackendMetricsData,FilteredTimeSerie};

mod network_drain;
mod local_drain;

use self::network_drain::NetworkDrain;
use self::local_drain::LocalDrain;

thread_local! {
  pub static METRICS: RefCell<Aggregator> = RefCell::new(Aggregator::new(String::from("sozu")));
}

#[derive(Debug,Clone,PartialEq)]
pub enum MetricData {
  Gauge(usize),
  GaugeAdd(i64),
  Count(i64),
  Time(usize),
}

impl MetricData {
  fn is_time(&self) -> bool {
    match self {
      &MetricData::Time(_) => true,
      _ => false,
    }
  }

  fn update(&mut self, key: &'static str, m: MetricData) {
    match (self, m) {
      (&mut MetricData::Gauge(ref mut v1), MetricData::Gauge(v2)) => {
        *v1 = v2;
      },
      (&mut MetricData::Gauge(ref mut v1), MetricData::GaugeAdd(v2)) => {
        debug_assert!(*v1 as i64 + v2 >= 0, "metric {} underflow: previous value: {}, adding: {}", key, v1, v2);
        let res = *v1 as i64 + v2;
        *v1 = if res >= 0 {
          res as usize
        } else {
          error!("metric {} underflow: previous value: {}, adding: {}", key, v1, v2);
          0
        }
      },
      (&mut MetricData::Count(ref mut v1), MetricData::Count(v2)) => {
        *v1 += v2;
      },
      (s,m) => panic!("tried to update metric {} of value {:?} with an incompatible metric: {:?}", key, s, m)
    }
  }
}

#[derive(Debug,Clone)]
pub struct StoredMetricData {
  last_sent: Instant,
  data:      MetricData,
}

impl StoredMetricData {
  pub fn new(last_sent: Instant, data: MetricData) -> StoredMetricData {
    StoredMetricData {
      last_sent: last_sent,
      data: if let MetricData::GaugeAdd(v) = data {
        MetricData::Gauge(v as usize)
      } else { data }
    }
  }
}

pub fn setup<H: AsRef<str>, O: Into<String>>(host: H, port: u16, origin: O, use_tagged_metrics: bool, prefix: Option<String>) {
  use std::net::ToSocketAddrs;
  let metrics_socket = udp_bind();

  debug!("setting up metrics: local address = {:#?}", metrics_socket.local_addr());
  let metrics_host   = (host.as_ref(), port).to_socket_addrs().expect("could not parse address").next().expect("could not get first address");

  METRICS.with(|metrics| {
    if let Some(p) = prefix {
      (*metrics.borrow_mut()).set_up_prefix(p);
    }
    (*metrics.borrow_mut()).set_up_remote(metrics_socket, metrics_host);
    (*metrics.borrow_mut()).set_up_origin(origin.into());
    (*metrics.borrow_mut()).set_up_tagged_metrics(use_tagged_metrics);
  });
}

pub trait Subscriber {
  fn receive_metric(&mut self, label: &'static str, app_id: Option<&str>, backend_id: Option<&str>, metric: MetricData);
}

pub struct Aggregator {
  prefix:  String,
  network: Option<NetworkDrain>,
  local:   LocalDrain,
}

impl Aggregator {
  pub fn new(prefix: String) -> Aggregator {
    Aggregator {
      prefix: prefix.clone(),
      network: None,
      local: LocalDrain::new(prefix),
    }
  }

  pub fn set_up_prefix(&mut self, prefix: String) {
    self.prefix = prefix;
  }

  pub fn set_up_remote(&mut self, socket: UdpSocket, addr: SocketAddr) {
    self.network = Some(NetworkDrain::new(self.prefix.clone(), socket, addr));
  }

  pub fn set_up_origin(&mut self, origin: String) {
    self.network.as_mut().map(|n| n.origin = origin);
  }

  pub fn set_up_tagged_metrics(&mut self, tagged: bool) {
    self.network.as_mut().map(|n| n.use_tagged_metrics = tagged);
  }

  pub fn socket(&self) -> Option<&UdpSocket> {
    self.network.as_ref().map(|n| &n.remote.get_ref().socket)
  }

  pub fn count_add(&mut self, key: &'static str, count_value: i64) {
    self.receive_metric(key, None, None, MetricData::Count(count_value));
  }

  pub fn set_gauge(&mut self, key: &'static str, gauge_value: usize) {
    self.receive_metric(key, None, None, MetricData::Gauge(gauge_value));
  }

  pub fn gauge_add(&mut self, key: &'static str, gauge_value: i64) {
    self.receive_metric(key, None, None, MetricData::GaugeAdd(gauge_value));
  }

  pub fn writable(&mut self) {
    if let Some(ref mut net) = self.network.as_mut() {
      net.writable();
    }
  }

  pub fn send_data(&mut self) {
    if let Some(ref mut net) = self.network.as_mut() {
      net.send_data();
    }
  }

  pub fn dump_metrics_data(&mut self) -> MetricsData {
    self.local.dump_metrics_data()
  }

  pub fn dump_process_data(&mut self) -> BTreeMap<String, FilteredData> {
    self.local.dump_process_data()
  }
}

impl Subscriber for Aggregator {
  fn receive_metric(&mut self, label: &'static str, app_id: Option<&str>, backend_id: Option<&str>, metric: MetricData) {
    if let Some(ref mut net) = self.network.as_mut() {
      net.receive_metric(label, app_id, backend_id, metric.clone());
    }
    self.local.receive_metric(label, app_id, backend_id, metric.clone());
  }
}

#[derive(Debug,Clone,PartialEq)]
pub struct MetricLine {
  label:      &'static str,
  app_id:     Option<String>,
  backend_id: Option<String>,
  /// in milliseconds
  duration:   usize,
}

pub struct MetricSocket {
  pub addr:   SocketAddr,
  pub socket: UdpSocket,
}

impl Write for MetricSocket {
  fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
    self.socket.send_to(buf, &self.addr)
  }

  fn flush(&mut self) -> io::Result<()> {
    Ok(())
  }
}

pub fn udp_bind() -> UdpSocket {
  UdpSocket::bind(&("0.0.0.0:0".parse().unwrap())).expect("could not parse address")
}

#[macro_export]
macro_rules! count (
  ($key:expr, $value: expr) => ({
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).count_add($key, v);
    });
  })
);

#[macro_export]
macro_rules! incr (
  ($key:expr) => (count!($key, 1);)
);

#[macro_export]
macro_rules! decr (
  ($key:expr) => (count!($key, -1);)
);

#[macro_export]
macro_rules! gauge (
  ($key:expr, $value: expr) => ({
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).set_gauge($key, v);
    });
  })
);

#[macro_export]
macro_rules! gauge_add (
  ($key:expr, $value: expr) => ({
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).gauge_add($key, v);
    });
  })
);

#[macro_export]
macro_rules! time (
  ($key:expr, $value: expr) => {
    use std::time::Instant;
    use $crate::network::metrics::{MetricData,Subscriber};
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      let ref mut m = *metrics.borrow_mut();
      let app: &str = $app_id;

      m.receive_metric($key, None, None, MetricData::Time($value as usize));
    });
  };
  ($key:expr, $app_id:expr, $value: expr) => {
    use std::time::Instant;
    use $crate::network::metrics::{MetricData,Subscriber};
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      let ref mut m = *metrics.borrow_mut();
      let app: &str = $app_id;

      m.receive_metric($key, Some(app), None, MetricData::Time($value as usize));
    });
  }
);

#[macro_export]
macro_rules! record_backend_metrics (
  ($app_id:expr, $backend_id:expr, $response_time: expr, $bin: expr, $bout: expr) => {
    use std::time::Instant;
    use $crate::network::metrics::{MetricData,Subscriber};
    $crate::network::metrics::METRICS.with(|metrics| {
      let ref mut m = *metrics.borrow_mut();
      let app_id: &str = $app_id.as_str();
      let backend_id: &str = $backend_id;

      m.receive_metric("bytes_in", Some(app_id), Some(backend_id), MetricData::Count($bin as i64));
      m.receive_metric("bytes_out", Some(app_id), Some(backend_id), MetricData::Count($bout as i64));
      m.receive_metric("response_time", Some(app_id), Some(backend_id), MetricData::Time($response_time as usize));
    });
  }
);

<|endoftext|>


<commit_before>use std::mem;
use std::cmp;
use vector::Vec2;

pub fn triangle(buffer: &mut Vec<u32>, x_size: usize, y_size: usize, p_a: Vec2, p_b: Vec2, p_c: Vec2) {
    let mut a = &p_a;
    let mut b = &p_b;
    let mut c = &p_c;

    // a.y > b.y > c.y
    if a.y < b.y {
        mem::swap(&mut a, &mut b);
    }
    if a.y < c.y {
        mem::swap(&mut a, &mut c);
    }
    if b.y < c.y {
        mem::swap(&mut b, &mut c);
    }

    // is visible
    let min_y = 0.5_f32;
    let min_x = 0.5_f32;
    let max_y = y_size as f32 - 0.5_f32;
    let max_x = x_size as f32 - 0.5_f32;
    if (a.y < min_y) ||
        (c.y > max_y) ||
        (a.x < min_x && b.x < min_x && c.x < min_x) ||
        (a.x > max_x && b.x > max_x && c.x > max_x) {
            return;
        }

    // steps for line
    let epsilon = 0.0001_f32;
    let step_ab = if a.y - b.y > epsilon {
        (a.x - b.x) / (a.y - b.y)
    } else {
        0.0_f32
    };
    let step_ac = if a.y - c.y > epsilon {
        (a.x - c.x) / (a.y - c.y)
    } else {
        0.0_f32
    };
    let step_bc = if b.y - c.y > epsilon {
        (b.x - c.x) / (b.y - c.y)
    } else {
        0.0_f32
    };

    // y-ranges: [y0; y1) + [y1; y2)
    let y0 = cmp::min(cmp::max((c.y + 0.5_f32) as i32, 0) as usize, y_size - 1);
    let y1 = cmp::min(cmp::max((b.y + 0.5_f32) as i32, 0) as usize, y_size);
    let y2 = cmp::min(cmp::max((a.y + 0.5_f32) as i32, 0) as usize, y_size);
    let point_base = [c, a];
    let y_begin = [y0, y1];
    let y_end = [y1, y2];

    let step0 = if step_bc > step_ac {
        (step_ac, step_bc)
    } else {
        (step_bc, step_ac)
    };
    let step1 = if step_ab > step_ac {
        (step_ab, step_ac)
    } else {
        (step_ac, step_ab)
    };
    let steps = [step0, step1];

    for i in (0..2) {
        if y_begin[i] < y_end[i] {
            let y_step = y_begin[i] as f32 + 0.5_f32 - point_base[i].y;
            let (x1_step, x2_step) = steps[i];
            let mut x1 = point_base[i].x + y_step * x1_step + (0.5_f32 - epsilon);
            let mut x2 = point_base[i].x + y_step * x2_step - (0.5_f32 + epsilon);

            println!("");
            println!("  step: x={}-{};", x1_step, x2_step);
            for y in y_begin[i]..y_end[i] {
                let x1_int = cmp::min(cmp::max(x1 as i32, 0) as usize, x_size);
                let x2_int = cmp::min(cmp::max(x2 as i32, 0) as usize, x_size) + 1;
                println!("{}: y={}; x={}-{};", i, y, x1_int, x2_int);
                println!("  real: x={}-{};", x1, x2);
                for x in (x1_int..x2_int) {
                    buffer[y * x_size + x] = 0x00FF00;
                }

                x1 += x1_step;
                x2 += x2_step;
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use vector::Vec2;
    use rasterization::triangle;

    fn triangle_test(a: Vec2, b: Vec2, c: Vec2, buffer_except: Vec<u32>) {
        let x_size: usize = 7;
        let y_size: usize = 5;
        let mut buffer: Vec<u32> = vec![0; x_size * y_size];
        triangle(&mut buffer, x_size, y_size, a, b, c);

        println!("");
        println!("real: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if buffer[(y_size - y - 1) * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        println!("except: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if buffer_except[y * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        for y in 0..y_size {
            for x in 0..x_size {
                let val_real = buffer[y * x_size + x];
                let val_except = buffer_except[(y_size - y - 1) * x_size + x];
                debug_assert!((val_real==0) == (val_except==0),
                              "real = {}, except = {}, x = {} y = {}",
                              val_real, val_except, x, y);
            }
        }
    }

    #[test]
    fn triangle_0() {
        triangle_test(Vec2::new(1.0,4.0), Vec2::new(2.0,1.0), Vec2::new(6.0,3.0),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_1() {
        triangle_test(Vec2::new(1.4,1.6), Vec2::new(2.4,1.6), Vec2::new(2.4,2.6),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_2() {
        triangle_test(Vec2::new(3.5,1.5), Vec2::new(4.5,1.5), Vec2::new(4.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_3() {
        triangle_test(Vec2::new(2.5,2.5), Vec2::new(2.5,2.5), Vec2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_4() {
        triangle_test(Vec2::new(0.0,0.0), Vec2::new(4.0,0.0), Vec2::new(6.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,1,0,0,
                           0,1,1,1,0,0,0]);
    }
}
<commit_msg>поправил ошибки отрисовки и добавил новые тесты<commit_after>use std::mem;
use std::cmp;
use vector::Vec2;

pub fn triangle(buffer: &mut Vec<u32>, x_size: usize, y_size: usize, p_a: Vec2, p_b: Vec2, p_c: Vec2) {
    let mut a = &p_a;
    let mut b = &p_b;
    let mut c = &p_c;

    // a.y > b.y > c.y
    if a.y < b.y {
        mem::swap(&mut a, &mut b);
    }
    if a.y < c.y {
        mem::swap(&mut a, &mut c);
    }
    if b.y < c.y {
        mem::swap(&mut b, &mut c);
    }

    // is visible
    let min_y = 0.5_f32;
    let min_x = 0.5_f32;
    let max_y = y_size as f32 - 0.5_f32;
    let max_x = x_size as f32 - 0.5_f32;
    if (a.y < min_y) ||
        (c.y > max_y) ||
        (a.x < min_x && b.x < min_x && c.x < min_x) ||
        (a.x > max_x && b.x > max_x && c.x > max_x) {
            return;
        }

    // steps for line
    let epsilon = 0.0001_f32;
    let step_ab = if a.y - b.y > epsilon {
        (a.x - b.x) / (a.y - b.y)
    } else {
        0.0_f32
    };
    let step_ac = if a.y - c.y > epsilon {
        (a.x - c.x) / (a.y - c.y)
    } else {
        0.0_f32
    };
    let step_bc = if b.y - c.y > epsilon {
        (b.x - c.x) / (b.y - c.y)
    } else {
        0.0_f32
    };

    // y-ranges: [y0; y1) + [y1; y2)
    let y0 = cmp::min(cmp::max((c.y + 0.5_f32) as i32, 0) as usize, y_size - 1);
    let y1 = cmp::min(cmp::max((b.y + 0.5_f32) as i32, 0) as usize, y_size);
    let y2 = cmp::min(cmp::max((a.y + 0.5_f32) as i32, 0) as usize, y_size);
    let point_base = [c, a];
    let y_begin = [y0, y1];
    let y_end = [y1, y2];

    let step0 = if step_bc > step_ac {
        (step_ac, step_bc)
    } else {
        (step_bc, step_ac)
    };
    let step1 = if step_ab > step_ac {
        (step_ab, step_ac)
    } else {
        (step_ac, step_ab)
    };
    let steps = [step0, step1];

    for i in (0..2) {
        if y_begin[i] < y_end[i] {
            let y_step = y_begin[i] as f32 + 0.5_f32 - point_base[i].y;
            let (x1_step, x2_step) = steps[i];
            let mut x1 = point_base[i].x + y_step * x1_step + (0.5_f32 - epsilon);
            let mut x2 = point_base[i].x + y_step * x2_step - (0.5_f32 + epsilon);

            for y in y_begin[i]..y_end[i] {
                if x2 >= 0.0_f32 {
                    let x1_int = cmp::min(cmp::max(x1 as i32, 0) as usize, x_size);
                    let x2_int = cmp::min(cmp::max(x2 as i32, 0) as usize, x_size) + 1;
                    for x in (x1_int..x2_int) {
                        buffer[y * x_size + x] = 0x00FF00;
                    }
                }

                x1 += x1_step;
                x2 += x2_step;
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use vector::Vec2;
    use rasterization::triangle;

    fn triangle_test(a: Vec2, b: Vec2, c: Vec2, buffer_except: Vec<u32>) {
        let x_size: usize = 7;
        let y_size: usize = 5;
        let mut buffer: Vec<u32> = vec![0; x_size * y_size];
        triangle(&mut buffer, x_size, y_size, a, b, c);

        println!("");
        println!("real: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if buffer[(y_size - y - 1) * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        println!("except: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if buffer_except[y * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        for y in 0..y_size {
            for x in 0..x_size {
                let val_real = buffer[y * x_size + x];
                let val_except = buffer_except[(y_size - y - 1) * x_size + x];
                debug_assert!((val_real==0) == (val_except==0),
                              "real = {}, except = {}, x = {} y = {}",
                              val_real, val_except, x, y);
            }
        }
    }

    #[test]
    fn triangle_00() {
        triangle_test(Vec2::new(1.0,4.0), Vec2::new(2.0,1.0), Vec2::new(6.0,3.0),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_01() {
        triangle_test(Vec2::new(1.4,1.6), Vec2::new(2.4,1.6), Vec2::new(2.4,2.6),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_02() {
        triangle_test(Vec2::new(3.5,1.5), Vec2::new(4.5,1.5), Vec2::new(4.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_03() {
        triangle_test(Vec2::new(2.5,2.5), Vec2::new(2.5,2.5), Vec2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_04() {
        triangle_test(Vec2::new(0.0,0.0), Vec2::new(4.0,0.0), Vec2::new(6.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,1,0,0,
                           0,1,1,1,0,0,0]);
    }

    #[test]
    fn triangle_05() {
        triangle_test(Vec2::new(1.0,2.0), Vec2::new(4.0,1.0), Vec2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,1,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_06() {
        triangle_test(Vec2::new(5.5,2.5), Vec2::new(4.0,1.0), Vec2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,1,0,0,0,
                           0,0,0,1,1,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_07() {
        triangle_test(Vec2::new(1.5,0.5), Vec2::new(2.5,0.5), Vec2::new(1.5,-2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0]);
    }

    #[test]
    fn triangle_08() {
        triangle_test(Vec2::new(0.7,3.5), Vec2::new(2.5,0.7), Vec2::new(4.6,3.5),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,1,1,1,0,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_09() {
        triangle_test(Vec2::new(0.7,1.5), Vec2::new(2.7,3.2), Vec2::new(4.7,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_10() {
        triangle_test(Vec2::new(0.5,0.5), Vec2::new(0.5,2.5), Vec2::new(1.5,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_11() {
        triangle_test(Vec2::new(0.5,0.5), Vec2::new(0.5,2.5), Vec2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_12() {
        triangle_test(Vec2::new(0.5,0.5), Vec2::new(2.5,2.5), Vec2::new(2.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_13() {
        triangle_test(Vec2::new(0.5,3.5), Vec2::new(1.5,2.5), Vec2::new(1.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_14() {
        triangle_test(Vec2::new(0.5,3.5), Vec2::new(1.5,2.5), Vec2::new(2.0,5.0),
                      vec![0,1,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_15() {
        triangle_test(Vec2::new(0.5,0.5), Vec2::new(2.5,0.5), Vec2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_16() {
        triangle_test(Vec2::new(2.5,2.5), Vec2::new(2.5,0.5), Vec2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }
}
<|endoftext|>


<commit_before>//! Amazon MWS Fulfillment Inbound Shipment API - Version 2010-10-01
//!
//! [Documentation](http://docs.developer.amazonservices.com/en_CA/fba_inbound/FBAInbound_Overview.html)

use chrono::{DateTime, UTC};
use client::{Client, Method, Response};
use xmlhelper::decode;
use super::types::ToIso8601;

mod types;
pub use self::types::*;

error_chain! {
  links {
    Client(super::client::Error, super::client::ErrorKind);
    Decode(decode::Error, decode::ErrorKind);
  }
}

static PATH: &'static str = "/FulfillmentInboundShipment/2010-10-01";
static VERSION: &'static str = "2010-10-01";

/// Parameters for `ListInboundShipments`
#[derive(Debug, Default)]
pub struct ListInboundShipmentsParameters {
  pub shipment_status_list: Vec<ShipmentStatus>,
  pub shipment_id_list: Vec<String>,
  pub last_updated_after: Option<DateTime<UTC>>,
  pub last_updated_before: Option<DateTime<UTC>>,
}

impl Into<Vec<(String, String)>> for ListInboundShipmentsParameters {
  fn into(self) -> Vec<(String, String)> {
    let mut result = vec![];
    for (i, s) in self.shipment_status_list.into_iter().enumerate() {
      result.push((format!("ShipmentStatusList.member.{}", i + 1), s.to_string()));
    }

    for (i, id) in self.shipment_id_list.into_iter().enumerate() {
      result.push((format!("ShipmentIdList.member.{}", i + 1), id.to_string()));
    }

    if let Some(date) = self.last_updated_after {
      result.push(("LastUpdatedAfter".to_string(), date.to_iso8601()));
    }

    if let Some(date) = self.last_updated_before {
      result.push(("LastUpdatedBefore".to_string(), date.to_iso8601()));
    }

    result
  }
}

#[derive(Debug, Default, PartialEq)]
pub struct ListInboundShipmentsResponse {
  pub request_id: String,
  pub shipment_data: Vec<InboundShipmentInfo>,
  pub next_token: Option<String>,
}

impl<S: decode::XmlEventStream> decode::FromXMLStream<S> for ListInboundShipmentsResponse {
  fn from_xml(s: &mut S) -> decode::Result<ListInboundShipmentsResponse> {
    use self::decode::{start_document, element, fold_elements, characters};
    start_document(s)?;
    element(s, vec!["ListInboundShipmentsResponse", "ListInboundShipmentsByNextTokenResponse"], |s| {
      fold_elements(s, ListInboundShipmentsResponse::default(), |s, response| {
        match s.local_name() {
          "ListInboundShipmentsResult" | "ListInboundShipmentsByNextTokenResult" => {
            fold_elements(s, (), |s, _| {
              match s.local_name() {
                "ShipmentData" => {
                  response.shipment_data = fold_elements(s, vec![], |s, list| {
                    list.push(InboundShipmentInfo::from_xml(s)?);
                    Ok(())
                  })?;
                },
                "NextToken" => {
                  response.next_token = Some(characters(s)?);
                },
                _ => {},
              }
              Ok(())
            })
          },
          "ResponseMetadata" => {
            response.request_id = element(s, "RequestId", |s| {
              characters(s)
            })?;
            Ok(())
          },
          _ => { Ok(()) }
        }
      })
    })
  }
}

/// Returns a list of inbound shipments based on criteria that you specify.
///
/// [Documentation](http://docs.developer.amazonservices.com/en_CA/fba_inbound/FBAInbound_ListInboundShipments.html)
#[allow(non_snake_case)]
pub fn ListInboundShipments(client: &Client, parameters: ListInboundShipmentsParameters) -> Result<Response<ListInboundShipmentsResponse>> {
  client.request_xml(Method::Post, PATH, VERSION, "ListInboundShipments", parameters).map_err(|err| err.into())
}

/// Returns the next page of inbound shipments using the NextToken parameter.
///
/// [Documentation](http://docs.developer.amazonservices.com/en_CA/fba_inbound/FBAInbound_ListInboundShipmentsByNextToken.html)
#[allow(non_snake_case)]
pub fn ListInboundShipmentsByNextToken(client: &Client, next_token: String) -> Result<Response<ListInboundShipmentsResponse>> {
  let params = vec![
    ("NextToken".to_string(), next_token)
  ];
  client.request_xml(Method::Post, PATH, VERSION, "ListInboundShipmentsByNextToken", params).map_err(|err| err.into())
}

/// Parameters for `ListInboundShipments`
#[derive(Debug, Default)]
pub struct ListInboundShipmentItemsParameters {
  pub shipment_id: String,
  pub last_updated_after: Option<DateTime<UTC>>,
  pub last_updated_before: Option<DateTime<UTC>>,
}

impl Into<Vec<(String, String)>> for ListInboundShipmentItemsParameters {
  fn into(self) -> Vec<(String, String)> {
    let mut result = vec![
      ("ShipmentId".to_owned(), self.shipment_id)
    ];

    if let Some(date) = self.last_updated_after {
      result.push(("LastUpdatedAfter".to_string(), date.to_iso8601()));
    }

    if let Some(date) = self.last_updated_before {
      result.push(("LastUpdatedBefore".to_string(), date.to_iso8601()));
    }

    result
  }
}

#[derive(Debug, Default, PartialEq)]
pub struct ListInboundShipmentItemsResponse {
  pub request_id: String,
  pub item_data: Vec<InboundShipmentItem>,
  pub next_token: Option<String>,
}

impl<S: decode::XmlEventStream> decode::FromXMLStream<S> for ListInboundShipmentItemsResponse {
  fn from_xml(s: &mut S) -> decode::Result<ListInboundShipmentItemsResponse> {
    use self::decode::{start_document, element, fold_elements, characters};
    start_document(s)?;
    element(s, vec!["ListInboundShipmentItemsResponse", "ListInboundShipmentItemsByNextTokenResponse"], |s| {
      fold_elements(s, ListInboundShipmentItemsResponse::default(), |s, response| {
        match s.local_name() {
          "ListInboundShipmentItemsResult" | "ListInboundShipmentItemsByNextTokenResult" => {
            fold_elements(s, (), |s, _| {
              match s.local_name() {
                "ItemData" => {
                  response.item_data = fold_elements(s, vec![], |s, list| {
                    list.push(InboundShipmentItem::from_xml(s)?);
                    Ok(())
                  })?;
                },
                "NextToken" => {
                  response.next_token = Some(characters(s)?);
                },
                _ => {},
              }
              Ok(())
            })
          },
          "ResponseMetadata" => {
            response.request_id = element(s, "RequestId", |s| {
              characters(s)
            })?;
            Ok(())
          },
          _ => { Ok(()) }
        }
      })
    })
  }
}

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

  #[test]
  fn test_decode_list_inbound_shipments_response() {
    test_decode!(ListInboundShipmentsResponse, r#"
    <ListInboundShipmentsResponse xmlns="http://mws.amazonaws.com/FulfillmentInboundShipment/2010-10-01/">
      <ListInboundShipmentsResult>
        <ShipmentData>
          <member>
            <DestinationFulfillmentCenterId>MDW2</DestinationFulfillmentCenterId>
            <LabelPrepType>NO_LABEL</LabelPrepType>
            <ShipFromAddress>
              <City>Fort Worth</City>
              <CountryCode>US</CountryCode>
              <PostalCode>76104</PostalCode>
              <Name>RPD LTD</Name>
              <AddressLine1>428 Hemphill St</AddressLine1>
              <StateOrProvinceCode>TX</StateOrProvinceCode>
            </ShipFromAddress>
            <ShipmentId>FBA4FWJMVV</ShipmentId>
            <AreCasesRequired>true</AreCasesRequired>
            <ShipmentName>FBA (2/19/17 9:39 PM) - 1</ShipmentName>
            <BoxContentsSource>INTERACTIVE</BoxContentsSource>
            <ShipmentStatus>CLOSED</ShipmentStatus>
          </member>
        </ShipmentData>
      </ListInboundShipmentsResult>
      <ResponseMetadata>
        <RequestId>04c87e79-f747-4da9-984f-5bc1f0b875e6</RequestId>
      </ResponseMetadata>
    </ListInboundShipmentsResponse>
    "#, ListInboundShipmentsResponse {
      next_token: None,
      request_id: "04c87e79-f747-4da9-984f-5bc1f0b875e6".to_owned(),
      shipment_data: vec![
        InboundShipmentInfo {
          DestinationFulfillmentCenterId: "MDW2".to_owned(),
          LabelPrepType: Some(LabelPrepType::NO_LABEL),
          ShipFromAddress: Address {
            City: "Fort Worth".to_owned(),
            CountryCode: "US".to_owned(),
            PostalCode: "76104".to_owned(),
            Name: "RPD LTD".to_owned(),
            AddressLine1: "428 Hemphill St".to_owned(),
            AddressLine2: "".to_owned(),
            StateOrProvinceCode: "TX".to_owned(),
            DistrictOrCounty: "".to_owned(),
          },
          ShipmentId: "FBA4FWJMVV".to_owned(),
          AreCasesRequired: true,
          ShipmentName: "FBA (2/19/17 9:39 PM) - 1".to_owned(),
          BoxContentsSource: Some(BoxContentsSource::INTERACTIVE),
          ShipmentStatus: ShipmentStatus::CLOSED,
          ConfirmedNeedByDate: "".to_owned(),
          EstimatedBoxContentsFee: None,
        }
      ],
    });
  }

  #[test]
  fn test_decode_list_inbound_shipment_items_response() {
    test_decode!(ListInboundShipmentItemsResponse, r#"
    <ListInboundShipmentItemsResponse xmlns="http://mws.amazonaws.com/FulfillmentInboundShipment/2010-10-01/">
      <ListInboundShipmentItemsResult>
        <ItemData>
          <member>
            <QuantityShipped>60</QuantityShipped>
            <ShipmentId>FBA3T68MQL</ShipmentId>
            <PrepDetailsList>
              <PrepDetails/>
            </PrepDetailsList>
            <FulfillmentNetworkSKU>B016P9HJIA</FulfillmentNetworkSKU>
            <SellerSKU>edifier-r1280t-fba</SellerSKU>
            <QuantityReceived>50</QuantityReceived>
            <QuantityInCase>2</QuantityInCase>
          </member>
        </ItemData>
      </ListInboundShipmentItemsResult>
      <ResponseMetadata>
        <RequestId>70a60f01-d0df-4a29-b093-e1cb53bd8fc2</RequestId>
      </ResponseMetadata>
    </ListInboundShipmentItemsResponse>
    "#, ListInboundShipmentItemsResponse {
      next_token: None,
      request_id: "70a60f01-d0df-4a29-b093-e1cb53bd8fc2".to_owned(),
      item_data: vec![
        InboundShipmentItem {
          ShipmentId: "FBA3T68MQL".to_owned(),
          SellerSKU: "edifier-r1280t-fba".to_owned(),
          QuantityShipped: 60,
          QuantityInCase: Some(2),
          QuantityReceived: Some(50),
          FulfillmentNetworkSKU: "B016P9HJIA".to_owned(),
        }
      ],
    });
  }

}<commit_msg>Implement missing methods for inbound inventory - ListInboundShipmentItems - ListInboundShipmentItemsByNextToken<commit_after>//! Amazon MWS Fulfillment Inbound Shipment API - Version 2010-10-01
//!
//! [Documentation](http://docs.developer.amazonservices.com/en_CA/fba_inbound/FBAInbound_Overview.html)

use chrono::{DateTime, UTC};
use client::{Client, Method, Response};
use xmlhelper::decode;
use super::types::ToIso8601;

mod types;
pub use self::types::*;

error_chain! {
  links {
    Client(super::client::Error, super::client::ErrorKind);
    Decode(decode::Error, decode::ErrorKind);
  }
}

static PATH: &'static str = "/FulfillmentInboundShipment/2010-10-01";
static VERSION: &'static str = "2010-10-01";

/// Parameters for `ListInboundShipments`
#[derive(Debug, Default)]
pub struct ListInboundShipmentsParameters {
  pub shipment_status_list: Vec<ShipmentStatus>,
  pub shipment_id_list: Vec<String>,
  pub last_updated_after: Option<DateTime<UTC>>,
  pub last_updated_before: Option<DateTime<UTC>>,
}

impl Into<Vec<(String, String)>> for ListInboundShipmentsParameters {
  fn into(self) -> Vec<(String, String)> {
    let mut result = vec![];
    for (i, s) in self.shipment_status_list.into_iter().enumerate() {
      result.push((format!("ShipmentStatusList.member.{}", i + 1), s.to_string()));
    }

    for (i, id) in self.shipment_id_list.into_iter().enumerate() {
      result.push((format!("ShipmentIdList.member.{}", i + 1), id.to_string()));
    }

    if let Some(date) = self.last_updated_after {
      result.push(("LastUpdatedAfter".to_string(), date.to_iso8601()));
    }

    if let Some(date) = self.last_updated_before {
      result.push(("LastUpdatedBefore".to_string(), date.to_iso8601()));
    }

    result
  }
}

#[derive(Debug, Default, PartialEq)]
pub struct ListInboundShipmentsResponse {
  pub request_id: String,
  pub shipment_data: Vec<InboundShipmentInfo>,
  pub next_token: Option<String>,
}

impl<S: decode::XmlEventStream> decode::FromXMLStream<S> for ListInboundShipmentsResponse {
  fn from_xml(s: &mut S) -> decode::Result<ListInboundShipmentsResponse> {
    use self::decode::{start_document, element, fold_elements, characters};
    start_document(s)?;
    element(s, vec!["ListInboundShipmentsResponse", "ListInboundShipmentsByNextTokenResponse"], |s| {
      fold_elements(s, ListInboundShipmentsResponse::default(), |s, response| {
        match s.local_name() {
          "ListInboundShipmentsResult" | "ListInboundShipmentsByNextTokenResult" => {
            fold_elements(s, (), |s, _| {
              match s.local_name() {
                "ShipmentData" => {
                  response.shipment_data = fold_elements(s, vec![], |s, list| {
                    list.push(InboundShipmentInfo::from_xml(s)?);
                    Ok(())
                  })?;
                },
                "NextToken" => {
                  response.next_token = Some(characters(s)?);
                },
                _ => {},
              }
              Ok(())
            })
          },
          "ResponseMetadata" => {
            response.request_id = element(s, "RequestId", |s| {
              characters(s)
            })?;
            Ok(())
          },
          _ => { Ok(()) }
        }
      })
    })
  }
}

/// Returns a list of inbound shipments based on criteria that you specify.
///
/// [Documentation](http://docs.developer.amazonservices.com/en_CA/fba_inbound/FBAInbound_ListInboundShipments.html)
#[allow(non_snake_case)]
pub fn ListInboundShipments(client: &Client, parameters: ListInboundShipmentsParameters) -> Result<Response<ListInboundShipmentsResponse>> {
  client.request_xml(Method::Post, PATH, VERSION, "ListInboundShipments", parameters).map_err(|err| err.into())
}

/// Returns the next page of inbound shipments using the NextToken parameter.
///
/// [Documentation](http://docs.developer.amazonservices.com/en_CA/fba_inbound/FBAInbound_ListInboundShipmentsByNextToken.html)
#[allow(non_snake_case)]
pub fn ListInboundShipmentsByNextToken(client: &Client, next_token: String) -> Result<Response<ListInboundShipmentsResponse>> {
  let params = vec![
    ("NextToken".to_string(), next_token)
  ];
  client.request_xml(Method::Post, PATH, VERSION, "ListInboundShipmentsByNextToken", params).map_err(|err| err.into())
}

/// Parameters for `ListInboundShipments`
#[derive(Debug, Default)]
pub struct ListInboundShipmentItemsParameters {
  pub shipment_id: String,
  pub last_updated_after: Option<DateTime<UTC>>,
  pub last_updated_before: Option<DateTime<UTC>>,
}

impl Into<Vec<(String, String)>> for ListInboundShipmentItemsParameters {
  fn into(self) -> Vec<(String, String)> {
    let mut result = vec![
      ("ShipmentId".to_owned(), self.shipment_id)
    ];

    if let Some(date) = self.last_updated_after {
      result.push(("LastUpdatedAfter".to_string(), date.to_iso8601()));
    }

    if let Some(date) = self.last_updated_before {
      result.push(("LastUpdatedBefore".to_string(), date.to_iso8601()));
    }

    result
  }
}

#[derive(Debug, Default, PartialEq)]
pub struct ListInboundShipmentItemsResponse {
  pub request_id: String,
  pub item_data: Vec<InboundShipmentItem>,
  pub next_token: Option<String>,
}

impl<S: decode::XmlEventStream> decode::FromXMLStream<S> for ListInboundShipmentItemsResponse {
  fn from_xml(s: &mut S) -> decode::Result<ListInboundShipmentItemsResponse> {
    use self::decode::{start_document, element, fold_elements, characters};
    start_document(s)?;
    element(s, vec!["ListInboundShipmentItemsResponse", "ListInboundShipmentItemsByNextTokenResponse"], |s| {
      fold_elements(s, ListInboundShipmentItemsResponse::default(), |s, response| {
        match s.local_name() {
          "ListInboundShipmentItemsResult" | "ListInboundShipmentItemsByNextTokenResult" => {
            fold_elements(s, (), |s, _| {
              match s.local_name() {
                "ItemData" => {
                  response.item_data = fold_elements(s, vec![], |s, list| {
                    list.push(InboundShipmentItem::from_xml(s)?);
                    Ok(())
                  })?;
                },
                "NextToken" => {
                  response.next_token = Some(characters(s)?);
                },
                _ => {},
              }
              Ok(())
            })
          },
          "ResponseMetadata" => {
            response.request_id = element(s, "RequestId", |s| {
              characters(s)
            })?;
            Ok(())
          },
          _ => { Ok(()) }
        }
      })
    })
  }
}

/// Returns a list of items in a specified inbound shipment, or a list of items that were updated within a specified time frame.
///
/// [Documentation](http://docs.developer.amazonservices.com/en_CA/fba_inbound/FBAInbound_ListInboundShipmentItems.html)
#[allow(non_snake_case)]
pub fn ListInboundShipmentItems(client: &Client, parameters: ListInboundShipmentItemsParameters) -> Result<Response<ListInboundShipmentItemsResponse>> {
  client.request_xml(Method::Post, PATH, VERSION, "ListInboundShipmentItems", parameters).map_err(|err| err.into())
}

/// Returns the next page of inbound shipment items using the NextToken parameter.
///
/// [Documentation](http://docs.developer.amazonservices.com/en_CA/fba_inbound/FBAInbound_ListInboundShipmentItemsByNextToken.html)
#[allow(non_snake_case)]
pub fn ListInboundShipmentItemsByNextToken(client: &Client, next_token: String) -> Result<Response<ListInboundShipmentItemsResponse>> {
  let params = vec![
    ("NextToken".to_string(), next_token)
  ];
  client.request_xml(Method::Post, PATH, VERSION, "ListInboundShipmentItemsByNextToken", params).map_err(|err| err.into())
}

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

  #[test]
  fn test_decode_list_inbound_shipments_response() {
    test_decode!(ListInboundShipmentsResponse, r#"
    <ListInboundShipmentsResponse xmlns="http://mws.amazonaws.com/FulfillmentInboundShipment/2010-10-01/">
      <ListInboundShipmentsResult>
        <ShipmentData>
          <member>
            <DestinationFulfillmentCenterId>MDW2</DestinationFulfillmentCenterId>
            <LabelPrepType>NO_LABEL</LabelPrepType>
            <ShipFromAddress>
              <City>Fort Worth</City>
              <CountryCode>US</CountryCode>
              <PostalCode>76104</PostalCode>
              <Name>RPD LTD</Name>
              <AddressLine1>428 Hemphill St</AddressLine1>
              <StateOrProvinceCode>TX</StateOrProvinceCode>
            </ShipFromAddress>
            <ShipmentId>FBA4FWJMVV</ShipmentId>
            <AreCasesRequired>true</AreCasesRequired>
            <ShipmentName>FBA (2/19/17 9:39 PM) - 1</ShipmentName>
            <BoxContentsSource>INTERACTIVE</BoxContentsSource>
            <ShipmentStatus>CLOSED</ShipmentStatus>
          </member>
        </ShipmentData>
      </ListInboundShipmentsResult>
      <ResponseMetadata>
        <RequestId>04c87e79-f747-4da9-984f-5bc1f0b875e6</RequestId>
      </ResponseMetadata>
    </ListInboundShipmentsResponse>
    "#, ListInboundShipmentsResponse {
      next_token: None,
      request_id: "04c87e79-f747-4da9-984f-5bc1f0b875e6".to_owned(),
      shipment_data: vec![
        InboundShipmentInfo {
          DestinationFulfillmentCenterId: "MDW2".to_owned(),
          LabelPrepType: Some(LabelPrepType::NO_LABEL),
          ShipFromAddress: Address {
            City: "Fort Worth".to_owned(),
            CountryCode: "US".to_owned(),
            PostalCode: "76104".to_owned(),
            Name: "RPD LTD".to_owned(),
            AddressLine1: "428 Hemphill St".to_owned(),
            AddressLine2: "".to_owned(),
            StateOrProvinceCode: "TX".to_owned(),
            DistrictOrCounty: "".to_owned(),
          },
          ShipmentId: "FBA4FWJMVV".to_owned(),
          AreCasesRequired: true,
          ShipmentName: "FBA (2/19/17 9:39 PM) - 1".to_owned(),
          BoxContentsSource: Some(BoxContentsSource::INTERACTIVE),
          ShipmentStatus: ShipmentStatus::CLOSED,
          ConfirmedNeedByDate: "".to_owned(),
          EstimatedBoxContentsFee: None,
        }
      ],
    });
  }

  #[test]
  fn test_decode_list_inbound_shipment_items_response() {
    test_decode!(ListInboundShipmentItemsResponse, r#"
    <ListInboundShipmentItemsResponse xmlns="http://mws.amazonaws.com/FulfillmentInboundShipment/2010-10-01/">
      <ListInboundShipmentItemsResult>
        <ItemData>
          <member>
            <QuantityShipped>60</QuantityShipped>
            <ShipmentId>FBA3T68MQL</ShipmentId>
            <PrepDetailsList>
              <PrepDetails/>
            </PrepDetailsList>
            <FulfillmentNetworkSKU>B016P9HJIA</FulfillmentNetworkSKU>
            <SellerSKU>edifier-r1280t-fba</SellerSKU>
            <QuantityReceived>50</QuantityReceived>
            <QuantityInCase>2</QuantityInCase>
          </member>
        </ItemData>
      </ListInboundShipmentItemsResult>
      <ResponseMetadata>
        <RequestId>70a60f01-d0df-4a29-b093-e1cb53bd8fc2</RequestId>
      </ResponseMetadata>
    </ListInboundShipmentItemsResponse>
    "#, ListInboundShipmentItemsResponse {
      next_token: None,
      request_id: "70a60f01-d0df-4a29-b093-e1cb53bd8fc2".to_owned(),
      item_data: vec![
        InboundShipmentItem {
          ShipmentId: "FBA3T68MQL".to_owned(),
          SellerSKU: "edifier-r1280t-fba".to_owned(),
          QuantityShipped: 60,
          QuantityInCase: Some(2),
          QuantityReceived: Some(50),
          FulfillmentNetworkSKU: "B016P9HJIA".to_owned(),
        }
      ],
    });
  }

}<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};
use std::iter::{Iterator, repeat};

use graph::{Edge, Graph};

pub struct AdjacencyMatrix {
    rows: Vec<Vec<u32>>,
}

impl AdjacencyMatrix {
    fn new(size: usize) -> AdjacencyMatrix {
        let row = vec![0; size];
        let rows = repeat(row).take(size).collect();

        AdjacencyMatrix { rows: rows }
    }

    pub fn from_graph(g: &Graph) -> AdjacencyMatrix {
        let mut m = AdjacencyMatrix::new(g.vertex_count);

        for &Edge { x, y } in &g.edges {
            m[x][y] = 1;
            if !g.directed {
                m[y][x] = 1;
            }
        }

        m
    }

    pub fn size(&self) -> usize {
        self.rows.len()
    }
}

// For convenience, enable writing matrix[x] instead of matrix.rows[x]).

impl Index<usize> for AdjacencyMatrix {
    type Output = Vec<u32>;

    fn index<'a>(&'a self, _index: usize) -> &'a Vec<u32> {
        &self.rows[_index]
    }
}

impl IndexMut<usize> for AdjacencyMatrix {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Vec<u32> {
        &mut self.rows[_index]
    }
}

// Breadth-first search.

impl AdjacencyMatrix {
    pub fn breadth_first_search(&self, start: usize) -> BreadthFirstSearch {
        let mut visited = vec!(false; self.size());
        visited[start] = true;

        BreadthFirstSearch {
            matrix: self,
            visited: visited,
            queue: vec![start],
            y: 0
        }
    }
}

struct BreadthFirstSearch<'a> {
    matrix: &'a AdjacencyMatrix,
    visited: Vec<bool>,
    queue: Vec<usize>,
    y: usize,
}

impl<'a> Iterator for BreadthFirstSearch<'a> {
    type Item = Edge;

    fn next(&mut self) -> Option<Edge> {
        while !self.queue.is_empty() {
            let x = self.queue[0];

            for y in self.y..self.matrix.size() {
                if self.visited[y] || self.matrix[x][y] == 0 {
                    continue;
                }
                self.visited[y] = true;
                self.queue.push(y);
                self.y = y + 1;
                return Some(Edge { x: x, y: y });
            }

            // Process the next element in the queue.
            self.queue.remove(0);
            self.y = 0;
        }

        None
    }
}

// Breadth-first search using std::iter::Unfold. Unless I missed something, it's much more
// complicated than not using Unfold.

// struct BreadthFirstSearchState<'a> {
//     matrix: &'a AdjacencyMatrix,
//     visited: Vec<bool>,
//     queue: Vec<usize>,
//     y: usize,
// }

// struct BreadthFirstSearch<'a> {
//     unfold: Unfold<BreadthFirstSearchState<'a>, fn(&mut BreadthFirstSearchState) -> Option<Edge>>,
// }

// impl<'a> Iterator for BreadthFirstSearch<'a> {
//     type Item = Edge;

//     fn next(&mut self) -> Option<Edge> {
//         self.unfold.next()
//     }
// }

// impl AdjacencyMatrix {
//     pub fn breadth_first_search(&self, start: usize) -> BreadthFirstSearch {
//         let mut visited = vec!(false; self.size());
//         visited[start] = true;

//         let state = BreadthFirstSearchState {
//             matrix: self,
//             visited: visited,
//             queue: vec![start],
//             y: 0
//         };

//         BreadthFirstSearch { unfold: Unfold::new(state, unfold_breadth_first_search) }
//     }
// }

// fn unfold_breadth_first_search(state: &mut BreadthFirstSearchState) -> Option<Edge> {
//     while !state.queue.is_empty() {
//         let x = state.queue[0];

//         for y in state.y..state.matrix.size() {
//             if state.visited[y] || state.matrix[x][y] == 0 {
//                 continue;
//             }

//             state.visited[y] = true;
//             state.queue.push(y);
//             state.y = y + 1;

//             return Some(Edge { x: x, y: y });
//         }

//         // Process the next element in the queue.
//         state.queue.remove(0);
//         state.y = 0;
//     }

//     None
// }

// Breadth-first search using a callback closure. The implementation is much simpler than the
// iterator-based BFS, however the external API is not as nice (forced to use a callback closure
// instead of a classic for loop).

// impl AdjacencyMatrix {
//     pub fn breadth_first_search<C>(&self, start: usize, mut callback: C) where C: FnMut(Edge) -> bool {
//         let mut visited = vec!(false; self.size());
//         visited[start] = true;

//         let mut queue = vec![start];

//         while queue.len() > 0 {
//             // Dequeue first element.
//             let x = queue.remove(0);

//             for y in 0..self.size() {
//                 if visited[y] || self[x][y] == 0 {
//                     continue;
//                 }
//                 visited[y] = true;
//                 queue.push(y);
//                 // The edge callback can return true to abort the current graph traversal.
//                 if callback(Edge { x: x, y: y }) {
//                     return;
//                 }
//             }
//         }
//     }
// }
<commit_msg>[edge_connectivity/rust] Wrap commented lines<commit_after>use std::ops::{Index, IndexMut};
use std::iter::{Iterator, repeat};

use graph::{Edge, Graph};

pub struct AdjacencyMatrix {
    rows: Vec<Vec<u32>>,
}

impl AdjacencyMatrix {
    fn new(size: usize) -> AdjacencyMatrix {
        let row = vec![0; size];
        let rows = repeat(row).take(size).collect();

        AdjacencyMatrix { rows: rows }
    }

    pub fn from_graph(g: &Graph) -> AdjacencyMatrix {
        let mut m = AdjacencyMatrix::new(g.vertex_count);

        for &Edge { x, y } in &g.edges {
            m[x][y] = 1;
            if !g.directed {
                m[y][x] = 1;
            }
        }

        m
    }

    pub fn size(&self) -> usize {
        self.rows.len()
    }
}

// For convenience, enable writing matrix[x] instead of matrix.rows[x]).

impl Index<usize> for AdjacencyMatrix {
    type Output = Vec<u32>;

    fn index<'a>(&'a self, _index: usize) -> &'a Vec<u32> {
        &self.rows[_index]
    }
}

impl IndexMut<usize> for AdjacencyMatrix {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Vec<u32> {
        &mut self.rows[_index]
    }
}

// Breadth-first search.

impl AdjacencyMatrix {
    pub fn breadth_first_search(&self, start: usize) -> BreadthFirstSearch {
        let mut visited = vec!(false; self.size());
        visited[start] = true;

        BreadthFirstSearch {
            matrix: self,
            visited: visited,
            queue: vec![start],
            y: 0
        }
    }
}

struct BreadthFirstSearch<'a> {
    matrix: &'a AdjacencyMatrix,
    visited: Vec<bool>,
    queue: Vec<usize>,
    y: usize,
}

impl<'a> Iterator for BreadthFirstSearch<'a> {
    type Item = Edge;

    fn next(&mut self) -> Option<Edge> {
        while !self.queue.is_empty() {
            let x = self.queue[0];

            for y in self.y..self.matrix.size() {
                if self.visited[y] || self.matrix[x][y] == 0 {
                    continue;
                }
                self.visited[y] = true;
                self.queue.push(y);
                self.y = y + 1;
                return Some(Edge { x: x, y: y });
            }

            // Process the next element in the queue.
            self.queue.remove(0);
            self.y = 0;
        }

        None
    }
}

// Breadth-first search using std::iter::Unfold. Unless I missed something, it's much more
// complicated than not using Unfold.

// struct BreadthFirstSearchState<'a> {
//     matrix: &'a AdjacencyMatrix,
//     visited: Vec<bool>,
//     queue: Vec<usize>,
//     y: usize,
// }

// struct BreadthFirstSearch<'a> {
//     unfold: Unfold<BreadthFirstSearchState<'a>,
//         fn(&mut BreadthFirstSearchState) -> Option<Edge>>,
// }

// impl<'a> Iterator for BreadthFirstSearch<'a> {
//     type Item = Edge;

//     fn next(&mut self) -> Option<Edge> {
//         self.unfold.next()
//     }
// }

// impl AdjacencyMatrix {
//     pub fn breadth_first_search(&self, start: usize) -> BreadthFirstSearch {
//         let mut visited = vec!(false; self.size());
//         visited[start] = true;

//         let state = BreadthFirstSearchState {
//             matrix: self,
//             visited: visited,
//             queue: vec![start],
//             y: 0
//         };

//         BreadthFirstSearch { unfold: Unfold::new(state, unfold_breadth_first_search) }
//     }
// }

// fn unfold_breadth_first_search(state: &mut BreadthFirstSearchState) -> Option<Edge> {
//     while !state.queue.is_empty() {
//         let x = state.queue[0];

//         for y in state.y..state.matrix.size() {
//             if state.visited[y] || state.matrix[x][y] == 0 {
//                 continue;
//             }

//             state.visited[y] = true;
//             state.queue.push(y);
//             state.y = y + 1;

//             return Some(Edge { x: x, y: y });
//         }

//         // Process the next element in the queue.
//         state.queue.remove(0);
//         state.y = 0;
//     }

//     None
// }

// Breadth-first search using a callback closure. The implementation is much simpler than the
// iterator-based BFS, however the external API is not as nice (forced to use a callback closure
// instead of a classic for loop).

// impl AdjacencyMatrix {
//     pub fn breadth_first_search<C>(&self, start: usize, mut callback: C)
//        where C: FnMut(Edge) -> bool {

//         let mut visited = vec!(false; self.size());
//         visited[start] = true;

//         let mut queue = vec![start];

//         while queue.len() > 0 {
//             // Dequeue first element.
//             let x = queue.remove(0);

//             for y in 0..self.size() {
//                 if visited[y] || self[x][y] == 0 {
//                     continue;
//                 }
//                 visited[y] = true;
//                 queue.push(y);
//                 // The edge callback can return true to abort the current graph traversal.
//                 if callback(Edge { x: x, y: y }) {
//                     return;
//                 }
//             }
//         }
//     }
// }
<|endoftext|>


<commit_before>use ra_syntax::{
    ast::{self, NameOwner, VisibilityOwner, TypeAscriptionOwner, AstNode},
};

pub(crate) trait Description {
    fn description(&self) -> Option<String>;
}

impl Description for ast::FnDef {
    fn description(&self) -> Option<String> {
        Some(crate::display::function_label(self))
    }
}

impl Description for ast::StructDef {
    fn description(&self) -> Option<String> {
        visit_node(self, "struct ")
    }
}

impl Description for ast::EnumDef {
    fn description(&self) -> Option<String> {
        visit_node(self, "enum ")
    }
}

impl Description for ast::TraitDef {
    fn description(&self) -> Option<String> {
        visit_node(self, "trait ")
    }
}

impl Description for ast::Module {
    fn description(&self) -> Option<String> {
        visit_node(self, "mod ")
    }
}

impl Description for ast::TypeAliasDef {
    fn description(&self) -> Option<String> {
        visit_node(self, "type ")
    }
}

impl Description for ast::ConstDef {
    fn description(&self) -> Option<String> {
        visit_ascribed_node(self, "const ")
    }
}

impl Description for ast::StaticDef {
    fn description(&self) -> Option<String> {
        visit_ascribed_node(self, "static ")
    }
}

impl Description for ast::NamedFieldDef {
    fn description(&self) -> Option<String> {
        visit_ascribed_node(self, "")
    }
}

impl Description for ast::EnumVariant {
    fn description(&self) -> Option<String> {
        Some(self.name()?.text().to_string())
    }
}

fn visit_ascribed_node<T>(node: &T, prefix: &str) -> Option<String>
where
    T: NameOwner + VisibilityOwner + TypeAscriptionOwner,
{
    let mut string = visit_node(node, prefix)?;

    if let Some(type_ref) = node.ascribed_type() {
        string.push_str(": ");
        type_ref.syntax().text().push_to(&mut string);
    }

    Some(string)
}

fn visit_node<T>(node: &T, label: &str) -> Option<String>
where
    T: NameOwner + VisibilityOwner,
{
    let mut string =
        node.visibility().map(|v| format!("{} ", v.syntax().text())).unwrap_or_default();
    string.push_str(label);
    string.push_str(node.name()?.text().as_str());
    Some(string)
}
<commit_msg>Rename description funcs<commit_after>use ra_syntax::{
    ast::{self, NameOwner, VisibilityOwner, TypeAscriptionOwner, AstNode},
};

pub(crate) trait Description {
    fn description(&self) -> Option<String>;
}

impl Description for ast::FnDef {
    fn description(&self) -> Option<String> {
        Some(crate::display::function_label(self))
    }
}

impl Description for ast::StructDef {
    fn description(&self) -> Option<String> {
        description_from_node(self, "struct ")
    }
}

impl Description for ast::EnumDef {
    fn description(&self) -> Option<String> {
        description_from_node(self, "enum ")
    }
}

impl Description for ast::TraitDef {
    fn description(&self) -> Option<String> {
        description_from_node(self, "trait ")
    }
}

impl Description for ast::Module {
    fn description(&self) -> Option<String> {
        description_from_node(self, "mod ")
    }
}

impl Description for ast::TypeAliasDef {
    fn description(&self) -> Option<String> {
        description_from_node(self, "type ")
    }
}

impl Description for ast::ConstDef {
    fn description(&self) -> Option<String> {
        description_from_ascribed_node(self, "const ")
    }
}

impl Description for ast::StaticDef {
    fn description(&self) -> Option<String> {
        description_from_ascribed_node(self, "static ")
    }
}

impl Description for ast::NamedFieldDef {
    fn description(&self) -> Option<String> {
        description_from_ascribed_node(self, "")
    }
}

impl Description for ast::EnumVariant {
    fn description(&self) -> Option<String> {
        Some(self.name()?.text().to_string())
    }
}

fn description_from_ascribed_node<T>(node: &T, prefix: &str) -> Option<String>
where
    T: NameOwner + VisibilityOwner + TypeAscriptionOwner,
{
    let mut string = description_from_node(node, prefix)?;

    if let Some(type_ref) = node.ascribed_type() {
        string.push_str(": ");
        type_ref.syntax().text().push_to(&mut string);
    }

    Some(string)
}

fn description_from_node<T>(node: &T, label: &str) -> Option<String>
where
    T: NameOwner + VisibilityOwner,
{
    let mut string =
        node.visibility().map(|v| format!("{} ", v.syntax().text())).unwrap_or_default();
    string.push_str(label);
    string.push_str(node.name()?.text().as_str());
    Some(string)
}
<|endoftext|>


<commit_before>use super::*;

#[test]
#[cfg(target_os = "linux")]
fn execute_valid() {
    execute(&vec!["fn main() {println!(\"test\");}".to_string()]);
}

#[test]
#[should_panic]
fn execute_not_compile() {
    execute(&vec!["fn main() {donotcompile();}".to_string()]);
}

#[test]
#[should_panic]
fn execute_runtime_panic() {
    execute(&vec!["fn main() {panic!(\"error\");}".to_string()]);
}
<commit_msg>test rs scripts only on linux<commit_after>use super::*;

#[test]
#[cfg(target_os = "linux")]
fn execute_valid() {
    execute(&vec!["fn main() {println!(\"test\");}".to_string()]);
}

#[test]
#[cfg(target_os = "linux")]
#[should_panic]
fn execute_not_compile() {
    execute(&vec!["fn main() {donotcompile();}".to_string()]);
}

#[test]
#[cfg(target_os = "linux")]
#[should_panic]
fn execute_runtime_panic() {
    execute(&vec!["fn main() {panic!(\"error\");}".to_string()]);
}
<|endoftext|>