<commit_before>//! Geometry object

use serde::de::{Deserialize, Deserializer, Error, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor};
use std::fmt;

/// The Geometry object specified in [The GeoJSON Format (RFC7946)](https://tools.ietf.org/html/rfc7946).
// https://tools.ietf.org/html/rfc7946#section-3.1
#[derive(Clone, Debug, PartialEq)]
pub enum Geometry {
    Point(Position),
    MultiPoint(Vec<Position>),
    LineString(LineString),
    MultiLineString(Vec<LineString>),
    Polygon(Polygon),
    MultiPolygon(Vec<Polygon>),
    // GeometryCollection(Vec<Geometry>),
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Position(
    /// Longitude
    pub f64,
    /// Latitude
    pub f64,
    // Twitter API does not provide altitudes
);

pub type LineString = Vec<Position>;
pub type Polygon = Vec<LinearRing>;
pub type LinearRing = LineString;

impl<'x> Deserialize<'x> for Geometry {
    fn deserialize<D: Deserializer<'x>>(d: D) -> Result<Self, D::Error> {
        struct GeometryVisitor;

        impl<'x> Visitor<'x> for GeometryVisitor {
            type Value = Geometry;

            fn visit_map<V: MapAccess<'x>>(self, mut v: V) -> Result<Geometry, V::Error> {
                enum Coordinates {
                    F64(f64),
                    Dim0(Position), // Point
                    Dim1(Vec<Position>), // MultiPoint, LineString
                    Dim2(Vec<Vec<Position>>), // MultiLineString, Polygon
                    Dim3(Vec<Vec<Vec<Position>>>), // MultiPolygon
                }

                impl<'x> Deserialize<'x> for Coordinates {
                    fn deserialize<D: Deserializer<'x>>(d: D) -> Result<Self, D::Error> {
                        struct CoordinatesVisitor;

                        impl<'x> Visitor<'x> for CoordinatesVisitor {
                            type Value = Coordinates;

                            fn visit_f64<E>(self, v: f64) -> Result<Coordinates, E> {
                                Ok(Coordinates::F64(v))
                            }

                            fn visit_i64<E>(self, v: i64) -> Result<Coordinates, E> {
                                Ok(Coordinates::F64(v as _))
                            }

                            fn visit_u64<E>(self, v: u64) -> Result<Coordinates, E> {
                                Ok(Coordinates::F64(v as _))
                            }

                            fn visit_seq<V: SeqAccess<'x>>(self, mut v: V) -> Result<Coordinates, V::Error> {
                                macro_rules! match_val {
                                    (
                                        $C:ident,
                                        $($V:ident => $R:ident,)*
                                    ) => {
                                        match v.next_element()? {
                                            Some($C::F64(v1)) => {
                                                let v2 = match v.next_element()? {
                                                    Some(val) => val,
                                                    None => return Err(V::Error::invalid_length(1, &self)),
                                                };
                                                while v.next_element::<IgnoredAny>()?.is_some() {}
                                                Ok($C::Dim0(Position(v1, v2)))
                                            },
                                            $(Some($C::$V(val)) => {
                                                let mut ret = v.size_hint().map_or_else(Vec::new, Vec::with_capacity);
                                                ret.push(val);
                                                while let Some(val) = v.next_element()? {
                                                    ret.push(val);
                                                }
                                                Ok($C::$R(ret))
                                            },)*
                                            Some($C::Dim3(_)) => Err(V::Error::invalid_type(Unexpected::Seq, &self)),
                                            None => Ok($C::Dim1(Vec::new())),
                                        }
                                    };
                                }

                                match_val! {
                                    Coordinates,
                                    Dim0 => Dim1,
                                    Dim1 => Dim2,
                                    Dim2 => Dim3,
                                }
                            }

                            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                                write!(f,
                                    "a floating point number \
                                    or an array of floating point number with a depth of 4 or lower"
                                )
                            }
                        }

                        d.deserialize_any(CoordinatesVisitor)
                    }
                }

                let mut c = None;

                use self::Geometry::*;

                macro_rules! end {
                    () => {{
                        while v.next_entry::<IgnoredAny, IgnoredAny>()?.is_some() {}
                    }};
                }

                while let Some(k) = v.next_key::<String>()? {
                    match k.as_str() {
                        "type" => {
                            let t = v.next_value::<String>()?;
                            macro_rules! match_type {
                                ($C:ident, $($($V:ident($typ:expr))|* => $D:ident,)*) => {{
                                    const EXPECTED: &'static [&'static str] = &[$($($typ),*),*];
                                    match t.as_str() {
                                        $($($typ => match c {
                                            Some($C::$D(val)) => {
                                                end!();
                                                return Ok($V(val));
                                            },
                                            None => {
                                                while let Some(k) = v.next_key::<String>()? {
                                                    if "coordinates" == k.as_str() {
                                                        end!();
                                                        return Ok($V(v.next_value()?));
                                                    } else {
                                                        v.next_value::<IgnoredAny>()?;
                                                    }
                                                }
                                                return Err(V::Error::missing_field("coordinates"));
                                            },
                                            _ => return Err(V::Error::custom("invalid coordinates type")),
                                        },)*)*
                                        s => return Err(V::Error::unknown_variant(&s, EXPECTED)),
                                    }
                                }};
                            }
                            match_type! {
                                Coordinates,
                                Point("Point") => Dim0,
                                MultiPoint("MultiPoint") | LineString("LineString") => Dim1,
                                MultiLineString("MultiLineString") | Polygon("Polygon") => Dim2,
                                MultiPolygon("MultiPolygon") => Dim3,
                            }
                        },
                        "coordinates" => c = Some(v.next_value()?),
                        _ => { v.next_value::<IgnoredAny>()?; },
                    }
                }

                Err(V::Error::missing_field("type"))
            }

            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "a map with `type` and `coordinate` fields")
            }
        }

        d.deserialize_map(GeometryVisitor)
    }
}

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

    #[test]
    fn deserialize() {
        assert_eq!(
            Geometry::Point(Position(-75.14310264, 40.05701649)),
            json::from_str("{\"coordinates\":[-75.14310264,40.05701649],\"type\":\"Point\"}").unwrap()
        );
        assert_eq!(
            Geometry::Polygon(vec![vec![Position(2.2241006,48.8155414), Position(2.4699099,48.8155414),
                Position(2.4699099,48.9021461), Position(2.2241006,48.9021461)]]),
            json::from_str("{\"coordinates\":[
                [[2.2241006,48.8155414],[2.4699099,48.8155414],[2.4699099,48.9021461],[2.2241006,48.9021461]]
                ],\"type\":\"Polygon\"}").unwrap()
        );
    }
}
<commit_msg>twitter-stream-message: Fix a possible deserialization error<commit_after>//! Geometry object

use serde::de::{Deserialize, Deserializer, Error, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor};
use std::fmt;

/// The Geometry object specified in [The GeoJSON Format (RFC7946)](https://tools.ietf.org/html/rfc7946).
// https://tools.ietf.org/html/rfc7946#section-3.1
#[derive(Clone, Debug, PartialEq)]
pub enum Geometry {
    Point(Position),
    MultiPoint(Vec<Position>),
    LineString(LineString),
    MultiLineString(Vec<LineString>),
    Polygon(Polygon),
    MultiPolygon(Vec<Polygon>),
    // GeometryCollection(Vec<Geometry>),
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Position(
    /// Longitude
    pub f64,
    /// Latitude
    pub f64,
    // Twitter API does not provide altitudes
);

pub type LineString = Vec<Position>;
pub type Polygon = Vec<LinearRing>;
pub type LinearRing = LineString;

impl<'x> Deserialize<'x> for Geometry {
    fn deserialize<D: Deserializer<'x>>(d: D) -> Result<Self, D::Error> {
        struct GeometryVisitor;

        impl<'x> Visitor<'x> for GeometryVisitor {
            type Value = Geometry;

            fn visit_map<V: MapAccess<'x>>(self, mut v: V) -> Result<Geometry, V::Error> {
                enum Coordinates {
                    F64(f64),
                    Dim0(Position), // Point
                    Dim1(Vec<Position>), // MultiPoint, LineString
                    Dim2(Vec<Vec<Position>>), // MultiLineString, Polygon
                    Dim3(Vec<Vec<Vec<Position>>>), // MultiPolygon
                }

                impl<'x> Deserialize<'x> for Coordinates {
                    fn deserialize<D: Deserializer<'x>>(d: D) -> Result<Self, D::Error> {
                        struct CoordinatesVisitor;

                        impl<'x> Visitor<'x> for CoordinatesVisitor {
                            type Value = Coordinates;

                            fn visit_f64<E>(self, v: f64) -> Result<Coordinates, E> {
                                Ok(Coordinates::F64(v))
                            }

                            fn visit_i64<E>(self, v: i64) -> Result<Coordinates, E> {
                                Ok(Coordinates::F64(v as _))
                            }

                            fn visit_u64<E>(self, v: u64) -> Result<Coordinates, E> {
                                Ok(Coordinates::F64(v as _))
                            }

                            fn visit_seq<V: SeqAccess<'x>>(self, mut v: V) -> Result<Coordinates, V::Error> {
                                macro_rules! match_val {
                                    (
                                        $C:ident,
                                        $($V:ident => $R:ident,)*
                                    ) => {
                                        match v.next_element()? {
                                            Some($C::F64(v1)) => {
                                                let v2 = match v.next_element()? {
                                                    Some(val) => val,
                                                    None => return Err(V::Error::invalid_length(1, &self)),
                                                };
                                                while v.next_element::<IgnoredAny>()?.is_some() {}
                                                Ok($C::Dim0(Position(v1, v2)))
                                            },
                                            $(Some($C::$V(val)) => {
                                                let mut ret = v.size_hint().map_or_else(Vec::new, Vec::with_capacity);
                                                ret.push(val);
                                                while let Some(val) = v.next_element()? {
                                                    ret.push(val);
                                                }
                                                Ok($C::$R(ret))
                                            },)*
                                            Some($C::Dim3(_)) => Err(V::Error::invalid_type(Unexpected::Seq, &self)),
                                            None => Ok($C::Dim1(Vec::new())),
                                        }
                                    };
                                }

