<commit_before>use super::super::{in_coroutine};

use std::sync::mpsc;

use super::notify;

/// Channel receiving end
///
/// Create with `channel()`
pub struct Receiver<T>{
    rx: Option<mpsc::Receiver<T>>,
    notify_rx: notify::Receiver,
}

impl<T> Receiver<T>
    where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                self.notify_rx.reset();

                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) =>
                        self.notify_rx.wait(),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => {
                        return Ok(t)
                    },
                }
            }
        } else {
            let recv = self.rx.as_ref().unwrap().recv();

                match recv {
                    Err(e) => Err(e),
                    Ok(t) => {
                        return Ok(t)
                    },
                }
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let recv = self.rx.as_ref().unwrap().try_recv();
        match recv {
            Err(e) => Err(e),
            Ok(t) => {
                return Ok(t)
            },
        }
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `channel()`
pub struct Sender<T> {
    tx: Option<mpsc::Sender<T>>,
    notif_tx: notify::Sender,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            tx: self.tx.clone(),
            notif_tx: self.notif_tx.clone(),
        }
    }
}

impl<T> Sender<T> {
    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
        try!(self.tx.as_ref().unwrap().send(t));
        self.notif_tx.notify();
        Ok(())
    }
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {

    let (n_tx, n_rx) = notify::channel();
    let (tx, rx) = mpsc::channel();
    (Sender {
        tx: Some(tx),
        notif_tx: n_tx,
    },
        Receiver {
            rx: Some(rx),
            notify_rx: n_rx,
        })
}

impl<T> Drop for Sender<T> {
    fn drop(&mut self) {
        {
            self.tx.take();
        }
        self.notif_tx.notify()
    }
}
<commit_msg>add SyncSender & SyncReceiver<commit_after>use super::super::{in_coroutine};

use std::sync::mpsc;

use super::notify;
use super::broadcast;

/// Channel receiving end
///
/// Create with `channel()`
pub struct Receiver<T>{
    rx: Option<mpsc::Receiver<T>>,
    notify_rx: notify::Receiver,
}

impl<T> Receiver<T>
    where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                self.notify_rx.reset();

                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) =>
                        self.notify_rx.wait(),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => {
                        return Ok(t)
                    },
                }
            }
        } else {
            let recv = self.rx.as_ref().unwrap().recv();

                match recv {
                    Err(e) => Err(e),
                    Ok(t) => {
                        return Ok(t)
                    },
                }
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let recv = self.rx.as_ref().unwrap().try_recv();
        match recv {
            Err(e) => Err(e),
            Ok(t) => {
                return Ok(t)
            },
        }
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `channel()`
pub struct Sender<T> {
    tx: Option<mpsc::Sender<T>>,
    notif_tx: notify::Sender,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            tx: self.tx.clone(),
            notif_tx: self.notif_tx.clone(),
        }
    }
}

impl<T> Sender<T> {
    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
        try!(self.tx.as_ref().unwrap().send(t));
        self.notif_tx.notify();
        Ok(())
    }
}

/// Channel receiving end
///
/// Create with `channel()`
pub struct SyncReceiver<T>{
    rx: Option<mpsc::Receiver<T>>,
    broadcast_tx: broadcast::Sender,
    broadcast_rx: broadcast::Receiver,
}

impl<T> SyncReceiver<T>
    where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                self.broadcast_rx.reset();

                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) => self.broadcast_rx.wait(),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => {
                        self.broadcast_tx.notify();
                        return Ok(t)
                    },
                }
            }
        } else {
            let recv = self.rx.as_ref().unwrap().recv();

                match recv {
                    Err(e) => Err(e),
                    Ok(t) => {
                        return Ok(t)
                    },
                }
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let recv = self.rx.as_ref().unwrap().try_recv();
        match recv {
            Err(e) => Err(e),
            Ok(t) => {
                return Ok(t)
            },
        }
    }
}

/// Channel sync sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `sync_channel()`
pub struct SyncSender<T> {
    tx: Option<mpsc::SyncSender<T>>,
    broadcast_rx: broadcast::Receiver,
    broadcast_tx: broadcast::Sender,
}

impl<T> SyncSender<T> {
    pub fn send(&self, mut t: T) -> Result<(), mpsc::SendError<T>> {
        if in_coroutine() {
            loop {
                t = match self.try_send(t) {
                    Ok(t) => return Ok(t),
                    Err(mpsc::TrySendError::Full(t)) => {
                        self.broadcast_rx.wait();
                        t
                    },
                    Err(mpsc::TrySendError::Disconnected(v)) => return Err(mpsc::SendError(v))
                };
            }
        } else {
            // previous send is notified. so 'rx' will be
            // notified and there will be space for this
            // send at some point
            self.tx.as_ref().unwrap().send(t)?;
        }
        self.broadcast_tx.notify();
        Ok(())
    }

    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn try_send(&self, t: T) -> Result<(), mpsc::TrySendError<T>> {
        self.tx.as_ref().unwrap().try_send(t)?;
        self.broadcast_tx.notify();
        Ok(())
    }
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {

    let (n_tx, n_rx) = notify::channel();
    let (tx, rx) = mpsc::channel();
    (Sender {
        tx: Some(tx),
        notif_tx: n_tx,
    },
        Receiver {
            rx: Some(rx),
            notify_rx: n_rx,
        })
}

impl<T> Drop for Sender<T> {
    fn drop(&mut self) {
        {
            self.tx.take();
        }
        self.notif_tx.notify()
    }
}

pub fn sync_channel<T>(size: usize) -> (SyncSender<T>, SyncReceiver<T>) {

    let (btx, brx) = broadcast::channel();
    let (tx, rx) = mpsc::sync_channel(size);
    (   SyncSender {
            tx: Some(tx),
            broadcast_tx: btx.clone(),
            broadcast_rx: brx.clone(),
        },
        SyncReceiver {
            rx: Some(rx),
            broadcast_tx: btx,
            broadcast_rx: brx,
        }
    )
}

impl<T> Drop for SyncSender<T> {
    fn drop(&mut self) {
        {
            self.tx.take();
        }
        self.broadcast_tx.notify()
    }
}
<|endoftext|>


<commit_before>use {Errno, Result};
use libc::c_int;
use std::os::unix::io::RawFd;

mod ffi {
    use libc::{c_int};
    use super::EpollEvent;

    extern {
        pub fn epoll_create(size: c_int) -> c_int;
        pub fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *const EpollEvent) -> c_int;
        pub fn epoll_wait(epfd: c_int, events: *mut EpollEvent, max_events: c_int, timeout: c_int) -> c_int;
    }
}

bitflags!(
    #[repr(C)]
    flags EpollEventKind: u32 {
        const EPOLLIN = 0x001,
        const EPOLLPRI = 0x002,
        const EPOLLOUT = 0x004,
        const EPOLLRDNORM = 0x040,
        const EPOLLRDBAND = 0x080,
        const EPOLLWRNORM = 0x100,
        const EPOLLWRBAND = 0x200,
        const EPOLLMSG = 0x400,
        const EPOLLERR = 0x008,
        const EPOLLHUP = 0x010,
        const EPOLLRDHUP = 0x2000,
        const EPOLLWAKEUP = 1 << 29,
        const EPOLLONESHOT = 1 << 30,
        const EPOLLET = 1 << 31
    }
);

#[derive(Clone, Copy)]
#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

#[cfg(not(target_arch = "x86_64"))]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    pub events: EpollEventKind,
    pub data: u64
}

