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

use super::row::{Row, RowError, RowBuilder, RowReader};
use super::schema::{Schema, Type};
use super::value::Value;
use super::parser::Expression;
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
pub enum StreamError {
    ValidationError(String),
    FieldNotFound(String),
    MissingRowId,
    UnknownError,
}

impl From<RowError> for StreamError {
    fn from(err: RowError) -> StreamError {
        match err {
            RowError::FieldNotFound(field) => StreamError::FieldNotFound(field),
            _ => StreamError::MissingRowId
        }
    }

}

#[derive(Debug)]
pub struct Stream {
    inserts: u64, // total number of inserts this Stream has seen
    lowest_id: Option<u64>,  // lowest id we still have in the Stream
    ttl: Option<u64>,
    rows: HashMap<u64, Row>,
    pub schema: Schema,

}

// Stream should deref schema since it's going to be used a lot
impl Deref for Stream {
    type Target = Schema;
    fn deref(&self) -> &Schema {
        &self.schema
    }
}
impl DerefMut for Stream {
    fn deref_mut(&mut self) -> &mut Schema {
        &mut self.schema
    }
}

/**
This is a weird DB.  There's no user defined primary key,
since everything is based off append only streaming
*/
impl Stream {
    pub fn new() -> Stream {
        let mut stream = Stream::new_empty();
        stream.schema.add_type("_id", Type::Int);
        stream.schema.add_type("_created", Type::Timestamp);
        stream
    }

    // used in temporary tables
    pub fn new_empty() -> Stream {
        let mut stream = Stream {
            inserts: 0,
            lowest_id: None,
            rows: HashMap::new(),
            schema: Schema::new(),
            ttl: None,
        };
        stream
    }

    /* we take a HashMap of String -> Field here
    * we're going to convert it to HashMap<u8, Field> for the Row struct
    */
    pub fn insert(&mut self, mut row_builder: RowBuilder) -> Result<u64, StreamError> {
        // validate the inserted data
        let row_id = self.inserts;
        row_builder.set_int("_id", row_id as i64);
        let row = try!(row_builder.to_row(&self.schema));
        self.rows.insert(self.inserts, row);
        self.inserts += 1;
        Ok(row_id)
    }

    pub fn get(&self, position: u64) -> Option<RowReader> {
        if let Some(tmp) = self.rows.get(&position) {
            return Some(RowReader::new(&self.schema, tmp.clone()));
        }
        None

    }
    pub fn select(&self, predicates: Option<Box<Expression>>) -> Result<(), StreamError> {
        Err(StreamError::UnknownError)
    }

}

impl<'a> IntoIterator for &'a Stream {
    type Item = RowReader<'a>;
    type IntoIter = StreamIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        // TODO fix the position
        StreamIterator{position:0,
                       stream: self}
    }
}

pub struct StreamIterator<'a> {
    position: u64,
    stream: &'a Stream,
}

impl<'a> StreamIterator<'a> {
    fn offset(&'a mut self, num: u64) -> &'a mut StreamIterator {
        self.position = num;
        self
    }
}

impl<'a> Iterator for StreamIterator<'a> {
    type Item = RowReader<'a>;
    fn next(&mut self) -> Option<RowReader<'a>> {
        let tmp = self.stream.get(self.position);
        self.position = self.position + 1;
        tmp
    }
}

#[cfg(test)]
mod tests {
    #![feature(test)]
    extern crate test;
    use super::{Stream};
    use db::row::RowBuilder;

    use db::schema::{Schema, Type};
    use db::value::{Value, TypedValue};
    use std::collections::HashMap;
    use self::test::Bencher;

    fn get_stream() -> Stream {
        let mut s = Stream::new();
        s.schema.add_type("name", Type::String);
        s.schema.add_type("age", Type::Int);
        s.schema.add_type("created", Type::Timestamp);
        s
    }

    fn get_stream_with_data() -> Stream {
        let mut s = get_stream();

        let names = vec!["Jon", "Dani", "Pete", "Sammy", "Steph",
                         "Blake", "Mr. Robot", "Ted", "Rachel", "Gloria"];
        let ages = vec![35, 29, 45, 56, 100,
                        35, 78, 32, 32, 67];

        for x in 0..10 {
            let mut row = RowBuilder::new();
            row.set_string("name", names[x]);
            row.set_int("age", ages[x]);
            let result = s.insert(row).unwrap();
        }
        s
    }

    #[test]
    fn test_insert_works_normal_case() {
        let mut s = Stream::new();
        let name_id = s.schema.add_type("name", Type::String);

        let mut row = RowBuilder::new();
        row.set_string("name", "test");
        let result = s.insert(row).unwrap();
        assert_eq!(result, 0);
        assert_eq!(s.inserts, 1);
        let row2 = s.get(result).unwrap();
        let name = row2.get("name").unwrap();
        // was the data inserted?
        assert_eq!(row2.get("name").unwrap(),
                   TypedValue::from("test"));

    }

    #[test]
    fn test_equality() {
        assert_eq!(TypedValue::from("jon"), TypedValue::from("jon"));
    }

    #[test]
    fn test_builder_insertion() {
        let mut s = get_stream();
        let mut row = RowBuilder::new();

        row.set_string("name", "value")
           .set_int("age", 10);
        s.insert(row);

        let mut c = 0;
        for r in s.into_iter() {
            c += 1;
        }
        assert_eq!(c, 1);
    }

    #[test]
    fn test_iterator_offset() {
        let mut s = get_stream_with_data();
        let mut i = 0;
        for row in s.into_iter().offset(9) {
            i = i + 1;
        }
        assert_eq!(i, 1);
    }

    #[bench]
    fn bench_add_two(b: &mut Bencher) {
        let mut stream = get_stream();
        // benched original row builder at 318 ns/iter (+/- 52)
        b.iter(|| {
            let mut row = RowBuilder::new();
            row.set_string("name", "Dani");
            row.set_int("num_tacos", 4);
            stream.insert(row);
        });
    }

    #[test]
    fn test_table_scan() {
        let mut stream = get_stream_with_data();

    }

}<commit_msg>fixed benchmark name<commit_after>use std::collections::HashMap;
use std::error;

use super::row::{Row, RowError, RowBuilder, RowReader};
use super::schema::{Schema, Type};
use super::value::Value;
use super::parser::Expression;
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
pub enum StreamError {
    ValidationError(String),
    FieldNotFound(String),
    MissingRowId,
    UnknownError,
}

impl From<RowError> for StreamError {
    fn from(err: RowError) -> StreamError {
        match err {
            RowError::FieldNotFound(field) => StreamError::FieldNotFound(field),
            _ => StreamError::MissingRowId
        }
    }

}

#[derive(Debug)]
pub struct Stream {
    inserts: u64, // total number of inserts this Stream has seen
    lowest_id: Option<u64>,  // lowest id we still have in the Stream
    ttl: Option<u64>,
    rows: HashMap<u64, Row>,
    pub schema: Schema,

}

// Stream should deref schema since it's going to be used a lot
impl Deref for Stream {
    type Target = Schema;
    fn deref(&self) -> &Schema {
        &self.schema
    }
}
impl DerefMut for Stream {
    fn deref_mut(&mut self) -> &mut Schema {
        &mut self.schema
    }
}

/**
This is a weird DB.  There's no user defined primary key,
since everything is based off append only streaming
*/
impl Stream {
    pub fn new() -> Stream {
        let mut stream = Stream::new_empty();
        stream.schema.add_type("_id", Type::Int);
        stream.schema.add_type("_created", Type::Timestamp);
        stream
    }

    // used in temporary tables
    pub fn new_empty() -> Stream {
        let mut stream = Stream {
            inserts: 0,
            lowest_id: None,
            rows: HashMap::new(),
            schema: Schema::new(),
            ttl: None,
        };
        stream
    }

    /* we take a HashMap of String -> Field here
    * we're going to convert it to HashMap<u8, Field> for the Row struct
    */
    pub fn insert(&mut self, mut row_builder: RowBuilder) -> Result<u64, StreamError> {
        // validate the inserted data
        let row_id = self.inserts;
        row_builder.set_int("_id", row_id as i64);
        let row = try!(row_builder.to_row(&self.schema));
        self.rows.insert(self.inserts, row);
        self.inserts += 1;
        Ok(row_id)
    }

    pub fn get(&self, position: u64) -> Option<RowReader> {
        if let Some(tmp) = self.rows.get(&position) {
            return Some(RowReader::new(&self.schema, tmp.clone()));
        }
        None

    }
    pub fn select(&self, predicates: Option<Box<Expression>>) -> Result<(), StreamError> {
        Err(StreamError::UnknownError)
    }

}

impl<'a> IntoIterator for &'a Stream {
    type Item = RowReader<'a>;
    type IntoIter = StreamIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        // TODO fix the position
        StreamIterator{position:0,
                       stream: self}
    }
}

pub struct StreamIterator<'a> {
    position: u64,
    stream: &'a Stream,
}

impl<'a> StreamIterator<'a> {
    fn offset(&'a mut self, num: u64) -> &'a mut StreamIterator {
        self.position = num;
        self
    }
}

impl<'a> Iterator for StreamIterator<'a> {
    type Item = RowReader<'a>;
    fn next(&mut self) -> Option<RowReader<'a>> {
        let tmp = self.stream.get(self.position);
        self.position = self.position + 1;
        tmp
    }
}

#[cfg(test)]
mod tests {
    #![feature(test)]
    extern crate test;
    use super::{Stream};
    use db::row::RowBuilder;

    use db::schema::{Schema, Type};
    use db::value::{Value, TypedValue};
    use std::collections::HashMap;
    use self::test::Bencher;

    fn get_stream() -> Stream {
        let mut s = Stream::new();
        s.schema.add_type("name", Type::String);
        s.schema.add_type("age", Type::Int);
        s.schema.add_type("created", Type::Timestamp);
        s
    }

    fn get_stream_with_data() -> Stream {
        let mut s = get_stream();

        let names = vec!["Jon", "Dani", "Pete", "Sammy", "Steph",
                         "Blake", "Mr. Robot", "Ted", "Rachel", "Gloria"];
        let ages = vec![35, 29, 45, 56, 100,
                        35, 78, 32, 32, 67];

        for x in 0..10 {
            let mut row = RowBuilder::new();
            row.set_string("name", names[x]);
            row.set_int("age", ages[x]);
            let result = s.insert(row).unwrap();
        }
        s
    }

    #[test]
    fn test_insert_works_normal_case() {
        let mut s = Stream::new();
        let name_id = s.schema.add_type("name", Type::String);

        let mut row = RowBuilder::new();
        row.set_string("name", "test");
        let result = s.insert(row).unwrap();
        assert_eq!(result, 0);
        assert_eq!(s.inserts, 1);
        let row2 = s.get(result).unwrap();
        let name = row2.get("name").unwrap();
        // was the data inserted?
        assert_eq!(row2.get("name").unwrap(),
                   TypedValue::from("test"));

    }

    #[test]
    fn test_equality() {
        assert_eq!(TypedValue::from("jon"), TypedValue::from("jon"));
    }