                                match_val! {
                                    Coordinates,
                                    Dim0 => Dim1,
                                    Dim1 => Dim2,
                                    Dim2 => Dim3,
                                }
                            }

                            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                                write!(f,
                                    "a floating point number \
                                    or an array of floating point number with a depth of 4 or lower"
                                )
                            }
                        }

                        d.deserialize_any(CoordinatesVisitor)
                    }
                }

                let mut c = None;

                use self::Geometry::*;

                macro_rules! end {
                    () => {{
                        while v.next_entry::<IgnoredAny, IgnoredAny>()?.is_some() {}
                    }};
                }

                while let Some(k) = v.next_key::<String>()? {
                    match k.as_str() {
                        "type" => {
                            let t = v.next_value::<String>()?;
                            macro_rules! match_type {
                                ($C:ident, $($($V:ident($typ:expr))|* => $D:ident,)*) => {{
                                    const EXPECTED: &'static [&'static str] = &[$($($typ),*),*];
                                    match t.as_str() {
                                        $($($typ => match c {
                                            Some($C::$D(val)) => {
                                                end!();
                                                return Ok($V(val));
                                            },
                                            None => {
                                                while let Some(k) = v.next_key::<String>()? {
                                                    if "coordinates" == k.as_str() {
                                                        let c = v.next_value()?;
                                                        end!();
                                                        return Ok($V(c));
                                                    } else {
                                                        v.next_value::<IgnoredAny>()?;
                                                    }
                                                }
                                                return Err(V::Error::missing_field("coordinates"));
                                            },
                                            _ => return Err(V::Error::custom("invalid coordinates type")),
                                        },)*)*
                                        s => return Err(V::Error::unknown_variant(&s, EXPECTED)),
                                    }
                                }};
                            }
                            match_type! {
                                Coordinates,
                                Point("Point") => Dim0,
                                MultiPoint("MultiPoint") | LineString("LineString") => Dim1,
                                MultiLineString("MultiLineString") | Polygon("Polygon") => Dim2,
                                MultiPolygon("MultiPolygon") => Dim3,
                            }
                        },
                        "coordinates" => c = Some(v.next_value()?),
                        _ => { v.next_value::<IgnoredAny>()?; },
                    }
                }

                Err(V::Error::missing_field("type"))
            }

            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "a map with `type` and `coordinate` fields")
            }
        }

        d.deserialize_map(GeometryVisitor)
    }
}

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

    #[test]
    fn deserialize() {
        let geo = Geometry::Point(Position(-75.14310264, 40.05701649));
        let c = "\"coordinates\":[-75.14310264,40.05701649]";
        let t = "\"type\":\"Point\"";
        assert_eq!(geo, json::from_str(&format!("{{{},{}}}", c, t)).unwrap());
        assert_eq!(geo, json::from_str(&format!("{{{},{}}}", t, c)).unwrap());

        let geo = Geometry::Polygon(vec![vec![Position(2.2241006,48.8155414), Position(2.4699099,48.8155414),
            Position(2.4699099,48.9021461), Position(2.2241006,48.9021461)]]);
        let c = "\"coordinates\":[\
            [[2.2241006,48.8155414],[2.4699099,48.8155414],[2.4699099,48.9021461],[2.2241006,48.9021461]]]";
        let t = "\"type\":\"Polygon\"";
        assert_eq!(geo, json::from_str(&format!("{{{},{}}}", c, t)).unwrap());
        assert_eq!(geo, json::from_str(&format!("{{{},{}}}", t, c)).unwrap());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::collections::HashSet;

use enums;
use parse;

pub fn write_descriptor_sets(doc: &parse::Spirv) -> String {
    // TODO: not implemented

    // finding all the descriptors
    let mut descriptors = Vec::new();
    struct Descriptor {
        name: String,
        desc_ty: String,
        bind_ty: String,
        bind_template_params: Vec<String>,
        bind_where_clauses: String,
        bind: String,
        set: u32,
        binding: u32,
    }

    // template parameter names that are available for the purpose of the code below
    // TODO: better system
    let mut template_params = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"].into_iter();

    // looping to find all the elements that have the `DescriptorSet` decoration
    for instruction in doc.instructions.iter() {
        let (variable_id, descriptor_set) = match instruction {
            &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationDescriptorSet, ref params } => {
                (target_id, params[0])
            },
            _ => continue
        };

        // find which type is pointed to by this variable
        let pointed_ty = pointer_variable_ty(doc, variable_id);
        // name of the variable
        let name = ::name_from_id(doc, variable_id);

        // find the binding point of this descriptor
        let binding = doc.instructions.iter().filter_map(|i| {
            match i {
                &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationBinding, ref params } if target_id == variable_id => {
                    Some(params[0])
                },
                _ => None,      // TODO: other types
            }
        }).next().expect(&format!("Uniform `{}` is missing a binding", name));

        // find informations about the kind of binding for this descriptor
        let (desc_ty, bind_template_params, bind_where_clauses, bind_ty, bind) = doc.instructions.iter().filter_map(|i| {
            match i {
                &parse::Instruction::TypeStruct { result_id, .. } if result_id == pointed_ty => {
                    let tp_buffer = template_params.next().unwrap();

                    Some((
                        "::vulkano::descriptor_set::DescriptorType::UniformBuffer",
                        vec![tp_buffer.to_owned()],
                        format!("{}: 'static + ::vulkano::buffer::TypedBuffer", tp_buffer),
                        format!("&'a ::std::sync::Arc<{}>", tp_buffer),
                        "::vulkano::descriptor_set::DescriptorBind::uniform_buffer(data)"
                    ))
                },
                &parse::Instruction::TypeImage { result_id, sampled_type_id, ref dim, arrayed, ms,
                                                 sampled, ref format, ref access, .. }
                                        if result_id == pointed_ty && sampled == Some(true) =>
                {
                    let img = template_params.next().unwrap();

                    Some((
                        "::vulkano::descriptor_set::DescriptorType::SampledImage",
                        vec![img.to_owned()],
                        format!("{}: 'static + ::vulkano::image::ImageView", img),
                        format!("&'a ::std::sync::Arc<{}>", img),
                        "::vulkano::descriptor_set::DescriptorBind::sampled_image(data)"
                    ))
                },
                &parse::Instruction::TypeImage { result_id, sampled_type_id, ref dim, arrayed, ms,
                                                 sampled, ref format, ref access, .. }
                                        if result_id == pointed_ty && sampled == Some(false) =>
                {
                    let img = template_params.next().unwrap();

                    Some((
                        "::vulkano::descriptor_set::DescriptorType::InputAttachment",       // FIXME: can be `StorageImage`
                        vec![img.to_owned()],
                        format!("{}: 'static + ::vulkano::image::ImageView", img),
                        format!("&'a ::std::sync::Arc<{}>", img),
                        "::vulkano::descriptor_set::DescriptorBind::input_attachment(data)"
                    ))
                },
                &parse::Instruction::TypeSampledImage { result_id, image_type_id }
                                                                    if result_id == pointed_ty =>
                {
                    let img = template_params.next().unwrap();

                    Some((
                        "::vulkano::descriptor_set::DescriptorType::CombinedImageSampler",
                        vec![img.to_owned()],
                        format!("{}: 'static + ::vulkano::image::ImageView", img),
                        format!("(&'a ::std::sync::Arc<::vulkano::sampler::Sampler>, &'a ::std::sync::Arc<{}>)", img),
                        "::vulkano::descriptor_set::DescriptorBind::combined_image_sampler(data.0, data.1)"
                    ))
                },
                _ => None,      // TODO: other types
            }
        }).next().expect(&format!("Couldn't find relevant type for uniform `{}` (type {}, maybe unimplemented)", name, pointed_ty));

        descriptors.push(Descriptor {
            name: name,
            desc_ty: desc_ty.to_owned(),
            bind_ty: bind_ty,
            bind_template_params: bind_template_params,
            bind_where_clauses: bind_where_clauses,
            bind: bind.to_owned(),
            set: descriptor_set,
            binding: binding,
        });
    }

    let sets_list = descriptors.iter().map(|d| d.set).collect::<HashSet<u32>>();

    let mut output = String::new();

    // iterate once per set that is defined somewhere
    for set in sets_list.iter() {
        let write_ty = descriptors.iter().filter(|d| d.set == *set)
                                  .map(|d| d.bind_ty.clone())
                                  .collect::<Vec<_>>();

        let write_tp = {
            let v = descriptors.iter().filter(|d| d.set == *set)
                               .map(|d| d.bind_template_params.join(", "))
                               .collect::<Vec<_>>().join(", ");
            if v.is_empty() { v } else { ", ".to_owned() + &v }
        };

        let write_where = {
            let v = descriptors.iter().filter(|d| d.set == *set)
                               .map(|d| d.bind_where_clauses.clone())
                               .collect::<Vec<_>>().join(", ");
            if v.is_empty() { v } else { "where ".to_owned() + &v }
        };

        let writes = descriptors.iter().enumerate().filter(|&(_, d)| d.set == *set)
                                .map(|(entry, d)| {
                                    let entry = if write_ty.len() == 1 {
                                        "".to_owned()
                                    } else {
                                        format!(".{}", entry)
                                    };

                                    format!("{{ let data = data{entry};
                                            ::vulkano::descriptor_set::DescriptorWrite {{
                                                 binding: {binding},
                                                 array_element: 0,
                                                 content: {bind},
                                             }} }}", binding = d.binding, bind = d.bind,
                                                     entry = entry)
                                })
                                .collect::<Vec<_>>();

        let write_ty = if write_ty.len() == 1 {
            write_ty.into_iter().next().unwrap()
        } else {
            format!("({})", write_ty.join(", "))
        };

        let descr = descriptors.iter().enumerate().filter(|&(_, d)| d.set == *set)
                               .map(|(entry, d)| {
                                   format!("::vulkano::descriptor_set::DescriptorDesc {{
                                                binding: {binding},
                                                ty: {desc_ty},
                                                array_count: 1,
                                                stages: ::vulkano::descriptor_set::ShaderStages::all(),        // TODO:
                                            }}", binding = d.binding, desc_ty = d.desc_ty)
                               })
                               .collect::<Vec<_>>();

        output.push_str(&format!(r#"
#[derive(Default)]
pub struct Set{set};

unsafe impl ::vulkano::descriptor_set::SetLayout for Set{set} {{
    fn descriptors(&self) -> Vec<::vulkano::descriptor_set::DescriptorDesc> {{
        vec![
            {descr}
        ]
    }}
}}

unsafe impl<'a {write_tp}> ::vulkano::descriptor_set::SetLayoutWrite<{write_ty}> for Set{set}
    {write_where}
{{
    fn decode(&self, data: {write_ty}) -> Vec<::vulkano::descriptor_set::DescriptorWrite> {{
        vec![
            {writes}
        ]
    }}
}}

unsafe impl<'a {write_tp}> ::vulkano::descriptor_set::SetLayoutInit<{write_ty}> for Set{set}
    {write_where}
{{
    fn decode(&self, data: {write_ty}) -> Vec<::vulkano::descriptor_set::DescriptorWrite> {{
        ::vulkano::descriptor_set::SetLayoutWrite::decode(self, data)
    }}
}}

"#, set = set, write_ty = write_ty, writes = writes.join(","), write_tp = write_tp,
    write_where = write_where, descr = descr.join(",")));
    }

    let max_set = sets_list.iter().cloned().max().map(|v| v + 1).unwrap_or(0);

    let sets_defs = (0 .. max_set).map(|num| {
        if sets_list.contains(&num) {
            format!("::std::sync::Arc<::vulkano::descriptor_set::DescriptorSet<Set{}>>", num)
        } else {
            "()".to_owned()
        }
    }).collect::<Vec<_>>();

    let sets = (0 .. max_set).map(|num| {
        if sets_list.contains(&num) {
            if sets_defs.len() == 1 {
                format!("sets")
            } else {
                format!("sets.{}", num)
            }
        } else {
            "()".to_owned()     // FIXME: wrong
        }
    }).collect::<Vec<_>>();

    let layouts_defs = (0 .. max_set).map(|num| {
        if sets_list.contains(&num) {
            format!("::std::sync::Arc<::vulkano::descriptor_set::DescriptorSetLayout<Set{}>>", num)
        } else {
            "()".to_owned()
        }
    }).collect::<Vec<_>>();

    let layouts = (0 .. max_set).map(|num| {
        if sets_list.contains(&num) {
            if layouts_defs.len() == 1 {
                format!("layouts")
            } else {
                format!("layouts.{}", num)
            }
        } else {
            "()".to_owned()     // FIXME: wrong
        }
    }).collect::<Vec<_>>();

    output.push_str(&format!(r#"
#[derive(Default)]
pub struct Layout;

unsafe impl ::vulkano::descriptor_set::Layout for Layout {{
    type DescriptorSets = ({sets_defs});
    type DescriptorSetLayouts = ({layouts_defs});
    type PushConstants = ();

    fn decode_descriptor_set_layouts(&self, layouts: Self::DescriptorSetLayouts)
        -> Vec<::std::sync::Arc<::vulkano::descriptor_set::AbstractDescriptorSetLayout>>
    {{
        vec![
            {layouts}
        ]
    }}

    fn decode_descriptor_sets(&self, sets: Self::DescriptorSets)
        -> Vec<::std::sync::Arc<::vulkano::descriptor_set::AbstractDescriptorSet>>
    {{
        vec![
            {sets}
        ]
    }}
}}
"#, sets_defs = sets_defs.join(","), layouts_defs = layouts_defs.join(","),
    layouts = layouts.join(","), sets = sets.join(",")));

    output
}

