<commit_before>pub use descartes::{N, P3, P2, V3, V4, M4, Iso3, Persp3, Into2d, Into3d, WithUniqueOrthogonal,
Area, Band};

use glium::{self, index};
use glium::backend::glutin::Display;

use compact::CVec;

#[derive(Copy, Clone, Debug)]
pub struct Vertex {
    pub position: [f32; 3],
}

implement_vertex!(Vertex, position);

#[derive(Copy, Clone)]
pub struct Instance {
    pub instance_position: [f32; 3],
    pub instance_direction: [f32; 2],
    pub instance_color: [f32; 3],
}

implement_vertex!(
    Instance,
    instance_position,
    instance_direction,
    instance_color
);

impl Instance {
    pub fn with_color(color: [f32; 3]) -> Instance {
        Instance {
            instance_position: [0.0, 0.0, 0.0],
            instance_direction: [1.0, 0.0],
            instance_color: color,
        }
    }
}

#[derive(Compact, Debug)]
pub struct Mesh {
    pub vertices: CVec<Vertex>,
    pub indices: CVec<u16>,
}

impl Mesh {
    pub fn new(vertices: Vec<Vertex>, indices: Vec<u16>) -> Mesh {
        Mesh {
            vertices: vertices.into(),
            indices: indices.into(),
        }
    }

    pub fn empty() -> Mesh {
        Mesh {
            vertices: CVec::new(),
            indices: CVec::new(),
        }
    }
}

impl Clone for Mesh {
    fn clone(&self) -> Mesh {
        Mesh {
            vertices: self.vertices.to_vec().into(),
            indices: self.indices.to_vec().into(),
        }
    }
}

impl ::std::ops::Add for Mesh {
    type Output = Mesh;

    fn add(mut self, rhs: Mesh) -> Mesh {
        let self_n_vertices = self.vertices.len();
        self.vertices.extend_from_copy_slice(&rhs.vertices);
        self.indices
            .extend(rhs.indices.iter().map(|i| *i + self_n_vertices as u16));
        self
    }
}

impl ::std::ops::AddAssign for Mesh {
    fn add_assign(&mut self, rhs: Mesh) {
        let self_n_vertices = self.vertices.len();
        for vertex in rhs.vertices.iter().cloned() {
            self.vertices.push(vertex);
        }
        for index in rhs.indices.iter() {
            self.indices.push(index + self_n_vertices as u16)
        }
    }
}

impl ::std::iter::Sum for Mesh {
    fn sum<I: Iterator<Item = Mesh>>(iter: I) -> Mesh {
        let mut summed_mesh = Mesh {
            vertices: CVec::new(),
            indices: CVec::new(),
        };
        for mesh in iter {
            summed_mesh += mesh;
        }
        summed_mesh
    }
}

impl<'a> ::std::ops::AddAssign<&'a Mesh> for Mesh {
    fn add_assign(&mut self, rhs: &'a Mesh) {
        let self_n_vertices = self.vertices.len();
        for vertex in rhs.vertices.iter().cloned() {
            self.vertices.push(vertex);
        }
        for index in rhs.indices.iter() {
            self.indices.push(index + self_n_vertices as u16)
        }
    }
}

impl<'a> ::std::iter::Sum<&'a Mesh> for Mesh {
    fn sum<I: Iterator<Item = &'a Mesh>>(iter: I) -> Mesh {
        let mut summed_mesh = Mesh {
            vertices: CVec::new(),
            indices: CVec::new(),
        };
        for mesh in iter {
            summed_mesh += mesh;
        }
        summed_mesh
    }
}

use itertools::{Itertools, Position};
use lyon_tessellation::{FillTessellator, FillOptions, FillVertex, GeometryBuilder};
use lyon_tessellation::geometry_builder::{VertexId, Count};
use lyon_tessellation::path::iterator::PathIter;
use lyon_tessellation::path::PathEvent;
use lyon_tessellation::math::point;

impl GeometryBuilder<FillVertex> for Mesh {
    fn begin_geometry(&mut self) {}
    fn end_geometry(&mut self) -> Count {
        Count {
            vertices: self.vertices.len() as u32,
            indices: self.indices.len() as u32,
        }
    }
    fn abort_geometry(&mut self) {}
    fn add_vertex(&mut self, input: FillVertex) -> VertexId {
        let id = self.vertices.len();
        self.vertices.push(Vertex {
            position: [input.position.x, input.position.y, 0.0],
        });
        VertexId(id as u16)
    }
    fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
        self.indices.push(a.0);
        self.indices.push(b.0);
        self.indices.push(c.0);
    }
}

impl Mesh {
    pub fn from_area(area: &Area) -> Mesh {
        let path_iterator = PathIter::new(area.primitives.iter().flat_map(|primitive| {
            primitive
                .boundary
                .path()
                .segments()
                .with_position()
                .flat_map(|segment_with_position| {
                    let initial_move = match segment_with_position {
                        Position::First(segment) | Position::Only(segment) => Some(
                            PathEvent::MoveTo(point(segment.start().x, segment.start().y)),
                        ),
                        _ => None,
                    };

                    let segment = segment_with_position.into_inner();

                    initial_move
                        .into_iter()
                        .chain(Some(PathEvent::LineTo(point(
                            segment.end().x,
                            segment.end().y,
                        ))))
                        .collect::<Vec<_>>()
                })
        }));

        let mut tesselator = FillTessellator::new();
        let mut output = Mesh::empty();

        tesselator
            .tessellate_path(path_iterator, &FillOptions::default(), &mut output)
            .unwrap();

        output
    }

    pub fn from_band(band: &Band, z: N) -> Mesh {
        fn to_vertex(point: P2, z: N) -> Vertex {
            Vertex {
                position: [point.x, point.y, z],
            }
        }

        let mut vertices = Vec::<Vertex>::new();
        let mut indices = Vec::<u16>::new();
        for segment in band.path.segments() {
            let first_new_vertex = vertices.len() as u16;
            let orth_direction = segment.direction().orthogonal();
            vertices.push(to_vertex(
                segment.start() + band.width_right * orth_direction,
                z,
            ));
            vertices.push(to_vertex(
                segment.start() - band.width_left * orth_direction,
                z,
            ));
            vertices.push(to_vertex(
                segment.end() + band.width_right * orth_direction,
                z,
            ));
            vertices.push(to_vertex(
                segment.end() - band.width_left * orth_direction,
                z,
            ));

            indices.extend_from_slice(&[
                first_new_vertex,
                first_new_vertex + 1,
                first_new_vertex + 2,
            ]);
            indices.extend_from_slice(&[
                first_new_vertex + 1,
                first_new_vertex + 3,
                first_new_vertex + 2,
            ]);
        }

        Mesh::new(vertices, indices)
    }
}

pub struct Batch {
    pub vertices: glium::VertexBuffer<Vertex>,
    pub indices: glium::IndexBuffer<u16>,
    pub instances: Vec<Instance>,
    pub clear_every_frame: bool,
    pub full_frame_instance_end: Option<usize>,
    pub is_decal: bool,
    pub frame: usize,
}

impl Batch {
    pub fn new(prototype: &Mesh, window: &Display) -> Batch {
        Batch {
            vertices: glium::VertexBuffer::new(window, &prototype.vertices).unwrap(),
            indices: glium::IndexBuffer::new(
                window,
                index::PrimitiveType::TrianglesList,
                &prototype.indices,
            ).unwrap(),
            instances: Vec::new(),
            full_frame_instance_end: None,
            clear_every_frame: true,
            is_decal: false,
            frame: 0,
        }
    }

    pub fn new_individual(
        mesh: &Mesh,
        instance: Instance,
        is_decal: bool,
        window: &Display,
    ) -> Batch {
        Batch {
            vertices: glium::VertexBuffer::new(window, &mesh.vertices).unwrap(),
            indices: glium::IndexBuffer::new(
                window,
                index::PrimitiveType::TrianglesList,
                &mesh.indices,
            ).unwrap(),
            instances: vec![instance],
            clear_every_frame: false,
            full_frame_instance_end: None,
            is_decal,
            frame: 0,
        }
    }
}
<commit_msg>fix band meshing<commit_after>pub use descartes::{N, P3, P2, V3, V4, M4, Iso3, Persp3, Into2d, Into3d, WithUniqueOrthogonal,
Area, Band};

use glium::{self, index};
use glium::backend::glutin::Display;

use compact::CVec;

#[derive(Copy, Clone, Debug)]
pub struct Vertex {
    pub position: [f32; 3],
}

implement_vertex!(Vertex, position);

#[derive(Copy, Clone)]
pub struct Instance {
    pub instance_position: [f32; 3],
    pub instance_direction: [f32; 2],
    pub instance_color: [f32; 3],
}

implement_vertex!(
    Instance,
    instance_position,
    instance_direction,
    instance_color
);

impl Instance {
    pub fn with_color(color: [f32; 3]) -> Instance {
        Instance {
            instance_position: [0.0, 0.0, 0.0],
            instance_direction: [1.0, 0.0],
            instance_color: color,
        }
    }
}

#[derive(Compact, Debug)]
pub struct Mesh {
    pub vertices: CVec<Vertex>,
    pub indices: CVec<u16>,
}

impl Mesh {
    pub fn new(vertices: Vec<Vertex>, indices: Vec<u16>) -> Mesh {
        Mesh {
            vertices: vertices.into(),
            indices: indices.into(),
        }
    }

    pub fn empty() -> Mesh {
        Mesh {
            vertices: CVec::new(),
            indices: CVec::new(),
        }
    }
}

impl Clone for Mesh {
    fn clone(&self) -> Mesh {
        Mesh {
            vertices: self.vertices.to_vec().into(),
            indices: self.indices.to_vec().into(),
        }
    }
}

impl ::std::ops::Add for Mesh {
    type Output = Mesh;

    fn add(mut self, rhs: Mesh) -> Mesh {
        let self_n_vertices = self.vertices.len();
        self.vertices.extend_from_copy_slice(&rhs.vertices);
        self.indices
            .extend(rhs.indices.iter().map(|i| *i + self_n_vertices as u16));
        self
    }
}

impl ::std::ops::AddAssign for Mesh {
    fn add_assign(&mut self, rhs: Mesh) {
        let self_n_vertices = self.vertices.len();
        for vertex in rhs.vertices.iter().cloned() {
            self.vertices.push(vertex);
        }
        for index in rhs.indices.iter() {
            self.indices.push(index + self_n_vertices as u16)
        }
    }
}

impl ::std::iter::Sum for Mesh {
    fn sum<I: Iterator<Item = Mesh>>(iter: I) -> Mesh {
        let mut summed_mesh = Mesh {
            vertices: CVec::new(),
            indices: CVec::new(),
        };
        for mesh in iter {
            summed_mesh += mesh;
        }
        summed_mesh
    }
}

impl<'a> ::std::ops::AddAssign<&'a Mesh> for Mesh {
    fn add_assign(&mut self, rhs: &'a Mesh) {
        let self_n_vertices = self.vertices.len();
        for vertex in rhs.vertices.iter().cloned() {
            self.vertices.push(vertex);
        }
        for index in rhs.indices.iter() {
            self.indices.push(index + self_n_vertices as u16)
        }
    }
}

impl<'a> ::std::iter::Sum<&'a Mesh> for Mesh {
    fn sum<I: Iterator<Item = &'a Mesh>>(iter: I) -> Mesh {
        let mut summed_mesh = Mesh {
            vertices: CVec::new(),
            indices: CVec::new(),
        };
        for mesh in iter {
            summed_mesh += mesh;
        }
        summed_mesh
    }
}

use itertools::{Itertools, Position};
use lyon_tessellation::{FillTessellator, FillOptions, FillVertex, GeometryBuilder};
use lyon_tessellation::geometry_builder::{VertexId, Count};
use lyon_tessellation::path::iterator::PathIter;
use lyon_tessellation::path::PathEvent;
use lyon_tessellation::math::point;

