<commit_before>//! Prelude

use std::ops::FnMut;

use futures::stream;

pub use command::Response;
pub use futures::Future;
pub use futures::stream::Stream;
pub use serde_json::{Value, from_str, to_string};

pub trait Consumer {
    fn consume(self);
}

macro_rules! consume {
    () => {
        fn consume(self) {
            for _ in self.wait() { }
        }
    }
}

impl<T> Consumer for Response<T> { consume!{} }
impl<S, F> Consumer for stream::ForEach<S, F>
    where S: Stream, F: FnMut(S::Item) -> Result<(), S::Error>
{ consume!{} }
<commit_msg>Cleanup the prelude<commit_after>//! Prelude

pub use command::Response;
pub use futures::Future;
pub use futures::stream::Stream;
pub use serde_json::{Value, from_str, to_string};

// Consumers to make blocking more convenient
//
// Ideally we would want to use just one trait `Consumer`.
// However, the implementations for `T: Stream` and `T: Future`
// would clash.

/// Block the current thread until we have received all the results from
/// the stream.
pub trait StreamConsumer {
    fn consume(self);
}

/// Block the current thread until we have received all the results from
/// the future.
pub trait FutureConsumer {
    fn consume(self);
}

macro_rules! consume {
    () => {
        fn consume(self) {
            for _ in self.wait() { }
        }
    }
}

impl<T: Stream> StreamConsumer for T { consume!{} }
impl<T: Future> FutureConsumer for T { consume!{} }
<|endoftext|>


<commit_before>use std::ops::Deref;
use core::*;
use lexer::*;
use parser::*;

struct Printer<'a> {
    ast: &'a AbstractSyntaxTree,
}

impl<'a> Printer<'a> {
    pub fn new(ast: &'a AbstractSyntaxTree) -> Self {
        Printer{ ast: ast }
    }

    pub fn print(&self) -> String {
        if let Some(entrypoint) = self.ast.entrypoint {
            println!("Printer print");
            self.print_aexp(entrypoint, 0)
        } else {
            "".to_string()
        }
    }

    fn print_aexp(&self, i: u32, nest_level: u32) -> String {
        let epiq = self.ast.get(i);
        match *epiq {
            Epiq::Name(ref n) => n.to_string(),
            Epiq::Uit8(ref n) => format!("{}", n),
            Epiq::Tpiq { ref o, p, q } => {
                format!("{}<{} {}>", o, self.print_aexp(p, nest_level + 1), self.print_aexp(q, nest_level + 1))
            }
            // _ => "".to_string(),
        }
    }
}

#[test]
// #[ignore]
fn test_print_symbol() {
    let scanners: &Vec<&Scanner> = &vec![&EOFScanner, &AlphanumericScanner];
    print_str("abc", "abc", scanners);
}

#[test]
// #[ignore]
fn test_print_number() {
    let scanners2: &Vec<&Scanner> = &vec![&EOFScanner, &ZeroScanner, &IntegerScanner];
    print_str("123", "123", scanners2);
}

#[test]
fn test_print_tpiq() {
    let scanners: &mut Vec<&Scanner> = &mut vec![
        &DelimiterScanner,
        &AlphanumericScanner,
        &ZeroScanner,
        &IntegerScanner,
        &EOFScanner,
    ];
    print_str("|: abc 123", ":<abc 123>", scanners);
}

#[test]
fn test_print_nested_tpiq() {
    let scanners: &mut Vec<&Scanner> = &mut vec![
        &DelimiterScanner,
        &AlphanumericScanner,
        &ZeroScanner,
        &IntegerScanner,
        &EOFScanner,
    ];
    print_str("|: |: cde |: abc 123 456", ":<:<cde :<abc 123>> 456>", scanners);
}

pub fn print_str(left: &str, right: &str, scanners: &Vec<&Scanner>) {
    let mut iter = left.bytes();
    let lexer = Lexer::new(&mut iter, scanners);
    let mut parser = Parser::new(lexer);
    let ast = parser.parse();
    let printer = Printer::new(ast.deref());

    assert_eq!(printer.print(), right);
}

/*
use super::core::{Epiq, Heliqs};

pub struct Printer<'a> {
    pub vm: &'a Heliqs,
}

impl<'a> Printer<'a> {
    pub fn print_aexp(&self, i: usize) -> String {
        if let Some(c) = self.vm.vctr.get(i) {
            match *c {
                Epiq::Name(ref n) => n.to_string(),
                Epiq::Tpiq { ref o, p, q } => {
                    format!(" {}<{} {}>", o, self.print_aexp(p), self.print_aexp(q))
                }
                _ => "".to_string(),
            }
        } else {
            "".to_string()
        }
    }
}
*/

/*
fn print_affx(&self, i: usize) -> String {
    let result = "".to_string();

    if let Some(c) = self.vm.vctr.get(i) {
        match c {
            &Epiq::Unit => {}, // case of 'has no affx'
            _ => {},
        }
    }

    return result;
}

fn print_epiq(&self, i: usize) -> String {
    let mut result = "".to_string();

    // check whether 'true list' or not
    let is_true_list = self.check_true_list(i);

    if let Some(c) = self.vm.vctr.get(i) {
        match c {
            &Epiq::Lpiq { p, q } => {
                if is_true_list {
                    result.push_str("[");
                    result.push_str(&self.print_list(p, q));
                } else {
                    result.push_str(&self.print_piq(" : ", p, q));
                }
            },
            &Epiq::Fpiq { p, q } => result.push_str(&self.print_piq(" |^ ", p, q)),
            &Epiq::Apiq { p, q } => result.push_str(&self.print_piq(" |! ", p, q)),

            &Epiq::Prmt(i) => {
                result.push_str("Prmt(");
                result.push_str(&self.print_aexp(i));
                result.push_str(")");
            },
            &Epiq::Aexp { a, e } => {
                result.push_str(&self.print_affx(a));
                result.push_str(&self.print_epiq(e));
            },
            &Epiq::Pprn(i) => {
                result.push_str("(");
                // print!("{:?}", self.check_true_list(i));
                result.push_str(&self.print_aexp(i));
                result.push_str(")");
            },
            _ => result.push_str(&format!("{:?}", c)),
        }
    }

    return result;
}

fn print_piq(&self, op: &str, p: usize, q: usize) -> String {
    let mut result = "".to_string();

    if self.vm.vctr.get(p).is_some() {
        result.push_str(&self.print_aexp(p));
    }
    print!("{:}",op);
    if self.vm.vctr.get(q).is_some() {
        result.push_str(&self.print_aexp(q));
    }

    return result;
}

/// check whether 'true list' or not
fn check_true_list(&self, i: usize) -> bool {
    let mut idx = i;
    while let Some(c) = self.vm.vctr.get(idx) {
        match c {
            &Epiq::Aexp { a:_, e } => {
                match self.vm.vctr.get(e) {
                    Some(&Epiq::Unit) => return true,
                    _ => return false,
                }
            },
            &Epiq::Unit => return true, // もはやここは通らないと思うが、一旦残しておく
            &Epiq::Lpiq { p:_, q } => {
                idx = q;
            },
            _ => return false,
        }
    }
    false
}

fn print_list(&self, pi: usize, qi: usize) -> String {
    let mut result = "".to_string();

    if self.vm.vctr.get(pi).is_some() {
        result.push_str(&self.print_aexp(pi));
    }

    match self.vm.vctr.get(qi) {
        Some(&Epiq::Aexp { a:_, e }) => {
            match self.vm.vctr.get(e) {
                Some(&Epiq::Unit) => result.push_str("]"),
                _ => {},
            }
        }
        Some(&Epiq::Lpiq { p, q }) => {
            result.push_str(" ");
            result.push_str(&self.print_list(p, q));
        },
        None => result.push_str(")"),
        _ => result.push_str(&format!("error on print vm: {:?}", self.vm.vctr)),
    }

    return result;
}
*/

/*
fn aexp_e<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Aexp { a:_, e }) => Some((t.0, e)),
    _ => None,
}
}

fn apiq_f<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Apiq { p, q:_ }) => Some((t.0, p)),
    _ => None,
}
}

fn apiq_q<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Apiq { p:_, q }) => Some((t.0, q)),
    _ => None,
}
}

fn fpiq_p<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Fpiq { p, q:_ }) => Some((t.0, p)),
    Some(a) => {
        println!("not fpiq: {:?}", a);
        None
    },
    _ => None,
}
}
*/
/*
fn pprn<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Pprn(i)) => Some((t.0, i)),
    Some(a) => {
        println!("not pprn: {:?}", a);
        None
    },
    _ => None,
}
}
*/
/*
fn print_one_piq<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(e) => {
        println!("print_one_piq: {:?}", e);
        Some(t)
    },
    _ => None,
}
}
*/
<commit_msg>change printing format a little<commit_after>use std::ops::Deref;
use core::*;
use lexer::*;
use parser::*;

struct Printer<'a> {
    ast: &'a AbstractSyntaxTree,
}

impl<'a> Printer<'a> {
    pub fn new(ast: &'a AbstractSyntaxTree) -> Self {
        Printer{ ast: ast }
    }

    pub fn print(&self) -> String {
        if let Some(entrypoint) = self.ast.entrypoint {
            println!("Printer print");
            self.print_aexp(entrypoint, 0)
        } else {
            "".to_string()
        }
    }

    fn print_aexp(&self, i: u32, nest_level: u32) -> String {
        let epiq = self.ast.get(i);
        match *epiq {
            Epiq::Name(ref n) => n.to_string(),
            Epiq::Uit8(ref n) => format!("{}", n),
            Epiq::Tpiq { ref o, p, q } => {
                format!("{}< {} {} >", o, self.print_aexp(p, nest_level + 1), self.print_aexp(q, nest_level + 1))
            }
            // _ => "".to_string(),
        }
    }
}

#[test]
// #[ignore]
fn test_print_symbol() {
    let scanners: &Vec<&Scanner> = &vec![&EOFScanner, &AlphanumericScanner];
    print_str("abc", "abc", scanners);
}

#[test]
// #[ignore]
fn test_print_number() {
    let scanners2: &Vec<&Scanner> = &vec![&EOFScanner, &ZeroScanner, &IntegerScanner];
    print_str("123", "123", scanners2);
}

