<commit_before>// Copyright 2021 Twitter, Inc.
// Licensed under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

use crate::codec::*;
use crate::config::*;
use crate::config_file::{Protocol, Verb};
use crate::*;

use rand::rngs::SmallRng;
use rand::SeedableRng;

use std::io::{BufRead, Write};
use std::str;

pub enum Mode {
    Inline,
    Resp,
}

pub struct Redis {
    config: Arc<Config>,
    mode: Mode,
    rng: SmallRng,
}

impl Redis {
    pub fn new(config: Arc<Config>) -> Self {
        let mode = match config.general().protocol() {
            Protocol::Redis | Protocol::RedisInline => Mode::Inline,
            Protocol::RedisResp => Mode::Resp,
            unknown => {
                fatal!("protocol: {:?} is not a redis protocol", unknown);
            }
        };
        Self {
            config,
            mode,
            rng: SmallRng::from_entropy(),
        }
    }

    fn command(buf: &mut Session, mode: &Mode, command: &str, args: Vec<Vec<u8>>) {
        match mode {
            Mode::Inline => {
                let _ = buf.write_all(command.to_string().as_bytes());
                for arg in args {
                    let _ = buf.write_all(b" ");
                    let _ = buf.write_all(&arg);
                }
                let _ = buf.write_all(b"\r\n");
            }
            Mode::Resp => {
                let _ = buf.write_all(
                    format!("*{}\r\n${}\r\n{}", 1 + args.len(), command.len(), command).as_bytes(),
                );
                for arg in args {
                    let _ = buf.write_all(format!("\r\n${}\r\n", arg.len()).as_bytes());
                    let _ = buf.write_all(&arg);
                }
                let _ = buf.write_all(b"\r\n");
            }
        }
    }

    fn get(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let args = vec![keyspace.generate_key(rng)];
        Redis::command(buf, mode, "get", args);
    }

    fn mget(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let mut args = Vec::new();
        for _ in 0..keyspace.batch_size() {
            args.push(keyspace.generate_key(rng));
        }
        Redis::command(buf, mode, "mget", args);
    }

    fn set(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "set";
        let mut args = vec![
            keyspace.generate_key(rng),
            keyspace.generate_value(rng).unwrap_or_else(|| b"".to_vec()),
        ];
        let ttl = keyspace.ttl();
        if ttl != 0 {
            args.push(b"EX".to_vec());
            args.push(format!("{}", ttl).as_bytes().to_vec());
        }
        Redis::command(buf, mode, command, args);
    }

    fn del(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let args = vec![keyspace.generate_key(rng)];
        Redis::command(buf, mode, "del", args);
    }

    fn hget(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "hget";
        let args = vec![
            keyspace.generate_key(rng),
            keyspace
                .generate_inner_key(rng)
                .unwrap_or_else(|| b"".to_vec()),
        ];
        Redis::command(buf, mode, command, args);
    }

    fn hset(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "hset";
        let args = vec![
            keyspace.generate_key(rng),
            keyspace
                .generate_inner_key(rng)
                .unwrap_or_else(|| b"".to_vec()),
            keyspace.generate_value(rng).unwrap_or_else(|| b"".to_vec()),
        ];
        Redis::command(buf, mode, command, args);
    }

    fn hsetnx(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "hsetnx";
        let args = vec![
            keyspace.generate_key(rng),
            keyspace
                .generate_inner_key(rng)
                .unwrap_or_else(|| b"".to_vec()),
            keyspace.generate_value(rng).unwrap_or_else(|| b"".to_vec()),
        ];
        Redis::command(buf, mode, command, args);
    }

    fn hdel(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "hdel";
        let args = vec![
            keyspace.generate_key(rng),
            keyspace
                .generate_inner_key(rng)
                .unwrap_or_else(|| b"".to_vec()),
        ];
        Redis::command(buf, mode, command, args);
    }
}

impl Codec for Redis {
    fn encode(&mut self, buf: &mut Session) {
        let keyspace = self.config.choose_keyspace(&mut self.rng);
        let command = keyspace.choose_command(&mut self.rng);
        match command.verb() {
            Verb::Get => {
                metrics::REQUEST_GET.increment();
                if keyspace.batch_size() == 1 {
                    Self::get(&mut self.rng, &self.mode, keyspace, buf)
                } else {
                    Self::mget(&mut self.rng, &self.mode, keyspace, buf)
                }
            }
            Verb::Set => Self::set(&mut self.rng, &self.mode, keyspace, buf),
            Verb::Delete => Self::del(&mut self.rng, &self.mode, keyspace, buf),
            Verb::Hget => {
                metrics::REQUEST_GET.increment();
                Self::hget(&mut self.rng, &self.mode, keyspace, buf)
            }
            Verb::Hset => Self::hset(&mut self.rng, &self.mode, keyspace, buf),
            Verb::Hsetnx => Self::hsetnx(&mut self.rng, &self.mode, keyspace, buf),
            Verb::Hdel => Self::hdel(&mut self.rng, &self.mode, keyspace, buf),
            _ => {
                unimplemented!()
            }
        }
    }