impl GeometryBuilder<FillVertex> for Mesh {
    fn begin_geometry(&mut self) {}
    fn end_geometry(&mut self) -> Count {
        Count {
            vertices: self.vertices.len() as u32,
            indices: self.indices.len() as u32,
        }
    }
    fn abort_geometry(&mut self) {}
    fn add_vertex(&mut self, input: FillVertex) -> VertexId {
        let id = self.vertices.len();
        self.vertices.push(Vertex {
            position: [input.position.x, input.position.y, 0.0],
        });
        VertexId(id as u16)
    }
    fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
        self.indices.push(a.0);
        self.indices.push(b.0);
        self.indices.push(c.0);
    }
}

impl Mesh {
    pub fn from_area(area: &Area) -> Mesh {
        let path_iterator = PathIter::new(area.primitives.iter().flat_map(|primitive| {
            primitive
                .boundary
                .path()
                .segments()
                .with_position()
                .flat_map(|segment_with_position| {
                    let initial_move = match segment_with_position {
                        Position::First(segment) | Position::Only(segment) => Some(
                            PathEvent::MoveTo(point(segment.start().x, segment.start().y)),
                        ),
                        _ => None,
                    };

                    let segment = segment_with_position.into_inner();

                    initial_move
                        .into_iter()
                        .chain(Some(PathEvent::LineTo(point(
                            segment.end().x,
                            segment.end().y,
                        ))))
                        .collect::<Vec<_>>()
                })
        }));

        let mut tesselator = FillTessellator::new();
        let mut output = Mesh::empty();

        tesselator
            .tessellate_path(path_iterator, &FillOptions::default(), &mut output)
            .unwrap();

        output
    }

    pub fn from_band(band: &Band, z: N) -> Mesh {
        fn to_vertex(point: P2, z: N) -> Vertex {
            Vertex {
                position: [point.x, point.y, z],
            }
        }

        let left = band
            .path
            .shift_orthogonally(-band.width_left)
            .unwrap_or_else(|| band.path.clone());
        let right = band
            .path
            .shift_orthogonally(band.width_right)
            .unwrap_or_else(|| band.path.clone());

        let vertices = left
            .points
            .iter()
            .chain(right.points.iter())
            .map(|&p| to_vertex(p, z))
            .collect::<Vec<_>>();

        let left_len = left.points.len();

        let indices = (0..(left_len - 1))
            .flat_map(|left_i| {
                let left_i = left_i as u16;
                let right_i = left_i + left_len as u16;

                vec![
                    left_i,
                    right_i.min(vertices.len() as u16 - 1),
                    left_i + 1,
                    left_i + 1,
                    right_i.min(vertices.len() as u16 - 1),
                    (right_i + 1).min(vertices.len() as u16 - 1),
                ]
            })
            .collect();

        Mesh::new(vertices, indices)
    }
}

pub struct Batch {
    pub vertices: glium::VertexBuffer<Vertex>,
    pub indices: glium::IndexBuffer<u16>,
    pub instances: Vec<Instance>,
    pub clear_every_frame: bool,
    pub full_frame_instance_end: Option<usize>,
    pub is_decal: bool,
    pub frame: usize,
}

impl Batch {
    pub fn new(prototype: &Mesh, window: &Display) -> Batch {
        Batch {
            vertices: glium::VertexBuffer::new(window, &prototype.vertices).unwrap(),
            indices: glium::IndexBuffer::new(
                window,
                index::PrimitiveType::TrianglesList,
                &prototype.indices,
            ).unwrap(),
            instances: Vec::new(),
            full_frame_instance_end: None,
            clear_every_frame: true,
            is_decal: false,
            frame: 0,
        }
    }

    pub fn new_individual(
        mesh: &Mesh,
        instance: Instance,
        is_decal: bool,
        window: &Display,
    ) -> Batch {
        Batch {
            vertices: glium::VertexBuffer::new(window, &mesh.vertices).unwrap(),
            indices: glium::IndexBuffer::new(
                window,
                index::PrimitiveType::TrianglesList,
                &mesh.indices,
            ).unwrap(),
            instances: vec![instance],
            clear_every_frame: false,
            full_frame_instance_end: None,
            is_decal,
            frame: 0,
        }
    }
}
<|endoftext|>


<commit_before>use async_trait::async_trait;
use crate::{
    ast::{Directive, FromInputValue, InputValue, Selection},
    value::{Object, ScalarRefValue, ScalarValue, Value},
};

use crate::{
    executor::{ExecutionResult, Executor},
    parser::Spanning,
};

use crate::BoxFuture;

use super::base::{is_excluded, merge_key_into, Arguments, GraphQLType};

#[async_trait]
pub trait GraphQLTypeAsync<S>: GraphQLType<S> + Send + Sync
where
    Self::Context: Send + Sync,
    Self::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    async fn resolve_field_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        field_name: &'a str,
        arguments: &'a Arguments<'a, S>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        panic!("resolve_field must be implemented by object types");
    }

    async fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> Value<S> {
        if let Some(selection_set) = selection_set {
            resolve_selection_set_into_async(self, info, selection_set, executor).await
        } else {
            panic!("resolve() must be implemented by non-object output types");
        }
    }

    async fn resolve_into_type_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        type_name: &str,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        if Self::name(info).unwrap() == type_name {
            Ok(self.resolve_async(info, selection_set, executor).await)
        } else {
            panic!("resolve_into_type_async must be implemented by unions and interfaces");
        }
    }
}

// Wrapper function around resolve_selection_set_into_async_recursive.
// This wrapper is necessary because async fns can not be recursive.
#[cfg(feature = "async")]
pub(crate) fn resolve_selection_set_into_async<'a, 'e, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'e [Selection<'e, S>],
    executor: &'e Executor<'e, CtxT, S>,
) -> BoxFuture<'a, Value<S>>
where
    T: GraphQLTypeAsync<S, Context = CtxT>,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    'e: 'a,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    Box::pin(resolve_selection_set_into_async_recursive(
        instance,
        info,
        selection_set,
        executor,
    ))
}

struct AsyncField<S> {
    name: String,
    value: Option<Value<S>>,
}

enum AsyncValue<S> {
    Field(AsyncField<S>),
    Nested(Value<S>),
}

#[cfg(feature = "async")]
pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'a [Selection<'a, S>],
    executor: &'a Executor<'a, CtxT, S>,
) -> Value<S>
where
    T: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    use futures::stream::{FuturesOrdered, StreamExt};

    let mut object = Object::with_capacity(selection_set.len());

    let mut async_values = FuturesOrdered::<BoxFuture<'a, AsyncValue<S>>>::new();

    let meta_type = executor
        .schema()
        .concrete_type_by_name(
            T::name(info)
                .expect("Resolving named type's selection set")
                .as_ref(),
        )
        .expect("Type not found in schema");

    for selection in selection_set {
        match *selection {
            Selection::Field(Spanning {
                item: ref f,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&f.directives, executor.variables()) {
                    continue;
                }

                let response_name = f.alias.as_ref().unwrap_or(&f.name).item;

                if f.name.item == "__typename" {
                    object.add_field(
                        response_name,
                        Value::scalar(instance.concrete_type_name(executor.context(), info)),
                    );
                    continue;
                }

                let meta_field = meta_type.field_by_name(f.name.item).unwrap_or_else(|| {
                    panic!(format!(
                        "Field {} not found on type {:?}",
                        f.name.item,
                        meta_type.name()
                    ))
                });

                let exec_vars = executor.variables();

                let sub_exec = executor.field_sub_executor(
                    &response_name,
                    f.name.item,
                    start_pos.clone(),
                    f.selection_set.as_ref().map(|v| &v[..]),
                );
                let args = Arguments::new(
                    f.arguments.as_ref().map(|m| {
                        m.item
                            .iter()
                            .map(|&(ref k, ref v)| (k.item, v.item.clone().into_const(exec_vars)))
                            .collect()
                    }),
                    &meta_field.arguments,
                );

                let pos = start_pos.clone();
                let is_non_null = meta_field.field_type.is_non_null();

                let response_name = response_name.to_string();
                let field_future = async move {
                    // TODO: implement custom future type instead of
                    //       two-level boxing.
                    let res = instance
                        .resolve_field_async(info, f.name.item, &args, &sub_exec)
                        .await;

                    let value = match res {
                        Ok(Value::Null) if is_non_null => None,
                        Ok(v) => Some(v),
                        Err(e) => {
                            sub_exec.push_error_at(e, pos);

                            if is_non_null {
                                None
                            } else {
                                Some(Value::null())
                            }
                        }
                    };
                    AsyncValue::Field(AsyncField {
                        name: response_name,
                        value,
                    })
                };
                async_values.push(Box::pin(field_future));
            }
            Selection::FragmentSpread(Spanning {
                item: ref spread, ..
            }) => {
                if is_excluded(&spread.directives, executor.variables()) {
                    continue;
                }

                // TODO: prevent duplicate boxing.
                let f = async move {
                    let fragment = &executor
                        .fragment_by_name(spread.name.item)
                        .expect("Fragment could not be found");
                    let value = resolve_selection_set_into_async(
                        instance,
                        info,
                        &fragment.selection_set[..],
                        executor,
                    )
                    .await;
                    AsyncValue::Nested(value)
                };
                async_values.push(Box::pin(f));
            }
            Selection::InlineFragment(Spanning {
                item: ref fragment,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&fragment.directives, executor.variables()) {
                    continue;
                }

                let sub_exec = executor.type_sub_executor(
                    fragment.type_condition.as_ref().map(|c| c.item),
                    Some(&fragment.selection_set[..]),
                );

                if let Some(ref type_condition) = fragment.type_condition {
                    // FIXME: implement async version.

                    let sub_result = instance.resolve_into_type_async(
                        info,
                        type_condition.item,
                        Some(&fragment.selection_set[..]),
                        &sub_exec,
                    ).await;

                    if let Ok(Value::Object(obj)) = sub_result {
                        for (k, v) in obj {
                            merge_key_into(&mut object, &k, v);
                        }
                    } else if let Err(e) = sub_result {
                        sub_exec.push_error_at(e, start_pos.clone());
                    }
                } else {
                    let f = async move {
                        let value = resolve_selection_set_into_async(
                            instance,
                            info,
                            &fragment.selection_set[..],
                            &sub_exec,
                        )
                        .await;
                        AsyncValue::Nested(value)
                    };
                    async_values.push(Box::pin(f));
                }
            }
        }
    }

    while let Some(item) = async_values.next().await {
        match item {
            AsyncValue::Field(AsyncField { name, value }) => {
                if let Some(value) = value {
                    object.add_field(&name, value);
                } else {
                    return Value::null();
                }
            }
            AsyncValue::Nested(obj) => match obj {
                v @ Value::Null => {
                    return v;
                }
                Value::Object(obj) => {
                    for (k, v) in obj {
                        merge_key_into(&mut object, &k, v);
                    }
                }
                _ => unreachable!(),
            },
        }
    }

    Value::Object(object)
}
<commit_msg>Remove useless todo<commit_after>use async_trait::async_trait;
use crate::{
    ast::{Directive, FromInputValue, InputValue, Selection},
    value::{Object, ScalarRefValue, ScalarValue, Value},
};

use crate::{
    executor::{ExecutionResult, Executor},
    parser::Spanning,
};

use crate::BoxFuture;

use super::base::{is_excluded, merge_key_into, Arguments, GraphQLType};

#[async_trait]
pub trait GraphQLTypeAsync<S>: GraphQLType<S> + Send + Sync
where
    Self::Context: Send + Sync,
    Self::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    async fn resolve_field_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        field_name: &'a str,
        arguments: &'a Arguments<'a, S>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        panic!("resolve_field must be implemented by object types");
    }

    async fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> Value<S> {
        if let Some(selection_set) = selection_set {
            resolve_selection_set_into_async(self, info, selection_set, executor).await
        } else {
            panic!("resolve() must be implemented by non-object output types");
        }
    }

    async fn resolve_into_type_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        type_name: &str,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        if Self::name(info).unwrap() == type_name {
            Ok(self.resolve_async(info, selection_set, executor).await)
        } else {
            panic!("resolve_into_type_async must be implemented by unions and interfaces");
        }
    }
}