    #[test]
    fn test_builder_insertion() {
        let mut s = get_stream();
        let mut row = RowBuilder::new();

        row.set_string("name", "value")
           .set_int("age", 10);
        s.insert(row);

        let mut c = 0;
        for r in s.into_iter() {
            c += 1;
        }
        assert_eq!(c, 1);
    }

    #[test]
    fn test_iterator_offset() {
        let mut s = get_stream_with_data();
        let mut i = 0;
        for row in s.into_iter().offset(9) {
            i = i + 1;
        }
        assert_eq!(i, 1);
    }

    #[bench]
    fn bench_row_insertion(b: &mut Bencher) {
        let mut stream = get_stream();
        // benched original row builder at 318 ns/iter (+/- 52)
        b.iter(|| {
            let mut row = RowBuilder::new();
            row.set_string("name", "Dani");
            row.set_int("num_tacos", 4);
            stream.insert(row);
        });
    }

    #[test]
    fn test_table_scan() {
        let mut stream = get_stream_with_data();

    }

}<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate futures;
#[macro_use]
extern crate tokio_core;

use std::io;
use std::net::SocketAddr;

use futures::{Future, Poll, Sink, Stream};
use tokio_core::net::UdpSocket;
use tokio_core::reactor::Core;
use tokio_core::channel::Sender;

use test::Bencher;
use std::thread;

use futures::sync::oneshot;

/// UDP echo server
struct EchoServer {
    socket: UdpSocket,
    buf: Vec<u8>,
    to_send: Option<(usize, SocketAddr)>,
}

impl EchoServer {
    fn new(s: UdpSocket) -> Self {
        EchoServer {
            socket: s,
            to_send: None,
            buf: vec![0u8; 1600],
        }
    }
}

impl Future for EchoServer {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        loop {
            if let Some(&(size, peer)) = self.to_send.as_ref() {
                try_nb!(self.socket.send_to(&self.buf[..size], &peer));
                self.to_send = None;
            }
            self.to_send = Some(try_nb!(self.socket.recv_from(&mut self.buf)));
        }
    }
}

#[bench]
fn udp_echo_latency(b: &mut Bencher) {
    let any_addr = "127.0.0.1:0".to_string();
    let any_addr = any_addr.parse::<SocketAddr>().unwrap();

    let (stop_c, stop_p) = oneshot::channel::<()>();
    let (tx, rx) = oneshot::channel();

    let child = thread::spawn(move || {
        let mut l = Core::new().unwrap();
        let handle = l.handle();

        let socket = tokio_core::net::UdpSocket::bind(&any_addr, &handle).unwrap();
        tx.complete(socket.local_addr().unwrap());

        let server = EchoServer::new(socket);
        let server = server.select(stop_p.map_err(|_| panic!()));
        let server = server.map_err(|_| ());
        l.run(server).unwrap()
    });

    let client = std::net::UdpSocket::bind(&any_addr).unwrap();

    let server_addr = rx.wait().unwrap();
    let mut buf = [0u8; 1000];

    // warmup phase; for some reason initial couple of
    // runs are much slower
    //
    // TODO: Describe the exact reasons; caching? branch predictor? lazy closures?
    for _ in 0..8 {
        client.send_to(&buf, &server_addr).unwrap();
        let _ = client.recv_from(&mut buf).unwrap();
    }

    b.iter(|| {
        client.send_to(&buf, &server_addr).unwrap();
        let _ = client.recv_from(&mut buf).unwrap();
    });

    stop_c.complete(());
    child.join().unwrap();
}

#[bench]
fn channel_latency(b: &mut Bencher) {
    let (tx, rx) = oneshot::channel();

    let child = thread::spawn(move || {
        let mut l = Core::new().unwrap();
        let handle = l.handle();

        let (in_tx, in_rx) = tokio_core::channel::channel(&handle).unwrap();
        let (out_tx, out_rx) = tokio_core::channel::channel(&handle).unwrap();
        tx.complete((in_tx, out_rx));

        let server = out_tx.send_all(in_rx);

        l.run(server).unwrap();
    });

    let (in_tx, out_rx) = rx.wait().unwrap();
    let mut rx_iter = out_rx.wait();

    // warmup phase; for some reason initial couple of runs are much slower
    //
    // TODO: Describe the exact reasons; caching? branch predictor? lazy closures?
    for _ in 0..8 {
        Sender::send(&in_tx, 1usize).unwrap();
        let _ = rx_iter.next();
    }

    b.iter(|| {
        Sender::send(&in_tx, 1usize).unwrap();
        let _ = rx_iter.next();
    });

    drop(in_tx);
    child.join().unwrap();
}
<commit_msg>Add a benchmark for futures channel latency<commit_after>#![feature(test)]

extern crate test;
extern crate futures;
#[macro_use]
extern crate tokio_core;

use std::io;
use std::net::SocketAddr;
use std::thread;

use futures::sync::oneshot;
use futures::sync::spsc;
use futures::{Future, Poll, Sink, Stream};
use test::Bencher;
use tokio_core::channel::Sender;
use tokio_core::net::UdpSocket;
use tokio_core::reactor::Core;

/// UDP echo server
struct EchoServer {
    socket: UdpSocket,
    buf: Vec<u8>,
    to_send: Option<(usize, SocketAddr)>,
}

impl EchoServer {
    fn new(s: UdpSocket) -> Self {
        EchoServer {
            socket: s,
            to_send: None,
            buf: vec![0u8; 1600],
        }
    }
}

impl Future for EchoServer {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        loop {
            if let Some(&(size, peer)) = self.to_send.as_ref() {
                try_nb!(self.socket.send_to(&self.buf[..size], &peer));
                self.to_send = None;
            }
            self.to_send = Some(try_nb!(self.socket.recv_from(&mut self.buf)));
        }
    }
}

#[bench]
fn udp_echo_latency(b: &mut Bencher) {
    let any_addr = "127.0.0.1:0".to_string();
    let any_addr = any_addr.parse::<SocketAddr>().unwrap();

    let (stop_c, stop_p) = oneshot::channel::<()>();
    let (tx, rx) = oneshot::channel();

    let child = thread::spawn(move || {
        let mut l = Core::new().unwrap();
        let handle = l.handle();

        let socket = tokio_core::net::UdpSocket::bind(&any_addr, &handle).unwrap();
        tx.complete(socket.local_addr().unwrap());

        let server = EchoServer::new(socket);
        let server = server.select(stop_p.map_err(|_| panic!()));
        let server = server.map_err(|_| ());
        l.run(server).unwrap()
    });

    let client = std::net::UdpSocket::bind(&any_addr).unwrap();

    let server_addr = rx.wait().unwrap();
    let mut buf = [0u8; 1000];

    // warmup phase; for some reason initial couple of
    // runs are much slower
    //
    // TODO: Describe the exact reasons; caching? branch predictor? lazy closures?
    for _ in 0..8 {
        client.send_to(&buf, &server_addr).unwrap();
        let _ = client.recv_from(&mut buf).unwrap();
    }

    b.iter(|| {
        client.send_to(&buf, &server_addr).unwrap();
        let _ = client.recv_from(&mut buf).unwrap();
    });

    stop_c.complete(());
    child.join().unwrap();
}

#[bench]
fn tokio_channel_latency(b: &mut Bencher) {
    let (tx, rx) = oneshot::channel();

    let child = thread::spawn(move || {
        let mut l = Core::new().unwrap();
        let handle = l.handle();

        let (in_tx, in_rx) = tokio_core::channel::channel(&handle).unwrap();
        let (out_tx, out_rx) = tokio_core::channel::channel(&handle).unwrap();
        tx.complete((in_tx, out_rx));

        let server = out_tx.send_all(in_rx);

        l.run(server).unwrap();
    });

    let (in_tx, out_rx) = rx.wait().unwrap();
    let mut rx_iter = out_rx.wait();

    // warmup phase; for some reason initial couple of runs are much slower
    //
    // TODO: Describe the exact reasons; caching? branch predictor? lazy closures?
    for _ in 0..8 {
        Sender::send(&in_tx, 1usize).unwrap();
        let _ = rx_iter.next();
    }

    b.iter(|| {
        Sender::send(&in_tx, 1usize).unwrap();
        let _ = rx_iter.next();
    });

    drop(in_tx);
    child.join().unwrap();
}

#[bench]
fn futures_channel_latency(b: &mut Bencher) {
    let (mut in_tx, in_rx) = spsc::channel();
    let (out_tx, out_rx) = spsc::channel::<_, ()>();

    let child = thread::spawn(|| out_tx.send_all(in_rx).wait());
    let mut rx_iter = out_rx.wait();

    // warmup phase; for some reason initial couple of runs are much slower
    //
    // TODO: Describe the exact reasons; caching? branch predictor? lazy closures?
    for _ in 0..8 {
        in_tx.start_send(Ok(Ok(1usize))).unwrap();
        let _ = rx_iter.next();
    }

    b.iter(|| {
        in_tx.start_send(Ok(Ok(1usize))).unwrap();
        let _ = rx_iter.next();
    });

    drop(in_tx);
    child.join().unwrap().unwrap();
}
<|endoftext|>


<commit_before>// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print v
// lldbg-check:[...]$0 = size=2 { [0] = size=2 { [0] = 1 [1] = 2 } [1] = size=1 { [0] = 3 } }
// lldb-command:print empty_v
// lldbg-check:[...]$1 = size=0

// === GDB TESTS ===================================================================================

// gdb-command:run

// gdb-command:print v
// gdbg-check:[...]$1 = size=2 = {size=2 = {1, 2}, size=1 = {3}}
// gdb-command:print empty_v
// gdbg-check:[...]$2 = size=0

fn main() {
    let v = vec![vec![1, 2], vec![3]];
    let empty_v: Vec<i32> = vec![];
    print!(""); // #break
}
<commit_msg>T: temporary disable formatters tests for `Vec`<commit_after>// max-version: 1.36.0

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print v
// lldbg-check:[...]$0 = size=2 { [0] = size=2 { [0] = 1 [1] = 2 } [1] = size=1 { [0] = 3 } }
// lldb-command:print empty_v
// lldbg-check:[...]$1 = size=0

// === GDB TESTS ===================================================================================

// gdb-command:run

// gdb-command:print v
// gdbg-check:[...]$1 = size=2 = {size=2 = {1, 2}, size=1 = {3}}
// gdb-command:print empty_v
// gdbg-check:[...]$2 = size=0

fn main() {
    let v = vec![vec![1, 2], vec![3]];
    let empty_v: Vec<i32> = vec![];
    print!(""); // #break
}
<|endoftext|>


<commit_before>// Copyright 2016 Mozilla Foundation
// Copyright 2016 Felix Obenhuber <felix@obenhuber.de>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::cache::{Cache, CacheRead, CacheWrite, Storage};
use crate::errors::*;
use futures_03::prelude::*;
use redis::aio::Connection;
use redis::{cmd, Client, InfoDict};
use std::collections::HashMap;
use std::io::Cursor;
use std::time::{Duration, Instant};

/// A cache that stores entries in a Redis.
#[derive(Clone)]
pub struct RedisCache {
    url: String,
    client: Client,
}

impl RedisCache {
    /// Create a new `RedisCache`.
    pub fn new(url: &str) -> Result<RedisCache> {
        Ok(RedisCache {
            url: url.to_owned(),
            client: Client::open(url)?,
        })
    }