/// Assumes that `variable` is a variable with a `TypePointer` and returns the id of the pointed
/// type.
fn pointer_variable_ty(doc: &parse::Spirv, variable: u32) -> u32 {
    let var_ty = doc.instructions.iter().filter_map(|i| {
        match i {
            &parse::Instruction::Variable { result_type_id, result_id, .. } if result_id == variable => {
                Some(result_type_id)
            },
            _ => None
        }
    }).next().unwrap();

    doc.instructions.iter().filter_map(|i| {
        match i {
            &parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == var_ty => {
                Some(type_id)
            },
            _ => None
        }
    }).next().unwrap()
}
<commit_msg>Add support for SSBOs in shader analyzer<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::collections::HashSet;

use enums;
use parse;

pub fn write_descriptor_sets(doc: &parse::Spirv) -> String {
    // TODO: not implemented

    // finding all the descriptors
    let mut descriptors = Vec::new();
    struct Descriptor {
        name: String,
        desc_ty: String,
        bind_ty: String,
        bind_template_params: Vec<String>,
        bind_where_clauses: String,
        bind: String,
        set: u32,
        binding: u32,
    }

    // template parameter names that are available for the purpose of the code below
    // TODO: better system
    let mut template_params = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"].into_iter();

    // looping to find all the elements that have the `DescriptorSet` decoration
    for instruction in doc.instructions.iter() {
        let (variable_id, descriptor_set) = match instruction {
            &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationDescriptorSet, ref params } => {
                (target_id, params[0])
            },
            _ => continue
        };

        // find which type is pointed to by this variable
        let pointed_ty = pointer_variable_ty(doc, variable_id);
        // name of the variable
        let name = ::name_from_id(doc, variable_id);

        // find the binding point of this descriptor
        let binding = doc.instructions.iter().filter_map(|i| {
            match i {
                &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationBinding, ref params } if target_id == variable_id => {
                    Some(params[0])
                },
                _ => None,      // TODO: other types
            }
        }).next().expect(&format!("Uniform `{}` is missing a binding", name));

        // find informations about the kind of binding for this descriptor
        let (desc_ty, bind_template_params, bind_where_clauses, bind_ty, bind) = doc.instructions.iter().filter_map(|i| {
            match i {
                &parse::Instruction::TypeStruct { result_id, .. } if result_id == pointed_ty => {
                    let tp_buffer = template_params.next().unwrap();

                    // Determine whether there's a Block or BufferBlock decoration.
                    let is_ssbo = doc.instructions.iter().filter_map(|i| {
                        match i {
                            &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationBufferBlock, .. } if target_id == pointed_ty => {
                                Some(true)
                            },
                            &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationBlock, .. } if target_id == pointed_ty => {
                                Some(false)
                            },
                            _ => None,
                        }
                    }).next().expect("Found a buffer uniform with neither the Block nor BufferBlock decorations");

                    Some((
                        if !is_ssbo {
                            "::vulkano::descriptor_set::DescriptorType::UniformBuffer"
                        } else {
                            "::vulkano::descriptor_set::DescriptorType::StorageBuffer"
                        },
                        vec![tp_buffer.to_owned()],
                        format!("{}: 'static + ::vulkano::buffer::TypedBuffer", tp_buffer),
                        format!("&'a ::std::sync::Arc<{}>", tp_buffer),
                        if !is_ssbo {
                            "::vulkano::descriptor_set::DescriptorBind::uniform_buffer(data)"
                        } else {
                            "::vulkano::descriptor_set::DescriptorBind::storage_buffer(data)"
                        }
                    ))
                },
                &parse::Instruction::TypeImage { result_id, sampled_type_id, ref dim, arrayed, ms,
                                                 sampled, ref format, ref access, .. }
                                        if result_id == pointed_ty && sampled == Some(true) =>
                {
                    let img = template_params.next().unwrap();

                    Some((
                        "::vulkano::descriptor_set::DescriptorType::SampledImage",
                        vec![img.to_owned()],
                        format!("{}: 'static + ::vulkano::image::ImageView", img),
                        format!("&'a ::std::sync::Arc<{}>", img),
                        "::vulkano::descriptor_set::DescriptorBind::sampled_image(data)"
                    ))
                },
                &parse::Instruction::TypeImage { result_id, sampled_type_id, ref dim, arrayed, ms,
                                                 sampled, ref format, ref access, .. }
                                        if result_id == pointed_ty && sampled == Some(false) =>
                {
                    let img = template_params.next().unwrap();

                    Some((
                        "::vulkano::descriptor_set::DescriptorType::InputAttachment",       // FIXME: can be `StorageImage`
                        vec![img.to_owned()],
                        format!("{}: 'static + ::vulkano::image::ImageView", img),
                        format!("&'a ::std::sync::Arc<{}>", img),
                        "::vulkano::descriptor_set::DescriptorBind::input_attachment(data)"
                    ))
                },
                &parse::Instruction::TypeSampledImage { result_id, image_type_id }
                                                                    if result_id == pointed_ty =>
                {
                    let img = template_params.next().unwrap();

                    Some((
                        "::vulkano::descriptor_set::DescriptorType::CombinedImageSampler",
                        vec![img.to_owned()],
                        format!("{}: 'static + ::vulkano::image::ImageView", img),
                        format!("(&'a ::std::sync::Arc<::vulkano::sampler::Sampler>, &'a ::std::sync::Arc<{}>)", img),
                        "::vulkano::descriptor_set::DescriptorBind::combined_image_sampler(data.0, data.1)"
                    ))
                },
                _ => None,      // TODO: other types
            }
        }).next().expect(&format!("Couldn't find relevant type for uniform `{}` (type {}, maybe unimplemented)", name, pointed_ty));

        descriptors.push(Descriptor {
            name: name,
            desc_ty: desc_ty.to_owned(),
            bind_ty: bind_ty,
            bind_template_params: bind_template_params,
            bind_where_clauses: bind_where_clauses,
            bind: bind.to_owned(),
            set: descriptor_set,
            binding: binding,
        });
    }

    let sets_list = descriptors.iter().map(|d| d.set).collect::<HashSet<u32>>();

    let mut output = String::new();

    // iterate once per set that is defined somewhere
    for set in sets_list.iter() {
        let write_ty = descriptors.iter().filter(|d| d.set == *set)
                                  .map(|d| d.bind_ty.clone())
                                  .collect::<Vec<_>>();

        let write_tp = {
            let v = descriptors.iter().filter(|d| d.set == *set)
                               .map(|d| d.bind_template_params.join(", "))
                               .collect::<Vec<_>>().join(", ");
            if v.is_empty() { v } else { ", ".to_owned() + &v }
        };

        let write_where = {
            let v = descriptors.iter().filter(|d| d.set == *set)
                               .map(|d| d.bind_where_clauses.clone())
                               .collect::<Vec<_>>().join(", ");
            if v.is_empty() { v } else { "where ".to_owned() + &v }
        };

        let writes = descriptors.iter().enumerate().filter(|&(_, d)| d.set == *set)
                                .map(|(entry, d)| {
                                    let entry = if write_ty.len() == 1 {
                                        "".to_owned()
                                    } else {
                                        format!(".{}", entry)
                                    };

                                    format!("{{ let data = data{entry};
                                            ::vulkano::descriptor_set::DescriptorWrite {{
                                                 binding: {binding},
                                                 array_element: 0,
                                                 content: {bind},
                                             }} }}", binding = d.binding, bind = d.bind,
                                                     entry = entry)
                                })
                                .collect::<Vec<_>>();

        let write_ty = if write_ty.len() == 1 {
            write_ty.into_iter().next().unwrap()
        } else {
            format!("({})", write_ty.join(", "))
        };

        let descr = descriptors.iter().enumerate().filter(|&(_, d)| d.set == *set)
                               .map(|(entry, d)| {
                                   format!("::vulkano::descriptor_set::DescriptorDesc {{
                                                binding: {binding},
                                                ty: {desc_ty},
                                                array_count: 1,
                                                stages: ::vulkano::descriptor_set::ShaderStages::all(),        // TODO:
                                            }}", binding = d.binding, desc_ty = d.desc_ty)
                               })
                               .collect::<Vec<_>>();

        output.push_str(&format!(r#"
#[derive(Default)]
pub struct Set{set};

unsafe impl ::vulkano::descriptor_set::SetLayout for Set{set} {{
    fn descriptors(&self) -> Vec<::vulkano::descriptor_set::DescriptorDesc> {{
        vec![
            {descr}
        ]
    }}
}}

unsafe impl<'a {write_tp}> ::vulkano::descriptor_set::SetLayoutWrite<{write_ty}> for Set{set}
    {write_where}
{{
    fn decode(&self, data: {write_ty}) -> Vec<::vulkano::descriptor_set::DescriptorWrite> {{
        vec![
            {writes}
        ]
    }}
}}

unsafe impl<'a {write_tp}> ::vulkano::descriptor_set::SetLayoutInit<{write_ty}> for Set{set}
    {write_where}
{{
    fn decode(&self, data: {write_ty}) -> Vec<::vulkano::descriptor_set::DescriptorWrite> {{
        ::vulkano::descriptor_set::SetLayoutWrite::decode(self, data)
    }}
}}

"#, set = set, write_ty = write_ty, writes = writes.join(","), write_tp = write_tp,
    write_where = write_where, descr = descr.join(",")));
    }

    let max_set = sets_list.iter().cloned().max().map(|v| v + 1).unwrap_or(0);

    let sets_defs = (0 .. max_set).map(|num| {
        if sets_list.contains(&num) {
            format!("::std::sync::Arc<::vulkano::descriptor_set::DescriptorSet<Set{}>>", num)
        } else {
            "()".to_owned()
        }
    }).collect::<Vec<_>>();

    let sets = (0 .. max_set).map(|num| {
        if sets_list.contains(&num) {
            if sets_defs.len() == 1 {
                format!("sets")
            } else {
                format!("sets.{}", num)
            }
        } else {
            "()".to_owned()     // FIXME: wrong
        }
    }).collect::<Vec<_>>();

    let layouts_defs = (0 .. max_set).map(|num| {
        if sets_list.contains(&num) {
            format!("::std::sync::Arc<::vulkano::descriptor_set::DescriptorSetLayout<Set{}>>", num)
        } else {
            "()".to_owned()
        }
    }).collect::<Vec<_>>();

    let layouts = (0 .. max_set).map(|num| {
        if sets_list.contains(&num) {
            if layouts_defs.len() == 1 {
                format!("layouts")
            } else {
                format!("layouts.{}", num)
            }
        } else {
            "()".to_owned()     // FIXME: wrong
        }
    }).collect::<Vec<_>>();

    output.push_str(&format!(r#"
#[derive(Default)]
pub struct Layout;

unsafe impl ::vulkano::descriptor_set::Layout for Layout {{
    type DescriptorSets = ({sets_defs});
    type DescriptorSetLayouts = ({layouts_defs});
    type PushConstants = ();

    fn decode_descriptor_set_layouts(&self, layouts: Self::DescriptorSetLayouts)
        -> Vec<::std::sync::Arc<::vulkano::descriptor_set::AbstractDescriptorSetLayout>>
    {{
        vec![
            {layouts}
        ]
    }}

    fn decode_descriptor_sets(&self, sets: Self::DescriptorSets)
        -> Vec<::std::sync::Arc<::vulkano::descriptor_set::AbstractDescriptorSet>>
    {{
        vec![
            {sets}
        ]
    }}
}}
"#, sets_defs = sets_defs.join(","), layouts_defs = layouts_defs.join(","),
    layouts = layouts.join(","), sets = sets.join(",")));

    output
}