// Wrapper function around resolve_selection_set_into_async_recursive.
// This wrapper is necessary because async fns can not be recursive.
#[cfg(feature = "async")]
pub(crate) fn resolve_selection_set_into_async<'a, 'e, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'e [Selection<'e, S>],
    executor: &'e Executor<'e, CtxT, S>,
) -> BoxFuture<'a, Value<S>>
where
    T: GraphQLTypeAsync<S, Context = CtxT>,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    'e: 'a,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    Box::pin(resolve_selection_set_into_async_recursive(
        instance,
        info,
        selection_set,
        executor,
    ))
}

struct AsyncField<S> {
    name: String,
    value: Option<Value<S>>,
}

enum AsyncValue<S> {
    Field(AsyncField<S>),
    Nested(Value<S>),
}

#[cfg(feature = "async")]
pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'a [Selection<'a, S>],
    executor: &'a Executor<'a, CtxT, S>,
) -> Value<S>
where
    T: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    use futures::stream::{FuturesOrdered, StreamExt};

    let mut object = Object::with_capacity(selection_set.len());

    let mut async_values = FuturesOrdered::<BoxFuture<'a, AsyncValue<S>>>::new();

    let meta_type = executor
        .schema()
        .concrete_type_by_name(
            T::name(info)
                .expect("Resolving named type's selection set")
                .as_ref(),
        )
        .expect("Type not found in schema");

    for selection in selection_set {
        match *selection {
            Selection::Field(Spanning {
                item: ref f,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&f.directives, executor.variables()) {
                    continue;
                }

                let response_name = f.alias.as_ref().unwrap_or(&f.name).item;

                if f.name.item == "__typename" {
                    object.add_field(
                        response_name,
                        Value::scalar(instance.concrete_type_name(executor.context(), info)),
                    );
                    continue;
                }

                let meta_field = meta_type.field_by_name(f.name.item).unwrap_or_else(|| {
                    panic!(format!(
                        "Field {} not found on type {:?}",
                        f.name.item,
                        meta_type.name()
                    ))
                });

                let exec_vars = executor.variables();

                let sub_exec = executor.field_sub_executor(
                    &response_name,
                    f.name.item,
                    start_pos.clone(),
                    f.selection_set.as_ref().map(|v| &v[..]),
                );
                let args = Arguments::new(
                    f.arguments.as_ref().map(|m| {
                        m.item
                            .iter()
                            .map(|&(ref k, ref v)| (k.item, v.item.clone().into_const(exec_vars)))
                            .collect()
                    }),
                    &meta_field.arguments,
                );

                let pos = start_pos.clone();
                let is_non_null = meta_field.field_type.is_non_null();

                let response_name = response_name.to_string();
                let field_future = async move {
                    // TODO: implement custom future type instead of
                    //       two-level boxing.
                    let res = instance
                        .resolve_field_async(info, f.name.item, &args, &sub_exec)
                        .await;

                    let value = match res {
                        Ok(Value::Null) if is_non_null => None,
                        Ok(v) => Some(v),
                        Err(e) => {
                            sub_exec.push_error_at(e, pos);

                            if is_non_null {
                                None
                            } else {
                                Some(Value::null())
                            }
                        }
                    };
                    AsyncValue::Field(AsyncField {
                        name: response_name,
                        value,
                    })
                };
                async_values.push(Box::pin(field_future));
            }
            Selection::FragmentSpread(Spanning {
                item: ref spread, ..
            }) => {
                if is_excluded(&spread.directives, executor.variables()) {
                    continue;
                }

                // TODO: prevent duplicate boxing.
                let f = async move {
                    let fragment = &executor
                        .fragment_by_name(spread.name.item)
                        .expect("Fragment could not be found");
                    let value = resolve_selection_set_into_async(
                        instance,
                        info,
                        &fragment.selection_set[..],
                        executor,
                    )
                    .await;
                    AsyncValue::Nested(value)
                };
                async_values.push(Box::pin(f));
            }
            Selection::InlineFragment(Spanning {
                item: ref fragment,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&fragment.directives, executor.variables()) {
                    continue;
                }

                let sub_exec = executor.type_sub_executor(
                    fragment.type_condition.as_ref().map(|c| c.item),
                    Some(&fragment.selection_set[..]),
                );

                if let Some(ref type_condition) = fragment.type_condition {
                    let sub_result = instance.resolve_into_type_async(
                        info,
                        type_condition.item,
                        Some(&fragment.selection_set[..]),
                        &sub_exec,
                    ).await;

                    if let Ok(Value::Object(obj)) = sub_result {
                        for (k, v) in obj {
                            merge_key_into(&mut object, &k, v);
                        }
                    } else if let Err(e) = sub_result {
                        sub_exec.push_error_at(e, start_pos.clone());
                    }
                } else {
                    let f = async move {
                        let value = resolve_selection_set_into_async(
                            instance,
                            info,
                            &fragment.selection_set[..],
                            &sub_exec,
                        )
                        .await;
                        AsyncValue::Nested(value)
                    };
                    async_values.push(Box::pin(f));
                }
            }
        }
    }

    while let Some(item) = async_values.next().await {
        match item {
            AsyncValue::Field(AsyncField { name, value }) => {
                if let Some(value) = value {
                    object.add_field(&name, value);
                } else {
                    return Value::null();
                }
            }
            AsyncValue::Nested(obj) => match obj {
                v @ Value::Null => {
                    return v;
                }
                Value::Object(obj) => {
                    for (k, v) in obj {
                        merge_key_into(&mut object, &k, v);
                    }
                }
                _ => unreachable!(),
            },
        }
    }

    Value::Object(object)
}
<|endoftext|>


<commit_before>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! The Ferragina-Mancini Index for finding suffix array intervals matching a given pattern.

use std::iter::DoubleEndedIterator;

use data_structures::bwt::{Occ, Less, less, BWT};
use data_structures::suffix_array::SuffixArray;
use alphabets::{Alphabet, dna};
use std::mem::swap;

#[derive(Copy)]
pub struct Interval {
    lower: usize,
    upper: usize
}

impl Interval {
    /// Return the occurrence positions of the pattern as a slice of the suffix array.
    pub fn occ<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        &pos[self.lower..self.upper + 1]
    }
}

pub struct FMIndex<'a> {
    bwt: &'a BWT,
    less: Less,
    occ: Occ
}

impl<'a> FMIndex<'a> {
    /// Construct a new instance of the FM index.
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate of the occ array: every k-th entry will be stored (higher k means
    ///   less memory usage, but worse performance)
    /// * `alphabet` - the alphabet of the underlying text, omitting the sentinel
    pub fn new(bwt: &'a BWT, k: usize, alphabet: &Alphabet) -> Self {
        FMIndex { bwt: bwt, less: less(bwt, alphabet), occ: Occ::new(bwt, k, alphabet)}
    }

    /// Perform backward search, yielding suffix array
    /// interval denoting exact occurences of the given pattern of length m in the text.
    /// Complexity: O(m).
    ///
    /// # Arguments
    ///
    /// * `pattern` - the pattern to search
    ///
    /// # Example
    ///
    /// ```
    /// use bio::data_structures::bwt::bwt;
    /// use bio::data_structures::fmindex::FMIndex;
    /// use bio::data_structures::suffix_array::suffix_array;
    /// use bio::alphabets::dna;
    ///
    /// let text = b"GCCTTAACATTATTACGCCTA$";
    /// let alphabet = dna::alphabet();
    /// let pos = suffix_array(text);
    /// let bwt = bwt(text, &pos);
    /// let fm = FMIndex::new(&bwt, 3, &alphabet);
    ///
    /// let pattern = b"TTA";
    /// let sai = fm.backward_search(pattern.iter());
    ///
    /// let occ = sai.occ(&pos);
    ///
    /// assert_eq!(occ, [3, 12, 9]);
    /// ```
    pub fn backward_search<'b, P: Iterator<Item=&'b u8> + DoubleEndedIterator>(&self, pattern: P) -> Interval {
        let (mut l, mut r) = (0, self.bwt.len() - 1);
        for &a in pattern.rev() {
            let less = self.less(a);
            l = less + if l > 0 { self.occ(l - 1, a) } else { 0 };
            r = less + self.occ(r, a) - 1;
        }

        Interval { lower: l, upper: r }
    }

    fn occ(&self, r: usize, a: u8) -> usize {
        self.occ.get(self.bwt, r, a)
    }

    fn less(&self, a: u8) -> usize {
        self.less[a as usize]
    }
}

#[derive(Copy)]
#[derive(Debug)]
pub struct BiInterval {
    lower: usize,
    lower_rev: usize,
    size: usize,
    match_size: usize,
}

impl BiInterval {
    /// Return the occurrence positions of the pattern as a slice of the suffix array.
    pub fn occ<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        self._pos(pos, self.lower)
    }

    /// Return the occurrence positions of the reverse complement of the pattern as a slice of the suffix array.
    pub fn occ_revcomp<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        self._pos(pos, self.lower_rev)
    }

    fn _pos<'a>(&self, pos: &'a SuffixArray, lower: usize) -> &'a [usize] {
        &pos[lower..lower + self.size]
    }

    fn swapped(&self) -> BiInterval {
        BiInterval {
            lower: self.lower_rev,
            lower_rev: self.lower,
            size: self.size,
            match_size: self.match_size
        }
    }
}

pub struct FMDIndex<'a> {
    fmindex: FMIndex<'a>,
    revcomp: dna::RevComp,
    interval_buffer: [BiInterval; 256],
}

