<commit_before>// Copyright 2016 LambdaStack All rights reserved.
//
// 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.
//

#![allow(unused_imports)]
#![allow(unused_variables)]

//! GET verb
//!
//! All GET requests are handled in this module.
//!

use rustc_serialize::json;

use clap::ArgMatches;
use aws_sdk_rust::aws::errors::s3::S3Error;
use aws_sdk_rust::aws::common::credentials::AwsCredentialsProvider;
use aws_sdk_rust::aws::common::request::DispatchSignedRequest;
use aws_sdk_rust::aws::s3::acl::*;
use aws_sdk_rust::aws::s3::bucket::*;
use aws_sdk_rust::aws::s3::object::ListObjectsRequest;

use term;
use Client;
use Output;
use OutputFormat;
use util::*;

/// All GET requests pass through this function.
pub fn commands<P: AwsCredentialsProvider, D: DispatchSignedRequest>(matches: &ArgMatches, client: &mut Client<P,D>) -> Result<(), S3Error> {
    //println!("Bucket-get -- get::commands::{:#?}", matches);
    let bucket = matches.value_of("name").unwrap_or("");

    match matches.subcommand() {
        /// acl command.
        ("acl", _) => {
            // Will bubble error up via try!
            let acl = try!(get_bucket_acl(bucket, client));
            match client.output.format {
                OutputFormat::Plain => {
                    // Could have already been serialized before being passed to this function.
                    println_color!(client.output.color, "{:#?}", acl);
                },
                OutputFormat::JSON => {
                    println_color!(client.output.color, "{}", json::encode(&acl).unwrap_or("{}".to_string()));
                },
                OutputFormat::PrettyJSON => {
                    println_color!(client.output.color, "{}", json::as_pretty_json(&acl));
                },
                OutputFormat::None => {},
                e @ _ => println!("Error: Format - {:#?}", e),
            }

        },
        ("list", _) => {
            // Will bubble error up via try!
            let list = try!(get_buckets_list(client));
        },
        (e,_) => {
            if e.is_empty() && !bucket.is_empty(){
                // Lists objects of a given bucket
                let output = get_bucket_list(bucket, client);
            } else {
                let error = format!("incorrect or missing request {}", e);
                println_color!(term::color::RED, "{}", error);
            }
        }
    }

    Ok(())
}

fn get_buckets_list<P: AwsCredentialsProvider, D: DispatchSignedRequest>(client: &Client<P,D>) -> Result<(), S3Error> {
    match client.s3client.list_buckets() {
      Ok(output) => {
          let format = format!("{:#?}", output);
          print_output(&client.output, &format);
          Ok(())
      }
      Err(error) => {
          let format = format!("{:#?}", error);
          print_error(&client.error, &format);
          let error = S3Error::new(format);
          Err(error)
      }
    }
}

fn get_bucket_list<P: AwsCredentialsProvider, D: DispatchSignedRequest>(bucket: &str, client: &Client<P,D>) -> Result<(), S3Error> {
    let mut list_objects = ListObjectsRequest::default();
    list_objects.bucket = bucket.to_string();

    match client.s3client.list_objects(&list_objects) {
      Ok(output) => {
          let format = format!("{:#?}", output);
          print_output(&client.output, &format);
          Ok(())
      }
      Err(error) => {
          let format = format!("{:#?}", error);
          print_error(&client.error, &format);
          let error = S3Error::new(format);
          Err(error)
      }
    }
}

pub fn get_bucket_acl<P: AwsCredentialsProvider, D: DispatchSignedRequest>(bucket: &str, client: &Client<P,D>) -> Result<AccessControlPolicy, S3Error> {
    let mut get_bucket_acl = GetBucketAclRequest::default();
    get_bucket_acl.bucket = bucket.to_string();

    match client.s3client.get_bucket_acl(&get_bucket_acl) {
        Ok(acl) => Ok(acl),
        Err(e) => {
            let format = format!("{:#?}", e);
            println_color!(term::color::RED, "missing or incorrect bucket name");
            print_error(&client.error, &format);
            Err(e)
        }
    }
}
<commit_msg>Updated bucket list output<commit_after>// Copyright 2016 LambdaStack All rights reserved.
//
// 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.
//

#![allow(unused_imports)]
#![allow(unused_variables)]

//! GET verb
//!
//! All GET requests are handled in this module.
//!

use rustc_serialize::json;

use clap::ArgMatches;
use aws_sdk_rust::aws::errors::s3::S3Error;
use aws_sdk_rust::aws::common::credentials::AwsCredentialsProvider;
use aws_sdk_rust::aws::common::request::DispatchSignedRequest;
use aws_sdk_rust::aws::s3::acl::*;
use aws_sdk_rust::aws::s3::bucket::*;
use aws_sdk_rust::aws::s3::object::ListObjectsRequest;

use term;
use Client;
use Output;
use OutputFormat;
use util::*;

/// All GET requests pass through this function.
pub fn commands<P: AwsCredentialsProvider, D: DispatchSignedRequest>(matches: &ArgMatches, client: &mut Client<P,D>) -> Result<(), S3Error> {
    //println!("Bucket-get -- get::commands::{:#?}", matches);
    let bucket = matches.value_of("name").unwrap_or("");

    match matches.subcommand() {
        /// acl command.
        ("acl", _) => {
            // Will bubble error up via try!
            let acl = try!(get_bucket_acl(bucket, client));
            match client.output.format {
                OutputFormat::Plain => {
                    // Could have already been serialized before being passed to this function.
                    println_color!(client.output.color, "{:#?}", acl);
                },
                OutputFormat::JSON => {
                    println_color!(client.output.color, "{}", json::encode(&acl).unwrap_or("{}".to_string()));
                },
                OutputFormat::PrettyJSON => {
                    println_color!(client.output.color, "{}", json::as_pretty_json(&acl));
                },
                OutputFormat::None => {},
                e @ _ => println!("Error: Format - {:#?}", e),
            }
        },
        ("list", _) => {
            // Will bubble error up via try!
            let list = try!(get_buckets_list(client));
        },
        (e,_) => {
            if e.is_empty() && !bucket.is_empty(){
                // Lists objects of a given bucket
                let output = get_bucket_list(bucket, client);
            } else {
                let error = format!("incorrect or missing request {}", e);
                println_color!(term::color::RED, "{}", error);
            }
        }
    }

    Ok(())
}

fn get_buckets_list<P: AwsCredentialsProvider, D: DispatchSignedRequest>(client: &Client<P,D>) -> Result<(), S3Error> {
    match client.s3client.list_buckets() {
      Ok(output) => {
          //let format = format!("{:#?}", output);
          //print_output(&client.output, &format);

          match client.output.format {
              OutputFormat::Plain => {
                  // Could have already been serialized before being passed to this function.
                  println_color!(client.output.color, "{:#?}", output);
              },
              OutputFormat::JSON => {
                  println_color!(client.output.color, "{}", json::encode(&output).unwrap_or("{}".to_string()));
              },
              OutputFormat::PrettyJSON => {
                  println_color!(client.output.color, "{}", json::as_pretty_json(&output));
              },
              OutputFormat::None => {},
              e @ _ => println!("Error: Format - {:#?}", e),
          }
          Ok(())
      }
      Err(error) => {
          let format = format!("{:#?}", error);
          print_error(&client.error, &format);
          let error = S3Error::new(format);
          Err(error)
      }
    }
}

fn get_bucket_list<P: AwsCredentialsProvider, D: DispatchSignedRequest>(bucket: &str, client: &Client<P,D>) -> Result<(), S3Error> {
    let mut list_objects = ListObjectsRequest::default();
    list_objects.bucket = bucket.to_string();

    match client.s3client.list_objects(&list_objects) {
      Ok(output) => {
          let format = format!("{:#?}", output);
          print_output(&client.output, &format);
          Ok(())
      }
      Err(error) => {
          let format = format!("{:#?}", error);
          print_error(&client.error, &format);
          let error = S3Error::new(format);
          Err(error)
      }
    }
}

pub fn get_bucket_acl<P: AwsCredentialsProvider, D: DispatchSignedRequest>(bucket: &str, client: &Client<P,D>) -> Result<AccessControlPolicy, S3Error> {
    let mut get_bucket_acl = GetBucketAclRequest::default();
    get_bucket_acl.bucket = bucket.to_string();

    match client.s3client.get_bucket_acl(&get_bucket_acl) {
        Ok(acl) => Ok(acl),
        Err(e) => {
            let format = format!("{:#?}", e);
            println_color!(term::color::RED, "missing or incorrect bucket name");
            print_error(&client.error, &format);
            Err(e)
        }
    }
}
<|endoftext|>


<commit_before>use core::{mem, str};

use pretty;

#[derive(Copy, Clone)]
pub struct Buffer {
    bytes: [u8; 24],
}

impl Buffer {
    #[inline]
    pub fn new() -> Self {
        Buffer {
            bytes: unsafe { mem::uninitialized() },
        }
    }

    pub fn format<F: Float>(&mut self, f: F) -> &str {
        f.write_to_ryu_buffer(self)
    }
}

impl Default for Buffer {
    #[inline]
    fn default() -> Self {
        Buffer::new()
    }
}

pub trait Float: Sealed {
    #[doc(hidden)]
    fn write_to_ryu_buffer(self, buffer: &mut Buffer) -> &str;
}

