<commit_before>use std::cell::RefCell;
use std::collections::VecDeque;
use std::ffi::CString;
use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
use std::sync::{Arc, Mutex};

use mio::Ready;

use nix::Result as NixResult;

use wayland_commons::map::{Object, ObjectMap, ObjectMetadata};
use wayland_commons::socket::{BufferedSocket, Socket};
use wayland_commons::wire::{Argument, ArgumentType, Message, MessageDesc, MessageParseError};

use sources::{FdEvent, FdInterest};
use Implementation;

use super::event_loop::SourcesPoll;
use super::resources::{ObjectMeta, ResourceInner};
use super::SourceInner;

#[derive(Clone, Debug)]
pub(crate) enum Error {
    Protocol,
    Parse(MessageParseError),
    Nix(::nix::Error),
}

pub(crate) struct ClientConnection {
    source: Option<SourceInner<FdEvent>>,
    socket: BufferedSocket,
    pub(crate) map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
    user_data: *mut (),
    destructor: Option<fn(*mut ())>,
    last_error: Option<Error>,
}

impl ClientConnection {
    unsafe fn new(fd: RawFd, display_object: Object<ObjectMeta>) -> ClientConnection {
        let socket = BufferedSocket::new(Socket::from_raw_fd(fd));

        let mut map = ObjectMap::new();
        // Insert first pre-existing object
        map.insert_at(1, display_object).unwrap();

        ClientConnection {
            socket,
            source: None,
            map: Arc::new(Mutex::new(map)),
            user_data: ::std::ptr::null_mut(),
            destructor: None,
            last_error: None,
        }
    }

    pub(crate) fn write_message(&mut self, msg: &Message) -> NixResult<()> {
        self.socket.write_message(msg)
    }

    pub(crate) fn flush(&mut self) -> NixResult<()> {
        self.socket.flush()
    }

    pub(crate) fn delete_id(&mut self, id: u32) -> NixResult<()> {
        self.map.lock().unwrap().remove(id);

        self.write_message(&Message {
            sender_id: 1,
            opcode: 1,
            args: vec![Argument::Uint(id)],
        })
    }

    pub(crate) fn read_requests(&mut self, buffer: &mut VecDeque<Message>) -> Result<usize, Error> {
        if let Some(ref err) = self.last_error {
            return Err(err.clone());
        }
        // acquire the map lock, this means no objects can be created nor destroyed while we
        // are reading requests
        let mut map = self.map.lock().unwrap();
        // wrap it in a RefCell for cheap sharing in the two closures below
        let map = RefCell::new(&mut *map);
        let last_error = &mut self.last_error;
        // read messages
        let ret = self.socket.read_messages(
            |id, opcode| {
                map.borrow()
                    .find(id)
                    .and_then(|o| o.requests.get(opcode as usize))
                    .map(|desc| desc.signature)
            },
            |msg| {
                let mut map = map.borrow_mut();
                let object = match map.find(msg.sender_id) {
                    Some(obj) => obj,
                    None => {
                        // this is a message sent to a destroyed object
                        // to avoid dying because of races, we just consume it into void
                        // closing any associated FDs
                        for a in msg.args {
                            if let Argument::Fd(fd) = a {
                                let _ = ::nix::unistd::close(fd);
                            }
                        }
                        // continue parsing to the next message
                        return true;
                    }
                };

                // create a new object if applicable
                if let Some(child) = object.request_child(msg.opcode) {
                    let new_id = msg.args
                        .iter()
                        .flat_map(|a| {
                            if let Argument::NewId(nid) = a {
                                Some(nid)
                            } else {
                                None
                            }
                        })
                        .cloned()
                        .next()
                        .unwrap();
                    let child_interface = child.interface;
                    if let Err(()) = map.insert_at(new_id, child) {
                        eprintln!(
                            "[wayland-client] Protocol error: server tried to create an object \"{}\" with invalid id \"{}\".",
                            child_interface,
                            new_id
                        );
                        // abort parsing, this is an unrecoverable error
                        *last_error = Some(Error::Protocol);
                        return false;
                    }
                } else {
                    // debug assert: if this opcode does not define a child, then there should be no
                    // NewId argument, unless we are the registry
                    debug_assert!(
                        object.interface == "wl_registry"
                            || msg.args.iter().any(|a| a.get_type() == ArgumentType::NewId) == false
                    );
                }

                // send the message to the appropriate pending queue
                buffer.push_back(msg);
                // continue parsing
                true
            },
        );
        match ret {
            Ok(Ok(n)) => if let Some(ref e) = *last_error {
                Err(e.clone())
            } else {
                Ok(n)
            },
            Ok(Err(e)) => {
                *last_error = Some(Error::Parse(e.clone()));
                Err(Error::Parse(e))
            }
            // non-fatal error
            Err(e @ ::nix::Error::Sys(::nix::errno::Errno::EAGAIN)) => Ok(0),
            // fatal errors
            Err(e) => {
                *last_error = Some(Error::Nix(e));
                Err(Error::Nix(e))
            }
        }
    }
}

#[derive(Clone)]
pub(crate) struct ClientInner {
    pub(crate) data: Arc<Mutex<Option<ClientConnection>>>,
}

impl ClientInner {
    pub(crate) fn alive(&self) -> bool {
        self.data.lock().unwrap().is_some()
    }

    pub(crate) fn equals(&self, other: &ClientInner) -> bool {
        Arc::ptr_eq(&self.data, &other.data)
    }

    pub(crate) fn flush(&self) {
        if let Some(ref mut data) = *self.data.lock().unwrap() {
            let _ = data.socket.flush();
        }
    }

    pub(crate) fn kill(&self) {
        if let Some(mut clientconn) = self.data.lock().unwrap().take() {
            if let Some(source) = clientconn.source.take() {
                source.remove();
            }
            let _ = clientconn.socket.flush();
            let _ = ::nix::unistd::close(clientconn.socket.into_socket().into_raw_fd());
            if let Some(destructor) = clientconn.destructor {
                destructor(clientconn.user_data);
            }
        }
    }

    pub(crate) fn set_user_data(&self, data: *mut ()) {
        if let Some(ref mut client_data) = *self.data.lock().unwrap() {
            client_data.user_data = data;
        }
    }

    pub(crate) fn get_user_data(&self) -> *mut () {
        if let Some(ref mut client_data) = *self.data.lock().unwrap() {
            client_data.user_data
        } else {
            ::std::ptr::null_mut()
        }
    }

    pub(crate) fn set_destructor(&self, destructor: fn(*mut ())) {
        if let Some(ref mut client_data) = *self.data.lock().unwrap() {
            client_data.destructor = Some(destructor);
        }
    }

    pub(crate) fn post_error(&self, object: u32, error_code: u32, msg: String) {
        if let Some(ref mut data) = *self.data.lock().unwrap() {
            let _ = data.write_message(&Message {
                sender_id: 1,
                opcode: 0,
                args: vec![
                    Argument::Object(object),
                    Argument::Uint(error_code),
                    Argument::Str(CString::new(msg).unwrap()),
                ],
            });
        }
        self.kill();
    }
}

pub(crate) struct ClientManager {
    sources_poll: SourcesPoll,
    clients: Vec<ClientInner>,
}

impl ClientManager {
    pub(crate) fn new(sources_poll: SourcesPoll) -> ClientManager {
        ClientManager {
            sources_poll,
            clients: Vec::new(),
        }
    }

    pub(crate) unsafe fn init_client(&mut self, fd: RawFd) -> ClientInner {
        let display_object = Object {
            interface: "wl_display",
            version: 1,
            requests: DISPLAY_REQUESTS,
            events: DISPLAY_EVENTS,
            meta: ObjectMeta::with_dispatcher(DisplayDispatcher {}),
            childs_from_events: no_child,
            childs_from_requests: display_req_child,
        };

        let cx = ClientConnection::new(fd, display_object);
        let map = cx.map.clone();

        let client = ClientInner {
            data: Arc::new(Mutex::new(Some(cx))),
        };

        match self.sources_poll.insert_source(
            fd,
            Ready::readable(),
            ClientImplementation {
                inner: client.clone(),
                map,
            },
            FdEvent::Ready {
                fd,
                mask: FdInterest::READ,
            },
        ) {
            Ok(source) => {
                client.data.lock().unwrap().as_mut().unwrap().source = Some(source);
            }
            Err((e, _)) => {
                eprintln!(
                    "[wayland-server] Failed to insert client into event loop: {:?}",
                    e
                );
            }
        }

        self.clients.push(client.clone());

        client
    }

    pub(crate) fn flush_all(&mut self) {
        // flush all clients and cleanup dead ones
        self.clients.retain(|c| {
            if let Some(ref mut data) = *c.data.lock().unwrap() {
                let _ = data.flush();
                true
            } else {
                false
            }
        });
    }
}

const DISPLAY_REQUESTS: &'static [MessageDesc] = &[
    MessageDesc {
        name: "sync",
        since: 1,
        signature: &[ArgumentType::NewId],
    },
    MessageDesc {
        name: "get_registry",
        since: 1,
        signature: &[ArgumentType::NewId],
    },
];

