<commit_before>use peer::{
  Peer,
  Shadow,
};

use std::io::{
  Write,
  Read,
  Result as IoResult,
  Cursor,
};
use rand::os::OsRng;
use rand::Rng;

use mydht_base::tunnel::{
  TunnelWriter,
  TunnelWriterExt,
  TunnelReader,
  TunnelReaderExt,
  TunnelMode,
  TunnelShadowMode,
  proxy_content,
  ErrorHandlingMode,
};

use readwrite_comp::{
  ExtRead,
  ExtWrite,
};
use peer::{
  PeerTest,
};
use transport::{
  LocalAdd,
};
use shadow::{
  ShadowTest,
  ShadowModeTest,
};
use mydht_base::bytes_wr::sized_windows::{
  SizedWindowsParams,
  SizedWindows,
};

#[derive(Clone)]
pub struct TestSizedWindows;

#[derive(Clone)]
pub struct TestSizedWindowsHead;
impl SizedWindowsParams for TestSizedWindowsHead {
    const INIT_SIZE : usize = 15;
    const GROWTH_RATIO : Option<(usize,usize)> = None;
    const WRITE_SIZE : bool = false;
    const SECURE_PAD : bool = false;
}

impl SizedWindowsParams for TestSizedWindows {
    const INIT_SIZE : usize = 45;
    const GROWTH_RATIO : Option<(usize,usize)> = Some((3,2));
    const WRITE_SIZE : bool = true;
    const SECURE_PAD : bool = false;
}

pub fn tunnel_test<P : Peer> (route : Vec<P>, input_length : usize, write_buffer_length : usize,
read_buffer_length : usize, tmode : TunnelMode,
shead : <<P as Peer>::Shadow as Shadow>::ShadowMode,
scont : <<P as Peer>::Shadow as Shadow>::ShadowMode,
)
where <<P as Peer>::Shadow as Shadow>::ShadowMode : Eq
{
  let route_len = route.len();

  let mut inputb = vec![0;input_length];
  OsRng::new().unwrap().fill_bytes(&mut inputb);
  let mut output = Cursor::new(Vec::new());
  let input = inputb;
  let vec_route : Vec<&P> = route.iter().map(|p|p).collect();
  // send message test
  {
    let mut tunn_we = TunnelWriterExt::new(
      &vec_route[..],
      SizedWindows::new(TestSizedWindows),
      tmode.clone(),
      None,
      shead.clone(),
      scont.clone(),
      None,// no specific reply route
    );

    let mut tunn_w = tunn_we.as_writer(&mut output);

    let mut ix = 0;
    while ix < input_length {
      if ix + write_buffer_length < input_length {
        ix += tunn_w.write(&input[ix..ix + write_buffer_length]).unwrap();
      } else {
        ix += tunn_w.write(&input[ix..]).unwrap();
      }
    }
    tunn_w.flush().unwrap();

  }

  // middle proxy message
  /*pub fn proxy_content<
  P : Peer,
  ER : ExtRead,
  R : Read,
  EW : ExtWrite,
  W : Write> (
  buf : &mut [u8],
  tre : &mut TunnelReaderExt<ER,P>,
  mut er : ER,
  mut ew : EW,
  r : &mut R,
  w : &mut W) -> Result<()> {
    {*/

  for i in 1 .. route_len - 1 {
    let mut readbuf = vec![0;read_buffer_length];

{
    let mut input_v = Cursor::new(output.into_inner());

    let mut tunn_r = TunnelReaderExt::new(route.get(i).unwrap(),SizedWindows::new(TestSizedWindows),None);
    //let mut tunn_r : TunnelReaderExt2<P,_> = TunnelReaderExt2::new(&mut input_v,&mut buf2[..],route.get(i).unwrap(),shead.clone(),scont.clone());

    assert!(tunn_r.is_dest() == None);
    tunn_r.read_header(&mut input_v).unwrap();
    assert!(tunn_r.is_dest() == Some(false));

    output = Cursor::new(Vec::new());

    // proxy message test
    proxy_content(&mut readbuf[..], &mut tunn_r,
    SizedWindows::new(TestSizedWindows),
    SizedWindows::new(TestSizedWindows),
    SizedWindows::new(TestSizedWindows), &mut input_v, &mut output).unwrap();
 }
   output.flush().unwrap();

  }
  // read message test for dest
  {
    let mut ix = 0;

    let mut readbuf = vec![0;read_buffer_length];
    let mut input_v = Cursor::new(output.into_inner());
    let mut tunn_re = TunnelReaderExt::new(route.get(route_len - 1).unwrap(),SizedWindows::new(TestSizedWindows),None);
    let mut tunn_r = tunn_re.as_reader(&mut input_v);
    assert_eq!(tunn_r.1.is_dest(), None);
    let mut emptybuf = [];
    assert_eq!(0,tunn_r.read( &mut emptybuf[..]).unwrap());
    assert_eq!(tunn_r.1.is_dest(), Some(true));

/*    let mut l = 1;
     while l != 0 {
      l = tunn_r.read( &mut readbuf).unwrap();

      if ix < input.len() {
      if ix + l < input.len() {
        assert!(&readbuf[..l] == &input[ix..ix + l]);
      } else {
        assert!(&readbuf[..input.len() - ix] == &input[ix..]);
      }
      }
      ix += l;
    }*/
    while ix < input_length { // known length
      let l = if ix + readbuf.len() < input.len() {
        tunn_r.read( &mut readbuf).unwrap()
      } else {
        tunn_r.read( &mut readbuf[..input.len() - ix]).unwrap()
      };
      assert!(l!=0);

      assert_eq!(&readbuf[..l], &input[ix..ix + l]);
      ix += l;
    }

    //let l = tunn_r.read(&mut readbuf).unwrap();
    //assert!(l==0);
    assert!(tunn_r.read_end().is_ok());
  }

}

#[test]
fn tunnel_nohop_notunnel_1() {
  let tmode = TunnelMode::NoTunnel;
  let input_length = 500;
  let write_buffer_length = 360;
  let read_buffer_length = 130;
  let mut route = Vec::new();
  let pt = peer_tests();
  route.push(pt[0].clone());
  route.push(pt[1].clone());
  tunnel_test(route, input_length, write_buffer_length, read_buffer_length, tmode, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow);
}

#[test]
fn tunnel_nohop_notunnel_2() {
  let tmode = TunnelMode::NoTunnel;
  let input_length = 500;
  let write_buffer_length = 130;
  let read_buffer_length = 360;
  let mut route = Vec::new();
  let pt = peer_tests();
  route.push(pt[0].clone());
  route.push(pt[1].clone());
  tunnel_test(route, input_length, write_buffer_length, read_buffer_length, tmode, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow);

}

fn tunnel_public_test(nbpeer : usize, tmode : TunnelShadowMode, input_length : usize, write_buffer_length : usize, read_buffer_length : usize, shead : ShadowModeTest, scont : ShadowModeTest) {
  let tmode = TunnelMode::PublicTunnel((nbpeer as u8) - 1,tmode, ErrorHandlingMode::KnownDest(None));
  let mut route = Vec::new();
  let pt = peer_tests();
  for i in 0..nbpeer {
    route.push(pt[i].clone());
  }
  tunnel_test(route, input_length, write_buffer_length, read_buffer_length, tmode, shead, scont);
}
#[test]
fn tunnel_nohop_publictunnel_1() {
  tunnel_public_test(2, TunnelShadowMode::Last, 500, 360, 130, ShadowModeTest::SimpleShiftNoHead, ShadowModeTest::SimpleShift);
}
#[test]
fn tunnel_nohop_publictunnel_2() {
  tunnel_public_test(2, TunnelShadowMode::Full, 500, 360, 130, ShadowModeTest::SimpleShiftNoHead, ShadowModeTest::SimpleShift);
}

#[test]
fn tunnel_nohop_publictunnel_3() {
  tunnel_public_test(2, TunnelShadowMode::Last, 500, 130, 360, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow);
}

#[test]
fn tunnel_onehop_publictunnel_1() {
  tunnel_public_test(3, TunnelShadowMode::Last, 500, 360, 130, ShadowModeTest::SimpleShiftNoHead, ShadowModeTest::SimpleShift);
}

#[test]
fn tunnel_onehop_publictunnel_2() {
  tunnel_public_test(3, TunnelShadowMode::Full, 500, 130, 360, ShadowModeTest::SimpleShift, ShadowModeTest::SimpleShift);
}

#[test]
fn tunnel_onehop_publictunnel_3() { // TODO disable (useless)
  tunnel_public_test(3, TunnelShadowMode::Last, 500, 130, 360, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow);
}

#[test]
fn tunnel_fourhop_publictunnel_2() {
  tunnel_public_test(6, TunnelShadowMode::Full, 500, 130, 360, ShadowModeTest::SimpleShift, ShadowModeTest::SimpleShift);
}

#[test]
fn tunnel_fourhop_publictunnel_3() {
  tunnel_public_test(4, TunnelShadowMode::Last, 500, 130, 360, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow);
}

fn peer_tests () -> Vec<PeerTest> {
[ PeerTest {
    nodeid: "toid1".to_string(),
    address : LocalAdd(1),
    keyshift: 2,
},
 PeerTest  {
    nodeid: "toid2".to_string(),
    address : LocalAdd(2),
    keyshift: 3,
},
 PeerTest {
    nodeid: "toid3".to_string(),
    address : LocalAdd(3),
    keyshift: 4,
},
 PeerTest {
    nodeid: "toid4".to_string(),
    address : LocalAdd(4),
    keyshift: 5,
},
 PeerTest {
    nodeid: "toid5".to_string(),
    address : LocalAdd(5),
    keyshift: 6,
},
 PeerTest {
    nodeid: "toid6".to_string(),
    address : LocalAdd(6),
    keyshift: 5,
},
].to_vec()
}

<commit_msg>Test cached error retrieve<commit_after>use peer::{
  Peer,
  Shadow,
};

use std::io::{
  Write,
  Read,
  Result as IoResult,
  Cursor,
};
use rand::os::OsRng;
use rand::Rng;

use mydht_base::tunnel::{
  self,
  TunnelWriter,
  TunnelWriterExt,
  TunnelReader,
  TunnelReaderExt,
  TunnelMode,
  TunnelState,
  TunnelShadowMode,
  proxy_content,
  report_error,
  flush_read_on_proxy_error,
  ErrorHandlingMode,
  ErrorHandlingInfo,
};

use readwrite_comp::{
  ExtRead,
  ExtWrite,
};
use peer::{
  PeerTest,
};
use transport::{
  LocalAdd,
};
use shadow::{
  ShadowTest,
  ShadowModeTest,
};
use mydht_base::bytes_wr::sized_windows::{
  SizedWindowsParams,
  SizedWindows,
};

#[derive(Clone)]
pub struct TestSizedWindows;

#[derive(Clone)]
pub struct TestSizedWindowsHead;
impl SizedWindowsParams for TestSizedWindowsHead {
    const INIT_SIZE : usize = 15;
    const GROWTH_RATIO : Option<(usize,usize)> = None;
    const WRITE_SIZE : bool = false;
    const SECURE_PAD : bool = false;
}

impl SizedWindowsParams for TestSizedWindows {
    const INIT_SIZE : usize = 45;
    const GROWTH_RATIO : Option<(usize,usize)> = Some((3,2));
    const WRITE_SIZE : bool = true;
    const SECURE_PAD : bool = false;
}