#[test]
fn test_print_tpiq() {
    let scanners: &mut Vec<&Scanner> = &mut vec![
        &DelimiterScanner,
        &AlphanumericScanner,
        &ZeroScanner,
        &IntegerScanner,
        &EOFScanner,
    ];
    print_str("|: abc 123", ":< abc 123 >", scanners);
}

#[test]
fn test_print_nested_tpiq() {
    let scanners: &mut Vec<&Scanner> = &mut vec![
        &DelimiterScanner,
        &AlphanumericScanner,
        &ZeroScanner,
        &IntegerScanner,
        &EOFScanner,
    ];
    print_str("|: |: cde |: abc 123 456", ":< :< cde :< abc 123 > > 456 >", scanners);
}

pub fn print_str(left: &str, right: &str, scanners: &Vec<&Scanner>) {
    let mut iter = left.bytes();
    let lexer = Lexer::new(&mut iter, scanners);
    let mut parser = Parser::new(lexer);
    let ast = parser.parse();
    let printer = Printer::new(ast.deref());

    assert_eq!(printer.print(), right);
}

/*
use super::core::{Epiq, Heliqs};

pub struct Printer<'a> {
    pub vm: &'a Heliqs,
}

impl<'a> Printer<'a> {
    pub fn print_aexp(&self, i: usize) -> String {
        if let Some(c) = self.vm.vctr.get(i) {
            match *c {
                Epiq::Name(ref n) => n.to_string(),
                Epiq::Tpiq { ref o, p, q } => {
                    format!(" {}<{} {}>", o, self.print_aexp(p), self.print_aexp(q))
                }
                _ => "".to_string(),
            }
        } else {
            "".to_string()
        }
    }
}
*/

/*
fn print_affx(&self, i: usize) -> String {
    let result = "".to_string();

    if let Some(c) = self.vm.vctr.get(i) {
        match c {
            &Epiq::Unit => {}, // case of 'has no affx'
            _ => {},
        }
    }

    return result;
}

fn print_epiq(&self, i: usize) -> String {
    let mut result = "".to_string();

    // check whether 'true list' or not
    let is_true_list = self.check_true_list(i);

    if let Some(c) = self.vm.vctr.get(i) {
        match c {
            &Epiq::Lpiq { p, q } => {
                if is_true_list {
                    result.push_str("[");
                    result.push_str(&self.print_list(p, q));
                } else {
                    result.push_str(&self.print_piq(" : ", p, q));
                }
            },
            &Epiq::Fpiq { p, q } => result.push_str(&self.print_piq(" |^ ", p, q)),
            &Epiq::Apiq { p, q } => result.push_str(&self.print_piq(" |! ", p, q)),

            &Epiq::Prmt(i) => {
                result.push_str("Prmt(");
                result.push_str(&self.print_aexp(i));
                result.push_str(")");
            },
            &Epiq::Aexp { a, e } => {
                result.push_str(&self.print_affx(a));
                result.push_str(&self.print_epiq(e));
            },
            &Epiq::Pprn(i) => {
                result.push_str("(");
                // print!("{:?}", self.check_true_list(i));
                result.push_str(&self.print_aexp(i));
                result.push_str(")");
            },
            _ => result.push_str(&format!("{:?}", c)),
        }
    }

    return result;
}

fn print_piq(&self, op: &str, p: usize, q: usize) -> String {
    let mut result = "".to_string();

    if self.vm.vctr.get(p).is_some() {
        result.push_str(&self.print_aexp(p));
    }
    print!("{:}",op);
    if self.vm.vctr.get(q).is_some() {
        result.push_str(&self.print_aexp(q));
    }

    return result;
}

/// check whether 'true list' or not
fn check_true_list(&self, i: usize) -> bool {
    let mut idx = i;
    while let Some(c) = self.vm.vctr.get(idx) {
        match c {
            &Epiq::Aexp { a:_, e } => {
                match self.vm.vctr.get(e) {
                    Some(&Epiq::Unit) => return true,
                    _ => return false,
                }
            },
            &Epiq::Unit => return true, // もはやここは通らないと思うが、一旦残しておく
            &Epiq::Lpiq { p:_, q } => {
                idx = q;
            },
            _ => return false,
        }
    }
    false
}

fn print_list(&self, pi: usize, qi: usize) -> String {
    let mut result = "".to_string();

    if self.vm.vctr.get(pi).is_some() {
        result.push_str(&self.print_aexp(pi));
    }

    match self.vm.vctr.get(qi) {
        Some(&Epiq::Aexp { a:_, e }) => {
            match self.vm.vctr.get(e) {
                Some(&Epiq::Unit) => result.push_str("]"),
                _ => {},
            }
        }
        Some(&Epiq::Lpiq { p, q }) => {
            result.push_str(" ");
            result.push_str(&self.print_list(p, q));
        },
        None => result.push_str(")"),
        _ => result.push_str(&format!("error on print vm: {:?}", self.vm.vctr)),
    }

    return result;
}
*/

/*
fn aexp_e<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Aexp { a:_, e }) => Some((t.0, e)),
    _ => None,
}
}

fn apiq_f<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Apiq { p, q:_ }) => Some((t.0, p)),
    _ => None,
}
}

fn apiq_q<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Apiq { p:_, q }) => Some((t.0, q)),
    _ => None,
}
}

fn fpiq_p<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Fpiq { p, q:_ }) => Some((t.0, p)),
    Some(a) => {
        println!("not fpiq: {:?}", a);
        None
    },
    _ => None,
}
}
*/
/*
fn pprn<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(&Epiq::Pprn(i)) => Some((t.0, i)),
    Some(a) => {
        println!("not pprn: {:?}", a);
        None
    },
    _ => None,
}
}
*/
/*
fn print_one_piq<'p, 'a>(t: (&'p Parser<'a>, usize)) -> Option<(&'p Parser<'a>, usize)> {
match t.0.vm.vctr.get(t.1) {
    Some(e) => {
        println!("print_one_piq: {:?}", e);
        Some(t)
    },
    _ => None,
}
}
*/
<|endoftext|>


<commit_before>use byteorder::ReadBytesExt;
use net2::TcpStreamExt;
use std::io;
use std::io::prelude::*;
use std::fmt;
use std::net::TcpStream;
use std::time::Duration;
use bufstream::BufStream;
#[cfg(feature = "unix_socket")]
use unix_socket::UnixStream;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, RawSocket};

use {SslMode, ConnectParams, ConnectTarget};
use error::ConnectError;
use io::{NegotiateSsl, StreamWrapper};
use message::{self, WriteMessage};
use message::FrontendMessage::SslRequest;

const DEFAULT_PORT: u16 = 5432;

#[doc(hidden)]
pub trait StreamOptions {
    fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()>;
    fn set_nonblocking(&self, nonblock: bool) -> io::Result<()>;
}

impl StreamOptions for BufStream<Box<StreamWrapper>> {
    fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
        match self.get_ref().get_ref().0 {
            InternalStream::Tcp(ref s) => {
                <TcpStream as TcpStreamExt>::set_read_timeout(s, timeout)
            }
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref s) => s.set_read_timeout(timeout),
        }
    }

    fn set_nonblocking(&self, nonblock: bool) -> io::Result<()> {
        match self.get_ref().get_ref().0 {
            InternalStream::Tcp(ref s) => s.set_nonblocking(nonblock),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref s) => s.set_nonblocking(nonblock),
        }
    }
}

/// A connection to the Postgres server.
///
/// It implements `Read`, `Write` and `StreamWrapper`, as well as `AsRawFd` on
/// Unix platforms and `AsRawSocket` on Windows platforms.
pub struct Stream(InternalStream);

impl fmt::Debug for Stream {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            InternalStream::Tcp(ref s) => fmt::Debug::fmt(s, fmt),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref s) => fmt::Debug::fmt(s, fmt),
        }
    }
}

impl Read for Stream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl Write for Stream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

impl StreamWrapper for Stream {
    fn get_ref(&self) -> &Stream {
        self
    }

    fn get_mut(&mut self) -> &mut Stream {
        self
    }
}

#[cfg(unix)]
impl AsRawFd for Stream {
    fn as_raw_fd(&self) -> RawFd {
        match self.0 {
            InternalStream::Tcp(ref s) => s.as_raw_fd(),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref s) => s.as_raw_fd(),
        }
    }
}

#[cfg(windows)]
impl AsRawSocket for Stream {
    fn as_raw_socket(&self) -> RawSocket {
        // Unix sockets aren't supported on windows, so no need to match
        match self.0 {
            InternalStream::Tcp(ref s) => s.as_raw_socket(),
        }
    }
}

enum InternalStream {
    Tcp(TcpStream),
    #[cfg(feature = "unix_socket")]
    Unix(UnixStream),
}

impl Read for InternalStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            InternalStream::Tcp(ref mut s) => s.read(buf),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref mut s) => s.read(buf),
        }
    }
}

impl Write for InternalStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match *self {
            InternalStream::Tcp(ref mut s) => s.write(buf),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref mut s) => s.write(buf),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match *self {
            InternalStream::Tcp(ref mut s) => s.flush(),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref mut s) => s.flush(),
        }
    }
}

fn open_socket(params: &ConnectParams) -> Result<InternalStream, ConnectError> {
    let port = params.port.unwrap_or(DEFAULT_PORT);
    match params.target {
        ConnectTarget::Tcp(ref host) => {
            Ok(try!(TcpStream::connect(&(&**host, port)).map(InternalStream::Tcp)))
        }
        #[cfg(feature = "unix_socket")]
        ConnectTarget::Unix(ref path) => {
            let path = path.join(&format!(".s.PGSQL.{}", port));
            Ok(try!(UnixStream::connect(&path).map(InternalStream::Unix)))
        }
    }
}