const DISPLAY_EVENTS: &'static [MessageDesc] = &[
    MessageDesc {
        name: "error",
        since: 1,
        signature: &[ArgumentType::Object, ArgumentType::Uint, ArgumentType::Str],
    },
    MessageDesc {
        name: "delete_id",
        since: 1,
        signature: &[ArgumentType::Uint],
    },
];

const REGISTRY_REQUESTS: &'static [MessageDesc] = &[MessageDesc {
    name: "bind",
    since: 1,
    signature: &[ArgumentType::Uint, ArgumentType::NewId],
}];

const REGISTRY_EVENTS: &'static [MessageDesc] = &[
    MessageDesc {
        name: "global",
        since: 1,
        signature: &[ArgumentType::Uint, ArgumentType::Str, ArgumentType::Uint],
    },
    MessageDesc {
        name: "global_remove",
        since: 1,
        signature: &[ArgumentType::Uint],
    },
];

fn display_req_child(opcode: u16, _: u32, meta: &ObjectMeta) -> Option<Object<ObjectMeta>> {
    match opcode {
        // sync
        0 => Some(Object::from_interface::<::protocol::wl_callback::WlCallback>(
            1,
            meta.child(),
        )),
        // registry
        1 => Some(Object {
            interface: "wl_registry",
            version: 1,
            requests: REGISTRY_REQUESTS,
            events: REGISTRY_EVENTS,
            meta: meta.child(),
            childs_from_events: no_child,
            childs_from_requests: no_child,
        }),
        _ => None,
    }
}

fn no_child(_: u16, _: u32, _: &ObjectMeta) -> Option<Object<ObjectMeta>> {
    None
}

struct ClientImplementation {
    inner: ClientInner,
    map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
}

impl Implementation<(), FdEvent> for ClientImplementation {
    fn receive(&mut self, event: FdEvent, (): ()) {
        match event {
            FdEvent::Ready { .. } => {
                let mut buffer = VecDeque::new();
                let ret = if let Some(ref mut data) = *self.inner.data.lock().unwrap() {
                    data.read_requests(&mut buffer)
                } else {
                    // do nothing if the client is already dead, this is a spurious wakeup
                    Ok(0)
                };

                if let Err(e) = ret {
                    self.inner.kill();
                }

                // now dispatch the requests
                let mut resourcemap = super::ResourceMap::make(self.map.clone(), self.inner.clone());
                for msg in buffer.drain(..) {
                    let id = msg.sender_id;
                    if let Some(res) = ResourceInner::from_id(id, self.map.clone(), self.inner.clone()) {
                        let object = res.object.clone();
                        let mut dispatcher = object.meta.dispatcher.lock().unwrap();
                        if let Err(()) = dispatcher.dispatch(msg, res, &mut resourcemap) {
                            self.inner.kill();
                            return;
                        }
                    } else {
                        self.inner.kill();
                        return;
                    }
                }
            }
            FdEvent::Error { .. } => {
                // in case of error, kill the client
                self.inner.kill();
            }
        }
    }
}

struct DisplayDispatcher {}

impl super::Dispatcher for DisplayDispatcher {
    fn dispatch(
        &mut self,
        msg: Message,
        resource: ResourceInner,
        _map: &mut super::ResourceMap,
    ) -> Result<(), ()> {
        unimplemented!()
    }
}

struct RegistryDispatcher {}

impl super::Dispatcher for RegistryDispatcher {
    fn dispatch(
        &mut self,
        msg: Message,
        resource: ResourceInner,
        _map: &mut super::ResourceMap,
    ) -> Result<(), ()> {
        unimplemented!()
    }
}
<commit_msg>server: ensure Client is Send<commit_after>use std::cell::RefCell;
use std::collections::VecDeque;
use std::ffi::CString;
use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
use std::sync::{Arc, Mutex};

use mio::Ready;

use nix::Result as NixResult;

use wayland_commons::map::{Object, ObjectMap, ObjectMetadata};
use wayland_commons::socket::{BufferedSocket, Socket};
use wayland_commons::wire::{Argument, ArgumentType, Message, MessageDesc, MessageParseError};

use sources::{FdEvent, FdInterest};
use Implementation;

use super::event_loop::SourcesPoll;
use super::resources::{ObjectMeta, ResourceInner};
use super::SourceInner;

#[derive(Clone, Debug)]
pub(crate) enum Error {
    Protocol,
    Parse(MessageParseError),
    Nix(::nix::Error),
}

struct UserData(*mut ());

unsafe impl Send for UserData {}

pub(crate) struct ClientConnection {
    socket: BufferedSocket,
    pub(crate) map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
    user_data: UserData,
    destructor: Option<fn(*mut ())>,
    last_error: Option<Error>,
}

impl ClientConnection {
    unsafe fn new(fd: RawFd, display_object: Object<ObjectMeta>) -> ClientConnection {
        let socket = BufferedSocket::new(Socket::from_raw_fd(fd));

        let mut map = ObjectMap::new();
        // Insert first pre-existing object
        map.insert_at(1, display_object).unwrap();

        ClientConnection {
            socket,
            map: Arc::new(Mutex::new(map)),
            user_data: UserData(::std::ptr::null_mut()),
            destructor: None,
            last_error: None,
        }
    }

    pub(crate) fn write_message(&mut self, msg: &Message) -> NixResult<()> {
        self.socket.write_message(msg)
    }

    pub(crate) fn flush(&mut self) -> NixResult<()> {
        self.socket.flush()
    }

    pub(crate) fn delete_id(&mut self, id: u32) -> NixResult<()> {
        self.map.lock().unwrap().remove(id);

        self.write_message(&Message {
            sender_id: 1,
            opcode: 1,
            args: vec![Argument::Uint(id)],
        })
    }

    pub(crate) fn read_requests(&mut self, buffer: &mut VecDeque<Message>) -> Result<usize, Error> {
        if let Some(ref err) = self.last_error {
            return Err(err.clone());
        }
        // acquire the map lock, this means no objects can be created nor destroyed while we
        // are reading requests
        let mut map = self.map.lock().unwrap();
        // wrap it in a RefCell for cheap sharing in the two closures below
        let map = RefCell::new(&mut *map);
        let last_error = &mut self.last_error;
        // read messages
        let ret = self.socket.read_messages(
            |id, opcode| {
                map.borrow()
                    .find(id)
                    .and_then(|o| o.requests.get(opcode as usize))
                    .map(|desc| desc.signature)
            },
            |msg| {
                let mut map = map.borrow_mut();
                let object = match map.find(msg.sender_id) {
                    Some(obj) => obj,
                    None => {
                        // this is a message sent to a destroyed object
                        // to avoid dying because of races, we just consume it into void
                        // closing any associated FDs
                        for a in msg.args {
                            if let Argument::Fd(fd) = a {
                                let _ = ::nix::unistd::close(fd);
                            }
                        }
                        // continue parsing to the next message
                        return true;
                    }
                };

                // create a new object if applicable
                if let Some(child) = object.request_child(msg.opcode) {
                    let new_id = msg.args
                        .iter()
                        .flat_map(|a| {
                            if let Argument::NewId(nid) = a {
                                Some(nid)
                            } else {
                                None
                            }
                        })
                        .cloned()
                        .next()
                        .unwrap();
                    let child_interface = child.interface;
                    if let Err(()) = map.insert_at(new_id, child) {
                        eprintln!(
                            "[wayland-client] Protocol error: server tried to create an object \"{}\" with invalid id \"{}\".",
                            child_interface,
                            new_id
                        );
                        // abort parsing, this is an unrecoverable error
                        *last_error = Some(Error::Protocol);
                        return false;
                    }
                } else {
                    // debug assert: if this opcode does not define a child, then there should be no
                    // NewId argument, unless we are the registry
                    debug_assert!(
                        object.interface == "wl_registry"
                            || msg.args.iter().any(|a| a.get_type() == ArgumentType::NewId) == false
                    );
                }

                // send the message to the appropriate pending queue
                buffer.push_back(msg);
                // continue parsing
                true
            },
        );
        match ret {
            Ok(Ok(n)) => if let Some(ref e) = *last_error {
                Err(e.clone())
            } else {
                Ok(n)
            },
            Ok(Err(e)) => {
                *last_error = Some(Error::Parse(e.clone()));
                Err(Error::Parse(e))
            }
            // non-fatal error
            Err(e @ ::nix::Error::Sys(::nix::errno::Errno::EAGAIN)) => Ok(0),
            // fatal errors
            Err(e) => {
                *last_error = Some(Error::Nix(e));
                Err(Error::Nix(e))
            }
        }
    }
}

#[derive(Clone)]
pub(crate) struct ClientInner {
    pub(crate) data: Arc<Mutex<Option<ClientConnection>>>,
}

impl ClientInner {
    pub(crate) fn alive(&self) -> bool {
        self.data.lock().unwrap().is_some()
    }

    pub(crate) fn equals(&self, other: &ClientInner) -> bool {
        Arc::ptr_eq(&self.data, &other.data)
    }

    pub(crate) fn flush(&self) {
        if let Some(ref mut data) = *self.data.lock().unwrap() {
            let _ = data.socket.flush();
        }
    }

    pub(crate) fn kill(&self) {
        if let Some(mut clientconn) = self.data.lock().unwrap().take() {
            let _ = clientconn.socket.flush();
            let _ = ::nix::unistd::close(clientconn.socket.into_socket().into_raw_fd());
            if let Some(destructor) = clientconn.destructor {
                destructor(clientconn.user_data.0);
            }
        }
    }

