<commit_before>
use wtest_basic::*;

#[cfg( feature = "in_wtools" )]
use wtools::string as TheModule;
#[cfg( not( feature = "in_wtools" ) )]
use wstring_tools as TheModule;

use TheModule::string::parse as parse;
use std::collections::HashMap;

//

fn _basic()
{
  let src = "";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = " ";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = " ";
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "  \t ";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = "  \t ";
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );
}

//

fn _with_subject_and_map()
{
  let src = "subj";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = "subj";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.maps = vec![ HashMap::new() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj with space";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = "subj with space";
  exp.subject = "subj with space".to_string();
  exp.subjects = vec![ "subj with space".to_string() ];
  exp.maps = vec![ HashMap::new() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:1";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:1";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:1 r:some";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  options.insert( String::from( "r" ), parse::OpType::Primitive( String::from( "some" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:1 r:some";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  /* */

  let src = "subj1 ; subj2";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = "subj1 ; subj2";
  exp.subject = "subj1".to_string();
  exp.subjects = vec![ "subj1".to_string(), "subj2".to_string() ];
  exp.maps = vec![ HashMap::new(), HashMap::new() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj1 v:1 ; subj2";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj1 v:1 ; subj2";
  exp.subject = "subj1".to_string();
  exp.subjects = vec![ "subj1".to_string(), "subj2".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone(), HashMap::new() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj1 v:1 ; subj2 v:2";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options1 = HashMap::new();
  options1.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  let mut options2 = HashMap::new();
  options2.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "2" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj1 v:1 ; subj2 v:2";
  exp.subject = "subj1".to_string();
  exp.subjects = vec![ "subj1".to_string(), "subj2".to_string() ];
  exp.map = options1.clone();
  exp.maps = vec![ options1.clone(), options2.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj1 v:1 ne:-2 ; subj2 v:2 r:some";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options1 = HashMap::new();
  options1.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  options1.insert( String::from( "ne" ), parse::OpType::Primitive( String::from( "-2" ) ) );
  let mut options2 = HashMap::new();
  options2.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "2" ) ) );
  options2.insert( String::from( "r" ), parse::OpType::Primitive( String::from( "some" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj1 v:1 ne:-2 ; subj2 v:2 r:some";
  exp.subject = "subj1".to_string();
  exp.subjects = vec![ "subj1".to_string(), "subj2".to_string() ];
  exp.map = options1.clone();
  exp.maps = vec![ options1.clone(), options2.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );
}

//

fn _with_several_values()
{
  let src = "subj v:1 v:2";
  let req = TheModule::string::request_parse()
  .src( src )
  .several_values( false )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( "2".to_string() ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:1 v:2";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:1 v:2";
  let req = TheModule::string::request_parse()
  .src( src )
  .several_values( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "1".to_string(), "2".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:1 v:2";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );
}

//

fn _with_parsing_arrays()
{
  let src = "subj v:[1,2]";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( false )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( "[1,2]".to_string() ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:[1,2]";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:[1,2]";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "1".to_string(), "2".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:[1,2]";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  /* */

  let src = "subj v:[1,2] v:3";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( true )
  .several_values( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "1".to_string(), "2".to_string(), "3".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:[1,2] v:3";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:3 v:[1,2]";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( true )
  .several_values( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "3".to_string(), "1".to_string(), "2".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:3 v:[1,2]";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:[1,2] v:[3,4]";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( true )
  .several_values( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "1".to_string(), "2".to_string(), "3".to_string(), "4".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:[1,2] v:[3,4]";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );
}

//

test_suite!
{
  basic,
  with_subject_and_map,
  with_several_values,
  with_parsing_arrays,
}
<commit_msg>Write test routine `op_type_from_into`<commit_after>
use wtest_basic::*;

#[cfg( feature = "in_wtools" )]
use wtools::string as TheModule;
#[cfg( not( feature = "in_wtools" ) )]
use wstring_tools as TheModule;

use TheModule::string::parse as parse;
use std::collections::HashMap;

//

fn _op_type_from_into()
{
  let got = parse::OpType::from( 1 );
  let exp = parse::OpType::Primitive( 1 );
  assert_eq!( got, exp );

  let got = parse::OpType::from( vec![ 1, 2 ] );
  let exp = parse::OpType::Vector( vec![ 1, 2 ] );
  assert_eq!( got, exp );

  /* */

  // let op = parse::OpType::from( 1 ); /* qqq : does not work properly, find better way to convert types */
  // let got : i32 = op.into();
  // assert_eq!( got, 1 );

  let op = parse::OpType::from( vec![ 1, 2 ] );
  let got : Vec<isize> = op.into();
  assert_eq!( got, vec![ 1, 2 ] );
}

//

fn _basic()
{
  let src = "";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = " ";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = " ";
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "  \t ";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = "  \t ";
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );
}

//

fn _with_subject_and_map()
{
  let src = "subj";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = "subj";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.maps = vec![ HashMap::new() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj with space";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = "subj with space";
  exp.subject = "subj with space".to_string();
  exp.subjects = vec![ "subj with space".to_string() ];
  exp.maps = vec![ HashMap::new() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:1";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:1";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:1 r:some";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  options.insert( String::from( "r" ), parse::OpType::Primitive( String::from( "some" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:1 r:some";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  /* */

  let src = "subj1 ; subj2";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut exp = parse::Request::default();
  exp.original = "subj1 ; subj2";
  exp.subject = "subj1".to_string();
  exp.subjects = vec![ "subj1".to_string(), "subj2".to_string() ];
  exp.maps = vec![ HashMap::new(), HashMap::new() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj1 v:1 ; subj2";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj1 v:1 ; subj2";
  exp.subject = "subj1".to_string();
  exp.subjects = vec![ "subj1".to_string(), "subj2".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone(), HashMap::new() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj1 v:1 ; subj2 v:2";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options1 = HashMap::new();
  options1.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  let mut options2 = HashMap::new();
  options2.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "2" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj1 v:1 ; subj2 v:2";
  exp.subject = "subj1".to_string();
  exp.subjects = vec![ "subj1".to_string(), "subj2".to_string() ];
  exp.map = options1.clone();
  exp.maps = vec![ options1.clone(), options2.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj1 v:1 ne:-2 ; subj2 v:2 r:some";
  let req = TheModule::string::request_parse()
  .src( src )
  .perform();
  let mut options1 = HashMap::new();
  options1.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "1" ) ) );
  options1.insert( String::from( "ne" ), parse::OpType::Primitive( String::from( "-2" ) ) );
  let mut options2 = HashMap::new();
  options2.insert( String::from( "v" ), parse::OpType::Primitive( String::from( "2" ) ) );
  options2.insert( String::from( "r" ), parse::OpType::Primitive( String::from( "some" ) ) );
  let mut exp = parse::Request::default();
  exp.original = "subj1 v:1 ne:-2 ; subj2 v:2 r:some";
  exp.subject = "subj1".to_string();
  exp.subjects = vec![ "subj1".to_string(), "subj2".to_string() ];
  exp.map = options1.clone();
  exp.maps = vec![ options1.clone(), options2.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );
}

//

fn _with_several_values()
{
  let src = "subj v:1 v:2";
  let req = TheModule::string::request_parse()
  .src( src )
  .several_values( false )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( "2".to_string() ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:1 v:2";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:1 v:2";
  let req = TheModule::string::request_parse()
  .src( src )
  .several_values( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "1".to_string(), "2".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:1 v:2";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );
}

//

fn _with_parsing_arrays()
{
  let src = "subj v:[1,2]";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( false )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Primitive( "[1,2]".to_string() ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:[1,2]";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:[1,2]";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "1".to_string(), "2".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:[1,2]";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  /* */

  let src = "subj v:[1,2] v:3";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( true )
  .several_values( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "1".to_string(), "2".to_string(), "3".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:[1,2] v:3";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:3 v:[1,2]";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( true )
  .several_values( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "3".to_string(), "1".to_string(), "2".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:3 v:[1,2]";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );

  let src = "subj v:[1,2] v:[3,4]";
  let req = TheModule::string::request_parse()
  .src( src )
  .parsing_arrays( true )
  .several_values( true )
  .perform();
  let mut options = HashMap::new();
  options.insert( String::from( "v" ), parse::OpType::Vector( vec![ "1".to_string(), "2".to_string(), "3".to_string(), "4".to_string() ] ) );
  let mut exp = parse::Request::default();
  exp.original = "subj v:[1,2] v:[3,4]";
  exp.subject = "subj".to_string();
  exp.subjects = vec![ "subj".to_string() ];
  exp.map = options.clone();
  exp.maps = vec![ options.clone() ];
  exp.key_val_delimeter = ":";
  exp.commands_delimeter = ";";
  assert_eq!( req, exp );
}

//

test_suite!
{
  op_type_from_into,
  basic,
  with_subject_and_map,
  with_several_values,
  with_parsing_arrays,
}
<|endoftext|>


<commit_before>// Given a set, generate its power set, which is the set of all subsets of that
// set: http://rosettacode.org/wiki/Power_set

use std::vec::Vec;
use std::slice::Items;

// If set == {}
//   return {{}}
// else if set == {a} U rest
//   return power_set(rest) U ({a} U each set in power_set(rest))
fn power_set<'a, T: Clone>(items: &mut Items<'a,T>) -> Vec<Vec<T>> {
    let mut power = Vec::new();
    match items.next() {
        None       => power.push(Vec::new()),
        Some(item) => {
            for set in power_set(items).iter() {
                power.push(set.clone());
                power.push(set.clone().append_one(item.clone()));
            }
        }
    }
    power
}

#[test]
fn test() {
    let set = Vec::<int>::new();
    let power = power_set(&mut set.iter());
    assert!(power == vec!(vec!()));

    let mut set = Vec::<int>::new();
    set.push(1);
    set.push(2);
    set.push(3);
    let power = power_set(&mut set.iter());
    assert!(power == vec!(vec!(), vec!(1), vec!(2), vec!(2, 1),
                          vec!(3), vec!(3, 1), vec!(3, 2), vec!(3, 2, 1)));
}

#[cfg(not(test))]
fn main() {
    let mut set = Vec::<int>::new();
    set.push(1);
    set.push(2);
    set.push(3);
    set.push(4);
    let power = power_set(&mut set.iter());
    println!("Set      : {}", set);
    println!("Power Set: {}", power);
}
<commit_msg>Fix power_set with explicit lifetime bound<commit_after>// Given a set, generate its power set, which is the set of all subsets of that
// set: http://rosettacode.org/wiki/Power_set

use std::vec::Vec;
use std::slice::Items;

// If set == {}
//   return {{}}
// else if set == {a} U rest
//   return power_set(rest) U ({a} U each set in power_set(rest))
fn power_set<'a, T: Clone + 'a>(items: &mut Items<'a,T>) -> Vec<Vec<T>> {
    let mut power = Vec::new();
    match items.next() {
        None       => power.push(Vec::new()),
        Some(item) => {
            for set in power_set(items).iter() {
                power.push(set.clone());
                power.push(set.clone().append_one(item.clone()));
            }
        }
    }
    power
}

#[test]
fn test() {
    let set = Vec::<int>::new();
    let power = power_set(&mut set.iter());
    assert!(power == vec!(vec!()));

    let mut set = Vec::<int>::new();
    set.push(1);
    set.push(2);
    set.push(3);
    let power = power_set(&mut set.iter());
    assert!(power == vec!(vec!(), vec!(1), vec!(2), vec!(2, 1),
                          vec!(3), vec!(3, 1), vec!(3, 2), vec!(3, 2, 1)));
}

#[cfg(not(test))]
fn main() {
    let mut set = Vec::<int>::new();
    set.push(1);
    set.push(2);
    set.push(3);
    set.push(4);
    let power = power_set(&mut set.iter());
    println!("Set      : {}", set);
    println!("Power Set: {}", power);
}
<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::io;
#[cfg(target_os = "linux")]
use std::os::unix::io::AsRawFd;
#[cfg(target_os = "linux")]
use std::convert::From;
use std::sync::Arc;
use std::thread;
#[cfg(target_os = "linux")]
use std::mem;

use coroutine::{State, Handle, Coroutine};

use mio::{EventLoop, Evented, Handler, Token, ReadHint, Interest, PollOpt};
use mio::util::Slab;
#[cfg(target_os = "linux")]
use mio::Io;

use mio::util::BoundedQueue;

use scheduler::Scheduler;

thread_local!(static PROCESSOR: UnsafeCell<Processor> = UnsafeCell::new(Processor::new()));

pub struct Processor {
    event_loop: EventLoop<IoHandler>,
    work_queue: Arc<BoundedQueue<Handle>>,
    handler: IoHandler,
}

impl Processor {
    pub fn new() -> Processor {
        Processor {
            event_loop: EventLoop::new().unwrap(),
            work_queue: Scheduler::get().get_queue(),
            handler: IoHandler::new(),
        }
    }

    pub fn current() -> &'static mut Processor {
        PROCESSOR.with(|p| unsafe { &mut *p.get() })
    }

    pub fn schedule(&mut self) -> io::Result<()> {
        loop {
            if self.handler.slabs.count() != 0 {
                try!(self.event_loop.run_once(&mut self.handler));
            }

            match self.work_queue.pop() {
                Some(hdl) => {
                    match hdl.resume() {
                        Ok(State::Suspended) => {
                            Scheduler::ready(hdl);
                        },
                        Ok(State::Finished) | Ok(State::Panicked) => {
                            Scheduler::finished(hdl);
                        },
                        Ok(State::Blocked) => (),
                        Ok(..) => unreachable!(),
                        Err(err) => {
                            error!("Coroutine resume failed, {:?}", err);
                            Scheduler::finished(hdl);
                        }
                    }
                },
                None => {
                    if Scheduler::get().work_count() == 0 {
                        break;
                    }
                    if self.handler.slabs.count() == 0 {
                        thread::sleep_ms(100);
                    }
                }
            }
        }

        Ok(())
    }
}

const MAX_TOKEN_NUM: usize = 102400;
impl IoHandler {
    fn new() -> IoHandler {
        IoHandler {
            slabs: Slab::new(MAX_TOKEN_NUM),
        }
    }
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
impl Processor {
    pub fn wait_event<E: Evented + AsRawFd>(&mut self, fd: &E, interest: Interest) -> io::Result<()> {
        let token = self.handler.slabs.insert((Coroutine::current().clone(), From::from(fd.as_raw_fd()))).unwrap();
        try!(self.event_loop.register_opt(fd, token, interest,
                                         PollOpt::level()|PollOpt::oneshot()));

        debug!("wait_event: Blocked current Coroutine ...; token={:?}", token);
        Coroutine::block();
        debug!("wait_event: Waked up; token={:?}", token);

        Ok(())
    }
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
struct IoHandler {
    slabs: Slab<(Handle, Io)>,
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
impl Handler for IoHandler {
    type Timeout = ();
    type Message = ();

    fn writable(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {

        debug!("In writable, token {:?}", token);

        match self.slabs.remove(token) {
            Some((hdl, fd)) => {
                // Linux EPoll needs to explicit EPOLL_CTL_DEL the fd
                event_loop.deregister(&fd).unwrap();
                mem::forget(fd);
                Scheduler::current().ready(hdl);
            },
            None => {
                warn!("No coroutine is waiting on writable {:?}", token);
            }
        }

    }

    fn readable(&mut self, event_loop: &mut EventLoop<Self>, token: Token, hint: ReadHint) {

        debug!("In readable, token {:?}, hint {:?}", token, hint);

        match self.slabs.remove(token) {
            Some((hdl, fd)) => {
                // Linux EPoll needs to explicit EPOLL_CTL_DEL the fd
                event_loop.deregister(&fd).unwrap();
                mem::forget(fd);
                Scheduler::current().ready(hdl);
            },
            None => {
                warn!("No coroutine is waiting on readable {:?}", token);
            }
        }

    }
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "openbsd"))]
impl Processor {
    pub fn wait_event<E: Evented>(&mut self, fd: &E, interest: Interest) -> io::Result<()> {
        let token = self.handler.slabs.insert(Coroutine::current().clone()).unwrap();
        try!(self.event_loop.register_opt(fd, token, interest,
                                         PollOpt::level()|PollOpt::oneshot()));

        debug!("wait_event: Blocked current Coroutine ...; token={:?}", token);
        Coroutine::block();
        debug!("wait_event: Waked up; token={:?}", token);

        Ok(())
    }
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "openbsd"))]
struct IoHandler {
    slabs: Slab<Handle>,
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "openbsd"))]
impl Handler for IoHandler {
    type Timeout = ();
    type Message = ();

    fn writable(&mut self, _: &mut EventLoop<Self>, token: Token) {

        debug!("In writable, token {:?}", token);

        match self.slabs.remove(token) {
            Some(hdl) => {
                Scheduler::ready(hdl);
            },
            None => {
                warn!("No coroutine is waiting on writable {:?}", token);
            }
        }

    }

    fn readable(&mut self, _: &mut EventLoop<Self>, token: Token, hint: ReadHint) {

        debug!("In readable, token {:?}, hint {:?}", token, hint);

        match self.slabs.remove(token) {
            Some(hdl) => {
                Scheduler::ready(hdl);
            },
            None => {
                warn!("No coroutine is waiting on readable {:?}", token);
            }
        }

    }
}
<commit_msg>fixed build error on linux<commit_after>use std::cell::UnsafeCell;
use std::io;
#[cfg(target_os = "linux")]
use std::os::unix::io::AsRawFd;
#[cfg(target_os = "linux")]
use std::convert::From;
use std::sync::Arc;
use std::thread;
#[cfg(target_os = "linux")]
use std::mem;

use coroutine::{State, Handle, Coroutine};

use mio::{EventLoop, Evented, Handler, Token, ReadHint, Interest, PollOpt};
use mio::util::Slab;
#[cfg(target_os = "linux")]
use mio::Io;

use mio::util::BoundedQueue;

use scheduler::Scheduler;

thread_local!(static PROCESSOR: UnsafeCell<Processor> = UnsafeCell::new(Processor::new()));

pub struct Processor {
    event_loop: EventLoop<IoHandler>,
    work_queue: Arc<BoundedQueue<Handle>>,
    handler: IoHandler,
}

impl Processor {
    pub fn new() -> Processor {
        Processor {
            event_loop: EventLoop::new().unwrap(),
            work_queue: Scheduler::get().get_queue(),
            handler: IoHandler::new(),
        }
    }

    pub fn current() -> &'static mut Processor {
        PROCESSOR.with(|p| unsafe { &mut *p.get() })
    }

    pub fn schedule(&mut self) -> io::Result<()> {
        loop {
            if self.handler.slabs.count() != 0 {
                try!(self.event_loop.run_once(&mut self.handler));
            }

            match self.work_queue.pop() {
                Some(hdl) => {
                    match hdl.resume() {
                        Ok(State::Suspended) => {
                            Scheduler::ready(hdl);
                        },
                        Ok(State::Finished) | Ok(State::Panicked) => {
                            Scheduler::finished(hdl);
                        },
                        Ok(State::Blocked) => (),
                        Ok(..) => unreachable!(),
                        Err(err) => {
                            error!("Coroutine resume failed, {:?}", err);
                            Scheduler::finished(hdl);
                        }
                    }
                },
                None => {
                    if Scheduler::get().work_count() == 0 {
                        break;
                    }
                    if self.handler.slabs.count() == 0 {
                        thread::sleep_ms(100);
                    }
                }
            }
        }

        Ok(())
    }
}

const MAX_TOKEN_NUM: usize = 102400;
impl IoHandler {
    fn new() -> IoHandler {
        IoHandler {
            slabs: Slab::new(MAX_TOKEN_NUM),
        }
    }
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
impl Processor {
    pub fn wait_event<E: Evented + AsRawFd>(&mut self, fd: &E, interest: Interest) -> io::Result<()> {
        let token = self.handler.slabs.insert((Coroutine::current().clone(), From::from(fd.as_raw_fd()))).unwrap();
        try!(self.event_loop.register_opt(fd, token, interest,
                                         PollOpt::level()|PollOpt::oneshot()));

        debug!("wait_event: Blocked current Coroutine ...; token={:?}", token);
        Coroutine::block();
        debug!("wait_event: Waked up; token={:?}", token);

        Ok(())
    }
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
struct IoHandler {
    slabs: Slab<(Handle, Io)>,
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
impl Handler for IoHandler {
    type Timeout = ();
    type Message = ();

    fn writable(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {

        debug!("In writable, token {:?}", token);

        match self.slabs.remove(token) {
            Some((hdl, fd)) => {
                // Linux EPoll needs to explicit EPOLL_CTL_DEL the fd
                event_loop.deregister(&fd).unwrap();
                mem::forget(fd);
                Scheduler::get().ready(hdl);
            },
            None => {
                warn!("No coroutine is waiting on writable {:?}", token);
            }
        }

    }

    fn readable(&mut self, event_loop: &mut EventLoop<Self>, token: Token, hint: ReadHint) {

        debug!("In readable, token {:?}, hint {:?}", token, hint);

        match self.slabs.remove(token) {
            Some((hdl, fd)) => {
                // Linux EPoll needs to explicit EPOLL_CTL_DEL the fd
                event_loop.deregister(&fd).unwrap();
                mem::forget(fd);
                Scheduler::get().ready(hdl);
            },
            None => {
                warn!("No coroutine is waiting on readable {:?}", token);
            }
        }

    }
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "openbsd"))]
impl Processor {
    pub fn wait_event<E: Evented>(&mut self, fd: &E, interest: Interest) -> io::Result<()> {
        let token = self.handler.slabs.insert(Coroutine::current().clone()).unwrap();
        try!(self.event_loop.register_opt(fd, token, interest,
                                         PollOpt::level()|PollOpt::oneshot()));

        debug!("wait_event: Blocked current Coroutine ...; token={:?}", token);
        Coroutine::block();
        debug!("wait_event: Waked up; token={:?}", token);

        Ok(())
    }
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "openbsd"))]
struct IoHandler {
    slabs: Slab<Handle>,
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "openbsd"))]
impl Handler for IoHandler {
    type Timeout = ();
    type Message = ();

    fn writable(&mut self, _: &mut EventLoop<Self>, token: Token) {

        debug!("In writable, token {:?}", token);

        match self.slabs.remove(token) {
            Some(hdl) => {
                Scheduler::ready(hdl);
            },
            None => {
                warn!("No coroutine is waiting on writable {:?}", token);
            }
        }

    }

    fn readable(&mut self, _: &mut EventLoop<Self>, token: Token, hint: ReadHint) {

        debug!("In readable, token {:?}, hint {:?}", token, hint);

        match self.slabs.remove(token) {
            Some(hdl) => {
                Scheduler::ready(hdl);
            },
            None => {
                warn!("No coroutine is waiting on readable {:?}", token);
            }
        }

    }
}
<|endoftext|>


<commit_before>//! Library service providers implementation.

extern crate hyper;

use hyper::client::{Client, Response};

/// Used to specify which provider to use to generate a short URL.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Provider {
    /// https://bn.gy provider
    BnGy,
    /// http://fifo.cc provider
    FifoCc,
    /// https://hec.su provider
    ///
    /// * Limited to 3000 API requests per day
    HecSu,
    /// https://is.gd provider
    IsGd,
    /// http://psbe.co provider
    PsbeCo,
    /// http://readbility.com provider
    Rdd,
    /// http://rlu.ru provider
    ///
    /// * Attention! If you send a lot of requests from one IP, it can be
    /// blocked. If you plan to add more then 100 URLs in one hour, please let
    /// the technical support know. Otherwise your IP can be blocked
    /// unexpectedly. Prior added URLs can be deleted.
    Rlu,
    /// http://tinyurl.com provider
    /// * Note: this service does not provide any API.
    /// The implementation result depends on the service result web page.
    TinyUrl,
    /// https://v.gd provider
    VGd,
}

impl Provider {
    /// Converts the Provider variant into its domain name equivilant
    pub fn to_name(&self) -> &str {
        match *self {
            Provider::BnGy => "bn.gy",
            Provider::FifoCc => "fifo.cc",
            Provider::HecSu => "hec.su",
            Provider::IsGd => "is.gd",
            Provider::PsbeCo => "psbe.co",
            Provider::Rdd => "readability.com",
            Provider::Rlu => "rlu.ru",
            Provider::TinyUrl => "tinyurl.com",
            Provider::VGd => "v.gd",
        }
    }
}

/// Returns a vector of all `Provider` variants.
///
/// The providers which are discouraged from use due to limitations such as
/// rate limitations are at the end of the resultant vector.
pub fn providers() -> Vec<Provider> {
    vec![
        Provider::IsGd,
        Provider::BnGy,
        Provider::VGd,
        Provider::Rdd,
        Provider::FifoCc,

        // The following list are items that are discouraged from use.
        // Reason: rate limit (3000 requests per day)
        Provider::HecSu,
        // Reason: does not provide an api
        Provider::TinyUrl,
        // Reason: unstable work
        Provider::PsbeCo,
        // Reason: rate limit (100 requests per hour)
        Provider::Rlu,
    ]
}

fn bngy_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortenedUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortenedUrl>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn bngy_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://bn.gy/API.asmx/CreateUrl?real_url={}", url))
        .send()
        .ok()
}

fn fifocc_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let value = string.split("\"shortner\"")
                      .nth(1).unwrap_or("")
                      .split(",").next().unwrap_or("")
                      .split("\"").nth(1);
    if let Some(string) = value {
        let mut short_url = string.to_owned();
        short_url = format!("http://fifo.cc/{}", short_url);
        Some(short_url)
    } else {
        None
    }
}

fn fifocc_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://fifo.cc/api/v2?url={}", url))
        .send()
        .ok()
}

fn hecsu_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<short>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</short>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn hecsu_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://hec.su/api?url={}&method=xml", url))
        .send()
        .ok()
}

fn isgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn isgd_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://is.gd/create.php?format=simple&url={}", url))
        .send()
        .ok()
}

fn psbeco_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortUrl>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn psbeco_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://psbe.co/API.asmx/CreateUrl?real_url={}", url))
        .send()
        .ok()
}

fn rdd_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let value = string.split("\"rdd_url\"")
                      .nth(1).unwrap_or("")
                      .split(",").next().unwrap_or("")
                      .split("\"").nth(1);
    if let Some(string) = value {
        let mut short_url = string.to_owned();
        let _ = short_url.pop();
        Some(short_url)
    } else {
        None
    }
}

fn rdd_request(url: &str, client: &Client) -> Option<Response> {
    client.post("https://readability.com/api/shortener/v1/urls")
        .body(&format!("url={}", url))
        .send()
        .ok()
}

fn rlu_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn rlu_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://rlu.ru/index.sema?a=api&link={}", url))
        .send()
        .ok()
}

fn tinyurl_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let value = string.split("data-clipboard-text=\"")
                      .nth(1).unwrap_or("")
                      .split("\">").next();
    if let Some(string) = value {
        Some(string.to_owned())
    } else {
        None
    }
}