/// main tunnel test : send message over a route
pub fn tunnel_test<P : Peer> (route : Vec<P>, tc : TunnelTestConfig<<<P as Peer>::Shadow as Shadow>::ShadowMode>)
where <<P as Peer>::Shadow as Shadow>::ShadowMode : Eq
{

 let TunnelTestConfig {
     error_hop : error_hop,
     nbpeer : nbpeer,
     tmode : tmode,
     input_length : input_length,
     write_buffer_length : write_buffer_length,
     read_buffer_length : read_buffer_length,
     shead : shead,
     scont : scont,
     cache_ids : cache_ids,
} = tc.clone();

  let route_len = route.len();

  let mut inputb = vec![0;input_length];
  let mut rnd = OsRng::new().unwrap();
  rnd.fill_bytes(&mut inputb);
  let mut output = Cursor::new(Vec::new());
  let input = inputb;
  let vec_route : Vec<(usize,&P)> = route.iter().map(|p|{
    let errorid = rnd.gen();
    (errorid,p)
  }).collect();
  // send message test
  {
    let mut tunn_we = TunnelWriterExt::new(
      &vec_route[..],
      SizedWindows::new(TestSizedWindows),
      tmode.clone(),
      TunnelState::QueryOnce,// query once default
      None,
      shead.clone(),
      scont.clone(),
      None,// no error routes
      None,// no specific reply route
      cache_ids[0].clone(),

    );

    let mut tunn_w = tunn_we.as_writer(&mut output);

    //tunn_w.write_all(&input[..input_length]).unwrap();
    let mut ix = 0;
    while ix < input_length {
      if ix + write_buffer_length < input_length {
        ix += tunn_w.write(&input[ix..ix + write_buffer_length]).unwrap();
      } else {
        ix += tunn_w.write(&input[ix..]).unwrap();
      }
    }
    tunn_w.flush().unwrap();

  }

  // middle proxy message
  /*pub fn proxy_content<
  P : Peer,
  ER : ExtRead,
  R : Read,
  EW : ExtWrite,
  W : Write> (
  buf : &mut [u8],
  tre : &mut TunnelReaderExt<ER,P>,
  mut er : ER,
  mut ew : EW,
  r : &mut R,
  w : &mut W) -> Result<()> {
    {*/

  for i in 1 .. route_len - 1 {
    let mut readbuf = vec![0;read_buffer_length];

{
    let mut input_v = Cursor::new(output.into_inner());

    let mut tunn_r = TunnelReaderExt::new(route.get(i).unwrap(),SizedWindows::new(TestSizedWindows),None,None);
    //let mut tunn_r : TunnelReaderExt2<P,_> = TunnelReaderExt2::new(&mut input_v,&mut buf2[..],route.get(i).unwrap(),shead.clone(),scont.clone());

    assert!(tunn_r.is_dest() == None);
    tunn_r.read_header(&mut input_v).unwrap();
    assert!(tunn_r.is_dest() == Some(false));
    // check tcid (head read)
    if tunn_r.mode.do_cache() {
     assert_eq!(tunn_r.previous_cacheid, cache_ids[i-1]);
    }

    // error mgmt
    if i == error_hop {
      return tunnel_test_err (vec_route, tc, &mut tunn_r, &mut readbuf, &mut input_v, i)
    }

    output = Cursor::new(Vec::new());

    // proxy message test
    proxy_content(
    &mut readbuf[..],
    &mut tunn_r,
    SizedWindows::new(TestSizedWindows),
    SizedWindows::new(TestSizedWindows),
    SizedWindows::new(TestSizedWindows),
    SizedWindows::new(TestSizedWindows),
    &mut input_v,
    &mut output,
    &cache_ids[i][..],
    ).unwrap();

 }
   output.flush().unwrap();

  }

  // read message test for dest
  {
    let mut ix = 0;

    let mut readbuf = vec![0;read_buffer_length];
    let mut input_v = Cursor::new(output.into_inner());
    let mut tunn_re = TunnelReaderExt::new(route.get(route_len - 1).unwrap(),SizedWindows::new(TestSizedWindows),None,None);
    let mut tunn_r = tunn_re.as_reader(&mut input_v);
    assert_eq!(tunn_r.1.is_dest(), None);
    let mut emptybuf = [];
    assert_eq!(0,tunn_r.read( &mut emptybuf[..]).unwrap());
    assert_eq!(tunn_r.1.is_dest(), Some(true));

/*    let mut l = 1;
     while l != 0 {
      l = tunn_r.read( &mut readbuf).unwrap();

      if ix < input.len() {
      if ix + l < input.len() {
        assert!(&readbuf[..l] == &input[ix..ix + l]);
      } else {
        assert!(&readbuf[..input.len() - ix] == &input[ix..]);
      }
      }
      ix += l;
    }*/
    while ix < input_length { // known length
      let l = if ix + readbuf.len() < input.len() {
        tunn_r.read( &mut readbuf).unwrap()
      } else {
        tunn_r.read( &mut readbuf[..input.len() - ix]).unwrap()
      };

      assert!(l!=0);
    if tunn_r.1.mode.do_cache() {
     assert_eq!(tunn_r.1.previous_cacheid, *cache_ids.last().unwrap());
    }

      assert_eq!(&readbuf[..l], &input[ix..ix + l]);
      ix += l;
    }

    //let l = tunn_r.read(&mut readbuf).unwrap();
    //assert!(l==0);
    assert!(tunn_r.read_end().is_ok());

    // check error report value (could add this to proxy to)
    match tunn_r.1.shadow.1.as_ref().unwrap().error_handle {
      ErrorHandlingInfo::NoHandling => {
        assert_eq!(tmode.errhandling_mode(), ErrorHandlingMode::NoHandling);
      },
      ErrorHandlingInfo::KnownDest(ref key, ref otm) => {
        assert_eq!(key, &route[0].get_key());
      },
      ErrorHandlingInfo::ErrorRoute(ref ecode) => {
        assert_eq!(tmode.errhandling_mode(), ErrorHandlingMode::ErrorRoute);
        assert_eq!(ecode, &vec_route.last().unwrap().0);
      },
      ErrorHandlingInfo::ErrorCachedRoute(ref ecode) => {
        assert_eq!(tmode.errhandling_mode(), ErrorHandlingMode::ErrorCachedRoute);
        assert_eq!(ecode, &vec_route.last().unwrap().0);
      },
    }
  }

}

/// return error up to
pub fn tunnel_test_err<P : Peer> (route : Vec<(usize,&P)>, tc : TunnelTestConfig<<<P as Peer>::Shadow as Shadow>::ShadowMode>, tunn_r : &mut TunnelReaderExt<SizedWindows<TestSizedWindows>,P>, buf : &mut [u8],input_v : &mut Cursor<Vec<u8>>, err_p : usize)
where <<P as Peer>::Shadow as Shadow>::ShadowMode : Eq
{

 let TunnelTestConfig {
     error_hop : error_hop,
     nbpeer : nbpeer,
     tmode : tmode,
     input_length : input_length,
     write_buffer_length : write_buffer_length,
     read_buffer_length : read_buffer_length,
     shead : shead,
     scont : scont,
     cache_ids : cache_ids,
} = tc;
  // do not have start proxy so consume (last arg) is true
  let odest = flush_read_on_proxy_error(
    tunn_r,
    SizedWindows::new(TestSizedWindows),
    input_v,
    true,
  ).unwrap();

  // send back error id
 // let error_id = tunn_r.
 let mut output = Cursor::new(Vec::new());
  report_error(buf,
               tunn_r,
  SizedWindows::new(TestSizedWindows),
  //mut err : ER, // only for reading of return route if needed
  input_v,
//  r : &mut R,
  &mut output,
//  w : &mut W, // w is for reply in reply route (error_read_dest has been called before)
  ).unwrap();

  // proxy it TODO factor code??
  for i in (1 .. err_p).rev() {
    let mut readbuf = vec![0;read_buffer_length];

{
    let mut input_v = Cursor::new(output.into_inner());

    output = Cursor::new(Vec::new());
    match tunnel::read_state(&mut input_v).unwrap() {
      TunnelState::QErrorCached => {
        let cid = tunnel::read_cacheid(&mut input_v).unwrap();
        assert!(&cid == cache_ids.get(i).unwrap());
        let cid_from_cache = cache_ids.get(i - 1).unwrap();
        let cached_errcode = route.get(i).unwrap().0;

        tunnel::proxy_cached_err (&mut input_v, &mut output, &cid_from_cache[..], cached_errcode).unwrap();
      },
      TunnelState::QError => {
        panic!("TODO");
      },
      _ => panic!("Received non error state"),
    };

   }
   output.flush().unwrap();

  }

  let mut input_v = Cursor::new(output.into_inner());
  // emitter got its content
  match tunnel::read_state(&mut input_v).unwrap() {
    TunnelState::QErrorCached => {
      let cid = tunnel::read_cacheid(&mut input_v).unwrap();
      assert!(&cid == cache_ids.get(0).unwrap());
      // reading cache we know we are dest and we retrieve route
      assert_eq!(tunnel::identify_cached_errcode(&mut input_v, route).unwrap(), err_p);
    },
    TunnelState::QError => {
      panic!("TODO");
    },
    _ => panic!("Received non error state"),
  };

/*  match tunn_r.shadow.1 {
    Some(
  ErrorHandlingMode::NoHandling => (),
  ErrorHandlingMode:: => (),

  KnownDest(Option<Box<TunnelMode>>),
  ErrorRoute,
  ErrorCachedRoute,
  _ => (),
  }
*/
}

#[test]
fn tunnel_nohop_notunnel_1() {
  let input_length = 500;
  let write_buffer_length = 360;
  let read_buffer_length = 130;
  let mut route = Vec::new();
  let pt = peer_tests();
  route.push(pt[0].clone());
  route.push(pt[1].clone());
  tunnel_test(route, TunnelTestConfig::new_notunnel(input_length, write_buffer_length, read_buffer_length, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow));
}

#[test]
fn tunnel_nohop_notunnel_2() {
  let input_length = 500;
  let write_buffer_length = 130;
  let read_buffer_length = 360;
  let mut route = Vec::new();
  let pt = peer_tests();
  route.push(pt[0].clone());
  route.push(pt[1].clone());
  tunnel_test(route, TunnelTestConfig::new_notunnel(input_length, write_buffer_length, read_buffer_length, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow));

}

fn tunnel_testpeer_test(tc : TunnelTestConfig<ShadowModeTest>) {

  let mut route = Vec::new();
  let pt = peer_tests();
  for i in 0..tc.nbpeer {
    route.push(pt[i].clone());
  }
  tunnel_test(route, tc);
}
#[test]
fn tunnel_nohop_noreptunnel_1() {
  tunnel_testpeer_test(TunnelTestConfig::new_norep(2, TunnelShadowMode::Last, 500, 360, 130, ShadowModeTest::SimpleShiftNoHead, ShadowModeTest::SimpleShift, ErrorHandlingMode::NoHandling));
}
#[test]
fn tunnel_nohop_noreptunnel_2() {
  tunnel_testpeer_test(TunnelTestConfig::new_norep(2, TunnelShadowMode::Full, 500, 360, 130, ShadowModeTest::SimpleShiftNoHead, ShadowModeTest::SimpleShift,ErrorHandlingMode::NoHandling));
}

#[test]
fn tunnel_nohop_noreptunnel_3() {
  tunnel_testpeer_test(TunnelTestConfig::new_norep(2, TunnelShadowMode::Last, 500, 130, 360, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow,ErrorHandlingMode::NoHandling));
}

#[test]
fn tunnel_onehop_noreptunnel_1() {
  tunnel_testpeer_test(TunnelTestConfig::new_norep(3, TunnelShadowMode::Last, 500, 360, 130, ShadowModeTest::SimpleShiftNoHead, ShadowModeTest::SimpleShift,ErrorHandlingMode::NoHandling));
}