impl Float for f32 {
    #[inline]
    fn write_to_ryu_buffer(self, buffer: &mut Buffer) -> &str {
        unsafe {
            let n = pretty::f2s_buffered_n(self, &mut buffer.bytes[0]);
            str::from_utf8_unchecked(&buffer.bytes[..n])
        }
    }
}

impl Float for f64 {
    #[inline]
    fn write_to_ryu_buffer(self, buffer: &mut Buffer) -> &str {
        unsafe {
            let n = pretty::d2s_buffered_n(self, &mut buffer.bytes[0]);
            str::from_utf8_unchecked(&buffer.bytes[..n])
        }
    }
}

pub trait Sealed {}
impl Sealed for f32 {}
impl Sealed for f64 {}
<commit_msg>Remove bounds check in pretty wrappers<commit_after>use core::{mem, str};

use pretty;

#[derive(Copy, Clone)]
pub struct Buffer {
    bytes: [u8; 24],
}

impl Buffer {
    #[inline]
    pub fn new() -> Self {
        Buffer {
            bytes: unsafe { mem::uninitialized() },
        }
    }

    pub fn format<F: Float>(&mut self, f: F) -> &str {
        f.write_to_ryu_buffer(self)
    }
}

impl Default for Buffer {
    #[inline]
    fn default() -> Self {
        Buffer::new()
    }
}

pub trait Float: Sealed {
    #[doc(hidden)]
    fn write_to_ryu_buffer(self, buffer: &mut Buffer) -> &str;
}

impl Float for f32 {
    #[inline]
    fn write_to_ryu_buffer(self, buffer: &mut Buffer) -> &str {
        unsafe {
            let n = pretty::f2s_buffered_n(self, &mut buffer.bytes[0]);
            debug_assert!(n <= buffer.bytes.len());
            let slice = buffer.bytes.get_unchecked(..n);
            str::from_utf8_unchecked(slice)
        }
    }
}

impl Float for f64 {
    #[inline]
    fn write_to_ryu_buffer(self, buffer: &mut Buffer) -> &str {
        unsafe {
            let n = pretty::d2s_buffered_n(self, &mut buffer.bytes[0]);
            debug_assert!(n <= buffer.bytes.len());
            let slice = buffer.bytes.get_unchecked(..n);
            str::from_utf8_unchecked(slice)
        }
    }
}

pub trait Sealed {}
impl Sealed for f32 {}
impl Sealed for f64 {}
<|endoftext|>


<commit_before>use {At, Command, Error, History, Meta, Record};

/// A checkpoint wrapper.
///
/// Wraps a Record or History and gives it checkpoint functionality.
#[derive(Debug)]
pub struct Checkpoint<'a, T: 'a> {
    inner: &'a mut T,
    at: Option<At>,
}

impl<'a, R> From<&'a mut Record<R>> for Checkpoint<'a, Record<R>> {
    #[inline]
    fn from(record: &'a mut Record<R>) -> Self {
        let cursor = record.cursor();
        Checkpoint {
            inner: record,
            at: Some(At { branch: 0, cursor }),
        }
    }
}

impl<'a, R> Checkpoint<'a, Record<R>> {
    #[inline]
    pub fn apply(
        &mut self,
        command: impl Command<R> + 'static,
    ) -> Result<impl Iterator<Item = impl Command<R> + 'static>, Error<R>>
    where
        R: 'static,
    {
        let cursor = self.inner.cursor();
        self.at = self.at.filter(|at| at.cursor <= cursor);
        let (merged, v) = self.inner.__apply(Meta::new(command))?;
        if !merged && cursor == self.inner.cursor() {
            self.at = self.at.and_then(|at| {
                at.cursor
                    .checked_sub(1)
                    .map(|cursor| At { branch: 0, cursor })
            });
        }
        Ok(v.into_iter())
    }

    #[inline]
    #[must_use]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        self.inner.undo()
    }

    #[inline]
    #[must_use]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        self.inner.redo()
    }

    #[inline]
    #[must_use]
    pub fn go_to(&mut self, cursor: usize) -> Option<Result<(), Error<R>>> {
        self.inner.go_to(cursor)
    }

    #[inline]
    pub fn commit(self) {}

    #[inline]
    pub fn cancel(self) -> Option<Result<(), Error<R>>> {
        let at = self.at?;
        self.inner.go_to(at.cursor)
    }

    #[inline]
    pub fn checkpoint(&mut self) -> Checkpoint<Record<R>> {
        self.inner.checkpoint()
    }

    #[inline]
    pub fn as_receiver(&self) -> &R {
        self.inner.as_receiver()
    }
}

impl<'a, R> AsRef<R> for Checkpoint<'a, Record<R>> {
    #[inline]
    fn as_ref(&self) -> &R {
        self.inner.as_ref()
    }
}

impl<'a, R> From<&'a mut History<R>> for Checkpoint<'a, History<R>> {
    #[inline]
    fn from(history: &'a mut History<R>) -> Self {
        let branch = history.root();
        let cursor = history.cursor();
        Checkpoint {
            inner: history,
            at: Some(At { branch, cursor }),
        }
    }
}

impl<'a, R> Checkpoint<'a, History<R>> {
    #[inline]
    pub fn apply(&mut self, command: impl Command<R> + 'static) -> Result<(), Error<R>>
    where
        R: 'static,
    {
        let root = self.inner.root();
        let cursor = self.inner.cursor();
        let merged = self.inner.__apply(Meta::new(command))?;
        if !merged && cursor == self.inner.cursor() {
            self.at = self.at.and_then(|at| {
                let branch = at.branch;
                at.cursor.checked_sub(1).map(|cursor| At { branch, cursor })
            });
        }
        self.at = match self.at {
            Some(at) if at.branch == root && at.cursor > cursor => Some(at),
            Some(at) if at.branch == root && at.cursor <= cursor => Some(At {
                branch: self.inner.root(),
                cursor: at.cursor,
            }),
            at => at,
        };
        Ok(())
    }

    #[inline]
    #[must_use]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        self.inner.undo()
    }

    #[inline]
    #[must_use]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        self.inner.redo()
    }

    #[inline]
    #[must_use]
    pub fn go_to(&mut self, branch: usize, cursor: usize) -> Option<Result<(), Error<R>>>
    where
        R: 'static,
    {
        let root = self.inner.root();
        let old = self.inner.cursor();
        let ok = self.inner.go_to(branch, cursor);
        // TODO: Test case when branch is not equal to root, but is part of the path to branch.
        self.at = match self.at {
            Some(at) if at.branch == root && at.cursor > old => Some(at),
            Some(at) if at.branch == root && at.cursor <= old => Some(At {
                branch: self.inner.root(),
                cursor: at.cursor,
            }),
            at => at,
        };
        ok
    }

    #[inline]
    pub fn commit(self) {}

    #[inline]
    pub fn cancel(self) -> Option<Result<(), Error<R>>>
    where
        R: 'static,
    {
        let at = self.at?;
        self.inner.go_to(at.branch, at.cursor)
    }

    #[inline]
    pub fn checkpoint(&mut self) -> Checkpoint<History<R>> {
        self.inner.checkpoint()
    }

    #[inline]
    pub fn as_receiver(&self) -> &R {
        self.inner.as_receiver()
    }
}

impl<'a, R> AsRef<R> for Checkpoint<'a, History<R>> {
    #[inline]
    fn as_ref(&self) -> &R {
        self.inner.as_ref()
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error;
    use {Command, Record};

    #[derive(Debug)]
    struct Add(char);

    impl Command<String> for Add {
        fn apply(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
            s.push(self.0);
            Ok(())
        }

        fn undo(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
            self.0 = s.pop().ok_or("`s` is empty")?;
            Ok(())
        }
    }

    #[test]
    fn commit() {
        let mut record = Record::default();
        {
            let mut cp = record.checkpoint();
            cp.apply(Add('a')).unwrap();
            cp.apply(Add('b')).unwrap();
            cp.apply(Add('c')).unwrap();
            assert_eq!(cp.as_receiver(), "abc");
            {
                let mut cp = cp.checkpoint();
                cp.apply(Add('d')).unwrap();
                cp.apply(Add('e')).unwrap();
                cp.apply(Add('f')).unwrap();
                assert_eq!(cp.as_receiver(), "abcdef");
                {
                    let mut cp = cp.checkpoint();
                    cp.apply(Add('g')).unwrap();
                    cp.apply(Add('h')).unwrap();
                    cp.apply(Add('i')).unwrap();
                    assert_eq!(cp.as_receiver(), "abcdefghi");
                    cp.commit();
                }
                cp.commit();
            }
            cp.commit();
        }
        assert_eq!(record.as_receiver(), "abcdefghi");
    }

    #[test]
    fn cancel() {
        let mut record = Record::default();
        {
            let mut cp = record.checkpoint();
            cp.apply(Add('a')).unwrap();
            cp.apply(Add('b')).unwrap();
            cp.apply(Add('c')).unwrap();
            {
                let mut cp = cp.checkpoint();
                cp.apply(Add('d')).unwrap();
                cp.apply(Add('e')).unwrap();
                cp.apply(Add('f')).unwrap();
                {
                    let mut cp = cp.checkpoint();
                    cp.apply(Add('g')).unwrap();
                    cp.apply(Add('h')).unwrap();
                    cp.apply(Add('i')).unwrap();
                    assert_eq!(cp.as_receiver(), "abcdefghi");
                    cp.cancel().unwrap().unwrap();
                }
                assert_eq!(cp.as_receiver(), "abcdef");
                cp.cancel().unwrap().unwrap();
            }
            assert_eq!(cp.as_receiver(), "abc");
            cp.cancel().unwrap().unwrap();
        }
        assert_eq!(record.as_receiver(), "");
    }
}
<commit_msg>Add docs for checkpoint<commit_after>use {At, Command, Error, History, Meta, Record};

/// A checkpoint wrapper.
///
/// Wraps a Record or History and gives it checkpoint functionality.
#[derive(Debug)]
pub struct Checkpoint<'a, T: 'a> {
    inner: &'a mut T,
    at: Option<At>,
}

impl<'a, R> From<&'a mut Record<R>> for Checkpoint<'a, Record<R>> {
    #[inline]
    fn from(record: &'a mut Record<R>) -> Self {
        let cursor = record.cursor();
        Checkpoint {
            inner: record,
            at: Some(At { branch: 0, cursor }),
        }
    }
}