fn tinyurl_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://tinyurl.com/create.php?url={}", url))
        .send()
        .ok()
}

fn vgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn vgd_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://v.gd/create.php?format=simple&url={}", url))
        .send()
        .ok()
}

/// Parses the response from a successful request to a provider into the
/// URL-shortened string.
pub fn parse(res: &str, provider: Provider) -> Option<String> {
    match provider {
        Provider::BnGy => bngy_parse(res),
        Provider::FifoCc => fifocc_parse(res),
        Provider::HecSu => hecsu_parse(res),
        Provider::IsGd => isgd_parse(res),
        Provider::PsbeCo => psbeco_parse(res),
        Provider::Rdd => rdd_parse(res),
        Provider::Rlu => rlu_parse(res),
        Provider::TinyUrl => tinyurl_parse(res),
        Provider::VGd => vgd_parse(res),
    }
}

/// Performs a request to the short link provider.
/// Response to be parsed or `None` on a error.
pub fn request(url: &str, client: &Client, provider: Provider) -> Option<Response> {
    match provider {
        Provider::BnGy => bngy_request(url, client),
        Provider::FifoCc => fifocc_request(url, client),
        Provider::HecSu => hecsu_request(url, client),
        Provider::IsGd => isgd_request(url, client),
        Provider::PsbeCo => psbeco_request(url, client),
        Provider::Rdd => rdd_request(url, client),
        Provider::Rlu => rlu_request(url, client),
        Provider::TinyUrl => tinyurl_request(url, client),
        Provider::VGd => vgd_request(url, client),
    }
}
<commit_msg>NowLinks provider implemented<commit_after>//! Library service providers implementation.