    /// Returns a connection with configured read and write timeouts.
    async fn connect(self) -> Result<Connection> {
        Ok(self.client.get_async_connection().await?)
    }
}

impl Storage for RedisCache {
    /// Open a connection and query for a key.
    fn get(&self, key: &str) -> SFuture<Cache> {
        let key = key.to_owned();
        let me = self.clone();
        Box::new(
            Box::pin(async move {
                let mut c = me.connect().await?;
                let d: Vec<u8> = cmd("GET").arg(key).query_async(&mut c).await?;
                if d.is_empty() {
                    Ok(Cache::Miss)
                } else {
                    CacheRead::from(Cursor::new(d)).map(Cache::Hit)
                }
            })
            .compat(),
        )
    }

    /// Open a connection and store a object in the cache.
    fn put(&self, key: &str, entry: CacheWrite) -> SFuture<Duration> {
        let key = key.to_owned();
        let me = self.clone();
        let start = Instant::now();
        Box::new(
            Box::pin(async move {
                let mut c = me.connect().await?;
                let d = entry.finish()?;
                cmd("SET").arg(key).arg(d).query_async(&mut c).await?;
                Ok(start.elapsed())
            })
            .compat(),
        )
    }

    /// Returns the cache location.
    fn location(&self) -> String {
        format!("Redis: {}", self.url)
    }

    /// Returns the current cache size. This value is aquired via
    /// the Redis INFO command (used_memory).
    fn current_size(&self) -> SFuture<Option<u64>> {
        let me = self.clone(); // TODO Remove clone
        Box::new(
            Box::pin(async move {
                let mut c = me.connect().await?;
                let v: InfoDict = cmd("INFO").query_async(&mut c).await?;
                Ok(v.get("used_memory"))
            })
            .compat(),
        )
    }

    /// Returns the maximum cache size. This value is read via
    /// the Redis CONFIG command (maxmemory). If the server has no
    /// configured limit, the result is None.
    fn max_size(&self) -> SFuture<Option<u64>> {
        let me = self.clone(); // TODO Remove clone
        Box::new(
            Box::pin(async move {
                let mut c = me.connect().await?;
                let h: HashMap<String, usize> = cmd("CONFIG")
                    .arg("GET")
                    .arg("maxmemory")
                    .query_async(&mut c)
                    .await?;
                Ok(h.get("maxmemory")
                    .and_then(|&s| if s != 0 { Some(s as u64) } else { None }))
            })
            .compat(),
        )
    }
}
<commit_msg>Treat failing Redis CONFIG call as null result<commit_after>// Copyright 2016 Mozilla Foundation
// Copyright 2016 Felix Obenhuber <felix@obenhuber.de>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::cache::{Cache, CacheRead, CacheWrite, Storage};
use crate::errors::*;
use futures_03::prelude::*;
use redis::aio::Connection;
use redis::{cmd, Client, InfoDict};
use std::collections::HashMap;
use std::io::Cursor;
use std::time::{Duration, Instant};

/// A cache that stores entries in a Redis.
#[derive(Clone)]
pub struct RedisCache {
    url: String,
    client: Client,
}

impl RedisCache {
    /// Create a new `RedisCache`.
    pub fn new(url: &str) -> Result<RedisCache> {
        Ok(RedisCache {
            url: url.to_owned(),
            client: Client::open(url)?,
        })
    }

    /// Returns a connection with configured read and write timeouts.
    async fn connect(self) -> Result<Connection> {
        Ok(self.client.get_async_connection().await?)
    }
}

impl Storage for RedisCache {
    /// Open a connection and query for a key.
    fn get(&self, key: &str) -> SFuture<Cache> {
        let key = key.to_owned();
        let me = self.clone();
        Box::new(
            Box::pin(async move {
                let mut c = me.connect().await?;
                let d: Vec<u8> = cmd("GET").arg(key).query_async(&mut c).await?;
                if d.is_empty() {
                    Ok(Cache::Miss)
                } else {
                    CacheRead::from(Cursor::new(d)).map(Cache::Hit)
                }
            })
            .compat(),
        )
    }

    /// Open a connection and store a object in the cache.
    fn put(&self, key: &str, entry: CacheWrite) -> SFuture<Duration> {
        let key = key.to_owned();
        let me = self.clone();
        let start = Instant::now();
        Box::new(
            Box::pin(async move {
                let mut c = me.connect().await?;
                let d = entry.finish()?;
                cmd("SET").arg(key).arg(d).query_async(&mut c).await?;
                Ok(start.elapsed())
            })
            .compat(),
        )
    }

    /// Returns the cache location.
    fn location(&self) -> String {
        format!("Redis: {}", self.url)
    }

    /// Returns the current cache size. This value is aquired via
    /// the Redis INFO command (used_memory).
    fn current_size(&self) -> SFuture<Option<u64>> {
        let me = self.clone(); // TODO Remove clone
        Box::new(
            Box::pin(async move {
                let mut c = me.connect().await?;
                let v: InfoDict = cmd("INFO").query_async(&mut c).await?;
                Ok(v.get("used_memory"))
            })
            .compat(),
        )
    }

    /// Returns the maximum cache size. This value is read via
    /// the Redis CONFIG command (maxmemory). If the server has no
    /// configured limit, the result is None.
    fn max_size(&self) -> SFuture<Option<u64>> {
        let me = self.clone(); // TODO Remove clone
        Box::new(
            Box::pin(async move {
                let mut c = me.connect().await?;
                let result: redis::RedisResult<HashMap<String, usize>> = cmd("CONFIG")
                    .arg("GET")
                    .arg("maxmemory")
                    .query_async(&mut c)
                    .await;
                match result {
                    Ok(h) => {
                        Ok(h.get("maxmemory")
                            .and_then(|&s| if s != 0 { Some(s as u64) } else { None }))
                    }
                    Err(_) => Ok(None),
                }
            })
            .compat(),
        )
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use core::*;

struct SymbolTable {
    pub table: HashMap<String, Option<Epiq>>,
}

pub struct Evaluator<'a> {
    ast :&'a RefCell<AbstractSyntaxTree>,
    symbol_table: SymbolTable,
}

enum Result {
    MakeEpiq(Option<Epiq>),
    NewIndex(u32),
}

impl<'a> Evaluator<'a> {
    pub fn new(ast :&'a RefCell<AbstractSyntaxTree>) -> Evaluator {
        Evaluator{ ast: ast, symbol_table: SymbolTable{ table: HashMap::new() } }
    }

    pub fn walk(&mut self) -> Option<&RefCell<AbstractSyntaxTree>> {
        println!("\n");
        let index;
        {
            let borrowed_ast = self.ast.borrow();
            index = borrowed_ast.entrypoint.unwrap();
        }
        let result = self.walk_internal(index, 0);
        // println!("max: {:?} index: {:?}", result, index);
        if result != index {
            // なんらかの変化があったので反映する必要がある
            // ここだと、entrypointを変更する
            let mut ast = self.ast.borrow_mut();
            (*ast).entrypoint = Some(result);
        }

        Some(self.ast)
    }

    fn walk_internal(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        // self.eval_internal(index)
        let res = {
            let borrowed_ast = self.ast.borrow();
            let piq = borrowed_ast.get(index);
            println!("{}walk ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                &Epiq::Tpiq{ref o, p, q} => {
                    match o.as_ref() {
                        ">" => {
                            // ひとまずpは無視
                            let new_q = self.eval_internal(q, nest_level+1);
                            if new_q == q {
                                Result::MakeEpiq(None)
                            } else {
                                Result::MakeEpiq(Some(borrowed_ast.get(new_q).clone()))
                            }
                        },

                        _ => {

                            // その他のTpiqの場合は、pとq両方をwalkしてみて、
                            // 結果が両方とも変わらなければそのまま返す、
                            // そうでなければ新しくTpiqを作ってそのindexを返す
                            println!("{}walk >以外 pに入ります", " ".repeat(lvl));
                            let new_p = self.walk_internal(p, nest_level+1);
                            println!("{}walk >以外 qに入ります", " ".repeat(lvl));
                            let new_q = self.walk_internal(q, nest_level+1);
                            if new_p == p && new_q == q {
                                // println!("{}pもqも同じなので変化なし", " ".repeat(lvl));
                                Result::MakeEpiq(None)
                            } else {
                                // 新しくTpiqを作成

                                Result::MakeEpiq(Some(Epiq::Tpiq{o: o.to_string(), p: new_p, q: new_q}))
                            }
                        },
                    }
                },
                _ => Result::MakeEpiq(None),
            }
        };

        match res {
            Result::MakeEpiq(Some(new_epiq)) => {
                // まずpushだけ
                println!("{}walk 生み出す: {:?}", " ".repeat(lvl), new_epiq);
                self.ast.borrow_mut().push(new_epiq);
                self.ast.borrow().max_index.get()
            },
            Result::MakeEpiq(None) => {
                // 変化なし
                let borrowed_ast = self.ast.borrow();
                let piq = borrowed_ast.get(index);
                println!("{}walk 変化なし: {:?}", " ".repeat(lvl), piq);
                index
            },
            Result::NewIndex(i) => {
                let borrowed_ast = self.ast.borrow();
                let piq1 = borrowed_ast.get(index);
                let piq2 = borrowed_ast.get(i);
                println!("{}walk 付け替え: {:?} から {:?}", " ".repeat(lvl), piq1, piq2);
                i
            },
        }
    }