pub fn initialize_stream(params: &ConnectParams,
                         ssl: SslMode)
                         -> Result<Box<StreamWrapper>, ConnectError> {
    let mut socket = Stream(try!(open_socket(params)));

    let (ssl_required, negotiator) = match ssl {
        SslMode::None => return Ok(Box::new(socket)),
        SslMode::Prefer(negotiator) => (false, negotiator),
        SslMode::Require(negotiator) => (true, negotiator),
    };

    try!(socket.write_message(&SslRequest { code: message::SSL_CODE }));
    try!(socket.flush());

    if try!(socket.read_u8()) == 'N' as u8 {
        if ssl_required {
            return Err(ConnectError::NoSslSupport);
        } else {
            return Ok(Box::new(socket));
        }
    }

    // Postgres doesn't support SSL over unix sockets
    let host = match params.target {
        ConnectTarget::Tcp(ref host) => host,
        #[cfg(feature = "unix_socket")]
        ConnectTarget::Unix(_) => return Err(ConnectError::Io(::bad_response())),
    };

    match negotiator.negotiate_ssl(host, socket) {
        Ok(stream) => Ok(stream),
        Err(err) => Err(ConnectError::Ssl(err)),
    }
}
<commit_msg>Drop UFCS for set_read_timeout<commit_after>use byteorder::ReadBytesExt;
use net2::TcpStreamExt;
use std::io;
use std::io::prelude::*;
use std::fmt;
use std::net::TcpStream;
use std::time::Duration;
use bufstream::BufStream;
#[cfg(feature = "unix_socket")]
use unix_socket::UnixStream;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, RawSocket};

use {SslMode, ConnectParams, ConnectTarget};
use error::ConnectError;
use io::{NegotiateSsl, StreamWrapper};
use message::{self, WriteMessage};
use message::FrontendMessage::SslRequest;

const DEFAULT_PORT: u16 = 5432;

#[doc(hidden)]
pub trait StreamOptions {
    fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()>;
    fn set_nonblocking(&self, nonblock: bool) -> io::Result<()>;
}

impl StreamOptions for BufStream<Box<StreamWrapper>> {
    fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
        match self.get_ref().get_ref().0 {
            InternalStream::Tcp(ref s) => s.set_read_timeout(timeout),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref s) => s.set_read_timeout(timeout),
        }
    }

    fn set_nonblocking(&self, nonblock: bool) -> io::Result<()> {
        match self.get_ref().get_ref().0 {
            InternalStream::Tcp(ref s) => s.set_nonblocking(nonblock),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref s) => s.set_nonblocking(nonblock),
        }
    }
}

/// A connection to the Postgres server.
///
/// It implements `Read`, `Write` and `StreamWrapper`, as well as `AsRawFd` on
/// Unix platforms and `AsRawSocket` on Windows platforms.
pub struct Stream(InternalStream);

impl fmt::Debug for Stream {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            InternalStream::Tcp(ref s) => fmt::Debug::fmt(s, fmt),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref s) => fmt::Debug::fmt(s, fmt),
        }
    }
}

impl Read for Stream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl Write for Stream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

impl StreamWrapper for Stream {
    fn get_ref(&self) -> &Stream {
        self
    }

    fn get_mut(&mut self) -> &mut Stream {
        self
    }
}

#[cfg(unix)]
impl AsRawFd for Stream {
    fn as_raw_fd(&self) -> RawFd {
        match self.0 {
            InternalStream::Tcp(ref s) => s.as_raw_fd(),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref s) => s.as_raw_fd(),
        }
    }
}

#[cfg(windows)]
impl AsRawSocket for Stream {
    fn as_raw_socket(&self) -> RawSocket {
        // Unix sockets aren't supported on windows, so no need to match
        match self.0 {
            InternalStream::Tcp(ref s) => s.as_raw_socket(),
        }
    }
}

enum InternalStream {
    Tcp(TcpStream),
    #[cfg(feature = "unix_socket")]
    Unix(UnixStream),
}

impl Read for InternalStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            InternalStream::Tcp(ref mut s) => s.read(buf),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref mut s) => s.read(buf),
        }
    }
}

impl Write for InternalStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match *self {
            InternalStream::Tcp(ref mut s) => s.write(buf),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref mut s) => s.write(buf),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match *self {
            InternalStream::Tcp(ref mut s) => s.flush(),
            #[cfg(feature = "unix_socket")]
            InternalStream::Unix(ref mut s) => s.flush(),
        }
    }
}

fn open_socket(params: &ConnectParams) -> Result<InternalStream, ConnectError> {
    let port = params.port.unwrap_or(DEFAULT_PORT);
    match params.target {
        ConnectTarget::Tcp(ref host) => {
            Ok(try!(TcpStream::connect(&(&**host, port)).map(InternalStream::Tcp)))
        }
        #[cfg(feature = "unix_socket")]
        ConnectTarget::Unix(ref path) => {
            let path = path.join(&format!(".s.PGSQL.{}", port));
            Ok(try!(UnixStream::connect(&path).map(InternalStream::Unix)))
        }
    }
}

pub fn initialize_stream(params: &ConnectParams,
                         ssl: SslMode)
                         -> Result<Box<StreamWrapper>, ConnectError> {
    let mut socket = Stream(try!(open_socket(params)));

    let (ssl_required, negotiator) = match ssl {
        SslMode::None => return Ok(Box::new(socket)),
        SslMode::Prefer(negotiator) => (false, negotiator),
        SslMode::Require(negotiator) => (true, negotiator),
    };

    try!(socket.write_message(&SslRequest { code: message::SSL_CODE }));
    try!(socket.flush());

    if try!(socket.read_u8()) == 'N' as u8 {
        if ssl_required {
            return Err(ConnectError::NoSslSupport);
        } else {
            return Ok(Box::new(socket));
        }
    }

    // Postgres doesn't support SSL over unix sockets
    let host = match params.target {
        ConnectTarget::Tcp(ref host) => host,
        #[cfg(feature = "unix_socket")]
        ConnectTarget::Unix(_) => return Err(ConnectError::Io(::bad_response())),
    };

    match negotiator.negotiate_ssl(host, socket) {
        Ok(stream) => Ok(stream),
        Err(err) => Err(ConnectError::Ssl(err)),
    }
}
<|endoftext|>


<commit_before>use {CameraCalibration, Error, MountCalibration, Result, ScanPosition, utils};
use element::Extension;
use nalgebra::Projective3;
use scan_position::{Image, Scan};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use xmltree::Element;

/// A RiSCAN Pro project.
///
/// These are always created by pointing at a path, either the `.RiSCAN` path or the `project.rsp`
/// in that directory:
///
/// ```
/// use riscan_pro::Project;
/// let project1 = Project::from_path("data/project.RiSCAN").unwrap();
/// let project2 = Project::from_path("data/project.RiSCAN/project.rsp").unwrap();
/// assert_eq!(project1, project2);
/// ```
#[derive(Clone, Debug, Serialize, PartialEq)]
pub struct Project {
    /// The path to the project rsp file.
    pub path: PathBuf,
    /// The camera calibrations, by name.
    pub camera_calibrations: HashMap<String, CameraCalibration>,
    /// The camera mount calibrations, by name.
    pub mount_calibrations: HashMap<String, MountCalibration>,
    /// The scan positions, by name.
    pub scan_positions: HashMap<String, ScanPosition>,
    /// The project's own position.
    pub pop: Projective3<f64>,
}

impl Project {
    /// Creates a project from a filesystem path.
    ///
    /// This path can be either the `.RiSCAN` directory or the contained `project.rsp`.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Project> {
        use std::fs::File;

        let path = rsp_path(path)?;
        let file = File::open(&path)?;
        let xml = Element::parse(file)?;

        let camera_calibrations = xml.children("calibrations/camcalibs/camcalib_opencv")?
            .iter()
            .map(|camcalib_opencv| {
                let camera_calibration = CameraCalibration::from_element(camcalib_opencv)?;
                Ok((camera_calibration.name.clone(), camera_calibration))
            })
            .collect::<Result<HashMap<_, _>>>()?;
        let mount_calibrations = xml.children("calibrations/mountcalibs/mountcalib")?
            .iter()
            .map(|mountcalib| {
                let mount_calibration = MountCalibration::from_element(mountcalib)?;
                Ok((mount_calibration.name.clone(), mount_calibration))
            })
            .collect::<Result<HashMap<_, _>>>()?;
        let scan_positions = xml.children("scanpositions/scanposition")?
            .iter()
            .map(|scanposition| {
                let scan_position = ScanPosition::from_element(scanposition)?;
                Ok((scan_position.name.clone(), scan_position))
            })
            .collect::<Result<HashMap<_, _>>>()?;

        Ok(Project {
            camera_calibrations: camera_calibrations,
            mount_calibrations: mount_calibrations,
            scan_positions: scan_positions,
            path: path.to_path_buf(),
            pop: utils::parse_projective3(xml.child("pop/matrix")?.as_str()?)?,
        })
    }

    /// Returns a scan position, as determined by the path.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let scan_position1 = project.scan_positions.get("SP01").unwrap();
    /// let path = "data/project.RiSCAN/SCANS/SP01/SCANPOSIMAGES/SP01 - Image001.csv";
    /// let scan_position2 = project.scan_position_from_path(path).unwrap();
    /// assert_eq!(scan_position1, scan_position2);
    /// ```
    pub fn scan_position_from_path<P: AsRef<Path>>(&self, path: P) -> Result<&ScanPosition> {
        path.as_ref()
            .file_stem()
            .map(|file_stem| file_stem.to_string_lossy())
            .and_then(|file_stem| {
                file_stem.split(" - ").next().and_then(|name| {
                    self.scan_positions.get(name)
                })
            })
            .ok_or_else(|| Error::ScanPositionFromPath(path.as_ref().to_path_buf()))
    }
}