    pub(crate) fn set_user_data(&self, data: *mut ()) {
        if let Some(ref mut client_data) = *self.data.lock().unwrap() {
            client_data.user_data.0 = data;
        }
    }

    pub(crate) fn get_user_data(&self) -> *mut () {
        if let Some(ref mut client_data) = *self.data.lock().unwrap() {
            client_data.user_data.0
        } else {
            ::std::ptr::null_mut()
        }
    }

    pub(crate) fn set_destructor(&self, destructor: fn(*mut ())) {
        if let Some(ref mut client_data) = *self.data.lock().unwrap() {
            client_data.destructor = Some(destructor);
        }
    }

    pub(crate) fn post_error(&self, object: u32, error_code: u32, msg: String) {
        if let Some(ref mut data) = *self.data.lock().unwrap() {
            let _ = data.write_message(&Message {
                sender_id: 1,
                opcode: 0,
                args: vec![
                    Argument::Object(object),
                    Argument::Uint(error_code),
                    Argument::Str(CString::new(msg).unwrap()),
                ],
            });
        }
        self.kill();
    }
}

pub(crate) struct ClientManager {
    sources_poll: SourcesPoll,
    clients: Vec<(RefCell<Option<SourceInner<FdEvent>>>, ClientInner)>,
}

impl ClientManager {
    pub(crate) fn new(sources_poll: SourcesPoll) -> ClientManager {
        ClientManager {
            sources_poll,
            clients: Vec::new(),
        }
    }

    pub(crate) unsafe fn init_client(&mut self, fd: RawFd) -> ClientInner {
        let display_object = Object {
            interface: "wl_display",
            version: 1,
            requests: DISPLAY_REQUESTS,
            events: DISPLAY_EVENTS,
            meta: ObjectMeta::with_dispatcher(DisplayDispatcher {}),
            childs_from_events: no_child,
            childs_from_requests: display_req_child,
        };

        let cx = ClientConnection::new(fd, display_object);
        let map = cx.map.clone();

        let client = ClientInner {
            data: Arc::new(Mutex::new(Some(cx))),
        };

        let source = match self.sources_poll.insert_source(
            fd,
            Ready::readable(),
            ClientImplementation {
                inner: client.clone(),
                map,
            },
            FdEvent::Ready {
                fd,
                mask: FdInterest::READ,
            },
        ) {
            Ok(source) => Some(source),
            Err((e, _)) => {
                eprintln!(
                    "[wayland-server] Failed to insert client into event loop: {:?}",
                    e
                );
                client.kill();
                None
            }
        };

        if source.is_some() {
            self.clients.push((RefCell::new(source), client.clone()));
        }

        client
    }

    pub(crate) fn flush_all(&mut self) {
        // flush all clients and cleanup dead ones
        self.clients.retain(|&(ref s, ref c)| {
            if let Some(ref mut data) = *c.data.lock().unwrap() {
                let _ = data.flush();
                true
            } else {
                // This is a dead client, clean it up
                if let Some(source) = s.borrow_mut().take() {
                    source.remove();
                }
                false
            }
        });
    }
}

const DISPLAY_REQUESTS: &'static [MessageDesc] = &[
    MessageDesc {
        name: "sync",
        since: 1,
        signature: &[ArgumentType::NewId],
    },
    MessageDesc {
        name: "get_registry",
        since: 1,
        signature: &[ArgumentType::NewId],
    },
];

const DISPLAY_EVENTS: &'static [MessageDesc] = &[
    MessageDesc {
        name: "error",
        since: 1,
        signature: &[ArgumentType::Object, ArgumentType::Uint, ArgumentType::Str],
    },
    MessageDesc {
        name: "delete_id",
        since: 1,
        signature: &[ArgumentType::Uint],
    },
];

const REGISTRY_REQUESTS: &'static [MessageDesc] = &[MessageDesc {
    name: "bind",
    since: 1,
    signature: &[ArgumentType::Uint, ArgumentType::NewId],
}];

const REGISTRY_EVENTS: &'static [MessageDesc] = &[
    MessageDesc {
        name: "global",
        since: 1,
        signature: &[ArgumentType::Uint, ArgumentType::Str, ArgumentType::Uint],
    },
    MessageDesc {
        name: "global_remove",
        since: 1,
        signature: &[ArgumentType::Uint],
    },
];

fn display_req_child(opcode: u16, _: u32, meta: &ObjectMeta) -> Option<Object<ObjectMeta>> {
    match opcode {
        // sync
        0 => Some(Object::from_interface::<::protocol::wl_callback::WlCallback>(
            1,
            meta.child(),
        )),
        // registry
        1 => Some(Object {
            interface: "wl_registry",
            version: 1,
            requests: REGISTRY_REQUESTS,
            events: REGISTRY_EVENTS,
            meta: meta.child(),
            childs_from_events: no_child,
            childs_from_requests: no_child,
        }),
        _ => None,
    }
}

fn no_child(_: u16, _: u32, _: &ObjectMeta) -> Option<Object<ObjectMeta>> {
    None
}

struct ClientImplementation {
    inner: ClientInner,
    map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
}

impl Implementation<(), FdEvent> for ClientImplementation {
    fn receive(&mut self, event: FdEvent, (): ()) {
        match event {
            FdEvent::Ready { .. } => {
                let mut buffer = VecDeque::new();
                let ret = if let Some(ref mut data) = *self.inner.data.lock().unwrap() {
                    data.read_requests(&mut buffer)
                } else {
                    // do nothing if the client is already dead, this is a spurious wakeup
                    Ok(0)
                };

                if let Err(e) = ret {
                    self.inner.kill();
                }

                // now dispatch the requests
                let mut resourcemap = super::ResourceMap::make(self.map.clone(), self.inner.clone());
                for msg in buffer.drain(..) {
                    let id = msg.sender_id;
                    if let Some(res) = ResourceInner::from_id(id, self.map.clone(), self.inner.clone()) {
                        let object = res.object.clone();
                        let mut dispatcher = object.meta.dispatcher.lock().unwrap();
                        if let Err(()) = dispatcher.dispatch(msg, res, &mut resourcemap) {
                            self.inner.kill();
                            return;
                        }
                    } else {
                        self.inner.kill();
                        return;
                    }
                }
            }
            FdEvent::Error { .. } => {
                // in case of error, kill the client
                self.inner.kill();
            }
        }
    }
}

struct DisplayDispatcher {}

impl super::Dispatcher for DisplayDispatcher {
    fn dispatch(
        &mut self,
        msg: Message,
        resource: ResourceInner,
        _map: &mut super::ResourceMap,
    ) -> Result<(), ()> {
        unimplemented!()
    }
}

struct RegistryDispatcher {}