#[test]
fn tunnel_onehop_noreptunnel_2() {
  tunnel_testpeer_test(TunnelTestConfig::new_norep(3, TunnelShadowMode::Full, 500, 130, 360, ShadowModeTest::SimpleShift, ShadowModeTest::SimpleShift,ErrorHandlingMode::NoHandling));
}

#[test]
fn tunnel_onehop_noreptunnel_3() { // TODO disable (useless)
  tunnel_testpeer_test(TunnelTestConfig::new_norep(3, TunnelShadowMode::Last, 500, 130, 360, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow,ErrorHandlingMode::NoHandling));
}

#[test]
fn tunnel_fourhop_noreptunnel_2() {
  tunnel_testpeer_test(TunnelTestConfig::new_norep(6, TunnelShadowMode::Full, 500, 130, 360, ShadowModeTest::SimpleShift, ShadowModeTest::SimpleShift,ErrorHandlingMode::NoHandling));
}

#[test]
fn tunnel_fourhop_noreptunnel_3() {
  tunnel_testpeer_test(TunnelTestConfig::new_norep(4, TunnelShadowMode::Last, 500, 130, 360, ShadowModeTest::NoShadow, ShadowModeTest::NoShadow,ErrorHandlingMode::KnownDest(None)));
}

#[test]
fn tunnel_cached_error() {
  let mut tc = TunnelTestConfig::new_norep(6, TunnelShadowMode::Full, 500, 130, 360, ShadowModeTest::SimpleShift, ShadowModeTest::SimpleShift,
     //ErrorHandlingMode::NoHandling);
     ErrorHandlingMode::ErrorCachedRoute); // TODO add test in proxy of cacheid value
//     ErrorHandlingMode::ErrorRoute);
  // error happening at last peer -1
  tc.error_hop = 6 - 2; // last proxy hop
  tunnel_testpeer_test(tc);
}

#[derive(Clone)]
pub struct TunnelTestConfig<SM> {
    pub error_hop : usize, // 0 as no error, then ix of proxy hop (starting at one)
    pub nbpeer : usize,
    pub tmode : TunnelMode,
    pub input_length : usize,
    pub write_buffer_length : usize,
    pub read_buffer_length : usize,
    pub shead : SM,
    pub scont : SM,
    pub cache_ids : Vec<Vec<u8>>,
}

pub fn test_cache_ids(nbpeer : usize) -> Vec<Vec<u8>> {

  let mut cache_ids = Vec::new();
  for i in 0 .. nbpeer {
    let cid : Vec<u8> = vec!(i as u8, (i + 1) as u8, (i + 2) as u8, (i + 3) as u8);
    cache_ids.push(cid);
  }
  cache_ids
}

impl<SM> TunnelTestConfig<SM> {
  pub fn new(nbpeer : usize, mode : TunnelMode,  input_length : usize, write_buffer_length : usize, read_buffer_length : usize, shead : SM, scont : SM) -> TunnelTestConfig<SM> {
 TunnelTestConfig {
    error_hop : 0,
     nbpeer : nbpeer,
     tmode : mode,
     input_length : input_length,
     write_buffer_length : write_buffer_length,
     read_buffer_length : read_buffer_length,
     shead : shead,
     scont : scont,
     cache_ids : test_cache_ids(nbpeer),
}
  }
pub fn new_norep(nbpeer : usize, tsmode : TunnelShadowMode,  input_length : usize, write_buffer_length : usize, read_buffer_length : usize, shead : SM, scont : SM, em : ErrorHandlingMode) -> TunnelTestConfig<SM> {

  let tmode = TunnelMode::NoRepTunnel((nbpeer as u8) - 1,tsmode, em);
  TunnelTestConfig::new(nbpeer,tmode, input_length, write_buffer_length, read_buffer_length, shead, scont)
}
pub fn new_notunnel(input_length : usize, write_buffer_length : usize, read_buffer_length : usize, shead : SM, scont : SM) -> TunnelTestConfig<SM> {
  TunnelTestConfig::new(2,TunnelMode::NoTunnel, input_length, write_buffer_length, read_buffer_length, shead, scont)
}

}

fn peer_tests () -> Vec<PeerTest> {
[ PeerTest {
    nodeid: "toid1".to_string(),
    address : LocalAdd(1),
    keyshift: 2,
},
 PeerTest  {
    nodeid: "toid2".to_string(),
    address : LocalAdd(2),
    keyshift: 3,
},
 PeerTest {
    nodeid: "toid3".to_string(),
    address : LocalAdd(3),
    keyshift: 4,
},
 PeerTest {
    nodeid: "toid4".to_string(),
    address : LocalAdd(4),
    keyshift: 5,
},
 PeerTest {
    nodeid: "toid5".to_string(),
    address : LocalAdd(5),
    keyshift: 6,
},
 PeerTest {
    nodeid: "toid6".to_string(),
    address : LocalAdd(6),
    keyshift: 5,
},
].to_vec()
}

<|endoftext|>


<commit_before>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use logger;

pub struct Env {
    device: String,
    dir:    String,
    script: String
}

impl Env {

    pub fn new() -> Env {
        return Env{device: "".to_string(),
                   dir:    "".to_string(),
                   script: "".to_string()}
    }

    pub fn load(&self, l: &logger::Logger) {
        self.load_device(l);
        self.load_dir(l);
        self.load_script(l);
    }

    fn load_device(&self, l: &logger::Logger) {
        //
        //TODO
        //
    }

    fn load_dir(&self, l: &logger::Logger) {
        //
        //TODO
        //
    }

    fn load_script(&self, l: &logger::Logger) {
        //
        //TODO
        //
    }
}
<commit_msg>mod env is completed?<commit_after>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

extern crate libc;

use logger;
use self::libc::getenv;

use std::ffi::CString;

pub struct Env {
    device: String,
    dir:    String,
    script: String
}

impl Env {
    pub fn new() -> Env {
        return Env{device: "".to_string(),
                   dir:    "".to_string(),
                   script: "".to_string()}
    }

    pub fn load(&mut self, l: &logger::Logger) {
        self.load_device(l);
        self.load_dir(l);
        self.load_script(l);
    }

    fn load_device(&mut self, l: &logger::Logger) {
        self.device = self.load_("AMAE_DEVICE", l);
    }

    fn load_dir(&mut self, l: &logger::Logger) {
        self.dir = self.load_("AMAE_MOUNT_DIR", l);
    }

    fn load_script(&mut self, l: &logger::Logger) {
        self.script = self.load_("AMAE_SCRIPT", l);
    }

    fn load_(&self, name: &str, l: &logger::Logger) -> String {
        let cname = CString::new(name).unwrap();
        let cname_ptr = cname.as_ptr();
        unsafe {
            let out = getenv(cname_ptr);
            if out.is_null() { self.error_(name, l); }
            let cstring = CString::from_raw(out);
            let res = cstring.into_string();
            match res {
                Ok(v)  => return v,
                Err(e) => {
                    let mut ss = self.ef(name);
                    ss += " ";
                    ss += &(format!("{:?}", e));
                    self.error__(ss, l);
                    return "".to_string();
                }
            }
        }
    }

    fn error_(&self, name: &str, l: &logger::Logger) {
        self.error__(self.ef(name), l);
    }

    fn ef(&self, name: &str) -> String {
        let em = "Can't get env: ".to_string() +
            name + "!";
        return em;
    }

    fn error__(&self, s: String, l: &logger::Logger) {
        l.error(s.as_str());
        panic!(s);
    }
}
/*
#[test]
fn hello() {
    let x = Err("test");
    assert_eq!("test", x.unwrap());
}
 */
<|endoftext|>


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

pub mod perm;
pub mod sys;
<commit_msg>[sup] Implement `Deserialize` for `ServiceSpec` via serde/toml.<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod perm;
pub mod sys;

use std::error;
use std::fmt;
use std::marker::PhantomData;
use std::result;
use std::str::FromStr;

use serde;

pub fn deserialize_using_from_str<T, E, D>(d: D) -> result::Result<T, D::Error>
    where T: FromStr<Err = E>,
          E: error::Error,
          D: serde::Deserializer
{
    struct FromStringable<T, E>(PhantomData<T>, PhantomData<E>);

    impl<T, E> serde::de::Visitor for FromStringable<T, E>
        where T: FromStr<Err = E>,
              E: error::Error
    {
        type Value = T;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("a string")
        }

        fn visit_str<R>(self, value: &str) -> result::Result<T, R>
            where R: serde::de::Error
        {
            match FromStr::from_str(value) {
                Ok(t) => Ok(t),
                Err(err) => {
                    Err(R::custom(format!("string cannot be parsed: \"{}\" ({})",
                                          value,
                                          err.description())))
                }
            }
        }
    }

    d.deserialize(FromStringable(PhantomData, PhantomData))
}
<|endoftext|>


<commit_before>pub fn to_hex_char(q: u8) -> u8 {
    if q <= 9 {b'0'+q} else {b'a'+q}
}

pub fn byte_to_hex(q: u8) -> [u8; 2] {
    [to_hex_char(q >> 4), to_hex_char(q & 0xF)]
}
<commit_msg>remove obsolete formatting utilities<commit_after><|endoftext|>


<commit_before>use super::{RemoteService, SeriesEntry, SeriesInfo, Status};
use crate::err::{self, Result};
use crate::file::{FileType, SaveDir, SaveFile};
use chrono::{Datelike, NaiveDate};
use lazy_static::lazy_static;
use reqwest::Client;
use serde_derive::{Deserialize, Serialize};
use serde_json as json;
use serde_json::json;
use snafu::ResultExt;
use std::convert::TryInto;
use std::fmt;
use std::result;

pub const LOGIN_URL: &str =
    "https://anilist.co/api/v2/oauth/authorize?client_id=427&response_type=token";

pub const API_URL: &str = "https://graphql.anilist.co";

macro_rules! send {
    ($token:expr, $file:expr, {$($vars:tt)*}, $($resp_root:expr)=>*) => {{
        let vars = json!({
            $($vars)*
        });

        let query = include_str!(concat!("../../../graphql/anilist/", $file, ".gql"));

        // We must bind the json variable mutably, but the compiler warns that it can be removed.
        #[allow(unused_mut)]
        match send_gql_request(query, &vars, $token) {
            Ok(mut json) => {
                $(json = json[$resp_root].take();)*
                Ok(json)
            },
            Err(err) => Err(err),
        }
    }};
}

macro_rules! query {
    ($token:expr, $file:expr, {$($vars:tt)*}, $($resp_root:expr)=>*) => {
        send!($token, $file, {$($vars)*}, $($resp_root)=>*).and_then(|json| {
            json::from_value(json).context(err::JsonDecode)
        })
    };
}

#[derive(Debug)]
pub struct AniList {
    config: AniListConfig,
    user: User,
}

impl AniList {
    pub fn login(config: AniListConfig) -> Result<AniList> {
        let token = config.token.decode()?;
        let user = query!(&token, "user", {}, "data" => "Viewer")?;

        Ok(AniList { config, user })
    }
}

impl RemoteService for AniList {
    fn search_info_by_name(&self, name: &str) -> Result<Vec<SeriesInfo>> {
        let token = self.config.token.decode()?;
        let entries: Vec<Media> = query!(
            &token,
            "info_by_name",
            { "name": name },
            "data" => "Page" => "media"
        )?;

        let entries = entries.into_iter().map(|entry| entry.into()).collect();
        Ok(entries)
    }