    fn eval_internal(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        let res = {
            let borrowed_ast = self.ast.borrow();
            let piq = borrowed_ast.get(index);
            println!("{}eval ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                &Epiq::Unit | &Epiq::Uit8(_) | &Epiq::Name(_) => Result::MakeEpiq(None),
                &Epiq::Tpiq{ref o, p, q} => {
                    match o.as_ref() {
                        "#" => {
                            // bind
                            // TODO: 実際のbindではなく、適当に固定値をbindしている
                            self.symbol_table.table.insert("abc".to_string(), Some(Epiq::Uit8(123)));

                            // Result::MakeEpiq(Some(Epiq::Unit))
                            Result::MakeEpiq(Some(Epiq::Uit8(123)))
                        },

                        // environment
                        "%" => {
                            // ひとまずNoneを返しておく
                            Result::MakeEpiq(None)
                        },

                        // block
                        r"\" => {
                            // TODO: 一つ目の環境の中身はひとまず無視する
                            // qのリストだけを逐次実行して、勝手に最後の値をwalkしてから返却するようにする
                            // ただ、そもそも、blockをevalしても、何も変化はないはず。
                            Result::MakeEpiq(None)
                        },

                        // apply
                        "!" => {
                            // p: lambda q:arguments
                            // 1. bind p.p(環境)の順番に沿って、q(引数リスト)を当てはめていく

                            // TODO: とりあえず引数なしとして処理する

                            // 2. p.q(関数本体)をそのまま返却する
                            let lambda_piq = borrowed_ast.get(p);
                            if let &Epiq::Tpiq{o:_, p:_, q:lambda_body} = lambda_piq {
                                // 本来は一応walkを挟むべきかもしれない
                                let new_lambda_body = self.walk_internal(lambda_body, nest_level+1);
                                /*
                                if new_lambda_body == lambda_body {
                                    // walk_internalの結果でも変化はないし、Noneを返す
                                    Result::MakeEpiq(None)
                                } else {
                                    // walk_internalの結果、変化があったんだけど、
                                    // それってもうepiqとしては作られているので、
                                    // そのままNoneを返せばいい？
                                    // でもそうなると、新しいnew_lambda_bodyが返せない

                                    // Some(borrowed_ast.get(new_lambda_body).clone())
                                    Result::NewIndex(new_lambda_body)
                                }
                                */
                                Result::NewIndex(new_lambda_body)

                            } else {
                                Result::MakeEpiq(None)
                            }
                        },

                        // eval
                        ">" => {
                            println!("eval");
                            // p: 用途未定。新しく何かを限定したりとかかなあ。
                            //    アイディアは思いつくけど、
                            //    そもそもパーサを変えたりとか？
                            //    環境を変更したりとか？
                            //    継続っぽく使うとか？
                            // q: evalされる本体。
                            let new_q = self.eval_internal(q, nest_level+1);
                            if new_q == q {
                                Result::MakeEpiq(None)
                            } else {
                                Result::MakeEpiq(Some(borrowed_ast.get(new_q).clone()))
                            }
                        },

                        // resolve
                        "@" => {
                            // p: 用途未定。ひとまず無視
                            // q: シンボルというか名前
                            Result::MakeEpiq(Some(Epiq::Uit8(666)))
                        }

                        _ => Result::MakeEpiq(None),
                    }
                },

                &Epiq::Mpiq{ref o, p, q} => {
                    match o.as_ref() {
                        ">" => {
                            // ^> リストのeval
                            // リストの要素それぞれをevalする
                            // pは-1だとして処理する(最後の項目の評価結果が最終的な結果となる)
                            // Result::MakeEpiq(None)
                            let res = self.eval_list(q, nest_level+1);
                            // 戻り値のindexがすでに存在するなら何もしない
                            if res <= self.ast.borrow().max_index.get() {
                                Result::NewIndex(res)
                            } else {
                                Result::MakeEpiq(Some(borrowed_ast.get(res).clone()))
                            }

                        },
                        _ => Result::MakeEpiq(None),
                    }
                },
            }
        };

        match res {
            Result::MakeEpiq(Some(new_epiq)) => {
                // まずpushだけ
                println!("{}eval 生み出す: {:?}", " ".repeat(lvl), new_epiq);
                self.ast.borrow_mut().push(new_epiq);
                self.ast.borrow().max_index.get()
            },
            Result::MakeEpiq(None) => {
                // 変化なし
                let borrowed_ast = self.ast.borrow();
                let piq = borrowed_ast.get(index);
                println!("{}eval 変化なし: {:?}", " ".repeat(lvl), piq);
                index
            },
            Result::NewIndex(i) => {
                let borrowed_ast = self.ast.borrow();
                let piq1 = borrowed_ast.get(index);
                let piq2 = borrowed_ast.get(i);
                println!("{}eval 付け替え: {:?} から {:?}", " ".repeat(lvl), piq1, piq2);
                i
            },
        }
    }

    fn eval_list(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        if let Some(res_index) = {
            let borrowed_ast = self.ast.borrow();
            let piq = borrowed_ast.get(index);
            println!("{}eval_list ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                &Epiq::Tpiq{ref o,p,q} => {
                    match o.as_ref() {
                        ":" => {
                            let q_piq = borrowed_ast.get(q);
                            if *q_piq == Epiq::Unit {
                                // リストの最後なので評価の結果を返す
                                Some(self.eval_internal(p, nest_level+1))
                            } else {
                                // 評価はするが返さない
                                let _p_ret = self.eval_internal(p, nest_level+1);
                                // 次の項目へ
                                Some(self.eval_list(q, nest_level+1))
                            }
                        },
                        _ => None,
                    }
                },
                _ => None,
            }
        } {
            res_index
        } else {
            index
        }
    }
}

#[test]
#[ignore]
fn test() {
    let ast = &RefCell::new(AbstractSyntaxTree::new());
    let mut evaluator = Evaluator::new(ast);
    evaluator.walk();
}

/*
fn beta_reduct(&mut self, entry: usize) {
    /*
    // 仮引数に実引数を入れる
    let mut a = vec![1, 3, 5];
    a.remove(1);
    a.insert(1, 2);
    println!("{:?}", a);

    // confirm that target is "application-piq"
    match self.vm.vctr.get(entry) {
        Some(&Epiq::Apiq { p: p1, q: q1 }) => {
            /* 引数をまず、lambdaの中に入れる */

            // ApiqのpはFpiqである必要がある(=ラムダ適用の左側はラムダ式でなければならない)
            match self.vm.vctr.get(p1) {
                Some(&Epiq::Fpiq { p: p2, q: q2 }) => {

                    // FpiqのpはPrmtである必要がある(=ラムダ式のは引数のシンボルが入る)
                    match self.vm.vctr.get(p2) {
                        Some(&Epiq::Prmt(_)) => {
                        },
                        Some(p3) => println!("not anonymous parameter {:?}", p3),
                        None => println!("{:?}", "index error"),
                    }
                },
                Some(p2) => println!("not function epiq {:?}", p2),
                None => println!("{:?}", "index error"),
            }

            println!("v.len(): {:?} entry: {:?}", self.vm.vctr.len(), entry);
        },
        Some(p1) => println!("not application epiq {:?}", p1),
        None => println!("{:?}", "index error"),
    }
    */

    let mut is_ok: (usize, usize) = (0, 0);

    match apiq_f((self, entry))
        // .and_then(aexp_e).and_then(pprn)
        .and_then(aexp_e).and_then(fpiq_p)
        // .and_then(aexp_e).and_then(pprn)
        .and_then(aexp_e) {
            Some(t) => {
                println!("{:?}", t.1);
                match apiq_q((self, entry)) {
                    Some(t2) => {
                        is_ok = (t.1, t2.1);
                    }
                    _ => {},
                }
            }
            None => {},
    }

    if is_ok != (0, 0) {
        self.vm.vctr.remove(is_ok.0);
        self.vm.vctr.insert(is_ok.0, Epiq::Prmt(is_ok.1));
    }
}
*/
<commit_msg>use clone() instead of ref avoid panic, but i want to do<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use core::*;

struct SymbolTable {
    pub table: HashMap<String, Option<Epiq>>,
}

pub struct Evaluator<'a> {
    ast :&'a RefCell<AbstractSyntaxTree>,
    symbol_table: SymbolTable,
}

enum Result {
    MakeEpiq(Option<Epiq>),
    NewIndex(u32),
}

impl<'a> Evaluator<'a> {
    pub fn new(ast :&'a RefCell<AbstractSyntaxTree>) -> Evaluator {
        Evaluator{ ast: ast, symbol_table: SymbolTable{ table: HashMap::new() } }
    }

    pub fn walk(&mut self) -> Option<&RefCell<AbstractSyntaxTree>> {
        println!("\n");
        let index;
        {
            let borrowed_ast = self.ast.borrow();
            index = borrowed_ast.entrypoint.unwrap();
        }
        let result = self.walk_internal(index, 0);
        // println!("max: {:?} index: {:?}", result, index);
        if result != index {
            // なんらかの変化があったので反映する必要がある
            // ここだと、entrypointを変更する
            let mut ast = self.ast.borrow_mut();
            (*ast).entrypoint = Some(result);
        }

        Some(self.ast)
    }