impl super::Dispatcher for RegistryDispatcher {
    fn dispatch(
        &mut self,
        msg: Message,
        resource: ResourceInner,
        _map: &mut super::ResourceMap,
    ) -> Result<(), ()> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>extern crate edit_distance;

#[test]
fn simple() {
    assert_eq!(edit_distance::edit_distance("kitten", "sitting"), 3);
    assert_eq!(edit_distance::edit_distance("Tier", "Tor"), 2);
}

#[test]
fn same() {
    assert_eq!(edit_distance::edit_distance("kitten", "kitten"), 0);
}

#[test]
fn empty_a() {
    assert_eq!(edit_distance::edit_distance("", "kitten"), 6);
}

#[test]
fn empty_b() {
    assert_eq!(edit_distance::edit_distance("sitting", ""), 7);
}

#[test]
fn empty_both() {
    assert_eq!(edit_distance::edit_distance("", ""), 0);
}

#[test]
fn unicode_misc() {
    assert_eq!(edit_distance::edit_distance("üö", "uo"), 2);
}

#[test]
fn unicode_thai() {
    assert_eq!(edit_distance::edit_distance("ฎ ฏ ฐ", "a b c"), 3);
}

#[test]
fn unicode_misc_equal() {
    assert_eq!(edit_distance::edit_distance("☀☂☃☄", "☀☂☃☄"), 0);
}

extern crate quickcheck;
use quickcheck::quickcheck;

#[test]
fn at_least_size_difference_property() {
    fn at_least_size_difference(a: String, b: String) -> bool {
        let size_a = a.chars().count() as i32;
        let size_b = b.chars().count() as i32;
        let diff = (size_a - size_b).abs();

        edit_distance::edit_distance(&a, &b) >= diff
    }

    quickcheck(at_least_size_difference as fn(a: String, b: String) -> bool);
}
<commit_msg>Max length of longer string<commit_after>extern crate edit_distance;

#[test]
fn simple() {
    assert_eq!(edit_distance::edit_distance("kitten", "sitting"), 3);
    assert_eq!(edit_distance::edit_distance("Tier", "Tor"), 2);
}

#[test]
fn same() {
    assert_eq!(edit_distance::edit_distance("kitten", "kitten"), 0);
}

#[test]
fn empty_a() {
    assert_eq!(edit_distance::edit_distance("", "kitten"), 6);
}

#[test]
fn empty_b() {
    assert_eq!(edit_distance::edit_distance("sitting", ""), 7);
}

#[test]
fn empty_both() {
    assert_eq!(edit_distance::edit_distance("", ""), 0);
}

#[test]
fn unicode_misc() {
    assert_eq!(edit_distance::edit_distance("üö", "uo"), 2);
}

#[test]
fn unicode_thai() {
    assert_eq!(edit_distance::edit_distance("ฎ ฏ ฐ", "a b c"), 3);
}

#[test]
fn unicode_misc_equal() {
    assert_eq!(edit_distance::edit_distance("☀☂☃☄", "☀☂☃☄"), 0);
}

extern crate quickcheck;
use quickcheck::quickcheck;

#[test]
fn at_least_size_difference_property() {
    fn at_least_size_difference(a: String, b: String) -> bool {
        let size_a = a.chars().count() as i32;
        let size_b = b.chars().count() as i32;
        let diff = (size_a - size_b).abs();

        edit_distance::edit_distance(&a, &b) >= diff
    }

    quickcheck(at_least_size_difference as fn(a: String, b: String) -> bool);
}

#[test]
fn at_most_length_of_longer_property() {
    fn at_most_size_of_longer(a: String, b: String) -> bool {
        let upper_bound = *[a.chars().count(),
                            b.chars().count()]
            .iter()
            .max()
            .unwrap() as i32;
        edit_distance::edit_distance(&a, &b) <= upper_bound
    }

    quickcheck(at_most_size_of_longer as fn(a: String, b: String) -> bool);
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::rc::Rc;
use std::cell::RefCell;

use sounding_base::Sounding;

use errors::*;
use sonde_widgets::SondeWidgets;
use sounding::{XYCoords, sounding_context};

pub type DataContextPointer = Rc<RefCell<DataContext>>;

pub struct DataContext {
    list: Vec<Sounding>,
    lower_left: XYCoords,
    upper_right: XYCoords,

    currently_displayed: usize,
    widgets: SondeWidgets,
}

impl DataContext {
    pub fn new(widgets: SondeWidgets) -> DataContextPointer {
        Rc::new(RefCell::new(DataContext {
            list: vec![],
            lower_left: (0.0, 0.0),
            upper_right: (1.0, 1.0),
            currently_displayed: 0,
            widgets: widgets,
        }))
    }

    /// Load data from a source.
    pub fn load_data(&mut self, src: &mut Iterator<Item = Sounding>) -> Result<()> {

        self.list = src.into_iter().collect();
        self.currently_displayed = 0;

        self.lower_left = (0.45, 0.45);
        self.upper_right = (0.55, 0.55);

        for snd in &self.list {
            for pair in snd.pressure.iter().zip(&snd.temperature).filter_map(|p| {
                if let (Some(p), Some(t)) = (p.0.as_option(), p.1.as_option()) {
                    Some((t, p))
                } else {
                    None
                }
            })
            {
                let (x, y) = sounding_context::SoundingContext::convert_tp_to_xy(pair);
                if x < self.lower_left.0 {
                    self.lower_left.0 = x;
                }
                if y < self.lower_left.1 {
                    self.lower_left.1 = y;
                }
                if x > self.upper_right.0 {
                    self.upper_right.0 = x;
                }
                if y > self.upper_right.1 {
                    self.upper_right.1 = y;
                }
            }

            // TODO: Once you get surface temperature, make a station pressure-surface temp
            // point and throw that in the mix.
            // if let Some(p) = snd.station_pres.as_option() {

            // }
        }

        self.widgets.draw_all();
        unimplemented!();
    }

    /// Is there any data to plot?
    pub fn plottable(&self) -> bool {
        !self.list.is_empty()
    }

    /// Set the next one as the one to display, or wrap to the beginning.
    pub fn display_next(&mut self) {
        if self.plottable() {
            if self.currently_displayed < self.list.len() - 1 {
                self.currently_displayed += 1;
            } else {
                self.currently_displayed = 0;
            }
        }

        self.widgets.draw_all();
    }

    /// Set the previous one as the one to display, or wrap to the end.
    pub fn display_previous(&mut self) {
        if self.plottable() {
            if self.currently_displayed > 0 {
                self.currently_displayed -= 1;
            } else {
                self.currently_displayed = self.list.len() - 1;
            }
        }

        self.widgets.draw_all();
    }

    /// Get the sounding to draw.
    pub fn get_sounding_for_display(&self) -> &Sounding {
        &self.list[self.currently_displayed]
    }
}
<commit_msg>Update comments.<commit_after>//! Globally shareable sounding data.
#![allow(dead_code)] // for now.

use std::rc::Rc;
use std::cell::RefCell;

use sounding_base::Sounding;

use errors::*;
use sonde_widgets::SondeWidgets;
use sounding::{XYCoords, sounding_context};

/// Smart pointer for globally shareable data
pub type DataContextPointer = Rc<RefCell<DataContext>>;

pub struct DataContext {
    list: Vec<Sounding>,
    lower_left: XYCoords,
    upper_right: XYCoords,

    currently_displayed: usize,
    widgets: SondeWidgets,
}

impl DataContext {
    pub fn new(widgets: SondeWidgets) -> DataContextPointer {
        Rc::new(RefCell::new(DataContext {
            list: vec![],
            lower_left: (0.0, 0.0),
            upper_right: (1.0, 1.0),
            currently_displayed: 0,
            widgets: widgets,
        }))
    }

    /// Load data from a source.
    pub fn load_data(&mut self, src: &mut Iterator<Item = Sounding>) -> Result<()> {

        self.list = src.into_iter().collect();
        self.currently_displayed = 0;

        self.lower_left = (0.45, 0.45);
        self.upper_right = (0.55, 0.55);

        for snd in &self.list {
            for pair in snd.pressure.iter().zip(&snd.temperature).filter_map(|p| {
                if let (Some(p), Some(t)) = (p.0.as_option(), p.1.as_option()) {
                    Some((t, p))
                } else {
                    None
                }
            })
            {
                let (x, y) = sounding_context::SoundingContext::convert_tp_to_xy(pair);
                if x < self.lower_left.0 {
                    self.lower_left.0 = x;
                }
                if y < self.lower_left.1 {
                    self.lower_left.1 = y;
                }
                if x > self.upper_right.0 {
                    self.upper_right.0 = x;
                }
                if y > self.upper_right.1 {
                    self.upper_right.1 = y;
                }
            }

            // TODO: Once you get surface temperature, make a station pressure-surface temp
            // point and throw that in the mix.
            // if let Some(p) = snd.station_pres.as_option() {

            // }
        }

        self.widgets.draw_all();
        unimplemented!();
    }

    /// Is there any data to plot?
    pub fn plottable(&self) -> bool {
        !self.list.is_empty()
    }

    /// Set the next one as the one to display, or wrap to the beginning.
    pub fn display_next(&mut self) {
        if self.plottable() {
            if self.currently_displayed < self.list.len() - 1 {
                self.currently_displayed += 1;
            } else {
                self.currently_displayed = 0;
            }
        }

        self.widgets.draw_all();
    }

    /// Set the previous one as the one to display, or wrap to the end.
    pub fn display_previous(&mut self) {
        if self.plottable() {
            if self.currently_displayed > 0 {
                self.currently_displayed -= 1;
            } else {
                self.currently_displayed = self.list.len() - 1;
            }
        }

        self.widgets.draw_all();
    }

    /// Get the sounding to draw.
    pub fn get_sounding_for_display(&self) -> &Sounding {
        &self.list[self.currently_displayed]
    }
}
<|endoftext|>


<commit_before>mod get;

pub use self::get::*;

use r2d2;
use r2d2_postgres::PostgresConnectionManager;

use super::errors::*;
use super::board::NewBoard;
use super::moderator::Mod;
use super::post::Post;

pub type Pool = r2d2::Pool<PostgresConnectionManager>;

pub fn create_tables(pool: Pool) -> Result<()> {
    let conn = pool.get().unwrap();
    // Create the boards table
    conn.execute("CREATE TABLE IF NOT EXISTS boards (
                    short_name VARCHAR PRIMARY KEY,
                    long_name VARCHAR NOT NULL,
                    description TEXT NOT NULL,
                    post_number BIGINT NOT NULL,
                    active_threads INT NOT NULL
                  )",
                 &[])?;

    // Create the admins table
    conn.execute("CREATE TABLE IF NOT EXISTS admins (
                    username VARCHAR PRIMARY KEY,
                    password VARCHAR NOT NULL,
                    boards VARCHAR[] NOT NULL,
                    admin boolean NOT NULL
                  )",
                 &[])?;

    // Create the posts table
    conn.execute("CREATE TABLE IF NOT EXISTS posts (
                    post_number BIGINT NOT NULL,
                    parent BIGINT NOT NULL,
                    board VARCHAR NOT NULL,
                    subject VARCHAR,
                    name VARCHAR NOT NULL,
                    email VARCHAR NOT NULL,
                    content TEXT NOT NULL,
                    thread boolean NOT NULL,
                    pinned boolean NOT NULL,
                    active boolean NOT NULL,
                    last_modified TIMESTAMP,
                    PRIMARY KEY (board, post_number)
                  )",
                 &[])?;

    Ok(())
}

pub fn create_admin(pool: Pool, admin: Mod) -> Result<()> {
    let conn = pool.get().unwrap();

    conn.execute("INSERT INTO admins (username, password, boards, admin) VALUES ($1, $2, $3, $4)",
                 &[&admin.username, &admin.password, &admin.boards, &admin.admin])?;
    Ok(())
}