impl<'a, R> Checkpoint<'a, Record<R>> {
    /// Calls the [`apply`] method.
    ///
    /// [`apply`]: struct.Record.html#method.apply
    #[inline]
    pub fn apply(
        &mut self,
        command: impl Command<R> + 'static,
    ) -> Result<impl Iterator<Item = impl Command<R> + 'static>, Error<R>>
    where
        R: 'static,
    {
        let cursor = self.inner.cursor();
        self.at = self.at.filter(|at| at.cursor <= cursor);
        let (merged, v) = self.inner.__apply(Meta::new(command))?;
        if !merged && cursor == self.inner.cursor() {
            self.at = self.at.and_then(|at| {
                at.cursor
                    .checked_sub(1)
                    .map(|cursor| At { branch: 0, cursor })
            });
        }
        Ok(v.into_iter())
    }

    /// Calls the [`undo`] method.
    ///
    /// [`undo`]: struct.Record.html#method.undo
    #[inline]
    #[must_use]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        self.inner.undo()
    }

    /// Calls the [`redo`] method.
    ///
    /// [`redo`]: struct.Record.html#method.redo
    #[inline]
    #[must_use]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        self.inner.redo()
    }

    /// Calls the [`go_to`] method.
    ///
    /// [`go_to`]: struct.Record.html#method.go_to
    #[inline]
    #[must_use]
    pub fn go_to(&mut self, cursor: usize) -> Option<Result<(), Error<R>>> {
        self.inner.go_to(cursor)
    }

    /// Commits the changes and consumes the checkpoint.
    #[inline]
    pub fn commit(self) {}

    /// Cancels the changes and consumes the checkpoint.
    #[inline]
    pub fn cancel(self) -> Option<Result<(), Error<R>>> {
        let at = self.at?;
        self.inner.go_to(at.cursor)
    }

    /// Returns a checkpoint.
    #[inline]
    pub fn checkpoint(&mut self) -> Checkpoint<Record<R>> {
        self.inner.checkpoint()
    }

    /// Returns a reference to the `receiver`.
    #[inline]
    pub fn as_receiver(&self) -> &R {
        self.inner.as_receiver()
    }
}

impl<'a, R> AsRef<R> for Checkpoint<'a, Record<R>> {
    #[inline]
    fn as_ref(&self) -> &R {
        self.inner.as_ref()
    }
}

impl<'a, R> From<&'a mut History<R>> for Checkpoint<'a, History<R>> {
    #[inline]
    fn from(history: &'a mut History<R>) -> Self {
        let branch = history.root();
        let cursor = history.cursor();
        Checkpoint {
            inner: history,
            at: Some(At { branch, cursor }),
        }
    }
}

impl<'a, R> Checkpoint<'a, History<R>> {
    /// Calls the [`apply`] method.
    ///
    /// [`apply`]: struct.History.html#method.apply
    #[inline]
    pub fn apply(&mut self, command: impl Command<R> + 'static) -> Result<(), Error<R>>
    where
        R: 'static,
    {
        let root = self.inner.root();
        let cursor = self.inner.cursor();
        let merged = self.inner.__apply(Meta::new(command))?;
        if !merged && cursor == self.inner.cursor() {
            self.at = self.at.and_then(|at| {
                let branch = at.branch;
                at.cursor.checked_sub(1).map(|cursor| At { branch, cursor })
            });
        }
        self.at = match self.at {
            Some(at) if at.branch == root && at.cursor > cursor => Some(at),
            Some(at) if at.branch == root && at.cursor <= cursor => Some(At {
                branch: self.inner.root(),
                cursor: at.cursor,
            }),
            at => at,
        };
        Ok(())
    }

    /// Calls the [`undo`] method.
    ///
    /// [`undo`]: struct.History.html#method.undo
    #[inline]
    #[must_use]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        self.inner.undo()
    }

    /// Calls the [`redo`] method.
    ///
    /// [`redo`]: struct.History.html#method.redo
    #[inline]
    #[must_use]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        self.inner.redo()
    }

    /// Calls the [`go_to`] method.
    ///
    /// [`go_to`]: struct.History.html#method.go_to
    #[inline]
    #[must_use]
    pub fn go_to(&mut self, branch: usize, cursor: usize) -> Option<Result<(), Error<R>>>
    where
        R: 'static,
    {
        let root = self.inner.root();
        let old = self.inner.cursor();
        let ok = self.inner.go_to(branch, cursor);
        // TODO: Test case when branch is not equal to root, but is part of the path to branch.
        self.at = match self.at {
            Some(at) if at.branch == root && at.cursor > old => Some(at),
            Some(at) if at.branch == root && at.cursor <= old => Some(At {
                branch: self.inner.root(),
                cursor: at.cursor,
            }),
            at => at,
        };
        ok
    }

    /// Commits the changes and consumes the checkpoint.
    #[inline]
    pub fn commit(self) {}

    /// Cancels the changes and consumes the checkpoint.
    #[inline]
    pub fn cancel(self) -> Option<Result<(), Error<R>>>
    where
        R: 'static,
    {
        let at = self.at?;
        self.inner.go_to(at.branch, at.cursor)
    }

    /// Returns a checkpoint.
    #[inline]
    pub fn checkpoint(&mut self) -> Checkpoint<History<R>> {
        self.inner.checkpoint()
    }

    /// Returns a reference to the `receiver`.
    #[inline]
    pub fn as_receiver(&self) -> &R {
        self.inner.as_receiver()
    }
}

impl<'a, R> AsRef<R> for Checkpoint<'a, History<R>> {
    #[inline]
    fn as_ref(&self) -> &R {
        self.inner.as_ref()
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error;
    use {Command, Record};

    #[derive(Debug)]
    struct Add(char);

    impl Command<String> for Add {
        fn apply(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
            s.push(self.0);
            Ok(())
        }

        fn undo(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
            self.0 = s.pop().ok_or("`s` is empty")?;
            Ok(())
        }
    }

    #[test]
    fn commit() {
        let mut record = Record::default();
        {
            let mut cp = record.checkpoint();
            cp.apply(Add('a')).unwrap();
            cp.apply(Add('b')).unwrap();
            cp.apply(Add('c')).unwrap();
            assert_eq!(cp.as_receiver(), "abc");
            {
                let mut cp = cp.checkpoint();
                cp.apply(Add('d')).unwrap();
                cp.apply(Add('e')).unwrap();
                cp.apply(Add('f')).unwrap();
                assert_eq!(cp.as_receiver(), "abcdef");
                {
                    let mut cp = cp.checkpoint();
                    cp.apply(Add('g')).unwrap();
                    cp.apply(Add('h')).unwrap();
                    cp.apply(Add('i')).unwrap();
                    assert_eq!(cp.as_receiver(), "abcdefghi");
                    cp.commit();
                }
                cp.commit();
            }
            cp.commit();
        }
        assert_eq!(record.as_receiver(), "abcdefghi");
    }

    #[test]
    fn cancel() {
        let mut record = Record::default();
        {
            let mut cp = record.checkpoint();
            cp.apply(Add('a')).unwrap();
            cp.apply(Add('b')).unwrap();
            cp.apply(Add('c')).unwrap();
            {
                let mut cp = cp.checkpoint();
                cp.apply(Add('d')).unwrap();
                cp.apply(Add('e')).unwrap();
                cp.apply(Add('f')).unwrap();
                {
                    let mut cp = cp.checkpoint();
                    cp.apply(Add('g')).unwrap();
                    cp.apply(Add('h')).unwrap();
                    cp.apply(Add('i')).unwrap();
                    assert_eq!(cp.as_receiver(), "abcdefghi");
                    cp.cancel().unwrap().unwrap();
                }
                assert_eq!(cp.as_receiver(), "abcdef");
                cp.cancel().unwrap().unwrap();
            }
            assert_eq!(cp.as_receiver(), "abc");
            cp.cancel().unwrap().unwrap();
        }
        assert_eq!(record.as_receiver(), "");
    }
}
<|endoftext|>


<commit_before>use std::convert::From;

use binding::hash;
use types::{Value, ValueType};

use {AnyObject, Object, VerifiedObject};

/// `Hash`
#[derive(Debug, PartialEq)]
pub struct Hash {
    value: Value,
}

impl Hash {
    /// Creates a new instance of empty `Hash`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, VM};
    /// # VM::init();
    ///
    /// Hash::new();
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// {}
    /// ```
    pub fn new() -> Self {
        Self::from(hash::new())
    }