    fn walk_internal(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        // self.eval_internal(index)
        let res = {
            let piq = {
                let borrowed_ast = self.ast.borrow();
                borrowed_ast.get(index).clone()
            };
            println!("{}walk ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                Epiq::Tpiq{ref o, p, q} => {
                    match o.as_ref() {
                        ">" => {
                            // ひとまずpは無視
                            let new_q = self.eval_internal(q, nest_level+1);
                            if new_q == q {
                                Result::MakeEpiq(None)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(new_q).clone()))
                            }
                        },

                        _ => {

                            // その他のTpiqの場合は、pとq両方をwalkしてみて、
                            // 結果が両方とも変わらなければそのまま返す、
                            // そうでなければ新しくTpiqを作ってそのindexを返す
                            println!("{}walk >以外 pに入ります", " ".repeat(lvl));
                            let new_p = self.walk_internal(p, nest_level+1);
                            println!("{}walk >以外 qに入ります", " ".repeat(lvl));
                            let new_q = self.walk_internal(q, nest_level+1);
                            if new_p == p && new_q == q {
                                // println!("{}pもqも同じなので変化なし", " ".repeat(lvl));
                                Result::MakeEpiq(None)
                            } else {
                                // 新しくTpiqを作成

                                Result::MakeEpiq(Some(Epiq::Tpiq{o: o.to_string(), p: new_p, q: new_q}))
                            }
                        },
                    }
                },
                _ => Result::MakeEpiq(None),
            }
        };

        match res {
            Result::MakeEpiq(Some(new_epiq)) => {
                // まずpushだけ
                println!("{}walk 生み出す: {:?}", " ".repeat(lvl), new_epiq);
                self.ast.borrow_mut().push(new_epiq);
                self.ast.borrow().max_index.get()
            },
            Result::MakeEpiq(None) => {
                // 変化なし
                let borrowed_ast = self.ast.borrow();
                let piq = borrowed_ast.get(index);
                println!("{}walk 変化なし: {:?}", " ".repeat(lvl), piq);
                index
            },
            Result::NewIndex(i) => {
                let borrowed_ast = self.ast.borrow();
                let piq1 = borrowed_ast.get(index);
                let piq2 = borrowed_ast.get(i);
                println!("{}walk 付け替え: {:?} から {:?}", " ".repeat(lvl), piq1, piq2);
                i
            },
        }
    }

    fn eval_internal(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        let res = {
            let piq = {
                let borrowed_ast = self.ast.borrow();
                borrowed_ast.get(index).clone()
            };
            println!("{}eval ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                Epiq::Unit | Epiq::Uit8(_) | Epiq::Name(_) => Result::MakeEpiq(None),
                Epiq::Tpiq{ref o, p, q} => {
                    match o.as_ref() {
                        "#" => {
                            // bind
                            // TODO: 実際のbindではなく、適当に固定値をbindしている
                            self.symbol_table.table.insert("abc".to_string(), Some(Epiq::Uit8(123)));

                            // Result::MakeEpiq(Some(Epiq::Unit))
                            Result::MakeEpiq(Some(Epiq::Unit))
                        },

                        // environment
                        "%" => {
                            // ひとまずNoneを返しておく
                            Result::MakeEpiq(None)
                        },

                        // block
                        r"\" => {
                            // TODO: 一つ目の環境の中身はひとまず無視する
                            // qのリストだけを逐次実行して、勝手に最後の値をwalkしてから返却するようにする
                            // ただ、そもそも、blockをevalしても、何も変化はないはず。
                            Result::MakeEpiq(None)
                        },

                        // apply
                        "!" => {
                            // p: lambda q:arguments
                            // 1. bind p.p(環境)の順番に沿って、q(引数リスト)を当てはめていく

                            // TODO: とりあえず引数なしとして処理する

                            // 2. p.q(関数本体)をそのまま返却する
                            let borrowed_ast = self.ast.borrow();
                            let lambda_piq = borrowed_ast.get(p);
                            if let &Epiq::Tpiq{o:_, p:_, q:lambda_body} = lambda_piq {
                                // 本来は一応walkを挟むべきかもしれない
                                let new_lambda_body = self.walk_internal(lambda_body, nest_level+1);
                                /*
                                if new_lambda_body == lambda_body {
                                    // walk_internalの結果でも変化はないし、Noneを返す
                                    Result::MakeEpiq(None)
                                } else {
                                    // walk_internalの結果、変化があったんだけど、
                                    // それってもうepiqとしては作られているので、
                                    // そのままNoneを返せばいい？
                                    // でもそうなると、新しいnew_lambda_bodyが返せない

                                    // Some(borrowed_ast.get(new_lambda_body).clone())
                                    Result::NewIndex(new_lambda_body)
                                }
                                */
                                Result::NewIndex(new_lambda_body)

                            } else {
                                Result::MakeEpiq(None)
                            }
                        },

                        // eval
                        ">" => {
                            println!("eval");
                            // p: 用途未定。新しく何かを限定したりとかかなあ。
                            //    アイディアは思いつくけど、
                            //    そもそもパーサを変えたりとか？
                            //    環境を変更したりとか？
                            //    継続っぽく使うとか？
                            // q: evalされる本体。
                            let new_q = self.eval_internal(q, nest_level+1);
                            if new_q == q {
                                Result::MakeEpiq(None)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(new_q).clone()))
                            }
                        },

                        // resolve
                        "@" => {
                            // p: 用途未定。ひとまず無視
                            // q: シンボルというか名前
                            Result::MakeEpiq(Some(Epiq::Uit8(666)))
                        }

                        _ => Result::MakeEpiq(None),
                    }
                },

                Epiq::Mpiq{ref o, p, q} => {
                    match o.as_ref() {
                        ">" => {
                            // ^> リストのeval
                            // リストの要素それぞれをevalする
                            // pは-1だとして処理する(最後の項目の評価結果が最終的な結果となる)
                            // Result::MakeEpiq(None)
                            let res = self.eval_list(q, nest_level+1);
                            // 戻り値のindexがすでに存在するなら何もしない
                            if res <= self.ast.borrow().max_index.get() {
                                Result::NewIndex(res)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(res).clone()))
                            }

                        },
                        _ => Result::MakeEpiq(None),
                    }
                },
            }
        };

        match res {
            Result::MakeEpiq(Some(new_epiq)) => {
                // まずpushだけ
                println!("{}eval 生み出す: {:?}", " ".repeat(lvl), new_epiq);
                self.ast.borrow_mut().push(new_epiq);
                self.ast.borrow().max_index.get()
            },
            Result::MakeEpiq(None) => {
                // 変化なし
                let borrowed_ast = self.ast.borrow();
                let piq = borrowed_ast.get(index);
                println!("{}eval 変化なし: {:?}", " ".repeat(lvl), piq);
                index
            },
            Result::NewIndex(i) => {
                let borrowed_ast = self.ast.borrow();
                let piq1 = borrowed_ast.get(index);
                let piq2 = borrowed_ast.get(i);
                println!("{}eval 付け替え: {:?} から {:?}", " ".repeat(lvl), piq1, piq2);
                i
            },
        }
    }

    fn eval_list(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        if let Some(res_index) = {
            let borrowed_ast = self.ast.borrow();
            let piq = borrowed_ast.get(index);
            println!("{}eval_list ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                &Epiq::Tpiq{ref o,p,q} => {
                    match o.as_ref() {
                        ":" => {
                            let q_piq = borrowed_ast.get(q);
                            if *q_piq == Epiq::Unit {
                                // リストの最後なので評価の結果を返す
                                Some(self.eval_internal(p, nest_level+1))
                            } else {
                                // 評価はするが返さない
                                let _p_ret = self.eval_internal(p, nest_level+1);
                                // 次の項目へ
                                Some(self.eval_list(q, nest_level+1))
                            }
                        },
                        _ => None,
                    }
                },
                _ => None,
            }
        } {
            res_index
        } else {
            index
        }
    }
}

#[test]
#[ignore]
fn test() {
    let ast = &RefCell::new(AbstractSyntaxTree::new());
    let mut evaluator = Evaluator::new(ast);
    evaluator.walk();
}

/*
fn beta_reduct(&mut self, entry: usize) {
    /*
    // 仮引数に実引数を入れる
    let mut a = vec![1, 3, 5];
    a.remove(1);
    a.insert(1, 2);
    println!("{:?}", a);

    // confirm that target is "application-piq"
    match self.vm.vctr.get(entry) {
        Some(&Epiq::Apiq { p: p1, q: q1 }) => {
            /* 引数をまず、lambdaの中に入れる */

            // ApiqのpはFpiqである必要がある(=ラムダ適用の左側はラムダ式でなければならない)
            match self.vm.vctr.get(p1) {
                Some(&Epiq::Fpiq { p: p2, q: q2 }) => {

                    // FpiqのpはPrmtである必要がある(=ラムダ式のは引数のシンボルが入る)
                    match self.vm.vctr.get(p2) {
                        Some(&Epiq::Prmt(_)) => {
                        },
                        Some(p3) => println!("not anonymous parameter {:?}", p3),
                        None => println!("{:?}", "index error"),
                    }
                },
                Some(p2) => println!("not function epiq {:?}", p2),
                None => println!("{:?}", "index error"),
            }

            println!("v.len(): {:?} entry: {:?}", self.vm.vctr.len(), entry);
        },
        Some(p1) => println!("not application epiq {:?}", p1),
        None => println!("{:?}", "index error"),
    }
    */

    let mut is_ok: (usize, usize) = (0, 0);

    match apiq_f((self, entry))
        // .and_then(aexp_e).and_then(pprn)
        .and_then(aexp_e).and_then(fpiq_p)
        // .and_then(aexp_e).and_then(pprn)
        .and_then(aexp_e) {
            Some(t) => {
                println!("{:?}", t.1);
                match apiq_q((self, entry)) {
                    Some(t2) => {
                        is_ok = (t.1, t2.1);
                    }
                    _ => {},
                }
            }
            None => {},
    }

    if is_ok != (0, 0) {
        self.vm.vctr.remove(is_ok.0);
        self.vm.vctr.insert(is_ok.0, Epiq::Prmt(is_ok.1));
    }
}
*/
<|endoftext|>


<commit_before>// Copyright 2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::ops;
use std::cell::RefCell;

/// Like `Send` but only if we have the unique reference to the object
pub unsafe trait SendUnique: 'static {
    fn is_unique(&self) -> bool;
}

/// Allows sending reference counted objects that don't implement `Send` to other threads
/// as long as only a single reference to the object exists.
#[derive(Debug)]
pub struct SendUniqueCell<T: SendUnique> {
    obj: T,
    // Thread id and refcount
    thread: RefCell<Option<(usize, usize)>>,
}

unsafe impl<T: SendUnique> Send for SendUniqueCell<T> {}

#[derive(Debug)]
pub struct BorrowError;

impl<T: SendUnique> SendUniqueCell<T> {
    /// Create a new `SendUniqueCell` out of `obj`
    ///
    /// Fails if `obj` is not unique at this time
    pub fn new(obj: T) -> Result<Self, T> {
        if !obj.is_unique() {
            return Err(obj);
        }

        Ok(SendUniqueCell {
            obj,
            thread: RefCell::new(None),
        })
    }

    /// Borrow the contained object or panic if borrowing
    /// is not possible at this time
    pub fn borrow(&self) -> Ref<T> {
        match self.try_borrow() {
            Err(_) => panic!("Can't borrow"),
            Ok(r) => r,
        }
    }

    /// Try borrowing the contained object
    ///
    /// Borrowing is possible as long as only a single reference
    /// to the object exists, or it is borrowed from the same
    /// thread currently
    pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> {
        let mut thread = self.thread.borrow_mut();

        // If the object is unique, we can borrow it from
        // any thread we want and just have to keep track
        // how often we borrowed it
        if self.obj.is_unique() {
            if *thread == None {
                *thread = Some((::get_thread_id(), 1));
            } else {
                thread.as_mut().unwrap().1 += 1;
            }

            return Ok(Ref(self));
        }

        // If we don't even know from which thread it is borrowed, this
        // means it somehow got borrowed from outside the SendUniqueCell
        if *thread == None {
            return Err(BorrowError);
        }

        // If the object is not unique, we can only borrow it
        // from the thread that currently has it borrowed
        if thread.as_ref().unwrap().0 != ::get_thread_id() {
            return Err(BorrowError);
        }

        thread.as_mut().unwrap().1 += 1;

        Ok(Ref(self))
    }

    /// Extract the contained object or panic if it is not possible
    /// at this time
    pub fn into_inner(self) -> T {
        match self.try_into_inner() {
            Err(_) => panic!("Can't convert into inner type"),
            Ok(obj) => obj,
        }
    }

    /// Try extracing the contained object
    ///
    /// Borrowing is possible as long as only a single reference
    /// to the object exists, or it is borrowed from the same
    /// thread currently
    pub fn try_into_inner(self) -> Result<T, Self> {
        if self.try_borrow().is_err() {
            Err(self)
        } else {
            Ok(self.obj)
        }
    }
}

pub struct Ref<'a, T: SendUnique>(&'a SendUniqueCell<T>);

impl<'a, T: SendUnique> AsRef<T> for Ref<'a, T> {
    fn as_ref(&self) -> &T {
        &self.0.obj
    }
}

impl<'a, T: SendUnique> ops::Deref for Ref<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0.obj
    }
}

impl<'a, T: SendUnique> Drop for Ref<'a, T> {
    fn drop(&mut self) {
        let is_unique = self.0.obj.is_unique();
        let mut thread = self.0.thread.borrow_mut();

        if is_unique && thread.as_ref().unwrap().1 == 1 {
            *thread = None;
        } else {
            thread.as_mut().unwrap().1 -= 1;
        }
    }
}
<commit_msg>Add some more docs to SendUnique<commit_after>// Copyright 2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::ops;
use std::cell::RefCell;

/// Like `Send` but only if we have the unique reference to the object
///
/// Note that implementing this trait has to be done especially careful.
/// It must only be implemented on types where the uniqueness of a reference
/// can be determined, i.e. the reference count field is accessible and it
/// must only have references itself to other types that are `Send`.
/// `SendUnique` is *not* enough for the other types unless uniqueness of
/// all of them can be guaranteed, which is e.g. not the case if there's a
/// getter for them.
pub unsafe trait SendUnique: 'static {
    fn is_unique(&self) -> bool;
}

/// Allows sending reference counted objects that don't implement `Send` to other threads
/// as long as only a single reference to the object exists.
#[derive(Debug)]
pub struct SendUniqueCell<T: SendUnique> {
    obj: T,
    // Thread id and refcount
    thread: RefCell<Option<(usize, usize)>>,
}

unsafe impl<T: SendUnique> Send for SendUniqueCell<T> {}

#[derive(Debug)]
pub struct BorrowError;

impl<T: SendUnique> SendUniqueCell<T> {
    /// Create a new `SendUniqueCell` out of `obj`
    ///
    /// Fails if `obj` is not unique at this time
    pub fn new(obj: T) -> Result<Self, T> {
        if !obj.is_unique() {
            return Err(obj);
        }

        Ok(SendUniqueCell {
            obj,
            thread: RefCell::new(None),
        })
    }