extern crate hyper;

use hyper::client::{Client, Response};

/// Used to specify which provider to use to generate a short URL.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Provider {
    /// https://bn.gy provider
    BnGy,
    /// http://fifo.cc provider
    FifoCc,
    /// https://hec.su provider
    ///
    /// * Limited to 3000 API requests per day
    HecSu,
    /// https://is.gd provider
    IsGd,
    /// http://nowlinks.net provider
    NowLinks,
    /// http://psbe.co provider
    PsbeCo,
    /// http://readbility.com provider
    Rdd,
    /// http://rlu.ru provider
    ///
    /// * Attention! If you send a lot of requests from one IP, it can be
    /// blocked. If you plan to add more then 100 URLs in one hour, please let
    /// the technical support know. Otherwise your IP can be blocked
    /// unexpectedly. Prior added URLs can be deleted.
    Rlu,
    /// http://tinyurl.com provider
    /// * Note: this service does not provide any API.
    /// The implementation result depends on the service result web page.
    TinyUrl,
    /// https://v.gd provider
    VGd,
}

impl Provider {
    /// Converts the Provider variant into its domain name equivilant
    pub fn to_name(&self) -> &str {
        match *self {
            Provider::BnGy => "bn.gy",
            Provider::FifoCc => "fifo.cc",
            Provider::HecSu => "hec.su",
            Provider::IsGd => "is.gd",
            Provider::NowLinks => "nowlinks.net",
            Provider::PsbeCo => "psbe.co",
            Provider::Rdd => "readability.com",
            Provider::Rlu => "rlu.ru",
            Provider::TinyUrl => "tinyurl.com",
            Provider::VGd => "v.gd",
        }
    }
}