/// Assumes that `variable` is a variable with a `TypePointer` and returns the id of the pointed
/// type.
fn pointer_variable_ty(doc: &parse::Spirv, variable: u32) -> u32 {
    let var_ty = doc.instructions.iter().filter_map(|i| {
        match i {
            &parse::Instruction::Variable { result_type_id, result_id, .. } if result_id == variable => {
                Some(result_type_id)
            },
            _ => None
        }
    }).next().unwrap();

    doc.instructions.iter().filter_map(|i| {
        match i {
            &parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == var_ty => {
                Some(type_id)
            },
            _ => None
        }
    }).next().unwrap()
}
<|endoftext|>


<commit_before>use super::types::{ShardAndCommittee, ValidatorRecord, ChainConfig};
use super::TransitionError;
use super::shuffle;
use std::cmp::min;

type DelegatedSlot = Vec<ShardAndCommittee>;
type DelegatedCycle = Vec<DelegatedSlot>;

/* Produce a vector of validators indicies where those validators start and end
 * dynasties are within the supplied `dynasty`.
*/
fn active_validator_indicies(
    dynasty: &u64,
    validators: &Vec<ValidatorRecord>)
    -> Vec<usize>
{
    validators.iter()
        .enumerate()
        .filter_map(|(i, validator)| {
            if (validator.start_dynasty >= *dynasty) &
                (validator.end_dynasty < *dynasty)
            {
                Some(i)
            } else {
                None
            }
        })
        .collect()
}

/*
 * splits a vector into chunks of size n. All postive n values are applicable,
 * hence the honey_badger prefix.
 */
fn honey_badger_split<T: Clone>(list: &Vec<T>, n: usize) -> Vec<Vec<T>> {
  let mut split_list: Vec<Vec<T>> = vec![];
  let list_length = list.len();
  for i in 0..n {
    let partition = match list.get(list_length*i/n..list_length*(i+1)/n) {
        Some(v) => v,
        None => unreachable!(),
    };
    split_list.push(partition.to_vec());
  }
  split_list
}

/*
 * Delegates active validators into slots for a given cycle, given a random seed.
 * Returns a vector or ShardAndComitte vectors representing the shards and committiees for
 * each slot.
 * References get_new_shuffling (ethereum 2.1 specification)
 */
pub fn delegate_validators(
    seed: &[u8],
    validators: &Vec<ValidatorRecord>,
    dynasty: &u64,
    crosslinking_shard_start: &u16,
    config: &ChainConfig)
    -> Result<DelegatedCycle, TransitionError>
{
    let shuffled_validator_indices = {
        let mut validator_indices = active_validator_indicies(dynasty, validators);
        match shuffle(seed, validator_indices) {
            Ok(shuffled) => shuffled,
            _ => return Err(TransitionError::InvalidInput(
                    String::from("Shuffle list length exceed.")))
        }
    };
    let shard_indices = (0_usize..config.shard_count as usize).into_iter().collect();
    let crosslinking_shard_start = *crosslinking_shard_start as usize;
    let cycle_length = config.cycle_length as usize;
    let min_committee_size = config.min_committee_size as usize;
    generate_cycle(
        &shuffled_validator_indices,
        &shard_indices,
        &crosslinking_shard_start,
        &cycle_length,
        &min_committee_size)
}

/*
 * Given the validator list, delegates the validators into slots and comittees for a given cycle.
 */