impl<'a> FMDIndex<'a> {
    /// Construct a new instance of the FMD index (see Heng Li (2012) Bioinformatics).
    /// This expects a BWT that was created from a text over the DNA alphabet
    /// (ACGTN) consisting of the
    /// concatenation with its reverse complement, separated by the sentinel symbol `$`.
    /// I.e., let T be the original text and R be its reverse complement.
    /// Then, the expected text is T$R$. Further, multiple concatenated texts are allowed, e.g.
    /// T1$R1$T2$R2$T3$R3$.
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate of the occ array: every k-th entry will be stored (higher k means
    ///   less memory usage, but worse performance)
    pub fn new(bwt: &'a BWT, k: usize) -> Self {
        let alphabet = Alphabet::new(b"$ACGTN");
        assert!(
            alphabet.is_word(bwt),
            "Expecting BWT over the DNA alphabet (including N) with the sentinel $."
        );

        FMDIndex {
            fmindex: FMIndex::new(bwt, k, &alphabet),
            revcomp: dna::RevComp::new(),
            interval_buffer: [BiInterval { lower: 0, lower_rev: 0, size: 0, match_size: 0 }; 256]
        }
    }

    /// Find supermaximal exact matches of given pattern overlapping position i.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::data_structures::fmindex::FMDIndex;
    /// use bio::data_structures::suffix_array::suffix_array;
    /// use bio::data_structures::bwt::bwt;
    ///
    /// let text = b"ATTC$GAAT$";
    /// let pos = suffix_array(text);
    /// let bwt = bwt(text, &pos);
    /// let mut fmdindex = FMDIndex::new(&bwt, 3);
    ///
    /// let pattern = b"ATT";
    /// let intervals = fmdindex.smems(pattern, 2);
    /// let occ = intervals[0].occ(&pos);
    /// let occ_revcomp = intervals[0].occ_revcomp(&pos);
    ///
    /// assert_eq!(occ, [0]);
    /// assert_eq!(occ_revcomp, [6]);
    /// ```
    pub fn smems(&mut self, pattern: &[u8], i: usize) -> Vec<BiInterval> {

        let curr = &mut Vec::new();
        let prev = &mut Vec::new();
        let mut matches = Vec::new();

        let mut interval = self.init_interval(pattern, i);

        for &a in pattern[i+1..].iter() {
            let _interval = self.forward_ext(&interval, a);

            if interval.size != _interval.size {
                curr.push(interval);
            }
            if _interval.size == 0 {
                break;
            }
            interval = _interval;
        }
        curr.push(interval);
        println!("{:?}", curr);

        swap(curr, prev);
        let mut j = pattern.len() as isize;

        for k in (-1..i as isize).rev() {
            let a = if k == -1 { b'$' } else { pattern[k as usize] };
            curr.clear();
            let mut s = -1;
            // iterate over forward extensions in reverse, as they are sorted by size
            // and we want longer matches first
            for &interval in prev.iter().rev() {
                let _interval = self.backward_ext(&interval, a);

                if _interval.size == 0 || k == -1 {
                    if curr.is_empty() && k < j {
                        j = k;
                        matches.push(interval);
                    }
                }
                // add _interval to curr (will be further extended next iteration
                if _interval.size != 0 && _interval.size != s {
                    s = _interval.size;
                    curr.push(_interval);
                }
            }
            if curr.is_empty() {
                break;
            }
            swap(curr, prev);
        }

        matches
    }

    fn init_interval(&self, pattern: &[u8], i: usize) -> BiInterval {
        let a = pattern[i];
        let _a = self.revcomp.comp(a);
        let lower = self.fmindex.less(a);

        BiInterval {
            lower: lower,
            lower_rev: self.fmindex.less(_a),
            size: self.fmindex.less(a + 1) - lower,
            match_size: 1,
        }
    }

    fn backward_ext(&mut self, interval: &BiInterval, a: u8) -> BiInterval {
        // calculate lower bound and size for all symbols
        for &b in b"$ACGTN".iter() {
            let o = self.fmindex.occ(interval.lower - 1, b);
            let b_interval = &mut self.interval_buffer[b as usize];
            b_interval.lower = self.fmindex.less(b) + o;
            b_interval.size = self.fmindex.occ(interval.lower + interval.size - 1, b) - o;
        }

        // calculate lower revcomp bounds
        {
            let sentinel_interval = &mut self.interval_buffer[b'$' as usize];
            sentinel_interval.lower_rev = interval.lower_rev;
        }

        let mut last = b'$' as usize;
        for &b in b"TGCAN".iter() {
            self.interval_buffer[b as usize].lower_rev = self.interval_buffer[last].lower_rev + self.interval_buffer[last].size;
            last = b as usize;
        }

        let mut ret = self.interval_buffer[a as usize];
        ret.match_size = interval.match_size + 1;

        ret
    }

    fn forward_ext(&mut self, interval: &BiInterval, a: u8) -> BiInterval {
        let _a = self.revcomp.comp(a);

        self.backward_ext(
            &interval.swapped(),
            _a
        ).swapped()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use alphabets::dna;
    use data_structures::suffix_array::suffix_array;
    use data_structures::bwt::bwt;

    #[test]
    fn test_smems() {
        let revcomp = dna::RevComp::new();
        let orig_text = b"GCCTTAACAT";
        let text = [orig_text, b"$", revcomp.get(orig_text).as_slice(), b"$"].concat();
        let pos = suffix_array(text.as_slice());
        println!("pos {:?}", pos);
        println!("text {:?}", text);
        let bwt = bwt(text.as_slice(), &pos);
        let mut fmdindex = FMDIndex::new(&bwt, 3);
        {
            let pattern = b"AA";
            let intervals = fmdindex.smems(pattern, 0);
            assert_eq!(intervals[0].occ(&pos), [5, 16]);
            assert_eq!(intervals[0].occ_revcomp(&pos), [3, 14]);
        }
        {
            let pattern = b"CTTAA";
            let intervals = fmdindex.smems(pattern, 1);
            assert_eq!(intervals[0].occ(&pos), [2]);
            assert_eq!(intervals[0].occ_revcomp(&pos), [14]);
            assert_eq!(intervals[0].match_size, 5)
        }
    }

    #[test]
    fn test_init_interval() {
        let text = b"ACGT$TGCA$";
        let pos = suffix_array(text);
        let bwt = bwt(text, &pos);
        let fmdindex = FMDIndex::new(&bwt, 3);
        let pattern = b"T";
        let interval = fmdindex.init_interval(pattern, 0);
        assert_eq!(interval.occ(&pos), [3, 5]);
        assert_eq!(interval.occ_revcomp(&pos), [8, 0]);
    }
}
<commit_msg>Simplified backward extension.<commit_after>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! The Ferragina-Mancini Index for finding suffix array intervals matching a given pattern.

use std::iter::DoubleEndedIterator;

use data_structures::bwt::{Occ, Less, less, BWT};
use data_structures::suffix_array::SuffixArray;
use alphabets::{Alphabet, dna};
use std::mem::swap;

#[derive(Copy)]
pub struct Interval {
    lower: usize,
    upper: usize
}

impl Interval {
    /// Return the occurrence positions of the pattern as a slice of the suffix array.
    pub fn occ<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        &pos[self.lower..self.upper + 1]
    }
}

pub struct FMIndex<'a> {
    bwt: &'a BWT,
    less: Less,
    occ: Occ
}

impl<'a> FMIndex<'a> {
    /// Construct a new instance of the FM index.
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate of the occ array: every k-th entry will be stored (higher k means
    ///   less memory usage, but worse performance)
    /// * `alphabet` - the alphabet of the underlying text, omitting the sentinel
    pub fn new(bwt: &'a BWT, k: usize, alphabet: &Alphabet) -> Self {
        FMIndex { bwt: bwt, less: less(bwt, alphabet), occ: Occ::new(bwt, k, alphabet)}
    }

    /// Perform backward search, yielding suffix array
    /// interval denoting exact occurences of the given pattern of length m in the text.
    /// Complexity: O(m).
    ///
    /// # Arguments
    ///
    /// * `pattern` - the pattern to search
    ///
    /// # Example
    ///
    /// ```
    /// use bio::data_structures::bwt::bwt;
    /// use bio::data_structures::fmindex::FMIndex;
    /// use bio::data_structures::suffix_array::suffix_array;
    /// use bio::alphabets::dna;
    ///
    /// let text = b"GCCTTAACATTATTACGCCTA$";
    /// let alphabet = dna::alphabet();
    /// let pos = suffix_array(text);
    /// let bwt = bwt(text, &pos);
    /// let fm = FMIndex::new(&bwt, 3, &alphabet);
    ///
    /// let pattern = b"TTA";
    /// let sai = fm.backward_search(pattern.iter());
    ///
    /// let occ = sai.occ(&pos);
    ///
    /// assert_eq!(occ, [3, 12, 9]);
    /// ```
    pub fn backward_search<'b, P: Iterator<Item=&'b u8> + DoubleEndedIterator>(&self, pattern: P) -> Interval {
        let (mut l, mut r) = (0, self.bwt.len() - 1);
        for &a in pattern.rev() {
            let less = self.less(a);
            l = less + if l > 0 { self.occ(l - 1, a) } else { 0 };
            r = less + self.occ(r, a) - 1;
        }

        Interval { lower: l, upper: r }
    }

    fn occ(&self, r: usize, a: u8) -> usize {
        self.occ.get(self.bwt, r, a)
    }

    fn less(&self, a: u8) -> usize {
        self.less[a as usize]
    }
}

#[derive(Copy)]
#[derive(Debug)]
pub struct BiInterval {
    lower: usize,
    lower_rev: usize,
    size: usize,
    match_size: usize,
}

impl BiInterval {
    /// Return the occurrence positions of the pattern as a slice of the suffix array.
    pub fn occ<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        self._pos(pos, self.lower)
    }

    /// Return the occurrence positions of the reverse complement of the pattern as a slice of the suffix array.
    pub fn occ_revcomp<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        self._pos(pos, self.lower_rev)
    }

    fn _pos<'a>(&self, pos: &'a SuffixArray, lower: usize) -> &'a [usize] {
        &pos[lower..lower + self.size]
    }

    fn swapped(&self) -> BiInterval {
        BiInterval {
            lower: self.lower_rev,
            lower_rev: self.lower,
            size: self.size,
            match_size: self.match_size
        }
    }
}

pub struct FMDIndex<'a> {
    fmindex: FMIndex<'a>,
    revcomp: dna::RevComp,
}