pub fn create_boards(pool: Pool, boards: &[NewBoard]) -> Result<()> {
    let conn = pool.get().unwrap();

    for b in boards {
        conn.execute("INSERT INTO boards (short_name, long_name, description, post_number, \
                      active_threads) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (short_name) DO \
                      NOTHING",
                     &[&b.short_name, &b.long_name, &b.description, &0i64, &b.active_threads])?;
    }

    Ok(())
}

pub fn board_exists(pool: Pool, board_name: &str) -> Result<bool> {
    let conn = pool.get().unwrap();

    // TODO(nokaa): Look at the EXISTS keyword for this check:
    // https://stackoverflow.com/questions/7471625/fastest-check-if-row-exists-in-postgresql
    let rows = conn.query("SELECT short_name FROM boards WHERE short_name = $1",
               &[&board_name])?;
    Ok(!rows.is_empty())

}

pub fn thread_exists(pool: Pool, board_name: &str, thread_number: i64) -> Result<bool> {
    let conn = pool.get().unwrap();

    // TODO(nokaa): Look at the EXISTS keyword for this check:
    // https://stackoverflow.com/questions/7471625/fastest-check-if-row-exists-in-postgresql
    let rows =
        conn.query("SELECT post_number, board, thread FROM posts WHERE board = $1 AND \
                    post_number = $2 AND thread = $3",
                   &[&board_name, &thread_number, &true])?;
    Ok(!rows.is_empty())
}

pub fn create_thread(pool: Pool, thread: Post) -> Result<i64> {
    let conn = pool.get().unwrap();

    // Get the post number for this post
    let rows =
        conn.query("UPDATE boards SET post_number = post_number + 1 WHERE short_name = $1 \
                    RETURNING post_number",
                   &[&thread.board])?;
    let post_number: i64 = rows.get(0).get(0);
    let time = ::chrono::UTC::now().naive_utc();

    let trans = conn.transaction()?;
    trans.execute("INSERT INTO posts (post_number, parent, board, subject, name, email, content, \
                  thread, pinned, active, last_modified) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, \
                  $9, $10, $11);",
                 &[&post_number,
                   &post_number,
                   &thread.board,
                   &thread.subject,
                   &thread.name,
                   &thread.email,
                   &thread.content,
                   &true,
                   &false,
                   &true,
                   &Some(time)])?;
    trans.commit()?;
    Ok(post_number)
}

pub fn create_post(pool: Pool, post: Post) -> Result<()> {
    let conn = pool.get().unwrap();
    let trans = conn.transaction()?;

    let time = ::chrono::UTC::now().naive_utc();
    trans.execute("UPDATE posts SET last_modified = $1 WHERE board = $2 AND post_number = $3 AND \
                  thread = true",
                 &[&time, &post.board, &post.parent])?;
    trans.execute("with rows as (UPDATE boards SET post_number = post_number + 1 where short_name \
                  = $1 returning post_number) INSERT INTO posts (post_number, parent, board, \
                  subject, name, email, content, thread, pinned, active, last_modified) VALUES \
                  ((SELECT post_number FROM rows), $2, $1, $3, $4, $5, $6, $7, $8, $9, $10);",
                 &[&post.board,
                   &post.parent,
                   &post.subject,
                   &post.name,
                   &post.email,
                   &post.content,
                   &false,
                   &false,
                   &false,
                   &None::<::chrono::NaiveDateTime>])?;
    trans.commit()?;
    Ok(())
}
<commit_msg>Clean up thread creation sql<commit_after>mod get;

pub use self::get::*;

use r2d2;
use r2d2_postgres::PostgresConnectionManager;

use super::errors::*;
use super::board::NewBoard;
use super::moderator::Mod;
use super::post::Post;

pub type Pool = r2d2::Pool<PostgresConnectionManager>;

pub fn create_tables(pool: Pool) -> Result<()> {
    let conn = pool.get().unwrap();
    // Create the boards table
    conn.execute("CREATE TABLE IF NOT EXISTS boards (
                    short_name VARCHAR PRIMARY KEY,
                    long_name VARCHAR NOT NULL,
                    description TEXT NOT NULL,
                    post_number BIGINT NOT NULL,
                    active_threads INT NOT NULL
                  )",
                 &[])?;

    // Create the admins table
    conn.execute("CREATE TABLE IF NOT EXISTS admins (
                    username VARCHAR PRIMARY KEY,
                    password VARCHAR NOT NULL,
                    boards VARCHAR[] NOT NULL,
                    admin boolean NOT NULL
                  )",
                 &[])?;

    // Create the posts table
    conn.execute("CREATE TABLE IF NOT EXISTS posts (
                    post_number BIGINT NOT NULL,
                    parent BIGINT NOT NULL,
                    board VARCHAR NOT NULL,
                    subject VARCHAR,
                    name VARCHAR NOT NULL,
                    email VARCHAR NOT NULL,
                    content TEXT NOT NULL,
                    thread boolean NOT NULL,
                    pinned boolean NOT NULL,
                    active boolean NOT NULL,
                    last_modified TIMESTAMP,
                    PRIMARY KEY (board, post_number)
                  )",
                 &[])?;

    Ok(())
}

pub fn create_admin(pool: Pool, admin: Mod) -> Result<()> {
    let conn = pool.get().unwrap();

    conn.execute("INSERT INTO admins (username, password, boards, admin) VALUES ($1, $2, $3, $4)",
                 &[&admin.username, &admin.password, &admin.boards, &admin.admin])?;
    Ok(())
}

pub fn create_boards(pool: Pool, boards: &[NewBoard]) -> Result<()> {
    let conn = pool.get().unwrap();

    for b in boards {
        conn.execute("INSERT INTO boards (short_name, long_name, description, post_number, \
                      active_threads) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (short_name) DO \
                      NOTHING",
                     &[&b.short_name, &b.long_name, &b.description, &0i64, &b.active_threads])?;
    }

    Ok(())
}

pub fn board_exists(pool: Pool, board_name: &str) -> Result<bool> {
    let conn = pool.get().unwrap();

    // TODO(nokaa): Look at the EXISTS keyword for this check:
    // https://stackoverflow.com/questions/7471625/fastest-check-if-row-exists-in-postgresql
    let rows = conn.query("SELECT short_name FROM boards WHERE short_name = $1",
               &[&board_name])?;
    Ok(!rows.is_empty())

}

pub fn thread_exists(pool: Pool, board_name: &str, thread_number: i64) -> Result<bool> {
    let conn = pool.get().unwrap();

    // TODO(nokaa): Look at the EXISTS keyword for this check:
    // https://stackoverflow.com/questions/7471625/fastest-check-if-row-exists-in-postgresql
    let rows =
        conn.query("SELECT post_number, board, thread FROM posts WHERE board = $1 AND \
                    post_number = $2 AND thread = $3",
                   &[&board_name, &thread_number, &true])?;
    Ok(!rows.is_empty())
}

pub fn create_thread(pool: Pool, thread: Post) -> Result<i64> {
    let conn = pool.get().unwrap();
    // let trans = conn.transaction()?;

    let time = ::chrono::UTC::now().naive_utc();
    let rows =
        conn.query("with rows as (UPDATE boards SET post_number = post_number + 1 where \
                    short_name = $1 returning post_number) INSERT INTO posts (post_number, \
                    parent, board, subject, name, email, content, thread, pinned, active, \
                    last_modified) VALUES ((SELECT post_number FROM rows), (SELECT post_number \
                    FROM rows), $1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING post_number;",
                   &[&thread.board,
                     &thread.subject,
                     &thread.name,
                     &thread.email,
                     &thread.content,
                     &true,
                     &false,
                     &true,
                     &(Some(time))])?;
    // trans.commit()?;

    let post_number: i64 = rows.get(0).get(0);
    Ok(post_number)
}