impl CameraCalibration {
    fn from_element(element: &Element) -> Result<CameraCalibration> {
        let version = element.child("version")?.as_str()?;
        if version == "2" {
            Ok(CameraCalibration {
                name: element.child("name")?.as_str()?.to_string(),
                cx: element.child("internal_opencv/cx")?.parse_text()?,
                cy: element.child("internal_opencv/cy")?.parse_text()?,
                fx: element.child("internal_opencv/fx")?.parse_text()?,
                fy: element.child("internal_opencv/fy")?.parse_text()?,
                k1: element.child("internal_opencv/k1")?.parse_text()?,
                k2: element.child("internal_opencv/k2")?.parse_text()?,
                k3: element.child("internal_opencv/k3")?.parse_text()?,
                k4: element.child("internal_opencv/k4")?.parse_text()?,
                p1: element.child("internal_opencv/p1")?.parse_text()?,
                p2: element.child("internal_opencv/p2")?.parse_text()?,
                tan_max_horz: element.child("angle_extents/tan_max_horz")?.parse_text()?,
                tan_max_vert: element.child("angle_extents/tan_max_vert")?.parse_text()?,
                tan_min_horz: element.child("angle_extents/tan_min_horz")?.parse_text()?,
                tan_min_vert: element.child("angle_extents/tan_min_vert")?.parse_text()?,
                width: element.child("intrinsic_opencv/nx")?.parse_text()?,
                height: element.child("intrinsic_opencv/ny")?.parse_text()?,
            })
        } else {
            Err(Error::CameraCalibrationVersion(version.to_string()))
        }
    }
}

impl MountCalibration {
    fn from_element(element: &Element) -> Result<MountCalibration> {
        Ok(MountCalibration {
            name: element.child("name")?.as_str()?.to_string(),
            matrix: utils::parse_projective3(element.child("matrix")?.as_str()?)?,
        })
    }
}

impl ScanPosition {
    fn from_element(element: &Element) -> Result<ScanPosition> {
        Ok(ScanPosition {
            name: element.child("name")?.as_str()?.to_string(),
            images: element
                .children("scanposimages/scanposimage")?
                .iter()
                .map(|scanposimage| {
                    let image = Image::from_element(scanposimage)?;
                    Ok((image.name.clone(), image))
                })
                .collect::<Result<_>>()?,
            scans: element
                .children("singlescans/scan")?
                .iter()
                .map(|scan| {
                    let scan = Scan::from_element(scan)?;
                    Ok((scan.name.clone(), scan))
                })
                .collect::<Result<_>>()?,
            sop: utils::parse_projective3(element.child("sop/matrix")?.as_str()?)?,
        })
    }
}

impl Scan {
    fn from_element(element: &Element) -> Result<Scan> {
        Ok(Scan {
            name: element.child("name")?.as_str()?.to_string(),
            file: element.child("file")?.as_str()?.to_string(),
            theta_count: element.child("theta_count")?.parse_text()?,
            phi_count: element.child("phi_count")?.parse_text()?,
        })
    }
}

impl Image {
    fn from_element(element: &Element) -> Result<Image> {
        Ok(Image {
            name: element.child("name")?.as_str()?.to_string(),
            cop: utils::parse_projective3(element.child("cop/matrix")?.as_str()?)?,
            camera_calibration_name: element.child("camcalib_ref")?.noderef()?.to_string(),
            mount_calibration_name: element.child("mountcalib_ref")?.noderef()?.to_string(),
        })
    }
}

fn rsp_path<P: AsRef<Path>>(path: P) -> Result<PathBuf> {
    if let Some(extension) = path.as_ref().extension() {
        let mut path_buf = path.as_ref().to_path_buf();
        if extension == "rsp" {
            return Ok(path_buf);
        } else if extension == "RiSCAN" {
            path_buf.push("project.rsp");
            return Ok(path_buf);
        }
    }
    let mut path_buf = PathBuf::new();
    for component in path.as_ref().iter() {
        path_buf.push(component);
        if Path::new(component)
            .extension()
            .map(|e| e == "RiSCAN")
            .unwrap_or(false)
        {
            return rsp_path(path_buf);
        }
    }
    Err(Error::ProjectPath(path_buf))
}

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

    #[test]
    fn from_path() {
        Project::from_path("data/project.RiSCAN").unwrap();
        Project::from_path("data/project.RiSCAN/project.rsp").unwrap();
        Project::from_path("data/project.RiSCAN/SCANS").unwrap();
        assert!(Project::from_path("data").is_err());
    }

    #[test]
    fn mount_calibrations() {
        use utils;

        let project = Project::from_path("data/project.RiSCAN").unwrap();
        let mount_calibration = project
            .mount_calibrations
            .get("Infratec_VarioCAM_HD_15mm_11-16-2015_Preston")
            .unwrap();
        let matrix = utils::parse_projective3("-0.010877741999999997 -0.003724941 -0.999933898 0.18508641   0.019274697 0.999806486 -0.0039341460000000013 0.000460517   0.99975505 -0.019316217 -0.01080384 -0.092802787   0 0 0 1").unwrap();
        assert_eq!(matrix, **mount_calibration);
    }

    #[test]
    fn scan_position_from_path() {
        let project = Project::from_path("data/project.RiSCAN").unwrap();
        let scan_position1 = project.scan_positions.get("SP01").unwrap();
        let scan_position2 = project
            .scan_position_from_path(
                "data/project.RiSCAN/SCANS/SP01/SCANPOSIMAGES/SP01 - Image001.csv",
            )
            .unwrap();
        assert_eq!(scan_position1, scan_position2);
    }

    #[test]
    fn only_accept_version_2_camera_calibrations() {
        Project::from_path("data/project.RiSCAN").unwrap();
        assert!(Project::from_path("data/camera-calibration-version-0.rsp").is_err());
        assert!(Project::from_path("data/camera-calibration-version-1.rsp").is_err());
    }
}
<commit_msg>Canonicalize the project path<commit_after>use {CameraCalibration, Error, MountCalibration, Result, ScanPosition, utils};
use element::Extension;
use nalgebra::Projective3;
use scan_position::{Image, Scan};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use xmltree::Element;

/// A RiSCAN Pro project.
///
/// These are always created by pointing at a path, either the `.RiSCAN` path or the `project.rsp`
/// in that directory:
///
/// ```
/// use riscan_pro::Project;
/// let project1 = Project::from_path("data/project.RiSCAN").unwrap();
/// let project2 = Project::from_path("data/project.RiSCAN/project.rsp").unwrap();
/// assert_eq!(project1, project2);
/// ```
#[derive(Clone, Debug, Serialize, PartialEq)]
pub struct Project {
    /// The path to the project rsp file.
    pub path: PathBuf,
    /// The camera calibrations, by name.
    pub camera_calibrations: HashMap<String, CameraCalibration>,
    /// The camera mount calibrations, by name.
    pub mount_calibrations: HashMap<String, MountCalibration>,
    /// The scan positions, by name.
    pub scan_positions: HashMap<String, ScanPosition>,
    /// The project's own position.
    pub pop: Projective3<f64>,
}

impl Project {
    /// Creates a project from a filesystem path.
    ///
    /// This path can be either the `.RiSCAN` directory or the contained `project.rsp`.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Project> {
        use std::fs::File;

        let path = rsp_path(path)?;
        let file = File::open(&path)?;
        let xml = Element::parse(file)?;

        let camera_calibrations = xml.children("calibrations/camcalibs/camcalib_opencv")?
            .iter()
            .map(|camcalib_opencv| {
                let camera_calibration = CameraCalibration::from_element(camcalib_opencv)?;
                Ok((camera_calibration.name.clone(), camera_calibration))
            })
            .collect::<Result<HashMap<_, _>>>()?;
        let mount_calibrations = xml.children("calibrations/mountcalibs/mountcalib")?
            .iter()
            .map(|mountcalib| {
                let mount_calibration = MountCalibration::from_element(mountcalib)?;
                Ok((mount_calibration.name.clone(), mount_calibration))
            })
            .collect::<Result<HashMap<_, _>>>()?;
        let scan_positions = xml.children("scanpositions/scanposition")?
            .iter()
            .map(|scanposition| {
                let scan_position = ScanPosition::from_element(scanposition)?;
                Ok((scan_position.name.clone(), scan_position))
            })
            .collect::<Result<HashMap<_, _>>>()?;

        Ok(Project {
            camera_calibrations: camera_calibrations,
            mount_calibrations: mount_calibrations,
            scan_positions: scan_positions,
            path: path.canonicalize()?,
            pop: utils::parse_projective3(xml.child("pop/matrix")?.as_str()?)?,
        })
    }

    /// Returns a scan position, as determined by the path.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let scan_position1 = project.scan_positions.get("SP01").unwrap();
    /// let path = "data/project.RiSCAN/SCANS/SP01/SCANPOSIMAGES/SP01 - Image001.csv";
    /// let scan_position2 = project.scan_position_from_path(path).unwrap();
    /// assert_eq!(scan_position1, scan_position2);
    /// ```
    pub fn scan_position_from_path<P: AsRef<Path>>(&self, path: P) -> Result<&ScanPosition> {
        path.as_ref()
            .file_stem()
            .map(|file_stem| file_stem.to_string_lossy())
            .and_then(|file_stem| {
                file_stem.split(" - ").next().and_then(|name| {
                    self.scan_positions.get(name)
                })
            })
            .ok_or_else(|| Error::ScanPositionFromPath(path.as_ref().to_path_buf()))
    }
}

impl CameraCalibration {
    fn from_element(element: &Element) -> Result<CameraCalibration> {
        let version = element.child("version")?.as_str()?;
        if version == "2" {
            Ok(CameraCalibration {
                name: element.child("name")?.as_str()?.to_string(),
                cx: element.child("internal_opencv/cx")?.parse_text()?,
                cy: element.child("internal_opencv/cy")?.parse_text()?,
                fx: element.child("internal_opencv/fx")?.parse_text()?,
                fy: element.child("internal_opencv/fy")?.parse_text()?,
                k1: element.child("internal_opencv/k1")?.parse_text()?,
                k2: element.child("internal_opencv/k2")?.parse_text()?,
                k3: element.child("internal_opencv/k3")?.parse_text()?,
                k4: element.child("internal_opencv/k4")?.parse_text()?,
                p1: element.child("internal_opencv/p1")?.parse_text()?,
                p2: element.child("internal_opencv/p2")?.parse_text()?,
                tan_max_horz: element.child("angle_extents/tan_max_horz")?.parse_text()?,
                tan_max_vert: element.child("angle_extents/tan_max_vert")?.parse_text()?,
                tan_min_horz: element.child("angle_extents/tan_min_horz")?.parse_text()?,
                tan_min_vert: element.child("angle_extents/tan_min_vert")?.parse_text()?,
                width: element.child("intrinsic_opencv/nx")?.parse_text()?,
                height: element.child("intrinsic_opencv/ny")?.parse_text()?,
            })
        } else {
            Err(Error::CameraCalibrationVersion(version.to_string()))
        }
    }
}