impl<'a> FMDIndex<'a> {
    /// Construct a new instance of the FMD index (see Heng Li (2012) Bioinformatics).
    /// This expects a BWT that was created from a text over the DNA alphabet
    /// (ACGTN) consisting of the
    /// concatenation with its reverse complement, separated by the sentinel symbol `$`.
    /// I.e., let T be the original text and R be its reverse complement.
    /// Then, the expected text is T$R$. Further, multiple concatenated texts are allowed, e.g.
    /// T1$R1$T2$R2$T3$R3$.
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate of the occ array: every k-th entry will be stored (higher k means
    ///   less memory usage, but worse performance)
    pub fn new(bwt: &'a BWT, k: usize) -> Self {
        let alphabet = Alphabet::new(b"$ACGTN");
        assert!(
            alphabet.is_word(bwt),
            "Expecting BWT over the DNA alphabet (including N) with the sentinel $."
        );

        FMDIndex {
            fmindex: FMIndex::new(bwt, k, &alphabet),
            revcomp: dna::RevComp::new()
        }
    }

    /// Find supermaximal exact matches of given pattern overlapping position i.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::data_structures::fmindex::FMDIndex;
    /// use bio::data_structures::suffix_array::suffix_array;
    /// use bio::data_structures::bwt::bwt;
    ///
    /// let text = b"ATTC$GAAT$";
    /// let pos = suffix_array(text);
    /// let bwt = bwt(text, &pos);
    /// let fmdindex = FMDIndex::new(&bwt, 3);
    ///
    /// let pattern = b"ATT";
    /// let intervals = fmdindex.smems(pattern, 2);
    /// let occ = intervals[0].occ(&pos);
    /// let occ_revcomp = intervals[0].occ_revcomp(&pos);
    ///
    /// assert_eq!(occ, [0]);
    /// assert_eq!(occ_revcomp, [6]);
    /// ```
    pub fn smems(&self, pattern: &[u8], i: usize) -> Vec<BiInterval> {

        let curr = &mut Vec::new();
        let prev = &mut Vec::new();
        let mut matches = Vec::new();

        let mut interval = self.init_interval(pattern, i);

        for &a in pattern[i+1..].iter() {
            let _interval = self.forward_ext(&interval, a);

            if interval.size != _interval.size {
                curr.push(interval);
            }
            if _interval.size == 0 {
                break;
            }
            interval = _interval;
        }
        curr.push(interval);
        println!("{:?}", curr);

        swap(curr, prev);
        let mut j = pattern.len() as isize;

        for k in (-1..i as isize).rev() {
            let a = if k == -1 { b'$' } else { pattern[k as usize] };
            curr.clear();
            let mut s = -1;
            // iterate over forward extensions in reverse, as they are sorted by size
            // and we want longer matches first
            for &interval in prev.iter().rev() {
                let _interval = self.backward_ext(&interval, a);

                if _interval.size == 0 || k == -1 {
                    if curr.is_empty() && k < j {
                        j = k;
                        matches.push(interval);
                    }
                }
                // add _interval to curr (will be further extended next iteration
                if _interval.size != 0 && _interval.size != s {
                    s = _interval.size;
                    curr.push(_interval);
                }
            }
            if curr.is_empty() {
                break;
            }
            swap(curr, prev);
        }

        matches
    }

    fn init_interval(&self, pattern: &[u8], i: usize) -> BiInterval {
        let a = pattern[i];
        let _a = self.revcomp.comp(a);
        let lower = self.fmindex.less(a);

        BiInterval {
            lower: lower,
            lower_rev: self.fmindex.less(_a),
            size: self.fmindex.less(a + 1) - lower,
            match_size: 1,
        }
    }

    fn backward_ext(&self, interval: &BiInterval, a: u8) -> BiInterval {
        let mut k = 0;
        let mut s = 0;
        let mut l = interval.lower_rev;
        for &b in b"$TGCAN".iter() {
            l = l + s;
            let o = self.fmindex.occ(interval.lower - 1, b);
            k = self.fmindex.less(b) + o;
            s = self.fmindex.occ(interval.lower + interval.size - 1, b) - o;
            if b == a {
                break;
            }
        }

        BiInterval {
            lower: k,
            lower_rev: l,
            size: s,
            match_size: interval.match_size + 1
        }
    }

    fn forward_ext(&self, interval: &BiInterval, a: u8) -> BiInterval {
        let _a = self.revcomp.comp(a);

        self.backward_ext(
            &interval.swapped(),
            _a
        ).swapped()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use alphabets::dna;
    use data_structures::suffix_array::suffix_array;
    use data_structures::bwt::bwt;

    #[test]
    fn test_smems() {
        let revcomp = dna::RevComp::new();
        let orig_text = b"GCCTTAACAT";
        let text = [orig_text, b"$", revcomp.get(orig_text).as_slice(), b"$"].concat();
        let pos = suffix_array(text.as_slice());
        println!("pos {:?}", pos);
        println!("text {:?}", text);
        let bwt = bwt(text.as_slice(), &pos);
        let fmdindex = FMDIndex::new(&bwt, 3);
        {
            let pattern = b"AA";
            let intervals = fmdindex.smems(pattern, 0);
            assert_eq!(intervals[0].occ(&pos), [5, 16]);
            assert_eq!(intervals[0].occ_revcomp(&pos), [3, 14]);
        }
        {
            let pattern = b"CTTAA";
            let intervals = fmdindex.smems(pattern, 1);
            assert_eq!(intervals[0].occ(&pos), [2]);
            assert_eq!(intervals[0].occ_revcomp(&pos), [14]);
            assert_eq!(intervals[0].match_size, 5)
        }
    }

    #[test]
    fn test_init_interval() {
        let text = b"ACGT$TGCA$";
        let pos = suffix_array(text);
        let bwt = bwt(text, &pos);
        let fmdindex = FMDIndex::new(&bwt, 3);
        let pattern = b"T";
        let interval = fmdindex.init_interval(pattern, 0);
        assert_eq!(interval.occ(&pos), [3, 5]);
        assert_eq!(interval.occ_revcomp(&pos), [8, 0]);
    }
}
<|endoftext|>


<commit_before>mod db_list;
pub use self::db_list::*;
mod changes;
pub use self::changes::*;
mod db_create;
pub use self::db_create::*;
mod db_drop;
pub use self::db_drop::*;
mod table_create;
pub use self::table_create::*;
mod table_drop;
pub use self::table_drop::*;
mod table_list;
pub use self::table_list::*;
mod index_create;
pub use self::index_create::*;
mod index_drop;
pub use self::index_drop::*;
mod index_list;
pub use self::index_list::*;
mod index_rename;
pub use self::index_rename::*;
mod index_status;
pub use self::index_status::*;
mod index_wait;
pub use self::index_wait::*;
mod insert;
pub use self::insert::*;
mod update;
pub use self::update::*;
mod replace;
pub use self::replace::*;
mod delete;
pub use self::delete::*;
mod sync;
pub use self::sync::*;
mod db;
pub use self::db::*;
mod table;
pub use self::table::*;
mod get;
pub use self::get::*;
mod get_all;
pub use self::get_all::*;
mod between;
pub use self::between::*;
mod filter;
pub use self::filter::*;
mod inner_join;
pub use self::inner_join::*;
mod outer_join;
pub use self::outer_join::*;
mod eq_join;
pub use self::eq_join::*;
mod zip;
pub use self::zip::*;
mod map;
pub use self::map::*;
mod with_fields;
pub use self::with_fields::*;
mod concat_map;
pub use self::concat_map::*;
mod order_by;
pub use self::order_by::*;
mod skip;
pub use self::skip::*;
mod limit;
pub use self::limit::*;
mod slice;
pub use self::slice::*;
mod nth;
pub use self::nth::*;
mod offsets_of;
pub use self::offsets_of::*;
mod is_empty;
pub use self::is_empty::*;
mod union;
pub use self::union::*;
mod sample;
pub use self::union::*;
mod group;
pub use self::group::*;
mod ungroup;
pub use self::ungroup::*;
mod reduce;
pub use self::reduce::*;
mod fold;
pub use self::fold::*;
mod count;
pub use self::count::*;
mod sum;
pub use self::sum::*;
mod avg;
pub use self::avg::*;
mod min;
pub use self::min::*;
mod max;
pub use self::max::*;
mod distinct;
pub use self::distinct::*;
mod contains;
pub use self::contains::*;
mod pluck;
pub use self::pluck::*;
mod without;
pub use self::without::*;
mod merge;
pub use self::merge::*;
mod append;
pub use self::append::*;
mod prepend;
pub use self::prepend::*;
mod difference;
pub use self::difference::*;
mod set_insert;
pub use self::set_insert::*;
mod set_union;
pub use self::set_union::*;
mod set_intersection;
pub use self::set_intersection::*;
mod set_difference;
pub use self::set_difference::*;
mod get_field;
pub use self::get_field::*;
mod has_fields;
pub use self::has_fields::*;
mod insert_at;
pub use self::insert_at::*;
mod splice_at;
pub use self::splice_at::*;
mod delete_at;
pub use self::delete_at::*;
mod change_at;
pub use self::change_at::*;
mod keys;
pub use self::keys::*;
mod values;
pub use self::values::*;
mod literal;
pub use self::literal::*;
<commit_msg>Disable unused import warnings in derived code<commit_after>// @TODO: remove this once https://github.com/dtolnay/syn/issues/76 is addressed
#![allow(unused_imports)]

mod db_list;
pub use self::db_list::*;
mod changes;
pub use self::changes::*;
mod db_create;
pub use self::db_create::*;
mod db_drop;
pub use self::db_drop::*;
mod table_create;
pub use self::table_create::*;
mod table_drop;
pub use self::table_drop::*;
mod table_list;
pub use self::table_list::*;
mod index_create;
pub use self::index_create::*;
mod index_drop;
pub use self::index_drop::*;
mod index_list;
pub use self::index_list::*;
mod index_rename;
pub use self::index_rename::*;
mod index_status;
pub use self::index_status::*;
mod index_wait;
pub use self::index_wait::*;
mod insert;
pub use self::insert::*;
mod update;
pub use self::update::*;
mod replace;
pub use self::replace::*;
mod delete;
pub use self::delete::*;
mod sync;
pub use self::sync::*;
mod db;
pub use self::db::*;
mod table;
pub use self::table::*;
mod get;
pub use self::get::*;
mod get_all;
pub use self::get_all::*;
mod between;
pub use self::between::*;
mod filter;
pub use self::filter::*;
mod inner_join;
pub use self::inner_join::*;
mod outer_join;
pub use self::outer_join::*;
mod eq_join;
pub use self::eq_join::*;
mod zip;
pub use self::zip::*;
mod map;
pub use self::map::*;
mod with_fields;
pub use self::with_fields::*;
mod concat_map;
pub use self::concat_map::*;
mod order_by;
pub use self::order_by::*;
mod skip;
pub use self::skip::*;
mod limit;
pub use self::limit::*;
mod slice;
pub use self::slice::*;
mod nth;
pub use self::nth::*;
mod offsets_of;
pub use self::offsets_of::*;
mod is_empty;
pub use self::is_empty::*;
mod union;
pub use self::union::*;
mod sample;
pub use self::union::*;
mod group;
pub use self::group::*;
mod ungroup;
pub use self::ungroup::*;
mod reduce;
pub use self::reduce::*;
mod fold;
pub use self::fold::*;
mod count;
pub use self::count::*;
mod sum;
pub use self::sum::*;
mod avg;
pub use self::avg::*;
mod min;
pub use self::min::*;
mod max;
pub use self::max::*;
mod distinct;
pub use self::distinct::*;
mod contains;
pub use self::contains::*;
mod pluck;
pub use self::pluck::*;
mod without;
pub use self::without::*;
mod merge;
pub use self::merge::*;
mod append;
pub use self::append::*;
mod prepend;
pub use self::prepend::*;
mod difference;
pub use self::difference::*;
mod set_insert;
pub use self::set_insert::*;
mod set_union;
pub use self::set_union::*;
mod set_intersection;
pub use self::set_intersection::*;
mod set_difference;
pub use self::set_difference::*;
mod get_field;
pub use self::get_field::*;
mod has_fields;
pub use self::has_fields::*;
mod insert_at;
pub use self::insert_at::*;
mod splice_at;
pub use self::splice_at::*;
mod delete_at;
pub use self::delete_at::*;
mod change_at;
pub use self::change_at::*;
mod keys;
pub use self::keys::*;
mod values;
pub use self::values::*;
mod literal;
pub use self::literal::*;
<|endoftext|>


<commit_before>use float::round;
use libc::types::os::arch::c95::c_double;
use css_colors::*;
use cmp::Eq;

pub enum Color = {red : u8, green : u8, blue : u8, alpha : float};

impl Color : Eq {
    pure fn eq(other: &Color) -> bool {
        return self.red == other.red && self.green == other.green && self.blue == other.blue &&
               self.alpha == other.alpha;
    }
    pure fn ne(other: &Color) -> bool {
        !self.eq(other)
    }
}

pub fn rgba(r : u8, g : u8, b : u8, a : float) -> Color {
    Color({red : r, green : g, blue : b, alpha : a})
}

pub fn rgb(r : u8, g : u8, b : u8) -> Color {
    return rgba(r, g, b, 1.0);
}

pub fn hsla(h : float, s : float, l : float, a : float) -> Color {
    // Algorithm for converting hsl to rbg taken from
    // http://www.w3.org/TR/2003/CR-css3-color-20030514/#hsl-color
    let m2 = if l <= 0.5 { l*(s + 1.0) } else { l + s - l*s };
    let m1 = l*2.0 - m2;
    let h = h / 360.0;

    fn hue_to_rgb(m1 : float, m2 : float, h : float) -> float {
        let h = if h < 0.0 { h + 1.0 } else if h > 1.0 { h - 1.0 } else { h };

        match h {
          0.0 .. 1.0/6.0 => m1 + (m2 - m1)*h*6.0,
          1.0/6.0 .. 1.0/2.0 => m2,
          1.0/2.0 .. 2.0/3.0 => m1 + (m2 - m1)*(4.0 - 6.0*h),
          2.0/3.0 .. 1.0 => return m1,
          _ => fail ~"unexpected hue value"
        }
    }

    let r = round(255.0*hue_to_rgb(m1, m2, h + 1.0/3.0) as c_double);;
    let g = round(255.0*hue_to_rgb(m1, m2, h) as c_double);
    let b = round(255.0*hue_to_rgb(m1, m2, h - 1.0/3.0) as c_double);

    return rgba(r as u8, g as u8, b as u8, a);
}

pub fn hsl(h : float, s : float, l : float) -> Color {
    return hsla(h, s, l, 1.0);
}

impl Color {
    fn print() -> ~str {
        fmt!("rgba(%u,%u,%u,%f)", self.red as uint, self.green as uint,
             self.blue as uint, self.alpha)
    }
}

pub mod parsing {
    export parse_color;

    fn fail_unrecognized(col : &str) -> Option<Color> {
        warn!("Unrecognized color %s", col);
        return None;
    }

    /** Match an exact color keyword. */
    fn parse_by_name(color : &str) -> Option<Color> {
        let col = match color.to_lower() {
          ~"black" => black(),
          ~"silver" => silver(),
          ~"gray" => gray(),
          ~"grey" => gray(),
          ~"white" => white(),
          ~"maroon" => maroon(),
          ~"red" => red(),
          ~"purple" => purple(),
          ~"fuchsia" => fuchsia(),
          ~"green" => green(),
          ~"lime" => lime(),
          ~"olive" => olive(),
          ~"yellow" => yellow(),
          ~"navy" => navy(),
          ~"blue" => blue(),
          ~"teal" => teal(),
          ~"aqua" => aqua(),
          _ => return fail_unrecognized(color)
        };

        return Some(col);
    }

    /** Parses a color specification in the form rgb(foo,bar,baz) */
    fn parse_rgb(color : &str) -> Option<Color> {
        // Shave off the rgb( and the )
        let only_colors = color.substr(4u, color.len() - 5u);

        // split up r, g, and b
        let cols = only_colors.split_char(',');
        if cols.len() != 3u { return fail_unrecognized(color); }

        match (u8::from_str(cols[0]), u8::from_str(cols[1]),
             u8::from_str(cols[2])) {
          (Some(r), Some(g), Some(b)) => { Some(rgb(r, g, b)) }
          _ => { fail_unrecognized(color) }
        }
    }

    /** Parses a color specification in the form rgba(foo,bar,baz,qux) */
    fn parse_rgba(color : &str) -> Option<Color> {
        // Shave off the rgba( and the )
        let only_vals = color.substr(5u, color.len() - 6u);

        // split up r, g, and b
        let cols = only_vals.split_char(',');
        if cols.len() != 4u { return fail_unrecognized(color); }

        match (u8::from_str(cols[0]), u8::from_str(cols[1]),
             u8::from_str(cols[2]), float::from_str(cols[3])) {
          (Some(r), Some(g), Some(b), Some(a)) => { Some(rgba(r, g, b, a)) }
          _ => { fail_unrecognized(color) }
        }
    }

    /** Parses a color specification in the form hsl(foo,bar,baz) */
    fn parse_hsl(color : &str) -> Option<Color> {
        // Shave off the hsl( and the )
        let only_vals = color.substr(4u, color.len() - 5u);

        // split up h, s, and l
        let vals = only_vals.split_char(',');
        if vals.len() != 3u { return fail_unrecognized(color); }

        match (float::from_str(vals[0]), float::from_str(vals[1]),
             float::from_str(vals[2])) {
          (Some(h), Some(s), Some(l)) => { Some(hsl(h, s, l)) }
          _ => { fail_unrecognized(color) }
        }
    }

    /** Parses a color specification in the form hsla(foo,bar,baz,qux) */
    fn parse_hsla(color : &str) -> Option<Color> {
        // Shave off the hsla( and the )
        let only_vals = color.substr(5u, color.len() - 6u);

        let vals = only_vals.split_char(',');
        if vals.len() != 4u { return fail_unrecognized(color); }

        match (float::from_str(vals[0]), float::from_str(vals[1]),
             float::from_str(vals[2]), float::from_str(vals[3])) {
          (Some(h), Some(s), Some(l), Some(a)) => { Some(hsla(h, s, l, a)) }
          _ => { fail_unrecognized(color) }
        }
    }

    // Currently colors are supported in rgb(a,b,c) form and also by
    // keywords for several common colors.
    // TODO: extend this
    fn parse_color(color : &str) -> Option<Color> {
        match color {
          c if c.starts_with("rgb(") => parse_rgb(c),
          c if c.starts_with("rgba(") => parse_rgba(c),
          c if c.starts_with("hsl(") => parse_hsl(c),
          c if c.starts_with("hsla(") => parse_hsla(c),
          c => parse_by_name(c)
        }
    }
}

#[cfg(test)]
mod test {
    use css_colors::*;
    use option::unwrap;
    use parsing::parse_color;

    #[test]
    fn test_parse_by_name() {
        assert red().eq(&unwrap(parse_color(~"red")));
        assert lime().eq(&unwrap(parse_color(~"Lime")));
        assert blue().eq(&unwrap(parse_color(~"BLUE")));
        assert green().eq(&unwrap(parse_color(~"GreEN")));
        assert white().eq(&unwrap(parse_color(~"white")));
        assert black().eq(&unwrap(parse_color(~"Black")));
        assert gray().eq(&unwrap(parse_color(~"Gray")));
        assert silver().eq(&unwrap(parse_color(~"SiLvEr")));
        assert maroon().eq(&unwrap(parse_color(~"maroon")));
        assert purple().eq(&unwrap(parse_color(~"PURPLE")));
        assert fuchsia().eq(&unwrap(parse_color(~"FUCHSIA")));
        assert olive().eq(&unwrap(parse_color(~"oLiVe")));
        assert yellow().eq(&unwrap(parse_color(~"yellow")));
        assert navy().eq(&unwrap(parse_color(~"NAVY")));
        assert teal().eq(&unwrap(parse_color(~"Teal")));
        assert aqua().eq(&unwrap(parse_color(~"Aqua")));
        assert None == parse_color(~"foobarbaz");
    }

    #[test]
    fn test_parsing_rgb() {
        assert red().eq(&unwrap(parse_color(~"rgb(255,0,0)")));
        assert red().eq(&unwrap(parse_color(~"rgba(255,0,0,1.0)")));
        assert red().eq(&unwrap(parse_color(~"rgba(255,0,0,1)")));
        assert lime().eq(&unwrap(parse_color(~"rgba(0,255,0,1.00)")));
        assert rgb(1u8,2u8,3u8).eq(&unwrap(parse_color(~"rgb(1,2,03)")));
        assert rgba(15u8,250u8,3u8,0.5).eq(&unwrap(parse_color(~"rgba(15,250,3,.5)")));
        assert rgba(15u8,250u8,3u8,0.5).eq(&unwrap(parse_color(~"rgba(15,250,3,0.5)")));
        assert None == parse_color(~"rbga(1,2,3)");
    }

    #[test]
    fn test_parsing_hsl() {
        assert red().eq(&unwrap(parse_color(~"hsl(0,1,.5)")));
        assert lime().eq(&unwrap(parse_color(~"hsl(120.0,1.0,.5)")));
        assert blue().eq(&unwrap(parse_color(~"hsl(240.0,1.0,.5)")));
        assert green().eq(&unwrap(parse_color(~"hsl(120.0,1.0,.25)")));
        assert white().eq(&unwrap(parse_color(~"hsl(1.0,1.,1.0)")));
        assert white().eq(&unwrap(parse_color(~"hsl(129.0,0.3,1.0)")));
        assert black().eq(&unwrap(parse_color(~"hsl(231.2,0.75,0.0)")));
        assert black().eq(&unwrap(parse_color(~"hsl(11.2,0.0,0.0)")));
        assert gray().eq(&unwrap(parse_color(~"hsl(0.0,0.0,0.5)")));
        assert maroon().eq(&unwrap(parse_color(~"hsl(0.0,1.0,0.25)")));
        assert purple().eq(&unwrap(parse_color(~"hsl(300.0,1.0,0.25)")));
        assert fuchsia().eq(&unwrap(parse_color(~"hsl(300,1.0,0.5)")));
        assert olive().eq(&unwrap(parse_color(~"hsl(60.,1.0,0.25)")));
        assert yellow().eq(&unwrap(parse_color(~"hsl(60.,1.0,0.5)")));
        assert navy().eq(&unwrap(parse_color(~"hsl(240.0,1.0,.25)")));
        assert teal().eq(&unwrap(parse_color(~"hsl(180.0,1.0,.25)")));
        assert aqua().eq(&unwrap(parse_color(~"hsl(180.0,1.0,.5)")));
        assert None == parse_color(~"hsl(1,2,3,.4)");
    }
}

/** Define the colors specified by css */
pub mod css_colors {
    // The 16 basic css colors
    fn black() -> Color {
        Color({red : 0u8, green : 0u8, blue : 0u8, alpha : 1.0})
    }
    fn silver() -> Color {
        Color({red : 192u8, green : 192u8, blue : 192u8, alpha : 1.0})
    }
    fn gray() -> Color {
        Color({red : 128u8, green : 128u8, blue : 128u8, alpha : 1.0})
    }
    fn white() -> Color {
        Color({red : 255u8, green : 255u8, blue : 255u8, alpha : 1.0})
    }
    fn maroon() -> Color {
        Color({red : 128u8, green : 0u8, blue : 0u8, alpha : 1.0})
    }
    fn red() -> Color {
        Color({red : 255u8, green : 0u8, blue : 0u8, alpha : 1.0})
    }
    fn purple() -> Color {
        Color({red : 128u8, green : 0u8, blue : 128u8, alpha : 1.0})
    }
    fn fuchsia() -> Color {
        Color({red : 255u8, green : 0u8, blue : 255u8, alpha : 1.0})
    }
    fn green() -> Color {
        Color({red : 0u8, green : 128u8, blue : 0u8, alpha : 1.0})
    }
    fn lime() -> Color {
        Color({red : 0u8, green : 255u8, blue : 0u8, alpha : 1.0})
    }
    fn olive() -> Color {
        Color({red : 128u8, green : 128u8, blue : 0u8, alpha : 1.0})
    }
    fn yellow() -> Color {
        Color({red : 255u8, green : 255u8, blue : 0u8, alpha : 1.0})
    }
    fn navy() -> Color {
        Color({red : 0u8, green : 0u8, blue : 128u8, alpha : 1.0})
    }
    fn blue() -> Color {
        Color({red : 0u8, green : 0u8, blue : 255u8, alpha : 1.0})
    }
    fn teal() -> Color {
        Color({red : 0u8, green : 128u8, blue : 128u8, alpha : 1.0})
    }
    fn aqua() -> Color {
        Color({red : 0u8, green : 255u8, blue : 255u8, alpha : 1.0})
    }

    // The other 130 css colors
    // TODO
}
<commit_msg>Convert Color to a struct<commit_after>use float::round;
use libc::types::os::arch::c95::c_double;
use css_colors::*;
use cmp::Eq;

pub struct Color { red : u8, green : u8, blue : u8, alpha : float}

impl Color : Eq {
    pure fn eq(other: &Color) -> bool {
        return self.red == other.red && self.green == other.green && self.blue == other.blue &&
               self.alpha == other.alpha;
    }
    pure fn ne(other: &Color) -> bool {
        !self.eq(other)
    }
}

pub fn rgba(r : u8, g : u8, b : u8, a : float) -> Color {
    Color { red : r, green : g, blue : b, alpha : a}
}

pub fn rgb(r : u8, g : u8, b : u8) -> Color {
    return rgba(r, g, b, 1.0);
}

pub fn hsla(h : float, s : float, l : float, a : float) -> Color {
    // Algorithm for converting hsl to rbg taken from
    // http://www.w3.org/TR/2003/CR-css3-color-20030514/#hsl-color
    let m2 = if l <= 0.5 { l*(s + 1.0) } else { l + s - l*s };
    let m1 = l*2.0 - m2;
    let h = h / 360.0;

    fn hue_to_rgb(m1 : float, m2 : float, h : float) -> float {
        let h = if h < 0.0 { h + 1.0 } else if h > 1.0 { h - 1.0 } else { h };

        match h {
          0.0 .. 1.0/6.0 => m1 + (m2 - m1)*h*6.0,
          1.0/6.0 .. 1.0/2.0 => m2,
          1.0/2.0 .. 2.0/3.0 => m1 + (m2 - m1)*(4.0 - 6.0*h),
          2.0/3.0 .. 1.0 => return m1,
          _ => fail ~"unexpected hue value"
        }
    }

    let r = round(255.0*hue_to_rgb(m1, m2, h + 1.0/3.0) as c_double);;
    let g = round(255.0*hue_to_rgb(m1, m2, h) as c_double);
    let b = round(255.0*hue_to_rgb(m1, m2, h - 1.0/3.0) as c_double);

    return rgba(r as u8, g as u8, b as u8, a);
}

pub fn hsl(h : float, s : float, l : float) -> Color {
    return hsla(h, s, l, 1.0);
}

impl Color {
    fn print() -> ~str {
        fmt!("rgba(%u,%u,%u,%f)", self.red as uint, self.green as uint,
             self.blue as uint, self.alpha)
    }
}

pub mod parsing {
    export parse_color;

    fn fail_unrecognized(col : &str) -> Option<Color> {
        warn!("Unrecognized color %s", col);
        return None;
    }

    /** Match an exact color keyword. */
    fn parse_by_name(color : &str) -> Option<Color> {
        let col = match color.to_lower() {
          ~"black" => black(),
          ~"silver" => silver(),
          ~"gray" => gray(),
          ~"grey" => gray(),
          ~"white" => white(),
          ~"maroon" => maroon(),
          ~"red" => red(),
          ~"purple" => purple(),
          ~"fuchsia" => fuchsia(),
          ~"green" => green(),
          ~"lime" => lime(),
          ~"olive" => olive(),
          ~"yellow" => yellow(),
          ~"navy" => navy(),
          ~"blue" => blue(),
          ~"teal" => teal(),
          ~"aqua" => aqua(),
          _ => return fail_unrecognized(color)
        };

        return Some(col);
    }

    /** Parses a color specification in the form rgb(foo,bar,baz) */
    fn parse_rgb(color : &str) -> Option<Color> {
        // Shave off the rgb( and the )
        let only_colors = color.substr(4u, color.len() - 5u);

        // split up r, g, and b
        let cols = only_colors.split_char(',');
        if cols.len() != 3u { return fail_unrecognized(color); }

        match (u8::from_str(cols[0]), u8::from_str(cols[1]),
             u8::from_str(cols[2])) {
          (Some(r), Some(g), Some(b)) => { Some(rgb(r, g, b)) }
          _ => { fail_unrecognized(color) }
        }
    }

    /** Parses a color specification in the form rgba(foo,bar,baz,qux) */
    fn parse_rgba(color : &str) -> Option<Color> {
        // Shave off the rgba( and the )
        let only_vals = color.substr(5u, color.len() - 6u);

        // split up r, g, and b
        let cols = only_vals.split_char(',');
        if cols.len() != 4u { return fail_unrecognized(color); }

        match (u8::from_str(cols[0]), u8::from_str(cols[1]),
             u8::from_str(cols[2]), float::from_str(cols[3])) {
          (Some(r), Some(g), Some(b), Some(a)) => { Some(rgba(r, g, b, a)) }
          _ => { fail_unrecognized(color) }
        }
    }

    /** Parses a color specification in the form hsl(foo,bar,baz) */
    fn parse_hsl(color : &str) -> Option<Color> {
        // Shave off the hsl( and the )
        let only_vals = color.substr(4u, color.len() - 5u);

        // split up h, s, and l
        let vals = only_vals.split_char(',');
        if vals.len() != 3u { return fail_unrecognized(color); }

        match (float::from_str(vals[0]), float::from_str(vals[1]),
             float::from_str(vals[2])) {
          (Some(h), Some(s), Some(l)) => { Some(hsl(h, s, l)) }
          _ => { fail_unrecognized(color) }
        }
    }

    /** Parses a color specification in the form hsla(foo,bar,baz,qux) */
    fn parse_hsla(color : &str) -> Option<Color> {
        // Shave off the hsla( and the )
        let only_vals = color.substr(5u, color.len() - 6u);

        let vals = only_vals.split_char(',');
        if vals.len() != 4u { return fail_unrecognized(color); }

        match (float::from_str(vals[0]), float::from_str(vals[1]),
             float::from_str(vals[2]), float::from_str(vals[3])) {
          (Some(h), Some(s), Some(l), Some(a)) => { Some(hsla(h, s, l, a)) }
          _ => { fail_unrecognized(color) }
        }
    }

    // Currently colors are supported in rgb(a,b,c) form and also by
    // keywords for several common colors.
    // TODO: extend this
    fn parse_color(color : &str) -> Option<Color> {
        match color {
          c if c.starts_with("rgb(") => parse_rgb(c),
          c if c.starts_with("rgba(") => parse_rgba(c),
          c if c.starts_with("hsl(") => parse_hsl(c),
          c if c.starts_with("hsla(") => parse_hsla(c),
          c => parse_by_name(c)
        }
    }
}

#[cfg(test)]
mod test {
    use css_colors::*;
    use option::unwrap;
    use parsing::parse_color;

    #[test]
    fn test_parse_by_name() {
        assert red().eq(&unwrap(parse_color(~"red")));
        assert lime().eq(&unwrap(parse_color(~"Lime")));
        assert blue().eq(&unwrap(parse_color(~"BLUE")));
        assert green().eq(&unwrap(parse_color(~"GreEN")));
        assert white().eq(&unwrap(parse_color(~"white")));
        assert black().eq(&unwrap(parse_color(~"Black")));
        assert gray().eq(&unwrap(parse_color(~"Gray")));
        assert silver().eq(&unwrap(parse_color(~"SiLvEr")));
        assert maroon().eq(&unwrap(parse_color(~"maroon")));
        assert purple().eq(&unwrap(parse_color(~"PURPLE")));
        assert fuchsia().eq(&unwrap(parse_color(~"FUCHSIA")));
        assert olive().eq(&unwrap(parse_color(~"oLiVe")));
        assert yellow().eq(&unwrap(parse_color(~"yellow")));
        assert navy().eq(&unwrap(parse_color(~"NAVY")));
        assert teal().eq(&unwrap(parse_color(~"Teal")));
        assert aqua().eq(&unwrap(parse_color(~"Aqua")));
        assert None == parse_color(~"foobarbaz");
    }

    #[test]
    fn test_parsing_rgb() {
        assert red().eq(&unwrap(parse_color(~"rgb(255,0,0)")));
        assert red().eq(&unwrap(parse_color(~"rgba(255,0,0,1.0)")));
        assert red().eq(&unwrap(parse_color(~"rgba(255,0,0,1)")));
        assert lime().eq(&unwrap(parse_color(~"rgba(0,255,0,1.00)")));
        assert rgb(1u8,2u8,3u8).eq(&unwrap(parse_color(~"rgb(1,2,03)")));
        assert rgba(15u8,250u8,3u8,0.5).eq(&unwrap(parse_color(~"rgba(15,250,3,.5)")));
        assert rgba(15u8,250u8,3u8,0.5).eq(&unwrap(parse_color(~"rgba(15,250,3,0.5)")));
        assert None == parse_color(~"rbga(1,2,3)");
    }

    #[test]
    fn test_parsing_hsl() {
        assert red().eq(&unwrap(parse_color(~"hsl(0,1,.5)")));
        assert lime().eq(&unwrap(parse_color(~"hsl(120.0,1.0,.5)")));
        assert blue().eq(&unwrap(parse_color(~"hsl(240.0,1.0,.5)")));
        assert green().eq(&unwrap(parse_color(~"hsl(120.0,1.0,.25)")));
        assert white().eq(&unwrap(parse_color(~"hsl(1.0,1.,1.0)")));
        assert white().eq(&unwrap(parse_color(~"hsl(129.0,0.3,1.0)")));
        assert black().eq(&unwrap(parse_color(~"hsl(231.2,0.75,0.0)")));
        assert black().eq(&unwrap(parse_color(~"hsl(11.2,0.0,0.0)")));
        assert gray().eq(&unwrap(parse_color(~"hsl(0.0,0.0,0.5)")));
        assert maroon().eq(&unwrap(parse_color(~"hsl(0.0,1.0,0.25)")));
        assert purple().eq(&unwrap(parse_color(~"hsl(300.0,1.0,0.25)")));
        assert fuchsia().eq(&unwrap(parse_color(~"hsl(300,1.0,0.5)")));
        assert olive().eq(&unwrap(parse_color(~"hsl(60.,1.0,0.25)")));
        assert yellow().eq(&unwrap(parse_color(~"hsl(60.,1.0,0.5)")));
        assert navy().eq(&unwrap(parse_color(~"hsl(240.0,1.0,.25)")));
        assert teal().eq(&unwrap(parse_color(~"hsl(180.0,1.0,.25)")));
        assert aqua().eq(&unwrap(parse_color(~"hsl(180.0,1.0,.5)")));
        assert None == parse_color(~"hsl(1,2,3,.4)");
    }
}

/** Define the colors specified by css */
pub mod css_colors {
    // The 16 basic css colors
    fn black() -> Color {
        Color {red : 0u8, green : 0u8, blue : 0u8, alpha : 1.0}
    }
    fn silver() -> Color {
        Color {red : 192u8, green : 192u8, blue : 192u8, alpha : 1.0}
    }
    fn gray() -> Color {
        Color {red : 128u8, green : 128u8, blue : 128u8, alpha : 1.0}
    }
    fn white() -> Color {
        Color {red : 255u8, green : 255u8, blue : 255u8, alpha : 1.0}
    }
    fn maroon() -> Color {
        Color {red : 128u8, green : 0u8, blue : 0u8, alpha : 1.0}
    }
    fn red() -> Color {
        Color {red : 255u8, green : 0u8, blue : 0u8, alpha : 1.0}
    }
    fn purple() -> Color {
        Color {red : 128u8, green : 0u8, blue : 128u8, alpha : 1.0}
    }
    fn fuchsia() -> Color {
        Color {red : 255u8, green : 0u8, blue : 255u8, alpha : 1.0}
    }
    fn green() -> Color {
        Color {red : 0u8, green : 128u8, blue : 0u8, alpha : 1.0}
    }
    fn lime() -> Color {
        Color {red : 0u8, green : 255u8, blue : 0u8, alpha : 1.0}
    }
    fn olive() -> Color {
        Color {red : 128u8, green : 128u8, blue : 0u8, alpha : 1.0}
    }
    fn yellow() -> Color {
        Color {red : 255u8, green : 255u8, blue : 0u8, alpha : 1.0}
    }
    fn navy() -> Color {
        Color {red : 0u8, green : 0u8, blue : 128u8, alpha : 1.0}
    }
    fn blue() -> Color {
        Color {red : 0u8, green : 0u8, blue : 255u8, alpha : 1.0}
    }
    fn teal() -> Color {
        Color {red : 0u8, green : 128u8, blue : 128u8, alpha : 1.0}
    }
    fn aqua() -> Color {
        Color {red : 0u8, green : 255u8, blue : 255u8, alpha : 1.0}
    }

    // The other 130 css colors
    // TODO
}
<|endoftext|>


<commit_before>// A tuple struct that can be compared
#[derive(PartialEq, PartialOrd)]
struct Centimeters(f64);

// A tuple struct that can be printed
#[derive(Debug)]
struct Inches(i32);

impl Inches {
    fn to_centimeters(&self) -> Centimeters {
        let &Inches(inches) = self;

        Centimeters(inches as f64 * 2.54)
    }
}

// A vanilla tuple struct
struct Seconds(i32);

fn main() {
    let _one_second = Seconds(1);

    // Error! `Seconds` can't be printed, because it doesn't implement the
    // `Debug` trait
    //println!("One second looks like: {}", _one_second);
    // TODO ^ Try uncommenting this line

    // Error: `Seconds` can't be compared, because it doesn't implement the
    // `PartialEq` trait
    //let _this_is_true = _one_second == _one_second;
    // TODO ^ Try uncommenting this line

    let foot = Inches(12);

    println!("One foot === {:?}", foot);

    let meter = Centimeters(100.0);

    let cmp =
        if foot.to_centimeters() < meter {
            "smaller"
        } else {
            "bigger"
        };

    println!("one foot is {} than one meter", cmp);
}
<commit_msg>trait/derive: changed the format pattern to "{:?}" for the Debug trait example<commit_after>// A tuple struct that can be compared
#[derive(PartialEq, PartialOrd)]
struct Centimeters(f64);

// A tuple struct that can be printed
#[derive(Debug)]
struct Inches(i32);

impl Inches {
    fn to_centimeters(&self) -> Centimeters {
        let &Inches(inches) = self;

        Centimeters(inches as f64 * 2.54)
    }
}

// A vanilla tuple struct
struct Seconds(i32);

fn main() {
    let _one_second = Seconds(1);

    // Error! `Seconds` can't be printed, because it doesn't implement the
    // `Debug` trait
    //println!("One second looks like: {:?}", _one_second);
    // TODO ^ Try uncommenting this line

    // Error: `Seconds` can't be compared, because it doesn't implement the
    // `PartialEq` trait
    //let _this_is_true = _one_second == _one_second;
    // TODO ^ Try uncommenting this line

    let foot = Inches(12);

    println!("One foot === {:?}", foot);

    let meter = Centimeters(100.0);

    let cmp =
        if foot.to_centimeters() < meter {
            "smaller"
        } else {
            "bigger"
        };

    println!("one foot is {} than one meter", cmp);
}
<|endoftext|>


<commit_before>mod advent_of_code;

use advent_of_code::get_numbers;

use std::io;
use std::io::BufRead;

fn is_valid(mut numbers: Vec<i32>)
    -> bool
{
    if numbers.len() != 3
    {
        panic!("Non-triangle vector passed: {:?}.", numbers);
    }
    numbers.sort();
    return numbers[0] >= 0 && numbers[0] + numbers[1] > numbers[2];
}

fn main()
{
    let stdin = io::stdin();
    let mut n_possible = 0;

    let mut rows = Vec::new();

    for line in stdin.lock().lines()
    {
        rows.push(get_numbers(line.unwrap()));
    }

    let mut maybe_triangles: Vec<Vec<i32>>;
    if false
    {
        // part 1 -- a row is assumed to be a triangle
        maybe_triangles = rows;
    }
    else
    {
        // part 2 -- triangles go "downwards"
        maybe_triangles = Vec::with_capacity(rows.len());
        for _ in 0..rows.len()
        {
            maybe_triangles.push(Vec::with_capacity(3));
        }
        for r in 0..(rows.len() / 3)
        {
            for r_ in 0..3
            {
                let ref row = rows[r * 3 + r_];
                for c in 0..3
                {
                    maybe_triangles[r + c].push(row[c]);
                }
            }
        }
    }

    for numbers in maybe_triangles
    {
        //println!("{:?}", numbers);
        if is_valid(numbers)
        {
            n_possible += 1;
        }
    }

    println!("{}", n_possible);
}
<commit_msg>Fix remapping of maybe triangles<commit_after>mod advent_of_code;

use advent_of_code::get_numbers;

use std::io;
use std::io::BufRead;

fn is_valid(mut numbers: Vec<i32>)
    -> bool
{
    if numbers.len() != 3
    {
        panic!("Non-triangle vector passed: {:?}.", numbers);
    }
    numbers.sort();
    return numbers[0] >= 0 && numbers[0] + numbers[1] > numbers[2];
}

fn main()
{
    let stdin = io::stdin();
    let mut n_possible = 0;

    let mut rows = Vec::new();

    for line in stdin.lock().lines()
    {
        rows.push(get_numbers(line.unwrap()));
    }

    let mut maybe_triangles: Vec<Vec<i32>>;
    if false
    {
        // part 1 -- a row is assumed to be a triangle
        maybe_triangles = rows;
    }
    else
    {
        // part 2 -- triangles go "downwards"
        maybe_triangles = Vec::with_capacity(rows.len());
        for _ in 0..rows.len()
        {
            maybe_triangles.push(Vec::with_capacity(3));
        }
        for r in 0..(rows.len() / 3)
        {
            for r_ in 0..3
            {
                let ref row = rows[r * 3 + r_];
                for c in 0..3
                {
                    maybe_triangles[r * 3 + c].push(row[c]);
                }
            }
        }
    }

    for numbers in maybe_triangles
    {
        //println!("{:?}", numbers);
        if is_valid(numbers)
        {
            n_possible += 1;
        }
    }

    println!("{}", n_possible);
}
<|endoftext|>


<commit_before><commit_msg>On utilise des ~et on passe le temps explicitement plutôt que de passer par la structure Crowd<commit_after><|endoftext|>


<commit_before>use std::collections::HashMap;

extern crate toml;
mod basics;
mod tiff;
mod mrw;
mod arw;
use self::basics::*;
use self::tiff::*;

pub static CAMERAS_TOML: &'static str = include_str!("../../data/cameras/all.toml");

pub trait Decoder {
  fn identify(&self) -> Result<&Camera, String>;
  fn image(&self) -> Result<Image, String>;
}

#[derive(Debug, Clone)]
pub struct Image {
  pub width: u32,
  pub height: u32,
  pub wb_coeffs: [f32;4],
  pub data: Box<[u16]>,
  pub whitelevels: [i64;4],
  pub blacklevels: [i64;4],
  pub color_matrix: [i64;12],
  pub dcraw_filters: u32,
  pub crops: [i64;4],
}

#[derive(Debug, Clone)]
pub struct Camera {
  pub make: String,
  pub model: String,
  pub canonical_make: String,
  pub canonical_model: String,
  whitelevels: [i64;4],
  blacklevels: [i64;4],
  color_matrix: [i64;12],
  dcraw_filters: u32,
  crops: [i64;4],
}

#[derive(Debug, Clone)]
pub struct RawLoader {
  pub cameras: HashMap<(String,String),Camera>,
}

impl RawLoader {
  pub fn new() -> RawLoader {
    let mut map = HashMap::new();

    let mut parser = toml::Parser::new(&CAMERAS_TOML);
    let toml = match parser.parse() {
      Some(val) => val,
      None => panic!(format!("Error parsing all.toml: {:?}", parser.errors)),
    };
    let cameras = toml.get("cameras").unwrap().as_table().unwrap();
    for (_,c) in cameras {
      let ct = c.as_table().unwrap();
      let make = ct.get("make").unwrap().as_str().unwrap().to_string();
      let model = ct.get("model").unwrap().as_str().unwrap().to_string();
      let canonical_make = ct.get("canonical_make").unwrap().as_str().unwrap().to_string();
      let canonical_model = ct.get("canonical_model").unwrap().as_str().unwrap().to_string();
      let white = ct.get("whitepoint").unwrap().as_integer().unwrap();
      let black = ct.get("blackpoint").unwrap().as_integer().unwrap();
      let matrix = ct.get("color_matrix").unwrap().as_slice().unwrap();
      let mut cmatrix: [i64;12] = [0,0,0,0,0,0,0,0,0,0,0,0];
      for (i, val) in matrix.into_iter().enumerate() {
        cmatrix[i] = val.as_integer().unwrap();
      }
      let crop_vals = ct.get("crops").unwrap().as_slice().unwrap();
      let mut crops: [i64;4] = [0,0,0,0];
      for (i, val) in crop_vals.into_iter().enumerate() {
        crops[i] = val.as_integer().unwrap();
      }
      let color_pattern = ct.get("color_pattern").unwrap().as_str().unwrap().to_string();
      let cam = Camera{
        make: make.clone(),
        model: model.clone(),
        canonical_make: canonical_make.clone(),
        canonical_model: canonical_model.clone(),
        whitelevels: [white, white, white, white],
        blacklevels: [black, black, black, black],
        color_matrix : cmatrix,
        dcraw_filters: RawLoader::dcraw_filters(&color_pattern),
        crops: crops,
      };
      map.insert((make.clone(),model.clone()), cam);
    }

    RawLoader{
      cameras: map,
    }
  }

  pub fn get_decoder<'b>(&'b self, buffer: &'b [u8]) -> Result<Box<Decoder+'b>, String> {
    if mrw::is_mrw(buffer) {
      let dec = Box::new(mrw::MrwDecoder::new(buffer, &self));
      return Ok(dec as Box<Decoder>);
    }

    let endian = match LEu16(buffer, 0) {
      0x4949 => LITTLE_ENDIAN,
      0x4d4d => BIG_ENDIAN,
      x => {return Err(format!("Couldn't find decoder for marker 0x{:x}", x).to_string())},
    };

    let tiff = TiffIFD::new_root(buffer, 4, 0, endian);
    // FIXME: Cloning tiff is ugly as hell, need to fix the borrowing in this case
    match try!(tiff.clone().find_entry(Tag::MAKE).ok_or("Couldn't find Make".to_string())).get_str() {
      "SONY" => Ok(Box::new(arw::ArwDecoder::new(tiff, &self)) as Box<Decoder>),
      make => Err(format!("Couldn't find a decoder for make \"{}\"", make).to_string()),
    }
  }

  pub fn check_supported<'a>(&'a self, make: &'a str, model: &'a str) -> Result<&Camera, String> {
    match self.cameras.get(&(make.to_string(),model.to_string())) {
      Some(cam) => Ok(cam),
      None => Err(format!("Couldn't find camera \"{}\" \"{}\"", make, model)),
    }
  }

  fn dcraw_filters(pattern: &str) -> u32 {
    match pattern {
      "BGGR" => 0x16161616,
      "GRBG" => 0x61616161,
      "GBRG" => 0x49494949,
      "RGGB" => 0x94949494,
      _ => 0,
    }
  }
}
<commit_msg>Abstract away the new decoder construct<commit_after>use std::collections::HashMap;

extern crate toml;
mod basics;
mod tiff;
mod mrw;
mod arw;
use self::basics::*;
use self::tiff::*;

pub static CAMERAS_TOML: &'static str = include_str!("../../data/cameras/all.toml");

pub trait Decoder {
  fn identify(&self) -> Result<&Camera, String>;
  fn image(&self) -> Result<Image, String>;
}

#[derive(Debug, Clone)]
pub struct Image {
  pub width: u32,
  pub height: u32,
  pub wb_coeffs: [f32;4],
  pub data: Box<[u16]>,
  pub whitelevels: [i64;4],
  pub blacklevels: [i64;4],
  pub color_matrix: [i64;12],
  pub dcraw_filters: u32,
  pub crops: [i64;4],
}

#[derive(Debug, Clone)]
pub struct Camera {
  pub make: String,
  pub model: String,
  pub canonical_make: String,
  pub canonical_model: String,
  whitelevels: [i64;4],
  blacklevels: [i64;4],
  color_matrix: [i64;12],
  dcraw_filters: u32,
  crops: [i64;4],
}

#[derive(Debug, Clone)]
pub struct RawLoader {
  pub cameras: HashMap<(String,String),Camera>,
}

impl RawLoader {
  pub fn new() -> RawLoader {
    let mut map = HashMap::new();

    let mut parser = toml::Parser::new(&CAMERAS_TOML);
    let toml = match parser.parse() {
      Some(val) => val,
      None => panic!(format!("Error parsing all.toml: {:?}", parser.errors)),
    };
    let cameras = toml.get("cameras").unwrap().as_table().unwrap();
    for (_,c) in cameras {
      let ct = c.as_table().unwrap();
      let make = ct.get("make").unwrap().as_str().unwrap().to_string();
      let model = ct.get("model").unwrap().as_str().unwrap().to_string();
      let canonical_make = ct.get("canonical_make").unwrap().as_str().unwrap().to_string();
      let canonical_model = ct.get("canonical_model").unwrap().as_str().unwrap().to_string();
      let white = ct.get("whitepoint").unwrap().as_integer().unwrap();
      let black = ct.get("blackpoint").unwrap().as_integer().unwrap();
      let matrix = ct.get("color_matrix").unwrap().as_slice().unwrap();
      let mut cmatrix: [i64;12] = [0,0,0,0,0,0,0,0,0,0,0,0];
      for (i, val) in matrix.into_iter().enumerate() {
        cmatrix[i] = val.as_integer().unwrap();
      }
      let crop_vals = ct.get("crops").unwrap().as_slice().unwrap();
      let mut crops: [i64;4] = [0,0,0,0];
      for (i, val) in crop_vals.into_iter().enumerate() {
        crops[i] = val.as_integer().unwrap();
      }
      let color_pattern = ct.get("color_pattern").unwrap().as_str().unwrap().to_string();
      let cam = Camera{
        make: make.clone(),
        model: model.clone(),
        canonical_make: canonical_make.clone(),
        canonical_model: canonical_model.clone(),
        whitelevels: [white, white, white, white],
        blacklevels: [black, black, black, black],
        color_matrix : cmatrix,
        dcraw_filters: RawLoader::dcraw_filters(&color_pattern),
        crops: crops,
      };
      map.insert((make.clone(),model.clone()), cam);
    }

    RawLoader{
      cameras: map,
    }
  }