#[cfg(target_arch = "x86_64")]
#[derive(Clone, Copy)]
#[repr(C, packed)]
pub struct EpollEvent {
    pub events: EpollEventKind,
    pub data: u64
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[test]
fn test_epoll_event_size() {
    use std::mem::size_of;
    assert_eq!(size_of::<EpollEvent>(), 12);
}

#[cfg(target_arch = "arm")]
#[test]
fn test_epoll_event_size() {
    use std::mem::size_of;
    assert_eq!(size_of::<EpollEvent>(), 16);
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { ffi::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl(epfd: RawFd, op: EpollOp, fd: RawFd, event: &EpollEvent) -> Result<()> {
    let res = unsafe { ffi::epoll_ctl(epfd, op as c_int, fd, event as *const EpollEvent) };

    Errno::result(res).map(drop)
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        ffi::epoll_wait(epfd, events.as_mut_ptr(), events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<commit_msg>epoll: Add EPOLLEXCLUSIVE flag.<commit_after>use {Errno, Result};
use libc::c_int;
use std::os::unix::io::RawFd;

mod ffi {
    use libc::{c_int};
    use super::EpollEvent;

    extern {
        pub fn epoll_create(size: c_int) -> c_int;
        pub fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *const EpollEvent) -> c_int;
        pub fn epoll_wait(epfd: c_int, events: *mut EpollEvent, max_events: c_int, timeout: c_int) -> c_int;
    }
}

bitflags!(
    #[repr(C)]
    flags EpollEventKind: u32 {
        const EPOLLIN = 0x001,
        const EPOLLPRI = 0x002,
        const EPOLLOUT = 0x004,
        const EPOLLRDNORM = 0x040,
        const EPOLLRDBAND = 0x080,
        const EPOLLWRNORM = 0x100,
        const EPOLLWRBAND = 0x200,
        const EPOLLMSG = 0x400,
        const EPOLLERR = 0x008,
        const EPOLLHUP = 0x010,
        const EPOLLRDHUP = 0x2000,
        const EPOLLEXCLUSIVE = 1 << 28,
        const EPOLLWAKEUP = 1 << 29,
        const EPOLLONESHOT = 1 << 30,
        const EPOLLET = 1 << 31
    }
);

#[derive(Clone, Copy)]
#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

#[cfg(not(target_arch = "x86_64"))]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    pub events: EpollEventKind,
    pub data: u64
}

#[cfg(target_arch = "x86_64")]
#[derive(Clone, Copy)]
#[repr(C, packed)]
pub struct EpollEvent {
    pub events: EpollEventKind,
    pub data: u64
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[test]
fn test_epoll_event_size() {
    use std::mem::size_of;
    assert_eq!(size_of::<EpollEvent>(), 12);
}

#[cfg(target_arch = "arm")]
#[test]
fn test_epoll_event_size() {
    use std::mem::size_of;
    assert_eq!(size_of::<EpollEvent>(), 16);
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { ffi::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl(epfd: RawFd, op: EpollOp, fd: RawFd, event: &EpollEvent) -> Result<()> {
    let res = unsafe { ffi::epoll_ctl(epfd, op as c_int, fd, event as *const EpollEvent) };

    Errno::result(res).map(drop)
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        ffi::epoll_wait(epfd, events.as_mut_ptr(), events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

/// Represent an instance of a term.
#[derive(Debug, Clone)]
pub enum TermKind {
	ERoot,
	EAny,
	ENone,
	Symbol,//(Box<Term>, String),
	EString,//(Box<Term>, String),
	Integer,//(Box<Term>, i64),
	Float,//(Box<Term>, f64),
	BitString,//(Box<Term>, Vec<i8>),
	Boolean,//(Box<Term>, bool),
}

/*pub trait Term {
    //Return the kind
     fn get_kind(&self) -> TermKind;
}*/

struct ERoot ( pub () );
struct EAny ( pub () );
struct ENone ( pub () );
#[derive(Debug)]
struct EString(pub String);
struct Symbol(pub String);
#[derive(Debug)]
struct Integer(pub isize);
struct Float(pub f64);
struct BitString(pub Vec<i8>);
struct Boolean(pub bool);

#[derive(Debug)]
struct Term<T> {
    value: T,
}

impl<T> Term<T> {
    pub fn new(t: T) -> Term<T> {
        Term { value: t }
    }
}

/*impl Term for RootTerm{
    fn get_kind(&self) -> TermKind { self.kind.clone() }
}*/

#[test]
fn term_type_check_test() -> (){
    let stringterm = Term::new(EString("test".to_string()));
    let nestedterm = Term::new(Term::new(Integer(3)));

    //let rootkind = rootterm.get_kind();
    //println!("{:?}", rootkind);
    panic!("Intential fail. {:?}", nestedterm);
}

<commit_msg>Cleaned out some dead code<commit_after>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

/// Represents root terms.
struct ERoot ( pub () );
struct EAny ( pub () );
struct ENone ( pub () );
#[derive(Debug)]
struct EString(pub String);
struct Symbol(pub String);
#[derive(Debug)]
struct Integer(pub isize);
struct Float(pub f64);
struct BitString(pub Vec<i8>);
struct Boolean(pub bool);

#[derive(Debug)]
struct Term<T> {
    value: T,
}

impl<T> Term<T> {
    pub fn new(t: T) -> Term<T> {
        Term { value: t }
    }
}

#[test]
fn term_type_check_test() -> (){
    let stringterm = Term::new(EString("test".to_string()));
    let nestedterm = Term::new(Term::new(Integer(3)));

    //let rootkind = rootterm.get_kind();
    //println!("{:?}", rootkind);
    panic!("Intential fail. {:?}", nestedterm);
}

<|endoftext|>


<commit_before>use std::process::Command;

use clap::ArgMatches;
use rusoto::{ChainProvider, ProvideAwsCredentials};

use aws::credentials_provider;
use error::{KawsError, KawsResult};

pub struct Terraform<'a> {
    aws_credentials_provider: ChainProvider,
    cluster: &'a str,
    terraform_args: Option<Vec<&'a str>>,
}

impl<'a> Terraform<'a> {
    pub fn new(matches: &'a ArgMatches) -> Terraform<'a> {
        Terraform {
            aws_credentials_provider: credentials_provider(
                matches.value_of("aws-credentials-path"),
                matches.value_of("aws-credentials-profile"),
            ),
            cluster: matches.value_of("cluster").expect("clap should have required cluster"),
            terraform_args: matches.values_of("terraform-args").map(|values| values.collect()),
        }
    }

    pub fn apply(&mut self) -> KawsResult {
        try!(self.get());

        let mut command = Command::new("terraform");

        command.args(&[
            "apply",
            "-backup=-",
            &format!("-state=clusters/{}/terraform.tfstate", self.cluster),
            &format!("-var-file=clusters/{}/terraform.tfvars", self.cluster),
        ]);

        if self.terraform_args.is_some() {
            command.args(self.terraform_args.as_ref().unwrap());
        }

        command.arg("terraform/kaws").env(
            "AWS_ACCESS_KEY_ID",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_access_key_id(),
        ).env(
            "AWS_SECRET_ACCESS_KEY",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_secret_access_key(),
        );

        try!(command.status());

        Ok(None)
    }

    pub fn destroy(&mut self) -> KawsResult {
        try!(self.get());

        let mut command = Command::new("terraform");

        command.args(&[
            "destroy",
            "-backup=-",
            &format!("-state=clusters/{}/terraform.tfstate", self.cluster),
            &format!("-var-file=clusters/{}/terraform.tfvars", self.cluster),
            "terraform",
        ]);

        if self.terraform_args.is_some() {
            command.args(self.terraform_args.as_ref().unwrap());
        }

        command.arg("terraform/kaws").env(
            "AWS_ACCESS_KEY_ID",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_access_key_id(),
        ).env(
            "AWS_SECRET_ACCESS_KEY",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_secret_access_key(),
        );

        let exit_status = try!(command.status());

        if exit_status.success() {
            Ok(Some(format!(
                "Destroyed cluster \"{}\"! You should remove clusters/{} from Git.",
                self.cluster,
                self.cluster,
            )))
        } else {
            Err(KawsError::new(format!("Failed to destroy cluster!")))
        }
    }

    pub fn plan(&mut self) -> KawsResult {
        try!(self.get());

        let mut command = Command::new("terraform");

        command.args(&[
            "plan",
            "-backup=-",
            "-module-depth=-1",
            &format!("-state=clusters/{}/terraform.tfstate", self.cluster),
            &format!("-var-file=clusters/{}/terraform.tfvars", self.cluster),
        ]);

        if self.terraform_args.is_some() {
            command.args(self.terraform_args.as_ref().unwrap());
        }

        command.arg("terraform/kaws").env(
            "AWS_ACCESS_KEY_ID",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_access_key_id(),
        ).env(
            "AWS_SECRET_ACCESS_KEY",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_secret_access_key(),
        );

        try!(command.status());

        Ok(None)
    }

    fn get(&self) -> KawsResult {
        let exit_status = try!(Command::new("terraform").args(&[
            "get",
            "terraform/kaws",
        ]).status());

        if exit_status.success() {
            Ok(None)
        } else {
            Err(KawsError::new(format!("Failed to download Terraform module!")))
        }
    }
}
<commit_msg>Remove extra argument to `terraform destroy`.<commit_after>use std::process::Command;

use clap::ArgMatches;
use rusoto::{ChainProvider, ProvideAwsCredentials};

use aws::credentials_provider;
use error::{KawsError, KawsResult};

pub struct Terraform<'a> {
    aws_credentials_provider: ChainProvider,
    cluster: &'a str,
    terraform_args: Option<Vec<&'a str>>,
}

impl<'a> Terraform<'a> {
    pub fn new(matches: &'a ArgMatches) -> Terraform<'a> {
        Terraform {
            aws_credentials_provider: credentials_provider(
                matches.value_of("aws-credentials-path"),
                matches.value_of("aws-credentials-profile"),
            ),
            cluster: matches.value_of("cluster").expect("clap should have required cluster"),
            terraform_args: matches.values_of("terraform-args").map(|values| values.collect()),
        }
    }

    pub fn apply(&mut self) -> KawsResult {
        try!(self.get());

        let mut command = Command::new("terraform");

        command.args(&[
            "apply",
            "-backup=-",
            &format!("-state=clusters/{}/terraform.tfstate", self.cluster),
            &format!("-var-file=clusters/{}/terraform.tfvars", self.cluster),
        ]);

        if self.terraform_args.is_some() {
            command.args(self.terraform_args.as_ref().unwrap());
        }

        command.arg("terraform/kaws").env(
            "AWS_ACCESS_KEY_ID",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_access_key_id(),
        ).env(
            "AWS_SECRET_ACCESS_KEY",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_secret_access_key(),
        );

        try!(command.status());

        Ok(None)
    }

    pub fn destroy(&mut self) -> KawsResult {
        try!(self.get());

        let mut command = Command::new("terraform");

        command.args(&[
            "destroy",
            "-backup=-",
            &format!("-state=clusters/{}/terraform.tfstate", self.cluster),
            &format!("-var-file=clusters/{}/terraform.tfvars", self.cluster),
        ]);

        if self.terraform_args.is_some() {
            command.args(self.terraform_args.as_ref().unwrap());
        }

        command.arg("terraform/kaws").env(
            "AWS_ACCESS_KEY_ID",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_access_key_id(),
        ).env(
            "AWS_SECRET_ACCESS_KEY",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_secret_access_key(),
        );

        let exit_status = try!(command.status());

        if exit_status.success() {
            Ok(Some(format!(
                "Destroyed cluster \"{}\"! You should remove clusters/{} from Git.",
                self.cluster,
                self.cluster,
            )))
        } else {
            Err(KawsError::new(format!("Failed to destroy cluster!")))
        }
    }

    pub fn plan(&mut self) -> KawsResult {
        try!(self.get());

        let mut command = Command::new("terraform");

        command.args(&[
            "plan",
            "-backup=-",
            "-module-depth=-1",
            &format!("-state=clusters/{}/terraform.tfstate", self.cluster),
            &format!("-var-file=clusters/{}/terraform.tfvars", self.cluster),
        ]);

        if self.terraform_args.is_some() {
            command.args(self.terraform_args.as_ref().unwrap());
        }

        command.arg("terraform/kaws").env(
            "AWS_ACCESS_KEY_ID",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_access_key_id(),
        ).env(
            "AWS_SECRET_ACCESS_KEY",
            self.aws_credentials_provider.credentials().expect(
                "Failed to get AWS credentials"
            ).aws_secret_access_key(),
        );

        try!(command.status());

        Ok(None)
    }

    fn get(&self) -> KawsResult {
        let exit_status = try!(Command::new("terraform").args(&[
            "get",
            "terraform/kaws",
        ]).status());

        if exit_status.success() {
            Ok(None)
        } else {
            Err(KawsError::new(format!("Failed to download Terraform module!")))
        }
    }
}
<|endoftext|>


<commit_before>/*
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

use rusqlite::Row;

use fromdb::FromDb;
use lrobject::{LrId, LrObject};

/// An image in the `Catalog`. Requires a `LibraryFile` backing it
pub struct Image {
    id: LrId,
    uuid: String,
    /// If this a copy, id of the `Image` it is a copy of
    pub master_image: Option<LrId>,
    /// Name of copy.
    pub copy_name: Option<String>,
    /// Star rating
    pub rating: Option<i64>,
    /// Backing `LibraryFile` id.
    pub root_file: LrId,
    /// File format
    pub file_format: String,
    /// Pick. -1, 0, 1
    pub pick: i64,
    /// Orientation
    pub orientation: Option<String>,
    /// Capture date.
    pub capture_time: String,
}

impl Image {
    /// Return the Exif value for the image orientation
    /// No orientation = 0.
    /// Error = -1 or unknown value
    /// Otherwise the Exif value for `orientation`
    pub fn exif_orientation(&self) -> i32 {
        match self.orientation {
            Some(ref s) => match s.as_ref() {
                "AB" => 1,
                "DA" => 8,
                "BC" => 6,
                "CD" => 3,
                _ => -1,
            },
            None => 0,
        }
    }
}

impl LrObject for Image {
    fn id(&self) -> LrId {
        self.id
    }
    fn uuid(&self) -> &str {
        &self.uuid
    }
}

impl FromDb for Image {
    fn read_from(row: &Row) -> Option<Self> {
        Some(Image {
            id: row.get(0),
            uuid: row.get(1),
            master_image: row.get_checked(2).ok(),
            rating: row.get_checked(3).ok(),
            root_file: row.get(4),
            file_format: row.get(5),
            pick: row.get(6),
            orientation: row.get_checked(7).ok(),
            capture_time: row.get(8),
            copy_name: row.get_checked(9).ok(),
        })
    }
    fn read_db_tables() -> &'static str {
        "Adobe_images"
    }
    fn read_db_columns() -> &'static str {
        "id_local,id_global,masterImage,rating,rootFile,fileFormat,cast(pick as integer),orientation,captureTime,copyName"
    }
}

#[cfg(test)]
#[test]
fn test_exif_orientation() {
    let mut image = Image {
        id: 1,
        uuid: String::new(),
        master_image: None,
        rating: None,
        root_file: 2,
        file_format: String::from("RAW"),
        pick: 0,
        orientation: None,
        capture_time: String::new(),
        copy_name: None,
    };

    assert_eq!(image.exif_orientation(), 0);
    image.orientation = Some(String::from("ZZ"));
    assert_eq!(image.exif_orientation(), -1);

    image.orientation = Some(String::from("AB"));
    assert_eq!(image.exif_orientation(), 1);
    image.orientation = Some(String::from("DA"));
    assert_eq!(image.exif_orientation(), 8);
    image.orientation = Some(String::from("BC"));
    assert_eq!(image.exif_orientation(), 6);
    image.orientation = Some(String::from("CD"));
    assert_eq!(image.exif_orientation(), 3);
}
<commit_msg>Use Option::map()<commit_after>/*
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

use rusqlite::Row;

use fromdb::FromDb;
use lrobject::{LrId, LrObject};

/// An image in the `Catalog`. Requires a `LibraryFile` backing it
pub struct Image {
    id: LrId,
    uuid: String,
    /// If this a copy, id of the `Image` it is a copy of
    pub master_image: Option<LrId>,
    /// Name of copy.
    pub copy_name: Option<String>,
    /// Star rating
    pub rating: Option<i64>,
    /// Backing `LibraryFile` id.
    pub root_file: LrId,
    /// File format
    pub file_format: String,
    /// Pick. -1, 0, 1
    pub pick: i64,
    /// Orientation
    pub orientation: Option<String>,
    /// Capture date.
    pub capture_time: String,
}

impl Image {
    /// Return the Exif value for the image orientation
    /// No orientation = 0.
    /// Error = -1 or unknown value
    /// Otherwise the Exif value for `orientation`
    pub fn exif_orientation(&self) -> i32 {
        self.orientation.as_ref().map_or(0, |s| match s.as_ref() {
            "AB" => 1,
            "DA" => 8,
            "BC" => 6,
            "CD" => 3,
            _ => -1,
        })
    }
}

impl LrObject for Image {
    fn id(&self) -> LrId {
        self.id
    }
    fn uuid(&self) -> &str {
        &self.uuid
    }
}

impl FromDb for Image {
    fn read_from(row: &Row) -> Option<Self> {
        Some(Image {
            id: row.get(0),
            uuid: row.get(1),
            master_image: row.get_checked(2).ok(),
            rating: row.get_checked(3).ok(),
            root_file: row.get(4),
            file_format: row.get(5),
            pick: row.get(6),
            orientation: row.get_checked(7).ok(),
            capture_time: row.get(8),
            copy_name: row.get_checked(9).ok(),
        })
    }
    fn read_db_tables() -> &'static str {
        "Adobe_images"
    }
    fn read_db_columns() -> &'static str {
        "id_local,id_global,masterImage,rating,rootFile,fileFormat,cast(pick as integer),orientation,captureTime,copyName"
    }
}

#[cfg(test)]
#[test]
fn test_exif_orientation() {
    let mut image = Image {
        id: 1,
        uuid: String::new(),
        master_image: None,
        rating: None,
        root_file: 2,
        file_format: String::from("RAW"),
        pick: 0,
        orientation: None,
        capture_time: String::new(),
        copy_name: None,
    };

    assert_eq!(image.exif_orientation(), 0);
    image.orientation = Some(String::from("ZZ"));
    assert_eq!(image.exif_orientation(), -1);

    image.orientation = Some(String::from("AB"));
    assert_eq!(image.exif_orientation(), 1);
    image.orientation = Some(String::from("DA"));
    assert_eq!(image.exif_orientation(), 8);
    image.orientation = Some(String::from("BC"));
    assert_eq!(image.exif_orientation(), 6);
    image.orientation = Some(String::from("CD"));
    assert_eq!(image.exif_orientation(), 3);
}
<|endoftext|>


<commit_before>use super::Tokens;

use std::borrow::Cow;

/// Types that can be interpolated inside a `quote!(...)` invocation.
pub trait ToTokens {
    /// Write `self` to the given `Tokens`.
    ///
    /// Example implementation for a struct representing Rust paths like
    /// `std::cmp::PartialEq`:
    ///
    /// ```ignore
    /// pub struct Path {
    ///     pub global: bool,
    ///     pub segments: Vec<PathSegment>,
    /// }
    ///
    /// impl ToTokens for Path {
    ///     fn to_tokens(&self, tokens: &mut Tokens) {
    ///         for (i, segment) in self.segments.iter().enumerate() {
    ///             if i > 0 || self.global {
    ///                 tokens.append("::");
    ///             }
    ///             segment.to_tokens(tokens);
    ///         }
    ///     }
    /// }
    /// ```
    fn to_tokens(&self, &mut Tokens);
}

impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        if let Some(ref t) = *self {
            t.to_tokens(tokens);
        }
    }
}

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut Tokens) {
        let mut escaped = "\"".to_string();
        for ch in self.chars() {
            match ch {
                '\0' => escaped.push_str(r"\0"),
                '\'' => escaped.push_str("'"),
                _ => escaped.extend(ch.escape_default().map(|c| c as char)),
            }
        }
        escaped.push('"');

        tokens.append(&escaped);
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut Tokens) {
        self.as_str().to_tokens(tokens);
    }
}

impl ToTokens for char {
    fn to_tokens(&self, tokens: &mut Tokens) {
        match *self {
            '\0' => tokens.append(r"'\0'"),
            '"' => tokens.append("'\"'"),
            _ => tokens.append(&format!("{:?}", self)),
        }
    }
}

/// Wrap a `&str` so it interpolates as a byte-string: `b"abc"`.
#[derive(Debug)]
pub struct ByteStr<'a>(pub &'a str);

impl<'a> ToTokens for ByteStr<'a> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        let mut escaped = "b\"".to_string();
        for b in self.0.bytes() {
            match b {
                b'\0' => escaped.push_str(r"\0"),
                b'\t' => escaped.push_str(r"\t"),
                b'\n' => escaped.push_str(r"\n"),
                b'\r' => escaped.push_str(r"\r"),
                b'"' => escaped.push_str("\\\""),
                b'\\' => escaped.push_str("\\\\"),
                b'\x20' ... b'\x7E' => escaped.push(b as char),
                _ => escaped.push_str(&format!("\\x{:02X}", b)),
            }
        }
        escaped.push('"');

        tokens.append(&escaped);
    }
}

macro_rules! impl_to_tokens_display {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&self.to_string());
            }
        }
    };
}

impl_to_tokens_display!(Tokens);
impl_to_tokens_display!(bool);

/// Wrap an integer so it interpolates as a hexadecimal.
#[derive(Debug)]
pub struct Hex<T>(pub T);

macro_rules! impl_to_tokens_integer {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&format!(concat!("{}", stringify!($ty)), self));
            }
        }

        impl ToTokens for Hex<$ty> {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&format!(concat!("0x{:X}", stringify!($ty)), self.0));
            }
        }
    };
}

impl_to_tokens_integer!(i8);
impl_to_tokens_integer!(i16);
impl_to_tokens_integer!(i32);
impl_to_tokens_integer!(i64);
impl_to_tokens_integer!(isize);
impl_to_tokens_integer!(u8);
impl_to_tokens_integer!(u16);
impl_to_tokens_integer!(u32);
impl_to_tokens_integer!(u64);
impl_to_tokens_integer!(usize);

macro_rules! impl_to_tokens_floating {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                use std::num::FpCategory::*;
                match self.classify() {
                    Zero | Subnormal | Normal => {
                        tokens.append(&format!(concat!("{}", stringify!($ty)), self));
                    }
                    Nan => {
                        tokens.append("::");
                        tokens.append("std");
                        tokens.append("::");
                        tokens.append(stringify!($ty));
                        tokens.append("::");
                        tokens.append("NAN");
                    }
                    Infinite => {
                        tokens.append("::");
                        tokens.append("std");
                        tokens.append("::");
                        tokens.append(stringify!($ty));
                        tokens.append("::");
                        if self.is_sign_positive() {
                            tokens.append("INFINITY");
                        } else {
                            tokens.append("NEG_INFINITY");
                        }
                    }
                }
            }
        }
    };
}
impl_to_tokens_floating!(f32);
impl_to_tokens_floating!(f64);

impl<T: ToTokens> ToTokens for [T] {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append("[");
        for item in self {
            item.to_tokens(tokens);
            tokens.append(",");
        }
        tokens.append("]");
    }
}

impl<T: ToTokens> ToTokens for Vec<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        self[..].to_tokens(tokens)
    }
}

macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<T: ToTokens> ToTokens for [T; $N] {
                fn to_tokens(&self, tokens: &mut Tokens) {
                    self[..].to_tokens(tokens)
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

macro_rules! tuple_impls {
    ($(
        $Tuple:ident {
            $(($idx:tt) -> $T:ident)*
        }
    )+) => {
        $(
            impl<$($T: ToTokens),*> ToTokens for ($($T,)*) {
                fn to_tokens(&self, tokens: &mut Tokens) {
                    tokens.append("(");
                    $(
                        self.$idx.to_tokens(tokens);
                        tokens.append(",");
                    )*
                    tokens.append(")");
                }
            }
        )+
    }
}

tuple_impls! {
    Tuple0 {}
    Tuple1 {
        (0) -> A
    }
    Tuple2 {
        (0) -> A
        (1) -> B
    }
    Tuple3 {
        (0) -> A
        (1) -> B
        (2) -> C
    }
    Tuple4 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
    }
    Tuple5 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
    }
    Tuple6 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
    }
    Tuple7 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
    }
    Tuple8 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
    }
    Tuple9 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
    }
    Tuple10 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
    }
    Tuple11 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
        (10) -> K
    }
    Tuple12 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
        (10) -> K
        (11) -> L
    }
}
<commit_msg>Add `ToTokens::into_tokens` to conveniently convert `ToTokens` types into `Tokens` objects<commit_after>use super::Tokens;

use std::borrow::Cow;

/// Types that can be interpolated inside a `quote!(...)` invocation.
pub trait ToTokens {
    /// Write `self` to the given `Tokens`.
    ///
    /// Example implementation for a struct representing Rust paths like
    /// `std::cmp::PartialEq`:
    ///
    /// ```ignore
    /// pub struct Path {
    ///     pub global: bool,
    ///     pub segments: Vec<PathSegment>,
    /// }
    ///
    /// impl ToTokens for Path {
    ///     fn to_tokens(&self, tokens: &mut Tokens) {
    ///         for (i, segment) in self.segments.iter().enumerate() {
    ///             if i > 0 || self.global {
    ///                 tokens.append("::");
    ///             }
    ///             segment.to_tokens(tokens);
    ///         }
    ///     }
    /// }
    /// ```
    fn to_tokens(&self, &mut Tokens);

    /// Convert `self` directly into a `Tokens` object.
    ///
    /// This method is implicitly implemented using `to_tokens`, and acts as a
    /// convenience method for consumers of the `ToTokens` trait.
    fn into_tokens(self) -> Tokens where Self: Sized {
        let mut tokens = Tokens::new();
        self.to_tokens(&mut tokens);
        tokens
    }
}

impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        if let Some(ref t) = *self {
            t.to_tokens(tokens);
        }
    }
}

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut Tokens) {
        let mut escaped = "\"".to_string();
        for ch in self.chars() {
            match ch {
                '\0' => escaped.push_str(r"\0"),
                '\'' => escaped.push_str("'"),
                _ => escaped.extend(ch.escape_default().map(|c| c as char)),
            }
        }
        escaped.push('"');

        tokens.append(&escaped);
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut Tokens) {
        self.as_str().to_tokens(tokens);
    }
}

impl ToTokens for char {
    fn to_tokens(&self, tokens: &mut Tokens) {
        match *self {
            '\0' => tokens.append(r"'\0'"),
            '"' => tokens.append("'\"'"),
            _ => tokens.append(&format!("{:?}", self)),
        }
    }
}

/// Wrap a `&str` so it interpolates as a byte-string: `b"abc"`.
#[derive(Debug)]
pub struct ByteStr<'a>(pub &'a str);

impl<'a> ToTokens for ByteStr<'a> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        let mut escaped = "b\"".to_string();
        for b in self.0.bytes() {
            match b {
                b'\0' => escaped.push_str(r"\0"),
                b'\t' => escaped.push_str(r"\t"),
                b'\n' => escaped.push_str(r"\n"),
                b'\r' => escaped.push_str(r"\r"),
                b'"' => escaped.push_str("\\\""),
                b'\\' => escaped.push_str("\\\\"),
                b'\x20' ... b'\x7E' => escaped.push(b as char),
                _ => escaped.push_str(&format!("\\x{:02X}", b)),
            }
        }
        escaped.push('"');

        tokens.append(&escaped);
    }
}

macro_rules! impl_to_tokens_display {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&self.to_string());
            }
        }
    };
}

impl_to_tokens_display!(bool);

impl ToTokens for Tokens {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(self.as_str());
    }

    fn into_tokens(self) -> Tokens {
        self
    }
}

/// Wrap an integer so it interpolates as a hexadecimal.
#[derive(Debug)]
pub struct Hex<T>(pub T);

macro_rules! impl_to_tokens_integer {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&format!(concat!("{}", stringify!($ty)), self));
            }
        }

        impl ToTokens for Hex<$ty> {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&format!(concat!("0x{:X}", stringify!($ty)), self.0));
            }
        }
    };
}

impl_to_tokens_integer!(i8);
impl_to_tokens_integer!(i16);
impl_to_tokens_integer!(i32);
impl_to_tokens_integer!(i64);
impl_to_tokens_integer!(isize);
impl_to_tokens_integer!(u8);
impl_to_tokens_integer!(u16);
impl_to_tokens_integer!(u32);
impl_to_tokens_integer!(u64);
impl_to_tokens_integer!(usize);

macro_rules! impl_to_tokens_floating {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                use std::num::FpCategory::*;
                match self.classify() {
                    Zero | Subnormal | Normal => {
                        tokens.append(&format!(concat!("{}", stringify!($ty)), self));
                    }
                    Nan => {
                        tokens.append("::");
                        tokens.append("std");
                        tokens.append("::");
                        tokens.append(stringify!($ty));
                        tokens.append("::");
                        tokens.append("NAN");
                    }
                    Infinite => {
                        tokens.append("::");
                        tokens.append("std");
                        tokens.append("::");
                        tokens.append(stringify!($ty));
                        tokens.append("::");
                        if self.is_sign_positive() {
                            tokens.append("INFINITY");
                        } else {
                            tokens.append("NEG_INFINITY");
                        }
                    }
                }
            }
        }
    };
}
impl_to_tokens_floating!(f32);
impl_to_tokens_floating!(f64);

impl<T: ToTokens> ToTokens for [T] {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append("[");
        for item in self {
            item.to_tokens(tokens);
            tokens.append(",");
        }
        tokens.append("]");
    }
}

impl<T: ToTokens> ToTokens for Vec<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        self[..].to_tokens(tokens)
    }
}

macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<T: ToTokens> ToTokens for [T; $N] {
                fn to_tokens(&self, tokens: &mut Tokens) {
                    self[..].to_tokens(tokens)
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

macro_rules! tuple_impls {
    ($(
        $Tuple:ident {
            $(($idx:tt) -> $T:ident)*
        }
    )+) => {
        $(
            impl<$($T: ToTokens),*> ToTokens for ($($T,)*) {
                fn to_tokens(&self, tokens: &mut Tokens) {
                    tokens.append("(");
                    $(
                        self.$idx.to_tokens(tokens);
                        tokens.append(",");
                    )*
                    tokens.append(")");
                }
            }
        )+
    }
}

tuple_impls! {
    Tuple0 {}
    Tuple1 {
        (0) -> A
    }
    Tuple2 {
        (0) -> A
        (1) -> B
    }
    Tuple3 {
        (0) -> A
        (1) -> B
        (2) -> C
    }
    Tuple4 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
    }
    Tuple5 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
    }
    Tuple6 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
    }
    Tuple7 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
    }
    Tuple8 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
    }
    Tuple9 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
    }
    Tuple10 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
    }
    Tuple11 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
        (10) -> K
    }
    Tuple12 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
        (10) -> K
        (11) -> L
    }
}
<|endoftext|>


<commit_before>
use vertex::{Vertex, VertexProxy};
use edge::{Edge, EdgeProxy};
use graph::TraversableToVertex;
// define a traversal as a series of stages

struct VertexVisit {
    vertex: VertexProxy
}

struct EdgeVisit {
    edge: EdgeProxy
}

enum TraversalStage {

}

pub enum GraphElement {
    Vertex(VertexProxy),
    Edge(EdgeProxy)
}

// used to track a single graph traversal
// will be used in conjunction with a GraphQuery

pub struct Path {
    path: Vec<GraphElement>
}

impl Path {
    fn new(vertex: VertexProxy) -> Path {
		Path{path:vec![GraphElement::Vertex(vertex)]}
    }
	fn new_empty() -> Path {
		Path{path:vec![]}
	}

}

impl Clone for Path {
	fn clone(&self) -> Path {
		Path::new_empty()
	}

	fn clone_from(&mut self, source: &Self ) {

	}
}

pub struct GraphQuery {
	// many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<VertexProxy>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
			let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

	pub fn get_paths(&self) -> &Vec<Path> {
		&self.paths
	}

	/*
	generic mapper for our queries
	future this may use worker threads to perform
	traversals
	 */
    fn full_map<F: Fn(&Path) -> Vec<Path>>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
		for x in self.paths.iter() {
			let mut tmp = closure(x);
			result.paths.append(&mut tmp)
		}
		result
    }

	/*
	accepts a proxy and a closure, per
	takes the last element
	 */
	fn map<F: Fn(&GraphElement) -> Vec<GraphElement>>(&self, closure: F)
		-> GraphQuery {
		let mut result = GraphQuery::empty();
		for x in self.paths.iter() {
			// apply the closure to the last element in each map
			// if nothing is returned, we should not use the path anymore
		}

		result

	}

	/*

	 */
    pub fn outV(&self) -> GraphQuery {
		let f = |path: &Path| {
			println!("applying outV");
			let mut result : Vec<Path> = Vec::new();
			//take the final element in the path
			let element = path.path.last().unwrap();

			match element {
				&GraphElement::Vertex(ref v) => {
					println!("matched vertex");
					let mut tmp = v.outV();
					for vertex in tmp {
						println!("adding path based on vertex match");
						let new_path = path.clone();
						result.push(new_path);
					}
				},
				&GraphElement::Edge(ref e) => {

				}
			}
			// apply outV

			result
		};
		self.full_map(f)
    }

//	pub fn inV(&self) -> GraphQuery {
//		let g = GraphQuery::empty();
//		let f = |element: &GraphElement| {
//			element.inV()
//		};
//		self.map(f)
//	}
}

<commit_msg>working on new iteration code<commit_after>
use vertex::{Vertex, VertexProxy};
use edge::{Edge, EdgeProxy};
use graph::TraversableToVertex;
// define a traversal as a series of stages

struct VertexVisit {
    vertex: VertexProxy
}

struct EdgeVisit {
    edge: EdgeProxy
}

enum TraversalStage {

}

pub enum GraphElement {
    Vertex(VertexProxy),
    Edge(EdgeProxy)
}

// used to track a single graph traversal
// will be used in conjunction with a GraphQuery

pub struct Path {
    path: Vec<GraphElement>
}

impl Path {
    fn new(vertex: VertexProxy) -> Path {
		Path{path:vec![GraphElement::Vertex(vertex)]}
    }
	fn new_empty() -> Path {
		Path{path:vec![]}
	}

}

impl Clone for Path {
	fn clone(&self) -> Path {
		Path::new_empty()
	}

	fn clone_from(&mut self, source: &Self ) {

	}
}

pub struct GraphQuery {
	// many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<VertexProxy>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
			let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

	pub fn get_paths(&self) -> &Vec<Path> {
		&self.paths
	}
	pub fn push(&self, path:Path) {
		self.paths.push(path)
	}

	/*
	generic mapper for our queries
	future this may use worker threads to perform
	traversals
	 */
    fn full_map<F: Fn(&Path) -> Vec<Path>>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
		for x in self.paths.iter() {
			let mut tmp = closure(x);
			result.paths.append(&mut tmp)
		}
		result
    }

	/*
	accepts a proxy and a closure, per
	takes the last element
	 */
	fn map<F: Fn(&GraphElement) -> Vec<GraphElement>>(&self, closure: F)
		-> GraphQuery {
		let mut result = GraphQuery::empty();
		for path in self.paths.iter() {
			// apply the closure to the last element in each map
			// if nothing is returned, we should not use the path anymore
			let element = path.path.last().unwrap();
			let mut tmp = closure(element);
			let new_path = path.clone();
			result.push(new_path);
		}

		result

	}

	/*

	 */
    pub fn outV(&self) -> GraphQuery {
		let f = |path: &Path| {
			println!("applying outV");
			let mut result : Vec<Path> = Vec::new();
			//take the final element in the path
			let element = path.path.last().unwrap();

			match element {
				&GraphElement::Vertex(ref v) => {
					println!("matched vertex");
					let mut tmp = v.outV();
					for vertex in tmp {
						println!("adding path based on vertex match");
						let new_path = path.clone();
						result.push(new_path);
					}
				},
				&GraphElement::Edge(ref e) => {

				}
			}
			// apply outV

			result
		};
		self.full_map(f)
    }

//	pub fn inV(&self) -> GraphQuery {
//		let g = GraphQuery::empty();
//		let f = |element: &GraphElement| {
//			element.inV()
//		};
//		self.map(f)
//	}
}

<|endoftext|>


<commit_before>//! Traits dealing with SQLite data types.
//!
//! SQLite uses a [dynamic type system](https://www.sqlite.org/datatype3.html). Implementations of
//! the `ToSql` and `FromSql` traits are provided for the basic types that SQLite provides methods
//! for:
//!
//! * Integers (`i32` and `i64`; SQLite uses `i64` internally, so getting an `i32` will truncate
//!   if the value is too large or too small).
//! * Reals (`f64`)
//! * Strings (`String` and `&str`)
//! * Blobs (`Vec<u8>` and `&[u8]`)
//!
//! Additionally, because it is such a common data type, implementations are provided for
//! `time::Timespec` that use a string for storage (using the same format string,
//! `"%Y-%m-%d %H:%M:%S"`, as SQLite's builtin
//! [datetime](https://www.sqlite.org/lang_datefunc.html) function.  Note that this storage
//! truncates timespecs to the nearest second. If you want different storage for timespecs, you can
//! use a newtype. For example, to store timespecs as `f64`s:
//!
//! ```rust,ignore
//! extern crate rusqlite;
//! extern crate libc;
//!
//! use rusqlite::types::{FromSql, ToSql, sqlite3_stmt};
//! use rusqlite::{Result};
//! use libc::c_int;
//! use time;
//!
//! pub struct TimespecSql(pub time::Timespec);
//!
//! impl FromSql for TimespecSql {
//!     fn column_result(value: ValueRef) -> Result<Self> {
//!         f64::column_result(value).map(|as_f64| {
//!             TimespecSql(time::Timespec{ sec: as_f64.trunc() as i64,
//!                                         nsec: (as_f64.fract() * 1.0e9) as i32 })
//!         })
//!     }
//! }
//!
//! impl ToSql for TimespecSql {
//!     unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
//!         let TimespecSql(ts) = *self;
//!         let as_f64 = ts.sec as f64 + (ts.nsec as f64) / 1.0e9;
//!         as_f64.bind_parameter(stmt, col)
//!     }
//! }
//! ```
//!
//! `ToSql` and `FromSql` are also implemented for `Option<T>` where `T` implements `ToSql` or
//! `FromSql` for the cases where you want to know if a value was NULL (which gets translated to
//! `None`).

pub use self::from_sql::{FromSql, FromSqlError, FromSqlResult};
pub use self::to_sql::{ToSql, ToSqlOutput};
pub use self::value::Value;
pub use self::value_ref::ValueRef;

use std::fmt;

mod value;
mod value_ref;
mod from_sql;
mod to_sql;
mod time;
#[cfg(feature = "chrono")]
mod chrono;
#[cfg(feature = "serde_json")]
mod serde_json;

/// Empty struct that can be used to fill in a query parameter as `NULL`.
///
/// ## Example
///
/// ```rust,no_run
/// # extern crate libc;
/// # extern crate rusqlite;
/// # use rusqlite::{Connection, Result};
/// # use rusqlite::types::{Null};
/// # use libc::{c_int};
/// fn main() {
/// }
/// fn insert_null(conn: &Connection) -> Result<c_int> {
///     conn.execute("INSERT INTO people (name) VALUES (?)", &[&Null])
/// }
/// ```
#[derive(Copy,Clone)]
pub struct Null;

#[derive(Clone,Debug,PartialEq)]
pub enum Type {
    Null,
    Integer,
    Real,
    Text,
    Blob,
}

impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Type::Null => write!(f, "Null"),
            Type::Integer => write!(f, "Integer"),
            Type::Real => write!(f, "Real"),
            Type::Text => write!(f, "Text"),
            Type::Blob => write!(f, "Blob"),
        }
    }
}

#[cfg(test)]
mod test {
    extern crate time;

    use Connection;
    use Error;
    use libc::{c_int, c_double};
    use std::f64::EPSILON;
    use super::Value;

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n)").unwrap();
        db
    }