    fn search_info_by_id(&self, id: u32) -> Result<SeriesInfo> {
        let token = self.config.token.decode()?;
        let info: Media = query!(&token, "info_by_id", { "id": id }, "data" => "Media")?;

        Ok(info.into())
    }

    fn get_list_entry(&self, id: u32) -> Result<Option<SeriesEntry>> {
        let token = self.config.token.decode()?;
        let query: Result<MediaEntry> = query!(
            &token,
            "get_list_entry",
            { "id": id, "userID": self.user.id },
            "data" => "MediaList"
        );

        match query {
            Ok(entry) => Ok(Some(entry.into_series_entry(id))),
            Err(ref err) if err.is_http_code(404) => Ok(None),
            Err(err) => Err(err),
        }
    }

    fn update_list_entry(&self, entry: &SeriesEntry) -> Result<()> {
        let token = self.config.token.decode()?;

        send!(
            &token,
            "update_list_entry",
            {
                "mediaId": entry.id,
                "watched_eps": entry.watched_eps,
                "score": entry.score.unwrap_or(0.0),
                "status": MediaStatus::from(entry.status),
                "start_date": entry.start_date.map(|date| MediaDate::from(&date)),
                "finish_date": entry.end_date.map(|date| MediaDate::from(&date)),
            },
        )?;

        Ok(())
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AniListConfig {
    #[serde(flatten)]
    pub token: AccessToken,
}

impl AniListConfig {
    pub fn new(token: AccessToken) -> AniListConfig {
        AniListConfig { token }
    }
}

impl SaveFile for AniListConfig {
    fn filename() -> &'static str {
        "anilist.toml"
    }

    fn save_dir() -> SaveDir {
        SaveDir::Config
    }

    fn file_type() -> FileType {
        FileType::Toml
    }
}

#[derive(Clone, Default, Deserialize, Serialize)]
pub struct AccessToken {
    encoded_token: String,
}

impl AccessToken {
    pub fn new<S>(token: S) -> AccessToken
    where
        S: AsRef<str>,
    {
        AccessToken {
            encoded_token: AccessToken::encode(token),
        }
    }

    fn encode<S>(value: S) -> String
    where
        S: AsRef<str>,
    {
        base64::encode(value.as_ref())
    }

    pub fn decode(&self) -> Result<String> {
        let bytes = base64::decode(&self.encoded_token).context(err::Base64Decode)?;
        let string = String::from_utf8(bytes).context(err::UTF8Decode)?;

        Ok(string)
    }
}

impl fmt::Debug for AccessToken {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "AccessToken {{}}")
    }
}

fn send_gql_request<S, R>(query: S, vars: &json::Value, token: R) -> Result<json::Value>
where
    S: Into<String>,
    R: AsRef<str>,
{
    lazy_static! {
        static ref CLIENT: Client = Client::new();
    }

    let query = minimize_query(query);

    let body = json!({
        "query": query,
        "variables": vars,
    })
    .to_string();

    let json: json::Value = CLIENT
        .post(API_URL)
        .header("Content-Type", "application/json")
        .header("Accept", "application/json")
        .bearer_auth(token.as_ref())
        .body(body)
        .send()
        .context(err::Reqwest)?
        .json()
        .context(err::Reqwest)?;

    if json["errors"] != json::Value::Null {
        let err = &json["errors"][0];

        let message = err["message"].as_str().unwrap_or("unknown").to_string();
        let code = err["status"].as_u64().unwrap_or(0) as u16;

        return Err(err::Error::BadAniListResponse { code, message });
    }

    Ok(json)
}

fn minimize_query<S>(value: S) -> String
where
    S: Into<String>,
{
    let mut value = value.into();
    value.retain(|c| c != ' ' && c != '\n');
    value
}

#[derive(Debug, Deserialize)]
struct User {
    id: u32,
    #[serde(rename = "mediaListOptions")]
    options: ListOptions,
}

#[derive(Debug, Deserialize)]
struct ListOptions {
    #[serde(rename = "scoreFormat")]
    score_format: ScoreFormat,
}

#[derive(Debug, Deserialize)]
#[allow(clippy::enum_variant_names)]
enum ScoreFormat {
    #[serde(rename = "POINT_100")]
    Point100,
    #[serde(rename = "POINT_10_DECIMAL")]
    Point10Decimal,
    #[serde(rename = "POINT_10")]
    Point10,
    #[serde(rename = "POINT_5")]
    Point5,
    #[serde(rename = "POINT_3")]
    Point3,
}

#[derive(Debug, Deserialize)]
struct Media {
    id: u32,
    title: MediaTitle,
    episodes: Option<u32>,
    relations: Option<MediaRelation>,
}

impl Into<SeriesInfo> for Media {
    fn into(self) -> SeriesInfo {
        let sequel = self
            .relations
            .and_then(|rel| rel.edges.into_iter().find(|e| e.is_sequel()))
            .map(|e| e.node.id);

        SeriesInfo {
            id: self.id,
            title: self.title.romaji,
            episodes: self.episodes.unwrap_or(1),
            sequel,
        }
    }
}

#[derive(Debug, Deserialize)]
struct MediaTitle {
    romaji: String,
}

#[derive(Debug, Deserialize)]
struct MediaRelation {
    edges: Vec<MediaEdge>,
}

#[derive(Debug, Deserialize)]
struct MediaEdge {
    #[serde(rename = "relationType")]
    relation: String,
    node: MediaNode,
}

impl MediaEdge {
    fn is_sequel(&self) -> bool {
        self.relation == "SEQUEL"
    }
}

#[derive(Debug, Deserialize)]
struct MediaNode {
    id: u32,
}

#[derive(Debug, Deserialize)]
struct MediaEntry {
    status: MediaStatus,
    score: f32,
    progress: u32,
    #[serde(rename = "startedAt")]
    start_date: Option<MediaDate>,
    #[serde(rename = "completedAt")]
    complete_date: Option<MediaDate>,
}