  pub fn get_decoder<'b>(&'b self, buffer: &'b [u8]) -> Result<Box<Decoder+'b>, String> {
    if mrw::is_mrw(buffer) {
      let dec = Box::new(mrw::MrwDecoder::new(buffer, &self));
      return Ok(dec as Box<Decoder>);
    }

    let endian = match LEu16(buffer, 0) {
      0x4949 => LITTLE_ENDIAN,
      0x4d4d => BIG_ENDIAN,
      x => {return Err(format!("Couldn't find decoder for marker 0x{:x}", x).to_string())},
    };

    macro_rules! use_decoder {
        ($dec:ty, $tiff:ident, $rawdec:ident) => (Ok(Box::new(<$dec>::new($tiff, $rawdec)) as Box<Decoder>));
    }

    let tiff = TiffIFD::new_root(buffer, 4, 0, endian);
    // FIXME: Cloning tiff is ugly as hell, need to fix the borrowing in this case
    match try!(tiff.clone().find_entry(Tag::MAKE).ok_or("Couldn't find Make".to_string())).get_str() {
      "SONY" => use_decoder!(arw::ArwDecoder, tiff, self),
      make => Err(format!("Couldn't find a decoder for make \"{}\"", make).to_string()),
    }
  }

  pub fn check_supported<'a>(&'a self, make: &'a str, model: &'a str) -> Result<&Camera, String> {
    match self.cameras.get(&(make.to_string(),model.to_string())) {
      Some(cam) => Ok(cam),
      None => Err(format!("Couldn't find camera \"{}\" \"{}\"", make, model)),
    }
  }

  fn dcraw_filters(pattern: &str) -> u32 {
    match pattern {
      "BGGR" => 0x16161616,
      "GRBG" => 0x61616161,
      "GBRG" => 0x49494949,
      "RGGB" => 0x94949494,
      _ => 0,
    }
  }
}
<|endoftext|>