pub fn create_post(pool: Pool, post: Post) -> Result<()> {
    let conn = pool.get().unwrap();
    let trans = conn.transaction()?;

    let time = ::chrono::UTC::now().naive_utc();
    trans.execute("UPDATE posts SET last_modified = $1 WHERE board = $2 AND post_number = $3 AND \
                  thread = true",
                 &[&time, &post.board, &post.parent])?;
    trans.execute("with rows as (UPDATE boards SET post_number = post_number + 1 where short_name \
                  = $1 returning post_number) INSERT INTO posts (post_number, parent, board, \
                  subject, name, email, content, thread, pinned, active, last_modified) VALUES \
                  ((SELECT post_number FROM rows), $2, $1, $3, $4, $5, $6, $7, $8, $9, $10);",
                 &[&post.board,
                   &post.parent,
                   &post.subject,
                   &post.name,
                   &post.email,
                   &post.content,
                   &false,
                   &false,
                   &false,
                   &None::<::chrono::NaiveDateTime>])?;
    trans.commit()?;
    Ok(())
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use decoders::ljpeg::*;
use std::f32::NAN;
use itertools::Itertools;

#[derive(Debug, Clone)]
pub struct Cr2Decoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> Cr2Decoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> Cr2Decoder<'a> {
    Cr2Decoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for Cr2Decoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let (raw, offset) = {
      if let Some(raw) = self.tiff.find_first_ifd(Tag::Cr2Id) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(raw) = self.tiff.find_first_ifd(Tag::CFAPattern) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(off) = self.tiff.find_entry(Tag::Cr2OldOffset) {
        (&self.tiff, off.get_usize(0))
      } else {
        return Err("CR2: Couldn't find raw info".to_string())
      }
    };
    let src = &self.buffer[offset..];

    let (width, height, cpp, image) = {
      let decompressor = try!(LjpegDecompressor::new(src));
      let ljpegwidth = decompressor.width();
      let mut width = ljpegwidth;
      let mut height = decompressor.height();
      let cpp = if decompressor.super_h() == 2 {3} else {1};
      let mut ljpegout = vec![0 as u16; width*height];
      try!(decompressor.decode(&mut ljpegout, 0, width, width, height));

      // Linearize the output (applies only to D2000 as far as I can tell)
      if camera.find_hint("linearization") {
        let table = {
          let linearization = fetch_tag!(self.tiff, Tag::GrayResponse);
          let mut t = [0 as u16;4096];
          for i in 0..t.len() {
            t[i] = linearization.get_u32(i) as u16;
          }
          LookupTable::new(&t)
        };

        let mut random = ljpegout[0] as u32;
        for o in ljpegout.chunks_mut(1) {
          o[0] = table.dither(o[0], &mut random);
        }
      }

      // Convert the YUV in sRAWs to RGB
      if cpp == 3 {
        try!(self.convert_to_rgb(camera, &mut ljpegout));
      }

      if raw.has_entry(Tag::ImageWidth) {
        width = fetch_tag!(raw, Tag::ImageWidth).get_usize(0) * cpp;
        height = fetch_tag!(raw, Tag::ImageLength).get_usize(0) ;
      } else if width/cpp < height {
        let temp = width/cpp;
        width = height*cpp;
        height = temp;
      } else if camera.find_hint("double_line") {
        width /= 2;
        height *= 2;
      }

      // Take each of the vertical fields and put them into the right location
      // FIXME: Doing this at the decode would reduce about 5% in runtime but I haven't
      //        been able to do it without hairy code
      if let Some(canoncol) = raw.find_entry(Tag::Cr2StripeWidths) {
        if canoncol.get_usize(0) == 0 {
          (width, height, cpp, ljpegout)
        } else {
          let mut out = vec![0 as u16; width*height];
          let mut fieldwidths = Vec::new();
          for _ in 0..canoncol.get_usize(0) {
            fieldwidths.push(canoncol.get_usize(1));
          }
          fieldwidths.push(canoncol.get_usize(2));

          if decompressor.super_v() == 2 {
            // We've decoded 2 lines at a time so we also need to copy two strips at a time
            let nfields = fieldwidths.len();
            let fieldwidth = fieldwidths[0];
            let mut fieldstart = 0;
            let mut inpos = 0;
            for _ in 0..nfields {
              for row in (0..height).step(2) {
                for col in (0..fieldwidth).step(3) {
                  let outpos = row*width+fieldstart+col;
                  out[outpos..outpos+3].copy_from_slice(&ljpegout[inpos..inpos+3]);
                  let outpos = (row+1)*width+fieldstart+col;
                  let inpos2 = inpos+ljpegwidth;
                  out[outpos..outpos+3].copy_from_slice(&ljpegout[inpos2..inpos2+3]);
                  inpos += 3;
                  if inpos % ljpegwidth == 0 {
                    // we've used a full input line and we're reading 2 by 2 so skip one
                    inpos += ljpegwidth;
                  }
                }
              }
              fieldstart += fieldwidth;
            }
          } else {
            let sh = decompressor.super_h();
            let mut fieldstart = 0;
            let mut fieldpos = 0;
            for fieldwidth in fieldwidths {
              let fieldwidth = fieldwidth/sh*cpp;
              for row in 0..height {
                let outpos = row*width+fieldstart;
                let inpos = fieldpos+row*fieldwidth;
                let outb = &mut out[outpos..outpos+fieldwidth];
                let inb = &ljpegout[inpos..inpos+fieldwidth];
                outb.copy_from_slice(inb);
              }
              fieldstart += fieldwidth;
              fieldpos += fieldwidth*height;
            }
          }

          (width, height, cpp, out)
        }
      } else {
        (width, height, cpp, ljpegout)
      }
    };

    let mut img = Image::new(camera, width, height, try!(self.get_wb(camera)), image);
    if cpp == 3 {
      img.cpp = 3;
      img.width /= 3;
      img.crops = [0,0,0,0];
      img.blacklevels = [0,0,0,0];
      img.whitelevels = [65535,65535,65535,65535];
    }
    Ok(img)
  }
}