    /// Retrieves an `AnyObject` from element stored at `key` key.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Fixnum, Hash, Object, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key"), Fixnum::new(1));
    ///
    /// assert_eq!(hash.at(Symbol::new("key")).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    /// hash[:key] = 1
    ///
    /// hash[:key] == 1
    /// ```
    pub fn at<T: Object>(&self, key: T) -> AnyObject {
        let result = hash::aref(self.value(), key.value());

        AnyObject::from(result)
    }

    /// Associates the `value` with the `key`.
    ///
    /// Both `key` and `value` must be types which implement `Object` trait.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Fixnum, Hash, Object, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key"), Fixnum::new(1));
    ///
    /// assert_eq!(hash.at(Symbol::new("key")).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    /// hash[:key] = 1
    ///
    /// hash[:key] == 1
    /// ```
    pub fn store<K: Object, V: Object>(&mut self, key: K, value: V) -> AnyObject {
        let result = hash::aset(self.value(), key.value(), value.value());

        AnyObject::from(result)
    }

    /// Retrieves the length of the hash.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, Fixnum, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key1"), Fixnum::new(1));
    /// assert_eq!(hash.length(), 1);
    ///
    /// hash.store(Symbol::new("key2"), Fixnum::new(2));
    /// assert_eq!(hash.length(), 2);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    ///
    /// hash[:key1] = 1
    /// hash.length == 1
    ///
    /// hash[:key2] = 2
    /// hash.length == 2
    /// ```
    pub fn length(&self) -> usize {
        hash::length(self.value()) as usize
    }

    /// Removes all key-value pairs.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, Fixnum, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key1"), Fixnum::new(1));
    /// hash.store(Symbol::new("key2"), Fixnum::new(2));
    /// assert_eq!(hash.length(), 2);
    ///
    /// hash.clear();
    /// assert_eq!(hash.length(), 0);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    ///
    /// hash[:key1] = 1
    /// hash[:key2] = 2
    /// hash.length == 2
    ///
    /// hash.clear
    ///
    /// hash.length == 0
    /// ```
    pub fn clear(&self) {
        hash::clear(self.value())
    }

    /// Deletes the key-value pair and returns the value from hsh whose key is equal to key. If the
    /// key is not found, it returns nil.
    ///
    /// `key` must be a type which implements the `Object` trait.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Fixnum, Hash, Object, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key1"), Fixnum::new(1));
    /// hash.store(Symbol::new("key2"), Fixnum::new(2));
    /// assert_eq!(hash.length(), 2);
    ///
    /// let deleted = hash.delete(Symbol::new("key2"));
    /// assert_eq!(hash.length(), 1);
    /// assert_eq!(deleted.try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    ///
    /// hash[:key1] = 1
    /// hash[:key2] = 2
    /// hash.length == 2
    ///
    /// deleted = hash.delete(:key2)
    ///
    /// hash.length == 1
    /// deleted == 2
    /// ```
    pub fn delete<K: Object>(&self, key: K) -> AnyObject {
        let result = hash::delete(self.value(), key.value());

        AnyObject::from(result)
    }

    /// Runs a closure for each `key` and `value` pair.
    ///
    /// Key and value have `AnyObject` type.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Fixnum, Hash, Object, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("first_key"), Fixnum::new(1));
    /// hash.store(Symbol::new("second_key"), Fixnum::new(2));
    ///
    /// let mut doubled_values: Vec<i64> = Vec::new();
    ///
    /// hash.each(|_key, value| {
    ///     if let Ok(value) = value.try_convert_to::<Fixnum>() {
    ///         doubled_values.push(value.to_i64() * 2);
    ///     }
    /// });
    ///
    /// assert_eq!(doubled_values, vec![2, 4]);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {
    ///   first_key: 1,
    ///   second_key: 2
    /// }
    ///
    /// doubled_values = []
    ///
    /// hash.each do |_key, value|
    ///   doubled_values << [value * 2]
    /// end
    ///
    /// doubled_values == [2, 4]
    /// ```
    pub fn each<F>(&self, closure: F)
        where F: FnMut(AnyObject, AnyObject)
    {
        hash::each(self.value(), closure);
    }
}

impl Clone for Hash {
    fn clone(&self) -> Hash {
        Hash { value: hash::dup(self.value()) }
    }
}

impl From<Value> for Hash {
    fn from(value: Value) -> Self {
        Hash { value: value }
    }
}

impl Object for Hash {
    #[inline]
    fn value(&self) -> Value {
        self.value
    }
}

impl VerifiedObject for Hash {
    fn is_correct_type<T: Object>(object: &T) -> bool {
        object.value().ty() == ValueType::Hash
    }

    fn error_message() -> &'static str {
        "Error converting to Hash"
    }
}
<commit_msg>Implement Default for Hash<commit_after>use std::convert::From;
use std::default::Default;

use binding::hash;
use types::{Value, ValueType};

use {AnyObject, Object, VerifiedObject};

/// `Hash`
#[derive(Debug, PartialEq)]
pub struct Hash {
    value: Value,
}

impl Hash {
    /// Creates a new instance of empty `Hash`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, VM};
    /// # VM::init();
    ///
    /// Hash::new();
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// {}
    /// ```
    pub fn new() -> Self {
        Self::from(hash::new())
    }

    /// Retrieves an `AnyObject` from element stored at `key` key.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Fixnum, Hash, Object, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key"), Fixnum::new(1));
    ///
    /// assert_eq!(hash.at(Symbol::new("key")).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    /// hash[:key] = 1
    ///
    /// hash[:key] == 1
    /// ```
    pub fn at<T: Object>(&self, key: T) -> AnyObject {
        let result = hash::aref(self.value(), key.value());

        AnyObject::from(result)
    }

    /// Associates the `value` with the `key`.
    ///
    /// Both `key` and `value` must be types which implement `Object` trait.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Fixnum, Hash, Object, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key"), Fixnum::new(1));
    ///
    /// assert_eq!(hash.at(Symbol::new("key")).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    /// hash[:key] = 1
    ///
    /// hash[:key] == 1
    /// ```
    pub fn store<K: Object, V: Object>(&mut self, key: K, value: V) -> AnyObject {
        let result = hash::aset(self.value(), key.value(), value.value());

        AnyObject::from(result)
    }

    /// Retrieves the length of the hash.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, Fixnum, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key1"), Fixnum::new(1));
    /// assert_eq!(hash.length(), 1);
    ///
    /// hash.store(Symbol::new("key2"), Fixnum::new(2));
    /// assert_eq!(hash.length(), 2);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    ///
    /// hash[:key1] = 1
    /// hash.length == 1
    ///
    /// hash[:key2] = 2
    /// hash.length == 2
    /// ```
    pub fn length(&self) -> usize {
        hash::length(self.value()) as usize
    }

    /// Removes all key-value pairs.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, Fixnum, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key1"), Fixnum::new(1));
    /// hash.store(Symbol::new("key2"), Fixnum::new(2));
    /// assert_eq!(hash.length(), 2);
    ///
    /// hash.clear();
    /// assert_eq!(hash.length(), 0);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    ///
    /// hash[:key1] = 1
    /// hash[:key2] = 2
    /// hash.length == 2
    ///
    /// hash.clear
    ///
    /// hash.length == 0
    /// ```
    pub fn clear(&self) {
        hash::clear(self.value())
    }

    /// Deletes the key-value pair and returns the value from hsh whose key is equal to key. If the
    /// key is not found, it returns nil.
    ///
    /// `key` must be a type which implements the `Object` trait.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Fixnum, Hash, Object, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("key1"), Fixnum::new(1));
    /// hash.store(Symbol::new("key2"), Fixnum::new(2));
    /// assert_eq!(hash.length(), 2);
    ///
    /// let deleted = hash.delete(Symbol::new("key2"));
    /// assert_eq!(hash.length(), 1);
    /// assert_eq!(deleted.try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {}
    ///
    /// hash[:key1] = 1
    /// hash[:key2] = 2
    /// hash.length == 2
    ///
    /// deleted = hash.delete(:key2)
    ///
    /// hash.length == 1
    /// deleted == 2
    /// ```
    pub fn delete<K: Object>(&self, key: K) -> AnyObject {
        let result = hash::delete(self.value(), key.value());

        AnyObject::from(result)
    }

    /// Runs a closure for each `key` and `value` pair.
    ///
    /// Key and value have `AnyObject` type.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Fixnum, Hash, Object, Symbol, VM};
    /// # VM::init();
    ///
    /// let mut hash = Hash::new();
    ///
    /// hash.store(Symbol::new("first_key"), Fixnum::new(1));
    /// hash.store(Symbol::new("second_key"), Fixnum::new(2));
    ///
    /// let mut doubled_values: Vec<i64> = Vec::new();
    ///
    /// hash.each(|_key, value| {
    ///     if let Ok(value) = value.try_convert_to::<Fixnum>() {
    ///         doubled_values.push(value.to_i64() * 2);
    ///     }
    /// });
    ///
    /// assert_eq!(doubled_values, vec![2, 4]);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// hash = {
    ///   first_key: 1,
    ///   second_key: 2
    /// }
    ///
    /// doubled_values = []
    ///
    /// hash.each do |_key, value|
    ///   doubled_values << [value * 2]
    /// end
    ///
    /// doubled_values == [2, 4]
    /// ```
    pub fn each<F>(&self, closure: F)
        where F: FnMut(AnyObject, AnyObject)
    {
        hash::each(self.value(), closure);
    }
}

impl Clone for Hash {
    fn clone(&self) -> Hash {
        Hash { value: hash::dup(self.value()) }
    }
}