    #[test]
    fn test_blob() {
        let db = checked_memory_handle();

        let v1234 = vec![1u8, 2, 3, 4];
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234]).unwrap();

        let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(v, v1234);
    }

    #[test]
    fn test_empty_blob() {
        let db = checked_memory_handle();

        let empty = vec![];
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&empty]).unwrap();

        let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(v, empty);
    }

    #[test]
    fn test_str() {
        let db = checked_memory_handle();

        let s = "hello, world!";
        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();

        let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(from, s);
    }

    #[test]
    fn test_string() {
        let db = checked_memory_handle();

        let s = "hello, world!";
        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s.to_owned()]).unwrap();

        let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(from, s);
    }

    #[test]
    fn test_value() {
        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(i) VALUES (?)", &[&Value::Integer(10)]).unwrap();

        assert_eq!(10i64,
                   db.query_row("SELECT i FROM foo", &[], |r| r.get(0)).unwrap());
    }

    #[test]
    fn test_option() {
        let db = checked_memory_handle();

        let s = Some("hello, world!");
        let b = Some(vec![1u8, 2, 3, 4]);

        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&b]).unwrap();

        let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        {
            let row1 = rows.next().unwrap().unwrap();
            let s1: Option<String> = row1.get(0);
            let b1: Option<Vec<u8>> = row1.get(1);
            assert_eq!(s.unwrap(), s1.unwrap());
            assert!(b1.is_none());
        }

        {
            let row2 = rows.next().unwrap().unwrap();
            let s2: Option<String> = row2.get(0);
            let b2: Option<Vec<u8>> = row2.get(1);
            assert!(s2.is_none());
            assert_eq!(b, b2);
        }
    }

    #[test]
    fn test_mismatched_types() {
        fn is_invalid_column_type(err: Error) -> bool {
            match err {
                Error::InvalidColumnType(_, _) => true,
                _ => false,
            }
        }

        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
                     &[])
            .unwrap();

        let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        let row = rows.next().unwrap().unwrap();

        // check the correct types come back as expected
        assert_eq!(vec![1, 2], row.get_checked::<i32, Vec<u8>>(0).unwrap());
        assert_eq!("text", row.get_checked::<i32, String>(1).unwrap());
        assert_eq!(1, row.get_checked::<i32, c_int>(2).unwrap());
        assert!((1.5 - row.get_checked::<i32, c_double>(3).unwrap()).abs() < EPSILON);
        assert!(row.get_checked::<i32, Option<c_int>>(4).unwrap().is_none());
        assert!(row.get_checked::<i32, Option<c_double>>(4).unwrap().is_none());
        assert!(row.get_checked::<i32, Option<String>>(4).unwrap().is_none());

        // check some invalid types

        // 0 is actually a blob (Vec<u8>)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, time::Timespec>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(0).err().unwrap()));

        // 1 is actually a text (String)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(1).err().unwrap()));

        // 2 is actually an integer
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(2).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(2).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<String>>(2).err().unwrap()));

        // 3 is actually a float (c_double)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(3).err().unwrap()));

        // 4 is actually NULL
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, time::Timespec>(4).err().unwrap()));
    }

    #[test]
    fn test_dynamic_type() {
        use super::Value;
        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
                     &[])
            .unwrap();

        let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        let row = rows.next().unwrap().unwrap();
        assert_eq!(Value::Blob(vec![1, 2]),
                   row.get_checked::<i32, Value>(0).unwrap());
        assert_eq!(Value::Text(String::from("text")),
                   row.get_checked::<i32, Value>(1).unwrap());
        assert_eq!(Value::Integer(1), row.get_checked::<i32, Value>(2).unwrap());
        match row.get_checked::<i32, Value>(3).unwrap() {
            Value::Real(val) => assert!((1.5 - val).abs() < EPSILON),
            x => panic!("Invalid Value {:?}", x),
        }
        assert_eq!(Value::Null, row.get_checked::<i32, Value>(4).unwrap());
    }
}
<commit_msg>Fix doc comment example of FromSql/ToSql<commit_after>//! Traits dealing with SQLite data types.
//!
//! SQLite uses a [dynamic type system](https://www.sqlite.org/datatype3.html). Implementations of
//! the `ToSql` and `FromSql` traits are provided for the basic types that SQLite provides methods
//! for:
//!
//! * Integers (`i32` and `i64`; SQLite uses `i64` internally, so getting an `i32` will truncate
//!   if the value is too large or too small).
//! * Reals (`f64`)
//! * Strings (`String` and `&str`)
//! * Blobs (`Vec<u8>` and `&[u8]`)
//!
//! Additionally, because it is such a common data type, implementations are provided for
//! `time::Timespec` that use a string for storage (using the same format string,
//! `"%Y-%m-%d %H:%M:%S"`, as SQLite's builtin
//! [datetime](https://www.sqlite.org/lang_datefunc.html) function.  Note that this storage
//! truncates timespecs to the nearest second. If you want different storage for timespecs, you can
//! use a newtype. For example, to store timespecs as `f64`s:
//!
//! ```rust
//! extern crate rusqlite;
//! extern crate time;
//!
//! use rusqlite::types::{FromSql, FromSqlResult, ValueRef, ToSql, ToSqlOutput};
//! use rusqlite::{Result};
//!
//! pub struct TimespecSql(pub time::Timespec);
//!
//! impl FromSql for TimespecSql {
//!     fn column_result(value: ValueRef) -> FromSqlResult<Self> {
//!         f64::column_result(value).map(|as_f64| {
//!             TimespecSql(time::Timespec{ sec: as_f64.trunc() as i64,
//!                                         nsec: (as_f64.fract() * 1.0e9) as i32 })
//!         })
//!     }
//! }
//!
//! impl ToSql for TimespecSql {
//!     fn to_sql(&self) -> Result<ToSqlOutput> {
//!         let TimespecSql(ts) = *self;
//!         let as_f64 = ts.sec as f64 + (ts.nsec as f64) / 1.0e9;
//!         Ok(as_f64.into())
//!     }
//! }
//!
//! # // Prevent this doc test from being wrapped in a `fn main()` so that it will compile.
//! # fn main() {}
//! ```
//!
//! `ToSql` and `FromSql` are also implemented for `Option<T>` where `T` implements `ToSql` or
//! `FromSql` for the cases where you want to know if a value was NULL (which gets translated to
//! `None`).