impl MountCalibration {
    fn from_element(element: &Element) -> Result<MountCalibration> {
        Ok(MountCalibration {
            name: element.child("name")?.as_str()?.to_string(),
            matrix: utils::parse_projective3(element.child("matrix")?.as_str()?)?,
        })
    }
}

impl ScanPosition {
    fn from_element(element: &Element) -> Result<ScanPosition> {
        Ok(ScanPosition {
            name: element.child("name")?.as_str()?.to_string(),
            images: element
                .children("scanposimages/scanposimage")?
                .iter()
                .map(|scanposimage| {
                    let image = Image::from_element(scanposimage)?;
                    Ok((image.name.clone(), image))
                })
                .collect::<Result<_>>()?,
            scans: element
                .children("singlescans/scan")?
                .iter()
                .map(|scan| {
                    let scan = Scan::from_element(scan)?;
                    Ok((scan.name.clone(), scan))
                })
                .collect::<Result<_>>()?,
            sop: utils::parse_projective3(element.child("sop/matrix")?.as_str()?)?,
        })
    }
}

impl Scan {
    fn from_element(element: &Element) -> Result<Scan> {
        Ok(Scan {
            name: element.child("name")?.as_str()?.to_string(),
            file: element.child("file")?.as_str()?.to_string(),
            theta_count: element.child("theta_count")?.parse_text()?,
            phi_count: element.child("phi_count")?.parse_text()?,
        })
    }
}

impl Image {
    fn from_element(element: &Element) -> Result<Image> {
        Ok(Image {
            name: element.child("name")?.as_str()?.to_string(),
            cop: utils::parse_projective3(element.child("cop/matrix")?.as_str()?)?,
            camera_calibration_name: element.child("camcalib_ref")?.noderef()?.to_string(),
            mount_calibration_name: element.child("mountcalib_ref")?.noderef()?.to_string(),
        })
    }
}

fn rsp_path<P: AsRef<Path>>(path: P) -> Result<PathBuf> {
    if let Some(extension) = path.as_ref().extension() {
        let mut path_buf = path.as_ref().to_path_buf();
        if extension == "rsp" {
            return Ok(path_buf);
        } else if extension == "RiSCAN" {
            path_buf.push("project.rsp");
            return Ok(path_buf);
        }
    }
    let mut path_buf = PathBuf::new();
    for component in path.as_ref().iter() {
        path_buf.push(component);
        if Path::new(component)
            .extension()
            .map(|e| e == "RiSCAN")
            .unwrap_or(false)
        {
            return rsp_path(path_buf);
        }
    }
    Err(Error::ProjectPath(path_buf))
}

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

    #[test]
    fn from_path() {
        Project::from_path("data/project.RiSCAN").unwrap();
        Project::from_path("data/project.RiSCAN/project.rsp").unwrap();
        Project::from_path("data/project.RiSCAN/SCANS").unwrap();
        assert!(Project::from_path("data").is_err());
    }

    #[test]
    fn mount_calibrations() {
        use utils;

        let project = Project::from_path("data/project.RiSCAN").unwrap();
        let mount_calibration = project
            .mount_calibrations
            .get("Infratec_VarioCAM_HD_15mm_11-16-2015_Preston")
            .unwrap();
        let matrix = utils::parse_projective3("-0.010877741999999997 -0.003724941 -0.999933898 0.18508641   0.019274697 0.999806486 -0.0039341460000000013 0.000460517   0.99975505 -0.019316217 -0.01080384 -0.092802787   0 0 0 1").unwrap();
        assert_eq!(matrix, **mount_calibration);
    }

    #[test]
    fn scan_position_from_path() {
        let project = Project::from_path("data/project.RiSCAN").unwrap();
        let scan_position1 = project.scan_positions.get("SP01").unwrap();
        let scan_position2 = project
            .scan_position_from_path(
                "data/project.RiSCAN/SCANS/SP01/SCANPOSIMAGES/SP01 - Image001.csv",
            )
            .unwrap();
        assert_eq!(scan_position1, scan_position2);
    }

    #[test]
    fn only_accept_version_2_camera_calibrations() {
        Project::from_path("data/project.RiSCAN").unwrap();
        assert!(Project::from_path("data/camera-calibration-version-0.rsp").is_err());
        assert!(Project::from_path("data/camera-calibration-version-1.rsp").is_err());
    }
}
<|endoftext|>


<commit_before>use itertools::{multipeek, MultiPeek};
use std::str;

#[derive(Debug, PartialEq)]
pub enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Equal,
    EqualEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(f64),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    // The book doesn't have tokens for comments and
    // whitespaces. Introducing them the scanner can
    // deal with them uniformly and in a more
    // functional way.
    Comment,
    Whitespace,
}

#[derive(Debug, Clone, Copy)]
/// Represents a position in the source file.
/// Both line and column are represented by a 1-based
/// index, since this struct exists only to provide
/// context to the user.
pub struct Position {
    line: usize,
    column: usize,
}

impl Position {
    fn initial() -> Position {
        Position { line: 1, column: 1 }
    }

    fn increment_column(&mut self) -> () {
        self.column += 1;
    }

    fn increment_line(&mut self) -> () {
        self.line += 1;
        self.column = 1;
    }
}

pub type Lexeme = String;

#[derive(Debug)]
pub struct TokenWithContext {
    pub token: Token,
    // Takes a copy. Tokens can outlive the file they came from
    pub lexeme: Lexeme,
    /// Position of the first character of the token
    pub position: Position,
}

#[derive(Debug, Clone)]
pub enum ScannerError {
    MissingStringTerminator(Position),
    UnexpectedCharacter(char, Position),
}

struct Scanner<'a> {
    current_position: Position,
    current_lexeme: String,
    source: MultiPeek<str::Chars<'a>>,
}

fn is_digit(c: char) -> bool {
    c >= '0' && c <= '9'
}

fn is_alpha(c: char) -> bool {
    (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
}

fn is_alphanumeric(c: char) -> bool {
    is_digit(c) || is_alpha(c)
}

fn is_whitespace(c: char) -> bool {
    match c {
        ' ' | '\r' | '\t' | '\n' => true,
        _ => false,
    }
}

impl<'a> Scanner<'a> {
    fn initialize(source: &str) -> Scanner {
        Scanner {
            current_position: Position::initial(),
            current_lexeme: "".into(),
            source: multipeek(source.chars()),
        }
    }

    fn peek_check(&mut self, check: &Fn(char) -> bool) -> bool {
        self.source.reset_peek();
        match self.source.peek() {
            Some(&c) => check(c),
            None => false,
        }
    }

    fn peek_check2(&mut self, check1: &Fn(char) -> bool, check2: &Fn(char) -> bool) -> bool {
        self.source.reset_peek();
        match self.source.peek() {
            Some(&p1) => match self.source.peek() {
                Some(&p2) => check1(p1) && check2(p2),
                None => false,
            },
            None => false,
        }
    }

    fn advance(&mut self) -> Option<char> {
        let next = self.source.next();
        if let Some(c) = next {
            self.current_lexeme.push(c);
            if c == '\n' {
                self.current_position.increment_line();
            } else {
                self.current_position.increment_column();;
            }
        };
        next
    }

    fn advance_if_match(&mut self, expected: char) -> bool {
        if self.peek_check(&|c| c == expected) {
            let _ = self.advance();
            true
        } else {
            false
        }
    }

    fn advance_while(&mut self, condition: &Fn(char) -> bool) -> () {
        while self.peek_check(condition) {
            self.advance();
        }
    }

    fn add_context(&mut self, token: Token, initial_position: Position) -> TokenWithContext {
        TokenWithContext {
            token: token,
            lexeme: self.current_lexeme.clone(),
            position: initial_position,
        }
    }

    fn string(&mut self) -> Result<Token, ScannerError> {
        self.advance_while(&|c| c != '"' && c != '\n');
        if !self.advance_if_match('"') {
            return Err(ScannerError::MissingStringTerminator(self.current_position));
        }
        let literal_length = self.current_lexeme.len() - 2;
        // Trims delimiters
        let literal = self.current_lexeme
            .chars()
            .skip(1)
            .take(literal_length)
            .collect();
        Ok(Token::StringLiteral(literal))
    }

    fn number(&mut self) -> Token {
        self.advance_while(&is_digit);
        if self.peek_check2(&|p1| p1 == '.', &is_digit) {
            self.advance(); // Consume the .
            self.advance_while(&is_digit);
        }
        let value = self.current_lexeme.parse::<f64>().unwrap();
        Token::NumberLiteral(value)
    }

    fn identifier(&mut self) -> Token {
        self.advance_while(&is_alphanumeric);
        match self.current_lexeme.as_ref() {
            "and" => Token::And,
            "class" => Token::Class,
            "else" => Token::Else,
            "false" => Token::False,
            "for" => Token::For,
            "fun" => Token::Fun,
            "if" => Token::If,
            "nil" => Token::Nil,
            "or" => Token::Or,
            "print" => Token::Print,
            "return" => Token::Return,
            "super" => Token::Super,
            "this" => Token::This,
            "true" => Token::True,
            "var" => Token::Var,
            "while" => Token::While,
            identifier => Token::Identifier(identifier.into()),
        }
    }

    fn scan_next(&mut self) -> Option<Result<TokenWithContext, ScannerError>> {
        let initial_position = self.current_position;
        self.current_lexeme.clear();
        // Check if there is something left to iterate on.
        // Early return if we're done.
        let next_char = match self.advance() {
            Some(c) => c,
            None => return None,
        };
        let result = match next_char {
            '(' => Ok(Token::LeftParen),
            ')' => Ok(Token::RightParen),
            '{' => Ok(Token::LeftBrace),
            '}' => Ok(Token::RightBrace),
            ',' => Ok(Token::Comma),
            '.' => Ok(Token::Dot),
            '-' => Ok(Token::Minus),
            '+' => Ok(Token::Plus),
            ';' => Ok(Token::Semicolon),
            '*' => Ok(Token::Star),
            '!' => {
                if self.advance_if_match('=') {
                    Ok(Token::BangEqual)
                } else {
                    Ok(Token::Bang)
                }
            }
            '=' => {
                if self.advance_if_match('=') {
                    Ok(Token::EqualEqual)
                } else {
                    Ok(Token::Equal)
                }
            }
            '<' => {
                if self.advance_if_match('=') {
                    Ok(Token::LessEqual)
                } else {
                    Ok(Token::Less)
                }
            }
            '>' => {
                if self.advance_if_match('=') {
                    Ok(Token::GreaterEqual)
                } else {
                    Ok(Token::Greater)
                }
            }
            '/' => {
                if self.advance_if_match('/') {
                    // Comments go on till the end of the line
                    self.advance_while(&|c| c != '\n');
                    Ok(Token::Comment)
                } else {
                    Ok(Token::Slash)
                }
            }
            '"' => self.string(),
            c if is_whitespace(c) => Ok(Token::Whitespace),
            c if is_digit(c) => Ok(self.number()),
            c if is_alpha(c) => Ok(self.identifier()),
            c => Err(ScannerError::UnexpectedCharacter(c, self.current_position)),
        };
        Some(result.map(|token| self.add_context(token, initial_position)))
    }
}

pub fn scan(source: &str) -> (Vec<TokenWithContext>, Vec<ScannerError>) {
    let mut scanner = Scanner::initialize(source);
    let mut tokens = Vec::new();
    let mut errors = Vec::new();
    while let Some(result) = scanner.scan_next() {
        match result {
            Ok(token_with_context) => {
                match token_with_context.token {
                    // Ignoring tokens we don't care about
                    Token::Comment | Token::Whitespace => {}
                    _ => tokens.push(token_with_context),
                };
            }
            Err(error) => errors.push(error),
        }
    }
    (tokens, errors)
}

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

    #[test]
    fn single_token() {
        let (tokens, _) = scan(&"+");
        assert_eq!(tokens[0].token, Token::Plus);
    }

    #[test]
    fn expression() {
        let (tokens, _) = scan(&"1+2");
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
    }

    #[test]
    fn expression_with_whitespaces() {
        let (tokens, _) = scan(&"1 + 2");
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
    }

    #[test]
    fn assignement_with_comment() {
        let (tokens, _) = scan(&"var a = 1.0; // A comment");
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
    }

    #[test]
    fn multiline_statements() {
        let (tokens, _) = scan(
            &r#"var a = 1.0;
                var b = "Hello";"#,
        );
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
        assert_eq!(tokens[5].token, Token::Var);
        assert_eq!(tokens[6].token, Token::Identifier("b".into()));
        assert_eq!(tokens[7].token, Token::Equal);
        assert_eq!(tokens[8].token, Token::StringLiteral("Hello".into()));
        assert_eq!(tokens[9].token, Token::Semicolon);
        assert_eq!(tokens[1].position.line, 1);
        assert_eq!(tokens[1].position.column, 5);
        assert_eq!(tokens[9].position.line, 2);
        assert_eq!(tokens[9].position.column, 46); // There are 30 spaces before the text!
    }

    #[test]
    fn expression_with_bad_character() {
        let (tokens, errors) = scan(&"1 + $2");
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
        assert_eq!(errors.len(), 1);
    }

    #[test]
    fn statements_with_unterminated_string() {
        let (tokens, errors) = scan(
            &r#"var a = "Unterminated;
                var b = "Hello";"#,
        );
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        // Literal not reported, it wasn't terminated
        // Semicolon got embedded into the string
        assert_eq!(tokens[3].token, Token::Var);
        assert_eq!(tokens[4].token, Token::Identifier("b".into()));
        assert_eq!(tokens[5].token, Token::Equal);
        assert_eq!(tokens[6].token, Token::StringLiteral("Hello".into()));
        assert_eq!(tokens[7].token, Token::Semicolon);
        assert_eq!(errors.len(), 1);
    }

}
<commit_msg>Fixed test<commit_after>use itertools::{multipeek, MultiPeek};
use std::str;