impl Default for Hash {
    fn default() -> Self {
        Hash::new()
    }
}

impl From<Value> for Hash {
    fn from(value: Value) -> Self {
        Hash { value: value }
    }
}

impl Object for Hash {
    #[inline]
    fn value(&self) -> Value {
        self.value
    }
}

impl VerifiedObject for Hash {
    fn is_correct_type<T: Object>(object: &T) -> bool {
        object.value().ty() == ValueType::Hash
    }

    fn error_message() -> &'static str {
        "Error converting to Hash"
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut Sender<Vec<u8>>);
    fn register_stop_tx(tx: *mut Sender<()>);
}

/// Connects to the provided address, (eg "123.123.123.123:3000") and registers
/// the on data received handler
#[no_mangle]
pub extern "C" fn connect(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - connect");

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            println!("Invalid host address");
            return -1 as c_int;
        }
    };

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    let kill_tx = k_tx.clone();
    let mut k_tx_ptr = Box::new(k_tx);
    unsafe {
        register_stop_tx(&mut *k_tx_ptr);
    }

    // Writer thread's channel
    let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    let mut w_tx_ptr = Box::new(w_tx);
    unsafe {
        register_writer_tx(&mut *w_tx_ptr);
    }

    println!("Attempting connect to: {}", host_address);

    let result = TcpStream::connect(host_address);
    if result.is_err() {
        println!("Error connecting to {} - {}", host_address, result.unwrap_err());
        return -1 as c_int;
    }
    println!("Connected");
    on_connect_handler();

    let stream = result.unwrap();
    let client = Bstream::new(stream);

    let r_client = client.clone();
    let r_kill_tx = kill_tx.clone();

    let w_client = client.clone();
    let w_kill_tx = kill_tx.clone();

    // Start the reader thread
    thread::Builder::new()
        .name("ReaderThread".to_string())
        .spawn(move||{
            reader_thread(r_client, handler, r_kill_tx)
        }).unwrap();

    // Start the writer thread
    thread::Builder::new()
        .name("WriterThread".to_string())
        .spawn(move||{
            writer_thread(w_rx, w_client, w_kill_tx)
        }).unwrap();

    // Wait for the kill signal
    match kill_rx.recv() {
        Ok(_) => { }
        Err(e) => {
            println!("Error on kill channel: {}", e);
            return -1 as c_int;
        }
    };
    on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<commit_msg>Debugging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut Sender<Vec<u8>>);
    fn register_stop_tx(tx: *mut Sender<()>);
}

/// Connects to the provided address, (eg "123.123.123.123:3000") and registers
/// the on data received handler
#[no_mangle]
pub extern "C" fn connect(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - connect");

    78 as c_int

    // let mut r_address;
    // unsafe {
    //     r_address = CStr::from_ptr(address);
    // }
    // let s_address = r_address.to_bytes();
    // let host_address = match str::from_utf8(s_address) {
    //     Ok(safe_str) => safe_str,
    //     Err(_) => {
    //         println!("Invalid host address");
    //         return -1 as c_int;
    //     }
    // };
    //
    // // Create and register a way to kill this client
    // let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    // let kill_tx = k_tx.clone();
    // let mut k_tx_ptr = Box::new(k_tx);
    // unsafe {
    //     register_stop_tx(&mut *k_tx_ptr);
    // }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);
    //
    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();
    //
    // // Exit out in standard C fashion
    // 0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<|endoftext|>


<commit_before>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::LitKind;
use crate::utils::{is_expn_of, match_def_path, opt_def_id, resolve_node, span_lint, span_lint_and_sugg};
use if_chain::if_chain;

/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be
/// replaced with `(e)print!()` / `(e)println!()`
///
/// **Why is this bad?** Using `(e)println! is clearer and more concise
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// // this would be clearer as `eprintln!("foo: {:?}", bar);`
/// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap();
/// ```
declare_clippy_lint! {
    pub EXPLICIT_WRITE,
    complexity,
    "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXPLICIT_WRITE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if_chain! {
            // match call to unwrap
            if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node;
            if unwrap_fun.ident.name == "unwrap";
            // match call to write_fmt
            if unwrap_args.len() > 0;
            if let ExprKind::MethodCall(ref write_fun, _, ref write_args) =
                unwrap_args[0].node;
            if write_fun.ident.name == "write_fmt";
            // match calls to std::io::stdout() / std::io::stderr ()
            if write_args.len() > 0;
            if let ExprKind::Call(ref dest_fun, _) = write_args[0].node;
            if let ExprKind::Path(ref qpath) = dest_fun.node;
            if let Some(dest_fun_id) =
                opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id));
            if let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) {
                Some("stdout")
            } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stderr"]) {
                Some("stderr")
            } else {
                None
            };
            then {
                let write_span = unwrap_args[0].span;
                let calling_macro =
                    // ordering is important here, since `writeln!` uses `write!` internally
                    if is_expn_of(write_span, "writeln").is_some() {
                        Some("writeln")
                    } else if is_expn_of(write_span, "write").is_some() {
                        Some("write")
                    } else {
                        None
                    };
                let prefix = if dest_name == "stderr" {
                    "e"
                } else {
                    ""
                };

                // We need to remove the last trailing newline from the string because the
                // underlying `fmt::write` function doesn't know whether `println!` or `print!` was
                // used.
                if let Some(mut write_output) = write_output_string(write_args) {
                    if write_output.ends_with('\n') {
                        write_output.pop();
                    }

                    if let Some(macro_name) = calling_macro {
                        span_lint_and_sugg(
                            cx,
                            EXPLICIT_WRITE,
                            expr.span,
                            &format!(
                                "use of `{}!({}(), ...).unwrap()`",
                                macro_name,
                                dest_name
                            ),
                            "try this",
                            format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default())
                        );
                    } else {
                        span_lint_and_sugg(
                            cx,
                            EXPLICIT_WRITE,
                            expr.span,
                            &format!("use of `{}().write_fmt(...).unwrap()`", dest_name),
                            "try this",
                            format!("{}print!(\"{}\")", prefix, write_output.escape_default())
                        );
                    }
                } else {
                    // We don't have a proper suggestion
                    if let Some(macro_name) = calling_macro {
                        span_lint(
                            cx,
                            EXPLICIT_WRITE,
                            expr.span,
                            &format!(
                                "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead",
                                macro_name,
                                dest_name,
                                prefix,
                                macro_name.replace("write", "print")
                            )
                        );
                    } else {
                        span_lint(
                            cx,
                            EXPLICIT_WRITE,
                            expr.span,
                            &format!("use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", dest_name, prefix),
                        );
                    }
                }

            }
        }
    }
}

// Extract the output string from the given `write_args`.
fn write_output_string(write_args: &HirVec<Expr>) -> Option<String> {
    if_chain! {
        // Obtain the string that should be printed
        if write_args.len() > 1;
        if let ExprKind::Call(_, ref output_args) = write_args[1].node;
        if output_args.len() > 0;
        if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node;
        if let ExprKind::Array(ref string_exprs) = output_string_expr.node;
        if string_exprs.len() > 0;
        if let ExprKind::Lit(ref lit) = string_exprs[0].node;
        if let LitKind::Str(ref write_output, _) = lit.node;
        then {
            return Some(write_output.to_string())
        }
    }
    None
}
<commit_msg>Make suggestion Applicability::MachineApplicable<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::rustc_errors::Applicability;
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::LitKind;
use crate::utils::{is_expn_of, match_def_path, opt_def_id, resolve_node, span_lint, span_lint_and_sugg};
use if_chain::if_chain;

/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be
/// replaced with `(e)print!()` / `(e)println!()`
///
/// **Why is this bad?** Using `(e)println! is clearer and more concise
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// // this would be clearer as `eprintln!("foo: {:?}", bar);`
/// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap();
/// ```
declare_clippy_lint! {
    pub EXPLICIT_WRITE,
    complexity,
    "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXPLICIT_WRITE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if_chain! {
            // match call to unwrap
            if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node;
            if unwrap_fun.ident.name == "unwrap";
            // match call to write_fmt
            if unwrap_args.len() > 0;
            if let ExprKind::MethodCall(ref write_fun, _, ref write_args) =
                unwrap_args[0].node;
            if write_fun.ident.name == "write_fmt";
            // match calls to std::io::stdout() / std::io::stderr ()
            if write_args.len() > 0;
            if let ExprKind::Call(ref dest_fun, _) = write_args[0].node;
            if let ExprKind::Path(ref qpath) = dest_fun.node;
            if let Some(dest_fun_id) =
                opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id));
            if let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) {
                Some("stdout")
            } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stderr"]) {
                Some("stderr")
            } else {
                None
            };
            then {
                let write_span = unwrap_args[0].span;
                let calling_macro =
                    // ordering is important here, since `writeln!` uses `write!` internally
                    if is_expn_of(write_span, "writeln").is_some() {
                        Some("writeln")
                    } else if is_expn_of(write_span, "write").is_some() {
                        Some("write")
                    } else {
                        None
                    };
                let prefix = if dest_name == "stderr" {
                    "e"
                } else {
                    ""
                };

                // We need to remove the last trailing newline from the string because the
                // underlying `fmt::write` function doesn't know whether `println!` or `print!` was
                // used.
                if let Some(mut write_output) = write_output_string(write_args) {
                    if write_output.ends_with('\n') {
                        write_output.pop();
                    }

                    if let Some(macro_name) = calling_macro {
                        span_lint_and_sugg(
                            cx,
                            EXPLICIT_WRITE,
                            expr.span,
                            &format!(
                                "use of `{}!({}(), ...).unwrap()`",
                                macro_name,
                                dest_name
                            ),
                            "try this",
                            format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default()),
                            Applicability::MachineApplicable
                        );
                    } else {
                        span_lint_and_sugg(
                            cx,
                            EXPLICIT_WRITE,
                            expr.span,
                            &format!("use of `{}().write_fmt(...).unwrap()`", dest_name),
                            "try this",
                            format!("{}print!(\"{}\")", prefix, write_output.escape_default()),
                            Applicability::MachineApplicable
                        );
                    }
                } else {
                    // We don't have a proper suggestion
                    if let Some(macro_name) = calling_macro {
                        span_lint(
                            cx,
                            EXPLICIT_WRITE,
                            expr.span,
                            &format!(
                                "use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead",
                                macro_name,
                                dest_name,
                                prefix,
                                macro_name.replace("write", "print")
                            )
                        );
                    } else {
                        span_lint(
                            cx,
                            EXPLICIT_WRITE,
                            expr.span,
                            &format!("use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", dest_name, prefix),
                        );
                    }
                }

            }
        }
    }
}