    /// Borrow the contained object or panic if borrowing
    /// is not possible at this time
    pub fn borrow(&self) -> Ref<T> {
        match self.try_borrow() {
            Err(_) => panic!("Can't borrow"),
            Ok(r) => r,
        }
    }

    /// Try borrowing the contained object
    ///
    /// Borrowing is possible as long as only a single reference
    /// to the object exists, or it is borrowed from the same
    /// thread currently
    pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> {
        let mut thread = self.thread.borrow_mut();

        // If the object is unique, we can borrow it from
        // any thread we want and just have to keep track
        // how often we borrowed it
        if self.obj.is_unique() {
            if *thread == None {
                *thread = Some((::get_thread_id(), 1));
            } else {
                thread.as_mut().unwrap().1 += 1;
            }

            return Ok(Ref(self));
        }

        // If we don't even know from which thread it is borrowed, this
        // means it somehow got borrowed from outside the SendUniqueCell
        if *thread == None {
            return Err(BorrowError);
        }

        // If the object is not unique, we can only borrow it
        // from the thread that currently has it borrowed
        if thread.as_ref().unwrap().0 != ::get_thread_id() {
            return Err(BorrowError);
        }

        thread.as_mut().unwrap().1 += 1;

        Ok(Ref(self))
    }

    /// Extract the contained object or panic if it is not possible
    /// at this time
    pub fn into_inner(self) -> T {
        match self.try_into_inner() {
            Err(_) => panic!("Can't convert into inner type"),
            Ok(obj) => obj,
        }
    }

    /// Try extracing the contained object
    ///
    /// Borrowing is possible as long as only a single reference
    /// to the object exists, or it is borrowed from the same
    /// thread currently
    pub fn try_into_inner(self) -> Result<T, Self> {
        if self.try_borrow().is_err() {
            Err(self)
        } else {
            Ok(self.obj)
        }
    }
}

pub struct Ref<'a, T: SendUnique>(&'a SendUniqueCell<T>);

impl<'a, T: SendUnique> AsRef<T> for Ref<'a, T> {
    fn as_ref(&self) -> &T {
        &self.0.obj
    }
}

impl<'a, T: SendUnique> ops::Deref for Ref<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0.obj
    }
}

impl<'a, T: SendUnique> Drop for Ref<'a, T> {
    fn drop(&mut self) {
        let is_unique = self.0.obj.is_unique();
        let mut thread = self.0.thread.borrow_mut();

        if is_unique && thread.as_ref().unwrap().1 == 1 {
            *thread = None;
        } else {
            thread.as_mut().unwrap().1 -= 1;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Utilities for working with sessions.
//!
//! Sessions are created per action request and should be used as the only way
//! to communicate with the server. Sessions are responsible for handling action
//! errors (when something goes wrong) or notifying the server that the action
//! finished (by sending appropriate status signal).
//!
//! They also keep track of various statistics (such as number of transferred
//! bytes, action runtime, etc.) and stop the execution if they exceed limits
//! for a particular request.

mod demand;
mod error;
mod response;
mod sink;

use std::convert::TryInto;

use log::{error, info};

use crate::action;
use crate::message;
pub use self::demand::{Demand, Header, Payload};
pub use self::error::{Error, ParseError};
use self::response::{Response, Status};
pub use self::sink::{Sink};

/// A specialized `Result` type for sessions.
pub type Result<T> = std::result::Result<T, Error>;

/// Object associating a session with particular action request.
///
/// This is just a convenience type used to avoid threading large numbers of
/// parameters through different function calls.
///
/// Note that the payload can be quite large object, so it should not be stored
/// with the session itself. The payload should be consumed as soon as the
/// request is dispatched to a particular handler and parsed to a concrete type.
pub struct Task<'s, S: Session> {
    /// A session that this task should be run on.
    pub session: &'s mut S,
    /// Serialized data of the action request.
    pub payload: Payload,
}

impl<'s, S: Session> Task<'s, S> {

    /// Executes the task with a particular action handler.
    pub fn execute<R, H>(self, handler: H) -> Result<()>
    where
        R: action::Request,
        H: FnOnce(&mut S, R) -> Result<()>,
    {
        let request = self.payload.parse()?;
        handler(self.session, request)
    }
}

/// Processes given message, handling all errors.
///
/// This function takes a message from the GRR server and interprets it as an
/// action request. It creates a new session object and dispatches the request
/// to an appropriate action handler. Once the action finishes, the function
/// will send a final status message, informing the server about a success
/// or a failure.
///
/// Note that if action execution fails, this function deals with all the errors
/// by sending appropriate information to the server (if possible), logging them
/// and failing hard if a critical error (e.g. communication failure) occurred.
pub fn handle<M>(message: M)
where
    M: TryInto<Demand, Error=ParseError>,
{
    let demand = match message.try_into() {
        Ok(demand) => {
            info!("requested to execute the '{}' action", demand.action);
            demand
        }
        Err(error) => {
            error!("failed to parse the message: {}", error);
            return;
        }
    };

    let mut session = Action::from_demand(&demand);

    let result = action::dispatch(&demand.action, Task {
        session: &mut session,
        payload: demand.payload,
    });

    if let Err(ref error) = result {
        error!("failed to execute the '{}' action: {}", demand.action, error);
    } else {
        info!("finished executing the '{}' action", demand.action);
    }

    let message = match session.status(result).try_into() {
        Ok(message) => message,
        Err(error) => {
            // If we cannot encode the final status message, there is nothing
            // we can do to notify the server, as status is responsible for
            // reporting errors. We can only log the error and carry on.
            error!("failed to encode status message: {}", error);
            return;
        }
    };

    message::send(message);
}

/// Abstraction for various kinds of sessions.
pub trait Session {
    /// Sends a reply to the flow that call the action.
    fn reply<R>(&mut self, response: R) -> Result<()>
    where R: action::Response;

    /// Sends a message to a particular sink.
    fn send<R>(&mut self, sink: Sink, response: R) -> Result<()>
    where R: action::Response;
}

/// A session type for unrequested action executions.
///
/// Certain kind of actions are executed not only when a server flow decides to
/// do so, but also upon particular kind of events (e.g. the agent's startup).
/// In such cases, when one needs to trigger action execution manually, ad-hoc
/// sessions should be used.
pub struct Adhoc;

impl Session for Adhoc {

    // TODO: Session trait should be probably split into two traits and then
    // make the actions that do not care about the `reply` method implement the
    // simpler one.
    fn reply<R>(&mut self, response: R) -> Result<()>
    where
        R: action::Response,
    {
        error!("attempted to reply to an ad-hoc session, dropping response");
        drop(response);

        Ok(())
    }

    fn send<R>(&mut self, sink: Sink, response: R) -> Result<()>
    where
        R: action::Response,
    {
        send(sink.wrap(response))?;

        Ok(())
    }
}

/// A session type for ordinary action requests.
///
/// This is a normal session type that that is associated with some flow on the
/// server. It keeps track of the responses it sends and collects statistics
/// about network and runtime utilization to kill the action if it is needed.
pub struct Action {
    header: Header,
    next_response_id: u64,
}

impl Action {

    /// Constructs a new session for the given `demand` object.
    pub fn from_demand(demand: &Demand) -> Action {
        // Response identifiers that GRR agents use start at 0. Unfortunately,
        // the server uses this assumption (to determine the number of expected
        // responses when status message is received), so we have to follow this
        // behaviour in RRG as well.
        Action {
            header: demand.header.clone(),
            next_response_id: 1,
        }
    }

    /// Wraps an action response to a session-specific response.
    fn wrap<R>(&self, response: R) -> Response<R>
    where
        R: action::Response
    {
        Response {
            session_id: self.header.session_id.clone(),
            request_id: Some(self.header.request_id),
            response_id: Some(self.next_response_id),
            data: response,
        }
    }

    /// Wraps an action result to a session-specific status response.
    ///
    /// Note that this method consumes the session. The reason for this is that
    /// status response should be obtained as the very last response and no
    /// further replies should be possible after that.
    fn status(self, result: Result<()>) -> Status {
        Status {
            session_id: self.header.session_id,
            request_id: self.header.request_id,
            response_id: self.next_response_id,
            result: result,
        }
    }
}

impl Session for Action {

    fn reply<R: action::Response>(&mut self, response: R) -> Result<()> {
        send(self.wrap(response))?;
        self.next_response_id += 1;

        Ok(())
    }

    fn send<R>(&mut self, sink: Sink, response: R) -> Result<()>
    where
        R: action::Response,
    {
        send(sink.wrap(response))?;

        Ok(())
    }
}

/// Sends a session response to the server.
///
/// Note that this function is not exposed on purpose. Actions should send
/// responses through session objects which introduce a layer of safety. `send`
/// is a low-level utility supposed to be used internally.
fn send<R>(response: Response<R>) -> Result<()>
where
    R: action::Response,
{
    let message = response.try_into()?;
    message::send(message);

    Ok(())
}
<commit_msg>Fix a typo in the comment about response ids.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Utilities for working with sessions.
//!
//! Sessions are created per action request and should be used as the only way
//! to communicate with the server. Sessions are responsible for handling action
//! errors (when something goes wrong) or notifying the server that the action
//! finished (by sending appropriate status signal).
//!
//! They also keep track of various statistics (such as number of transferred
//! bytes, action runtime, etc.) and stop the execution if they exceed limits
//! for a particular request.

mod demand;
mod error;
mod response;
mod sink;

use std::convert::TryInto;

use log::{error, info};

use crate::action;
use crate::message;
pub use self::demand::{Demand, Header, Payload};
pub use self::error::{Error, ParseError};
use self::response::{Response, Status};
pub use self::sink::{Sink};

/// A specialized `Result` type for sessions.
pub type Result<T> = std::result::Result<T, Error>;

/// Object associating a session with particular action request.
///
/// This is just a convenience type used to avoid threading large numbers of
/// parameters through different function calls.
///
/// Note that the payload can be quite large object, so it should not be stored
/// with the session itself. The payload should be consumed as soon as the
/// request is dispatched to a particular handler and parsed to a concrete type.
pub struct Task<'s, S: Session> {
    /// A session that this task should be run on.
    pub session: &'s mut S,
    /// Serialized data of the action request.
    pub payload: Payload,
}

impl<'s, S: Session> Task<'s, S> {