    fn decode(&self, buffer: &mut Session) -> Result<(), ParseError> {
        // no-copy borrow as a slice
        let buf: &[u8] = (*buffer).buffer();

        if buf.len() < 1 {
            return Err(ParseError::Incomplete);
        }

        let first_char = &buf[0..1];
        match str::from_utf8(first_char) {
            Ok("+") => {
                // simple string response
                let mut lines = buf.windows(2);
                if let Some(line_end) = lines.position(|w| w == b"\r\n") {
                    let msg = &buf[1..line_end];
                    match str::from_utf8(msg) {
                        Ok("OK") | Ok("PONG") => {
                            let _ = buffer.consume(line_end + 2);
                            Ok(())
                        }
                        _ => Err(ParseError::Unknown),
                    }
                } else {
                    Err(ParseError::Incomplete)
                }
            }
            Ok("-") => {
                // error response
                Err(ParseError::Error)
            }
            Ok(":") => {
                // numeric response
                let mut lines = buf.windows(2);
                if let Some(line_end) = lines.position(|w| w == b"\r\n") {
                    let msg = &buf[1..line_end];
                    match str::from_utf8(msg) {
                        Ok(msg) => match msg.parse::<i64>() {
                            Ok(_) => {
                                let _ = buffer.consume(line_end + 2);
                                Ok(())
                            }
                            Err(_) => Err(ParseError::Unknown),
                        },
                        Err(_) => Err(ParseError::Unknown),
                    }
                } else {
                    Err(ParseError::Incomplete)
                }
            }
            Ok("$") => {
                // bulk string
                let mut lines = buf.windows(2);
                if let Some(line_end) = lines.position(|w| w == b"\r\n") {
                    let msg = &buf[1..line_end];
                    match str::from_utf8(msg) {
                        Ok("-1") => {
                            let _ = buffer.consume(line_end + 2);
                            Ok(())
                        }
                        Ok(n) => {
                            let len = n.parse::<usize>().map_err(|_| ParseError::Unknown)?;
                            let response_end = len + line_end + 2;
                            if response_end <= buf.len() {
                                metrics::RESPONSE_HIT.increment();
                                let _ = buffer.consume(response_end);
                                Ok(())
                            } else {
                                Err(ParseError::Incomplete)
                            }
                        }
                        Err(_) => Err(ParseError::Unknown),
                    }
                } else {
                    Err(ParseError::Incomplete)
                }
            }
            Ok("*") => {
                // arrays
                let msg = &buf[1..buf.len() - 2];
                match str::from_utf8(msg) {
                    Ok("-1") => {
                        let response_end = buf.len();
                        let _ = buffer.consume(response_end);
                        Ok(())
                    }
                    Ok(_) => {
                        // TODO: implement array parsing
                        Err(ParseError::Unknown)
                    }
                    Err(_) => Err(ParseError::Unknown),
                }
            }
            _ => Err(ParseError::Unknown),
        }
    }
}
<commit_msg>fix: redis bulk string parser (#371)<commit_after>// Copyright 2021 Twitter, Inc.
// Licensed under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

use crate::codec::*;
use crate::config::*;
use crate::config_file::{Protocol, Verb};
use crate::*;

use rand::rngs::SmallRng;
use rand::SeedableRng;

use std::io::{BufRead, Write};
use std::str;

pub enum Mode {
    Inline,
    Resp,
}

pub struct Redis {
    config: Arc<Config>,
    mode: Mode,
    rng: SmallRng,
}

impl Redis {
    pub fn new(config: Arc<Config>) -> Self {
        let mode = match config.general().protocol() {
            Protocol::Redis | Protocol::RedisInline => Mode::Inline,
            Protocol::RedisResp => Mode::Resp,
            unknown => {
                fatal!("protocol: {:?} is not a redis protocol", unknown);
            }
        };
        Self {
            config,
            mode,
            rng: SmallRng::from_entropy(),
        }
    }

    fn command(buf: &mut Session, mode: &Mode, command: &str, args: Vec<Vec<u8>>) {
        match mode {
            Mode::Inline => {
                let _ = buf.write_all(command.to_string().as_bytes());
                for arg in args {
                    let _ = buf.write_all(b" ");
                    let _ = buf.write_all(&arg);
                }
                let _ = buf.write_all(b"\r\n");
            }
            Mode::Resp => {
                let _ = buf.write_all(
                    format!("*{}\r\n${}\r\n{}", 1 + args.len(), command.len(), command).as_bytes(),
                );
                for arg in args {
                    let _ = buf.write_all(format!("\r\n${}\r\n", arg.len()).as_bytes());
                    let _ = buf.write_all(&arg);
                }
                let _ = buf.write_all(b"\r\n");
            }
        }
    }

    fn get(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let args = vec![keyspace.generate_key(rng)];
        Redis::command(buf, mode, "get", args);
    }

    fn mget(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let mut args = Vec::new();
        for _ in 0..keyspace.batch_size() {
            args.push(keyspace.generate_key(rng));
        }
        Redis::command(buf, mode, "mget", args);
    }

    fn set(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "set";
        let mut args = vec![
            keyspace.generate_key(rng),
            keyspace.generate_value(rng).unwrap_or_else(|| b"".to_vec()),
        ];
        let ttl = keyspace.ttl();
        if ttl != 0 {
            args.push(b"EX".to_vec());
            args.push(format!("{}", ttl).as_bytes().to_vec());
        }
        Redis::command(buf, mode, command, args);
    }

    fn del(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let args = vec![keyspace.generate_key(rng)];
        Redis::command(buf, mode, "del", args);
    }

    fn hget(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "hget";
        let args = vec![
            keyspace.generate_key(rng),
            keyspace
                .generate_inner_key(rng)
                .unwrap_or_else(|| b"".to_vec()),
        ];
        Redis::command(buf, mode, command, args);
    }

    fn hset(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "hset";
        let args = vec![
            keyspace.generate_key(rng),
            keyspace
                .generate_inner_key(rng)
                .unwrap_or_else(|| b"".to_vec()),
            keyspace.generate_value(rng).unwrap_or_else(|| b"".to_vec()),
        ];
        Redis::command(buf, mode, command, args);
    }

    fn hsetnx(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "hsetnx";
        let args = vec![
            keyspace.generate_key(rng),
            keyspace
                .generate_inner_key(rng)
                .unwrap_or_else(|| b"".to_vec()),
            keyspace.generate_value(rng).unwrap_or_else(|| b"".to_vec()),
        ];
        Redis::command(buf, mode, command, args);
    }

    fn hdel(rng: &mut SmallRng, mode: &Mode, keyspace: &Keyspace, buf: &mut Session) {
        let command = "hdel";
        let args = vec![
            keyspace.generate_key(rng),
            keyspace
                .generate_inner_key(rng)
                .unwrap_or_else(|| b"".to_vec()),
        ];
        Redis::command(buf, mode, command, args);
    }
}

impl Codec for Redis {
    fn encode(&mut self, buf: &mut Session) {
        let keyspace = self.config.choose_keyspace(&mut self.rng);
        let command = keyspace.choose_command(&mut self.rng);
        match command.verb() {
            Verb::Get => {
                metrics::REQUEST_GET.increment();
                if keyspace.batch_size() == 1 {
                    Self::get(&mut self.rng, &self.mode, keyspace, buf)
                } else {
                    Self::mget(&mut self.rng, &self.mode, keyspace, buf)
                }
            }
            Verb::Set => Self::set(&mut self.rng, &self.mode, keyspace, buf),
            Verb::Delete => Self::del(&mut self.rng, &self.mode, keyspace, buf),
            Verb::Hget => {
                metrics::REQUEST_GET.increment();
                Self::hget(&mut self.rng, &self.mode, keyspace, buf)
            }
            Verb::Hset => Self::hset(&mut self.rng, &self.mode, keyspace, buf),
            Verb::Hsetnx => Self::hsetnx(&mut self.rng, &self.mode, keyspace, buf),
            Verb::Hdel => Self::hdel(&mut self.rng, &self.mode, keyspace, buf),
            _ => {
                unimplemented!()
            }
        }
    }

    fn decode(&self, buffer: &mut Session) -> Result<(), ParseError> {
        // no-copy borrow as a slice
        let buf: &[u8] = (*buffer).buffer();

        if buf.len() < 1 {
            return Err(ParseError::Incomplete);
        }

        let first_char = &buf[0..1];
        match str::from_utf8(first_char) {
            Ok("+") => {
                // simple string response
                let mut lines = buf.windows(2);
                if let Some(line_end) = lines.position(|w| w == b"\r\n") {
                    let msg = &buf[1..line_end];
                    match str::from_utf8(msg) {
                        Ok("OK") | Ok("PONG") => {
                            let _ = buffer.consume(line_end + 2);
                            Ok(())
                        }
                        _ => Err(ParseError::Unknown),
                    }
                } else {
                    Err(ParseError::Incomplete)
                }
            }
            Ok("-") => {
                // error response
                Err(ParseError::Error)
            }
            Ok(":") => {
                // numeric response
                let mut lines = buf.windows(2);
                if let Some(line_end) = lines.position(|w| w == b"\r\n") {
                    let msg = &buf[1..line_end];
                    match str::from_utf8(msg) {
                        Ok(msg) => match msg.parse::<i64>() {
                            Ok(_) => {
                                let _ = buffer.consume(line_end + 2);
                                Ok(())
                            }
                            Err(_) => Err(ParseError::Unknown),
                        },
                        Err(_) => Err(ParseError::Unknown),
                    }
                } else {
                    Err(ParseError::Incomplete)
                }
            }
            Ok("$") => {
                // bulk string
                let mut lines = buf.windows(2);
                if let Some(line_end) = lines.position(|w| w == b"\r\n") {
                    let msg = &buf[1..line_end];
                    match str::from_utf8(msg) {
                        Ok("-1") => {
                            let _ = buffer.consume(line_end + 2);
                            Ok(())
                        }
                        Ok(n) => {
                            let len = n.parse::<usize>().map_err(|_| ParseError::Unknown)?;
                            let response_end = len + line_end + 4;
                            if response_end <= buf.len() {
                                metrics::RESPONSE_HIT.increment();
                                let _ = buffer.consume(response_end);
                                Ok(())
                            } else {
                                Err(ParseError::Incomplete)
                            }
                        }
                        Err(_) => Err(ParseError::Unknown),
                    }
                } else {
                    Err(ParseError::Incomplete)
                }
            }
            Ok("*") => {
                // arrays
                let msg = &buf[1..buf.len() - 2];
                match str::from_utf8(msg) {
                    Ok("-1") => {
                        let response_end = buf.len();
                        let _ = buffer.consume(response_end);
                        Ok(())
                    }
                    Ok(_) => {
                        // TODO: implement array parsing
                        Err(ParseError::Unknown)
                    }
                    Err(_) => Err(ParseError::Unknown),
                }
            }
            _ => Err(ParseError::Unknown),
        }
    }
}
<|endoftext|>


<commit_before>use buffer::operation::Operation;

/// Tracks a series of operations, which can be traversed backwards and forwards.
pub struct History {
    previous: Vec<Box<Operation>>,
    next: Vec<Box<Operation>>,
}

impl History {
    /// Store an operation that has already been run.
    pub fn add(&mut self, operation: Box<Operation>) {
        self.previous.push(operation);
    }

    /// Navigate the history backwards.
    pub fn previous(&mut self) -> Option<Box<Operation>> {
        match self.previous.pop() {
            Some(operation) => {
                // We've found a previous operation. Before we return it, store
                // a clone of it so that we can re-apply it as a redo operation.
                self.next.push(operation.clone_operation());
                Some(operation)
            },
            None => None
        }
    }

    /// Navigate the history forwards.
    pub fn next(&mut self) -> Option<Box<Operation>> {
        self.next.pop()
    }
}

pub fn new() -> History {
    History{ previous: Vec::new(), next: Vec::new() }
}

#[cfg(test)]
mod tests {
    use super::new;
    use buffer::{gap_buffer, Position, operations};
    use buffer::operation::Operation;

    #[test]
    fn previous_and_next_return_the_correct_operations() {
        let mut history = new();

        // Set up a buffer with some data.
        let mut buffer = gap_buffer::new(String::new());

        // Run an insert operation and add it to the history.
        let insert_position = Position{ line: 0, offset: 0 };
        let mut insert_operation = operations::insert::new("scribe".to_string(), insert_position);
        insert_operation.run(&mut buffer);
        history.add(Box::new(insert_operation));

        // Make sure the buffer has the inserted content.
        assert_eq!(buffer.to_string(), "scribe");

        // Pull and reverse the last history item.
        match history.previous() {
            Some(mut operation) => operation.reverse(&mut buffer),
            None => (),
        };

        // Make sure the buffer had the inserted content removed.
        assert_eq!(buffer.to_string(), "");

        // Pull and run the next history item.
        match history.next() {
            Some(mut operation) => operation.run(&mut buffer),
            None => (),
        };

        // Make sure the buffer has the re-inserted content.
        assert_eq!(buffer.to_string(), "scribe");
    }
}
<commit_msg>Update history type's next method to set things up for previous.<commit_after>use buffer::operation::Operation;

/// Tracks a series of operations, which can be traversed backwards and forwards.
pub struct History {
    previous: Vec<Box<Operation>>,
    next: Vec<Box<Operation>>,
}

impl History {
    /// Store an operation that has already been run.
    pub fn add(&mut self, operation: Box<Operation>) {
        self.previous.push(operation);
    }

    /// Navigate the history backwards.
    pub fn previous(&mut self) -> Option<Box<Operation>> {
        match self.previous.pop() {
            Some(operation) => {
                // We've found a previous operation. Before we return it, store a
                // clone of it so that it can be re-applied as a redo operation.
                self.next.push(operation.clone_operation());
                Some(operation)
            },
            None => None
        }
    }

    /// Navigate the history forwards.
    pub fn next(&mut self) -> Option<Box<Operation>> {
        match self.next.pop() {
            Some(operation) => {
                // We've found a subsequent operation. Before we return it, store a
                // clone of it so that it can be re-applied as an undo operation, again.
                self.previous.push(operation.clone_operation());
                Some(operation)
            },
            None => None
        }
    }
}

pub fn new() -> History {
    History{ previous: Vec::new(), next: Vec::new() }
}

#[cfg(test)]
mod tests {
    use super::new;
    use buffer::{gap_buffer, Position, operations};
    use buffer::operation::Operation;

    #[test]
    fn previous_and_next_return_the_correct_operations() {
        let mut history = new();

        // Set up a buffer with some data.
        let mut buffer = gap_buffer::new(String::new());

        // Run an insert operation and add it to the history.
        let insert_position = Position{ line: 0, offset: 0 };
        let mut insert_operation = operations::insert::new("scribe".to_string(), insert_position);
        insert_operation.run(&mut buffer);
        history.add(Box::new(insert_operation));

        // Make sure the buffer has the inserted content.
        assert_eq!(buffer.to_string(), "scribe");

        // Pull and reverse the last history item.
        match history.previous() {
            Some(mut operation) => operation.reverse(&mut buffer),
            None => (),
        };

        // Make sure the buffer had the inserted content removed.
        assert_eq!(buffer.to_string(), "");

        // Pull and run the next history item.
        match history.next() {
            Some(mut operation) => operation.run(&mut buffer),
            None => (),
        };

        // Make sure the buffer has the re-inserted content.
        assert_eq!(buffer.to_string(), "scribe");

        // Pull and reverse the last history item, to make sure
        // the next function properly sets up the previous command.
        match history.previous() {
            Some(mut operation) => operation.reverse(&mut buffer),
            None => (),
        };

        // Make sure the buffer had the inserted content removed.
        assert_eq!(buffer.to_string(), "");
    }
}
<|endoftext|>


<commit_before>//! Squirrel away SBD messages and retrieve them later.

mod filesystem;
mod memory;

pub use self::filesystem::Storage as FilesystemStorage;
pub use self::memory::Storage as MemoryStorage;

use Result;
use mo::Message;

/// Basic storage operations.
pub trait Storage {
    /// Stores a message, consuming it.
    ///
    /// # Examples
    ///
    /// ```
    /// # use sbd::mo::Message;
    /// # use sbd::storage::{Storage, MemoryStorage};
    /// let message = Message::from_path("data/0-mo.sbd").unwrap();
    /// let mut storage = MemoryStorage::new();
    /// storage.store(message);
    /// ```
    fn store(&mut self, message: Message) -> Result<()>;

    /// Retrieves all messages in this storage as a vector.
    ///
    /// # Examples
    ///
    /// ```
    /// # use sbd::mo::Message;
    /// # use sbd::storage::{Storage, MemoryStorage};
    /// let message = Message::from_path("data/0-mo.sbd").unwrap();
    /// let mut storage = MemoryStorage::new();
    /// storage.store(message.clone());
    /// let messages = storage.messages().unwrap();
    /// assert_eq!(vec![message], messages);
    /// ```
    fn messages(&self) -> Result<Vec<Message>>;
}
<commit_msg>Add messages_from_imei method<commit_after>//! Squirrel away SBD messages and retrieve them later.

mod filesystem;
mod memory;

pub use self::filesystem::Storage as FilesystemStorage;
pub use self::memory::Storage as MemoryStorage;

use Result;
use mo::Message;

/// Basic storage operations.
pub trait Storage {
    /// Stores a message, consuming it.
    ///
    /// # Examples
    ///
    /// ```
    /// # use sbd::mo::Message;
    /// # use sbd::storage::{Storage, MemoryStorage};
    /// let message = Message::from_path("data/0-mo.sbd").unwrap();
    /// let mut storage = MemoryStorage::new();
    /// storage.store(message);
    /// ```
    fn store(&mut self, message: Message) -> Result<()>;

    /// Retrieves all messages in this storage as a vector.
    ///
    /// # Examples
    ///
    /// ```
    /// # use sbd::mo::Message;
    /// # use sbd::storage::{Storage, MemoryStorage};
    /// let message = Message::from_path("data/0-mo.sbd").unwrap();
    /// let mut storage = MemoryStorage::new();
    /// storage.store(message.clone());
    /// let messages = storage.messages().unwrap();
    /// assert_eq!(vec![message], messages);
    /// ```
    fn messages(&self) -> Result<Vec<Message>>;

    /// Retrieves all messages for a given IMEI.
    ///
    /// The default implementation just filters the vector provided by `messages`, but some
    /// implementors could be more intelligent.
    ///
    /// # Examples
    ///
    /// ```
    /// # use sbd::mo::Message;
    /// # use sbd::storage::{Storage, MemoryStorage};
    /// let message = Message::from_path("data/0-mo.sbd").unwrap();
    /// let mut storage = MemoryStorage::new();
    /// storage.store(message.clone());
    /// let messages = storage.messages_from_imei("300234063904190").unwrap();
    /// assert_eq!(vec![message], messages);
    /// let messages = storage.messages_from_imei("300234063904191").unwrap();
    /// assert!(messages.is_empty());
    /// ```
    fn messages_from_imei(&self, imei: &str) -> Result<Vec<Message>> {
        self.messages().map(|mut v| {
            v.retain(|m| m.imei() == imei);
            v
        })
    }
}
<|endoftext|>


<commit_before>use util::errors::{
    Result,
    Error,
};

use term::terminfo::TermInfo;
use term::terminfo::parm;
use term::terminfo::parm::{
    Param,
    Variables,
};

// String constants correspond to terminfo capnames and are used inside the module for convenience.
const ENTER_CA: &'static str = "smcup";
const EXIT_CA: &'static str = "rmcup";
const SHOW_CURSOR: &'static str = "cnorm";
const HIDE_CURSOR: &'static str = "civis";
const SET_CURSOR: &'static str = "cup";
const CLEAR: &'static str = "clear";
const RESET: &'static str = "sgr0";
const UNDERLINE: &'static str = "smul";
const BOLD: &'static str = "bold";
const BLINK: &'static str = "blink";
const REVERSE: &'static str = "rev";
const SETFG: &'static str = "setaf";
const SETBG: &'static str = "setab";

// Terminfo keys. These are arrays because the terminfo database from the `term` crate sometimes
// uses the variable name and othertimes the capname.
//
// Arrays are formatted as ["variable_name", "cap_name"].
const KEY_F1: &'static [&'static str] = &["key_f1", "kf1"];
const KEY_F2: &'static [&'static str] = &["key_f2", "kf2"];
const KEY_F3: &'static [&'static str] = &["key_f3", "kf3"];
const KEY_F4: &'static [&'static str] = &["key_f4", "kf4"];
const KEY_F5: &'static [&'static str] = &["key_f5", "kf5"];
const KEY_F6: &'static [&'static str] = &["key_f6", "kf6"];
const KEY_F7: &'static [&'static str] = &["key_f7", "kf7"];
const KEY_F8: &'static [&'static str] = &["key_f8", "kf8"];
const KEY_F9: &'static [&'static str] = &["key_f9", "kf9"];
const KEY_F10: &'static [&'static str] = &["key_f10", "kf10"];
const KEY_F11: &'static [&'static str] = &["key_f11", "kf11"];
const KEY_F12: &'static [&'static str] = &["key_f12", "kf12"];
const KEY_UP: &'static [&'static str] = &["key_up", "kcuu1"];
const KEY_DOWN: &'static [&'static str] = &["key_down", "kcud1"];
const KEY_LEFT: &'static [&'static str] = &["key_left", "kcub1"];
const KEY_RIGHT: &'static [&'static str] = &["key_right", "kcuf1"];