impl MediaEntry {
    fn into_series_entry(self, id: u32) -> SeriesEntry {
        let score = if self.score > 0.0 {
            Some(self.score)
        } else {
            None
        };

        SeriesEntry {
            id,
            watched_eps: self.progress,
            score,
            status: self.status.into(),
            start_date: self.start_date.and_then(|d| d.try_into().ok()),
            end_date: self.complete_date.and_then(|d| d.try_into().ok()),
        }
    }
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum MediaStatus {
    #[serde(rename = "CURRENT")]
    Current,
    #[serde(rename = "COMPLETED")]
    Completed,
    #[serde(rename = "PAUSED")]
    Paused,
    #[serde(rename = "DROPPED")]
    Dropped,
    #[serde(rename = "PLANNING")]
    Planning,
    #[serde(rename = "REPEATING")]
    Repeating,
}

impl Into<Status> for MediaStatus {
    fn into(self) -> Status {
        match self {
            MediaStatus::Current => Status::Watching,
            MediaStatus::Completed => Status::Completed,
            MediaStatus::Paused => Status::OnHold,
            MediaStatus::Dropped => Status::Dropped,
            MediaStatus::Planning => Status::PlanToWatch,
            MediaStatus::Repeating => Status::Rewatching,
        }
    }
}

impl From<Status> for MediaStatus {
    fn from(status: Status) -> MediaStatus {
        match status {
            Status::Watching => MediaStatus::Current,
            Status::Completed => MediaStatus::Completed,
            Status::OnHold => MediaStatus::Paused,
            Status::Dropped => MediaStatus::Dropped,
            Status::PlanToWatch => MediaStatus::Planning,
            Status::Rewatching => MediaStatus::Repeating,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct MediaDate {
    year: Option<i32>,
    month: Option<u32>,
    day: Option<u32>,
}

impl TryInto<NaiveDate> for MediaDate {
    type Error = ();

    fn try_into(self) -> result::Result<NaiveDate, Self::Error> {
        match (self.year, self.month, self.day) {
            (Some(y), Some(m), Some(d)) => Ok(NaiveDate::from_ymd(y, m, d)),
            _ => Err(()),
        }
    }
}

impl From<&NaiveDate> for MediaDate {
    fn from(date: &NaiveDate) -> MediaDate {
        MediaDate {
            year: Some(date.year()),
            month: Some(date.month()),
            day: Some(date.day()),
        }
    }
}
<commit_msg>[series] Display requests made to AniList for debug builds<commit_after>use super::{RemoteService, SeriesEntry, SeriesInfo, Status};
use crate::err::{self, Result};
use crate::file::{FileType, SaveDir, SaveFile};
use chrono::{Datelike, NaiveDate};
use lazy_static::lazy_static;
use reqwest::Client;
use serde_derive::{Deserialize, Serialize};
use serde_json as json;
use serde_json::json;
use snafu::ResultExt;
use std::convert::TryInto;
use std::fmt;
use std::result;

pub const LOGIN_URL: &str =
    "https://anilist.co/api/v2/oauth/authorize?client_id=427&response_type=token";

pub const API_URL: &str = "https://graphql.anilist.co";

macro_rules! send {
    ($token:expr, $file:expr, {$($vars:tt)*}, $($resp_root:expr)=>*) => {{
        if cfg!(debug_assertions) {
            println!("DEBUG: AniList request: {}", $file);
        }

        let vars = json!({
            $($vars)*
        });

        let query = include_str!(concat!("../../../graphql/anilist/", $file, ".gql"));

        // We must bind the json variable mutably, but the compiler warns that it can be removed.
        #[allow(unused_mut)]
        match send_gql_request(query, &vars, $token) {
            Ok(mut json) => {
                $(json = json[$resp_root].take();)*
                Ok(json)
            },
            Err(err) => Err(err),
        }
    }};
}

macro_rules! query {
    ($token:expr, $file:expr, {$($vars:tt)*}, $($resp_root:expr)=>*) => {
        send!($token, $file, {$($vars)*}, $($resp_root)=>*).and_then(|json| {
            json::from_value(json).context(err::JsonDecode)
        })
    };
}

#[derive(Debug)]
pub struct AniList {
    config: AniListConfig,
    user: User,
}

impl AniList {
    pub fn login(config: AniListConfig) -> Result<AniList> {
        let token = config.token.decode()?;
        let user = query!(&token, "user", {}, "data" => "Viewer")?;

        Ok(AniList { config, user })
    }
}

impl RemoteService for AniList {
    fn search_info_by_name(&self, name: &str) -> Result<Vec<SeriesInfo>> {
        let token = self.config.token.decode()?;
        let entries: Vec<Media> = query!(
            &token,
            "info_by_name",
            { "name": name },
            "data" => "Page" => "media"
        )?;

        let entries = entries.into_iter().map(|entry| entry.into()).collect();
        Ok(entries)
    }

    fn search_info_by_id(&self, id: u32) -> Result<SeriesInfo> {
        let token = self.config.token.decode()?;
        let info: Media = query!(&token, "info_by_id", { "id": id }, "data" => "Media")?;

        Ok(info.into())
    }

    fn get_list_entry(&self, id: u32) -> Result<Option<SeriesEntry>> {
        let token = self.config.token.decode()?;
        let query: Result<MediaEntry> = query!(
            &token,
            "get_list_entry",
            { "id": id, "userID": self.user.id },
            "data" => "MediaList"
        );

        match query {
            Ok(entry) => Ok(Some(entry.into_series_entry(id))),
            Err(ref err) if err.is_http_code(404) => Ok(None),
            Err(err) => Err(err),
        }
    }

    fn update_list_entry(&self, entry: &SeriesEntry) -> Result<()> {
        let token = self.config.token.decode()?;

        send!(
            &token,
            "update_list_entry",
            {
                "mediaId": entry.id,
                "watched_eps": entry.watched_eps,
                "score": entry.score.unwrap_or(0.0),
                "status": MediaStatus::from(entry.status),
                "start_date": entry.start_date.map(|date| MediaDate::from(&date)),
                "finish_date": entry.end_date.map(|date| MediaDate::from(&date)),
            },
        )?;

        Ok(())
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AniListConfig {
    #[serde(flatten)]
    pub token: AccessToken,
}

impl AniListConfig {
    pub fn new(token: AccessToken) -> AniListConfig {
        AniListConfig { token }
    }
}

impl SaveFile for AniListConfig {
    fn filename() -> &'static str {
        "anilist.toml"
    }

    fn save_dir() -> SaveDir {
        SaveDir::Config
    }

    fn file_type() -> FileType {
        FileType::Toml
    }
}

#[derive(Clone, Default, Deserialize, Serialize)]
pub struct AccessToken {
    encoded_token: String,
}

impl AccessToken {
    pub fn new<S>(token: S) -> AccessToken
    where
        S: AsRef<str>,
    {
        AccessToken {
            encoded_token: AccessToken::encode(token),
        }
    }

    fn encode<S>(value: S) -> String
    where
        S: AsRef<str>,
    {
        base64::encode(value.as_ref())
    }

    pub fn decode(&self) -> Result<String> {
        let bytes = base64::decode(&self.encoded_token).context(err::Base64Decode)?;
        let string = String::from_utf8(bytes).context(err::UTF8Decode)?;

        Ok(string)
    }
}

impl fmt::Debug for AccessToken {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "AccessToken {{}}")
    }
}

fn send_gql_request<S, R>(query: S, vars: &json::Value, token: R) -> Result<json::Value>
where
    S: Into<String>,
    R: AsRef<str>,
{
    lazy_static! {
        static ref CLIENT: Client = Client::new();
    }

    let query = minimize_query(query);

    let body = json!({
        "query": query,
        "variables": vars,
    })
    .to_string();

    let json: json::Value = CLIENT
        .post(API_URL)
        .header("Content-Type", "application/json")
        .header("Accept", "application/json")
        .bearer_auth(token.as_ref())
        .body(body)
        .send()
        .context(err::Reqwest)?
        .json()
        .context(err::Reqwest)?;

    if json["errors"] != json::Value::Null {
        let err = &json["errors"][0];

        let message = err["message"].as_str().unwrap_or("unknown").to_string();
        let code = err["status"].as_u64().unwrap_or(0) as u16;

        return Err(err::Error::BadAniListResponse { code, message });
    }

    Ok(json)
}

fn minimize_query<S>(value: S) -> String
where
    S: Into<String>,
{
    let mut value = value.into();
    value.retain(|c| c != ' ' && c != '\n');
    value
}

#[derive(Debug, Deserialize)]
struct User {
    id: u32,
    #[serde(rename = "mediaListOptions")]
    options: ListOptions,
}

#[derive(Debug, Deserialize)]
struct ListOptions {
    #[serde(rename = "scoreFormat")]
    score_format: ScoreFormat,
}

#[derive(Debug, Deserialize)]
#[allow(clippy::enum_variant_names)]
enum ScoreFormat {
    #[serde(rename = "POINT_100")]
    Point100,
    #[serde(rename = "POINT_10_DECIMAL")]
    Point10Decimal,
    #[serde(rename = "POINT_10")]
    Point10,
    #[serde(rename = "POINT_5")]
    Point5,
    #[serde(rename = "POINT_3")]
    Point3,
}

#[derive(Debug, Deserialize)]
struct Media {
    id: u32,
    title: MediaTitle,
    episodes: Option<u32>,
    relations: Option<MediaRelation>,
}

impl Into<SeriesInfo> for Media {
    fn into(self) -> SeriesInfo {
        let sequel = self
            .relations
            .and_then(|rel| rel.edges.into_iter().find(|e| e.is_sequel()))
            .map(|e| e.node.id);

        SeriesInfo {
            id: self.id,
            title: self.title.romaji,
            episodes: self.episodes.unwrap_or(1),
            sequel,
        }
    }
}

#[derive(Debug, Deserialize)]
struct MediaTitle {
    romaji: String,
}

#[derive(Debug, Deserialize)]
struct MediaRelation {
    edges: Vec<MediaEdge>,
}

#[derive(Debug, Deserialize)]
struct MediaEdge {
    #[serde(rename = "relationType")]
    relation: String,
    node: MediaNode,
}

impl MediaEdge {
    fn is_sequel(&self) -> bool {
        self.relation == "SEQUEL"
    }
}

#[derive(Debug, Deserialize)]
struct MediaNode {
    id: u32,
}

#[derive(Debug, Deserialize)]
struct MediaEntry {
    status: MediaStatus,
    score: f32,
    progress: u32,
    #[serde(rename = "startedAt")]
    start_date: Option<MediaDate>,
    #[serde(rename = "completedAt")]
    complete_date: Option<MediaDate>,
}

impl MediaEntry {
    fn into_series_entry(self, id: u32) -> SeriesEntry {
        let score = if self.score > 0.0 {
            Some(self.score)
        } else {
            None
        };

        SeriesEntry {
            id,
            watched_eps: self.progress,
            score,
            status: self.status.into(),
            start_date: self.start_date.and_then(|d| d.try_into().ok()),
            end_date: self.complete_date.and_then(|d| d.try_into().ok()),
        }
    }
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum MediaStatus {
    #[serde(rename = "CURRENT")]
    Current,
    #[serde(rename = "COMPLETED")]
    Completed,
    #[serde(rename = "PAUSED")]
    Paused,
    #[serde(rename = "DROPPED")]
    Dropped,
    #[serde(rename = "PLANNING")]
    Planning,
    #[serde(rename = "REPEATING")]
    Repeating,
}

impl Into<Status> for MediaStatus {
    fn into(self) -> Status {
        match self {
            MediaStatus::Current => Status::Watching,
            MediaStatus::Completed => Status::Completed,
            MediaStatus::Paused => Status::OnHold,
            MediaStatus::Dropped => Status::Dropped,
            MediaStatus::Planning => Status::PlanToWatch,
            MediaStatus::Repeating => Status::Rewatching,
        }
    }
}

impl From<Status> for MediaStatus {
    fn from(status: Status) -> MediaStatus {
        match status {
            Status::Watching => MediaStatus::Current,
            Status::Completed => MediaStatus::Completed,
            Status::OnHold => MediaStatus::Paused,
            Status::Dropped => MediaStatus::Dropped,
            Status::PlanToWatch => MediaStatus::Planning,
            Status::Rewatching => MediaStatus::Repeating,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct MediaDate {
    year: Option<i32>,
    month: Option<u32>,
    day: Option<u32>,
}

impl TryInto<NaiveDate> for MediaDate {
    type Error = ();

    fn try_into(self) -> result::Result<NaiveDate, Self::Error> {
        match (self.year, self.month, self.day) {
            (Some(y), Some(m), Some(d)) => Ok(NaiveDate::from_ymd(y, m, d)),
            _ => Err(()),
        }
    }
}

impl From<&NaiveDate> for MediaDate {
    fn from(date: &NaiveDate) -> MediaDate {
        MediaDate {
            year: Some(date.year()),
            month: Some(date.month()),
            day: Some(date.day()),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
extern crate ansi_term;

use std::os;

use file::File;
use dir::Dir;
use column::{Column, Left};
use options::{Options, Lines, Grid};
use unix::Unix;

use ansi_term::{Paint, Plain, strip_formatting};

pub mod column;
pub mod dir;
pub mod format;
pub mod file;
pub mod filetype;
pub mod unix;
pub mod options;
pub mod sort;

fn main() {
    let args = os::args();

    match Options::getopts(args) {
        Err(err) => println!("Invalid options:\n{}", err),
        Ok(opts) => exa(&opts),
    };
}

fn exa(opts: &Options) {
    let mut first = true;

    // It's only worth printing out directory names if the user supplied
    // more than one of them.
    let print_dir_names = opts.dirs.len() > 1;

    for dir_name in opts.dirs.clone().move_iter() {
        if first {
            first = false;
        }
        else {
            print!("\n");
        }

        match Dir::readdir(Path::new(dir_name.clone())) {
            Ok(dir) => {
                if print_dir_names { println!("{}:", dir_name); }
                match opts.view {
                    Lines(ref cols) => lines_view(opts, cols, dir),
                    Grid(bool) => grid_view(opts, bool, dir),
                }
            }
            Err(e) => {
                println!("{}: {}", dir_name, e);
                return;
            }
        };
    }
}

fn grid_view(options: &Options, across: bool, dir: Dir) {
    let unsorted_files = dir.files();
    let files: Vec<&File> = options.transform_files(&unsorted_files);

    let max_column_length = files.iter().map(|f| f.name.len()).max().unwrap();
    let console_width = 80;
    let num_columns = (console_width + 1) / (max_column_length + 1);
    let count = files.len();

    let mut num_rows = count / num_columns;
    if count % num_columns != 0 {
        num_rows += 1;
    }

    for y in range(0, num_rows) {
        for x in range(0, num_columns) {
            let num = if across {
                y * num_columns + x
            }
            else {
                y + num_rows * x
            };

            if num >= count {
                continue;
            }

            let file = files.get(num);
            let file_name = file.name.clone();
            let styled_name = file.file_colour().paint(file_name.as_slice());
            print!("{}", Left.pad_string(&styled_name, max_column_length - file_name.len() + 1));
        }
        print!("\n");
    }
}

fn lines_view(options: &Options, columns: &Vec<Column>, dir: Dir) {
    let unsorted_files = dir.files();
    let files: Vec<&File> = options.transform_files(&unsorted_files);

    // The output gets formatted into columns, which looks nicer. To
    // do this, we have to write the results into a table, instead of
    // displaying each file immediately, then calculating the maximum
    // width of each column based on the length of the results and
    // padding the fields during output.

    let mut cache = Unix::empty_cache();

    let mut table: Vec<Vec<String>> = files.iter()
        .map(|f| columns.iter().map(|c| f.display(c, &mut cache)).collect())
        .collect();

    if options.header {
        table.unshift(columns.iter().map(|c| Plain.underline().paint(c.header())).collect());
    }

    // Each column needs to have its invisible colour-formatting
    // characters stripped before it has its width calculated, or the
    // width will be incorrect and the columns won't line up properly.
    // This is fairly expensive to do (it uses a regex), so the
    // results are cached.

    let lengths: Vec<Vec<uint>> = table.iter()
        .map(|row| row.iter().map(|col| strip_formatting(col.clone()).len()).collect())
        .collect();

    let column_widths: Vec<uint> = range(0, columns.len())
        .map(|n| lengths.iter().map(|row| *row.get(n)).max().unwrap())
        .collect();

    for (field_widths, row) in lengths.iter().zip(table.iter()) {
        for (num, column) in columns.iter().enumerate() {
            if num != 0 {
                print!(" ");
            }

            if num == columns.len() - 1 {
                print!("{}", row.get(num));
            }
            else {
                let padding = *column_widths.get(num) - *field_widths.get(num);
                print!("{}", column.alignment().pad_string(row.get(num), padding));
            }
        }
        print!("\n");
    }
}
<commit_msg>Don't pad the final column<commit_after>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
extern crate ansi_term;

use std::os;

use file::File;
use dir::Dir;
use column::{Column, Left};
use options::{Options, Lines, Grid};
use unix::Unix;

use ansi_term::{Paint, Plain, strip_formatting};

pub mod column;
pub mod dir;
pub mod format;
pub mod file;
pub mod filetype;
pub mod unix;
pub mod options;
pub mod sort;

fn main() {
    let args = os::args();

    match Options::getopts(args) {
        Err(err) => println!("Invalid options:\n{}", err),
        Ok(opts) => exa(&opts),
    };
}

fn exa(opts: &Options) {
    let mut first = true;

    // It's only worth printing out directory names if the user supplied
    // more than one of them.
    let print_dir_names = opts.dirs.len() > 1;

    for dir_name in opts.dirs.clone().move_iter() {
        if first {
            first = false;
        }
        else {
            print!("\n");
        }

        match Dir::readdir(Path::new(dir_name.clone())) {
            Ok(dir) => {
                if print_dir_names { println!("{}:", dir_name); }
                match opts.view {
                    Lines(ref cols) => lines_view(opts, cols, dir),
                    Grid(bool) => grid_view(opts, bool, dir),
                }
            }
            Err(e) => {
                println!("{}: {}", dir_name, e);
                return;
            }
        };
    }
}

fn grid_view(options: &Options, across: bool, dir: Dir) {
    let unsorted_files = dir.files();
    let files: Vec<&File> = options.transform_files(&unsorted_files);

    let max_column_length = files.iter().map(|f| f.name.len()).max().unwrap();
    let console_width = 80;
    let num_columns = (console_width + 1) / (max_column_length + 1);
    let count = files.len();

    let mut num_rows = count / num_columns;
    if count % num_columns != 0 {
        num_rows += 1;
    }

    for y in range(0, num_rows) {
        for x in range(0, num_columns) {
            let num = if across {
                y * num_columns + x
            }
            else {
                y + num_rows * x
            };

            if num >= count {
                continue;
            }

            let file = files.get(num);
            let file_name = file.name.clone();
            let styled_name = file.file_colour().paint(file_name.as_slice());
            if x == num_columns - 1 {
                print!("{}", styled_name);
            }
            else {
                print!("{}", Left.pad_string(&styled_name, max_column_length - file_name.len() + 1));
            }
        }
        print!("\n");
    }
}

fn lines_view(options: &Options, columns: &Vec<Column>, dir: Dir) {
    let unsorted_files = dir.files();
    let files: Vec<&File> = options.transform_files(&unsorted_files);

    // The output gets formatted into columns, which looks nicer. To
    // do this, we have to write the results into a table, instead of
    // displaying each file immediately, then calculating the maximum
    // width of each column based on the length of the results and
    // padding the fields during output.

    let mut cache = Unix::empty_cache();

    let mut table: Vec<Vec<String>> = files.iter()
        .map(|f| columns.iter().map(|c| f.display(c, &mut cache)).collect())
        .collect();

    if options.header {
        table.unshift(columns.iter().map(|c| Plain.underline().paint(c.header())).collect());
    }

    // Each column needs to have its invisible colour-formatting
    // characters stripped before it has its width calculated, or the
    // width will be incorrect and the columns won't line up properly.
    // This is fairly expensive to do (it uses a regex), so the
    // results are cached.

    let lengths: Vec<Vec<uint>> = table.iter()
        .map(|row| row.iter().map(|col| strip_formatting(col.clone()).len()).collect())
        .collect();

    let column_widths: Vec<uint> = range(0, columns.len())
        .map(|n| lengths.iter().map(|row| *row.get(n)).max().unwrap())
        .collect();

    for (field_widths, row) in lengths.iter().zip(table.iter()) {
        for (num, column) in columns.iter().enumerate() {
            if num != 0 {
                print!(" ");
            }

            if num == columns.len() - 1 {
                print!("{}", row.get(num));
            }
            else {
                let padding = *column_widths.get(num) - *field_widths.get(num);
                print!("{}", column.alignment().pad_string(row.get(num), padding));
            }
        }
        print!("\n");
    }
}
<|endoftext|>


<commit_before>#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]

#[miri_run(expected = "Int(1)")]
fn ret() -> i32 {
    1
}

#[miri_run(expected = "Int(-1)")]
fn neg() -> i32 {
    -1
}

#[miri_run(expected = "Int(3)")]
fn add() -> i32 {
    1 + 2
}

#[miri_run(expected = "Int(3)")]
fn indirect_add() -> i32 {
    let x = 1;
    let y = 2;
    x + y
}

#[miri_run(expected = "Int(25)")]
fn arith() -> i32 {
    3*3 + 4*4
}

#[miri_run(expected = "Int(0)")]
fn if_false() -> i32 {
    if false { 1 } else { 0 }
}

#[miri_run(expected = "Int(1)")]
fn if_true() -> i32 {
    if true { 1 } else { 0 }
}

#[miri_run(expected = "Int(2)")]
fn call() -> i32 {
    fn increment(x: i32) -> i32 {
        x + 1
    }

    increment(1)
}

#[miri_run(expected = "Int(3628800)")]
fn factorial_loop() -> i32 {
    let mut product = 1;
    let mut i = 1;

    while i <= 10 {
        product *= i;
        i += 1;
    }

    product
}

#[miri_run(expected = "Int(3628800)")]
fn factorial_recursive() -> i32 {
    fn fact(n: i32) -> i32 {
        if n == 0 {
            1
        } else {
            n * fact(n - 1)
        }
    }

    fact(10)
}

#[miri_run(expected = "Int(1)")]
fn match_bool() -> i32 {
    let b = true;
    match b {
        true => 1,
        false => 0,
    }
}

#[miri_run(expected = "Int(20)")]
fn match_int() -> i32 {
    let n = 2;
    match n {
        0 => 0,
        1 => 10,
        2 => 20,
        3 => 30,
        _ => 100,
    }
}

#[miri_run(expected = "Int(1)")]
fn one_line_ref() -> i32 {
    *&1
}

#[miri_run(expected = "Int(1)")]
fn basic_ref() -> i32 {
    let x = &1;
    *x
}

#[miri_run(expected = "Int(3)")]
fn basic_ref_mut() -> i32 {
    let x = &mut 1;
    *x += 2;
    *x
}

#[miri_run(expected = "Int(3)")]
fn basic_ref_mut_var() -> i32 {
    let mut a = 1;
    {
        let x = &mut a;
        *x += 2;
    }
    a
}

#[miri_run(expected = "Int(4)")]
fn match_int_range() -> i32 {
    let n = 42;
    match n {
        0...9 => 0,
        10...19 => 1,
        20...29 => 2,
        30...39 => 3,
        40...49 => 4,
        _ => 5,
    }
}

enum MyOption<T> {
    Some { data: T },
    None,
}

#[miri_run(expected = "Int(13)")]
fn match_my_opt_some() -> i32 {
    let x = MyOption::Some { data: 13 };
    match x {
        MyOption::Some { data } => data,
        MyOption::None => 42,
    }
}

#[miri_run(expected = "Int(42)")]
fn match_my_opt_none() -> i32 {
    let x = MyOption::None;
    match x {
        MyOption::Some { data } => data,
        MyOption::None => 42,
    }
}

// #[miri_run(expected = "Int(13)")]
// fn match_opt_some() -> i32 {
//     let x = Some(13);
//     match x {
//         Some(data)  => data,
//         None => 42,
//     }
// }

/// Test calling a very simple function from the standard library.
#[miri_run(expected = "Int(1)")]
fn cross_crate_fn_call() -> i32 {
    if 1i32.is_positive() { 1 } else { 0 }
}

fn main() {}
<commit_msg>Disable tests that fail on rustc master due to () rvalues.<commit_after>#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]

#[miri_run(expected = "Int(1)")]
fn ret() -> i32 {
    1
}

#[miri_run(expected = "Int(-1)")]
fn neg() -> i32 {
    -1
}

#[miri_run(expected = "Int(3)")]
fn add() -> i32 {
    1 + 2
}

#[miri_run(expected = "Int(3)")]
fn indirect_add() -> i32 {
    let x = 1;
    let y = 2;
    x + y
}

#[miri_run(expected = "Int(25)")]
fn arith() -> i32 {
    3*3 + 4*4
}

#[miri_run(expected = "Int(0)")]
fn if_false() -> i32 {
    if false { 1 } else { 0 }
}

#[miri_run(expected = "Int(1)")]
fn if_true() -> i32 {
    if true { 1 } else { 0 }
}

#[miri_run(expected = "Int(2)")]
fn call() -> i32 {
    fn increment(x: i32) -> i32 {
        x + 1
    }

    increment(1)
}

// #[miri_run(expected = "Int(3628800)")]
// fn factorial_loop() -> i32 {
//     let mut product = 1;
//     let mut i = 1;

//     while i <= 10 {
//         product *= i;
//         i += 1;
//     }

//     product
// }

#[miri_run(expected = "Int(3628800)")]
fn factorial_recursive() -> i32 {
    fn fact(n: i32) -> i32 {
        if n == 0 {
            1
        } else {
            n * fact(n - 1)
        }
    }

    fact(10)
}

#[miri_run(expected = "Int(1)")]
fn match_bool() -> i32 {
    let b = true;
    match b {
        true => 1,
        false => 0,
    }
}

#[miri_run(expected = "Int(20)")]
fn match_int() -> i32 {
    let n = 2;
    match n {
        0 => 0,
        1 => 10,
        2 => 20,
        3 => 30,
        _ => 100,
    }
}

#[miri_run(expected = "Int(1)")]
fn one_line_ref() -> i32 {
    *&1
}

#[miri_run(expected = "Int(1)")]
fn basic_ref() -> i32 {
    let x = &1;
    *x
}

#[miri_run(expected = "Int(3)")]
fn basic_ref_mut() -> i32 {
    let x = &mut 1;
    *x += 2;
    *x
}

// #[miri_run(expected = "Int(3)")]
// fn basic_ref_mut_var() -> i32 {
//     let mut a = 1;
//     {
//         let x = &mut a;
//         *x += 2;
//     }
//     a
// }

#[miri_run(expected = "Int(4)")]
fn match_int_range() -> i32 {
    let n = 42;
    match n {
        0...9 => 0,
        10...19 => 1,
        20...29 => 2,
        30...39 => 3,
        40...49 => 4,
        _ => 5,
    }
}

enum MyOption<T> {
    Some { data: T },
    None,
}

#[miri_run(expected = "Int(13)")]
fn match_my_opt_some() -> i32 {
    let x = MyOption::Some { data: 13 };
    match x {
        MyOption::Some { data } => data,
        MyOption::None => 42,
    }
}

#[miri_run(expected = "Int(42)")]
fn match_my_opt_none() -> i32 {
    let x = MyOption::None;
    match x {
        MyOption::Some { data } => data,
        MyOption::None => 42,
    }
}

// #[miri_run(expected = "Int(13)")]
// fn match_opt_some() -> i32 {
//     let x = Some(13);
//     match x {
//         Some(data)  => data,
//         None => 42,
//     }
// }

/// Test calling a very simple function from the standard library.
#[miri_run(expected = "Int(1)")]
fn cross_crate_fn_call() -> i32 {
    if 1i32.is_positive() { 1 } else { 0 }
}

fn main() {}
<|endoftext|>


<commit_before>#![allow(non_uppercase_statics)]
#![allow(non_camel_case_types)]

use libc::*;
use xlib::Display;

pub struct XineramaScreenInfo {
   screen_number: c_int,
   x_org : c_short,
   y_org : c_short,
   width : c_short,
   height : c_short
}

#[link(name="Xinerama")]
extern {
	pub fn XineramaIsActive(dpy: *mut Display) -> c_int;
	pub fn XineramaQueryScreens(dpy: *mut Display, number: *mut c_int) -> *const XineramaScreenInfo;
}
<commit_msg>added functions<commit_after>#![allow(non_uppercase_statics)]
#![allow(non_camel_case_types)]

use libc::*;
use xlib::Display;
use xlib::Window;
use xlib::Drawable;
use xlib::XID;

#[repr(C)]
pub struct XineramaScreenInfo {
   screen_number: c_int,
   x_org : c_short,
   y_org : c_short,
   width : c_short,
   height : c_short
}

#[repr(C)]
pub struct XPanoramiXInfo {
    window: Window,
    screen: c_int,
    State: c_int,
    width: c_int,
    height: c_int,
    ScreenCount: c_int,
    eventMask: XID
}

#[link(name="Xinerama")]
extern {
    pub fn XPanoramiXGetState(dpy: *mut Display, drawable: Drawable, panoramix_info: *mut XPanoramiXInfo) -> c_int;
    pub fn XPanoramiXGetScreenCount(dpy: *mut Display, drawable: Drawable, panoramix_info: *mut XPanoramiXInfo) -> c_int;
    pub fn XPanoramiXGetScreenSize(dpy: *mut Display, drawable: Drawable, screen_num: c_int, panoramix_info: *mut XPanoramiXInfo) -> c_int;
    pub fn XineramaQueryExtension(dpy: *mut Display, event: *mut c_int, error: *mut c_int) -> c_int;
    pub fn XineramaQueryVersion(dpy: *mut Display, major: *mut c_int, minor: *mut c_int) -> c_int;
	pub fn XineramaIsActive(dpy: *mut Display) -> c_int;
	pub fn XineramaQueryScreens(dpy: *mut Display, number: *mut c_int) -> *const XineramaScreenInfo;
}
<|endoftext|>


<commit_before>extern crate xlib;

use std::ptr;
use xlib::{ Display, Window, XDefaultScreenOfDisplay, XOpenDisplay, XQueryExtension, XRootWindowOfScreen };

//
// X Extension Linking
//

#[link(name = "Xcomposite")]
extern {
  fn XCompositeQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

#[link(name = "Xdamage")]
extern {
  fn XDamageQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

#[link(name = "Xext")]
extern {
  fn XShapeQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

#[link(name = "Xfixes")]
extern {
  fn XFixesQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

#[link(name = "Xrender")]
extern {
  fn XRenderQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

//
// XServer Struct
//

pub struct XServer {
  display: *mut Display,
  root:         Window
}

impl XServer {
  pub fn new() -> XServer {
    unsafe {
      let display = XOpenDisplay(ptr::null_mut());
      if display.is_null() {
        panic!("Could not open display!");
      }

      let screen = XDefaultScreenOfDisplay(display);
      let root = XRootWindowOfScreen(screen);

      XServer {
        display: display,
        root: root
      }
    }
  }
}

pub fn query_extension(xserver: &XServer, name: &str) {
  let mut event_base = &mut 0;
  let mut error_base = &mut 0;

  unsafe {
    match name {
      "Xcomposite" => if XCompositeQueryExtension(xserver.display, event_base, error_base) == 0 {
                        panic!("No XComposite extension!");
                      },
      "Xdamage" => if XDamageQueryExtension(xserver.display, event_base, error_base) == 0 {
                     panic!("No XDamage extension!");
                   },
      "Xfixes" => if XFixesQueryExtension(xserver.display, event_base, error_base) == 0 {
                    panic!("No XFixes extension!");
                  },
      "Xrender" => if XRenderQueryExtension(xserver.display, event_base, error_base) == 0 {
                     panic!("No XRender extension!");
                   },
      "Xshape" => if XShapeQueryExtension(xserver.display, event_base, error_base) == 0 {
                    panic!("No XShape extension!");
                  },
      _ => panic!(format!("Don't know how to query for {} extension", name)),
    }
  }
}
<commit_msg>Add XWMHints type and link against Xutf8SetWMProps<commit_after>extern crate xlib;

use libc::*;
use std::ptr;
use std::ffi;
use xlib::{ Display, Pixmap, Window, XClassHint, XDefaultScreenOfDisplay, XID, XOpenDisplay, XRootWindowOfScreen, XSizeHints };

//
// XWMHints Type and Linking Against Xutf8SetWMProperties
//

#[repr(C)]
pub struct struct__XWMHints {
  pub flags: c_long,
  pub input: c_int,
  pub initial_state: c_int,
  pub icon_pixmap: Pixmap,
  pub icon_window: Window,
  pub icon_x: c_int,
  pub icon_y: c_int,
  pub icon_mask: Pixmap,
  pub window_group: XID,
}

pub type XWMHints = struct__XWMHints;

#[link(name = "X11")]
extern {
  fn Xutf8SetWMProperties(display: *mut Display, window: Window, window_name: *mut c_char,
                          icon_name: *mut c_char, argv: *mut *mut c_char, argc: i32,
                          normal_hints: *mut XSizeHints, wm_hints: *mut XWMHints,
                          class_hints: *mut XClassHint);
}

//
// X Extension Linking
//

#[link(name = "Xcomposite")]
extern {
  fn XCompositeQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

#[link(name = "Xdamage")]
extern {
  fn XDamageQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

#[link(name = "Xext")]
extern {
  fn XShapeQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

#[link(name = "Xfixes")]
extern {
  fn XFixesQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

#[link(name = "Xrender")]
extern {
  fn XRenderQueryExtension(display: *mut Display, event: *mut i32, error: *mut i32) -> i32;
}

//
// XServer Struct
//

pub struct XServer {
  display: *mut Display,
  root:         Window
}

impl XServer {
  pub fn new() -> XServer {
    unsafe {
      let display = XOpenDisplay(ptr::null_mut());
      if display.is_null() {
        panic!("Could not open display!");
      }

      let screen = XDefaultScreenOfDisplay(display);
      let root = XRootWindowOfScreen(screen);

      XServer {
        display: display,
        root: root
      }
    }
  }
}

pub fn query_extension(xserver: &XServer, name: &str) {
  let mut event_base = &mut 0;
  let mut error_base = &mut 0;

  unsafe {
    match name {
      "Xcomposite" => if XCompositeQueryExtension(xserver.display, event_base, error_base) == 0 {
                        panic!("No XComposite extension!");
                      },
      "Xdamage" => if XDamageQueryExtension(xserver.display, event_base, error_base) == 0 {
                     panic!("No XDamage extension!");
                   },
      "Xfixes" => if XFixesQueryExtension(xserver.display, event_base, error_base) == 0 {
                    panic!("No XFixes extension!");
                  },
      "Xrender" => if XRenderQueryExtension(xserver.display, event_base, error_base) == 0 {
                     panic!("No XRender extension!");
                   },
      "Xshape" => if XShapeQueryExtension(xserver.display, event_base, error_base) == 0 {
                    panic!("No XShape extension!");
                  },
      _ => panic!(format!("Don't know how to query for {} extension", name)),
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>Forbid tarballs with hard links being uploaded<commit_after><|endoftext|>


<commit_before>//! Use this library to open a path or URL using the program configured on the system.
//!
//! # Usage
//!
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::that("/path/to/file/with.fancy-extension");
//! if open::that("https://rust-lang.org").is_ok() {
//!     println!("Look at your browser !");
//! }
//! # }
//! ```
//!
//! # Notes
//! As an operating system program is used, chances are that the open operation fails.
//! Therfore, you are advised to at least check the result with `.is_err()` and
//! behave accordingly, e.g. by letting the user know what you tried to open, and failed.
use std::io;
use std::process::{Command, ExitStatus};
use std::ffi::OsStr;

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
pub fn that<T:AsRef<OsStr>+Sized>(path: T) -> io::Result<ExitStatus> {
    let mut last_err: io::Result<ExitStatus> = Err(io::Error::from_raw_os_error(0));
    for program in &["xdg-open", "gnome-open", "kde-open"] {
        match Command::new(program).arg(path.as_ref()).spawn() {
            Ok(mut child) => return child.wait(),
            Err(err) => {
                last_err = Err(err);
                continue;
            },
        }
    }
    last_err
}

#[cfg(target_os = "windows")]
pub fn that<T:AsRef<OsStr>+Sized>(path: T) -> io::Result<ExitStatus> {
    try!(Command::new("cmd").arg("/C").arg("start").arg(path.as_ref()).spawn()).wait()
}

#[cfg(target_os = "macos")]
pub fn that<T:AsRef<OsStr>+Sized>(path: T) -> io::Result<ExitStatus> {
    try!(Command::new("open").arg(path.as_ref()).spawn()).wait()
}
<commit_msg>Escape GET parameters for Windows<commit_after>//! Use this library to open a path or URL using the program configured on the system.
//!
//! # Usage
//!
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::that("/path/to/file/with.fancy-extension");
//! if open::that("https://rust-lang.org").is_ok() {
//!     println!("Look at your browser !");
//! }
//! # }
//! ```
//!
//! # Notes
//! As an operating system program is used, chances are that the open operation fails.
//! Therfore, you are advised to at least check the result with `.is_err()` and
//! behave accordingly, e.g. by letting the user know what you tried to open, and failed.
use std::io;
use std::process::{Command, ExitStatus};
use std::ffi::OsStr;

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
pub fn that<T:AsRef<OsStr>+Sized>(path: T) -> io::Result<ExitStatus> {
    let mut last_err: io::Result<ExitStatus> = Err(io::Error::from_raw_os_error(0));
    for program in &["xdg-open", "gnome-open", "kde-open"] {
        match Command::new(program).arg(path.as_ref()).spawn() {
            Ok(mut child) => return child.wait(),
            Err(err) => {
                last_err = Err(err);
                continue;
            },
        }
    }
    last_err
}

#[cfg(target_os = "windows")]
pub fn that<T:AsRef<OsStr>+Sized>(path: T) -> io::Result<ExitStatus> {
    let mut cmd = Command::new("cmd");
    cmd.arg("/C").arg("start");
    if let Some(s) = path.as_ref().to_str() {
        cmd.arg(s.replace("&", "^&"));
    } else {
        cmd.arg(path.as_ref());
    }
    try!(cmd.spawn()).wait()
}

#[cfg(target_os = "macos")]
pub fn that<T:AsRef<OsStr>+Sized>(path: T) -> io::Result<ExitStatus> {
    try!(Command::new("open").arg(path.as_ref()).spawn()).wait()
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std::io::Cursor;
use byteorder::{LittleEndian,ReadBytesExt};

const CHUNK_SIZE: usize = 32;

const PRIME64_1: u64 = 11400714785074694791;
const PRIME64_2: u64 = 14029467366897019727;
const PRIME64_3: u64 = 1609587929392839161;
const PRIME64_4: u64 = 9650029242287828579;
const PRIME64_5: u64 = 2870177450012600261;

#[derive(Copy,Clone,PartialEq)]
struct XxCore {
    v1: u64,
    v2: u64,
    v3: u64,
    v4: u64,
}

#[derive(Debug,Copy,Clone)]
pub struct XxHash {
    total_len: u64,
    seed: u64,
    core: XxCore,
    buffer: [u8; CHUNK_SIZE],
    buffer_usage: usize,
}

impl XxCore {
    fn from_seed(seed: u64) -> XxCore {
        XxCore {
            v1: seed.wrapping_add(PRIME64_1).wrapping_add(PRIME64_2),
            v2: seed.wrapping_add(PRIME64_2),
            v3: seed,
            v4: seed.wrapping_sub(PRIME64_1),
        }
    }

    #[inline(always)]
    fn ingest_one_chunk(&mut self, bytes: &[u8]) {
        let mut rdr = Cursor::new(bytes);

        let mut do_one_number = |mut my_v: u64| -> u64 {
            let v = rdr.read_u64::<LittleEndian>().unwrap();
            let v = v.wrapping_mul(PRIME64_2);
            my_v = my_v.wrapping_add(v);
            my_v = my_v.rotate_left(31);
            my_v.wrapping_mul(PRIME64_1)
        };

        self.v1 = do_one_number(self.v1);
        self.v2 = do_one_number(self.v2);
        self.v3 = do_one_number(self.v3);
        self.v4 = do_one_number(self.v4);
    }
}

impl std::fmt::Debug for XxCore {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(
            f, "XxCore {{ {:016x} {:016x} {:016x} {:016x} }}",
            self.v1, self.v2, self.v3, self.v4
        )
    }
}

impl XxHash {
    pub fn from_seed(seed: u64) -> XxHash {
        XxHash {
            total_len: 0,
            seed: seed,
            core: XxCore::from_seed(seed),
            buffer: [0; CHUNK_SIZE],
            buffer_usage: 0,
        }
    }
}

impl XxHash {
    pub fn write(&mut self, bytes: &[u8]) {
        let mut bytes = bytes;

        self.total_len += bytes.len() as u64;

        // Even with new data, we still don't have a full buffer. Wait
        // until we have a full buffer.
        if self.buffer_usage + bytes.len() < self.buffer.len() {
            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                std::ptr::copy_nonoverlapping(bytes.as_ptr(), tail, bytes.len());
            }
            self.buffer_usage += bytes.len();
            return;
        }

        // Some data left from previous update. Fill the buffer and
        // consume it first.
        if self.buffer_usage > 0 {
            let bytes_to_use = self.buffer.len() - self.buffer_usage;
            let (to_use, leftover) = bytes.split_at(bytes_to_use);

            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                std::ptr::copy_nonoverlapping(to_use.as_ptr(), tail, bytes_to_use);
            }

            self.core.ingest_one_chunk(&self.buffer);

            bytes = leftover;
            self.buffer_usage = 0;
        }

        // Consume the input data in large chunks
        if bytes.len() >= CHUNK_SIZE {
            // TODO: The original code pulls out local vars for
            // v[1234], presumably for performance
            // reasons. Investigate.

            let full_chunks = bytes.len() / CHUNK_SIZE;
            let (to_use, leftover) = bytes.split_at(full_chunks * CHUNK_SIZE);

            for chunk in to_use.chunks(CHUNK_SIZE) {
                self.core.ingest_one_chunk(chunk);
            }

            bytes = leftover;
        }

        // Save any leftover data for the next call
        if bytes.len() > 0 {
            unsafe {
                std::ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.as_mut_ptr(), bytes.len());
            }
            self.buffer_usage = bytes.len();
        }
    }
}

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

    #[test]
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
        let bytes: Vec<_> = (0..32).map(|_| 0).collect();

        let mut byte_by_byte = XxHash::from_seed(0);
        for byte in bytes.chunks(1) {
            byte_by_byte.write(byte);
        }

        let mut one_chunk = XxHash::from_seed(0);
        one_chunk.write(&bytes);

        assert_eq!(byte_by_byte.core, one_chunk.core);
    }
}
<commit_msg>Add finish method<commit_after>#![feature(core)]

extern crate byteorder;

use std::io::Cursor;
use byteorder::{LittleEndian,ReadBytesExt};

const CHUNK_SIZE: usize = 32;

const PRIME64_1: u64 = 11400714785074694791;
const PRIME64_2: u64 = 14029467366897019727;
const PRIME64_3: u64 = 1609587929392839161;
const PRIME64_4: u64 = 9650029242287828579;
const PRIME64_5: u64 = 2870177450012600261;

#[derive(Copy,Clone,PartialEq)]
struct XxCore {
    v1: u64,
    v2: u64,
    v3: u64,
    v4: u64,
}

#[derive(Debug,Copy,Clone)]
pub struct XxHash {
    total_len: u64,
    seed: u64,
    core: XxCore,
    buffer: [u8; CHUNK_SIZE],
    buffer_usage: usize,
}

impl XxCore {
    fn from_seed(seed: u64) -> XxCore {
        XxCore {
            v1: seed.wrapping_add(PRIME64_1).wrapping_add(PRIME64_2),
            v2: seed.wrapping_add(PRIME64_2),
            v3: seed,
            v4: seed.wrapping_sub(PRIME64_1),
        }
    }

    #[inline(always)]
    fn ingest_one_chunk(&mut self, bytes: &[u8]) {
        let mut rdr = Cursor::new(bytes);

        let mut do_one_number = |mut my_v: u64| -> u64 {
            let v = rdr.read_u64::<LittleEndian>().unwrap();
            let v = v.wrapping_mul(PRIME64_2);
            my_v = my_v.wrapping_add(v);
            my_v = my_v.rotate_left(31);
            my_v.wrapping_mul(PRIME64_1)
        };

        self.v1 = do_one_number(self.v1);
        self.v2 = do_one_number(self.v2);
        self.v3 = do_one_number(self.v3);
        self.v4 = do_one_number(self.v4);
    }

    #[inline(always)]
    fn finish(&self) -> u64 {
        let mut hash;

        hash =                   self.v1.rotate_left( 1);
        hash = hash.wrapping_add(self.v2.rotate_left( 7));
        hash = hash.wrapping_add(self.v3.rotate_left(12));
        hash = hash.wrapping_add(self.v4.rotate_left(18));

        #[inline(always)]
        fn mix_one(mut hash: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME64_2);
            value = value.rotate_left(31);
            value = value.wrapping_mul(PRIME64_1);
            hash ^= value;
            hash = hash.wrapping_mul(PRIME64_1);
            hash.wrapping_add(PRIME64_4)
        }

        hash = mix_one(hash, self.v1);
        hash = mix_one(hash, self.v2);
        hash = mix_one(hash, self.v3);
        hash = mix_one(hash, self.v4);

        hash
    }
}

impl std::fmt::Debug for XxCore {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(
            f, "XxCore {{ {:016x} {:016x} {:016x} {:016x} }}",
            self.v1, self.v2, self.v3, self.v4
        )
    }
}

impl XxHash {
    pub fn from_seed(seed: u64) -> XxHash {
        XxHash {
            total_len: 0,
            seed: seed,
            core: XxCore::from_seed(seed),
            buffer: [0; CHUNK_SIZE],
            buffer_usage: 0,
        }
    }
}

#[inline(always)]
fn split_at_maximum_chunk_size(bytes: &[u8], chunk_size: usize) -> (&[u8], &[u8]) {
    let full_chunks = bytes.len() / chunk_size;
    bytes.split_at(full_chunks * chunk_size)
}

impl XxHash {
    pub fn write(&mut self, bytes: &[u8]) {
        let mut bytes = bytes;

        self.total_len += bytes.len() as u64;

        // Even with new data, we still don't have a full buffer. Wait
        // until we have a full buffer.
        if self.buffer_usage + bytes.len() < self.buffer.len() {
            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                std::ptr::copy_nonoverlapping(bytes.as_ptr(), tail, bytes.len());
            }
            self.buffer_usage += bytes.len();
            return;
        }

        // Some data left from previous update. Fill the buffer and
        // consume it first.
        if self.buffer_usage > 0 {
            let bytes_to_use = self.buffer.len() - self.buffer_usage;
            let (to_use, leftover) = bytes.split_at(bytes_to_use);

            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                std::ptr::copy_nonoverlapping(to_use.as_ptr(), tail, bytes_to_use);
            }

            self.core.ingest_one_chunk(&self.buffer);

            bytes = leftover;
            self.buffer_usage = 0;
        }

        // Consume the input data in large chunks
        if bytes.len() >= CHUNK_SIZE {
            // TODO: The original code pulls out local vars for
            // v[1234], presumably for performance
            // reasons. Investigate.

            let (to_use, leftover) = split_at_maximum_chunk_size(bytes, CHUNK_SIZE);

            for chunk in to_use.chunks(CHUNK_SIZE) {
                self.core.ingest_one_chunk(chunk);
            }

            bytes = leftover;
        }

        // Save any leftover data for the next call
        if bytes.len() > 0 {
            unsafe {
                std::ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.as_mut_ptr(), bytes.len());
            }
            self.buffer_usage = bytes.len();
        }
    }

    pub fn finish(&self) -> u64 {
        let mut hash;

        // We have processed at least one full chunk
        if self.total_len >= CHUNK_SIZE as u64 {
            // TODO: The original code pulls out local vars for
            // v[1234], presumably for performance
            // reasons. Investigate.

            hash = self.core.finish();
        } else {
            hash = self.seed.wrapping_add(PRIME64_5);
        }

        hash = hash.wrapping_add(self.total_len);

        let buffered = &self.buffer[..self.buffer_usage];
        let (buffered_u64s, buffered) = split_at_maximum_chunk_size(buffered, 8);

        // TODO: Should we create the cursor out here and just iterate
        // until not enough?
        for buffered_u64 in buffered_u64s.chunks(8) {
            let mut rdr = Cursor::new(buffered_u64);
            let mut k1 = rdr.read_u64::<LittleEndian>().unwrap();
            k1 = k1.wrapping_mul(PRIME64_2);
            k1 = k1.rotate_left(31);
            k1 = k1.wrapping_mul(PRIME64_1);
            hash ^= k1;
            hash = hash.rotate_left(27);
            hash = hash.wrapping_mul(PRIME64_1);
            hash = hash.wrapping_add(PRIME64_4);
        }

        let (buffered_u32s, buffered) = split_at_maximum_chunk_size(buffered, 4);

        for buffered_u32 in buffered_u32s.chunks(4) {
            let mut rdr = Cursor::new(buffered_u32);
            let mut k1 = rdr.read_u32::<LittleEndian>().unwrap() as u64;
            k1 = k1.wrapping_mul(PRIME64_1);
            hash ^= k1;
            hash = hash.rotate_left(23);
            hash = hash.wrapping_mul(PRIME64_2);
            hash = hash.wrapping_add(PRIME64_3);
        }

        for buffered_u8 in buffered {
            let k1 = (*buffered_u8 as u64).wrapping_mul(PRIME64_5);
            hash ^= k1;
            hash = hash.rotate_left(11);
            hash = hash.wrapping_mul(PRIME64_1);
        }

        // The final intermixing
        hash ^= hash.wrapping_shr(33);
        hash = hash.wrapping_mul(PRIME64_2);
        hash ^= hash.wrapping_shr(29);
        hash = hash.wrapping_mul(PRIME64_3);
        hash ^= hash.wrapping_shr(32);

        hash
    }
}

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

    #[test]
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
        let bytes: Vec<_> = (0..32).map(|_| 0).collect();

        let mut byte_by_byte = XxHash::from_seed(0);
        for byte in bytes.chunks(1) {
            byte_by_byte.write(byte);
        }

        let mut one_chunk = XxHash::from_seed(0);
        one_chunk.write(&bytes);

        assert_eq!(byte_by_byte.core, one_chunk.core);
    }

    #[test]
    fn hash_of_nothing_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0xef46db3751d8e999);
    }

    #[test]
    fn hash_of_single_byte_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&[42]);
        assert_eq!(hasher.finish(), 0x0a9edecebeb03ae4);
    }

    #[test]
    fn hash_of_multiple_bytes_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(b"Hello, world!\0");
        assert_eq!(hasher.finish(), 0x7b06c531ea43e89f);
    }

    #[test]
    fn hash_of_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x6ac1e58032166597);
    }

    #[test]
    fn hash_with_different_seed_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0xae0543311b702d91);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0x4b6a04fcdf7a4672);
    }

    #[test]
    fn hash_with_different_seed_and_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::from_seed(0xae0543311b702d91);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x567e355e0682e1f1);
    }
}
<|endoftext|>