    /// Executes the task with a particular action handler.
    pub fn execute<R, H>(self, handler: H) -> Result<()>
    where
        R: action::Request,
        H: FnOnce(&mut S, R) -> Result<()>,
    {
        let request = self.payload.parse()?;
        handler(self.session, request)
    }
}

/// Processes given message, handling all errors.
///
/// This function takes a message from the GRR server and interprets it as an
/// action request. It creates a new session object and dispatches the request
/// to an appropriate action handler. Once the action finishes, the function
/// will send a final status message, informing the server about a success
/// or a failure.
///
/// Note that if action execution fails, this function deals with all the errors
/// by sending appropriate information to the server (if possible), logging them
/// and failing hard if a critical error (e.g. communication failure) occurred.
pub fn handle<M>(message: M)
where
    M: TryInto<Demand, Error=ParseError>,
{
    let demand = match message.try_into() {
        Ok(demand) => {
            info!("requested to execute the '{}' action", demand.action);
            demand
        }
        Err(error) => {
            error!("failed to parse the message: {}", error);
            return;
        }
    };

    let mut session = Action::from_demand(&demand);

    let result = action::dispatch(&demand.action, Task {
        session: &mut session,
        payload: demand.payload,
    });

    if let Err(ref error) = result {
        error!("failed to execute the '{}' action: {}", demand.action, error);
    } else {
        info!("finished executing the '{}' action", demand.action);
    }

    let message = match session.status(result).try_into() {
        Ok(message) => message,
        Err(error) => {
            // If we cannot encode the final status message, there is nothing
            // we can do to notify the server, as status is responsible for
            // reporting errors. We can only log the error and carry on.
            error!("failed to encode status message: {}", error);
            return;
        }
    };

    message::send(message);
}

/// Abstraction for various kinds of sessions.
pub trait Session {
    /// Sends a reply to the flow that call the action.
    fn reply<R>(&mut self, response: R) -> Result<()>
    where R: action::Response;

    /// Sends a message to a particular sink.
    fn send<R>(&mut self, sink: Sink, response: R) -> Result<()>
    where R: action::Response;
}

/// A session type for unrequested action executions.
///
/// Certain kind of actions are executed not only when a server flow decides to
/// do so, but also upon particular kind of events (e.g. the agent's startup).
/// In such cases, when one needs to trigger action execution manually, ad-hoc
/// sessions should be used.
pub struct Adhoc;

impl Session for Adhoc {

    // TODO: Session trait should be probably split into two traits and then
    // make the actions that do not care about the `reply` method implement the
    // simpler one.
    fn reply<R>(&mut self, response: R) -> Result<()>
    where
        R: action::Response,
    {
        error!("attempted to reply to an ad-hoc session, dropping response");
        drop(response);

        Ok(())
    }

    fn send<R>(&mut self, sink: Sink, response: R) -> Result<()>
    where
        R: action::Response,
    {
        send(sink.wrap(response))?;

        Ok(())
    }
}

/// A session type for ordinary action requests.
///
/// This is a normal session type that that is associated with some flow on the
/// server. It keeps track of the responses it sends and collects statistics
/// about network and runtime utilization to kill the action if it is needed.
pub struct Action {
    header: Header,
    next_response_id: u64,
}

impl Action {

    /// Constructs a new session for the given `demand` object.
    pub fn from_demand(demand: &Demand) -> Action {
        // Response identifiers that GRR agents use start at 1. Unfortunately,
        // the server uses this assumption (to determine the number of expected
        // responses when status message is received), so we have to follow this
        // behaviour in RRG as well.
        Action {
            header: demand.header.clone(),
            next_response_id: 1,
        }
    }

    /// Wraps an action response to a session-specific response.
    fn wrap<R>(&self, response: R) -> Response<R>
    where
        R: action::Response
    {
        Response {
            session_id: self.header.session_id.clone(),
            request_id: Some(self.header.request_id),
            response_id: Some(self.next_response_id),
            data: response,
        }
    }

    /// Wraps an action result to a session-specific status response.
    ///
    /// Note that this method consumes the session. The reason for this is that
    /// status response should be obtained as the very last response and no
    /// further replies should be possible after that.
    fn status(self, result: Result<()>) -> Status {
        Status {
            session_id: self.header.session_id,
            request_id: self.header.request_id,
            response_id: self.next_response_id,
            result: result,
        }
    }
}

impl Session for Action {

    fn reply<R: action::Response>(&mut self, response: R) -> Result<()> {
        send(self.wrap(response))?;
        self.next_response_id += 1;

        Ok(())
    }

    fn send<R>(&mut self, sink: Sink, response: R) -> Result<()>
    where
        R: action::Response,
    {
        send(sink.wrap(response))?;

        Ok(())
    }
}

/// Sends a session response to the server.
///
/// Note that this function is not exposed on purpose. Actions should send
/// responses through session objects which introduce a layer of safety. `send`
/// is a low-level utility supposed to be used internally.
fn send<R>(response: Response<R>) -> Result<()>
where
    R: action::Response,
{
    let message = response.try_into()?;
    message::send(message);

    Ok(())
}
<|endoftext|>


<commit_before>pub mod config;
pub mod util;

extern crate clap;

use std::convert;
use std::fs::File;
use std::fmt::Debug;
use std::io::{self, BufReader, BufRead};
use std::iter::FromIterator;
use std::path::Path;
use std::str::FromStr;
use structs::Data;

use self::clap::{App, AppSettings, Arg, SubCommand};

const DEFAULT_SAVE_FILE: &'static str = "model_state.ser";

/// Reads the arguments given to this program at execution and returns them
pub fn read_arguments() -> config::GlobalConfig {
    let matches = App::new("rustle my net")
        .subcommand(SubCommand::with_name("learn")
            .arg(Arg::with_name("topology")
                .long("topology")
                .short("t")
                // TODO: proper help
                .help("a list of values representing the number of neurons in each layer")
                .multiple(true)
                .value_delimiter(" ")
                .required(true)
                .min_values(3))
            .arg(Arg::with_name("learning_rate")
                .long("eta")
                .takes_value(true)
                .help("The learning rate eta. Should be between 0.0 and 1.0")
                .default_value("0.05"))
            .arg(Arg::with_name("epochs")
                .long("epochs")
                .takes_value(true)
                .help("The number of training epochs")
                .default_value("100"))
            .arg(Arg::with_name("mini_batch_size")
                .long("batchsize")
                .takes_value(true)
                .help("The size of the mini batches for the learning process.")
                .default_value("32"))
            .arg(Arg::with_name("test_data_size")
                .long("testsize")
                .takes_value(true)
                .default_value("20")))
        .subcommand(SubCommand::with_name("classify"))
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(Arg::with_name("verbosity")
            .long("verbosity")
            .short("v")
            .takes_value(true)
            .possible_values(&["debug", "info", "error", "off"])
            // TODO: change default to warn for production
            .default_value("debug"))
        .arg(Arg::with_name("data")
            .long("data")
            .short("i")
            .takes_value(true)
            .default_value("data/iris_flowers.txt"))
        .arg(Arg::with_name("network_model")
            .long("model")
            .short("m")
            .takes_value(true))
        .arg(Arg::with_name("datatype")
            .long("type")
            .short("d")
            .takes_value(true)
            .possible_values(&["flower", "mnist"])
            .default_value("flower"))
        .arg(Arg::with_name("save_file")
            .long("file")
            .short("f")
            .takes_value(true)
            .default_value(DEFAULT_SAVE_FILE))
        .get_matches();

    config::GlobalConfig::from_arguments(matches)
}

/// Generically parse data from given input file into a Vec<Data>
fn parse_data<T>(datafile: &str) -> Result<Vec<Data>, io::Error>
    where T: FromStr + Into<Data>,
          T::Err: convert::From<io::Error> + Debug,
          Result<Vec<T>, T::Err>: FromIterator<Result<T, io::Error>>,
          Result<Vec<T>, io::Error>: FromIterator<Result<T, T::Err>>
{
    let mut path = self::util::get_root_dir();
    path.push(Path::new(datafile));

    let f = File::open(path)?;
    let reader = BufReader::new(&f);

    // TODO: rm unwrapping + trait bounds
    let v: Vec<Data> = reader.lines()
        .map(|l| l.unwrap().parse::<T>().unwrap().into())
        .collect();
    Ok(v)

}
<commit_msg>make clap help better<commit_after>pub mod config;
pub mod util;

extern crate clap;

use std::convert;
use std::fs::File;
use std::fmt::Debug;
use std::io::{self, BufReader, BufRead};
use std::iter::FromIterator;
use std::path::Path;
use std::str::FromStr;
use structs::Data;

use self::clap::{App, AppSettings, Arg, SubCommand};

const DEFAULT_SAVE_FILE: &'static str = "model_state.ser";

/// Reads the arguments given to this program at execution and returns them
pub fn read_arguments() -> config::GlobalConfig {
    let matches = App::new("rustle my net")
        .subcommand(SubCommand::with_name("learn")
            .arg(Arg::with_name("topology")
                .long("topology")
                .short("t")
                .help("A list of values representing the topology of the neural network. For \
                       example, the input '-t 4 5 3' would create a network with: 4 nodes in \
                       the input layer, a single hidden layer of 5 nodes and 3 nodes in the \
                       output layer.")
                .multiple(true)
                .value_delimiter(" ")
                .required(true)
                .min_values(3))
            .arg(Arg::with_name("learning_rate")
                .long("eta")
                .takes_value(true)
                .help("The learning rate eta. Should be between 0.0 and 1.0. Default is 0.05.")
                .default_value("0.05"))
            .arg(Arg::with_name("epochs")
                .long("epochs")
                .takes_value(true)
                .help("The number of training epochs. The default value is 100.")
                .default_value("100"))
            .arg(Arg::with_name("mini_batch_size")
                .long("batchsize")
                .takes_value(true)
                .help("The size of the mini batches for the learning process. Default: 32.")
                .default_value("32"))
            .arg(Arg::with_name("test_data_size")
                .long("testsize")
                .takes_value(true)
                .help("The size of the data that is used for validation. Defaults to 20.")
                .default_value("20")))
        .subcommand(SubCommand::with_name("classify"))
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(Arg::with_name("verbosity")
            .long("verbosity")
            .short("v")
            .takes_value(true)
            .possible_values(&["debug", "info", "error", "off"])
            .default_value("info"))
        .arg(Arg::with_name("data")
            .long("data")
            .short("i")
            .takes_value(true)
            .default_value("data/iris_flowers.txt"))
        .arg(Arg::with_name("datatype")
            .long("type")
            .short("d")
            .takes_value(true)
            .possible_values(&["flower", "mnist"])
            .default_value("flower"))
        .arg(Arg::with_name("save_file")
            .long("file")
            .short("f")
            .takes_value(true)
            .default_value(DEFAULT_SAVE_FILE))
        .get_matches();

    config::GlobalConfig::from_arguments(matches)
}

/// Generically parse data from given input file into a Vec<Data>
fn parse_data<T>(datafile: &str) -> Result<Vec<Data>, io::Error>
    where T: FromStr + Into<Data>,
          T::Err: convert::From<io::Error> + Debug,
          Result<Vec<T>, T::Err>: FromIterator<Result<T, io::Error>>,
          Result<Vec<T>, io::Error>: FromIterator<Result<T, T::Err>>
{
    let mut path = self::util::get_root_dir();
    path.push(Path::new(datafile));

    let f = File::open(path)?;
    let reader = BufReader::new(&f);

    // TODO: rm unwrapping + trait bounds
    let v: Vec<Data> = reader.lines()
        .map(|l| l.unwrap().parse::<T>().unwrap().into())
        .collect();
    Ok(v)

}
<|endoftext|>


<commit_before>use std::fmt;

use game_state::{GameState, GameMode};
use command::{CommandProcessor, HelpInfo};

pub enum Item {
  Torch,
}

impl Item {
  pub fn price(&self) -> i32 {
    match *self {
      Item::Torch => 15
    }
  }
}

impl fmt::Display for Item {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", match *self {
      Item::Torch => "a flaming torch",
    })
  }
}