#[derive(Debug, PartialEq)]
pub enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Equal,
    EqualEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(f64),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    // The book doesn't have tokens for comments and
    // whitespaces. Introducing them the scanner can
    // deal with them uniformly and in a more
    // functional way.
    Comment,
    Whitespace,
}

#[derive(Debug, Clone, Copy)]
/// Represents a position in the source file.
/// Both line and column are represented by a 1-based
/// index, since this struct exists only to provide
/// context to the user.
pub struct Position {
    line: usize,
    column: usize,
}

impl Position {
    fn initial() -> Position {
        Position { line: 1, column: 1 }
    }

    fn increment_column(&mut self) -> () {
        self.column += 1;
    }

    fn increment_line(&mut self) -> () {
        self.line += 1;
        self.column = 1;
    }
}

pub type Lexeme = String;

#[derive(Debug)]
pub struct TokenWithContext {
    pub token: Token,
    // Takes a copy. Tokens can outlive the file they came from
    pub lexeme: Lexeme,
    /// Position of the first character of the token
    pub position: Position,
}

#[derive(Debug, Clone)]
pub enum ScannerError {
    MissingStringTerminator(Position),
    UnexpectedCharacter(char, Position),
}

struct Scanner<'a> {
    current_position: Position,
    current_lexeme: String,
    source: MultiPeek<str::Chars<'a>>,
}

fn is_digit(c: char) -> bool {
    c >= '0' && c <= '9'
}

fn is_alpha(c: char) -> bool {
    (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
}

fn is_alphanumeric(c: char) -> bool {
    is_digit(c) || is_alpha(c)
}

fn is_whitespace(c: char) -> bool {
    match c {
        ' ' | '\r' | '\t' | '\n' => true,
        _ => false,
    }
}

impl<'a> Scanner<'a> {
    fn initialize(source: &str) -> Scanner {
        Scanner {
            current_position: Position::initial(),
            current_lexeme: "".into(),
            source: multipeek(source.chars()),
        }
    }

    fn peek_check(&mut self, check: &Fn(char) -> bool) -> bool {
        self.source.reset_peek();
        match self.source.peek() {
            Some(&c) => check(c),
            None => false,
        }
    }

    fn peek_check2(&mut self, check1: &Fn(char) -> bool, check2: &Fn(char) -> bool) -> bool {
        self.source.reset_peek();
        match self.source.peek() {
            Some(&p1) => match self.source.peek() {
                Some(&p2) => check1(p1) && check2(p2),
                None => false,
            },
            None => false,
        }
    }

    fn advance(&mut self) -> Option<char> {
        let next = self.source.next();
        if let Some(c) = next {
            self.current_lexeme.push(c);
            if c == '\n' {
                self.current_position.increment_line();
            } else {
                self.current_position.increment_column();;
            }
        };
        next
    }

    fn advance_if_match(&mut self, expected: char) -> bool {
        if self.peek_check(&|c| c == expected) {
            let _ = self.advance();
            true
        } else {
            false
        }
    }

    fn advance_while(&mut self, condition: &Fn(char) -> bool) -> () {
        while self.peek_check(condition) {
            self.advance();
        }
    }

    fn add_context(&mut self, token: Token, initial_position: Position) -> TokenWithContext {
        TokenWithContext {
            token: token,
            lexeme: self.current_lexeme.clone(),
            position: initial_position,
        }
    }

    fn string(&mut self) -> Result<Token, ScannerError> {
        self.advance_while(&|c| c != '"' && c != '\n');
        if !self.advance_if_match('"') {
            return Err(ScannerError::MissingStringTerminator(self.current_position));
        }
        let literal_length = self.current_lexeme.len() - 2;
        // Trims delimiters
        let literal = self.current_lexeme
            .chars()
            .skip(1)
            .take(literal_length)
            .collect();
        Ok(Token::StringLiteral(literal))
    }

    fn number(&mut self) -> Token {
        self.advance_while(&is_digit);
        if self.peek_check2(&|p1| p1 == '.', &is_digit) {
            self.advance(); // Consume the .
            self.advance_while(&is_digit);
        }
        let value = self.current_lexeme.parse::<f64>().unwrap();
        Token::NumberLiteral(value)
    }

    fn identifier(&mut self) -> Token {
        self.advance_while(&is_alphanumeric);
        match self.current_lexeme.as_ref() {
            "and" => Token::And,
            "class" => Token::Class,
            "else" => Token::Else,
            "false" => Token::False,
            "for" => Token::For,
            "fun" => Token::Fun,
            "if" => Token::If,
            "nil" => Token::Nil,
            "or" => Token::Or,
            "print" => Token::Print,
            "return" => Token::Return,
            "super" => Token::Super,
            "this" => Token::This,
            "true" => Token::True,
            "var" => Token::Var,
            "while" => Token::While,
            identifier => Token::Identifier(identifier.into()),
        }
    }

    fn scan_next(&mut self) -> Option<Result<TokenWithContext, ScannerError>> {
        let initial_position = self.current_position;
        self.current_lexeme.clear();
        // Check if there is something left to iterate on.
        // Early return if we're done.
        let next_char = match self.advance() {
            Some(c) => c,
            None => return None,
        };
        let result = match next_char {
            '(' => Ok(Token::LeftParen),
            ')' => Ok(Token::RightParen),
            '{' => Ok(Token::LeftBrace),
            '}' => Ok(Token::RightBrace),
            ',' => Ok(Token::Comma),
            '.' => Ok(Token::Dot),
            '-' => Ok(Token::Minus),
            '+' => Ok(Token::Plus),
            ';' => Ok(Token::Semicolon),
            '*' => Ok(Token::Star),
            '!' => {
                if self.advance_if_match('=') {
                    Ok(Token::BangEqual)
                } else {
                    Ok(Token::Bang)
                }
            }
            '=' => {
                if self.advance_if_match('=') {
                    Ok(Token::EqualEqual)
                } else {
                    Ok(Token::Equal)
                }
            }
            '<' => {
                if self.advance_if_match('=') {
                    Ok(Token::LessEqual)
                } else {
                    Ok(Token::Less)
                }
            }
            '>' => {
                if self.advance_if_match('=') {
                    Ok(Token::GreaterEqual)
                } else {
                    Ok(Token::Greater)
                }
            }
            '/' => {
                if self.advance_if_match('/') {
                    // Comments go on till the end of the line
                    self.advance_while(&|c| c != '\n');
                    Ok(Token::Comment)
                } else {
                    Ok(Token::Slash)
                }
            }
            '"' => self.string(),
            c if is_whitespace(c) => Ok(Token::Whitespace),
            c if is_digit(c) => Ok(self.number()),
            c if is_alpha(c) => Ok(self.identifier()),
            c => Err(ScannerError::UnexpectedCharacter(c, self.current_position)),
        };
        Some(result.map(|token| self.add_context(token, initial_position)))
    }
}

pub fn scan(source: &str) -> (Vec<TokenWithContext>, Vec<ScannerError>) {
    let mut scanner = Scanner::initialize(source);
    let mut tokens = Vec::new();
    let mut errors = Vec::new();
    while let Some(result) = scanner.scan_next() {
        match result {
            Ok(token_with_context) => {
                match token_with_context.token {
                    // Ignoring tokens we don't care about
                    Token::Comment | Token::Whitespace => {}
                    _ => tokens.push(token_with_context),
                };
            }
            Err(error) => errors.push(error),
        }
    }
    (tokens, errors)
}

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

    #[test]
    fn single_token() {
        let (tokens, _) = scan(&"+");
        assert_eq!(tokens[0].token, Token::Plus);
    }

    #[test]
    fn expression() {
        let (tokens, _) = scan(&"1+2");
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
    }

    #[test]
    fn expression_with_whitespaces() {
        let (tokens, _) = scan(&"1 + 2");
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
    }

    #[test]
    fn assignement_with_comment() {
        let (tokens, _) = scan(&"var a = 1.0; // A comment");
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
    }

    #[test]
    fn multiline_statements() {
        let (tokens, _) = scan(
            &r#"var a = 1.0;
                var b = "Hello";"#,
        );
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
        assert_eq!(tokens[5].token, Token::Var);
        assert_eq!(tokens[6].token, Token::Identifier("b".into()));
        assert_eq!(tokens[7].token, Token::Equal);
        assert_eq!(tokens[8].token, Token::StringLiteral("Hello".into()));
        assert_eq!(tokens[9].token, Token::Semicolon);
        assert_eq!(tokens[1].position.line, 1);
        assert_eq!(tokens[1].position.column, 5);
        assert_eq!(tokens[9].position.line, 2);
        assert_eq!(tokens[9].position.column, 32); // There are 16 spaces before the text!
    }

    #[test]
    fn expression_with_bad_character() {
        let (tokens, errors) = scan(&"1 + $2");
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
        assert_eq!(errors.len(), 1);
    }

    #[test]
    fn statements_with_unterminated_string() {
        let (tokens, errors) = scan(
            &r#"var a = "Unterminated;
                var b = "Hello";"#,
        );
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        // Literal not reported, it wasn't terminated
        // Semicolon got embedded into the string
        assert_eq!(tokens[3].token, Token::Var);
        assert_eq!(tokens[4].token, Token::Identifier("b".into()));
        assert_eq!(tokens[5].token, Token::Equal);
        assert_eq!(tokens[6].token, Token::StringLiteral("Hello".into()));
        assert_eq!(tokens[7].token, Token::Semicolon);
        assert_eq!(errors.len(), 1);
    }

}
<|endoftext|>