// Extract the output string from the given `write_args`.
fn write_output_string(write_args: &HirVec<Expr>) -> Option<String> {
    if_chain! {
        // Obtain the string that should be printed
        if write_args.len() > 1;
        if let ExprKind::Call(_, ref output_args) = write_args[1].node;
        if output_args.len() > 0;
        if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node;
        if let ExprKind::Array(ref string_exprs) = output_string_expr.node;
        if string_exprs.len() > 0;
        if let ExprKind::Lit(ref lit) = string_exprs[0].node;
        if let LitKind::Str(ref write_output, _) = lit.node;
        then {
            return Some(write_output.to_string())
        }
    }
    None
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;
use websocket;
use websocket::{Message, Sender, Receiver};
use websocket::server::sender;
use websocket::stream::WebSocketStream;
use websocket::message::CloseData;
use std::io::prelude::*;
use std::fs::{OpenOptions};
use std::net::Shutdown;
use rustc_serialize::json::{Json, ToJson};
use cbor;
use hyper::header::Cookie;

use value::Value;
use relation::Change;
use flow::{Changes, Flow};

// The server manages a single Eve program and handles communication with the editor and clients
// TODO needs review / refactoring, especially session handling

pub struct Server {
    pub flow: Flow,
    pub senders: Vec<sender::Sender<WebSocketStream>>,
}

#[derive(Debug, Clone)]
pub struct Event {
    pub changes: Changes,
    pub session: String,
    // commands that affect the whole program state have to go through this side-channel rather than being added to a view
    pub commands: Vec<Vec<String>>,
}

pub enum ServerEvent {
    Change(Vec<u8>),
    Sync((sender::Sender<WebSocketStream>, Option<String>)),
    Terminate(Option<CloseData>),
}

// --- json encodings ---

pub trait FromJson {
    fn from_json(json: &Json) -> Self;
}

impl ToJson for Value {
    fn to_json(&self) -> Json {
        match *self {
            Value::Null => panic!("Cannot allow the client to see nulls"),
            Value::Bool(bool) => Json::Boolean(bool),
            Value::String(ref string) => Json::String(string.clone()),
            Value::Float(float) => Json::F64(float),
            Value::Column(ref column) => Json::Array(column.iter().map(|v| v.to_json()).collect()),
        }
    }
}

impl FromJson for Value {
    fn from_json(json: &Json) -> Self {
        match *json {
            Json::Boolean(bool) => Value::Bool(bool),
            Json::String(ref string) => Value::String(string.clone()),
            Json::F64(float) => Value::Float(float),
            Json::I64(int) => Value::Float(int as f64),
            Json::U64(uint) => Value::Float(uint as f64),
            Json::Array(ref array) => Value::Column(array.iter().map(FromJson::from_json).collect()),
            _ => panic!("Cannot decode {:?} as Value", json),
        }
    }
}

impl FromJson for String {
    fn from_json(json: &Json) -> Self {
        json.as_string().unwrap().to_owned()
    }
}

impl<T: FromJson> FromJson for Vec<T> {
    fn from_json(json: &Json) -> Self {
        json.as_array().unwrap().iter().map(|t| FromJson::from_json(t)).collect()
    }
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("changes".to_string(), Json::Array(
                self.changes.iter().map(|&(ref view_id, ref view_changes)| {
                    Json::Array(vec![
                        view_id.to_json(),
                        view_changes.fields.to_json(),
                        view_changes.insert.to_json(),
                        view_changes.remove.to_json(),
                        ])
                }).collect()
                )
            ),
            ("session".to_string(), self.session.to_json()),
            ("commands".to_string(), self.commands.to_json()),
        ].into_iter().collect())
    }
}

impl FromJson for Event {
    fn from_json(json: &Json) -> Self {
        Event{
            changes: json.as_object().unwrap()["changes"]
            .as_array().unwrap().iter().map(|change| {
                let change = change.as_array().unwrap();
                assert_eq!(change.len(), 4);
                let view_id = FromJson::from_json(&change[0]);
                let fields = FromJson::from_json(&change[1]);
                let insert = FromJson::from_json(&change[2]);
                let remove = FromJson::from_json(&change[3]);
                (view_id, Change{fields:fields, insert: insert, remove: remove})
            }).collect(),
            session: "".to_string(),
            commands: FromJson::from_json(json.as_object().unwrap().get("commands").unwrap_or(&Json::Array(vec![]))),
        }
    }
}

// --- persistence ---

pub fn read_file(filename: &str) -> String {
    let mut file = OpenOptions::new().create(true).open(filename).unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    contents
}

pub fn write_file(filename: &str, contents: &str) {
    let mut file = OpenOptions::new().create(true).truncate(true).write(true).open(filename).unwrap();
    file.write_all(contents.as_bytes()).unwrap();
}

pub fn load(flow: &mut Flow, filename: &str) {
    for line in read_file(filename).lines() {
        let json = Json::from_str(&line).unwrap();
        let event: Event = FromJson::from_json(&json);
        flow.quiesce(event.changes);
    }
}

// TODO should probably just save changes, not the whole event
pub fn save(flow: &Flow, filename: &str) {
    let changes = flow.as_changes();
    let text = format!("{}", Event{changes: changes, session: "".to_owned(), commands: vec![]}.to_json());
    write_file(filename, &text[..]);
}

// --- server ---

pub fn send_event(server: &mut Server, changes: &Changes, commands: &Vec<Vec<String>>) {
    for sender in server.senders.iter_mut() {
        let session_id = format!("{}", sender.get_mut().peer_addr().unwrap());
        let event = Event{changes: changes.clone(), session: session_id, commands: commands.clone()};
        let text = format!("{}", event.to_json());
        match sender.send_message(Message::Text(text)) {
            Ok(_) => (),
            Err(error) => println!("Send error: {}", error),
        };
    }
}

pub fn get_user_id(cookies: Option<&Cookie>) -> Option<String> {
    match cookies {
        Some(cookies) => {
            match cookies.iter().find(|cookie| cookie.name == "userid") {
                Some(user_id) => Some(user_id.value.clone()),
                None => None,
            }
        },
        None => None,
    }
}

// rust-websocket is blocking, so we have to spawn a thread per connection
// each thread sends events back to a central channel
pub fn server_events() -> mpsc::Receiver<ServerEvent> {
    let (event_sender, event_receiver) = mpsc::channel();
    thread::spawn(move || {
        let server = websocket::Server::bind("0.0.0.0:2794").unwrap();
        for connection in server {
            let event_sender = event_sender.clone();
            thread::spawn(move || {
                // accept request
                let request = connection.unwrap().read_request().unwrap();
                request.validate().unwrap();

                // get the User ID from a cookie in the headers
                let user_id = get_user_id(request.headers.get::<Cookie>());

                let response = request.accept();
                let (mut sender, mut receiver) = response.send().unwrap().split();

                let ip = sender.get_mut().peer_addr().unwrap();
                println!("Connection from {}", ip);
                ::std::io::stdout().flush().unwrap(); // TODO is this actually necessary?

                // hand over the sender
                event_sender.send(ServerEvent::Sync((sender,user_id))).unwrap();

                // handle messages
                for message in receiver.incoming_messages() {
                    let message = match message {
                        Ok(m) => m,
                        Err(_) => return,
                    };
                    match message {
                        Message::Binary(bytes) => {
                            event_sender.send(ServerEvent::Change(bytes)).unwrap();
                        }
                        Message::Close(_) => {
                            let ip_addr = format!("{}", ip);
                            println!("Received close message from {}.",ip_addr);
                            let close_message = CloseData{status_code: 0, reason: ip_addr};
                            event_sender.send(ServerEvent::Terminate(Some(close_message))).unwrap();
                        }
                        _ => println!("Unknown message: {:?}", message)
                    }
                }
            });
        }
    });
    event_receiver
}