pub enum InventoryCommand {
  Buy(Item),
  Quit,
}

impl CommandProcessor<InventoryCommand> for InventoryCommand {
  fn prompt() -> &'static str { "What do you want to buy? " }

  fn get_help() -> Vec<HelpInfo> {
    let buy = |item: Item| format!("buy {} (${})", item, item.price());

    HelpInfo::list(vec![
      ('1', buy(Item::Torch)),
      ('0', String::from("continue adventure")),
    ])
  }

  fn from_char(c: char) -> Option<InventoryCommand> {
    match c {
      '1' => Some(InventoryCommand::Buy(Item::Torch)),
      _ => Some(InventoryCommand::Quit),
    }
  }
}

impl<'a> GameState<'a> {
  pub fn tick_inventory_mode(&mut self) {
    if self.show_desc {
      println!("Provisions & inventory\n");
      self.print_wealth();
      println!("");
      InventoryCommand::show_help();
      println!("");
      self.show_desc = false;
    }

    if let Some(cmd) = InventoryCommand::get() {
      match cmd {
        InventoryCommand::Buy(item) => {
          let price = item.price();
          if price > self.wealth {
            println!("You don't have enough money to buy that.");
          } else {
            self.wealth -= price;
            println!("You bought {}.", item);
            self.print_wealth();
            match item {
              Item::Torch => self.light = true,
            }
          }
          println!("");
        },
        InventoryCommand::Quit => { self.set_mode(GameMode::Primary) },
      }
    }
  }
}
<commit_msg>Minor readability refactoring.<commit_after>use std::fmt;

use game_state::{GameState, GameMode};
use command::{CommandProcessor, HelpInfo};

use self::Item::*;

pub enum Item {
  Torch,
}

impl Item {
  pub fn price(&self) -> i32 {
    match *self {
      Torch => 15
    }
  }
}

impl fmt::Display for Item {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", match *self {
      Torch => "a flaming torch",
    })
  }
}

pub enum InventoryCommand {
  Buy(Item),
  Quit,
}

impl CommandProcessor<InventoryCommand> for InventoryCommand {
  fn prompt() -> &'static str { "What do you want to buy? " }

  fn get_help() -> Vec<HelpInfo> {
    let buy = |item: Item| format!("buy {} (${})", item, item.price());

    HelpInfo::list(vec![
      ('1', buy(Torch)),
      ('0', String::from("continue adventure")),
    ])
  }

  fn from_char(c: char) -> Option<InventoryCommand> {
    match c {
      '1' => Some(InventoryCommand::Buy(Torch)),
      _ => Some(InventoryCommand::Quit),
    }
  }
}

impl<'a> GameState<'a> {
  pub fn tick_inventory_mode(&mut self) {
    if self.show_desc {
      println!("Provisions & inventory\n");
      self.print_wealth();
      println!("");
      InventoryCommand::show_help();
      println!("");
      self.show_desc = false;
    }

    if let Some(cmd) = InventoryCommand::get() {
      match cmd {
        InventoryCommand::Buy(item) => {
          let price = item.price();
          if price > self.wealth {
            println!("You don't have enough money to buy that.");
          } else {
            self.wealth -= price;
            println!("You bought {}.", item);
            self.print_wealth();
            match item {
              Torch => self.light = true,
            }
          }
          println!("");
        },
        InventoryCommand::Quit => { self.set_mode(GameMode::Primary) },
      }
    }
  }
}
<|endoftext|>


<commit_before>use std::io;
use std::net::SocketAddr;

use tokio::net::TcpListener;
use tokio::net::TcpStream;

use futures::future::Future;
use futures::future::TryFutureExt;

use net2;

use crate::net::addr::AnySocketAddr;
use crate::net::connect::ToClientStream;
use crate::net::listen::SocketListener;
use crate::net::listen::ToSocketListener;
use crate::net::listen::ToTokioListener;
use crate::net::socket::SocketStream;
use crate::ServerConf;
use std::pin::Pin;
use tokio::runtime::Handle;

impl ToSocketListener for SocketAddr {
    fn listen(&self, conf: &ServerConf) -> io::Result<Box<dyn ToTokioListener + Send>> {
        Ok(Box::new(listener(self, conf)?))
    }

    fn cleanup(&self) {}
}

#[cfg(not(windows))]
fn configure_tcp(tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    use net2::unix::UnixTcpBuilderExt;
    if let Some(reuse_port) = conf.reuse_port {
        tcp.reuse_port(reuse_port)?;
    }
    Ok(())
}

#[cfg(windows)]
fn configure_tcp(_tcp: &net2::TcpBuilder, _conf: &ServerConf) -> io::Result<()> {
    Ok(())
}

fn listener(addr: &SocketAddr, conf: &ServerConf) -> io::Result<::std::net::TcpListener> {
    let listener = match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?,
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?,
    };

    if let SocketAddr::V6(_) = *addr {
        // Assume only_v6 = false by default
        // Note: it is not default behavior for Rust
        let only_v6 = conf.only_v6.unwrap_or(false);
        listener.only_v6(only_v6)?;
    }

    configure_tcp(&listener, conf)?;
    listener.reuse_address(true)?;
    debug!("binding socket to {}", addr);
    listener.bind(addr)?;
    let backlog = conf.backlog.unwrap_or(1024);
    listener.listen(backlog)
}

impl ToTokioListener for ::std::net::TcpListener {
    fn into_tokio_listener(self: Box<Self>, handle: &Handle) -> Pin<Box<dyn SocketListener>> {
        let _g = handle.enter();
        Box::pin(TcpListener::from_std(*self).unwrap())
    }

    fn local_addr(&self) -> io::Result<AnySocketAddr> {
        Ok(AnySocketAddr::Inet(self.local_addr().unwrap()))
    }
}

impl SocketListener for TcpListener {
    fn accept<'a>(
        self: Pin<&'a mut Self>,
    ) -> Pin<
        Box<
            dyn Future<Output = io::Result<(Pin<Box<dyn SocketStream + Send>>, AnySocketAddr)>>
                + Send
                + 'a,
        >,
    > {
        Box::pin(async move {
            let (socket, peer_addr) = TcpListener::accept(Pin::get_mut(self)).await?;
            Ok((
                Box::pin(socket) as Pin<Box<dyn SocketStream + Send>>,
                AnySocketAddr::Inet(peer_addr),
            ))
        })
    }
}

impl ToClientStream for SocketAddr {
    fn connect(
        &self,
        _handle: &Handle,
    ) -> Pin<Box<dyn Future<Output = io::Result<Pin<Box<dyn SocketStream>>>> + Send>> {
        let future = TcpStream::connect(self.clone())
            .map_ok(|stream| Box::pin(stream) as Pin<Box<dyn SocketStream>>);
        Box::pin(future)
    }

    fn socket_addr(&self) -> AnySocketAddr {
        AnySocketAddr::Inet(*self)
    }
}

impl SocketStream for TcpStream {
    fn is_tcp(&self) -> bool {
        true
    }

    fn set_tcp_nodelay(&self, no_delay: bool) -> io::Result<()> {
        self.set_nodelay(no_delay)
    }

    fn peer_addr(&self) -> io::Result<AnySocketAddr> {
        Ok(AnySocketAddr::Inet(TcpStream::peer_addr(self)?))
    }
}
<commit_msg>Make TcpListener non-blocking<commit_after>use std::io;
use std::net::SocketAddr;

use tokio::net::TcpListener;
use tokio::net::TcpStream;

use futures::future::Future;
use futures::future::TryFutureExt;

use net2;

use crate::net::addr::AnySocketAddr;
use crate::net::connect::ToClientStream;
use crate::net::listen::SocketListener;
use crate::net::listen::ToSocketListener;
use crate::net::listen::ToTokioListener;
use crate::net::socket::SocketStream;
use crate::ServerConf;
use std::pin::Pin;
use tokio::runtime::Handle;

impl ToSocketListener for SocketAddr {
    fn listen(&self, conf: &ServerConf) -> io::Result<Box<dyn ToTokioListener + Send>> {
        Ok(Box::new(listener(self, conf)?))
    }

    fn cleanup(&self) {}
}

#[cfg(not(windows))]
fn configure_tcp(tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    use net2::unix::UnixTcpBuilderExt;
    if let Some(reuse_port) = conf.reuse_port {
        tcp.reuse_port(reuse_port)?;
    }
    Ok(())
}

#[cfg(windows)]
fn configure_tcp(_tcp: &net2::TcpBuilder, _conf: &ServerConf) -> io::Result<()> {
    Ok(())
}

fn listener(addr: &SocketAddr, conf: &ServerConf) -> io::Result<::std::net::TcpListener> {
    let listener = match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?,
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?,
    };

    if let SocketAddr::V6(_) = *addr {
        // Assume only_v6 = false by default
        // Note: it is not default behavior for Rust
        let only_v6 = conf.only_v6.unwrap_or(false);
        listener.only_v6(only_v6)?;
    }

    configure_tcp(&listener, conf)?;
    listener.reuse_address(true)?;
    debug!("binding socket to {}", addr);
    listener.bind(addr)?;
    let backlog = conf.backlog.unwrap_or(1024);
    listener.listen(backlog)
}

impl ToTokioListener for ::std::net::TcpListener {
    fn into_tokio_listener(self: Box<Self>, handle: &Handle) -> Pin<Box<dyn SocketListener>> {
        let _g = handle.enter();
        self.set_nonblocking(true).unwrap();
        Box::pin(TcpListener::from_std(*self).unwrap())
    }

    fn local_addr(&self) -> io::Result<AnySocketAddr> {
        Ok(AnySocketAddr::Inet(self.local_addr().unwrap()))
    }
}

impl SocketListener for TcpListener {
    fn accept<'a>(
        self: Pin<&'a mut Self>,
    ) -> Pin<
        Box<
            dyn Future<Output = io::Result<(Pin<Box<dyn SocketStream + Send>>, AnySocketAddr)>>
                + Send
                + 'a,
        >,
    > {
        Box::pin(async move {
            let (socket, peer_addr) = TcpListener::accept(Pin::get_mut(self)).await?;
            Ok((
                Box::pin(socket) as Pin<Box<dyn SocketStream + Send>>,
                AnySocketAddr::Inet(peer_addr),
            ))
        })
    }
}

impl ToClientStream for SocketAddr {
    fn connect(
        &self,
        _handle: &Handle,
    ) -> Pin<Box<dyn Future<Output = io::Result<Pin<Box<dyn SocketStream>>>> + Send>> {
        let future = TcpStream::connect(self.clone())
            .map_ok(|stream| Box::pin(stream) as Pin<Box<dyn SocketStream>>);
        Box::pin(future)
    }

    fn socket_addr(&self) -> AnySocketAddr {
        AnySocketAddr::Inet(*self)
    }
}

impl SocketStream for TcpStream {
    fn is_tcp(&self) -> bool {
        true
    }

    fn set_tcp_nodelay(&self, no_delay: bool) -> io::Result<()> {
        self.set_nodelay(no_delay)
    }

    fn peer_addr(&self) -> io::Result<AnySocketAddr> {
        Ok(AnySocketAddr::Inet(TcpStream::peer_addr(self)?))
    }
}
<|endoftext|>