/// Returns a vector of all `Provider` variants.
///
/// The providers which are discouraged from use due to limitations such as
/// rate limitations are at the end of the resultant vector.
pub fn providers() -> Vec<Provider> {
    vec![
        Provider::IsGd,
        Provider::BnGy,
        Provider::VGd,
        Provider::Rdd,
        Provider::FifoCc,

        // The following list are items that are discouraged from use.
        // Reason: rate limit (3000 requests per day)
        Provider::HecSu,
        // Reason: does not provide an api
        Provider::TinyUrl,
        // Reason: unstable work
        Provider::PsbeCo,
        // Reason: rate limit (100 requests per hour)
        Provider::Rlu,

        // The following list are items that show previews instead of direct links.
        Provider::NowLinks,
    ]
}

fn bngy_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortenedUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortenedUrl>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn bngy_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://bn.gy/API.asmx/CreateUrl?real_url={}", url))
        .send()
        .ok()
}

fn fifocc_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let value = string.split("\"shortner\"")
                      .nth(1).unwrap_or("")
                      .split(",").next().unwrap_or("")
                      .split("\"").nth(1);
    if let Some(string) = value {
        let mut short_url = string.to_owned();
        short_url = format!("http://fifo.cc/{}", short_url);
        Some(short_url)
    } else {
        None
    }
}

fn fifocc_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://fifo.cc/api/v2?url={}", url))
        .send()
        .ok()
}

fn hecsu_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<short>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</short>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn hecsu_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://hec.su/api?url={}&method=xml", url))
        .send()
        .ok()
}

fn isgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn isgd_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://is.gd/create.php?format=simple&url={}", url))
        .send()
        .ok()
}

fn nowlinks_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn nowlinks_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://nowlinks.net/api?url={}", url))
        .send()
        .ok()
}

fn psbeco_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortUrl>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn psbeco_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://psbe.co/API.asmx/CreateUrl?real_url={}", url))
        .send()
        .ok()
}

fn rdd_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let value = string.split("\"rdd_url\"")
                      .nth(1).unwrap_or("")
                      .split(",").next().unwrap_or("")
                      .split("\"").nth(1);
    if let Some(string) = value {
        let mut short_url = string.to_owned();
        let _ = short_url.pop();
        Some(short_url)
    } else {
        None
    }
}

fn rdd_request(url: &str, client: &Client) -> Option<Response> {
    client.post("https://readability.com/api/shortener/v1/urls")
        .body(&format!("url={}", url))
        .send()
        .ok()
}

fn rlu_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn rlu_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://rlu.ru/index.sema?a=api&link={}", url))
        .send()
        .ok()
}

fn tinyurl_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let value = string.split("data-clipboard-text=\"")
                      .nth(1).unwrap_or("")
                      .split("\">").next();
    if let Some(string) = value {
        Some(string.to_owned())
    } else {
        None
    }
}

fn tinyurl_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://tinyurl.com/create.php?url={}", url))
        .send()
        .ok()
}

fn vgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn vgd_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://v.gd/create.php?format=simple&url={}", url))
        .send()
        .ok()
}

/// Parses the response from a successful request to a provider into the
/// URL-shortened string.
pub fn parse(res: &str, provider: Provider) -> Option<String> {
    match provider {
        Provider::BnGy => bngy_parse(res),
        Provider::FifoCc => fifocc_parse(res),
        Provider::HecSu => hecsu_parse(res),
        Provider::IsGd => isgd_parse(res),
        Provider::NowLinks => nowlinks_parse(res),
        Provider::PsbeCo => psbeco_parse(res),
        Provider::Rdd => rdd_parse(res),
        Provider::Rlu => rlu_parse(res),
        Provider::TinyUrl => tinyurl_parse(res),
        Provider::VGd => vgd_parse(res),
    }
}

/// Performs a request to the short link provider.
/// Response to be parsed or `None` on a error.
pub fn request(url: &str, client: &Client, provider: Provider) -> Option<Response> {
    match provider {
        Provider::BnGy => bngy_request(url, client),
        Provider::FifoCc => fifocc_request(url, client),
        Provider::HecSu => hecsu_request(url, client),
        Provider::IsGd => isgd_request(url, client),
        Provider::NowLinks => nowlinks_request(url, client),
        Provider::PsbeCo => psbeco_request(url, client),
        Provider::Rdd => rdd_request(url, client),
        Provider::Rlu => rlu_request(url, client),
        Provider::TinyUrl => tinyurl_request(url, client),
        Provider::VGd => vgd_request(url, client),
    }
}
<|endoftext|>


<commit_before>extern crate rustbox;

use cursor::Direction;
use buffer::Buffer;
use cursor::Cursor;
use uibuf::UIBuffer;

use utils;

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer<'v>,
    pub top_line_num: uint,
    pub cursor: Cursor<'v>,

    uibuf: UIBuffer,
    threshold: int,
}