pub fn handle_event(server: &mut Server, event: Event, event_json: Json) {
    // save the event
    {
        let mut autosave = OpenOptions::new().write(true).append(true).open("./autosave").unwrap();
        autosave.write_all(format!("{}", event_json).as_bytes()).unwrap();
        autosave.write_all("\n".as_bytes()).unwrap();
        autosave.flush().unwrap();
    }

    // copy the old flow so we can compare to the new flow for changes
    let old_flow = server.flow.clone();

    // run the flow until it reaches fixpoint
    server.flow.quiesce(event.changes);

    // handle commands
    for command in event.commands.iter() {
        let borrowed_words = command.iter().map(|word| &word[..]).collect::<Vec<_>>();
        match &borrowed_words[..] {
            ["load", filename] => {
                server.flow = Flow::new();
                load(&mut server.flow, "./bootstrap");
                load(&mut server.flow, filename);
                save(&server.flow, "./autosave");
                let current_dir = ::std::env::current_dir().unwrap().to_str().unwrap().to_owned();
                send_event(server, &vec![], &vec![
                    vec!["loaded".to_owned(), current_dir, filename.to_owned()]
                    ]);
            }
            ["save", filename] => {
                save(&server.flow, filename);
                let current_dir = ::std::env::current_dir().unwrap().to_str().unwrap().to_owned();
                send_event(server, &vec![], &vec![
                    vec!["saved".to_owned(), current_dir, filename.to_owned()]
                    ]);
            }
            ["get events", id] => {
                let events_string = read_file("./autosave");
                send_event(server, &vec![], &vec![
                    vec!["got events".to_owned(), id.to_owned(), events_string]
                    ]);
            }
            ["set events", events_string] => {
                write_file("./autosave", events_string);
                server.flow = Flow::new();
                load(&mut server.flow, "./bootstrap");
                load(&mut server.flow, "./autosave");
            }
            other => panic!("Unknown command: {:?}", other),
        }
    }

    let changes = &server.flow.changes_from(old_flow);
    send_event(server, changes, &vec![]);
}

pub fn run() {
    let mut flow = Flow::new();
    time!("reading saved state", {
        load(&mut flow, "./bootstrap");
        load(&mut flow, "./autosave");
    });

    let senders: Vec<sender::Sender<WebSocketStream>> = Vec::new();

    let mut server = Server{flow: flow, senders: senders};

    for server_event in server_events() {
        match server_event {

            // a new client has connected and needs to sync its state
            ServerEvent::Sync((mut sender, user_id)) => {
                let mut changes = vec![];

                // add a session to the session table
                let session_id = format!("{}", sender.get_mut().peer_addr().unwrap());
                changes.push(("sessions".to_owned(),
                    Change{
                        fields: vec!["sessions: id".to_owned(), "sessions: status".to_owned()],
                        insert: vec![vec![Value::String(session_id.clone()), Value::Float(1f64)]],
                        remove: vec![],
                    }));

                // if we have a user ID, add a mapping from the session ID to the user ID
                if let Some(user_id) = user_id {
                    changes.push(("session id to user id".to_owned(),
                        Change{
                            fields: vec!["session id to user id: session id".to_owned(), "session id to user id: user id".to_owned()],
                            insert: vec![vec![Value::String(session_id.clone()), Value::String(user_id)]],
                            remove: vec![]
                        }));
                }

                // handle the session change
                let event = Event{changes: changes, session: session_id.clone(), commands: vec![]};
                let json = event.to_json();
                handle_event(&mut server, event, json);

                // sync the new client
                let changes = server.flow.as_changes();
                let event = Event{changes: changes, session: session_id, commands: vec![]};
                let text = format!("{}", event.to_json());
                match sender.send_message(Message::Text(text)) {
                    Ok(_) => (),
                    Err(error) => println!("Send error: {}", error),
                };
                server.senders.push(sender)
            }

            // an existing client has sent a new message
            ServerEvent::Change(input_bytes) => {
                // TODO we throw cbor in here to avoid https://github.com/rust-lang/rustc-serialize/issues/113
                let mut decoder = cbor::Decoder::from_bytes(&input_bytes[..]);
                let cbor = decoder.items().next().unwrap().unwrap();
                let json = cbor.to_json();
                let event = FromJson::from_json(&json);
                handle_event(&mut server, event, json);
            }

            ServerEvent::Terminate(m) => {
                let terminate_ip = m.unwrap().reason;
                println!("Closing connection from {}...",terminate_ip);

                // find the index of the connection's sender
                let ip_ix = server.senders.iter_mut().position(|mut sender| {
                    let ip = format!("{}",sender.get_mut().peer_addr().unwrap());
                    ip == terminate_ip
                });

                match ip_ix {
                    Some(ix) => {
                        // close the connection
                        let _ = server.senders[ix].send_message(Message::Close(None));
                        match server.senders[ix].get_mut().shutdown(Shutdown::Both) {
                            Ok(_) => println!("Connection from {} has closed successfully.",terminate_ip),
                            Err(e) => println!("Connection from {} failed to shut down properly: {}",terminate_ip,e),
                        }
                        server.senders.remove(ix);

                        // update the session table
                        let sessions = server.flow.get_output("sessions").clone();
                        let ip_string = Value::String(terminate_ip.clone());

                        // change the session status to 0
                        for row in sessions.find(vec![&ip_string, &Value::Null]) {
                            match row {
                                [_, ref status] => {
                                    let change = Change {
                                        fields: sessions.fields.clone(),
                                        insert: vec![vec![ip_string.clone(), Value::Float(0f64)]],
                                        remove: vec![vec![ip_string.clone(), status.clone()]],
                                    };
                                    let event = Event{changes: vec![("sessions".to_string(),change)], session: "".to_string(), commands: vec![]};
                                    let json = event.to_json();
                                    handle_event(&mut server, event, json);
                                }
                                _ => unreachable!(),
                            }
                        }

                    },
                    None => panic!("IP address {} is not connected",terminate_ip),
                }
            }
        }
    }
}<commit_msg>Send back id for set_events<commit_after>use std::thread;
use std::sync::mpsc;
use websocket;
use websocket::{Message, Sender, Receiver};
use websocket::server::sender;
use websocket::stream::WebSocketStream;
use websocket::message::CloseData;
use std::io::prelude::*;
use std::fs::{OpenOptions};
use std::net::Shutdown;
use rustc_serialize::json::{Json, ToJson};
use cbor;
use hyper::header::Cookie;

use value::Value;
use relation::Change;
use flow::{Changes, Flow};

// The server manages a single Eve program and handles communication with the editor and clients
// TODO needs review / refactoring, especially session handling

pub struct Server {
    pub flow: Flow,
    pub senders: Vec<sender::Sender<WebSocketStream>>,
}

#[derive(Debug, Clone)]
pub struct Event {
    pub changes: Changes,
    pub session: String,
    // commands that affect the whole program state have to go through this side-channel rather than being added to a view
    pub commands: Vec<Vec<String>>,
}

pub enum ServerEvent {
    Change(Vec<u8>),
    Sync((sender::Sender<WebSocketStream>, Option<String>)),
    Terminate(Option<CloseData>),
}

// --- json encodings ---

pub trait FromJson {
    fn from_json(json: &Json) -> Self;
}

impl ToJson for Value {
    fn to_json(&self) -> Json {
        match *self {
            Value::Null => panic!("Cannot allow the client to see nulls"),
            Value::Bool(bool) => Json::Boolean(bool),
            Value::String(ref string) => Json::String(string.clone()),
            Value::Float(float) => Json::F64(float),
            Value::Column(ref column) => Json::Array(column.iter().map(|v| v.to_json()).collect()),
        }
    }
}

impl FromJson for Value {
    fn from_json(json: &Json) -> Self {
        match *json {
            Json::Boolean(bool) => Value::Bool(bool),
            Json::String(ref string) => Value::String(string.clone()),
            Json::F64(float) => Value::Float(float),
            Json::I64(int) => Value::Float(int as f64),
            Json::U64(uint) => Value::Float(uint as f64),
            Json::Array(ref array) => Value::Column(array.iter().map(FromJson::from_json).collect()),
            _ => panic!("Cannot decode {:?} as Value", json),
        }
    }
}

impl FromJson for String {
    fn from_json(json: &Json) -> Self {
        json.as_string().unwrap().to_owned()
    }
}

impl<T: FromJson> FromJson for Vec<T> {
    fn from_json(json: &Json) -> Self {
        json.as_array().unwrap().iter().map(|t| FromJson::from_json(t)).collect()
    }
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("changes".to_string(), Json::Array(
                self.changes.iter().map(|&(ref view_id, ref view_changes)| {
                    Json::Array(vec![
                        view_id.to_json(),
                        view_changes.fields.to_json(),
                        view_changes.insert.to_json(),
                        view_changes.remove.to_json(),
                        ])
                }).collect()
                )
            ),
            ("session".to_string(), self.session.to_json()),
            ("commands".to_string(), self.commands.to_json()),
        ].into_iter().collect())
    }
}

impl FromJson for Event {
    fn from_json(json: &Json) -> Self {
        Event{
            changes: json.as_object().unwrap()["changes"]
            .as_array().unwrap().iter().map(|change| {
                let change = change.as_array().unwrap();
                assert_eq!(change.len(), 4);
                let view_id = FromJson::from_json(&change[0]);
                let fields = FromJson::from_json(&change[1]);
                let insert = FromJson::from_json(&change[2]);
                let remove = FromJson::from_json(&change[3]);
                (view_id, Change{fields:fields, insert: insert, remove: remove})
            }).collect(),
            session: "".to_string(),
            commands: FromJson::from_json(json.as_object().unwrap().get("commands").unwrap_or(&Json::Array(vec![]))),
        }
    }
}

// --- persistence ---

pub fn read_file(filename: &str) -> String {
    let mut file = OpenOptions::new().create(true).open(filename).unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    contents
}