<commit_before>//! Identifier of server

use std::{
    fmt::{self, Debug},
    sync::atomic::{AtomicU32, Ordering},
};

use shadowsocks::ServerConfig;
use tokio::sync::Mutex;

use super::server_stat::{Score, ServerStat};

/// Server's statistic score
pub struct ServerScore {
    stat_data: Mutex<ServerStat>,
    score: AtomicU32,
}

impl ServerScore {
    /// Create a `ServerScore`
    pub fn new(user_weight: f32) -> ServerScore {
        ServerScore {
            stat_data: Mutex::new(ServerStat::new(user_weight)),
            score: AtomicU32::new(0),
        }
    }

    /// Get server's current statistic scores
    pub fn score(&self) -> u32 {
        self.score.load(Ordering::Acquire)
    }

    /// Append a `Score` into statistic and recalculate score of the server
    pub async fn push_score(&self, score: Score) -> u32 {
        let updated_score = {
            let mut stat = self.stat_data.lock().await;
            stat.push_score(score)
        };
        self.score.store(updated_score, Ordering::Release);
        updated_score
    }

    /// Report request failure of this server, which will eventually records an `Errored` score
    pub async fn report_failure(&self) -> u32 {
        self.push_score(Score::Errored).await
    }
}

impl Debug for ServerScore {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("ServerScore").field("score", &self.score()).finish()
    }
}

/// Identifer for a server
#[derive(Debug)]
pub struct ServerIdent {
    tcp_score: ServerScore,
    udp_score: ServerScore,
    svr_cfg: ServerConfig,
}

impl ServerIdent {
    /// Create a  ServerIdent`
    pub fn new(svr_cfg: ServerConfig) -> ServerIdent {
        ServerIdent {
            tcp_score: ServerScore::new(svr_cfg.weight().tcp_weight()),
            udp_score: ServerScore::new(svr_cfg.weight().udp_weight()),
            svr_cfg,
        }
    }

    pub fn server_config(&self) -> &ServerConfig {
        &self.svr_cfg
    }

    pub fn tcp_score(&self) -> &ServerScore {
        &self.tcp_score
    }

    pub fn udp_score(&self) -> &ServerScore {
        &self.udp_score
    }
}
<commit_msg>bug fixed, score should be initialized to u32::MAX<commit_after>//! Identifier of server

use std::{
    fmt::{self, Debug},
    sync::atomic::{AtomicU32, Ordering},
};

use shadowsocks::ServerConfig;
use tokio::sync::Mutex;

use super::server_stat::{Score, ServerStat};

/// Server's statistic score
pub struct ServerScore {
    stat_data: Mutex<ServerStat>,
    score: AtomicU32,
}

impl ServerScore {
    /// Create a `ServerScore`
    pub fn new(user_weight: f32) -> ServerScore {
        ServerScore {
            stat_data: Mutex::new(ServerStat::new(user_weight)),
            score: AtomicU32::new(u32::MAX),
        }
    }

    /// Get server's current statistic scores
    pub fn score(&self) -> u32 {
        self.score.load(Ordering::Acquire)
    }

    /// Append a `Score` into statistic and recalculate score of the server
    pub async fn push_score(&self, score: Score) -> u32 {
        let updated_score = {
            let mut stat = self.stat_data.lock().await;
            stat.push_score(score)
        };
        self.score.store(updated_score, Ordering::Release);
        updated_score
    }

    /// Report request failure of this server, which will eventually records an `Errored` score
    pub async fn report_failure(&self) -> u32 {
        self.push_score(Score::Errored).await
    }
}

impl Debug for ServerScore {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("ServerScore").field("score", &self.score()).finish()
    }
}

/// Identifer for a server
#[derive(Debug)]
pub struct ServerIdent {
    tcp_score: ServerScore,
    udp_score: ServerScore,
    svr_cfg: ServerConfig,
}

impl ServerIdent {
    /// Create a  ServerIdent`
    pub fn new(svr_cfg: ServerConfig) -> ServerIdent {
        ServerIdent {
            tcp_score: ServerScore::new(svr_cfg.weight().tcp_weight()),
            udp_score: ServerScore::new(svr_cfg.weight().udp_weight()),
            svr_cfg,
        }
    }

    pub fn server_config(&self) -> &ServerConfig {
        &self.svr_cfg
    }

    pub fn tcp_score(&self) -> &ServerScore {
        &self.tcp_score
    }

    pub fn udp_score(&self) -> &ServerScore {
        &self.udp_score
    }
}
<|endoftext|>


<commit_before>use std::{Box, String};
use std::collections::VecDeque;
use std::ops::DerefMut;

use orbital::{Color, Point, Size, Event, KeyEvent, MouseEvent, QuitEvent};

use super::display::Display;
use super::scheduler;

/// A window
pub struct Window {
    /// The position of the window
    pub point: Point,
    /// The size of the window
    pub size: Size,
    /// The title of the window
    pub title: String,
    /// The content of the window
    pub content: Box<Display>,
    /// The color of the window title
    pub title_color: Color,
    /// The color of the border
    pub border_color: Color,
    /// Is the window focused?
    pub focused: bool,
    /// Is the window minimized?
    pub minimized: bool,
    dragging: bool,
    last_mouse_event: MouseEvent,
    events: VecDeque<Event>,
    ptr: *mut Window,
}

impl Window {
    /// Create a new window
    pub fn new(point: Point, size: Size, title: String) -> Box<Self> {
        let mut ret = box Window {
            point: point,
            size: size,
            title: title,
            content: Display::new(size.width, size.height),
            title_color: Color::rgb(255, 255, 255),
            border_color: Color::rgba(64, 64, 64, 128),
            focused: false,
            minimized: false,
            dragging: false,
            last_mouse_event: MouseEvent {
                x: 0,
                y: 0,
                left_button: false,
                right_button: false,
                middle_button: false,
            },
            events: VecDeque::new(),
            ptr: 0 as *mut Window,
        };

        unsafe {
            ret.ptr = ret.deref_mut();

            if ret.ptr as usize > 0 {
                (*super::session_ptr).add_window(ret.ptr);
            }
        }

        ret
    }

    /// Poll the window (new)
    pub fn poll(&mut self) -> Option<Event> {
        let event_option;
        unsafe {
            let reenable = scheduler::start_no_ints();
            event_option = self.events.pop_front();
            scheduler::end_no_ints(reenable);
        }
        return event_option;
    }

    /// Redraw the window
    pub fn redraw(&mut self) {
        unsafe {
            let reenable = scheduler::start_no_ints();
            self.content.flip();
            (*super::session_ptr).redraw = true;
            (*super::session_ptr).redraw();
            scheduler::end_no_ints(reenable);
        }
    }