impl<'v> View<'v> {
    pub fn new(path: Option<String>) -> View<'v> {
        let buffer = match path {
            Some(s) => Buffer::new_from_file(&Path::new(s)),
            None    => Buffer::new_empty(),
        };
        //buffer = Buffer::new_from_file(path);

        let uibuf = UIBuffer::new();
        let mut cursor = Cursor::new();
        cursor.set_line(Some(&buffer.lines[0]));

        View {
            buffer: buffer,
            top_line_num: 0,
            cursor: cursor,
            uibuf: uibuf,
            threshold: 5,
        }
    }

    /// Get the height of the view in which content can be drawn
    ///
    /// Excludes the status bar height
    pub fn get_internal_height(&self) -> uint {
        let term_height = utils::get_term_height();

        term_height - 2
    }

    pub fn clear(&mut self) {
        self.uibuf.fill(' ');
    }

    pub fn draw(&mut self) {
        let height = self.get_internal_height();

        let num_lines = self.buffer.lines.len();
        let lines_to_draw = self.buffer.lines.slice(self.top_line_num, num_lines);

        for (index, line) in lines_to_draw.iter().enumerate() {
            if index <= height {
                let ln = line.borrow();
                let data = ln.data.clone();
                for (ch_index, ch) in data.into_bytes().iter().enumerate() {
                    self.uibuf.update_cell_content(ch_index, index, *ch as char);
                }
            }
        }
        self.uibuf.draw_range(0, height+1);
    }

    pub fn draw_status(&mut self) {
        let buffer_status = self.buffer.get_status_text();
        let cursor_status = self.cursor.get_status_text();
        let status_text = format!("{} {}", buffer_status, cursor_status).into_bytes();
        let status_text_len = status_text.len();
        let term_height = utils::get_term_height();
        let term_width = utils::get_term_width();

        for index in range(0, term_width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, term_height-1, ch, rustbox::Color::Black, rustbox::Color::Blue);
        }

        self.uibuf.draw_range(term_height-1, term_height);
    }

    pub fn draw_cursor(&self) {
        let offset = self.cursor.get_offset();
        let linenum = self.cursor.get_linenum();

        utils::draw_cursor(offset, linenum-self.top_line_num);
    }

    pub fn move_cursor(&mut self, direction: Direction) {
        match direction {
            Direction::Up    => { self.move_cursor_up(); },
            Direction::Down  => { self.move_cursor_down(); },
            Direction::Right => { self.cursor.move_right(); },
            Direction::Left  => { self.cursor.move_left(); },
        }
    }

    // TODO(greg): refactor this method with move_cursor_down
    pub fn move_cursor_up(&mut self) {
        let cursor_linenum = self.cursor.get_linenum();
        let prev_linenum = cursor_linenum - 1;

        let num_lines = self.buffer.lines.len() - 1;
        if prev_linenum > num_lines { return }

        {
            let line = &self.buffer.lines[prev_linenum];
            self.cursor.set_line(Some(line));
        }

        let cursor_linenum = self.cursor.get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;

        if cursor_offset < self.threshold {
            let times = cursor_offset - self.threshold;
            self.move_top_line_n_times(times);
        }

    }

    // TODO(greg): refactor this method with move_cursor_up
    pub fn move_cursor_down(&mut self) {
        let cursor_linenum = self.cursor.get_linenum();
        let next_linenum = cursor_linenum + 1;

        let num_lines = self.buffer.lines.len() - 1;
        if next_linenum > num_lines { return }

        {
            let line = &self.buffer.lines[next_linenum];
            self.cursor.set_line(Some(line));
        }

        let cursor_linenum = self.cursor.get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;
        let height = self.get_internal_height() as int;

        // TODO(greg) move this value
        // let threshold: int = 5;

        if cursor_offset >= (height - self.threshold) {
            let times = cursor_offset - (height - self.threshold) + 1;
            self.move_top_line_n_times(times);
        }
    }

    fn move_top_line_n_times(&mut self, mut num_times: int) {
        if num_times == 0 { return }

        // moving down
        if num_times > 0 {
            while num_times > 0 {
                self.top_line_num += 1;
                num_times -= 1;
            }
            return
        }

        // moving up
        if num_times < 0 {
            while num_times < 0 {
                if self.top_line_num == 0 { return }
                self.top_line_num -= 1;
                num_times += 1;
            }
            return
        }
    }

    pub fn delete_char(&mut self, direction: Direction) {
        let (offset, line_num) = self.cursor.get_position();

        if offset == 0 && direction.is_left() {
            let offset = self.buffer.join_line_with_previous(offset, line_num);
            self.move_cursor_up();
            self.cursor.set_offset(offset);
            return
        }

        let line_len = self.cursor.get_line_length();
        if offset == line_len && direction.is_right() {
            self.buffer.join_line_with_previous(offset, line_num+1);
            return
        }

        match direction {
            Direction::Left  => self.cursor.delete_backward_char(),
            Direction::Right => self.cursor.delete_forward_char(),
            _                => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0i, 4) {
            self.insert_char(' ');
        }
    }

    pub fn insert_char(&mut self, ch: char) {
        self.cursor.insert_char(ch);
    }

    pub fn insert_line(&mut self) {
        let (offset, line_num) = self.cursor.get_position();
        self.buffer.insert_line(offset, line_num);

        self.move_cursor_down();
        self.cursor.set_offset(0);
    }
}

#[cfg(test)]
mod tests {

    use std::cell::RefCell;

    use buffer::{Line, Buffer};
    use cursor::{Cursor, Direction};
    use view::View;
    use uibuf::UIBuffer;
    use utils;

    fn setup_view<'v>() -> View<'v> {
        let mut view = View {
            buffer: Buffer::new(),
            top_line_num: 0,
            cursor: Cursor::new(),
            uibuf: UIBuffer::new(),
            threshold: 5,
        };

        let first_line = RefCell::new(Line::new("test".to_string(), 0));
        let second_line = RefCell::new(Line::new("second".to_string(), 1));

        view.buffer.lines = vec!(first_line, second_line);
        view.cursor.set_line(Some(&view.buffer.lines[0]));

        return view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view();
        view.move_cursor_down();

        assert_eq!(view.cursor.get_linenum(), 1);
        assert_eq!(view.cursor.get_line().borrow().data, "second".to_string());
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.move_cursor_up();
        assert_eq!(view.cursor.get_linenum(), 0);
        assert_eq!(view.cursor.get_line().borrow().data, "test".to_string());
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view();
        view.cursor.move_right();
        view.insert_line();

        assert_eq!(view.buffer.lines.len(), 3);
        assert_eq!(view.cursor.get_offset(), 0);
        assert_eq!(view.cursor.get_line().borrow().linenum, 1);
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view();
        view.insert_char('t');

        assert_eq!(view.cursor.get_line().borrow().data, "ttest".to_string());
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view();
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor.get_line().borrow().data, "est".to_string());
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view();
        view.cursor.move_right();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor.get_line().borrow().data, "est".to_string());
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor.get_line().borrow().data, "testsecond".to_string());
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view();
        view.cursor.set_offset(4);
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor.get_line().borrow().data, "testsecond".to_string());
    }

    #[test]
    fn test_get_internal_height() {
        let view = setup_view();
        let term_height = utils::get_term_height();
        assert_eq!(view.get_internal_height(), term_height - 2);
    }
}
<commit_msg>Remove commented code<commit_after>extern crate rustbox;

use cursor::Direction;
use buffer::Buffer;
use cursor::Cursor;
use uibuf::UIBuffer;

use utils;

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer<'v>,
    pub top_line_num: uint,
    pub cursor: Cursor<'v>,

    uibuf: UIBuffer,
    threshold: int,
}

impl<'v> View<'v> {
    pub fn new(path: Option<String>) -> View<'v> {
        let buffer = match path {
            Some(s) => Buffer::new_from_file(&Path::new(s)),
            None    => Buffer::new_empty(),
        };

        let uibuf = UIBuffer::new();
        let mut cursor = Cursor::new();
        cursor.set_line(Some(&buffer.lines[0]));