// Array of terminal keys.
const KEYS: &'static [&'static [&'static str]] = &[
    KEY_F1,
    KEY_F2,
    KEY_F3,
    KEY_F4,
    KEY_F5,
    KEY_F6,
    KEY_F7,
    KEY_F8,
    KEY_F9,
    KEY_F10,
    KEY_F11,
    KEY_F12,
    KEY_UP,
    KEY_DOWN,
    KEY_LEFT,
    KEY_RIGHT,
];

// Array of terminal capabilities. Used as an iterator to test for functionality.
//
// At the moment all functionality is required, however in the future we should implement optional
// functionality checks so the absence of underlining or reverse video doesn't cause initialization
// to fail.
//
// TODO: Optional functionality testing.
const CAPABILITIES: &'static [&'static str] = &[
    ENTER_CA,
    EXIT_CA,
    SHOW_CURSOR,
    HIDE_CURSOR,
    SET_CURSOR,
    CLEAR,
    RESET,
    UNDERLINE,
    BOLD,
    REVERSE,
    SETFG,
    SETBG,
];

// Driver capabilities are an enum instead of string constants (there are string constants private
// to the module however, those are only used for naming convenience and disambiguation)
// to take advantage of compile-time type-checking instead of hoping invalid strings aren't passed.
// This allows us to guarantee that driver accesses will succeed. In addition, using an enum means
// Driver doesn't need hard-coded methods for each capability we want to use.
#[allow(dead_code)]
pub enum DevFn {
    EnterCa,
    ExitCa,
    ShowCursor,
    HideCursor,
    SetCursor(usize, usize),
    Clear,
    Reset,
    Underline,
    Bold,
    Blink,
    Reverse,
    SetFg(u8),
    SetBg(u8),
}