fn generate_cycle(
    validator_indices: &Vec<usize>,
    shard_indices: &Vec<usize>,
    crosslinking_shard_start: &usize,
    cycle_length: &usize,
    min_committee_size: &usize)
    -> Result<DelegatedCycle, TransitionError>
{

    let validator_count = validator_indices.len();
    let shard_count = shard_indices.len();

    if shard_count / cycle_length == 0 {
	    return Err(TransitionError::InvalidInput(String::from("Number of
					    shards needs to be greater than
					    cycle length")));

    }

    let (committees_per_slot, slots_per_committee) = {
        if validator_count >= cycle_length * min_committee_size {
            let committees_per_slot = min(validator_count / cycle_length /
			    (min_committee_size * 2) + 1, shard_count /
			    cycle_length);
            let slots_per_committee = 1;
            (committees_per_slot, slots_per_committee)
        } else {
            let committees_per_slot = 1;
            let mut slots_per_committee = 1;
            while (validator_count * slots_per_committee < cycle_length * min_committee_size) &
                (slots_per_committee < *cycle_length) {
                slots_per_committee = slots_per_committee * 2;
            }
            (committees_per_slot, slots_per_committee)
        }
    };

    let cycle = validator_indices
        .chunks(validator_indices.len() / *cycle_length)
        .enumerate()
        .map(|(i, slot_indices)| {
            let shard_id_start = crosslinking_shard_start + i * committees_per_slot / slots_per_committee;
            return slot_indices
                .chunks(slot_indices.len() / committees_per_slot)
                .enumerate()
                .map(|(j, shard_indices)| {
                    return ShardAndCommittee{
                        shard_id: ((shard_id_start + j) % shard_count) as u16,
                        committee: shard_indices.to_vec(),
                    }
                })
                .collect()
        })
        .collect();
    Ok(cycle)
}

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

    fn generate_cycle_helper(
        validator_count: &usize,
        shard_count: &usize,
        crosslinking_shard_start: &usize,
        cycle_length: &usize,
        min_committee_size: &usize)
        -> (Vec<usize>, Vec<usize>, Result<DelegatedCycle, TransitionError>)
    {
        let validator_indices = (0_usize..*validator_count).into_iter().collect();
        let shard_indices = (0_usize..*shard_count).into_iter().collect();
        let result = generate_cycle(
            &validator_indices,
            &shard_indices,
            &crosslinking_shard_start,
            &cycle_length,
            &min_committee_size);
        (validator_indices, shard_indices, result)
    }

    #[allow(dead_code)]
    fn print_cycle(cycle: &DelegatedCycle) {
        cycle.iter()
            .enumerate()
            .for_each(|(i, slot)| {
                println!("slot {:?}", &i);
                slot.iter()
                    .enumerate()
                    .for_each(|(i, sac)| {
                        println!("#{:?}\tshard_id={}\tcommittee.len()={}",
                            &i, &sac.shard_id, &sac.committee.len())
                    })
            });
    }

    fn flatten_validators(cycle: &DelegatedCycle)
        -> Vec<usize>
    {
        let mut flattened = vec![];
        for slot in cycle.iter() {
            for sac in slot.iter() {
                for validator in sac.committee.iter() {
                    flattened.push(*validator);
                }
            }
        }
        flattened
    }

    fn flatten_and_dedup_shards(cycle: &DelegatedCycle)
        -> Vec<usize>
    {
        let mut flattened = vec![];
        for slot in cycle.iter() {
            for sac in slot.iter() {
                flattened.push(sac.shard_id as usize);
            }
        }
        flattened.dedup();
        flattened
    }

    fn flatten_shards_in_slots(cycle: &DelegatedCycle)
        -> Vec<Vec<usize>>
    {
        let mut shards_in_slots: Vec<Vec<usize>> = vec![];
        for slot in cycle.iter() {
            let mut shards: Vec<usize> = vec![];
            for sac in slot.iter() {
                shards.push(sac.shard_id as usize);
            }
            shards_in_slots.push(shards);
        }
        shards_in_slots
    }

    #[test]
    fn test_generate_cycle() {
        let validator_count: usize = 100;
        let shard_count: usize = 10;
        let crosslinking_shard_start: usize = 0;
        let cycle_length: usize = 20;
        let min_committee_size: usize = 10;
        let (validators, shards, result) = generate_cycle_helper(
            &validator_count,
            &shard_count,
            &crosslinking_shard_start,
            &cycle_length,
            &min_committee_size);
        let cycle = result.unwrap();

        let assigned_validators = flatten_validators(&cycle);
        let assigned_shards = flatten_and_dedup_shards(&cycle);
        let shards_in_slots = flatten_shards_in_slots(&cycle);
        assert_eq!(assigned_validators, validators, "Validator assignment incorrect");
        assert_eq!(assigned_shards, shards, "Shard assignment incorrect");

        let expected_shards_in_slots: Vec<Vec<usize>> = vec![
            vec![0], vec![0],   // Each line is 2 slots..
            vec![1], vec![1],
            vec![2], vec![2],
            vec![3], vec![3],
            vec![4], vec![4],
            vec![5], vec![5],
            vec![6], vec![6],
            vec![7], vec![7],
            vec![8], vec![8],
            vec![9], vec![9],
        ];
        // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots));
        assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.")
    }

    #[test]
    // Check that the committees per slot is upper bounded by shard count
    fn test_generate_cycle_committees_bounded() {
        let validator_count: usize = 101;
        let shard_count: usize = 15;
        let crosslinking_shard_start: usize = 0;
        let cycle_length: usize = 10;
        let min_committee_size: usize = 10;
        let (validators, shards, result) = generate_cycle_helper(
            &validator_count,
            &shard_count,
            &crosslinking_shard_start,
            &cycle_length,
            &min_committee_size);
        let cycle = result.unwrap();

        let assigned_validators = flatten_validators(&cycle);
        let assigned_shards = flatten_and_dedup_shards(&cycle);
        let shards_in_slots = flatten_shards_in_slots(&cycle);
        print_cycle(&cycle);
        assert_eq!(assigned_validators, validators, "Validator assignment incorrect");
        assert_eq!(assigned_shards, shards, "Shard assignment incorrect");

        let expected_shards_in_slots: Vec<Vec<usize>> = vec![
            vec![0], vec![0],   // Each line is 2 slots..
            vec![1], vec![1],
            vec![2], vec![2],
            vec![3], vec![3],
            vec![4], vec![4],
            vec![5], vec![5],
            vec![6], vec![6],
            vec![7], vec![7],
            vec![8], vec![8],
            vec![9], vec![9],
        ];
        // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots));
        assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.")
    }
}
<commit_msg>Converts split function into an iterable trait<commit_after>use super::types::{ShardAndCommittee, ValidatorRecord, ChainConfig};
use super::TransitionError;
use super::shuffle;
use std::cmp::min;

type DelegatedSlot = Vec<ShardAndCommittee>;
type DelegatedCycle = Vec<DelegatedSlot>;

/*
 * Iterator for the honey_badger_split function
 */
struct Split<'a, T: 'a> {
    n: usize,
    current_pos: usize,
    list: &'a [T],
    list_length: usize
}

impl<'a,T> Iterator for Split<'a, T> {
    type Item = &'a [T];

    fn next(&mut self) -> Option<Self::Item> {
        self.current_pos +=1;
        if self.current_pos <= self.n {
            match self.list.get(self.list_length*(self.current_pos-1)/self.n..self.list_length*self.current_pos/self.n) {
                Some(v) => Some(v),
                None => unreachable!()
            }
        }
        else {
            None
        }
    }
}

/*
 * splits a slice into chunks of size n. All postive n values are applicable,
 * hence the honey_badger prefix.
 * Returns an iterator over the original list.
 */
trait SplitExt<T> {
    fn honey_badger_split(&self, n: usize) -> Split<T>;
}

impl<T> SplitExt<T> for [T] {

    fn honey_badger_split(&self, n: usize) -> Split<T> {
        Split {
            n: n,
            current_pos: 0,
            list: &self,
            list_length: self.len(),
        }
    }
}

/* Produce a vector of validators indicies where those validators start and end
 * dynasties are within the supplied `dynasty`.
*/
fn active_validator_indicies(
    dynasty: &u64,
    validators: &Vec<ValidatorRecord>)
    -> Vec<usize>
{
    validators.iter()
        .enumerate()
        .filter_map(|(i, validator)| {
            if (validator.start_dynasty >= *dynasty) &
                (validator.end_dynasty < *dynasty)
            {
                Some(i)
            } else {
                None
            }
        })
        .collect()
}

/*
 * Delegates active validators into slots for a given cycle, given a random seed.
 * Returns a vector or ShardAndComitte vectors representing the shards and committiees for
 * each slot.
 * References get_new_shuffling (ethereum 2.1 specification)
 */
pub fn delegate_validators(
    seed: &[u8],
    validators: &Vec<ValidatorRecord>,
    dynasty: &u64,
    crosslinking_shard_start: &u16,
    config: &ChainConfig)
    -> Result<DelegatedCycle, TransitionError>
{
    let shuffled_validator_indices = {
        let mut validator_indices = active_validator_indicies(dynasty, validators);
        match shuffle(seed, validator_indices) {
            Ok(shuffled) => shuffled,
            _ => return Err(TransitionError::InvalidInput(
                    String::from("Shuffle list length exceed.")))
        }
    };
    let shard_indices = (0_usize..config.shard_count as usize).into_iter().collect();
    let crosslinking_shard_start = *crosslinking_shard_start as usize;
    let cycle_length = config.cycle_length as usize;
    let min_committee_size = config.min_committee_size as usize;
    generate_cycle(
        &shuffled_validator_indices,
        &shard_indices,
        &crosslinking_shard_start,
        &cycle_length,
        &min_committee_size)
}

/*
 * Given the validator list, delegates the validators into slots and comittees for a given cycle.
 */
fn generate_cycle(
    validator_indices: &Vec<usize>,
    shard_indices: &Vec<usize>,
    crosslinking_shard_start: &usize,
    cycle_length: &usize,
    min_committee_size: &usize)
    -> Result<DelegatedCycle, TransitionError>
{

    let validator_count = validator_indices.len();
    let shard_count = shard_indices.len();

    if shard_count / cycle_length == 0 {
	    return Err(TransitionError::InvalidInput(String::from("Number of
					    shards needs to be greater than
					    cycle length")));

    }

    let (committees_per_slot, slots_per_committee) = {
        if validator_count >= cycle_length * min_committee_size {
            let committees_per_slot = min(validator_count / cycle_length /
			    (min_committee_size * 2) + 1, shard_count /
			    cycle_length);
            let slots_per_committee = 1;
            (committees_per_slot, slots_per_committee)
        } else {
            let committees_per_slot = 1;
            let mut slots_per_committee = 1;
            while (validator_count * slots_per_committee < cycle_length * min_committee_size) &
                (slots_per_committee < *cycle_length) {
                slots_per_committee = slots_per_committee * 2;
            }
            (committees_per_slot, slots_per_committee)
        }
    };

    let cycle = validator_indices.honey_badger_split(*cycle_length)
        .enumerate()
        .map(|(i, slot_indices)| {
            let shard_id_start = crosslinking_shard_start + i * committees_per_slot / slots_per_committee;
            return slot_indices.honey_badger_split(committees_per_slot)
                .enumerate()
                .map(|(j, shard_indices)| {
                    return ShardAndCommittee{
                        shard_id: ((shard_id_start + j) % shard_count) as u16,
                        committee: shard_indices.to_vec(),
                    }
                })
                .collect()
        })
        .collect();
    Ok(cycle)
}

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

    fn generate_cycle_helper(
        validator_count: &usize,
        shard_count: &usize,
        crosslinking_shard_start: &usize,
        cycle_length: &usize,
        min_committee_size: &usize)
        -> (Vec<usize>, Vec<usize>, Result<DelegatedCycle, TransitionError>)
    {
        let validator_indices = (0_usize..*validator_count).into_iter().collect();
        let shard_indices = (0_usize..*shard_count).into_iter().collect();
        let result = generate_cycle(
            &validator_indices,
            &shard_indices,
            &crosslinking_shard_start,
            &cycle_length,
            &min_committee_size);
        (validator_indices, shard_indices, result)
    }

    #[allow(dead_code)]
    fn print_cycle(cycle: &DelegatedCycle) {
        cycle.iter()
            .enumerate()
            .for_each(|(i, slot)| {
                println!("slot {:?}", &i);
                slot.iter()
                    .enumerate()
                    .for_each(|(i, sac)| {
                        println!("#{:?}\tshard_id={}\tcommittee.len()={}",
                            &i, &sac.shard_id, &sac.committee.len())
                    })
            });
    }

    fn flatten_validators(cycle: &DelegatedCycle)
        -> Vec<usize>
    {
        let mut flattened = vec![];
        for slot in cycle.iter() {
            for sac in slot.iter() {
                for validator in sac.committee.iter() {
                    flattened.push(*validator);
                }
            }
        }
        flattened
    }

    fn flatten_and_dedup_shards(cycle: &DelegatedCycle)
        -> Vec<usize>
    {
        let mut flattened = vec![];
        for slot in cycle.iter() {
            for sac in slot.iter() {
                flattened.push(sac.shard_id as usize);
            }
        }
        flattened.dedup();
        flattened
    }

    fn flatten_shards_in_slots(cycle: &DelegatedCycle)
        -> Vec<Vec<usize>>
    {
        let mut shards_in_slots: Vec<Vec<usize>> = vec![];
        for slot in cycle.iter() {
            let mut shards: Vec<usize> = vec![];
            for sac in slot.iter() {
                shards.push(sac.shard_id as usize);
            }
            shards_in_slots.push(shards);
        }
        shards_in_slots
    }

    #[test]
    fn test_generate_cycle() {
        let validator_count: usize = 100;
        let shard_count: usize = 10;
        let crosslinking_shard_start: usize = 0;
        let cycle_length: usize = 20;
        let min_committee_size: usize = 10;
        let (validators, shards, result) = generate_cycle_helper(
            &validator_count,
            &shard_count,
            &crosslinking_shard_start,
            &cycle_length,
            &min_committee_size);
        let cycle = result.unwrap();

        let assigned_validators = flatten_validators(&cycle);
        let assigned_shards = flatten_and_dedup_shards(&cycle);
        let shards_in_slots = flatten_shards_in_slots(&cycle);
        assert_eq!(assigned_validators, validators, "Validator assignment incorrect");
        assert_eq!(assigned_shards, shards, "Shard assignment incorrect");

        let expected_shards_in_slots: Vec<Vec<usize>> = vec![
            vec![0], vec![0],   // Each line is 2 slots..
            vec![1], vec![1],
            vec![2], vec![2],
            vec![3], vec![3],
            vec![4], vec![4],
            vec![5], vec![5],
            vec![6], vec![6],
            vec![7], vec![7],
            vec![8], vec![8],
            vec![9], vec![9],
        ];
        // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots));
        assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.")
    }

    #[test]
    // Check that the committees per slot is upper bounded by shard count
    fn test_generate_cycle_committees_bounded() {
        let validator_count: usize = 1001;
        let shard_count: usize = 15;
        let crosslinking_shard_start: usize = 0;
        let cycle_length: usize = 10;
        let min_committee_size: usize = 10;
        let (validators, shards, result) = generate_cycle_helper(
            &validator_count,
            &shard_count,
            &crosslinking_shard_start,
            &cycle_length,
            &min_committee_size);
        let cycle = result.unwrap();
        print_cycle(&cycle);
        let assigned_validators = flatten_validators(&cycle);
        let assigned_shards = flatten_and_dedup_shards(&cycle);
        let shards_in_slots = flatten_shards_in_slots(&cycle);
        assert_eq!(assigned_validators, validators, "Validator assignment incorrect");
        assert_eq!(assigned_shards, shards, "Shard assignment incorrect");

        let expected_shards_in_slots: Vec<Vec<usize>> = vec![
            vec![0], vec![0],   // Each line is 2 slots..
            vec![1], vec![1],
            vec![2], vec![2],
            vec![3], vec![3],
            vec![4], vec![4],
            vec![5], vec![5],
            vec![6], vec![6],
            vec![7], vec![7],
            vec![8], vec![8],
            vec![9], vec![9],
        ];
        // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots));
        assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.")
    }
}
<|endoftext|>


<commit_before>use escargot::CargoBuild;
use failure::ResultExt;
use std::io;
use std::{thread, time};
use varlink::Connection;
use Result;

fn run_self_test(address: String) -> Result<()> {
    let client_address = address.clone();

    let child = thread::spawn(move || {
        if let Err(e) = ::run_server(&address, 4) {
            match e.kind() {
                ::varlink::ErrorKind::Timeout => {}
                _ => panic!("error: {}", e),
            }
        }
    });

    // give server time to start
    thread::sleep(time::Duration::from_secs(1));

    let ret = ::run_client(Connection::with_address(&client_address)?);
    if let Err(e) = ret {
        panic!("error: {:?}", e);
    }
    if let Err(e) = child.join() {
        Err(io::Error::new(io::ErrorKind::ConnectionRefused, format!("{:#?}", e)).into())
    } else {
        Ok(())
    }
}

#[test]
fn test_unix() -> ::Result<()> {
    run_self_test("unix:/tmp/org.varlink.certification".into())
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_unix_abstract() -> Result<()> {
    run_self_test("unix:@org.varlink.certification".into())
}

#[test]
fn test_tcp() -> Result<()> {
    run_self_test("tcp:0.0.0.0:23456".into())
}

fn get_exec() -> Result<String> {
    let runner = CargoBuild::new()
        .current_release()
        .run()
        .context(::ErrorKind::Io_Error(::std::io::ErrorKind::NotFound))?;
    Ok(runner.path().to_owned().to_string_lossy().to_string())
}

#[test]
fn test_exec() -> Result<()> {
    ::run_client(Connection::with_activate(&format!(
        "{} --varlink=$VARLINK_ADDRESS",
        get_exec()?
    ))?)
}

#[test]
fn test_wrong_address_1() {
    assert!(::run_server("tcpd:0.0.0.0:12345".into(), 1).is_err());
}
<commit_msg>varlink-certification/src/test.rs: test_exec() only for unix<commit_after>use std::io;
use std::{thread, time};
use varlink::Connection;
use Result;

fn run_self_test(address: String) -> Result<()> {
    let client_address = address.clone();

    let child = thread::spawn(move || {
        if let Err(e) = ::run_server(&address, 4) {
            match e.kind() {
                ::varlink::ErrorKind::Timeout => {}
                _ => panic!("error: {}", e),
            }
        }
    });

    // give server time to start
    thread::sleep(time::Duration::from_secs(1));

    let ret = ::run_client(Connection::with_address(&client_address)?);
    if let Err(e) = ret {
        panic!("error: {:?}", e);
    }
    if let Err(e) = child.join() {
        Err(io::Error::new(io::ErrorKind::ConnectionRefused, format!("{:#?}", e)).into())
    } else {
        Ok(())
    }
}

#[test]
fn test_unix() -> ::Result<()> {
    run_self_test("unix:org.varlink.certification".into())
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_unix_abstract() -> Result<()> {
    run_self_test("unix:@org.varlink.certification".into())
}

#[test]
fn test_tcp() -> Result<()> {
    run_self_test("tcp:127.0.0.1:23456".into())
}

#[cfg(unix)]
#[test]
fn test_exec() -> Result<()> {
    use escargot::CargoBuild;
    use failure::ResultExt;
    fn get_exec() -> Result<String> {
        let runner = CargoBuild::new()
            .current_release()
            .run()
            .context(::ErrorKind::Io_Error(::std::io::ErrorKind::NotFound))?;
        Ok(runner.path().to_owned().to_string_lossy().to_string())
    }

    ::run_client(Connection::with_activate(&format!(
        "{} --varlink=$VARLINK_ADDRESS",
        get_exec()?
    ))?)
}

#[test]
fn test_wrong_address_1() {
    assert!(::run_server("tcpd:0.0.0.0:12345".into(), 1).is_err());
}
<|endoftext|>


<commit_before>use std::iter::successors;

use hir::{TypeInfo, HirDisplay};
use itertools::Itertools;
use syntax::{
    algo::neighbor,
    ast::{self, AstNode},
    Direction,
};

use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange};

// Assist: merge_match_arms
//
// Merges the current match arm with the following if their bodies are identical.
//
// ```
// enum Action { Move { distance: u32 }, Stop }
//
// fn handle(action: Action) {
//     match action {
//         $0Action::Move(..) => foo(),
//         Action::Stop => foo(),
//     }
// }
// ```
// ->
// ```
// enum Action { Move { distance: u32 }, Stop }
//
// fn handle(action: Action) {
//     match action {
//         Action::Move(..) | Action::Stop => foo(),
//     }
// }
// ```
pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let current_arm = ctx.find_node_at_offset::<ast::MatchArm>()?;
    // Don't try to handle arms with guards for now - can add support for this later
    if current_arm.guard().is_some() {
        return None;
    }
    let current_expr = current_arm.expr()?;
    let current_text_range = current_arm.syntax().text_range();
    let current_arm_types = get_arm_types(&ctx, &current_arm);

    // We check if the following match arms match this one. We could, but don't,
    // compare to the previous match arm as well.
    let arms_to_merge = successors(Some(current_arm), |it| neighbor(it, Direction::Next))
        .take_while(|arm| match arm.expr() {
            Some(expr) if arm.guard().is_none() => {
                let same_text = expr.syntax().text() == current_expr.syntax().text();
                if !same_text {
                    return false;
                }

                let arm_types = get_arm_types(&ctx, &arm);
                for i in 0..arm_types.len() {
                    let other_arm_type = &arm_types[i].as_ref();
                    let current_arm_type = current_arm_types[i].as_ref();
                    if let (Some(other_arm_type), Some(current_arm_type)) = (other_arm_type, current_arm_type) {
                        return &other_arm_type.original == &current_arm_type.original;
                    }
                }

                true
            }
            _ => false,
        })
        .collect::<Vec<_>>();

    if arms_to_merge.len() <= 1 {
        return None;
    }

    acc.add(
        AssistId("merge_match_arms", AssistKind::RefactorRewrite),
        "Merge match arms",
        current_text_range,
        |edit| {
            let pats = if arms_to_merge.iter().any(contains_placeholder) {
                "_".into()
            } else {
                arms_to_merge
                    .iter()
                    .filter_map(ast::MatchArm::pat)
                    .map(|x| x.syntax().to_string())
                    .collect::<Vec<String>>()
                    .join(" | ")
            };

            let arm = format!("{} => {},", pats, current_expr.syntax().text());

            if let [first, .., last] = &*arms_to_merge {
                let start = first.syntax().text_range().start();
                let end = last.syntax().text_range().end();

                edit.replace(TextRange::new(start, end), arm);
            }
        },
    )
}

fn contains_placeholder(a: &ast::MatchArm) -> bool {
    matches!(a.pat(), Some(ast::Pat::WildcardPat(..)))
}

fn get_arm_types(ctx: &AssistContext, arm: &ast::MatchArm) -> Vec<Option<TypeInfo>> {
    match arm.pat() {
        Some(ast::Pat::TupleStructPat(tp)) => tp
            .fields()
            .into_iter()
            .map(|field| {
                let pat_type = ctx.sema.type_of_pat(&field);
                pat_type
            })
            .collect_vec(),
        _ => Vec::new(),
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn merge_match_arms_single_patterns() {
        check_assist(
            merge_match_arms,
            r#"
#[derive(Debug)]
enum X { A, B, C }

fn main() {
    let x = X::A;
    let y = match x {
        X::A => { 1i32$0 }
        X::B => { 1i32 }
        X::C => { 2i32 }
    }
}
"#,
            r#"
#[derive(Debug)]
enum X { A, B, C }

fn main() {
    let x = X::A;
    let y = match x {
        X::A | X::B => { 1i32 },
        X::C => { 2i32 }
    }
}
"#,
        );
    }

    #[test]
    fn merge_match_arms_multiple_patterns() {
        check_assist(
            merge_match_arms,
            r#"
#[derive(Debug)]
enum X { A, B, C, D, E }

fn main() {
    let x = X::A;
    let y = match x {
        X::A | X::B => {$0 1i32 },
        X::C | X::D => { 1i32 },
        X::E => { 2i32 },
    }
}
"#,
            r#"
#[derive(Debug)]
enum X { A, B, C, D, E }

fn main() {
    let x = X::A;
    let y = match x {
        X::A | X::B | X::C | X::D => { 1i32 },
        X::E => { 2i32 },
    }
}
"#,
        );
    }

    #[test]
    fn merge_match_arms_placeholder_pattern() {
        check_assist(
            merge_match_arms,
            r#"
#[derive(Debug)]
enum X { A, B, C, D, E }

fn main() {
    let x = X::A;
    let y = match x {
        X::A => { 1i32 },
        X::B => { 2i$032 },
        _ => { 2i32 }
    }
}
"#,
            r#"
#[derive(Debug)]
enum X { A, B, C, D, E }

fn main() {
    let x = X::A;
    let y = match x {
        X::A => { 1i32 },
        _ => { 2i32 },
    }
}
"#,
        );
    }

    #[test]
    fn merges_all_subsequent_arms() {
        check_assist(
            merge_match_arms,
            r#"
enum X { A, B, C, D, E }

fn main() {
    match X::A {
        X::A$0 => 92,
        X::B => 92,
        X::C => 92,
        X::D => 62,
        _ => panic!(),
    }
}
"#,
            r#"
enum X { A, B, C, D, E }

fn main() {
    match X::A {
        X::A | X::B | X::C => 92,
        X::D => 62,
        _ => panic!(),
    }
}
"#,
        )
    }

    #[test]
    fn merge_match_arms_rejects_guards() {
        check_assist_not_applicable(
            merge_match_arms,
            r#"
#[derive(Debug)]
enum X {
    A(i32),
    B,
    C
}

fn main() {
    let x = X::A;
    let y = match x {
        X::A(a) if a > 5 => { $01i32 },
        X::B => { 1i32 },
        X::C => { 2i32 }
    }
}
"#,
        );
    }

    #[test]
    fn merge_match_arms_different_type() {
        check_assist_not_applicable(
            merge_match_arms,
            r#"//- minicore: result
fn func() {
    match Result::<i32, f32>::Ok(0) {
        Ok(x) => $0x.to_string(),
        Err(x) => x.to_string()
    };
}
"#,
        );
    }
}

// fn func() {
//     match Result::<i32, f32>::Ok(0) {
//         Ok(x) => x.to_string(),
//         Err(x) => x.to_string()
//     };
// }
<commit_msg>using classify()<commit_after>use std::iter::successors;
use hir::TypeInfo;
use itertools::Itertools;
use syntax::{
    algo::neighbor,
    ast::{self, AstNode},
    Direction,
};

use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange};

// Assist: merge_match_arms
//
// Merges the current match arm with the following if their bodies are identical.
//
// ```
// enum Action { Move { distance: u32 }, Stop }
//
// fn handle(action: Action) {
//     match action {
//         $0Action::Move(..) => foo(),
//         Action::Stop => foo(),
//     }
// }
// ```
// ->
// ```
// enum Action { Move { distance: u32 }, Stop }
//
// fn handle(action: Action) {
//     match action {
//         Action::Move(..) | Action::Stop => foo(),
//     }
// }
// ```
pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let current_arm = ctx.find_node_at_offset::<ast::MatchArm>()?;
    // Don't try to handle arms with guards for now - can add support for this later
    if current_arm.guard().is_some() {
        return None;
    }
    let current_expr = current_arm.expr()?;
    let current_text_range = current_arm.syntax().text_range();
    let current_arm_types = get_arm_types(&ctx, &current_arm);

    // We check if the following match arms match this one. We could, but don't,
    // compare to the previous match arm as well.
    let arms_to_merge = successors(Some(current_arm), |it| neighbor(it, Direction::Next))
        .take_while(|arm| match arm.expr() {
            Some(expr) if arm.guard().is_none() => {
                let same_text = expr.syntax().text() == current_expr.syntax().text();
                if !same_text {
                    return false;
                }

                let arm_types = get_arm_types(&ctx, &arm);
                for i in 0..arm_types.len() {
                    let other_arm_type = &arm_types[i].as_ref();
                    let current_arm_type = current_arm_types[i].as_ref();
                    if let (Some(other_arm_type), Some(current_arm_type)) = (other_arm_type, current_arm_type) {
                        return &other_arm_type.original == &current_arm_type.original;
                    }
                }

                true
            }
            _ => false,
        })
        .collect::<Vec<_>>();

    if arms_to_merge.len() <= 1 {
        return None;
    }

    acc.add(
        AssistId("merge_match_arms", AssistKind::RefactorRewrite),
        "Merge match arms",
        current_text_range,
        |edit| {
            let pats = if arms_to_merge.iter().any(contains_placeholder) {
                "_".into()
            } else {
                arms_to_merge
                    .iter()
                    .filter_map(ast::MatchArm::pat)
                    .map(|x| x.syntax().to_string())
                    .collect::<Vec<String>>()
                    .join(" | ")
            };

            let arm = format!("{} => {},", pats, current_expr.syntax().text());

            if let [first, .., last] = &*arms_to_merge {
                let start = first.syntax().text_range().start();
                let end = last.syntax().text_range().end();

                edit.replace(TextRange::new(start, end), arm);
            }
        },
    )
}

fn contains_placeholder(a: &ast::MatchArm) -> bool {
    matches!(a.pat(), Some(ast::Pat::WildcardPat(..)))
}

fn get_arm_types(ctx: &AssistContext, arm: &ast::MatchArm) -> Vec<Option<TypeInfo>> {
    match arm.pat() {
        Some(ast::Pat::TupleStructPat(tp)) => tp
            .fields()
            .into_iter()
            .map(|field| {
                let pat_type = ctx.sema.type_of_pat(&field);
                pat_type
            })
            .collect_vec(),
        _ => Vec::new(),
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn merge_match_arms_single_patterns() {
        check_assist(
            merge_match_arms,
            r#"
#[derive(Debug)]
enum X { A, B, C }

fn main() {
    let x = X::A;
    let y = match x {
        X::A => { 1i32$0 }
        X::B => { 1i32 }
        X::C => { 2i32 }
    }
}
"#,
            r#"
#[derive(Debug)]
enum X { A, B, C }

fn main() {
    let x = X::A;
    let y = match x {
        X::A | X::B => { 1i32 },
        X::C => { 2i32 }
    }
}
"#,
        );
    }

    #[test]
    fn merge_match_arms_multiple_patterns() {
        check_assist(
            merge_match_arms,
            r#"
#[derive(Debug)]
enum X { A, B, C, D, E }

fn main() {
    let x = X::A;
    let y = match x {
        X::A | X::B => {$0 1i32 },
        X::C | X::D => { 1i32 },
        X::E => { 2i32 },
    }
}
"#,
            r#"
#[derive(Debug)]
enum X { A, B, C, D, E }

fn main() {
    let x = X::A;
    let y = match x {
        X::A | X::B | X::C | X::D => { 1i32 },
        X::E => { 2i32 },
    }
}
"#,
        );
    }

    #[test]
    fn merge_match_arms_placeholder_pattern() {
        check_assist(
            merge_match_arms,
            r#"
#[derive(Debug)]
enum X { A, B, C, D, E }

fn main() {
    let x = X::A;
    let y = match x {
        X::A => { 1i32 },
        X::B => { 2i$032 },
        _ => { 2i32 }
    }
}
"#,
            r#"
#[derive(Debug)]
enum X { A, B, C, D, E }

fn main() {
    let x = X::A;
    let y = match x {
        X::A => { 1i32 },
        _ => { 2i32 },
    }
}
"#,
        );
    }

    #[test]
    fn merges_all_subsequent_arms() {
        check_assist(
            merge_match_arms,
            r#"
enum X { A, B, C, D, E }

fn main() {
    match X::A {
        X::A$0 => 92,
        X::B => 92,
        X::C => 92,
        X::D => 62,
        _ => panic!(),
    }
}
"#,
            r#"
enum X { A, B, C, D, E }

fn main() {
    match X::A {
        X::A | X::B | X::C => 92,
        X::D => 62,
        _ => panic!(),
    }
}
"#,
        )
    }

    #[test]
    fn merge_match_arms_rejects_guards() {
        check_assist_not_applicable(
            merge_match_arms,
            r#"
#[derive(Debug)]
enum X {
    A(i32),
    B,
    C
}

fn main() {
    let x = X::A;
    let y = match x {
        X::A(a) if a > 5 => { $01i32 },
        X::B => { 1i32 },
        X::C => { 2i32 }
    }
}
"#,
        );
    }

    #[test]
    fn merge_match_arms_different_type() {
        check_assist_not_applicable(
            merge_match_arms,
            r#"//- minicore: result
fn func() {
    match Result::<f64, f32>::Ok(0f64) {
        Ok(x) => $0x.classify(),
        Err(x) => x.classify()
    };
}
"#,
        );
    }
}

// fn func() {
//     match Result::<f64, f32>::Ok(0f64) {
//         Ok(x) => x.classify(),
//         Err(x) => x.classify()
//     };
// }
<|endoftext|>


<commit_before>extern crate mio;
extern crate mai;
extern crate env_logger;

//use mio::Token;
use mio::tcp::{TcpSocket, TcpStream};
use mai::*;

struct EchoCodec;
struct EchoClient;
struct EchoClientHandler;

impl Protocol for EchoClient {
  type ByteStream = TcpStream;
  type Frame = String;
  type Codec = EchoCodec;
  type Handler = EchoClientHandler;
  type Timeout = usize;
  type Session = ();
}

impl Codec<String> for EchoCodec {

  fn new() -> Self {
    EchoCodec
  }

  fn encode(&mut self, message: &String, buffer: &mut [u8]) -> EncodingResult {
    let bytes = message.as_bytes();
    if bytes.len() > buffer.len() {
      return Err(EncodingError::InsufficientBuffer);
    }
    for (index, &byte) in bytes.iter().enumerate() {
        buffer[index] = byte;
    }
    Ok(BytesWritten(bytes.len()))
  }

  fn decode(&mut self, buffer: &[u8]) -> DecodingResult<String> {
    use std::str;
    let message: String = match str::from_utf8(buffer) {
      Ok(message) => message.to_owned(),
      Err(_error) => return Err(DecodingError::IncompleteFrame)
    };
    Ok(DecodedFrame::new(message, BytesRead(buffer.len())))
  }
}

impl Handler<EchoClient> for EchoClientHandler {
  fn on_ready(&mut self, context: &mut Context<EchoClient>) {
    context.engine().timeout_ms(55, 5_000);
    let mut stream = context.stream();
    println!("Connected to {:?}, issued {:?}",
             stream.peer_addr().unwrap(),
             stream.token());
    let message: String = "Supercalifragilisticexpialidocious!
                    Even though the sound of it
                    Is something quite atrocious
                    If you say it loud enough
                    You\\'ll always sound precocious!
                    Supercalifragilisticexpialidocious!\n".to_owned();
    println!("Sending message...");
    stream.send(message);
  }
  fn on_frame(&mut self, context: &mut Context<EchoClient>, message: String) {
    let stream = context.stream();
    println!("Received a message from {:?}/{:?}: '{}'",
             stream.peer_addr().unwrap(),
             stream.token(),
             &message.trim_right());
  }
  fn on_timeout(&mut self, timeout: usize) {
    println!("A timeout occurred: #{:?}", timeout);
  }
  fn on_error(&mut self, context: &mut Context<EchoClient>, error: &Error) {
    let stream = context.stream();
    println!("Error. {:?}/{:?}, {:?}",
             stream.peer_addr().unwrap(),
             stream.token(),
             error);
  }
  fn on_closed(&mut self, context: &mut Context<EchoClient>) {
    let stream = context.stream();
    println!("Disconnected from {:?}/{:?}",
             stream.peer_addr().unwrap(),
             stream.token());
  }
}

fn main() {
  use std;
  env_logger::init().unwrap();
  println!("Connecting to localhost:9999...");
  let address = "0.0.0.0:9999".parse().unwrap();
  let socket = TcpSocket::v4().unwrap();
  let (stream, _complete) = socket.connect(&address).unwrap();

  let mut frame_engine: FrameEngine<EchoClient> =
      mai::frame_engine(EchoClientHandler)
        .with(InitialBufferSize(Kilobytes(32)))
        .with(InitialBufferPoolSize(16))
        .with(MaxBufferPoolSize(128))
        .build();
  let token = frame_engine.manage(stream);
  let thread_handle = std::thread::spawn(||{
    println!("Firing up the engine in a new thread...");
    let _ = frame_engine.run();
  });
  println!("Awaiting engine...");
  thread_handle.join();
}
<commit_msg>Updated example.<commit_after>extern crate mio;
extern crate mai;
extern crate env_logger;

//use mio::Token;
use mio::tcp::{TcpSocket, TcpStream};
use mai::*;

struct EchoCodec;
struct EchoClient;
struct EchoClientHandler;

impl Protocol for EchoClient {
  type ByteStream = TcpStream;
  type Frame = String;
  type Codec = EchoCodec;
  type Handler = EchoClientHandler;
  type Timeout = usize;
  type Session = ();
}

impl Codec<String> for EchoCodec {

  fn new() -> Self {
    EchoCodec
  }

  fn encode(&mut self, message: &String, buffer: &mut [u8]) -> EncodingResult {
    let bytes = message.as_bytes();
    if bytes.len() > buffer.len() {
      return Err(EncodingError::InsufficientBuffer);
    }
    for (index, &byte) in bytes.iter().enumerate() {
        buffer[index] = byte;
    }
    Ok(BytesWritten(bytes.len()))
  }

  fn decode(&mut self, buffer: &[u8]) -> DecodingResult<String> {
    use std::str;
    let message: String = match str::from_utf8(buffer) {
      Ok(message) => message.to_owned(),
      Err(_error) => return Err(DecodingError::IncompleteFrame)
    };
    Ok(DecodedFrame::new(message, BytesRead(buffer.len())))
  }
}

impl Handler<EchoClient> for EchoClientHandler {
  fn on_ready(&mut self, context: &mut Context<EchoClient>) {
    context.engine().timeout_ms(55, 5_000);
    let mut stream = context.stream();
    println!("Connected to {:?}, issued {:?}",
             stream.peer_addr().unwrap(),
             stream.token());
    let message: String = "Supercalifragilisticexpialidocious!
                    Even though the sound of it
                    Is something quite atrocious
                    If you say it loud enough
                    You\\'ll always sound precocious!
                    Supercalifragilisticexpialidocious!\n".to_owned();
    println!("Sending message...");
    stream.send(message);
  }
  fn on_frame(&mut self, context: &mut Context<EchoClient>, message: String) {
    let stream = context.stream();
    println!("Received a message from {:?}/{:?}: '{}'",
             stream.peer_addr().unwrap(),
             stream.token(),
             &message.trim_right());
  }
  fn on_timeout(&mut self, timeout: usize) {
    println!("A timeout occurred: #{:?}", timeout);
  }
  fn on_error(&mut self, context: &mut Context<EchoClient>, error: &Error) {
    let stream = context.stream();
    println!("Error. {:?}/{:?}, {:?}",
             stream.peer_addr().unwrap(),
             stream.token(),
             error);
  }
  fn on_closed(&mut self, context: &mut Context<EchoClient>) {
    let stream = context.stream();
    println!("Disconnected from {:?}/{:?}",
             stream.peer_addr().unwrap(),
             stream.token());
  }
}

fn main() {
  use std;
  env_logger::init().unwrap();
  println!("Connecting to localhost:9999...");
  let address = "0.0.0.0:9999".parse().unwrap();
  let socket = TcpSocket::v4().unwrap();
  let (stream, _complete) = socket.connect(&address).unwrap();

  let mut protocol_engine: ProtocolEngine<EchoClient> =
      mai::protocol_engine(EchoClientHandler)
        .with(InitialBufferSize(Kilobytes(32)))
        .with(InitialBufferPoolSize(16))
        .with(MaxBufferPoolSize(128))
        .build();
  let token = protocol_engine.manage(stream);
  let _ = protocol_engine.run();
}
<|endoftext|>