        View {
            buffer: buffer,
            top_line_num: 0,
            cursor: cursor,
            uibuf: uibuf,
            threshold: 5,
        }
    }

    /// Get the height of the view in which content can be drawn
    ///
    /// Excludes the status bar height
    pub fn get_internal_height(&self) -> uint {
        let term_height = utils::get_term_height();

        term_height - 2
    }

    pub fn clear(&mut self) {
        self.uibuf.fill(' ');
    }

    pub fn draw(&mut self) {
        let height = self.get_internal_height();

        let num_lines = self.buffer.lines.len();
        let lines_to_draw = self.buffer.lines.slice(self.top_line_num, num_lines);

        for (index, line) in lines_to_draw.iter().enumerate() {
            if index <= height {
                let ln = line.borrow();
                let data = ln.data.clone();
                for (ch_index, ch) in data.into_bytes().iter().enumerate() {
                    self.uibuf.update_cell_content(ch_index, index, *ch as char);
                }
            }
        }
        self.uibuf.draw_range(0, height+1);
    }

    pub fn draw_status(&mut self) {
        let buffer_status = self.buffer.get_status_text();
        let cursor_status = self.cursor.get_status_text();
        let status_text = format!("{} {}", buffer_status, cursor_status).into_bytes();
        let status_text_len = status_text.len();
        let term_height = utils::get_term_height();
        let term_width = utils::get_term_width();

        for index in range(0, term_width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, term_height-1, ch, rustbox::Color::Black, rustbox::Color::Blue);
        }

        self.uibuf.draw_range(term_height-1, term_height);
    }

    pub fn draw_cursor(&self) {
        let offset = self.cursor.get_offset();
        let linenum = self.cursor.get_linenum();

        utils::draw_cursor(offset, linenum-self.top_line_num);
    }

    pub fn move_cursor(&mut self, direction: Direction) {
        match direction {
            Direction::Up    => { self.move_cursor_up(); },
            Direction::Down  => { self.move_cursor_down(); },
            Direction::Right => { self.cursor.move_right(); },
            Direction::Left  => { self.cursor.move_left(); },
        }
    }

    // TODO(greg): refactor this method with move_cursor_down
    pub fn move_cursor_up(&mut self) {
        let cursor_linenum = self.cursor.get_linenum();
        let prev_linenum = cursor_linenum - 1;

        let num_lines = self.buffer.lines.len() - 1;
        if prev_linenum > num_lines { return }

        {
            let line = &self.buffer.lines[prev_linenum];
            self.cursor.set_line(Some(line));
        }

        let cursor_linenum = self.cursor.get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;

        if cursor_offset < self.threshold {
            let times = cursor_offset - self.threshold;
            self.move_top_line_n_times(times);
        }

    }

    // TODO(greg): refactor this method with move_cursor_up
    pub fn move_cursor_down(&mut self) {
        let cursor_linenum = self.cursor.get_linenum();
        let next_linenum = cursor_linenum + 1;

        let num_lines = self.buffer.lines.len() - 1;
        if next_linenum > num_lines { return }

        {
            let line = &self.buffer.lines[next_linenum];
            self.cursor.set_line(Some(line));
        }

        let cursor_linenum = self.cursor.get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;
        let height = self.get_internal_height() as int;

        // TODO(greg) move this value
        // let threshold: int = 5;

        if cursor_offset >= (height - self.threshold) {
            let times = cursor_offset - (height - self.threshold) + 1;
            self.move_top_line_n_times(times);
        }
    }

    fn move_top_line_n_times(&mut self, mut num_times: int) {
        if num_times == 0 { return }

        // moving down
        if num_times > 0 {
            while num_times > 0 {
                self.top_line_num += 1;
                num_times -= 1;
            }
            return
        }

        // moving up
        if num_times < 0 {
            while num_times < 0 {
                if self.top_line_num == 0 { return }
                self.top_line_num -= 1;
                num_times += 1;
            }
            return
        }
    }

    pub fn delete_char(&mut self, direction: Direction) {
        let (offset, line_num) = self.cursor.get_position();

        if offset == 0 && direction.is_left() {
            let offset = self.buffer.join_line_with_previous(offset, line_num);
            self.move_cursor_up();
            self.cursor.set_offset(offset);
            return
        }

        let line_len = self.cursor.get_line_length();
        if offset == line_len && direction.is_right() {
            self.buffer.join_line_with_previous(offset, line_num+1);
            return
        }

        match direction {
            Direction::Left  => self.cursor.delete_backward_char(),
            Direction::Right => self.cursor.delete_forward_char(),
            _                => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0i, 4) {
            self.insert_char(' ');
        }
    }

    pub fn insert_char(&mut self, ch: char) {
        self.cursor.insert_char(ch);
    }

    pub fn insert_line(&mut self) {
        let (offset, line_num) = self.cursor.get_position();
        self.buffer.insert_line(offset, line_num);

        self.move_cursor_down();
        self.cursor.set_offset(0);
    }
}

#[cfg(test)]
mod tests {

    use std::cell::RefCell;

    use buffer::{Line, Buffer};
    use cursor::{Cursor, Direction};
    use view::View;
    use uibuf::UIBuffer;
    use utils;

    fn setup_view<'v>() -> View<'v> {
        let mut view = View {
            buffer: Buffer::new(),
            top_line_num: 0,
            cursor: Cursor::new(),
            uibuf: UIBuffer::new(),
            threshold: 5,
        };

        let first_line = RefCell::new(Line::new("test".to_string(), 0));
        let second_line = RefCell::new(Line::new("second".to_string(), 1));

        view.buffer.lines = vec!(first_line, second_line);
        view.cursor.set_line(Some(&view.buffer.lines[0]));

        return view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view();
        view.move_cursor_down();

        assert_eq!(view.cursor.get_linenum(), 1);
        assert_eq!(view.cursor.get_line().borrow().data, "second".to_string());
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.move_cursor_up();
        assert_eq!(view.cursor.get_linenum(), 0);
        assert_eq!(view.cursor.get_line().borrow().data, "test".to_string());
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view();
        view.cursor.move_right();
        view.insert_line();

        assert_eq!(view.buffer.lines.len(), 3);
        assert_eq!(view.cursor.get_offset(), 0);
        assert_eq!(view.cursor.get_line().borrow().linenum, 1);
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view();
        view.insert_char('t');

        assert_eq!(view.cursor.get_line().borrow().data, "ttest".to_string());
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view();
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor.get_line().borrow().data, "est".to_string());
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view();
        view.cursor.move_right();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor.get_line().borrow().data, "est".to_string());
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor.get_line().borrow().data, "testsecond".to_string());
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view();
        view.cursor.set_offset(4);
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor.get_line().borrow().data, "testsecond".to_string());
    }

    #[test]
    fn test_get_internal_height() {
        let view = setup_view();
        let term_height = utils::get_term_height();
        assert_eq!(view.get_internal_height(), term_height - 2);
    }
}
<|endoftext|>


<commit_before>use bincode::{SizeLimit, serde as bincode};

#[macro_export]
macro_rules! serialize {
    ($e:expr) => {bincode::serialize($e, SizeLimit::Infinite).unwrap()};
}

#[macro_export]
macro_rules! deserialize {
    ($e:expr) => {bincode::deserialize($e).unwrap()};
}

#[macro_export]
macro_rules! dispatch_rpc_service_functions {
    ($s:ty) => {
        impl $crate::rpc::RPCService for $s {
            fn dispatch(&self, data: Vec<u8>) -> Result<Vec<u8>, $crate::rpc::RPCRequestError> {
                self.inner_dispatch(data)
            }
            fn register_shortcut_service(&self, service_ptr: usize, server_id: u64, service_id: u64) {
                let mut cbs = RPC_CALLBACKS.write();
                let service = unsafe {Arc::from_raw(service_ptr as *const $s)};
                cbs.insert((server_id, service_id), service);
            }
        }
    };
}