impl DevFn {
    fn as_str(&self) -> &'static str {
        match *self {
            DevFn::EnterCa => ENTER_CA,
            DevFn::ExitCa => EXIT_CA,
            DevFn::ShowCursor => SHOW_CURSOR,
            DevFn::HideCursor => HIDE_CURSOR,
            DevFn::SetCursor(..) => SET_CURSOR,
            DevFn::Clear => CLEAR,
            DevFn::Reset => RESET,
            DevFn::Underline => UNDERLINE,
            DevFn::Bold => BOLD,
            DevFn::Blink => BLINK,
            DevFn::Reverse => REVERSE,
            DevFn::SetFg(..) => SETFG,
            DevFn::SetBg(..) => SETBG,
        }
    }
}

pub struct Driver {
    tinfo: &'static TermInfo,
}

// We will never need to mutate the terminfo database, and it is only used internally as a lookup
// table for the driver. `lazy_static` seems to be the best approach at the moment.
lazy_static! {
    static ref TINFO: TermInfo = {
        TermInfo::from_env().unwrap_or({
            TermInfo {
                names: Default::default(),
                bools: Default::default(),
                numbers: Default::default(),
                strings: Default::default(),
            }
        })
    };
}

// Validates and returns a reference to the terminfo database.
//
// If this function returns Ok(..), the contained terminfo database is guaranteed to have the
// functionality found in CAPABILITIES.
//
// If this function returns Err(..), the terminfo database did not contain all the required
// functionality; the error returned will provide more specific detail.
fn get_tinfo() -> Result<&'static TermInfo> {
    let tinfo = &*TINFO;

    for capname in CAPABILITIES {
        if !tinfo.strings.contains_key(*capname) {
            return Err(Error::new(format!("terminal missing capability: '{}'", capname)));
        }
    }
    Ok(tinfo)
}

impl Driver {
    // Creates a new `Driver`
    //
    // If successful, the terminfo database is guaranteed to contain all capabilities we support.
    pub fn new() -> Result<Driver> {
        let tinfo = try!(get_tinfo());
        Ok(Driver {
            tinfo: tinfo,
        })
    }

    // Returns the device specific escape sequence for the given `DevFn`.
    //
    // get() will not return an error, and (in theory) should never panic. The `DevFn` enum
    // restricts possible inputs to a subset that will not fail when passed to `parm::expand()`.
    // This can be verified by examining the source of the `parm::expand()` function in the `term`
    // crate.
    //
    // Furthermore, the pre-flight checks on initialization of `Driver` ensure that every
    // capability is present, thus the call to `Hashmap::get()` should never fail.
    pub fn get(&self, dfn: DevFn) -> Vec<u8> {
        let capname = dfn.as_str();
        let cap = self.tinfo.strings.get(capname).unwrap();

        match dfn {
            DevFn::SetFg(attr) | DevFn::SetBg(attr) => {
                let params = &[Param::Number(attr as i16)];
                let mut vars = Variables::new();
                parm::expand(cap, params, &mut vars).unwrap()
            },
            DevFn::SetCursor(x, y) => {
                let params = &[Param::Number(y as i16), Param::Number(x as i16)];
                let mut vars = Variables::new();
                parm::expand(cap, params, &mut vars).unwrap()
            },
            _ => {
                cap.clone()
            },
        }
    }
}

<commit_msg>allow dead code for the moment<commit_after>#![allow(dead_code)]

use util::errors::{
    Result,
    Error,
};

use term::terminfo::TermInfo;
use term::terminfo::parm;
use term::terminfo::parm::{
    Param,
    Variables,
};

// String constants correspond to terminfo capnames and are used inside the module for convenience.
const ENTER_CA: &'static str = "smcup";
const EXIT_CA: &'static str = "rmcup";
const SHOW_CURSOR: &'static str = "cnorm";
const HIDE_CURSOR: &'static str = "civis";
const SET_CURSOR: &'static str = "cup";
const CLEAR: &'static str = "clear";
const RESET: &'static str = "sgr0";
const UNDERLINE: &'static str = "smul";
const BOLD: &'static str = "bold";
const BLINK: &'static str = "blink";
const REVERSE: &'static str = "rev";
const SETFG: &'static str = "setaf";
const SETBG: &'static str = "setab";

// Terminfo keys. These are arrays because the terminfo database from the `term` crate sometimes
// uses the variable name and othertimes the capname.
//
// Arrays are formatted as ["variable_name", "cap_name"].
const KEY_F1: &'static [&'static str] = &["key_f1", "kf1"];
const KEY_F2: &'static [&'static str] = &["key_f2", "kf2"];
const KEY_F3: &'static [&'static str] = &["key_f3", "kf3"];
const KEY_F4: &'static [&'static str] = &["key_f4", "kf4"];
const KEY_F5: &'static [&'static str] = &["key_f5", "kf5"];
const KEY_F6: &'static [&'static str] = &["key_f6", "kf6"];
const KEY_F7: &'static [&'static str] = &["key_f7", "kf7"];
const KEY_F8: &'static [&'static str] = &["key_f8", "kf8"];
const KEY_F9: &'static [&'static str] = &["key_f9", "kf9"];
const KEY_F10: &'static [&'static str] = &["key_f10", "kf10"];
const KEY_F11: &'static [&'static str] = &["key_f11", "kf11"];
const KEY_F12: &'static [&'static str] = &["key_f12", "kf12"];
const KEY_UP: &'static [&'static str] = &["key_up", "kcuu1"];
const KEY_DOWN: &'static [&'static str] = &["key_down", "kcud1"];
const KEY_LEFT: &'static [&'static str] = &["key_left", "kcub1"];
const KEY_RIGHT: &'static [&'static str] = &["key_right", "kcuf1"];

// Array of terminal keys.
const KEYS: &'static [&'static [&'static str]] = &[
    KEY_F1,
    KEY_F2,
    KEY_F3,
    KEY_F4,
    KEY_F5,
    KEY_F6,
    KEY_F7,
    KEY_F8,
    KEY_F9,
    KEY_F10,
    KEY_F11,
    KEY_F12,
    KEY_UP,
    KEY_DOWN,
    KEY_LEFT,
    KEY_RIGHT,
];

// Array of terminal capabilities. Used as an iterator to test for functionality.
//
// At the moment all functionality is required, however in the future we should implement optional
// functionality checks so the absence of underlining or reverse video doesn't cause initialization
// to fail.
//
// TODO: Optional functionality testing.
const CAPABILITIES: &'static [&'static str] = &[
    ENTER_CA,
    EXIT_CA,
    SHOW_CURSOR,
    HIDE_CURSOR,
    SET_CURSOR,
    CLEAR,
    RESET,
    UNDERLINE,
    BOLD,
    REVERSE,
    SETFG,
    SETBG,
];