pub use self::from_sql::{FromSql, FromSqlError, FromSqlResult};
pub use self::to_sql::{ToSql, ToSqlOutput};
pub use self::value::Value;
pub use self::value_ref::ValueRef;

use std::fmt;

mod value;
mod value_ref;
mod from_sql;
mod to_sql;
mod time;
#[cfg(feature = "chrono")]
mod chrono;
#[cfg(feature = "serde_json")]
mod serde_json;

/// Empty struct that can be used to fill in a query parameter as `NULL`.
///
/// ## Example
///
/// ```rust,no_run
/// # extern crate libc;
/// # extern crate rusqlite;
/// # use rusqlite::{Connection, Result};
/// # use rusqlite::types::{Null};
/// # use libc::{c_int};
/// fn main() {
/// }
/// fn insert_null(conn: &Connection) -> Result<c_int> {
///     conn.execute("INSERT INTO people (name) VALUES (?)", &[&Null])
/// }
/// ```
#[derive(Copy,Clone)]
pub struct Null;

#[derive(Clone,Debug,PartialEq)]
pub enum Type {
    Null,
    Integer,
    Real,
    Text,
    Blob,
}

impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Type::Null => write!(f, "Null"),
            Type::Integer => write!(f, "Integer"),
            Type::Real => write!(f, "Real"),
            Type::Text => write!(f, "Text"),
            Type::Blob => write!(f, "Blob"),
        }
    }
}