    /// Draw the window using a `Display`
    pub fn draw(&mut self, display: &Display, font: usize) {
        if self.focused {
            self.border_color = Color::rgba(128, 128, 128, 192);
        } else {
            self.border_color = Color::rgba(64, 64, 64, 128);
        }

        if self.minimized {
            self.title_color = Color::rgb(0, 0, 0);
        } else {
            self.title_color = Color::rgb(255, 255, 255);

            display.rect(Point::new(self.point.x - 2, self.point.y - 18),
                         Size::new(self.size.width + 4, 18),
                         self.border_color);

            let mut cursor = Point::new(self.point.x, self.point.y - 17);
            for c in self.title.chars() {
                if cursor.x + 8 <= self.point.x + self.size.width as isize {
                    display.char(cursor, c, self.title_color, font);
                }
                cursor.x += 8;
            }

            display.rect(Point::new(self.point.x - 2, self.point.y),
                         Size::new(2, self.size.height),
                         self.border_color);
            display.rect(Point::new(self.point.x - 2, self.point.y + self.size.height as isize),
                         Size::new(self.size.width + 4, 2),
                         self.border_color);
            display.rect(Point::new(self.point.x + self.size.width as isize, self.point.y),
                         Size::new(2, self.size.height),
                         self.border_color);

            unsafe {
                let reenable = scheduler::start_no_ints();
                display.image(self.point,
                              self.content.onscreen as *const Color,
                              Size::new(self.content.width, self.content.height));
                scheduler::end_no_ints(reenable);
            }
        }
    }

    /// Called on key press
    pub fn on_key(&mut self, key_event: KeyEvent) {
        unsafe {
            let reenable = scheduler::start_no_ints();
            self.events.push_back(key_event.to_event());
            scheduler::end_no_ints(reenable);
        }
    }

    fn on_window_decoration(&self, x: isize, y: isize) -> bool {
        !self.minimized && x >= -2 && x < self.size.width as isize + 4 && y >= -18 && y < 0
    }

    fn on_window_body(&self, x: isize, y: isize) -> bool {
        !self.minimized && x >= 0 && x < self.size.width as isize && y >= 0 &&
        y < self.size.height as isize
    }

    fn mouse_button_pressed(mouse_event: &MouseEvent) -> bool {
        mouse_event.left_button || mouse_event.middle_button || mouse_event.right_button
    }

    /// Called on mouse movement
    pub fn on_mouse(&mut self, orig_mouse_event: MouseEvent, allow_catch: bool, active_window: bool) -> bool {
        let mut mouse_event = orig_mouse_event;

        mouse_event.x -= self.point.x;
        mouse_event.y -= self.point.y;

        let mut caught = false;

        if allow_catch && (active_window || Window::mouse_button_pressed(&mouse_event)) {
            if self.on_window_body(mouse_event.x, mouse_event.y) {
                caught = true;
            } else if self.on_window_decoration(mouse_event.x, mouse_event.y) {
                caught = true;

                if mouse_event.left_button {
                    if !self.last_mouse_event.left_button {
                        self.dragging = true;
                    }
                } else {
                    self.dragging = false;
                }

                if mouse_event.right_button {
                    if !self.last_mouse_event.right_button {
                        self.minimized = !self.minimized;
                    }
                }

                if mouse_event.middle_button {
                    unsafe {
                        let reenable = scheduler::start_no_ints();
                        self.events.push_back(QuitEvent.to_event());
                        scheduler::end_no_ints(reenable);
                    }
                }
            }

            if self.dragging {
                self.point.x += orig_mouse_event.x - self.last_mouse_event.x;
                self.point.y += orig_mouse_event.y - self.last_mouse_event.y;
                caught = true;
            }
        } else {
            self.dragging = false;
        }

        self.last_mouse_event = orig_mouse_event;

        if caught && !self.dragging {
            unsafe {
                let reenable = scheduler::start_no_ints();
                self.events.push_back(mouse_event.to_event());
                scheduler::end_no_ints(reenable);
            }
        }

        caught
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        unsafe {
            if self.ptr as usize > 0 {
                (*super::session_ptr).remove_window(self.ptr);
            }
        }
    }
}
<commit_msg>Fix for case when mouse button held down<commit_after>use std::{Box, String};
use std::collections::VecDeque;
use std::ops::DerefMut;

use orbital::{Color, Point, Size, Event, KeyEvent, MouseEvent, QuitEvent};

use super::display::Display;
use super::scheduler;

/// A window
pub struct Window {
    /// The position of the window
    pub point: Point,
    /// The size of the window
    pub size: Size,
    /// The title of the window
    pub title: String,
    /// The content of the window
    pub content: Box<Display>,
    /// The color of the window title
    pub title_color: Color,
    /// The color of the border
    pub border_color: Color,
    /// Is the window focused?
    pub focused: bool,
    /// Is the window minimized?
    pub minimized: bool,
    dragging: bool,
    last_mouse_event: MouseEvent,
    events: VecDeque<Event>,
    ptr: *mut Window,
}

impl Window {
    /// Create a new window
    pub fn new(point: Point, size: Size, title: String) -> Box<Self> {
        let mut ret = box Window {
            point: point,
            size: size,
            title: title,
            content: Display::new(size.width, size.height),
            title_color: Color::rgb(255, 255, 255),
            border_color: Color::rgba(64, 64, 64, 128),
            focused: false,
            minimized: false,
            dragging: false,
            last_mouse_event: MouseEvent {
                x: 0,
                y: 0,
                left_button: false,
                right_button: false,
                middle_button: false,
            },
            events: VecDeque::new(),
            ptr: 0 as *mut Window,
        };

        unsafe {
            ret.ptr = ret.deref_mut();

            if ret.ptr as usize > 0 {
                (*super::session_ptr).add_window(ret.ptr);
            }
        }

        ret
    }

    /// Poll the window (new)
    pub fn poll(&mut self) -> Option<Event> {
        let event_option;
        unsafe {
            let reenable = scheduler::start_no_ints();
            event_option = self.events.pop_front();
            scheduler::end_no_ints(reenable);
        }
        return event_option;
    }

    /// Redraw the window
    pub fn redraw(&mut self) {
        unsafe {
            let reenable = scheduler::start_no_ints();
            self.content.flip();
            (*super::session_ptr).redraw = true;
            (*super::session_ptr).redraw();
            scheduler::end_no_ints(reenable);
        }
    }

    /// Draw the window using a `Display`
    pub fn draw(&mut self, display: &Display, font: usize) {
        if self.focused {
            self.border_color = Color::rgba(128, 128, 128, 192);
        } else {
            self.border_color = Color::rgba(64, 64, 64, 128);
        }

        if self.minimized {
            self.title_color = Color::rgb(0, 0, 0);
        } else {
            self.title_color = Color::rgb(255, 255, 255);

            display.rect(Point::new(self.point.x - 2, self.point.y - 18),
                         Size::new(self.size.width + 4, 18),
                         self.border_color);

            let mut cursor = Point::new(self.point.x, self.point.y - 17);
            for c in self.title.chars() {
                if cursor.x + 8 <= self.point.x + self.size.width as isize {
                    display.char(cursor, c, self.title_color, font);
                }
                cursor.x += 8;
            }

            display.rect(Point::new(self.point.x - 2, self.point.y),
                         Size::new(2, self.size.height),
                         self.border_color);
            display.rect(Point::new(self.point.x - 2, self.point.y + self.size.height as isize),
                         Size::new(self.size.width + 4, 2),
                         self.border_color);
            display.rect(Point::new(self.point.x + self.size.width as isize, self.point.y),
                         Size::new(2, self.size.height),
                         self.border_color);

            unsafe {
                let reenable = scheduler::start_no_ints();
                display.image(self.point,
                              self.content.onscreen as *const Color,
                              Size::new(self.content.width, self.content.height));
                scheduler::end_no_ints(reenable);
            }
        }
    }

    /// Called on key press
    pub fn on_key(&mut self, key_event: KeyEvent) {
        unsafe {
            let reenable = scheduler::start_no_ints();
            self.events.push_back(key_event.to_event());
            scheduler::end_no_ints(reenable);
        }
    }

    fn on_window_decoration(&self, x: isize, y: isize) -> bool {
        !self.minimized && x >= -2 && x < self.size.width as isize + 4 && y >= -18 && y < 0
    }

    fn on_window_body(&self, x: isize, y: isize) -> bool {
        !self.minimized && x >= 0 && x < self.size.width as isize && y >= 0 &&
        y < self.size.height as isize
    }

    fn mouse_button_pressed(mouse_event: &MouseEvent) -> bool {
        mouse_event.left_button || mouse_event.middle_button || mouse_event.right_button
    }

    /// Called on mouse movement
    pub fn on_mouse(&mut self, orig_mouse_event: MouseEvent, allow_catch: bool, active_window: bool) -> bool {
        let mut mouse_event = orig_mouse_event;

        mouse_event.x -= self.point.x;
        mouse_event.y -= self.point.y;

        let mut caught = false;

        if allow_catch && (active_window || (Window::mouse_button_pressed(&mouse_event) && !Window::mouse_button_pressed(&self.last_mouse_event))) {
            if self.on_window_body(mouse_event.x, mouse_event.y) {
                caught = true;
            } else if self.on_window_decoration(mouse_event.x, mouse_event.y) {
                caught = true;

                if mouse_event.left_button {
                    if !self.last_mouse_event.left_button {
                        self.dragging = true;
                    }
                } else {
                    self.dragging = false;
                }

                if mouse_event.right_button {
                    if !self.last_mouse_event.right_button {
                        self.minimized = !self.minimized;
                    }
                }

                if mouse_event.middle_button {
                    unsafe {
                        let reenable = scheduler::start_no_ints();
                        self.events.push_back(QuitEvent.to_event());
                        scheduler::end_no_ints(reenable);
                    }
                }
            }

            if self.dragging {
                self.point.x += orig_mouse_event.x - self.last_mouse_event.x;
                self.point.y += orig_mouse_event.y - self.last_mouse_event.y;
                caught = true;
            }
        } else {
            self.dragging = false;
        }

        self.last_mouse_event = orig_mouse_event;

        if caught && !self.dragging {
            unsafe {
                let reenable = scheduler::start_no_ints();
                self.events.push_back(mouse_event.to_event());
                scheduler::end_no_ints(reenable);
            }
        }

        caught
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        unsafe {
            if self.ptr as usize > 0 {
                (*super::session_ptr).remove_window(self.ptr);
            }
        }
    }
}
<|endoftext|>