pub fn write_file(filename: &str, contents: &str) {
    let mut file = OpenOptions::new().create(true).truncate(true).write(true).open(filename).unwrap();
    file.write_all(contents.as_bytes()).unwrap();
}

pub fn load(flow: &mut Flow, filename: &str) {
    for line in read_file(filename).lines() {
        let json = Json::from_str(&line).unwrap();
        let event: Event = FromJson::from_json(&json);
        flow.quiesce(event.changes);
    }
}

// TODO should probably just save changes, not the whole event
pub fn save(flow: &Flow, filename: &str) {
    let changes = flow.as_changes();
    let text = format!("{}", Event{changes: changes, session: "".to_owned(), commands: vec![]}.to_json());
    write_file(filename, &text[..]);
}

// --- server ---

pub fn send_event(server: &mut Server, changes: &Changes, commands: &Vec<Vec<String>>) {
    for sender in server.senders.iter_mut() {
        let session_id = format!("{}", sender.get_mut().peer_addr().unwrap());
        let event = Event{changes: changes.clone(), session: session_id, commands: commands.clone()};
        let text = format!("{}", event.to_json());
        match sender.send_message(Message::Text(text)) {
            Ok(_) => (),
            Err(error) => println!("Send error: {}", error),
        };
    }
}

pub fn get_user_id(cookies: Option<&Cookie>) -> Option<String> {
    match cookies {
        Some(cookies) => {
            match cookies.iter().find(|cookie| cookie.name == "userid") {
                Some(user_id) => Some(user_id.value.clone()),
                None => None,
            }
        },
        None => None,
    }
}

// rust-websocket is blocking, so we have to spawn a thread per connection
// each thread sends events back to a central channel
pub fn server_events() -> mpsc::Receiver<ServerEvent> {
    let (event_sender, event_receiver) = mpsc::channel();
    thread::spawn(move || {
        let server = websocket::Server::bind("0.0.0.0:2794").unwrap();
        for connection in server {
            let event_sender = event_sender.clone();
            thread::spawn(move || {
                // accept request
                let request = connection.unwrap().read_request().unwrap();
                request.validate().unwrap();

                // get the User ID from a cookie in the headers
                let user_id = get_user_id(request.headers.get::<Cookie>());

                let response = request.accept();
                let (mut sender, mut receiver) = response.send().unwrap().split();

                let ip = sender.get_mut().peer_addr().unwrap();
                println!("Connection from {}", ip);
                ::std::io::stdout().flush().unwrap(); // TODO is this actually necessary?

                // hand over the sender
                event_sender.send(ServerEvent::Sync((sender,user_id))).unwrap();

                // handle messages
                for message in receiver.incoming_messages() {
                    let message = match message {
                        Ok(m) => m,
                        Err(_) => return,
                    };
                    match message {
                        Message::Binary(bytes) => {
                            event_sender.send(ServerEvent::Change(bytes)).unwrap();
                        }
                        Message::Close(_) => {
                            let ip_addr = format!("{}", ip);
                            println!("Received close message from {}.",ip_addr);
                            let close_message = CloseData{status_code: 0, reason: ip_addr};
                            event_sender.send(ServerEvent::Terminate(Some(close_message))).unwrap();
                        }
                        _ => println!("Unknown message: {:?}", message)
                    }
                }
            });
        }
    });
    event_receiver
}

pub fn handle_event(server: &mut Server, event: Event, event_json: Json) {
    // save the event
    {
        let mut autosave = OpenOptions::new().write(true).append(true).open("./autosave").unwrap();
        autosave.write_all(format!("{}", event_json).as_bytes()).unwrap();
        autosave.write_all("\n".as_bytes()).unwrap();
        autosave.flush().unwrap();
    }

    // copy the old flow so we can compare to the new flow for changes
    let old_flow = server.flow.clone();

    // run the flow until it reaches fixpoint
    server.flow.quiesce(event.changes);

    // handle commands
    for command in event.commands.iter() {
        let borrowed_words = command.iter().map(|word| &word[..]).collect::<Vec<_>>();
        match &borrowed_words[..] {
            ["load", filename] => {
                server.flow = Flow::new();
                load(&mut server.flow, "./bootstrap");
                load(&mut server.flow, filename);
                save(&server.flow, "./autosave");
                let current_dir = ::std::env::current_dir().unwrap().to_str().unwrap().to_owned();
                send_event(server, &vec![], &vec![
                    vec!["loaded".to_owned(), current_dir, filename.to_owned()]
                    ]);
            }
            ["save", filename] => {
                save(&server.flow, filename);
                let current_dir = ::std::env::current_dir().unwrap().to_str().unwrap().to_owned();
                send_event(server, &vec![], &vec![
                    vec!["saved".to_owned(), current_dir, filename.to_owned()]
                    ]);
            }
            ["get events", id] => {
                let events_string = read_file("./autosave");
                send_event(server, &vec![], &vec![
                    vec!["events got".to_owned(), id.to_owned(), events_string]
                    ]);
            }
            ["set events", events_string] => {
                write_file("./autosave", events_string);
                server.flow = Flow::new();
                load(&mut server.flow, "./bootstrap");
                load(&mut server.flow, "./autosave");
                send_event(server, &vec![], &vec![
                    vec!["events set".to_owned(), id.to_owned()]
                    ]);
            }
            other => panic!("Unknown command: {:?}", other),
        }
    }

    let changes = &server.flow.changes_from(old_flow);
    send_event(server, changes, &vec![]);
}

pub fn run() {
    let mut flow = Flow::new();
    time!("reading saved state", {
        load(&mut flow, "./bootstrap");
        load(&mut flow, "./autosave");
    });

    let senders: Vec<sender::Sender<WebSocketStream>> = Vec::new();

    let mut server = Server{flow: flow, senders: senders};

    for server_event in server_events() {
        match server_event {

            // a new client has connected and needs to sync its state
            ServerEvent::Sync((mut sender, user_id)) => {
                let mut changes = vec![];

                // add a session to the session table
                let session_id = format!("{}", sender.get_mut().peer_addr().unwrap());
                changes.push(("sessions".to_owned(),
                    Change{
                        fields: vec!["sessions: id".to_owned(), "sessions: status".to_owned()],
                        insert: vec![vec![Value::String(session_id.clone()), Value::Float(1f64)]],
                        remove: vec![],
                    }));

                // if we have a user ID, add a mapping from the session ID to the user ID
                if let Some(user_id) = user_id {
                    changes.push(("session id to user id".to_owned(),
                        Change{
                            fields: vec!["session id to user id: session id".to_owned(), "session id to user id: user id".to_owned()],
                            insert: vec![vec![Value::String(session_id.clone()), Value::String(user_id)]],
                            remove: vec![]
                        }));
                }

                // handle the session change
                let event = Event{changes: changes, session: session_id.clone(), commands: vec![]};
                let json = event.to_json();
                handle_event(&mut server, event, json);

                // sync the new client
                let changes = server.flow.as_changes();
                let event = Event{changes: changes, session: session_id, commands: vec![]};
                let text = format!("{}", event.to_json());
                match sender.send_message(Message::Text(text)) {
                    Ok(_) => (),
                    Err(error) => println!("Send error: {}", error),
                };
                server.senders.push(sender)
            }

            // an existing client has sent a new message
            ServerEvent::Change(input_bytes) => {
                // TODO we throw cbor in here to avoid https://github.com/rust-lang/rustc-serialize/issues/113
                let mut decoder = cbor::Decoder::from_bytes(&input_bytes[..]);
                let cbor = decoder.items().next().unwrap().unwrap();
                let json = cbor.to_json();
                let event = FromJson::from_json(&json);
                handle_event(&mut server, event, json);
            }

            ServerEvent::Terminate(m) => {
                let terminate_ip = m.unwrap().reason;
                println!("Closing connection from {}...",terminate_ip);

                // find the index of the connection's sender
                let ip_ix = server.senders.iter_mut().position(|mut sender| {
                    let ip = format!("{}",sender.get_mut().peer_addr().unwrap());
                    ip == terminate_ip
                });

                match ip_ix {
                    Some(ix) => {
                        // close the connection
                        let _ = server.senders[ix].send_message(Message::Close(None));
                        match server.senders[ix].get_mut().shutdown(Shutdown::Both) {
                            Ok(_) => println!("Connection from {} has closed successfully.",terminate_ip),
                            Err(e) => println!("Connection from {} failed to shut down properly: {}",terminate_ip,e),
                        }
                        server.senders.remove(ix);

                        // update the session table
                        let sessions = server.flow.get_output("sessions").clone();
                        let ip_string = Value::String(terminate_ip.clone());

                        // change the session status to 0
                        for row in sessions.find(vec![&ip_string, &Value::Null]) {
                            match row {
                                [_, ref status] => {
                                    let change = Change {
                                        fields: sessions.fields.clone(),
                                        insert: vec![vec![ip_string.clone(), Value::Float(0f64)]],
                                        remove: vec![vec![ip_string.clone(), status.clone()]],
                                    };
                                    let event = Event{changes: vec![("sessions".to_string(),change)], session: "".to_string(), commands: vec![]};
                                    let json = event.to_json();
                                    handle_event(&mut server, event, json);
                                }
                                _ => unreachable!(),
                            }
                        }

                    },
                    None => panic!("IP address {} is not connected",terminate_ip),
                }
            }
        }
    }
}<|endoftext|>