#[cfg(test)]
mod test {
    extern crate time;

    use Connection;
    use Error;
    use libc::{c_int, c_double};
    use std::f64::EPSILON;
    use super::Value;

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n)").unwrap();
        db
    }

    #[test]
    fn test_blob() {
        let db = checked_memory_handle();

        let v1234 = vec![1u8, 2, 3, 4];
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234]).unwrap();

        let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(v, v1234);
    }

    #[test]
    fn test_empty_blob() {
        let db = checked_memory_handle();

        let empty = vec![];
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&empty]).unwrap();

        let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(v, empty);
    }

    #[test]
    fn test_str() {
        let db = checked_memory_handle();

        let s = "hello, world!";
        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();

        let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(from, s);
    }

    #[test]
    fn test_string() {
        let db = checked_memory_handle();

        let s = "hello, world!";
        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s.to_owned()]).unwrap();

        let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(from, s);
    }

    #[test]
    fn test_value() {
        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(i) VALUES (?)", &[&Value::Integer(10)]).unwrap();

        assert_eq!(10i64,
                   db.query_row("SELECT i FROM foo", &[], |r| r.get(0)).unwrap());
    }

    #[test]
    fn test_option() {
        let db = checked_memory_handle();

        let s = Some("hello, world!");
        let b = Some(vec![1u8, 2, 3, 4]);

        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&b]).unwrap();

        let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        {
            let row1 = rows.next().unwrap().unwrap();
            let s1: Option<String> = row1.get(0);
            let b1: Option<Vec<u8>> = row1.get(1);
            assert_eq!(s.unwrap(), s1.unwrap());
            assert!(b1.is_none());
        }

        {
            let row2 = rows.next().unwrap().unwrap();
            let s2: Option<String> = row2.get(0);
            let b2: Option<Vec<u8>> = row2.get(1);
            assert!(s2.is_none());
            assert_eq!(b, b2);
        }
    }

    #[test]
    fn test_mismatched_types() {
        fn is_invalid_column_type(err: Error) -> bool {
            match err {
                Error::InvalidColumnType(_, _) => true,
                _ => false,
            }
        }

        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
                     &[])
            .unwrap();

        let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        let row = rows.next().unwrap().unwrap();

        // check the correct types come back as expected
        assert_eq!(vec![1, 2], row.get_checked::<i32, Vec<u8>>(0).unwrap());
        assert_eq!("text", row.get_checked::<i32, String>(1).unwrap());
        assert_eq!(1, row.get_checked::<i32, c_int>(2).unwrap());
        assert!((1.5 - row.get_checked::<i32, c_double>(3).unwrap()).abs() < EPSILON);
        assert!(row.get_checked::<i32, Option<c_int>>(4).unwrap().is_none());
        assert!(row.get_checked::<i32, Option<c_double>>(4).unwrap().is_none());
        assert!(row.get_checked::<i32, Option<String>>(4).unwrap().is_none());

        // check some invalid types

        // 0 is actually a blob (Vec<u8>)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, time::Timespec>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(0).err().unwrap()));

        // 1 is actually a text (String)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(1).err().unwrap()));

        // 2 is actually an integer
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(2).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(2).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<String>>(2).err().unwrap()));

        // 3 is actually a float (c_double)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(3).err().unwrap()));

        // 4 is actually NULL
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, time::Timespec>(4).err().unwrap()));
    }

    #[test]
    fn test_dynamic_type() {
        use super::Value;
        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
                     &[])
            .unwrap();

        let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        let row = rows.next().unwrap().unwrap();
        assert_eq!(Value::Blob(vec![1, 2]),
                   row.get_checked::<i32, Value>(0).unwrap());
        assert_eq!(Value::Text(String::from("text")),
                   row.get_checked::<i32, Value>(1).unwrap());
        assert_eq!(Value::Integer(1), row.get_checked::<i32, Value>(2).unwrap());
        match row.get_checked::<i32, Value>(3).unwrap() {
            Value::Real(val) => assert!((1.5 - val).abs() < EPSILON),
            x => panic!("Invalid Value {:?}", x),
        }
        assert_eq!(Value::Null, row.get_checked::<i32, Value>(4).unwrap());
    }
}
<|endoftext|>