// Driver capabilities are an enum instead of string constants (there are string constants private
// to the module however, those are only used for naming convenience and disambiguation)
// to take advantage of compile-time type-checking instead of hoping invalid strings aren't passed.
// This allows us to guarantee that driver accesses will succeed. In addition, using an enum means
// Driver doesn't need hard-coded methods for each capability we want to use.
#[allow(dead_code)]
pub enum DevFn {
    EnterCa,
    ExitCa,
    ShowCursor,
    HideCursor,
    SetCursor(usize, usize),
    Clear,
    Reset,
    Underline,
    Bold,
    Blink,
    Reverse,
    SetFg(u8),
    SetBg(u8),
}

impl DevFn {
    fn as_str(&self) -> &'static str {
        match *self {
            DevFn::EnterCa => ENTER_CA,
            DevFn::ExitCa => EXIT_CA,
            DevFn::ShowCursor => SHOW_CURSOR,
            DevFn::HideCursor => HIDE_CURSOR,
            DevFn::SetCursor(..) => SET_CURSOR,
            DevFn::Clear => CLEAR,
            DevFn::Reset => RESET,
            DevFn::Underline => UNDERLINE,
            DevFn::Bold => BOLD,
            DevFn::Blink => BLINK,
            DevFn::Reverse => REVERSE,
            DevFn::SetFg(..) => SETFG,
            DevFn::SetBg(..) => SETBG,
        }
    }
}

pub struct Driver {
    tinfo: &'static TermInfo,
}

// We will never need to mutate the terminfo database, and it is only used internally as a lookup
// table for the driver. `lazy_static` seems to be the best approach at the moment.
lazy_static! {
    static ref TINFO: TermInfo = {
        TermInfo::from_env().unwrap_or({
            TermInfo {
                names: Default::default(),
                bools: Default::default(),
                numbers: Default::default(),
                strings: Default::default(),
            }
        })
    };
}

// Validates and returns a reference to the terminfo database.
//
// If this function returns Ok(..), the contained terminfo database is guaranteed to have the
// functionality found in CAPABILITIES.
//
// If this function returns Err(..), the terminfo database did not contain all the required
// functionality; the error returned will provide more specific detail.
fn get_tinfo() -> Result<&'static TermInfo> {
    let tinfo = &*TINFO;

    for capname in CAPABILITIES {
        if !tinfo.strings.contains_key(*capname) {
            return Err(Error::new(format!("terminal missing capability: '{}'", capname)));
        }
    }
    Ok(tinfo)
}

impl Driver {
    // Creates a new `Driver`
    //
    // If successful, the terminfo database is guaranteed to contain all capabilities we support.
    pub fn new() -> Result<Driver> {
        let tinfo = try!(get_tinfo());
        Ok(Driver {
            tinfo: tinfo,
        })
    }

    // Returns the device specific escape sequence for the given `DevFn`.
    //
    // get() will not return an error, and (in theory) should never panic. The `DevFn` enum
    // restricts possible inputs to a subset that will not fail when passed to `parm::expand()`.
    // This can be verified by examining the source of the `parm::expand()` function in the `term`
    // crate.
    //
    // Furthermore, the pre-flight checks on initialization of `Driver` ensure that every
    // capability is present, thus the call to `Hashmap::get()` should never fail.
    pub fn get(&self, dfn: DevFn) -> Vec<u8> {
        let capname = dfn.as_str();
        let cap = self.tinfo.strings.get(capname).unwrap();

        match dfn {
            DevFn::SetFg(attr) | DevFn::SetBg(attr) => {
                let params = &[Param::Number(attr as i16)];
                let mut vars = Variables::new();
                parm::expand(cap, params, &mut vars).unwrap()
            },
            DevFn::SetCursor(x, y) => {
                let params = &[Param::Number(y as i16), Param::Number(x as i16)];
                let mut vars = Variables::new();
                parm::expand(cap, params, &mut vars).unwrap()
            },
            _ => {
                cap.clone()
            },
        }
    }
}

<|endoftext|>


<commit_before>#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box {
        #[serde(with = "urdf_vec3")]
        size: [f64; 3],
    },
    Cylinder { radius: f64, length: f64 },
    Capsule { radius: f64, length: f64 },
    Sphere { radius: f64 },
    Mesh {
        filename: String,
        #[serde(default = "default_scale")]
        #[serde(with = "urdf_vec3")]
        scale: [f64; 3],
    },
}

fn default_scale() -> [f64; 3] {
    [1.0f64; 3]
}

fn default_one() -> f64 {
    1.0f64
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box { size: [0.0f64, 0.0, 0.0] }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Color {
    #[serde(with = "urdf_vec4")]
    #[serde(default = "default_rgba")]
    pub rgba: [f64; 4],
}

#[derive(Debug, Deserialize, Clone)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture { filename: "".to_string() }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub color: Color,
    #[serde(default)]
    pub texture: Texture,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default)]
    pub material: Material,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
}

/// Urdf Link element
/// See http://wiki.ros.org/urdf/XML/link for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Vec<Visual>,
    #[serde(default)]
    pub collision: Vec<Collision>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Vec3 {
    #[serde(with = "urdf_vec3")]
    pub data: [f64; 3],
}

mod urdf_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<D>(deserializer: D) -> Result<[f64; 3], D::Error>
    where
        D: Deserializer,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s.split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 3 {
            return Err(serde::de::Error::custom(
                format!("failed to parse float array in {}", s),
            ));
        }
        let mut arr = [0.0f64; 3];
        for i in 0..3 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

mod urdf_vec4 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<D>(deserializer: D) -> Result<[f64; 4], D::Error>
    where
        D: Deserializer,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s.split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 4 {
            return Err(serde::de::Error::custom(
                format!("failed to parse float array in {}", s),
            ));
        }
        let mut arr = [0.0f64; 4];
        for i in 0..4 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Axis {
    #[serde(with = "urdf_vec3")]
    pub xyz: [f64; 3],
}