// this macro expansion design took credits from tarpc by Google Inc.
#[macro_export]
macro_rules! service {
    (
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) $(-> $out:ty)* $(| $error:ty)*;
        )*
    ) => {
        service! {{
            $(
                $(#[$attr])*
                rpc $fn_name( $( $arg : $in_ ),* ) $(-> $out)* $(| $error)*;
            )*
        }}
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ); // No return, no error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> () | ();
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty; //return, no error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out | ();
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) | $error:ty; //no return, error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> () | $error;
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty | $error:ty; //return, error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out | $error;
        }
    };
    (
        {} // all expanded
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident ( $( $arg:ident : $in_:ty ),* ) -> $out:ty | $error:ty;
        )*
    ) => {
        use std;
        use std::time::Duration;
        use bincode::{SizeLimit, serde as bincode};
        use std::sync::Arc;
        use std::io;
        use $crate::rpc::*;
        use $crate::utils::u8vec::*;
        use futures::Future;

        lazy_static! {
            pub static ref RPC_CALLBACKS:
            ::parking_lot::RwLock<::std::collections::BTreeMap<(u64, u64), Arc<Service>>>
            = ::parking_lot::RwLock::new(::std::collections::BTreeMap::new());
        }

        pub trait Service: RPCService {
           $(
                $(#[$attr])*
                fn $fn_name(&self, $($arg:$in_),*) -> std::result::Result<$out, $error>;
           )*
           fn inner_dispatch(&self, data: Vec<u8>) -> Result<Vec<u8>, RPCRequestError> {
               let (func_id, body) = extract_u64_head(data);
               match func_id as usize {
                   $(hash_ident!($fn_name) => {
                       let ($($arg,)*) : ($($in_,)*) = deserialize!(&body);
                       let f_result = self.$fn_name($($arg,)*);
                       Ok(serialize!(&f_result))
                   }),*
                   _ => {
                       Err(RPCRequestError::FunctionIdNotFound)
                   }
               }
           }

        }
        pub struct SyncServiceClient {
            pub service_id: u64,
            pub server_id: u64,
            pub client: Arc<RPCClient>,
        }
        impl SyncServiceClient {
           $(
                #[allow(non_camel_case_types)]
                $(#[$attr])*
                pub fn $fn_name(&self, $($arg:&$in_),*) -> Result<std::result::Result<$out, $error>, RPCError> {
                    let req_data = ($($arg,)*);
                    let req_data_bytes = serialize!(&req_data);
                    let req_bytes = prepend_u64(hash_ident!($fn_name) as u64, req_data_bytes);
                    let res_bytes = self.client.send(self.service_id, req_bytes);
                    if let Ok(res_bytes) = res_bytes {
                        Ok(deserialize!(res_bytes.as_slice()))
                    } else {
                        Err(res_bytes.err().unwrap())
                    }
                }
           )*
           pub fn new(service_id: u64, client: &Arc<RPCClient>) -> Arc<SyncServiceClient> {
                Arc::new(SyncServiceClient{
                    service_id: service_id,
                    server_id:client.server_id,
                    client: client.clone()
                })
           }
        }
        pub struct AsyncServiceClient {
            pub service_id: u64,
            pub server_id: u64,
            pub client: Arc<RPCClient>,
        }
        impl AsyncServiceClient {
           $(
                #[allow(non_camel_case_types)]
                $(#[$attr])*
                pub fn $fn_name(&self, $($arg:&$in_),*) -> Box<Future<Item = std::result::Result<$out, $error>, Error = RPCError>> {
                    let req_data = ($($arg,)*);
                    let req_data_bytes = serialize!(&req_data);
                    let req_bytes = prepend_u64(hash_ident!($fn_name) as u64, req_data_bytes);
                    let res_bytes = self.client.send_async(self.service_id, req_bytes);
                    Box::new(res_bytes.then(|res_bytes| -> Result<std::result::Result<$out, $error>, RPCError> {
                        if let Ok(res_bytes) = res_bytes {
                            Ok(deserialize!(res_bytes.as_slice()))
                        } else {
                            Err(res_bytes.err().unwrap())
                        }
                    }))
                }
           )*
           pub fn new(service_id: u64, client: &Arc<RPCClient>) -> Arc<SyncServiceClient> {
                Arc::new(SyncServiceClient{
                    service_id: service_id,
                    server_id:client.server_id,
                    client: client.clone()
                })
           }
        }
    }
}

mod syntax_test {
    service! {
        rpc test(a: u32, b: u32) -> bool;
        rpc test2(a: u32);
        rpc test3(a: u32, b: u32, c: u32, d: u32);
        rpc test4(a: u32, b: u32, c: u32, d: u32) -> bool | String;
        rpc test5(a: u32, b: u32, c: u32, d: u32) | String;
    }
}

#[cfg(test)]
mod struct_test {

    #[derive(Serialize, Deserialize, Debug)]
    pub struct a {
        b: u32,
        d: u64,
        e: String,
        f: f32
    }

    service! {
        rpc test(a: a, b: u32) -> bool;
    }
}
<commit_msg>stash for switch workspace<commit_after>use bincode::{SizeLimit, serde as bincode};

#[macro_export]
macro_rules! serialize {
    ($e:expr) => {bincode::serialize($e, SizeLimit::Infinite).unwrap()};
}

#[macro_export]
macro_rules! deserialize {
    ($e:expr) => {bincode::deserialize($e).unwrap()};
}

#[macro_export]
macro_rules! dispatch_rpc_service_functions {
    ($s:ty) => {
        impl $crate::rpc::RPCService for $s {
            fn dispatch(&self, data: Vec<u8>) -> Result<Vec<u8>, $crate::rpc::RPCRequestError> {
                self.inner_dispatch(data)
            }
            fn register_shortcut_service(&self, service_ptr: usize, server_id: u64, service_id: u64) {
                let mut cbs = RPC_SVRS.write();
                let service = unsafe {Arc::from_raw(service_ptr as *const $s)};
                cbs.insert((server_id, service_id), service);
            }
        }
    };
}

// this macro expansion design took credits from tarpc by Google Inc.
#[macro_export]
macro_rules! service {
    (
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) $(-> $out:ty)* $(| $error:ty)*;
        )*
    ) => {
        service! {{
            $(
                $(#[$attr])*
                rpc $fn_name( $( $arg : $in_ ),* ) $(-> $out)* $(| $error)*;
            )*
        }}
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ); // No return, no error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> () | ();
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty; //return, no error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out | ();
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) | $error:ty; //no return, error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> () | $error;
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty | $error:ty; //return, error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out | $error;
        }
    };
    (
        {} // all expanded
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident ( $( $arg:ident : $in_:ty ),* ) -> $out:ty | $error:ty;
        )*
    ) => {
        use std;
        use std::time::Duration;
        use bincode::{SizeLimit, serde as bincode};
        use std::sync::Arc;
        use std::io;
        use $crate::rpc::*;
        use $crate::utils::u8vec::*;
        use futures::Future;

        lazy_static! {
            pub static ref RPC_SVRS:
            ::parking_lot::RwLock<::std::collections::BTreeMap<(u64, u64), Arc<Service>>>
            = ::parking_lot::RwLock::new(::std::collections::BTreeMap::new());
        }

        pub trait Service: RPCService {
           $(
                $(#[$attr])*
                fn $fn_name(&self, $($arg:$in_),*) -> std::result::Result<$out, $error>;
           )*
           fn inner_dispatch(&self, data: Vec<u8>) -> Result<Vec<u8>, RPCRequestError> {
               let (func_id, body) = extract_u64_head(data);
               match func_id as usize {
                   $(hash_ident!($fn_name) => {
                       let ($($arg,)*) : ($($in_,)*) = deserialize!(&body);
                       let f_result = self.$fn_name($($arg,)*);
                       Ok(serialize!(&f_result))
                   }),*
                   _ => {
                       Err(RPCRequestError::FunctionIdNotFound)
                   }
               }
           }
        }
        pub struct SyncServiceClient {
            pub service_id: u64,
            pub server_id: u64,
            pub client: Arc<RPCClient>,
        }
        impl SyncServiceClient {
           $(
                #[allow(non_camel_case_types)]
                $(#[$attr])*
                pub fn $fn_name(&self, $($arg:&$in_),*) -> Result<std::result::Result<$out, $error>, RPCError> {
                    let local_svr = {
                        let svrs = RPC_SVRS.read();
                        match svrs.get(&(self.server_id, self.service_id)) {
                            Some(s) => Some(s.clone()),
                            _ => None
                        }
                    };
                    if let Some(local) = local_svr {
                        Ok(local.$fn_name($($arg.clone()),*))
                    } else {
                        let req_data = ($($arg,)*);
                        let req_data_bytes = serialize!(&req_data);
                        let req_bytes = prepend_u64(hash_ident!($fn_name) as u64, req_data_bytes);
                        let res_bytes = self.client.send(self.service_id, req_bytes);
                        if let Ok(res_bytes) = res_bytes {
                            Ok(deserialize!(res_bytes.as_slice()))
                        } else {
                            Err(res_bytes.err().unwrap())
                        }
                    }
                }
           )*
           pub fn new(service_id: u64, client: &Arc<RPCClient>) -> Arc<SyncServiceClient> {
                Arc::new(SyncServiceClient{
                    service_id: service_id,
                    server_id:client.server_id,
                    client: client.clone()
                })
           }
        }
        pub struct AsyncServiceClient {
            pub service_id: u64,
            pub server_id: u64,
            pub client: Arc<RPCClient>,
        }
        impl AsyncServiceClient {
           $(
                #[allow(non_camel_case_types)]
                $(#[$attr])*
                pub fn $fn_name(&self, $($arg:&$in_),*) -> Box<Future<Item = std::result::Result<$out, $error>, Error = RPCError>> {
                    let req_data = ($($arg,)*);
                    let req_data_bytes = serialize!(&req_data);
                    let req_bytes = prepend_u64(hash_ident!($fn_name) as u64, req_data_bytes);
                    let res_bytes = self.client.send_async(self.service_id, req_bytes);
                    Box::new(res_bytes.then(|res_bytes| -> Result<std::result::Result<$out, $error>, RPCError> {
                        if let Ok(res_bytes) = res_bytes {
                            Ok(deserialize!(res_bytes.as_slice()))
                        } else {
                            Err(res_bytes.err().unwrap())
                        }
                    }))
                }
           )*
           pub fn new(service_id: u64, client: &Arc<RPCClient>) -> Arc<SyncServiceClient> {
                Arc::new(SyncServiceClient{
                    service_id: service_id,
                    server_id:client.server_id,
                    client: client.clone()
                })
           }
        }
    }
}

mod syntax_test {
    service! {
        rpc test(a: u32, b: u32) -> bool;
        rpc test2(a: u32);
        rpc test3(a: u32, b: u32, c: u32, d: u32);
        rpc test4(a: u32, b: u32, c: u32, d: u32) -> bool | String;
        rpc test5(a: u32, b: u32, c: u32, d: u32) | String;
    }
}

#[cfg(test)]
mod struct_test {

    #[derive(Serialize, Deserialize, Debug)]
    pub struct a {
        b: u32,
        d: u64,
        e: String,
        f: f32
    }

    service! {
        rpc test(a: a, b: u32) -> bool;
    }
}
<|endoftext|>


<commit_before>extern crate regex;

mod matching;
mod support;
mod tokens;
mod lexer;
mod files;
mod parser;

use std::vec::Vec;
use tokens::*;
use lexer::*;
use parser::*;

fn main()
{
    let source_file = "sampleData/BasicArithmatic.java";
    let lex_output_file = "sampleData/output/stable/BasicArithmatic.java.lexed";
    let preprocessed_output_file = "sampleData/output/stable/BasicArithmatic.java.preprocessed";

    let mut tokens: Vec<Token> = lex_file(source_file);

    println!("\n\nFound Tokens:");
    tokens.print_to(lex_output_file, true);

    remove_meta(&mut tokens);
    println!("\n\nPerged Tokens:");
    tokens.print_to(preprocessed_output_file, true);

    if tokens[0].value != "class"
    {
        panic!("Unexpected token: {}: {}", tokens[0].value, tokens[0].name);
    }

    let (last_index, asm_string) = compile_class(&tokens, 1);
}

fn compile_class(tokens: &Vec<Token>, start_index: usize) -> (usize, String)
{
    let invalid_types = get_invalid_token_types();
    let invalid_values = get_invalid_token_values();

    let mut plp_string: String = String::new();
    let mut current_index: usize = start_index;

    if tokens[current_index].value != "{" { panic!("Expected '{{' received: {}", tokens[current_index].value); }
    else { current_index += 1; }

    for (index, token) in tokens.iter().enumerate()
    {
        // Handle forward skipping
        if index < current_index { continue; }
        else { current_index = index; }

        // TODO: encapsulate into token_rules.validate(token)
        // Panic! if token type is invalid
        if invalid_types.contains(&token.name)
        {
            panic!("Unsupported token type: {}", token.name);
        }
        // Panic! if token value is invalid
        else if invalid_values.contains(&&*token.value)
        {
            panic!("Unsupported token value: {}", token.value);
        }

        if token.value == "class"
        {
            // parse class body
            let (end_index, compiled_class) = compile_class(&tokens, index + 1);
            plp_string.push_str(&*compiled_class);

            current_index = end_index;
        }
        else if token.name == "type" // || token.name == "identifier"
        {
            // look ahead
            // parse variable declaration
            // OR parse method declaration
        }
        else if token.value == "if"
        {
            // parse if body
            // Unsupported for now
        }
        else if token.name == "construct.conditional"
        {
            // parse conditional
            // Unsupported for now
        }
        else
        {
            panic!("Unexpected token: {}\t{}", token.name, token.value);
        }
    }

    (current_index + 1, plp_string)
}

fn remove_meta(tokens: &mut Vec<Token>)
{
    // Indecies of tokens vector to be removed
    let mut invalid_indecies: Vec<usize> = Vec::new();

    let mut min_index: usize = 0;
    for (index, token) in tokens.iter().enumerate()
    {
        // Allow forward skipping (by setting min_index)
        if index < min_index
        {
            invalid_indecies.push(index);
        }
        // Remove imports
        else if token.name == "special.import"
        {
            invalid_indecies.push(index);
            min_index = index + 2; // skip the next token (semi-colon)
        }
        // Remove comments
        else if token.name.starts_with("comment")
        {
            invalid_indecies.push(index);
        }
        // Remove all modifiers (public, private, volatile, transient, static, etc.)
        else if token.name.starts_with("mod")
        {
            invalid_indecies.push(index);
        }
        // Remove package declarations
        else if token.name == "special.package"
        {
            invalid_indecies.push(index);
            min_index = find_next_semicolon(tokens, index) + 1;
        }
    }

    // count := how many indecies have already been removed
    // index := the index in the original tokens vector that should be removed
    for (count, index) in invalid_indecies.iter().enumerate()
    {
        // "index" refers to the index before any others were removed. Therefore, it must be offset by the number of removed tokens
        tokens.remove(index - count);
    }
}

fn find_next_semicolon(tokens: &Vec<Token>, start: usize) -> usize
{
    for (index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == ";" { return index + start; }
    }

    return 0;
}
<commit_msg>Remove Package and Static Purging<commit_after>extern crate regex;

mod matching;
mod support;
mod tokens;
mod lexer;
mod files;
mod parser;

use std::vec::Vec;
use tokens::*;
use lexer::*;
use parser::*;

fn main()
{
    let source_file = "sampleData/BasicArithmatic.java";
    let lex_output_file = "sampleData/output/stable/BasicArithmatic.java.lexed";
    let preprocessed_output_file = "sampleData/output/stable/BasicArithmatic.java.preprocessed";

    let mut tokens: Vec<Token> = lex_file(source_file);

    println!("\n\nFound Tokens:");
    tokens.print_to(lex_output_file, true);

    remove_meta(&mut tokens);
    println!("\n\nPerged Tokens:");
    tokens.print_to(preprocessed_output_file, true);

    if tokens[0].value != "class"
    {
        panic!("Unexpected token: {}: {}", tokens[0].value, tokens[0].name);
    }

    let (last_index, asm_string) = compile_class(&tokens, 1);
}

fn compile_class(tokens: &Vec<Token>, start_index: usize) -> (usize, String)
{
    let invalid_types = get_invalid_token_types();
    let invalid_values = get_invalid_token_values();

    let mut plp_string: String = String::new();
    let mut current_index: usize = start_index;

    if tokens[current_index].value != "{" { panic!("Expected '{{' received: {}", tokens[current_index].value); }
    else { current_index += 1; }

    for (index, token) in tokens.iter().enumerate()
    {
        // Handle forward skipping
        if index < current_index { continue; }
        else { current_index = index; }

        // TODO: encapsulate into token_rules.validate(token)
        // Panic! if token type is invalid
        if invalid_types.contains(&token.name)
        {
            panic!("Unsupported token type: {}", token.name);
        }
        // Panic! if token value is invalid
        else if invalid_values.contains(&&*token.value)
        {
            panic!("Unsupported token value: {}", token.value);
        }

        if token.value == "class"
        {
            // parse class body
            let (end_index, compiled_class) = compile_class(&tokens, index + 1);
            plp_string.push_str(&*compiled_class);

            current_index = end_index;
        }
        else if token.name == "type" // || token.name == "identifier"
        {
            // look ahead
            // parse variable declaration
            // OR parse method declaration
        }
        else if token.value == "if"
        {
            // parse if body
            // Unsupported for now
        }
        else if token.name == "construct.conditional"
        {
            // parse conditional
            // Unsupported for now
        }
        else
        {
            panic!("Unexpected token: {}\t{}", token.name, token.value);
        }
    }

    (current_index + 1, plp_string)
}

fn remove_meta(tokens: &mut Vec<Token>)
{
    // Indecies of tokens vector to be removed
    let mut invalid_indecies: Vec<usize> = Vec::new();

    let mut min_index: usize = 0;
    for (index, token) in tokens.iter().enumerate()
    {
        // Allow forward skipping (by setting min_index)
        if index < min_index
        {
            invalid_indecies.push(index);
        }
        // Remove imports
        else if token.name == "special.import"
        {
            invalid_indecies.push(index);
            min_index = index + 2; // skip the next token (semi-colon)
        }
        // Remove comments
        else if token.name.starts_with("comment")
        {
            invalid_indecies.push(index);
        }
        // Remove all modifiers (public, private, volatile, transient, static, etc.)
        else if token.name.starts_with("mod")
        {
            if token.name.ends_with("access")
            {
                continue;
            }
            invalid_indecies.push(index);
        }
        // Remove package declarations
        else if token.name == "special.package"
        {
            if token.name.ends_with("package")
            {
                continue;
            }
            invalid_indecies.push(index);
            min_index = find_next_semicolon(tokens, index) + 1;
        }
    }

    // count := how many indecies have already been removed
    // index := the index in the original tokens vector that should be removed
    for (count, index) in invalid_indecies.iter().enumerate()
    {
        // "index" refers to the index before any others were removed. Therefore, it must be offset by the number of removed tokens
        tokens.remove(index - count);
    }
}

fn find_next_semicolon(tokens: &Vec<Token>, start: usize) -> usize
{
    for (index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == ";" { return index + start; }
    }

    return 0;
}
<|endoftext|>