impl<'a> Cr2Decoder<'a> {
  fn get_wb(&self, cam: &Camera) -> Result<[f32;4], String> {
    if let Some(levels) = self.tiff.find_entry(Tag::Cr2ColorData) {
      let offset = if cam.wb_offset != 0 {cam.wb_offset} else {63};
      Ok([levels.get_force_u16(offset) as f32, levels.get_force_u16(offset+1) as f32,
          levels.get_force_u16(offset+3) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2PowerShotWB) {
      Ok([levels.get_force_u32(3) as f32, levels.get_force_u32(2) as f32,
          levels.get_force_u32(4) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2OldWB) {
      Ok([levels.get_f32(0), levels.get_f32(1), levels.get_f32(2), NAN])
    } else {
      // At least the D2000 has no WB
      Ok([NAN,NAN,NAN,NAN])
    }
  }

  fn convert_to_rgb(&self, cam: &Camera, image: &mut [u16]) -> Result<(),String>{
    let coeffs = try!(self.get_wb(cam));
    let c1 = (1024.0*1024.0/coeffs[0]) as i32;
    let c2 = coeffs[1] as i32;
    let c3 = (1024.0*1024.0/coeffs[2]) as i32;

    for pix in image.chunks_mut(3) {
      let y = pix[0] as i32;
      let cb = pix[1] as i32 - 16383;
      let cr = pix[2] as i32 - 16383;

      let r = c1 * (y + cr);
      let g = c2 * (y + ((-778*cb - (cr<<11)) >> 12));
      let b = c3 * (y + cb);

      pix[0] = clampbits(r >> 8, 16) as u16;
      pix[1] = clampbits(g >> 8, 16) as u16;
      pix[2] = clampbits(b >> 8, 16) as u16;
    }
    Ok(())
  }
}
<commit_msg>CR2: fix broken dimensions in old format 1D/1Ds<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use decoders::ljpeg::*;
use std::f32::NAN;
use itertools::Itertools;

#[derive(Debug, Clone)]
pub struct Cr2Decoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> Cr2Decoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> Cr2Decoder<'a> {
    Cr2Decoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for Cr2Decoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let (raw, offset) = {
      if let Some(raw) = self.tiff.find_first_ifd(Tag::Cr2Id) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(raw) = self.tiff.find_first_ifd(Tag::CFAPattern) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(off) = self.tiff.find_entry(Tag::Cr2OldOffset) {
        (&self.tiff, off.get_usize(0))
      } else {
        return Err("CR2: Couldn't find raw info".to_string())
      }
    };
    let src = &self.buffer[offset..];

    let (width, height, cpp, image) = {
      let decompressor = try!(LjpegDecompressor::new(src));
      let ljpegwidth = decompressor.width();
      let mut width = ljpegwidth;
      let mut height = decompressor.height();
      let cpp = if decompressor.super_h() == 2 {3} else {1};
      let mut ljpegout = vec![0 as u16; width*height];
      try!(decompressor.decode(&mut ljpegout, 0, width, width, height));

      // Linearize the output (applies only to D2000 as far as I can tell)
      if camera.find_hint("linearization") {
        let table = {
          let linearization = fetch_tag!(self.tiff, Tag::GrayResponse);
          let mut t = [0 as u16;4096];
          for i in 0..t.len() {
            t[i] = linearization.get_u32(i) as u16;
          }
          LookupTable::new(&t)
        };

        let mut random = ljpegout[0] as u32;
        for o in ljpegout.chunks_mut(1) {
          o[0] = table.dither(o[0], &mut random);
        }
      }

      // Convert the YUV in sRAWs to RGB
      if cpp == 3 {
        try!(self.convert_to_rgb(camera, &mut ljpegout));
        if raw.has_entry(Tag::ImageWidth) {
          width = fetch_tag!(raw, Tag::ImageWidth).get_usize(0) * cpp;
          height = fetch_tag!(raw, Tag::ImageLength).get_usize(0) ;
        } else if width/cpp < height {
          let temp = width/cpp;
          width = height*cpp;
          height = temp;
        }
      }
      if camera.find_hint("double_line") {
        width /= 2;
        height *= 2;
      }

      // Take each of the vertical fields and put them into the right location
      // FIXME: Doing this at the decode would reduce about 5% in runtime but I haven't
      //        been able to do it without hairy code
      if let Some(canoncol) = raw.find_entry(Tag::Cr2StripeWidths) {
        if canoncol.get_usize(0) == 0 {
          (width, height, cpp, ljpegout)
        } else {
          let mut out = vec![0 as u16; width*height];
          let mut fieldwidths = Vec::new();
          for _ in 0..canoncol.get_usize(0) {
            fieldwidths.push(canoncol.get_usize(1));
          }
          fieldwidths.push(canoncol.get_usize(2));

          if decompressor.super_v() == 2 {
            // We've decoded 2 lines at a time so we also need to copy two strips at a time
            let nfields = fieldwidths.len();
            let fieldwidth = fieldwidths[0];
            let mut fieldstart = 0;
            let mut inpos = 0;
            for _ in 0..nfields {
              for row in (0..height).step(2) {
                for col in (0..fieldwidth).step(3) {
                  let outpos = row*width+fieldstart+col;
                  out[outpos..outpos+3].copy_from_slice(&ljpegout[inpos..inpos+3]);
                  let outpos = (row+1)*width+fieldstart+col;
                  let inpos2 = inpos+ljpegwidth;
                  out[outpos..outpos+3].copy_from_slice(&ljpegout[inpos2..inpos2+3]);
                  inpos += 3;
                  if inpos % ljpegwidth == 0 {
                    // we've used a full input line and we're reading 2 by 2 so skip one
                    inpos += ljpegwidth;
                  }
                }
              }
              fieldstart += fieldwidth;
            }
          } else {
            let sh = decompressor.super_h();
            let mut fieldstart = 0;
            let mut fieldpos = 0;
            for fieldwidth in fieldwidths {
              let fieldwidth = fieldwidth/sh*cpp;
              for row in 0..height {
                let outpos = row*width+fieldstart;
                let inpos = fieldpos+row*fieldwidth;
                let outb = &mut out[outpos..outpos+fieldwidth];
                let inb = &ljpegout[inpos..inpos+fieldwidth];
                outb.copy_from_slice(inb);
              }
              fieldstart += fieldwidth;
              fieldpos += fieldwidth*height;
            }
          }

          (width, height, cpp, out)
        }
      } else {
        (width, height, cpp, ljpegout)
      }
    };

    let mut img = Image::new(camera, width, height, try!(self.get_wb(camera)), image);
    if cpp == 3 {
      img.cpp = 3;
      img.width /= 3;
      img.crops = [0,0,0,0];
      img.blacklevels = [0,0,0,0];
      img.whitelevels = [65535,65535,65535,65535];
    }
    Ok(img)
  }
}

impl<'a> Cr2Decoder<'a> {
  fn get_wb(&self, cam: &Camera) -> Result<[f32;4], String> {
    if let Some(levels) = self.tiff.find_entry(Tag::Cr2ColorData) {
      let offset = if cam.wb_offset != 0 {cam.wb_offset} else {63};
      Ok([levels.get_force_u16(offset) as f32, levels.get_force_u16(offset+1) as f32,
          levels.get_force_u16(offset+3) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2PowerShotWB) {
      Ok([levels.get_force_u32(3) as f32, levels.get_force_u32(2) as f32,
          levels.get_force_u32(4) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2OldWB) {
      Ok([levels.get_f32(0), levels.get_f32(1), levels.get_f32(2), NAN])
    } else {
      // At least the D2000 has no WB
      Ok([NAN,NAN,NAN,NAN])
    }
  }

  fn convert_to_rgb(&self, cam: &Camera, image: &mut [u16]) -> Result<(),String>{
    let coeffs = try!(self.get_wb(cam));
    let c1 = (1024.0*1024.0/coeffs[0]) as i32;
    let c2 = coeffs[1] as i32;
    let c3 = (1024.0*1024.0/coeffs[2]) as i32;

    for pix in image.chunks_mut(3) {
      let y = pix[0] as i32;
      let cb = pix[1] as i32 - 16383;
      let cr = pix[2] as i32 - 16383;

      let r = c1 * (y + cr);
      let g = c2 * (y + ((-778*cb - (cr<<11)) >> 12));
      let b = c3 * (y + cb);

      pix[0] = clampbits(r >> 8, 16) as u16;
      pix[1] = clampbits(g >> 8, 16) as u16;
      pix[2] = clampbits(b >> 8, 16) as u16;
    }
    Ok(())
  }
}
<|endoftext|>


<commit_before>use protocol::ProtocolId;
use data::{ Value, Type };
use protocol::Shape;
use super::scope::{Item, Scope};
use super::ast;
use super::expr;
use super::{ Ctxt, PrimitiveDef };
use super::eval::Expr;

/// A pattern to match a protocol. These are used in the predicate of `with` blocks.
#[derive(Debug, Clone)]
enum ProtocolMatch<'a> {
    Protocol { id: ProtocolId, param: &'a ast::Expr },
    Type(Type),
    Tup(Vec<ProtocolMatch<'a>>),
    Const(Value),
}

impl<'a> ProtocolMatch<'a> {
    /// Attempt to match the protocol pattern against the supplied shape, returning whether it
    /// succeeded. Destructured variables are added to the scope. Even if it returns false,
    /// the scope may have already been modified.
    fn try_match(&self, ctx: &'a Ctxt<'a>, shape: &Shape, scope: &mut Scope) -> bool {
        debug!("Trying to match {:?} against {:?}", self, shape);
        match (self, shape) {
            (&ProtocolMatch::Protocol { id: l_id, param: l_param }, &Shape::Protocol { def: r_id, param: ref r_param, ..}) => {
                l_id == r_id && expr::lexpr(ctx, scope, l_param, r_param.clone()).is_ok()
            }
            (&ProtocolMatch::Type(ref l_ty), &Shape::Val(ref r_ty)) => {
                l_ty == r_ty
            }
            (&ProtocolMatch::Tup(ref l_items), &Shape::Tup(ref r_items)) => {
                l_items.len() == r_items.len() && l_items.iter().zip(r_items.iter()).all(|(p, s)| p.try_match(ctx, s, scope))
            }
            (&ProtocolMatch::Const(ref l_val), &Shape::Const(ref r_val)) => {
                l_val == r_val
            }
            _ => false
        }
    }
}

pub fn resolve_protocol_invoke<'a>(ctx: &'a Ctxt<'a>, scope: &Scope, ast: &'a ast::ProtocolRef) -> Shape {
    match *ast {
        ast::ProtocolRef::Protocol{ ref name, param: ref param_ast } => {
            if let Some(Item::Protocol(protocol_id)) = scope.get(&name[..]) {
                let protocol = ctx.protocols.get(protocol_id);
                let param = expr::rexpr(ctx, scope, param_ast);

                let mut protocol_def_scope = protocol.scope.child();
                expr::lexpr(ctx, &mut protocol_def_scope, &protocol.ast.param, param.clone())
                    .unwrap_or_else(|e| panic!("failed to match parameters for protocol `{}`: {:?}", name, e));

                let mut messages = vec![];
                for entry in &protocol.ast.entries {
                    match *entry {
                        ast::ProtocolEntry::Message(ref e) => {
                            messages.push(resolve_protocol_invoke(ctx, &protocol_def_scope, e));
                        }
                    }
                }

                Shape::Protocol { def: protocol_id, messages: messages, param }
            } else {
                panic!("Protocol `{}` not found", name);
            }
        }
        ast::ProtocolRef::Type(ref expr) => {
            match expr::value(ctx, scope, expr) {
                Expr::Const(c) => Shape::Const(c),
                e => Shape::Val(e.get_type())
            }
        }
        ast::ProtocolRef::Tup(ref items) => {
            let resolved_items = items.iter().map(|x| resolve_protocol_invoke(ctx, scope, x)).collect::<Vec<_>>();
            if resolved_items.len() == 1 {
                resolved_items.into_iter().next().unwrap()
            } else {
                Shape::Tup(resolved_items)
            }
        }
    }
}

fn resolve_protocol_match<'a>(ctx: &'a Ctxt<'a>, scope: &Scope, ast: &'a ast::ProtocolRef) -> ProtocolMatch<'a> {
    match *ast {
        ast::ProtocolRef::Protocol{ ref name, ref param } => {
            if let Some(Item::Protocol(protocol_id)) = scope.get(&name[..]) {
                ProtocolMatch::Protocol{ id: protocol_id, param: param }
            } else {
                panic!("Protocol `{}` not found", name);
            }
        }
        ast::ProtocolRef::Type(ref expr) => {
            ProtocolMatch::Type(expr::value(ctx, scope, expr).get_type())
        }
        ast::ProtocolRef::Tup(ref items) => {
            let resolved_items = items.iter().map(|x| resolve_protocol_match(ctx, scope, x)).collect::<Vec<_>>();
            if resolved_items.len() == 1 {
                resolved_items.into_iter().next().unwrap()
            } else {
                ProtocolMatch::Tup(resolved_items)
            }
        }
    }
}

struct WithBlock<'a> {
    protocol: ProtocolMatch<'a>,
    name: String,
    param: &'a ast::Expr,
    scope: Scope,
    shape_up: &'a Option<ast::ProtocolRef>,
    implementation: DefImpl<'a>
}

pub enum DefImpl <'a> {
    Code(&'a ast::Block),
    Primitive(Vec<PrimitiveDef>)
 }

pub struct ProtocolScope<'a> {
    entries: Vec<WithBlock<'a>>,
}

impl<'a> ProtocolScope<'a> {
    pub fn new() -> Self {
        ProtocolScope { entries: vec![] }
    }

    pub fn add_def(&mut self, ctx: &'a Ctxt<'a>, scope: Scope, def: &'a ast::Def) {
        self.entries.push(WithBlock {
            protocol: resolve_protocol_match(ctx, &scope, &def.bottom),
            name: def.name.clone(),
            scope: scope,
            param: &def.param,
            shape_up: &def.top,
            implementation: DefImpl::Code(&def.block)
        });
    }

    pub fn add_primitive(&mut self, ctx: &'a Ctxt<'a>, scope: &Scope, header: &'a ast::PrimitiveHeader, defs: Vec<PrimitiveDef>) {
        self.entries.push(WithBlock {
            protocol: resolve_protocol_match(ctx, scope, &header.bottom),
            name: header.name.clone(),
            scope: scope.child(),
            param: &header.param,
            shape_up: &header.top,
            implementation: DefImpl::Primitive(defs),
        });
    }

    pub fn find(&self, ctx: &'a Ctxt<'a>, shape: &Shape, name: &str, param: Item) -> (Scope, &DefImpl<'a>, Shape) {
        let mut found = None;
        for entry in &self.entries {
            if entry.name != name { continue }

            let mut scope = entry.scope.child();

            if !entry.protocol.try_match(ctx, shape, &mut scope) {
                debug!("Failed to match protocol for `{}`", name);
                continue
            }

            if let Err(err) = expr::lexpr(ctx, &mut scope, &entry.param, param.clone()) {
                debug!("Failed to match argument for `{}`: {:?}", name, err);
                continue
            }

            if found.is_none() {
                let shape_up = if let &Some(ref x) = entry.shape_up {
                    resolve_protocol_invoke(ctx, &scope, x)
                } else {
                    Shape::null()
                };

                found = Some((scope, &entry.implementation, shape_up));
            } else {
                panic!("Multiple definition of `{}`", name);
            }
        }
        found.unwrap_or_else(|| panic!("No definition found for `{}`", name))
    }
}
<commit_msg>Allow tuples in protocol variants created from items<commit_after>use protocol::ProtocolId;
use data::{ Value, Type };
use protocol::Shape;
use super::scope::{Item, Scope};
use super::ast;
use super::expr;
use super::{ Ctxt, PrimitiveDef };
use super::eval::Expr;

/// A pattern to match a protocol. These are used in the predicate of `with` blocks.
#[derive(Debug, Clone)]
enum ProtocolMatch<'a> {
    Protocol { id: ProtocolId, param: &'a ast::Expr },
    Type(Type),
    Tup(Vec<ProtocolMatch<'a>>),
    Const(Value),
}

impl<'a> ProtocolMatch<'a> {
    /// Attempt to match the protocol pattern against the supplied shape, returning whether it
    /// succeeded. Destructured variables are added to the scope. Even if it returns false,
    /// the scope may have already been modified.
    fn try_match(&self, ctx: &'a Ctxt<'a>, shape: &Shape, scope: &mut Scope) -> bool {
        debug!("Trying to match {:?} against {:?}", self, shape);
        match (self, shape) {
            (&ProtocolMatch::Protocol { id: l_id, param: l_param }, &Shape::Protocol { def: r_id, param: ref r_param, ..}) => {
                l_id == r_id && expr::lexpr(ctx, scope, l_param, r_param.clone()).is_ok()
            }
            (&ProtocolMatch::Type(ref l_ty), &Shape::Val(ref r_ty)) => {
                l_ty == r_ty
            }
            (&ProtocolMatch::Tup(ref l_items), &Shape::Tup(ref r_items)) => {
                l_items.len() == r_items.len() && l_items.iter().zip(r_items.iter()).all(|(p, s)| p.try_match(ctx, s, scope))
            }
            (&ProtocolMatch::Const(ref l_val), &Shape::Const(ref r_val)) => {
                l_val == r_val
            }
            _ => false
        }
    }
}

fn item_to_shape(item: Item) -> Shape {
    match item {
        Item::Value(Expr::Const(c)) => Shape::Const(c),
        Item::Value(e) => Shape::Val(e.get_type()),
        Item::Tuple(t) => Shape::Tup(t.into_iter().map(item_to_shape).collect()),
        e => panic!("{:?} cannot be converted to Shape", e),
    }
}

pub fn resolve_protocol_invoke<'a>(ctx: &'a Ctxt<'a>, scope: &Scope, ast: &'a ast::ProtocolRef) -> Shape {
    match *ast {
        ast::ProtocolRef::Protocol{ ref name, param: ref param_ast } => {
            if let Some(Item::Protocol(protocol_id)) = scope.get(&name[..]) {
                let protocol = ctx.protocols.get(protocol_id);
                let param = expr::rexpr(ctx, scope, param_ast);

                let mut protocol_def_scope = protocol.scope.child();
                expr::lexpr(ctx, &mut protocol_def_scope, &protocol.ast.param, param.clone())
                    .unwrap_or_else(|e| panic!("failed to match parameters for protocol `{}`: {:?}", name, e));

                let mut messages = vec![];
                for entry in &protocol.ast.entries {
                    match *entry {
                        ast::ProtocolEntry::Message(ref e) => {
                            messages.push(resolve_protocol_invoke(ctx, &protocol_def_scope, e));
                        }
                    }
                }

                Shape::Protocol { def: protocol_id, messages: messages, param }
            } else {
                panic!("Protocol `{}` not found", name);
            }
        }
        ast::ProtocolRef::Type(ref expr) => {
            item_to_shape(expr::rexpr(ctx, scope, expr))
        }
        ast::ProtocolRef::Tup(ref items) => {
            let resolved_items = items.iter().map(|x| resolve_protocol_invoke(ctx, scope, x)).collect::<Vec<_>>();
            if resolved_items.len() == 1 {
                resolved_items.into_iter().next().unwrap()
            } else {
                Shape::Tup(resolved_items)
            }
        }
    }
}

fn resolve_protocol_match<'a>(ctx: &'a Ctxt<'a>, scope: &Scope, ast: &'a ast::ProtocolRef) -> ProtocolMatch<'a> {
    match *ast {
        ast::ProtocolRef::Protocol{ ref name, ref param } => {
            if let Some(Item::Protocol(protocol_id)) = scope.get(&name[..]) {
                ProtocolMatch::Protocol{ id: protocol_id, param: param }
            } else {
                panic!("Protocol `{}` not found", name);
            }
        }
        ast::ProtocolRef::Type(ref expr) => {
            ProtocolMatch::Type(expr::value(ctx, scope, expr).get_type())
        }
        ast::ProtocolRef::Tup(ref items) => {
            let resolved_items = items.iter().map(|x| resolve_protocol_match(ctx, scope, x)).collect::<Vec<_>>();
            if resolved_items.len() == 1 {
                resolved_items.into_iter().next().unwrap()
            } else {
                ProtocolMatch::Tup(resolved_items)
            }
        }
    }
}