<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn insert_dummy_setup(&mut self) {
        self.elements.push(Element::Other(Sexp::List(vec![Sexp::String(String::from("setup"))])))
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num:i64, name:&'static str) {
        self.elements.push(Element::Net(Net { num:num, name:String::from(name) }));
    }
    pub fn add_netclass(&mut self, name:&'static str, desc:&'static str, clearance:f64, trace_width:f64, via_dia:f64, via_drill:f64, uvia_dia:f64, uvia_drill:f64, nets:Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name:String::from(name),
            desc:String::from(desc),
            clearance:clearance,
            trace_width:trace_width,
            via_dia:via_dia,
            via_drill:via_drill,
            uvia_dia:uvia_dia,
            uvia_drill:uvia_drill,
            nets:nets
            }));
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other:&NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        return s1 == s2;
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>has_net<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn insert_dummy_setup(&mut self) {
        self.elements.push(Element::Other(Sexp::List(vec![Sexp::String(String::from("setup"))])))
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num:i64, name:&'static str) {
        self.elements.push(Element::Net(Net { num:num, name:String::from(name) }));
    }
    pub fn add_netclass(&mut self, name:&'static str, desc:&'static str, clearance:f64, trace_width:f64, via_dia:f64, via_drill:f64, uvia_dia:f64, uvia_drill:f64, nets:Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name:String::from(name),
            desc:String::from(desc),
            clearance:clearance,
            trace_width:trace_width,
            via_dia:via_dia,
            via_drill:via_drill,
            uvia_dia:uvia_dia,
            uvia_drill:uvia_drill,
            nets:nets
            }));
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other:&NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        return s1 == s2;
    }
    pub fn has_net(&self, name:&'static str) -> bool {
        for net in &self.nets {
            if &net[..] == name {
                return true
            }
        }
        return false
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>