impl Default for Axis {
    fn default() -> Axis {
        Axis { xyz: [1.0f64, 0.0, 0.0] }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Pose {
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub xyz: [f64; 3],
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub rpy: [f64; 3],
}

fn default_zero3() -> [f64; 3] {
    [0.0f64, 0.0, 0.0]
}

fn default_rgba() -> [f64; 4] {
    [1.0f64, 1.0, 1.0, 1.0]
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: default_zero3(),
            rpy: default_zero3(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
    Free,
    Spherical,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    #[serde(default)]
    pub effort: f64,
    #[serde(default)]
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mimic {
    pub joint: String,
    #[serde(default = "default_one")]
    pub multiplier: f64,
    #[serde(default)]
    pub offset: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct SafetyController {
    #[serde(default)]
    pub soft_lower_limit: f64,
    #[serde(default)]
    pub soft_upper_limit: f64,
    #[serde(default)]
    pub k_position: f64,
    pub k_velocity: f64,
}

/// Urdf Joint element
/// See http://wiki.ros.org/urdf/XML/joint for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    #[serde(default)]
    pub limit: JointLimit,
    #[serde(default)]
    pub dynamics: Dynamics,
    #[serde(default)]
    pub mimic: Mimic,
    #[serde(default)]
    pub safety_controller: SafetyController,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Dynamics {
    #[serde(default)]
    pub damping: f64,
    #[serde(default)]
    pub friction: f64,
}

/// Top level struct to access urdf.
#[derive(Debug, Deserialize, Clone)]
pub struct Robot {
    #[serde(default)]
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,

    #[serde(rename = "material", default)]
    pub materials: Vec<Material>,
}
<commit_msg>remove free again, can use 'floating' now<commit_after>#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box {
        #[serde(with = "urdf_vec3")]
        size: [f64; 3],
    },
    Cylinder { radius: f64, length: f64 },
    Capsule { radius: f64, length: f64 },
    Sphere { radius: f64 },
    Mesh {
        filename: String,
        #[serde(default = "default_scale")]
        #[serde(with = "urdf_vec3")]
        scale: [f64; 3],
    },
}

fn default_scale() -> [f64; 3] {
    [1.0f64; 3]
}

fn default_one() -> f64 {
    1.0f64
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box { size: [0.0f64, 0.0, 0.0] }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Color {
    #[serde(with = "urdf_vec4")]
    #[serde(default = "default_rgba")]
    pub rgba: [f64; 4],
}

#[derive(Debug, Deserialize, Clone)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture { filename: "".to_string() }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub color: Color,
    #[serde(default)]
    pub texture: Texture,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default)]
    pub material: Material,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
}

/// Urdf Link element
/// See http://wiki.ros.org/urdf/XML/link for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Vec<Visual>,
    #[serde(default)]
    pub collision: Vec<Collision>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Vec3 {
    #[serde(with = "urdf_vec3")]
    pub data: [f64; 3],
}

mod urdf_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<D>(deserializer: D) -> Result<[f64; 3], D::Error>
    where
        D: Deserializer,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s.split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 3 {
            return Err(serde::de::Error::custom(
                format!("failed to parse float array in {}", s),
            ));
        }
        let mut arr = [0.0f64; 3];
        for i in 0..3 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

mod urdf_vec4 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<D>(deserializer: D) -> Result<[f64; 4], D::Error>
    where
        D: Deserializer,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s.split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 4 {
            return Err(serde::de::Error::custom(
                format!("failed to parse float array in {}", s),
            ));
        }
        let mut arr = [0.0f64; 4];
        for i in 0..4 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Axis {
    #[serde(with = "urdf_vec3")]
    pub xyz: [f64; 3],
}

impl Default for Axis {
    fn default() -> Axis {
        Axis { xyz: [1.0f64, 0.0, 0.0] }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Pose {
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub xyz: [f64; 3],
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub rpy: [f64; 3],
}

fn default_zero3() -> [f64; 3] {
    [0.0f64, 0.0, 0.0]
}

fn default_rgba() -> [f64; 4] {
    [1.0f64, 1.0, 1.0, 1.0]
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: default_zero3(),
            rpy: default_zero3(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
    Spherical,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    #[serde(default)]
    pub effort: f64,
    #[serde(default)]
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mimic {
    pub joint: String,
    #[serde(default = "default_one")]
    pub multiplier: f64,
    #[serde(default)]
    pub offset: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct SafetyController {
    #[serde(default)]
    pub soft_lower_limit: f64,
    #[serde(default)]
    pub soft_upper_limit: f64,
    #[serde(default)]
    pub k_position: f64,
    pub k_velocity: f64,
}

/// Urdf Joint element
/// See http://wiki.ros.org/urdf/XML/joint for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    #[serde(default)]
    pub limit: JointLimit,
    #[serde(default)]
    pub dynamics: Dynamics,
    #[serde(default)]
    pub mimic: Mimic,
    #[serde(default)]
    pub safety_controller: SafetyController,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Dynamics {
    #[serde(default)]
    pub damping: f64,
    #[serde(default)]
    pub friction: f64,
}

/// Top level struct to access urdf.
#[derive(Debug, Deserialize, Clone)]
pub struct Robot {
    #[serde(default)]
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,

    #[serde(rename = "material", default)]
    pub materials: Vec<Material>,
}
<|endoftext|>


<commit_before>extern crate image;

use self::image::ImageBuffer;

use std::fs::File;
use std::path::PathBuf;
use std::cmp;

pub fn prime_filter_to_spiral_png(x_size: usize, from_vec: Vec<bool>, path: String){
    let imgbuf = make_spiral_buffer(x_size, from_vec);
    let mut w_path = PathBuf::from(path);

    w_path.push(format!("ulam_spiral{}", x_size));
    w_path.set_extension("png");

    let ref mut four = File::create(w_path).unwrap();

    let _ = image::ImageLuma8(imgbuf).save(four, image::PNG);
}
fn point_on_spiral_to_array_index_end(spiral_size: usize, x: usize, y: usize)->usize{
    let ss_minus_one = spiral_size-1;
    match (x, y) {
        (x, y) if y == 0 => x,
        (x, y) if x == 0 => ss_minus_one*4 - y,
        (x, y) if y == spiral_size-1 => ss_minus_one*3 - x,
        (x, y) if x == spiral_size-1 => ss_minus_one + y,
        (x, y) => {
            let skip_loop_num = cmp::min(cmp::min(x, y), cmp::min(ss_minus_one-x, ss_minus_one-y));
            (2*spiral_size - skip_loop_num)*skip_loop_num + point_on_spiral_to_array_index_end(
                    spiral_size-2*skip_loop_num, x-skip_loop_num, y-skip_loop_num)
        },
    }

}
fn point_on_spiral_to_array_index(spiral_size: usize, x: usize, y: usize)->usize{
    spiral_size*spiral_size - point_on_spiral_to_array_index_end(spiral_size, x, y)
}
fn make_spiral_buffer(x_size: usize, from_vec: Vec<bool>)->
                    ImageBuffer<image::Luma<u8>, Vec<u8>>{
    assert_eq!(from_vec.len(), x_size*x_size+1);
    let img = ImageBuffer::from_fn(x_size as u32, x_size as u32, |x, y| {
        match from_vec[point_on_spiral_to_array_index(x_size, x as usize, y as usize)] {
            true  => image::Luma([0u8]),
            false => image::Luma([255u8]),
        }
    });
    img
}
<commit_msg>Revert "Fixed recursion stack problem."<commit_after>extern crate image;

use self::image::ImageBuffer;

use std::fs::File;
use std::path::PathBuf;

pub fn prime_filter_to_spiral_png(x_size: usize, from_vec: Vec<bool>, path: String){
    let imgbuf = make_spiral_buffer(x_size, from_vec);
    let mut w_path = PathBuf::from(path);

    w_path.push(format!("ulam_spiral{}", x_size));
    w_path.set_extension("png");

    let ref mut four = File::create(w_path).unwrap();

    let _ = image::ImageLuma8(imgbuf).save(four, image::PNG);
}
fn point_on_spiral_to_array_index_end(spiral_size: usize, x: usize, y: usize)->usize{
    let ss_minus_one = spiral_size-1;
    match (x, y) {
        (x, y) if y == 0 => x,
        (x, y) if x == 0 => ss_minus_one*4 - y,
        (x, y) if y == spiral_size-1 => ss_minus_one*3 - x,
        (x, y) if x == spiral_size-1 => ss_minus_one + y,
        (x, y) => ss_minus_one*4 + point_on_spiral_to_array_index_end(spiral_size-2, x-1, y-1),
    }

}
fn point_on_spiral_to_array_index(spiral_size: usize, x: usize, y: usize)->usize{
    spiral_size*spiral_size - point_on_spiral_to_array_index_end(spiral_size, x, y)
}
fn make_spiral_buffer(x_size: usize, from_vec: Vec<bool>)->
                    ImageBuffer<image::Luma<u8>, Vec<u8>>{
    assert_eq!(from_vec.len(), x_size*x_size+1);
    let img = ImageBuffer::from_fn(x_size as u32, x_size as u32, |x, y| {
        match from_vec[point_on_spiral_to_array_index(x_size, x as usize, y as usize)] {
            true  => image::Luma([0u8]),
            false => image::Luma([255u8]),
        }
    });
    img
}
<|endoftext|>


<commit_before>use chrono::{DateTime, UTC};
use common::{ApiError, Body, Credentials, Deleted, Query, Status,
             discovery_api};
use hyper::method::Method::{Delete, Get, Post};
use serde_json::de::from_str;
use serde_json::ser::to_string;

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct Capacity {
    pub used_bytes: u64,
    pub total_bytes: u64,
    pub used: String,
    pub total: String,
    pub percent_used: f64,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct IndexCapacity {
    pub disk_usage: Capacity,
    pub memory_usage: Capacity,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct DeletedEnvironment {
    pub environment_id: String,
    pub status: Deleted,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct NewEnvironment {
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    pub size: u64,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct Environment {
    pub environment_id: String,
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    pub created: DateTime<UTC>,
    pub updated: DateTime<UTC>,
    pub status: Status,
    pub read_only: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub index_capacity: Option<IndexCapacity>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct Environments {
    pub environments: Vec<Environment>,
}

pub fn list(creds: &Credentials) -> Result<Environments, ApiError> {
    let res =
        discovery_api(creds, Get, "/v1/environments", Query::None, Body::None)?;
    Ok(from_str(&res)?)
}

pub fn detail(creds: &Credentials,
              env_id: &str)
              -> Result<Environment, ApiError> {
    let path = "/v1/environments/".to_string() + env_id;
    let res = discovery_api(creds, Get, &path, Query::None, Body::None)?;
    Ok(from_str(&res)?)
}

pub fn create(creds: &Credentials,
              options: &NewEnvironment)
              -> Result<Environment, ApiError> {
    let request_body = to_string(options)
        .expect("Internal error: failed to convert NewEnvironment into JSON");
    let res = discovery_api(creds,
                            Post,
                            "/v1/environments",
                            Query::None,
                            Body::Json(&request_body))?;
    Ok(from_str(&res)?)
}

pub fn delete(creds: &Credentials,
              env_id: &str)
              -> Result<DeletedEnvironment, ApiError> {
    let path = "/v1/environments/".to_string() + env_id;
    let res = discovery_api(creds, Delete, &path, Query::None, Body::None)?;
    Ok(from_str(&res)?)
}
<commit_msg>Support "size" for Environment<commit_after>use chrono::{DateTime, UTC};
use common::{ApiError, Body, Credentials, Deleted, Query, Status,
             discovery_api};
use hyper::method::Method::{Delete, Get, Post};
use serde_json::de::from_str;
use serde_json::ser::to_string;

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct Capacity {
    pub used_bytes: u64,
    pub total_bytes: u64,
    pub used: String,
    pub total: String,
    pub percent_used: f64,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct IndexCapacity {
    pub disk_usage: Capacity,
    pub memory_usage: Capacity,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct DeletedEnvironment {
    pub environment_id: String,
    pub status: Deleted,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct NewEnvironment {
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    pub size: u64,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct Environment {
    pub environment_id: String,
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    pub created: DateTime<UTC>,
    pub updated: DateTime<UTC>,
    pub status: Status,
    pub read_only: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub size: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub index_capacity: Option<IndexCapacity>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct Environments {
    pub environments: Vec<Environment>,
}

pub fn list(creds: &Credentials) -> Result<Environments, ApiError> {
    let res =
        discovery_api(creds, Get, "/v1/environments", Query::None, Body::None)?;
    Ok(from_str(&res)?)
}

pub fn detail(creds: &Credentials,
              env_id: &str)
              -> Result<Environment, ApiError> {
    let path = "/v1/environments/".to_string() + env_id;
    let res = discovery_api(creds, Get, &path, Query::None, Body::None)?;
    Ok(from_str(&res)?)
}

pub fn create(creds: &Credentials,
              options: &NewEnvironment)
              -> Result<Environment, ApiError> {
    let request_body = to_string(options)
        .expect("Internal error: failed to convert NewEnvironment into JSON");
    let res = discovery_api(creds,
                            Post,
                            "/v1/environments",
                            Query::None,
                            Body::Json(&request_body))?;
    Ok(from_str(&res)?)
}

pub fn delete(creds: &Credentials,
              env_id: &str)
              -> Result<DeletedEnvironment, ApiError> {
    let path = "/v1/environments/".to_string() + env_id;
    let res = discovery_api(creds, Delete, &path, Query::None, Body::None)?;
    Ok(from_str(&res)?)
}
<|endoftext|>


<commit_before>//! Constructions related to feed-forward networks

use std::cmp::min;

use num::{Float, one, zero};

use {Compute, BackpropTrain, SupervisedTrain};
use activations::ActivationFunction;
use training::{PerceptronRule, GradientDescent};

/// A feedforward layer
pub struct FeedforwardLayer<F: Float, V: Fn(F) -> F, D: Fn(F) -> F> {
    inputs: usize,
    coeffs: Vec<F>,
    biases: Vec<F>,
    activation: ActivationFunction<F, V, D>
}

impl<F, V, D> FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    /// Creates a new linear feedforward layer with all its weights set
    /// to 1 and its biases set to 0
    pub fn new(inputs: usize,
               outputs: usize,
               activation: ActivationFunction<F, V, D>)
        -> FeedforwardLayer<F, V, D>
    {
        FeedforwardLayer {
            inputs: inputs,
            coeffs: vec![one(); inputs*outputs],
            biases: vec![zero(); outputs],
            activation: activation
        }
    }

    /// Creates a new linear feedforward layer with all its weights and biases
    /// generated by provided closure (for example a random number generator).
    pub fn new_from<G>(inputs: usize,
                       outputs: usize,
                       activation: ActivationFunction<F, V, D>,
                       mut generator: G)
        -> FeedforwardLayer<F, V, D>
        where G: FnMut() -> F
    {
        FeedforwardLayer {
            inputs: inputs,
            coeffs: (0..inputs*outputs).map(|_| generator()).collect(),
            biases: (0..outputs).map(|_| generator()).collect(),
            activation: activation
        }
    }
}

impl<F, V, D> Compute<F> for FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    fn compute(&self, input: &[F]) -> Vec<F> {
        let mut out = self.biases.clone();
        for j in 0..self.biases.len() {
            for i in 0..min(self.inputs, input.len()) {
                out[j] = out[j] + self.coeffs[j*self.inputs + i] * input[i]
            }
        }

        for o in &mut out {
            *o = (self.activation.value)(*o);
        }

        out
    }

    fn input_size(&self) -> usize {
        self.inputs
    }

    fn output_size(&self) -> usize {
        self.biases.len()
    }
}

impl<F, V, D> SupervisedTrain<F, PerceptronRule<F>> for FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    fn supervised_train(&mut self,
                        rule: &PerceptronRule<F>,
                        input: &[F],
                        target: &[F])
    {
        let out = self.compute(input);
        for j in 0..self.biases.len() {
            let diff = target.get(j).map(|v| *v).unwrap_or(zero()) - out[j];
            for i in 0..min(self.inputs, input.len()) {
                self.coeffs[i + j*self.inputs] =
                    self.coeffs[i + j*self.inputs] + rule.rate * diff * input[i];
            }
        }
    }
}

impl<F, V, D> BackpropTrain<F, GradientDescent<F>> for FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    fn backprop_train(&mut self,
                      rule: &GradientDescent<F>,
                      input: &[F],
                      target: &[F])
        -> Vec<F>
    {
        // we need to compute the intermediate states
        let mut out = self.biases.clone();
        for j in 0..self.biases.len() {
            for i in 0..min(self.inputs, input.len()) {
                out[j] = out[j] + self.coeffs[j*self.inputs + i] * input[i]
            }
        }

        let deltas = out.iter()
                            .map(|x| { (self.activation.derivative)(*x) })
                            .collect::<Vec<_>>();
        for o in &mut out {
            *o = (self.activation.value)(*o);
        }

        let mut returned = input.to_owned();
        for j in 0..self.biases.len() {
            for i in 0..min(self.inputs, input.len()) {
                returned[i] = returned[i] - self.coeffs[i + j*self.inputs]*deltas[j];
                self.coeffs[i + j*self.inputs] =
                    self.coeffs[i + j*self.inputs]
                    - rule.rate * input.get(i).map(|x| *x).unwrap_or(zero())
                                * deltas[j]
                                * ( out[j] - target.get(j).map(|x| *x).unwrap_or(zero()) )

            }
        }
        returned
    }
}

impl<F, V, D> SupervisedTrain<F, GradientDescent<F>> for FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    fn supervised_train(&mut self,
                        rule: &GradientDescent<F>,
                        input: &[F],
                        target: &[F])
    {
        self.backprop_train(rule, input, target);
    }
}

#[cfg(test)]
mod tests {
    use Compute;
    use activations::identity;
    use super::FeedforwardLayer;

    #[test]
    fn basics() {
        let layer = FeedforwardLayer::<f32, _, _>::new(7, 3, identity());
        assert_eq!(layer.input_size(), 7);
        assert_eq!(layer.output_size(), 3);
    }

    #[test]
    fn compute() {
        let layer = FeedforwardLayer::new_from(4, 2, identity(), || 0.5f32);
        let output = layer.compute(&[1.0, 1.0, 1.0, 1.0]);
        // all weigths and biases are 0.5, output should be 4*0.5 + 0.5 = 2.5
        for o in &output {
            assert!((o - 2.5).abs() < 0.00001);
        }
    }
}<commit_msg>Improve FeedForward doc.<commit_after>//! Constructions related to feed-forward networks

use std::cmp::min;

use num::{Float, one, zero};

use {Compute, BackpropTrain, SupervisedTrain};
use activations::ActivationFunction;
use training::{PerceptronRule, GradientDescent};

/// A feedforward layer
///
/// Such layer is composed of a set of output neurons, and have all its
/// inputs connected to all its outputs.
///
/// The effective computation is thus, if `X` is the vector of inputs,
/// `Y` the vector of outputs, `W` the internal weigths matrix, `B` the vector
/// of biases and `f()` the activation function (applied on all components of
/// the vector in parallel):
///
/// ```text
/// Y = f( W*X + B )
/// ```
///
/// The training of this layer consists on fitting the values of `W` and `B`.
pub struct FeedforwardLayer<F: Float, V: Fn(F) -> F, D: Fn(F) -> F> {
    inputs: usize,
    coeffs: Vec<F>,
    biases: Vec<F>,
    activation: ActivationFunction<F, V, D>
}

impl<F, V, D> FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    /// Creates a new linear feedforward layer with all its weights set
    /// to 1 and its biases set to 0
    pub fn new(inputs: usize,
               outputs: usize,
               activation: ActivationFunction<F, V, D>)
        -> FeedforwardLayer<F, V, D>
    {
        FeedforwardLayer {
            inputs: inputs,
            coeffs: vec![one(); inputs*outputs],
            biases: vec![zero(); outputs],
            activation: activation
        }
    }

    /// Creates a new linear feedforward layer with all its weights and biases
    /// generated by provided closure (for example a random number generator).
    pub fn new_from<G>(inputs: usize,
                       outputs: usize,
                       activation: ActivationFunction<F, V, D>,
                       mut generator: G)
        -> FeedforwardLayer<F, V, D>
        where G: FnMut() -> F
    {
        FeedforwardLayer {
            inputs: inputs,
            coeffs: (0..inputs*outputs).map(|_| generator()).collect(),
            biases: (0..outputs).map(|_| generator()).collect(),
            activation: activation
        }
    }
}

impl<F, V, D> Compute<F> for FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    fn compute(&self, input: &[F]) -> Vec<F> {
        let mut out = self.biases.clone();
        for j in 0..self.biases.len() {
            for i in 0..min(self.inputs, input.len()) {
                out[j] = out[j] + self.coeffs[j*self.inputs + i] * input[i]
            }
        }

        for o in &mut out {
            *o = (self.activation.value)(*o);
        }

        out
    }

    fn input_size(&self) -> usize {
        self.inputs
    }

    fn output_size(&self) -> usize {
        self.biases.len()
    }
}

impl<F, V, D> SupervisedTrain<F, PerceptronRule<F>> for FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    fn supervised_train(&mut self,
                        rule: &PerceptronRule<F>,
                        input: &[F],
                        target: &[F])
    {
        let out = self.compute(input);
        for j in 0..self.biases.len() {
            let diff = target.get(j).map(|v| *v).unwrap_or(zero()) - out[j];
            for i in 0..min(self.inputs, input.len()) {
                self.coeffs[i + j*self.inputs] =
                    self.coeffs[i + j*self.inputs] + rule.rate * diff * input[i];
            }
        }
    }
}

impl<F, V, D> BackpropTrain<F, GradientDescent<F>> for FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    fn backprop_train(&mut self,
                      rule: &GradientDescent<F>,
                      input: &[F],
                      target: &[F])
        -> Vec<F>
    {
        // we need to compute the intermediate states
        let mut out = self.biases.clone();
        for j in 0..self.biases.len() {
            for i in 0..min(self.inputs, input.len()) {
                out[j] = out[j] + self.coeffs[j*self.inputs + i] * input[i]
            }
        }

        let deltas = out.iter()
                            .map(|x| { (self.activation.derivative)(*x) })
                            .collect::<Vec<_>>();
        for o in &mut out {
            *o = (self.activation.value)(*o);
        }

        let mut returned = input.to_owned();
        for j in 0..self.biases.len() {
            for i in 0..min(self.inputs, input.len()) {
                returned[i] = returned[i] - self.coeffs[i + j*self.inputs]*deltas[j];
                self.coeffs[i + j*self.inputs] =
                    self.coeffs[i + j*self.inputs]
                    - rule.rate * input.get(i).map(|x| *x).unwrap_or(zero())
                                * deltas[j]
                                * ( out[j] - target.get(j).map(|x| *x).unwrap_or(zero()) )

            }
        }
        returned
    }
}

impl<F, V, D> SupervisedTrain<F, GradientDescent<F>> for FeedforwardLayer<F, V, D>
    where F: Float,
          V: Fn(F) -> F,
          D: Fn(F) -> F
{
    fn supervised_train(&mut self,
                        rule: &GradientDescent<F>,
                        input: &[F],
                        target: &[F])
    {
        self.backprop_train(rule, input, target);
    }
}

#[cfg(test)]
mod tests {
    use Compute;
    use activations::identity;
    use super::FeedforwardLayer;

    #[test]
    fn basics() {
        let layer = FeedforwardLayer::<f32, _, _>::new(7, 3, identity());
        assert_eq!(layer.input_size(), 7);
        assert_eq!(layer.output_size(), 3);
    }

    #[test]
    fn compute() {
        let layer = FeedforwardLayer::new_from(4, 2, identity(), || 0.5f32);
        let output = layer.compute(&[1.0, 1.0, 1.0, 1.0]);
        // all weigths and biases are 0.5, output should be 4*0.5 + 0.5 = 2.5
        for o in &output {
            assert!((o - 2.5).abs() < 0.00001);
        }
    }
}<|endoftext|>


<commit_before>use std::marker::PhantomData;
use gl;
use gl::types::*;
use context::Context;
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl Context {
    pub unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> GLenum {
        gl::FRAMEBUFFER
    }

    pub fn check_framebuffer_status(&self) -> Option<GLFramebufferError> {
        unsafe {
            match gl::CheckFramebufferStatus(self.target()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(self.target(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture_2d<T: TextureType>(&mut self,
                                      attachment: FramebufferAttachment,
                                      tex_target: T::ImageTargetType,
                                      texture: &mut Texture<T>,
                                      level: i32)
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target(),
                                     attachment.gl_enum(),
                                     tex_target.gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding<'a>(&'a mut self) -> FramebufferBinding<'a> {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind<'a>(&'a mut self, fbo: &mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<commit_msg>Add `FramebufferTarget` GL enum<commit_after>use std::marker::PhantomData;
use gl;
use gl::types::*;
use context::Context;
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl Context {
    pub unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> GLenum {
        gl::FRAMEBUFFER
    }

    pub fn check_framebuffer_status(&self) -> Option<GLFramebufferError> {
        unsafe {
            match gl::CheckFramebufferStatus(self.target()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(self.target(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture_2d<T: TextureType>(&mut self,
                                      attachment: FramebufferAttachment,
                                      tex_target: T::ImageTargetType,
                                      texture: &mut Texture<T>,
                                      level: i32)
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target(),
                                     attachment.gl_enum(),
                                     tex_target.gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding<'a>(&'a mut self) -> FramebufferBinding<'a> {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind<'a>(&'a mut self, fbo: &mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use gl;
use gl::types::*;
use context::Context;
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl Context {
    pub unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> GLenum {
        gl::FRAMEBUFFER
    }

    pub fn check_framebuffer_status(&self) -> Option<GLFramebufferError> {
        unsafe {
            match gl::CheckFramebufferStatus(self.target()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(self.target(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture_2d<T: TextureType>(&mut self,
                                      attachment: FramebufferAttachment,
                                      tex_target: T::ImageTargetType,
                                      texture: &mut Texture<T>,
                                      level: i32)
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target(),
                                     attachment.gl_enum(),
                                     tex_target.gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding<'a>(&'a mut self) -> FramebufferBinding<'a> {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind<'a>(&'a mut self, fbo: &mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<commit_msg>Change `FramebufferBinding.target()` to return a `FramebufferTarget`<commit_after>use std::marker::PhantomData;
use gl;
use gl::types::*;
use context::Context;
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl Context {
    pub unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> FramebufferTarget {
        FramebufferTarget::Framebuffer
    }

    pub fn check_framebuffer_status(&self) -> Option<GLFramebufferError> {
        unsafe {
            match gl::CheckFramebufferStatus(self.target().gl_enum()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(self.target().gl_enum(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture_2d<T: TextureType>(&mut self,
                                      attachment: FramebufferAttachment,
                                      tex_target: T::ImageTargetType,
                                      texture: &mut Texture<T>,
                                      level: i32)
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target().gl_enum(),
                                     attachment.gl_enum(),
                                     tex_target.gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding<'a>(&'a mut self) -> FramebufferBinding<'a> {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind<'a>(&'a mut self, fbo: &mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target().gl_enum(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<|endoftext|>


<commit_before>pub trait NumberOps : Sized {
   fn rounding_div(self, other: Self) -> Self;

   fn sqrt(self) -> Self;
}

impl NumberOps for i64 {
   #[inline]
   fn rounding_div(self, other: i64) -> i64 {
      if (self < 0) ^ (other < 0) {
         (self - (other / 2)) / other
      } else {
         (self + (other / 2)) / other
      }
   }

   #[inline]
   fn sqrt(self) -> i64 {
      (self as f64).sqrt() as i64
   }
}

#[cfg(test)]
mod tests {
   use test::{Bencher, black_box};

   use super::*;

   #[bench]
   fn bench_rounding_div(b: &mut Bencher) {
      b.iter(|| {
         for _ in 0..1000 {
            black_box(15023081_i64.rounding_div(black_box(108877_i64)));
         }
      });
   }
}
<commit_msg>Adding rounding at the sqrt function<commit_after>pub trait NumberOps : Sized {
   fn rounding_div(self, other: Self) -> Self;

   fn sqrt(self) -> Self;
}

impl NumberOps for i64 {
   #[inline]
   fn rounding_div(self, other: i64) -> i64 {
      if (self < 0) ^ (other < 0) {
         (self - (other / 2)) / other
      } else {
         (self + (other / 2)) / other
      }
   }

   #[inline]
   fn sqrt(self) -> i64 {
      (self as f64).sqrt().round() as i64
   }
}

#[cfg(test)]
mod tests {
   use test::{Bencher, black_box};

   use super::*;

   #[bench]
   fn bench_rounding_div(b: &mut Bencher) {
      b.iter(|| {
         for _ in 0..1000 {
            black_box(15023081_i64.rounding_div(black_box(108877_i64)));
         }
      });
   }
}
<|endoftext|>