struct WithBlock<'a> {
    protocol: ProtocolMatch<'a>,
    name: String,
    param: &'a ast::Expr,
    scope: Scope,
    shape_up: &'a Option<ast::ProtocolRef>,
    implementation: DefImpl<'a>
}

pub enum DefImpl <'a> {
    Code(&'a ast::Block),
    Primitive(Vec<PrimitiveDef>)
 }

pub struct ProtocolScope<'a> {
    entries: Vec<WithBlock<'a>>,
}

impl<'a> ProtocolScope<'a> {
    pub fn new() -> Self {
        ProtocolScope { entries: vec![] }
    }

    pub fn add_def(&mut self, ctx: &'a Ctxt<'a>, scope: Scope, def: &'a ast::Def) {
        self.entries.push(WithBlock {
            protocol: resolve_protocol_match(ctx, &scope, &def.bottom),
            name: def.name.clone(),
            scope: scope,
            param: &def.param,
            shape_up: &def.top,
            implementation: DefImpl::Code(&def.block)
        });
    }

    pub fn add_primitive(&mut self, ctx: &'a Ctxt<'a>, scope: &Scope, header: &'a ast::PrimitiveHeader, defs: Vec<PrimitiveDef>) {
        self.entries.push(WithBlock {
            protocol: resolve_protocol_match(ctx, scope, &header.bottom),
            name: header.name.clone(),
            scope: scope.child(),
            param: &header.param,
            shape_up: &header.top,
            implementation: DefImpl::Primitive(defs),
        });
    }

    pub fn find(&self, ctx: &'a Ctxt<'a>, shape: &Shape, name: &str, param: Item) -> (Scope, &DefImpl<'a>, Shape) {
        let mut found = None;
        for entry in &self.entries {
            if entry.name != name { continue }

            let mut scope = entry.scope.child();

            if !entry.protocol.try_match(ctx, shape, &mut scope) {
                debug!("Failed to match protocol for `{}`", name);
                continue
            }

            if let Err(err) = expr::lexpr(ctx, &mut scope, &entry.param, param.clone()) {
                debug!("Failed to match argument for `{}`: {:?}", name, err);
                continue
            }

            if found.is_none() {
                let shape_up = if let &Some(ref x) = entry.shape_up {
                    resolve_protocol_invoke(ctx, &scope, x)
                } else {
                    Shape::null()
                };

                found = Some((scope, &entry.implementation, shape_up));
            } else {
                panic!("Multiple definition of `{}`", name);
            }
        }
        found.unwrap_or_else(|| panic!("No definition found for `{}`", name))
    }
}
<|endoftext|>