<commit_before>
#[macro_use]
extern crate nom;

use nom::{IResult,not_line_ending, space, alphanumeric, multispace};

use std::str;
use std::collections::HashMap;

named!(category     <&[u8], &str>,
  chain!(
          tag!("[")       ~
    name: map_res!(
      take_until!("]"),
      str::from_utf8)     ~
          tag!("]")       ~
          multispace?     ,
    ||{ name }
  )
);

named!(key_value    <&[u8],(&str,&str)>,
  chain!(
    key: map_res!(alphanumeric, std::str::from_utf8) ~
         space?                            ~
         tag!("=")                         ~
         space?                            ~
    val: map_res!(
           take_until_either!("\n;"),
           str::from_utf8
         )                                 ~
         space?                            ~
         chain!(
           tag!(";")        ~
           not_line_ending  ,
           ||{}
         ) ?                               ~
         multispace?                       ,
    ||{(key, val)}
  )
);

named!(keys_and_values_aggregator<&[u8], Vec<(&str,&str)> >, many0!(key_value));

fn keys_and_values(input:&[u8]) -> IResult<&[u8], HashMap<&str, &str> > {
  let mut h: HashMap<&str, &str> = HashMap::new();

  match keys_and_values_aggregator(input) {
    IResult::Done(i,tuple_vec) => {
      for &(k,v) in tuple_vec.iter() {
        h.insert(k, v);
      }
      IResult::Done(i, h)
    },
    IResult::Incomplete(a)     => IResult::Incomplete(a),
    IResult::Error(a)          => IResult::Error(a)
  }
}

named!(category_and_keys<&[u8],(&str,HashMap<&str,&str>)>,
  chain!(
    category: category    ~
    keys: keys_and_values ,
    move ||{(category, keys)}
  )
);

named!(categories_aggregator<&[u8], Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));

fn categories(input: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str> > > {
  let mut h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();

  match categories_aggregator(input) {
    IResult::Done(i,tuple_vec) => {
      for &(k,ref v) in tuple_vec.iter() {
        h.insert(k, v.clone());
      }
      IResult::Done(i, h)
    },
    IResult::Incomplete(a)     => IResult::Incomplete(a),
    IResult::Error(a)          => IResult::Error(a)
  }
}

#[test]
fn parse_category_test() {
  let ini_file = &b"[category]

parameter=value
key = value2"[..];

  let ini_without_category = &b"parameter=value
key = value2"[..];

  let res = category(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_category, "category"));
}

#[test]
fn parse_key_value_test() {
  let ini_file = &b"parameter=value
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_key_value_with_space_test() {
  let ini_file = &b"parameter = value
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_key_value_with_comment_test() {
  let ini_file = &b"parameter=value;abc
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_multiple_keys_and_values_test() {
  let ini_file = &b"parameter=value;abc

key = value2

[category]"[..];

  let ini_without_key_value = &b"[category]"[..];

  let res = keys_and_values(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected: HashMap<&str, &str> = HashMap::new();
  expected.insert("parameter", "value");
  expected.insert("key", "value2");
  assert_eq!(res, IResult::Done(ini_without_key_value, expected));
}

#[test]
fn parse_category_then_multiple_keys_and_values_test() {
  //FIXME: there can be an empty line or a comment line after a category
  let ini_file = &b"[abcd]
parameter=value;abc

key = value2

[category]"[..];

  let ini_after_parser = &b"[category]"[..];

  let res = category_and_keys(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected_h: HashMap<&str, &str> = HashMap::new();
  expected_h.insert("parameter", "value");
  expected_h.insert("key", "value2");
  assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
}

#[test]
fn parse_multiple_categories_test() {
  let ini_file = &b"[abcd]

parameter=value;abc

key = value2

[category]
parameter3=value3
key4 = value4
"[..];

  let ini_after_parser = &b""[..];

  let res = categories(ini_file);
  //println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected_1: HashMap<&str, &str> = HashMap::new();
  expected_1.insert("parameter", "value");
  expected_1.insert("key", "value2");
  let mut expected_2: HashMap<&str, &str> = HashMap::new();
  expected_2.insert("parameter3", "value3");
  expected_2.insert("key4", "value4");
  let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
  expected_h.insert("abcd",     expected_1);
  expected_h.insert("category", expected_2);
  assert_eq!(res, IResult::Done(ini_after_parser, expected_h));
}
<commit_msg>Use for _ in &vec {} instead of for _ in vec.iter() {}<commit_after>
#[macro_use]
extern crate nom;

use nom::{IResult,not_line_ending, space, alphanumeric, multispace};

use std::str;
use std::collections::HashMap;

named!(category     <&[u8], &str>,
  chain!(
          tag!("[")       ~
    name: map_res!(
      take_until!("]"),
      str::from_utf8)     ~
          tag!("]")       ~
          multispace?     ,
    ||{ name }
  )
);

named!(key_value    <&[u8],(&str,&str)>,
  chain!(
    key: map_res!(alphanumeric, std::str::from_utf8) ~
         space?                            ~
         tag!("=")                         ~
         space?                            ~
    val: map_res!(
           take_until_either!("\n;"),
           str::from_utf8
         )                                 ~
         space?                            ~
         chain!(
           tag!(";")        ~
           not_line_ending  ,
           ||{}
         ) ?                               ~
         multispace?                       ,
    ||{(key, val)}
  )
);

named!(keys_and_values_aggregator<&[u8], Vec<(&str,&str)> >, many0!(key_value));

fn keys_and_values(input:&[u8]) -> IResult<&[u8], HashMap<&str, &str> > {
  let mut h: HashMap<&str, &str> = HashMap::new();

  match keys_and_values_aggregator(input) {
    IResult::Done(i,tuple_vec) => {
      for &(k,v) in &tuple_vec {
        h.insert(k, v);
      }
      IResult::Done(i, h)
    },
    IResult::Incomplete(a)     => IResult::Incomplete(a),
    IResult::Error(a)          => IResult::Error(a)
  }
}

named!(category_and_keys<&[u8],(&str,HashMap<&str,&str>)>,
  chain!(
    category: category    ~
    keys: keys_and_values ,
    move ||{(category, keys)}
  )
);

named!(categories_aggregator<&[u8], Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));

fn categories(input: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str> > > {
  let mut h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();

  match categories_aggregator(input) {
    IResult::Done(i,tuple_vec) => {
      for &(k,ref v) in &tuple_vec {
        h.insert(k, v.clone());
      }
      IResult::Done(i, h)
    },
    IResult::Incomplete(a)     => IResult::Incomplete(a),
    IResult::Error(a)          => IResult::Error(a)
  }
}

#[test]
fn parse_category_test() {
  let ini_file = &b"[category]

parameter=value
key = value2"[..];

  let ini_without_category = &b"parameter=value
key = value2"[..];

  let res = category(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_category, "category"));
}

#[test]
fn parse_key_value_test() {
  let ini_file = &b"parameter=value
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_key_value_with_space_test() {
  let ini_file = &b"parameter = value
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_key_value_with_comment_test() {
  let ini_file = &b"parameter=value;abc
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_multiple_keys_and_values_test() {
  let ini_file = &b"parameter=value;abc

key = value2

[category]"[..];

  let ini_without_key_value = &b"[category]"[..];

  let res = keys_and_values(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected: HashMap<&str, &str> = HashMap::new();
  expected.insert("parameter", "value");
  expected.insert("key", "value2");
  assert_eq!(res, IResult::Done(ini_without_key_value, expected));
}

#[test]
fn parse_category_then_multiple_keys_and_values_test() {
  //FIXME: there can be an empty line or a comment line after a category
  let ini_file = &b"[abcd]
parameter=value;abc

key = value2

[category]"[..];

  let ini_after_parser = &b"[category]"[..];

  let res = category_and_keys(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected_h: HashMap<&str, &str> = HashMap::new();
  expected_h.insert("parameter", "value");
  expected_h.insert("key", "value2");
  assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
}

#[test]
fn parse_multiple_categories_test() {
  let ini_file = &b"[abcd]

parameter=value;abc

key = value2

[category]
parameter3=value3
key4 = value4
"[..];

  let ini_after_parser = &b""[..];

  let res = categories(ini_file);
  //println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected_1: HashMap<&str, &str> = HashMap::new();
  expected_1.insert("parameter", "value");
  expected_1.insert("key", "value2");
  let mut expected_2: HashMap<&str, &str> = HashMap::new();
  expected_2.insert("parameter3", "value3");
  expected_2.insert("key4", "value4");
  let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
  expected_h.insert("abcd",     expected_1);
  expected_h.insert("category", expected_2);
  assert_eq!(res, IResult::Done(ini_after_parser, expected_h));
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(stainless)]

extern crate proton_cli;
extern crate tempdir;
extern crate git2;
extern crate rustc_serialize;

pub use std::{env, fs};
pub use std::fs::File;
pub use std::path::{Path, PathBuf};
pub use std::io::Read;

pub use git2::{Repository, Signature, Time};
pub use tempdir::TempDir;
pub use rustc_serialize::json;

pub use proton_cli::{Error, Project, initialize_project};

describe! initialize_project {
    before_each {
        let signature = Signature::now("tester", "t@example.com").unwrap();
        let root_dir = TempDir::new("proton_cli_tests").unwrap();
    }

    it "works with an empty directory" {
        let root = root_dir.path();
        initialize_project(root, &signature).expect("Initialization failed");
    }

    after_each {
        // Assert that exactly Protonfile.json and .git exist.
        let protonfile_path = root.join(Path::new("Protonfile.json"));
        let git_path = root.join(Path::new(".git"));
        assert!(protonfile_path.is_file(), "protonfile must exist");
        assert!(git_path.is_dir(), ".git must exist");
        assert!(2 == fs::read_dir(root).unwrap().count(), "root must have 2 files");

        // Check that protonfile has right content
        assert_eq!(Project::empty(), File::open(&protonfile_path)
            .and_then(|mut protonfile| {
                let mut content = "".to_owned();
                protonfile.read_to_string(&mut content).map(|_| content)
            })
            .map_err(Error::Io)
            .and_then(|content| json::decode(&content).map_err(Error::JsonDecode))
            .expect("Loading protonfile into Project failed"));

        // Open a git repo
        let repo = Repository::open(root).unwrap();
        let master_head = repo.refname_to_id("refs/heads/master")
            .and_then(|oid| repo.find_commit(oid))
            .expect("Finding master failed");
        let master_tree = master_head.tree().expect("Opening master tree failed");

        // Check that master has only the initial commit.
        assert_eq!("Initial commit.", master_head.message().unwrap());
        assert!(0 == master_head.parents().count(), "master must have 0 parents");

        // Check that it includes the protonfile
        assert!(1 == master_tree.len(), "master must have 1 entry");
        assert!(master_tree.get_name("Protonfile.json").is_some(), "master must have protonfile");

        // Check that it has the right signature
    }
}
<commit_msg>Works with empty dir is done<commit_after>#![feature(plugin)]
#![plugin(stainless)]

extern crate proton_cli;
extern crate tempdir;
extern crate git2;
extern crate rustc_serialize;

pub use std::{env, fs};
pub use std::fs::File;
pub use std::path::{Path, PathBuf};
pub use std::io::Read;

pub use git2::{Repository, Signature, Time};
pub use tempdir::TempDir;
pub use rustc_serialize::json;

pub use proton_cli::{Error, Project, initialize_project};

describe! initialize_project {
    before_each {
        let signature = Signature::now("tester", "t@example.com").unwrap();
        let root_dir = TempDir::new("proton_cli_tests").unwrap();
    }

    it "works with an empty directory" {
        let root = root_dir.path();
        initialize_project(root, &signature).expect("Initialization failed");
    }

    after_each {
        // Assert that protonfile exists
        let protonfile_path = root.join(Path::new("Protonfile.json"));
        assert!(protonfile_path.is_file(), "protonfile must exist");

        // Check that protonfile has right content
        assert_eq!(Project::empty(), File::open(&protonfile_path)
            .and_then(|mut protonfile| {
                let mut content = "".to_owned();
                protonfile.read_to_string(&mut content).map(|_| content)
            })
            .map_err(Error::Io)
            .and_then(|content| json::decode(&content).map_err(Error::JsonDecode))
            .expect("Loading protonfile into Project failed"));

        // Open a git repo
        let repo = Repository::open(root).unwrap();
        let commit = repo.refname_to_id("refs/heads/master")
            .and_then(|oid| repo.find_commit(oid))
            .expect("Finding master failed");
        let tree = commit.tree().expect("Opening master tree failed");

        assert!(0 == commit.parents().count(), "master must have 0 parents");
        assert!(tree.get_name("Protonfile.json").is_some(), "master must have protonfile");
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

use nom::{IResult,FlatMapper,Mapper,Mapper2,Producer,ProducerState,FileProducer,HexDisplay};
use nom::IResult::*;

use std::str;
use std::collections::HashMap;

fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {

  take!(offset_parser 4);
  match offset_parser(input) {
    Done(i, offset_bytes) => {
      let offset:u32 = (offset_bytes[3] as u32) + (offset_bytes[2] as u32) * 0x100 + (offset_bytes[1] as u32) * 0x10000 + (offset_bytes[0] as u32) * 0x1000000;
      let sz: usize = offset as usize;
      //println!("box size: {} -> {}", offset_bytes.to_hex(8), sz);
      if i.len() >= sz {
        return Done(&i[(sz-4)..], &i[0..(sz-4)])
      } else {
        return Incomplete(0)
      }
    },
    e => e
  }
}

#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
  major_brand:         &'a str,
  major_brand_version: &'a [u8],
  compatible_brands:   Vec<&'a str>
}

#[derive(PartialEq,Eq,Debug)]
pub enum MoovBox {
  Mdra,
  Dref,
  Cmov,
  Rmra,
  Iods,
  Mvhd,
  Clip,
  Trak,
  Udta
}

#[derive(PartialEq,Eq,Debug)]
enum MP4Box<'a> {
  Ftyp(FileType<'a>),
  Moov(Vec<MoovBox>),
  Free,
  Skip,
  Wide,
  Unknown
}

take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn brand_name(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);
many0!(compatible_brands<&[u8], &str> brand_name);

fn filetype_parser<'a>(input: &'a[u8]) -> IResult<&'a [u8], FileType<'a> > {
  chaining_parser!(input, ||{FileType{major_brand: m, major_brand_version:v, compatible_brands: c}},
    m: brand_name,
    v: major_brand_version,
    c: compatible_brands,)
}

o!(filetype <&[u8], FileType>  ftyp ~ [ filetype_parser ]);

fn filetype_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match filetype(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      Done(i, MP4Box::Ftyp(o))
    }
  }
}

tag!(moov_tag "moov".as_bytes());

tag!(mdra    "mdra".as_bytes());
fn moov_mdra(input:&[u8]) -> IResult<&[u8], MoovBox> {
  mdra(input).map(|o| MoovBox::Mdra)
}

tag!(dref    "dref".as_bytes());
fn moov_dref(input:&[u8]) -> IResult<&[u8], MoovBox> {
  dref(input).map(|o| MoovBox::Dref)
}

tag!(cmov    "cmov".as_bytes());
fn moov_cmov(input:&[u8]) -> IResult<&[u8], MoovBox> {
  cmov(input).map(|o| MoovBox::Cmov)
}

tag!(rmra    "rmra".as_bytes());
fn moov_rmra(input:&[u8]) -> IResult<&[u8], MoovBox> {
  rmra(input).map(|o| MoovBox::Rmra)
}

tag!(iods    "iods".as_bytes());
fn moov_iods(input:&[u8]) -> IResult<&[u8], MoovBox> {
  iods(input).map(|o| MoovBox::Iods)
}

tag!(mvhd    "mvhd".as_bytes());
fn moov_mvhd(input:&[u8]) -> IResult<&[u8], MoovBox> {
  mvhd(input).map(|o| MoovBox::Mvhd)
}

tag!(clip    "clip".as_bytes());
fn moov_clip(input:&[u8]) -> IResult<&[u8], MoovBox> {
  clip(input).map(|o| MoovBox::Clip)
}

tag!(trak    "trak".as_bytes());
fn moov_trak(input:&[u8]) -> IResult<&[u8], MoovBox> {
  trak(input).map(|o| MoovBox::Trak)
}

tag!(udta   "udta".as_bytes());
fn moov_udta(input:&[u8]) -> IResult<&[u8], MoovBox> {
  udta(input).map(|o| MoovBox::Udta)
}

alt!(moov_internal<&[u8], MoovBox>, moov_mdra | moov_dref | moov_cmov |
     moov_rmra | moov_iods | moov_mvhd | moov_clip | moov_trak | moov_udta);

fn moov(input:&[u8]) -> IResult<&[u8], MoovBox> {
  match mp4_box(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      match moov_internal(o) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2, o2)  => {
          Done(i, o2)
        }

      }
    }
  }
}

many0!(moov_many<&[u8],MoovBox> moov);

o!(moov_box_internal <&[u8], Vec<MoovBox> >  moov_tag ~ [ moov_many ]);
fn moov_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match moov_box_internal(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)  => {
      Done(i, MP4Box::Moov(o))
    }
  }
}

tag!(free    "free".as_bytes());
fn free_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match free(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, _)    => {
      Done(i, MP4Box::Free)
    }
  }
}

tag!(skip    "skip".as_bytes());
fn skip_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match free(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, _)    => {
      Done(i, MP4Box::Skip)
    }
  }
}

tag!(wide    "wide".as_bytes());
fn wide_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match free(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, _)    => {
      Done(i, MP4Box::Wide)
    }
  }
}

fn unknown_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  println!("calling UNKNOWN");
  Done(input, MP4Box::Unknown)
}

alt!(box_parser_internal<&[u8], MP4Box>, filetype_box | moov_box | free_box | skip_box | wide_box | unknown_box);
fn box_parser(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match mp4_box(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      match box_parser_internal(o) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2, o2)  => {
          Done(i, o2)
        }
      }
    }
  }
}

fn data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  //println!("bytes:\n{}", bytes.to_hex(8));
  match box_parser(bytes) {
    Done(i, o) => {
      match o {
        MP4Box::Ftyp(f) => println!("-> FTYP: {:?}", f),
        MP4Box::Moov(m) => {println!("-> MOOV: {:?}", m); println!("remaining:\n{}", i.to_hex(8))},
        MP4Box::Free    => println!("-> FREE"),
        MP4Box::Skip    => println!("-> SKIP"),
        MP4Box::Wide    => println!("-> WIDE"),
        MP4Box::Unknown => println!("-> UNKNOWN")
      }
      //println!("remaining:\n{}", i.to_hex(8));
      Done(i,())
    },
    Error(a) => {
      println!("mp4 parsing error: {:?}", a);
      Error(a)
    },
    Incomplete(a) => {
      //println!("incomplete: {:?}", a);
      Incomplete(a)
    }
  }
}

fn multiple_data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  match data_interpreter(bytes) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, ())   => {
      println!("NEXT BOX");
      match data_interpreter(i) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2,())   => {
          println!("NEXT BOX 2");
          match data_interpreter(i2) {
            Error(a)      => Error(a),
            Incomplete(a) => Incomplete(a),
            Done(i3,())   => {
              println!("NEXT BOX 3");
                data_interpreter(i3)
            }
          }
        }
      }
    },
  }
}

fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 40000).map(|producer: FileProducer| {
    let mut p = producer;
    match p.produce() {
      ProducerState::Data(bytes) => {
        multiple_data_interpreter(bytes);
      },
      _ => println!("got error")
    }
    /*
    pusher!(ps, data_interpreter);
    ps(&mut p);
    */
    //assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<commit_msg>add mdat box<commit_after>#[macro_use]
extern crate nom;

use nom::{IResult,FlatMapper,Mapper,Mapper2,Producer,ProducerState,FileProducer,HexDisplay};
use nom::IResult::*;

use std::str;
use std::collections::HashMap;

fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {

  take!(offset_parser 4);
  match offset_parser(input) {
    Done(i, offset_bytes) => {
      let offset:u32 = (offset_bytes[3] as u32) + (offset_bytes[2] as u32) * 0x100 + (offset_bytes[1] as u32) * 0x10000 + (offset_bytes[0] as u32) * 0x1000000;
      let sz: usize = offset as usize;
      //println!("box size: {} -> {}", offset_bytes.to_hex(8), sz);
      if i.len() >= sz {
        return Done(&i[(sz-4)..], &i[0..(sz-4)])
      } else {
        return Incomplete(0)
      }
    },
    e => e
  }
}

#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
  major_brand:         &'a str,
  major_brand_version: &'a [u8],
  compatible_brands:   Vec<&'a str>
}

#[derive(PartialEq,Eq,Debug)]
pub enum MoovBox {
  Mdra,
  Dref,
  Cmov,
  Rmra,
  Iods,
  Mvhd,
  Clip,
  Trak,
  Udta
}

#[derive(PartialEq,Eq,Debug)]
enum MP4Box<'a> {
  Ftyp(FileType<'a>),
  Moov(Vec<MoovBox>),
  Mdat,
  Free,
  Skip,
  Wide,
  Unknown
}

take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn brand_name(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);
many0!(compatible_brands<&[u8], &str> brand_name);

fn filetype_parser<'a>(input: &'a[u8]) -> IResult<&'a [u8], FileType<'a> > {
  chaining_parser!(input, ||{FileType{major_brand: m, major_brand_version:v, compatible_brands: c}},
    m: brand_name,
    v: major_brand_version,
    c: compatible_brands,)
}

o!(filetype <&[u8], FileType>  ftyp ~ [ filetype_parser ]);

fn filetype_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match filetype(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      Done(i, MP4Box::Ftyp(o))
    }
  }
}

tag!(moov_tag "moov".as_bytes());

tag!(mdra    "mdra".as_bytes());
fn moov_mdra(input:&[u8]) -> IResult<&[u8], MoovBox> {
  mdra(input).map(|o| MoovBox::Mdra)
}

tag!(dref    "dref".as_bytes());
fn moov_dref(input:&[u8]) -> IResult<&[u8], MoovBox> {
  dref(input).map(|o| MoovBox::Dref)
}

tag!(cmov    "cmov".as_bytes());
fn moov_cmov(input:&[u8]) -> IResult<&[u8], MoovBox> {
  cmov(input).map(|o| MoovBox::Cmov)
}

tag!(rmra    "rmra".as_bytes());
fn moov_rmra(input:&[u8]) -> IResult<&[u8], MoovBox> {
  rmra(input).map(|o| MoovBox::Rmra)
}

tag!(iods    "iods".as_bytes());
fn moov_iods(input:&[u8]) -> IResult<&[u8], MoovBox> {
  iods(input).map(|o| MoovBox::Iods)
}

tag!(mvhd    "mvhd".as_bytes());
fn moov_mvhd(input:&[u8]) -> IResult<&[u8], MoovBox> {
  mvhd(input).map(|o| MoovBox::Mvhd)
}

tag!(clip    "clip".as_bytes());
fn moov_clip(input:&[u8]) -> IResult<&[u8], MoovBox> {
  clip(input).map(|o| MoovBox::Clip)
}

tag!(trak    "trak".as_bytes());
fn moov_trak(input:&[u8]) -> IResult<&[u8], MoovBox> {
  trak(input).map(|o| MoovBox::Trak)
}

tag!(udta   "udta".as_bytes());
fn moov_udta(input:&[u8]) -> IResult<&[u8], MoovBox> {
  udta(input).map(|o| MoovBox::Udta)
}

alt!(moov_internal<&[u8], MoovBox>, moov_mdra | moov_dref | moov_cmov |
     moov_rmra | moov_iods | moov_mvhd | moov_clip | moov_trak | moov_udta);

fn moov(input:&[u8]) -> IResult<&[u8], MoovBox> {
  match mp4_box(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      match moov_internal(o) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2, o2)  => {
          Done(i, o2)
        }

      }
    }
  }
}

many0!(moov_many<&[u8],MoovBox> moov);

o!(moov_box_internal <&[u8], Vec<MoovBox> >  moov_tag ~ [ moov_many ]);
fn moov_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match moov_box_internal(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)  => {
      Done(i, MP4Box::Moov(o))
    }
  }
}

tag!(mdat    "mdat".as_bytes());
fn mdat_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match mdat(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, _)    => {
      Done(i, MP4Box::Mdat)
    }
  }
}
tag!(free    "free".as_bytes());
fn free_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match free(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, _)    => {
      Done(i, MP4Box::Free)
    }
  }
}

tag!(skip    "skip".as_bytes());
fn skip_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match free(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, _)    => {
      Done(i, MP4Box::Skip)
    }
  }
}

tag!(wide    "wide".as_bytes());
fn wide_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match free(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, _)    => {
      Done(i, MP4Box::Wide)
    }
  }
}

fn unknown_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  println!("calling UNKNOWN");
  Done(input, MP4Box::Unknown)
}

alt!(box_parser_internal<&[u8], MP4Box>, filetype_box | moov_box | mdat_box | free_box | skip_box | wide_box | unknown_box);
fn box_parser(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match mp4_box(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      match box_parser_internal(o) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2, o2)  => {
          Done(i, o2)
        }
      }
    }
  }
}

fn data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  //println!("bytes:\n{}", bytes.to_hex(8));
  match box_parser(bytes) {
    Done(i, o) => {
      match o {
        MP4Box::Ftyp(f) => println!("-> FTYP: {:?}", f),
        MP4Box::Moov(m) => {println!("-> MOOV: {:?}", m); println!("remaining:\n{}", i.to_hex(8))},
        MP4Box::Mdat    => println!("-> MDAT"),
        MP4Box::Free    => println!("-> FREE"),
        MP4Box::Skip    => println!("-> SKIP"),
        MP4Box::Wide    => println!("-> WIDE"),
        MP4Box::Unknown => println!("-> UNKNOWN")
      }
      //println!("remaining:\n{}", i.to_hex(8));
      Done(i,())
    },
    Error(a) => {
      println!("mp4 parsing error: {:?}", a);
      Error(a)
    },
    Incomplete(a) => {
      //println!("incomplete: {:?}", a);
      Incomplete(a)
    }
  }
}

fn multiple_data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  match data_interpreter(bytes) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, ())   => {
      println!("NEXT BOX");
      match data_interpreter(i) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2,())   => {
          println!("NEXT BOX 2");
          match data_interpreter(i2) {
            Error(a)      => Error(a),
            Incomplete(a) => Incomplete(a),
            Done(i3,())   => {
              println!("NEXT BOX 3");
                data_interpreter(i3)
            }
          }
        }
      }
    },
  }
}

fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 40000).map(|producer: FileProducer| {
    let mut p = producer;
    match p.produce() {
      ProducerState::Data(bytes) => {
        multiple_data_interpreter(bytes);
      },
      _ => println!("got error")
    }
    /*
    pusher!(ps, data_interpreter);
    ps(&mut p);
    */
    //assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<|endoftext|>


<commit_before>extern crate backblaze_b2;
extern crate hyper;
extern crate hyper_native_tls;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate rand;
extern crate sha1;

use std::io::{Read, Write};
use std::fs::File;

use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;

use rand::Rng;

use backblaze_b2::raw::authorize::*;
use backblaze_b2::raw::buckets::*;
use backblaze_b2::raw::files::*;

use serde_json::value::Value;

fn make_connector() -> HttpsConnector<NativeTlsClient> {
    let ssl = NativeTlsClient::new().unwrap();
    HttpsConnector::new(ssl)
}
fn make_client() -> Client {
    Client::with_connector(make_connector())
}

fn rand_string(len: usize) -> String {
    let mut rng = rand::thread_rng();
    rng.gen_ascii_chars().take(len).collect()
}

#[test]
fn list_all_files() {
    let client = make_client();
    let connector = make_connector();
    let cred_file = match File::open("credentials.txt") {
        Ok(f) => f,
        Err(_) =>
            panic!("The test requires the credentials for b2 to be placed in the file \'credentials.txt\' which contains a json object with the properties \"id\" and \"key\".")
    };
    let cred: B2Credentials = serde_json::from_reader(cred_file).unwrap();
    let auth: B2Authorization = cred.authorize(&client).unwrap();
    let new_bucket_name = format!("rust-b2-test-{}", rand_string(16));
    let bucket = auth.create_bucket_no_info(&new_bucket_name, BucketType::Private,
                                            Vec::new(), &client).unwrap();
    let mut files = Vec::new();
    let upload_auth = auth.get_upload_url(&bucket.bucket_id, &client).unwrap();
    for i in 0..30 {
        let mut file_data: [u8; 9] = [0,0,0,0,0,0,0,0,0];
        let mut rng = rand::thread_rng();
        for j in 0..9 {
            file_data[j] = rng.gen();
        }

        let mut m = sha1::Sha1::new();
        m.update(&file_data);
        let sha1 = m.digest().to_string();
        let file: MoreFileInfo = {
            if i % 3 == 0 {
                upload_auth.upload_file(
                    &mut&file_data[..],
                    format!("{}", i),
                    None, 9,
                    sha1.clone(), &connector
                ).unwrap()
            } else if i % 3 == 1 {
                let mut request = upload_auth.create_upload_file_request(
                    format!("{}", i),
                    None, 9, sha1.clone(),
                    &connector
                ).unwrap();
                request.write_all(&file_data[..]).unwrap();
                request.finish().unwrap()
            } else {
                let mut request = upload_auth.create_upload_file_request_sha1_at_end(
                    format!("{}", i),
                    None, 9,
                    &connector
                ).unwrap();
                request.write_all(&file_data[..]).unwrap();
                request.finish(&sha1).unwrap()
            }
        };
        files.push(file);
    }
    let listing = auth.list_all_file_names::<Value>(&bucket.bucket_id, 12, None, None, &client).unwrap();
    assert_eq!(listing.folders.len(), 0);
    for file in listing.files {
        let fi: usize = file.file_name.parse().unwrap();
        assert_eq!(files[fi].content_sha1, file.content_sha1);
        auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
    }
    auth.delete_bucket(&bucket, &client).unwrap();
}
#[test]
#[allow(unused_variables)]
fn main_test() {
    let client = make_client();
    let cred_file = match File::open("credentials.txt") {
        Ok(f) => f,
        Err(_) =>
            panic!("The test requires the credentials for b2 to be placed in the file \'credentials.txt\' which contains a json object with the properties \"id\" and \"key\".")
    };
    let cred: B2Credentials = serde_json::from_reader(cred_file).unwrap();
    let auth: B2Authorization = cred.authorize(&client).unwrap();

    let buckets_before: Vec<Bucket> = auth.list_buckets(&client).unwrap();

    let new_bucket_name = format!("rust-b2-test-{}", rand_string(16));

    {
        let bucket_info = json!({"abc": "test", "json": "data"});
        let bucket = auth.create_bucket(&new_bucket_name, BucketType::Private,
                                        bucket_info.clone(), Vec::new(), &client).unwrap();
        assert_eq!(bucket.bucket_name, new_bucket_name);
        assert_eq!(bucket.bucket_type, BucketType::Private);
        assert_eq!(bucket.bucket_info, bucket_info);
        assert_eq!(bucket.account_id, auth.credentials.id);
        auth.delete_bucket_id::<Value>(&bucket.bucket_id, &client).unwrap();
    }
    let bucket = auth.create_bucket_no_info(&new_bucket_name, BucketType::Private,
                                            Vec::new(), &client).unwrap();
    assert_eq!(bucket.bucket_name, new_bucket_name);
    assert_eq!(bucket.bucket_type, BucketType::Private);
    assert_eq!(bucket.bucket_info, json!({}));
    assert_eq!(bucket.account_id, auth.credentials.id);

    let buckets_after: Vec<Bucket> = auth.list_buckets(&client).unwrap();
    //assert_eq!(buckets_after.len() - buckets_before.len(), 1);
    //other tests intefere with this

    if let Ok((fnl, None)) =
        auth.list_file_names::<Value>(&bucket.bucket_id, None, 10, None, None, &client) {
        assert_eq!(fnl.files.len(), 0);
        assert_eq!(fnl.folders.len(), 0);
    } else {
        panic!();
    }

    let file_data: [u8; 9] = [23, 10, 43, 94, 23, 0, 18, 34, 244];
    let mut m = sha1::Sha1::new();
    m.update(&file_data);
    let sha1 = m.digest().to_string();
    let file = {
        let upload_auth = auth.get_upload_url(&bucket.bucket_id, &client).unwrap();

        let file: MoreFileInfo = upload_auth.upload_file(&mut&file_data[..], "test_file.png".to_owned(), None, 9,
        sha1.clone(), &make_connector()).unwrap();
        assert_eq!(&file.file_name, "test_file.png");
        assert_eq!(file.account_id, auth.credentials.id);
        assert_eq!(file.content_sha1, sha1);
        assert_eq!(file.bucket_id, bucket.bucket_id);
        assert_eq!(file.content_length, 9);
        assert_eq!(file.content_type, "image/png");
        assert_eq!(file.action, FileType::File);
        file
    };

    {
        let file2: MoreFileInfo = auth.get_file_info(&file.file_id, &client).unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.account_id, auth.credentials.id);
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.bucket_id, bucket.bucket_id);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
        assert_eq!(file2.action, FileType::File);
    }
    if let Ok((fnl, None)) =
        auth.list_file_names::<Value>(&bucket.bucket_id, None, 10, None, None, &client) {
        assert_eq!(fnl.files.len(), 1);
        assert_eq!(fnl.folders.len(), 0);
        let file2 = &fnl.files[0];
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    } else {
        panic!();
    }
    if let Ok((fvl, None, None)) =
        auth.list_file_versions::<Value>(&bucket.bucket_id, None, None, 10, None, None, &client) {
        assert_eq!(fvl.files.len(), 1);
        assert_eq!(fvl.folders.len(), 0);
        assert_eq!(fvl.hide_markers.len(), 0);
        assert_eq!(fvl.unfinished_large_files.len(), 0);
        let file2 = &fvl.files[0];
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    } else {
        panic!();
    }

    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_file_by_id(&file.file_id, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[..]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_file_by_name(&bucket.bucket_name, &file.file_name, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[..]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_range_by_id(&file.file_id, 1, 3, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[1..4]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 3);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_range_by_name(&bucket.bucket_name, &file.file_name, 1, 3, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[1..4]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 3);
        assert_eq!(file2.content_type, "image/png");
    }

    auth.hide_file(&file.file_name, &bucket.bucket_id, &client).unwrap();
    if let Ok((fvl, None, None)) =
        auth.list_file_versions::<Value>(&bucket.bucket_id, None, None, 10, None, None, &client) {
        for file in fvl.files {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
        for file in fvl.hide_markers {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
        for file in fvl.unfinished_large_files {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
    } else {
        panic!();
    }
    auth.delete_bucket(&bucket, &client).unwrap();

    /*  comment in to clean up buckets
    for buck in buckets_before {
        if buck.bucket_name.starts_with("rust-b2-test-") {
            match auth.list_file_versions::<Value>(&buck.bucket_id, None, None, 10, None, None, &client) {
                Ok((fvl, None, None)) => {
                    for f in fvl.files {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                    for f in fvl.hide_markers {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                    for f in fvl.unfinished_large_files {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                },
                Ok(x) => panic!("{:?}", x),
                Err(e) => panic!("{:?}", e)
            }
            auth.delete_bucket(&buck, &client).unwrap();
        }
    }
    // */

}

<commit_msg>change tests<commit_after>extern crate backblaze_b2;
extern crate hyper;
extern crate hyper_native_tls;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate rand;
extern crate sha1;

use std::io::{Read, Write};
use std::fs::File;

use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;

use rand::Rng;

use backblaze_b2::raw::authorize::*;
use backblaze_b2::raw::buckets::*;
use backblaze_b2::raw::files::*;

use serde_json::value::Value;

fn make_connector() -> HttpsConnector<NativeTlsClient> {
    let ssl = NativeTlsClient::new().unwrap();
    HttpsConnector::new(ssl)
}
fn make_client() -> Client {
    Client::with_connector(make_connector())
}

fn rand_string(len: usize) -> String {
    let mut rng = rand::thread_rng();
    rng.gen_ascii_chars().take(len).collect()
}

#[test]
fn list_all_files() {
    let client = make_client();
    let connector = make_connector();
    let cred_file = match File::open("credentials.txt") {
        Ok(f) => f,
        Err(_) =>
            panic!("The test requires the credentials for b2 to be placed in the file \'credentials.txt\' which contains a json object with the properties \"id\" and \"key\".")
    };
    let cred: B2Credentials = serde_json::from_reader(cred_file).unwrap();
    let auth: B2Authorization = cred.authorize(&client).unwrap();
    let new_bucket_name = format!("rust-b2-test-{}", rand_string(16));
    let bucket = auth.create_bucket_no_info(&new_bucket_name, BucketType::Private,
                                            Vec::new(), &client).unwrap();
    let mut files = Vec::new();
    let upload_auth = auth.get_upload_url(&bucket.bucket_id, &client).unwrap();
    for i in 0..30 {
        let mut file_data: [u8; 9] = [0,0,0,0,0,0,0,0,0];
        let mut rng = rand::thread_rng();
        for j in 0..9 {
            file_data[j] = rng.gen();
        }

        let mut m = sha1::Sha1::new();
        m.update(&file_data);
        let sha1 = m.digest().to_string();
        let file: MoreFileInfo = {
            if i % 3 == 0 {
                upload_auth.upload_file(
                    &mut&file_data[..],
                    format!("{}", i),
                    None, 9,
                    sha1.clone(), &connector
                ).unwrap()
            } else if i % 3 == 1 {
                let mut request = upload_auth.create_upload_file_request(
                    format!("{}", i),
                    None, 9, sha1.clone(),
                    &connector
                ).unwrap();
                request.write_all(&file_data[..]).unwrap();
                request.finish().unwrap()
            } else {
                let mut request = upload_auth.create_upload_file_request_sha1_at_end(
                    format!("{}", i),
                    None, 9,
                    &connector
                ).unwrap();
                request.write_all(&file_data[..]).unwrap();
                request.finish(&sha1).unwrap()
            }
        };
        files.push(file);
    }
    let listing = auth.list_all_file_names::<Value>(&bucket.bucket_id, 12, None, None, &client).unwrap();
    assert_eq!(listing.folders.len(), 0);
    for file in listing.files {
        let fi: usize = file.file_name.parse().unwrap();
        assert_eq!(files[fi].content_sha1, file.content_sha1);
        auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
    }
    auth.delete_bucket(&bucket, &client).unwrap();
}
#[test]
#[allow(unused_variables)]
fn main_test() {
    let client = make_client();
    let cred_file = match File::open("credentials.txt") {
        Ok(f) => f,
        Err(_) =>
            panic!("The test requires the credentials for b2 to be placed in the file \'credentials.txt\' which contains a json object with the properties \"id\" and \"key\".")
    };
    let cred: B2Credentials = serde_json::from_reader(cred_file).unwrap();
    let auth: B2Authorization = cred.authorize(&client).unwrap();

    let buckets_before: Vec<Bucket> = auth.list_buckets(&client).unwrap();

    let new_bucket_name = format!("rust-b2-test-{}", rand_string(16));

    {
        let bucket_info = json!({"abc": "test", "json": "data"});
        let bucket = auth.create_bucket(&new_bucket_name, BucketType::Private,
                                        bucket_info.clone(), Vec::new(), &client).unwrap();
        assert_eq!(bucket.bucket_name, new_bucket_name);
        assert_eq!(bucket.bucket_type, BucketType::Private);
        assert_eq!(bucket.bucket_info, bucket_info);
        assert_eq!(bucket.account_id, auth.account_id);
        auth.delete_bucket_id::<Value>(&bucket.bucket_id, &client).unwrap();
    }
    let bucket = auth.create_bucket_no_info(&new_bucket_name, BucketType::Private,
                                            Vec::new(), &client).unwrap();
    assert_eq!(bucket.bucket_name, new_bucket_name);
    assert_eq!(bucket.bucket_type, BucketType::Private);
    assert_eq!(bucket.bucket_info, json!({}));
    assert_eq!(bucket.account_id, auth.account_id);

    let buckets_after: Vec<Bucket> = auth.list_buckets(&client).unwrap();
    //assert_eq!(buckets_after.len() - buckets_before.len(), 1);
    //other tests intefere with this

    if let Ok((fnl, None)) =
        auth.list_file_names::<Value>(&bucket.bucket_id, None, 10, None, None, &client) {
        assert_eq!(fnl.files.len(), 0);
        assert_eq!(fnl.folders.len(), 0);
    } else {
        panic!();
    }

    let file_data: [u8; 9] = [23, 10, 43, 94, 23, 0, 18, 34, 244];
    let mut m = sha1::Sha1::new();
    m.update(&file_data);
    let sha1 = m.digest().to_string();
    let file = {
        let upload_auth = auth.get_upload_url(&bucket.bucket_id, &client).unwrap();

        let file: MoreFileInfo = upload_auth.upload_file(&mut&file_data[..], "test_file.png".to_owned(), None, 9,
        sha1.clone(), &make_connector()).unwrap();
        assert_eq!(&file.file_name, "test_file.png");
        assert_eq!(file.account_id, auth.account_id);
        assert_eq!(file.content_sha1, sha1);
        assert_eq!(file.bucket_id, bucket.bucket_id);
        assert_eq!(file.content_length, 9);
        assert_eq!(file.content_type, "image/png");
        assert_eq!(file.action, FileType::File);
        file
    };

    {
        let file2: MoreFileInfo = auth.get_file_info(&file.file_id, &client).unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.account_id, auth.account_id);
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.bucket_id, bucket.bucket_id);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
        assert_eq!(file2.action, FileType::File);
    }
    if let Ok((fnl, None)) =
        auth.list_file_names::<Value>(&bucket.bucket_id, None, 10, None, None, &client) {
        assert_eq!(fnl.files.len(), 1);
        assert_eq!(fnl.folders.len(), 0);
        let file2 = &fnl.files[0];
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    } else {
        panic!();
    }
    if let Ok((fvl, None, None)) =
        auth.list_file_versions::<Value>(&bucket.bucket_id, None, None, 10, None, None, &client) {
        assert_eq!(fvl.files.len(), 1);
        assert_eq!(fvl.folders.len(), 0);
        assert_eq!(fvl.hide_markers.len(), 0);
        assert_eq!(fvl.unfinished_large_files.len(), 0);
        let file2 = &fvl.files[0];
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    } else {
        panic!();
    }

    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_file_by_id(&file.file_id, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[..]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_file_by_name(&bucket.bucket_name, &file.file_name, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[..]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_range_by_id(&file.file_id, 1, 3, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[1..4]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 3);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_range_by_name(&bucket.bucket_name, &file.file_name, 1, 3, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[1..4]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 3);
        assert_eq!(file2.content_type, "image/png");
    }

    auth.hide_file(&file.file_name, &bucket.bucket_id, &client).unwrap();
    if let Ok((fvl, None, None)) =
        auth.list_file_versions::<Value>(&bucket.bucket_id, None, None, 10, None, None, &client) {
        for file in fvl.files {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
        for file in fvl.hide_markers {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
        for file in fvl.unfinished_large_files {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
    } else {
        panic!();
    }
    auth.delete_bucket(&bucket, &client).unwrap();

    /*  comment in to clean up buckets
    for buck in buckets_before {
        if buck.bucket_name.starts_with("rust-b2-test-") {
            match auth.list_file_versions::<Value>(&buck.bucket_id, None, None, 10, None, None, &client) {
                Ok((fvl, None, None)) => {
                    for f in fvl.files {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                    for f in fvl.hide_markers {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                    for f in fvl.unfinished_large_files {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                },
                Ok(x) => panic!("{:?}", x),
                Err(e) => panic!("{:?}", e)
            }
            auth.delete_bucket(&buck, &client).unwrap();
        }
    }
    // */

}

<|endoftext|>


<commit_before>extern crate alacritty;
extern crate serde_json as json;

use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

use alacritty::Grid;
use alacritty::Term;
use alacritty::ansi;
use alacritty::index::{Line, Column};
use alacritty::term::Cell;
use alacritty::term::SizeInfo;
use alacritty::util::fmt::{Red, Green};

macro_rules! ref_tests {
    ($($name:ident)*) => {
        $(
            #[test]
            fn $name() {
                let test_dir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/ref"));
                let test_path = test_dir.join(stringify!($name));
                ref_test(&test_path);
            }
        )*
    }
}

ref_tests! {
    csi_rep
    fish_cc
    indexed_256_colors
    ll
    tab_rendering
    tmux_git_log
    tmux_htop
    vim_large_window_scroll
    vim_simple_edit
    vttest_cursor_movement_1
    vttest_insert
    vttest_origin_mode_1
    vttest_origin_mode_2
    vttest_scroll
    vttest_tab_clear_set
    zsh_tab_completion
}

fn read_u8<P>(path: P) -> Vec<u8>
    where P: AsRef<Path>
{
    let mut res = Vec::new();
    File::open(path.as_ref()).unwrap()
        .read_to_end(&mut res).unwrap();

    res
}

fn read_string<P>(path: P) -> String
    where P: AsRef<Path>
{
    let mut res = String::new();
    File::open(path.as_ref()).unwrap()
        .read_to_string(&mut res).unwrap();

    res
}

fn ref_test(dir: &Path) {
    let recording = read_u8(dir.join("alacritty.recording"));
    let serialized_size = read_string(dir.join("size.json"));
    let serialized_grid = read_string(dir.join("grid.json"));

    let size: SizeInfo = json::from_str(&serialized_size).unwrap();
    let grid: Grid<Cell> = json::from_str(&serialized_grid).unwrap();

    let mut terminal = Term::new(&Default::default(), size);
    let mut parser = ansi::Processor::new();

    for byte in recording {
        parser.advance(&mut terminal, byte, &mut io::sink());
    }

    if grid != *terminal.grid() {
        for (i, row) in terminal.grid().iter_rows().enumerate() {
            for (j, cell) in row.iter().enumerate() {
                let original_cell = &grid[Line(i)][Column(j)];
                if *original_cell != *cell {
                    println!("[{i}][{j}] {original:?} => {now:?}",
                             i=i, j=j, original=Green(original_cell), now=Red(cell));
                }
            }
        }

        panic!("Ref test failed; grid doesn't match");
    }

    assert_eq!(grid, *terminal.grid());
}
<commit_msg>Run all ref tests<commit_after>extern crate alacritty;
extern crate serde_json as json;

use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

use alacritty::Grid;
use alacritty::Term;
use alacritty::ansi;
use alacritty::index::{Line, Column};
use alacritty::term::Cell;
use alacritty::term::SizeInfo;
use alacritty::util::fmt::{Red, Green};

macro_rules! ref_tests {
    ($($name:ident)*) => {
        $(
            #[test]
            fn $name() {
                let test_dir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/ref"));
                let test_path = test_dir.join(stringify!($name));
                ref_test(&test_path);
            }
        )*
    }
}

ref_tests! {
    csi_rep
    fish_cc
    indexed_256_colors
    ll
    newline_with_cursor_beyond_scroll_region
    tab_rendering
    tmux_git_log
    tmux_htop
    vim_24bitcolors_bce
    vim_large_window_scroll
    vim_simple_edit
    vttest_cursor_movement_1
    vttest_insert
    vttest_origin_mode_1
    vttest_origin_mode_2
    vttest_scroll
    vttest_tab_clear_set
    zsh_tab_completion
}

fn read_u8<P>(path: P) -> Vec<u8>
    where P: AsRef<Path>
{
    let mut res = Vec::new();
    File::open(path.as_ref()).unwrap()
        .read_to_end(&mut res).unwrap();

    res
}

fn read_string<P>(path: P) -> String
    where P: AsRef<Path>
{
    let mut res = String::new();
    File::open(path.as_ref()).unwrap()
        .read_to_string(&mut res).unwrap();

    res
}

fn ref_test(dir: &Path) {
    let recording = read_u8(dir.join("alacritty.recording"));
    let serialized_size = read_string(dir.join("size.json"));
    let serialized_grid = read_string(dir.join("grid.json"));

    let size: SizeInfo = json::from_str(&serialized_size).unwrap();
    let grid: Grid<Cell> = json::from_str(&serialized_grid).unwrap();

    let mut terminal = Term::new(&Default::default(), size);
    let mut parser = ansi::Processor::new();

    for byte in recording {
        parser.advance(&mut terminal, byte, &mut io::sink());
    }

    if grid != *terminal.grid() {
        for (i, row) in terminal.grid().iter_rows().enumerate() {
            for (j, cell) in row.iter().enumerate() {
                let original_cell = &grid[Line(i)][Column(j)];
                if *original_cell != *cell {
                    println!("[{i}][{j}] {original:?} => {now:?}",
                             i=i, j=j, original=Green(original_cell), now=Red(cell));
                }
            }
        }

        panic!("Ref test failed; grid doesn't match");
    }

    assert_eq!(grid, *terminal.grid());
}
<|endoftext|>


<commit_before>use bifrost::rpc::*;
use byteorder::{ByteOrder, LittleEndian};
use futures::prelude::*;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;

pub mod simple_service {

    use super::*;

    service! {
        rpc hello(name: String) -> String;
        rpc error(message: String) | String;
    }

    struct HelloServer;

    impl Service for HelloServer {
        fn hello(&self, name: String) -> Box<Future<Item = String, Error = ()>> {
            box future::finished(format!("Hello, {}!", name))
        }
        fn error(&self, message: String) -> Box<Future<Item = (), Error = String>> {
            box future::failed(message.clone())
        }
    }
    dispatch_rpc_service_functions!(HelloServer);

    #[test]
    pub fn simple_rpc() {
        let addr = String::from("127.0.0.1:1300");
        {
            let addr = addr.clone();
            let server = Server::new(&addr);
            server.register_service(0, &Arc::new(HelloServer));
            Server::listen_and_resume(&server);;
        }
        thread::sleep(Duration::from_millis(1000));
        let client = RPCClient::new_async(addr).wait().unwrap();
        let service_client = AsyncServiceClient::new(0, &client);
        let response = service_client.hello(String::from("Jack"));
        let greeting_str = response.wait().unwrap().unwrap();
        println!("SERVER RESPONDED: {}", greeting_str);
        assert_eq!(greeting_str, String::from("Hello, Jack!"));
        let expected_err_msg = String::from("This error is a good one");
        let response = service_client.error(expected_err_msg.clone());
        let error_msg = response.wait().unwrap().err().unwrap();
        assert_eq!(error_msg, expected_err_msg);
    }

}

pub mod struct_service {

    use super::*;

    #[derive(Serialize, Deserialize, Debug, Clone)]
    pub struct Greeting {
        pub name: String,
        pub time: u32,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct Respond {
        pub text: String,
        pub owner: u32,
    }

    service! {
        rpc hello(gret: Greeting) -> Respond;
    }

    pub struct HelloServer;

    impl Service for HelloServer {
        fn hello(&self, gret: Greeting) -> Box<Future<Item = Respond, Error = ()>> {
            box future::ok(Respond {
                text: format!("Hello, {}. It is {} now!", gret.name, gret.time),
                owner: 42,
            })
        }
    }
    dispatch_rpc_service_functions!(HelloServer);

    #[test]
    pub fn struct_rpc() {
        let addr = String::from("127.0.0.1:1400");
        {
            let addr = addr.clone();
            let server = Server::new(&addr); // 0 is service id
            server.register_service(0, &Arc::new(HelloServer));
            Server::listen_and_resume(&server);
        }
        thread::sleep(Duration::from_millis(1000));
        let client = RPCClient::new_async(addr).wait().unwrap();
        let service_client = AsyncServiceClient::new(0, &client);
        let response = service_client.hello(Greeting {
            name: String::from("Jack"),
            time: 12,
        });
        let res = response.wait().unwrap().unwrap();
        let greeting_str = res.text;
        println!("SERVER RESPONDED: {}", greeting_str);
        assert_eq!(greeting_str, String::from("Hello, Jack. It is 12 now!"));
        assert_eq!(42, res.owner);
    }
}

mod multi_server {

    use super::*;

    service! {
        rpc query_server_id() -> u64;
    }

    struct IdServer {
        id: u64,
    }
    impl Service for IdServer {
        fn query_server_id(&self) -> Box<Future<Item = u64, Error = ()>> {
            box future::ok(self.id)
        }
    }
    dispatch_rpc_service_functions!(IdServer);

    #[test]
    fn multi_server_rpc() {
        let addrs = vec![
            String::from("127.0.0.1:1500"),
            String::from("127.0.0.1:1600"),
            String::from("127.0.0.1:1700"),
            String::from("127.0.0.1:1800"),
        ];
        let mut id = 0;
        for addr in &addrs {
            {
                let addr = addr.clone();
                thread::spawn(move || {
                    let server = Server::new(&addr); // 0 is service id
                    server.register_service(id, &Arc::new(IdServer { id: id }));
                    Server::listen(&server);
                });
                id += 1;
            }
        }
        id = 0;
        thread::sleep(Duration::from_millis(1000));
        for addr in &addrs {
            let client = RPCClient::new_async(addr.clone()).wait().unwrap();
            let service_client = AsyncServiceClient::new(id, &client);
            let id_res = service_client.query_server_id().wait().unwrap();
            assert_eq!(id_res.unwrap(), id);
            id += 1;
        }
    }
}

mod parallel {

    extern crate rayon;
    use self::rayon::iter::IntoParallelIterator;
    use self::rayon::prelude::*;
    use super::struct_service::*;
    use super::*;

    #[test]
    pub fn lots_of_reqs() {
        let addr = String::from("127.0.0.1:1411");
        {
            let addr = addr.clone();
            let server = Server::new(&addr); // 0 is service id
            server.register_service(0, &Arc::new(HelloServer));
            Server::listen_and_resume(&server);
        }
        thread::sleep(Duration::from_millis(1000));
        let client = RPCClient::new_async(addr).wait().unwrap();
        let service_client = AsyncServiceClient::new(0, &client);

        println!("Testing parallel RPC reqs");

        (0..1000).collect::<Vec<_>>().into_par_iter().for_each(|i| {
            let response = service_client.hello(Greeting {
                name: String::from("John"),
                time: i,
            });
            let res = response.wait().unwrap().unwrap();
            let greeting_str = res.text;
            println!("SERVER RESPONDED: {}", greeting_str);
            assert_eq!(greeting_str, format!("Hello, John. It is {} now!", i));
            assert_eq!(42, res.owner);
        });
    }
}
<commit_msg>pool test<commit_after>use bifrost::rpc::*;
use byteorder::{ByteOrder, LittleEndian};
use futures::prelude::*;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;

pub mod simple_service {

    use super::*;

    service! {
        rpc hello(name: String) -> String;
        rpc error(message: String) | String;
    }

    struct HelloServer;

    impl Service for HelloServer {
        fn hello(&self, name: String) -> Box<Future<Item = String, Error = ()>> {
            box future::finished(format!("Hello, {}!", name))
        }
        fn error(&self, message: String) -> Box<Future<Item = (), Error = String>> {
            box future::failed(message.clone())
        }
    }
    dispatch_rpc_service_functions!(HelloServer);

    #[test]
    pub fn simple_rpc() {
        let addr = String::from("127.0.0.1:1300");
        {
            let addr = addr.clone();
            let server = Server::new(&addr);
            server.register_service(0, &Arc::new(HelloServer));
            Server::listen_and_resume(&server);;
        }
        thread::sleep(Duration::from_millis(1000));
        let client = RPCClient::new_async(addr).wait().unwrap();
        let service_client = AsyncServiceClient::new(0, &client);
        let response = service_client.hello(String::from("Jack"));
        let greeting_str = response.wait().unwrap().unwrap();
        println!("SERVER RESPONDED: {}", greeting_str);
        assert_eq!(greeting_str, String::from("Hello, Jack!"));
        let expected_err_msg = String::from("This error is a good one");
        let response = service_client.error(expected_err_msg.clone());
        let error_msg = response.wait().unwrap().err().unwrap();
        assert_eq!(error_msg, expected_err_msg);
    }

}

pub mod struct_service {

    use super::*;

    #[derive(Serialize, Deserialize, Debug, Clone)]
    pub struct Greeting {
        pub name: String,
        pub time: u32,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct Respond {
        pub text: String,
        pub owner: u32,
    }

    service! {
        rpc hello(gret: Greeting) -> Respond;
    }

    pub struct HelloServer;

    impl Service for HelloServer {
        fn hello(&self, gret: Greeting) -> Box<Future<Item = Respond, Error = ()>> {
            box future::ok(Respond {
                text: format!("Hello, {}. It is {} now!", gret.name, gret.time),
                owner: 42,
            })
        }
    }
    dispatch_rpc_service_functions!(HelloServer);

    #[test]
    pub fn struct_rpc() {
        let addr = String::from("127.0.0.1:1400");
        {
            let addr = addr.clone();
            let server = Server::new(&addr); // 0 is service id
            server.register_service(0, &Arc::new(HelloServer));
            Server::listen_and_resume(&server);
        }
        thread::sleep(Duration::from_millis(1000));
        let client = RPCClient::new_async(addr).wait().unwrap();
        let service_client = AsyncServiceClient::new(0, &client);
        let response = service_client.hello(Greeting {
            name: String::from("Jack"),
            time: 12,
        });
        let res = response.wait().unwrap().unwrap();
        let greeting_str = res.text;
        println!("SERVER RESPONDED: {}", greeting_str);
        assert_eq!(greeting_str, String::from("Hello, Jack. It is 12 now!"));
        assert_eq!(42, res.owner);
    }
}

mod multi_server {

    use super::*;

    service! {
        rpc query_server_id() -> u64;
    }

    struct IdServer {
        id: u64,
    }
    impl Service for IdServer {
        fn query_server_id(&self) -> Box<Future<Item = u64, Error = ()>> {
            box future::ok(self.id)
        }
    }
    dispatch_rpc_service_functions!(IdServer);

    #[test]
    fn multi_server_rpc() {
        let addrs = vec![
            String::from("127.0.0.1:1500"),
            String::from("127.0.0.1:1600"),
            String::from("127.0.0.1:1700"),
            String::from("127.0.0.1:1800"),
        ];
        let mut id = 0;
        for addr in &addrs {
            {
                let addr = addr.clone();
                thread::spawn(move || {
                    let server = Server::new(&addr); // 0 is service id
                    server.register_service(id, &Arc::new(IdServer { id: id }));
                    Server::listen(&server);
                });
                id += 1;
            }
        }
        id = 0;
        thread::sleep(Duration::from_millis(1000));
        for addr in &addrs {
            let client = RPCClient::new_async(addr.clone()).wait().unwrap();
            let service_client = AsyncServiceClient::new(id, &client);
            let id_res = service_client.query_server_id().wait().unwrap();
            assert_eq!(id_res.unwrap(), id);
            id += 1;
        }
    }
}

mod parallel {

    extern crate rayon;
    use self::rayon::iter::IntoParallelIterator;
    use self::rayon::prelude::*;
    use super::struct_service::*;
    use super::*;
    use bifrost_hasher::hash_str;

    #[test]
    pub fn lots_of_reqs() {
        let addr = String::from("127.0.0.1:1411");
        {
            let addr = addr.clone();
            let server = Server::new(&addr); // 0 is service id
            server.register_service(0, &Arc::new(HelloServer));
            Server::listen_and_resume(&server);
        }
        thread::sleep(Duration::from_millis(1000));
        let client = RPCClient::new_async(addr.clone()).wait().unwrap();
        let service_client = AsyncServiceClient::new(0, &client);

        println!("Testing parallel RPC reqs");

        (0..1000).collect::<Vec<_>>().into_par_iter().for_each(|i| {
            let response = service_client.hello(Greeting {
                name: String::from("John"),
                time: i,
            });
            let res = response.wait().unwrap().unwrap();
            let greeting_str = res.text;
            println!("SERVER RESPONDED: {}", greeting_str);
            assert_eq!(greeting_str, format!("Hello, John. It is {} now!", i));
            assert_eq!(42, res.owner);
        });

        // test pool
        let server_id = hash_str(&addr);
        (0..1000).collect::<Vec<_>>().into_par_iter().for_each(|i| {
            let client = DEFAULT_CLIENT_POOL.get_by_id(server_id, |_| (&addr).clone()).unwrap();
            let service_client = AsyncServiceClient::new(0, &client);
            let response = service_client.hello(Greeting {
                name: String::from("John"),
                time: i,
            });
            let res = response.wait().unwrap().unwrap();
            let greeting_str = res.text;
            println!("SERVER RESPONDED: {}", greeting_str);
            assert_eq!(greeting_str, format!("Hello, John. It is {} now!", i));
            assert_eq!(42, res.owner);
        });
    }
}
<|endoftext|>


<commit_before>//! Tree nodes, the representation of SVG elements.
//!
//! Librsvg uses the [rctree crate][rctree] to represent the SVG tree of elements.
//! Its [`Node`] struct provides a generic wrapper over nodes in a tree.
//! Librsvg puts a [`NodeData`] as the type parameter of [`Node`].  For convenience,
//! librsvg has a type alias `Node = Node<NodeData>`.
//!
//! Nodes are not constructed directly by callers;
//!
//! [rctree]: ../../rctree/index.html
//! [`Node`]: ../../rctree/struct.Node.html
//! [`NodeData`]: struct.NodeData.html

use markup5ever::QualName;
use std::cell::{Ref, RefMut};
use std::fmt;

use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::*;
use crate::error::*;
use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
use crate::text::Chars;

/// Strong reference to an element in the SVG tree.
///
/// See the [module documentation](index.html) for more information.
pub type Node = rctree::Node<NodeData>;

/// Weak reference to an element in the SVG tree.
///
/// See the [module documentation](index.html) for more information.
pub type WeakNode = rctree::WeakNode<NodeData>;

/// Data for a single DOM node.
///
/// ## Memory consumption
///
/// SVG files look like this, roughly:
///
/// ```xml
/// <svg>
///   <rect x="10" y="20"/>
///   <path d="..."/>
///   <text x="10" y="20">Hello</text>
///   <!-- etc -->
/// </svg>
/// ```
///
/// Each element has a bunch of data, including the styles, which is
/// the biggest consumer of memory within the `Element` struct.  But
/// between each element there is a text node; in the example above
/// there are a bunch of text nodes with just whitespace (newlines and
/// spaces), and a single text node with "`Hello`" in it from the
/// `<text>` element.
///
/// ## Accessing the node's contents
///
/// Code that traverses the DOM tree needs to find out at runtime what
/// each node stands for.  First, use the `is_chars` or `is_element`
/// methods from the `NodeBorrow` trait to see if you can then call
/// `borrow_chars`, `borrow_element`, or `borrow_element_mut`.
pub enum NodeData {
    Element(Element),
    Text(Chars),
}

impl NodeData {
    pub fn new_element(name: &QualName, pbag: &PropertyBag) -> NodeData {
        NodeData::Element(Element::new(name, pbag))
    }

    pub fn new_chars() -> NodeData {
        NodeData::Text(Chars::new())
    }
}

impl fmt::Display for NodeData {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            NodeData::Element(ref e) => {
                write!(f, "{}", e)?;
            }
            NodeData::Text(_) => {
                write!(f, "Chars")?;
            }
        }

        Ok(())
    }
}

/// Can obtain computed values from a node
///
/// In our tree of SVG elements (Node in our parlance), each node stores a `ComputedValues` that
/// gets computed during the initial CSS cascade.  However, sometimes nodes need to be rendered
/// outside the normal hierarchy.  For example, the `<use>` element can "instance" a subtree from
/// elsewhere in the SVG; it causes the instanced subtree to re-cascade from the computed values for
/// the `<use>` element.
///
/// You can then call the `get()` method on the resulting `CascadedValues` to get a
/// `&ComputedValues` whose fields you can access.
pub struct CascadedValues<'a> {
    inner: CascadedInner<'a>,
}

enum CascadedInner<'a> {
    FromNode(Ref<'a, Element>),
    FromValues(ComputedValues),
}

impl<'a> CascadedValues<'a> {
    /// Creates a `CascadedValues` that has the same cascading mode as &self
    ///
    /// This is what nodes should normally use to draw their children from their `draw()` method.
    /// Nodes that need to override the cascade for their children can use `new_from_values()`
    /// instead.
    pub fn new(&self, node: &'a Node) -> CascadedValues<'a> {
        match self.inner {
            CascadedInner::FromNode(_) => CascadedValues {
                inner: CascadedInner::FromNode(node.borrow_element()),
            },

            CascadedInner::FromValues(ref v) => CascadedValues::new_from_values(node, v),
        }
    }

    /// Creates a `CascadedValues` that will hold the `node`'s computed values
    ///
    /// This is to be used only in the toplevel drawing function, or in elements like `<marker>`
    /// that don't propagate their parent's cascade to their children.  All others should use
    /// `new()` to derive the cascade from an existing one.
    pub fn new_from_node(node: &Node) -> CascadedValues<'_> {
        CascadedValues {
            inner: CascadedInner::FromNode(node.borrow_element()),
        }
    }

    /// Creates a `CascadedValues` that will override the `node`'s cascade with the specified
    /// `values`
    ///
    /// This is for the `<use>` element, which draws the element which it references with the
    /// `<use>`'s own cascade, not wih the element's original cascade.
    pub fn new_from_values(node: &'a Node, values: &ComputedValues) -> CascadedValues<'a> {
        let mut v = values.clone();
        node.borrow_element()
            .get_specified_values()
            .to_computed_values(&mut v);

        CascadedValues {
            inner: CascadedInner::FromValues(v),
        }
    }

    /// Returns the cascaded `ComputedValues`.
    ///
    /// Nodes should use this from their `SetAttributes::draw()` implementation to get the
    /// `ComputedValues` from the `CascadedValues` that got passed to `draw()`.
    pub fn get(&'a self) -> &'a ComputedValues {
        match self.inner {
            CascadedInner::FromNode(ref e) => e.get_computed_values(),
            CascadedInner::FromValues(ref v) => v,
        }
    }
}

/// Helper trait to get different NodeData variants
pub trait NodeBorrow {
    /// Returns `false` for NodeData::Text, `true` otherwise.
    fn is_element(&self) -> bool;

    /// Returns `true` for NodeData::Text, `false` otherwise.
    fn is_chars(&self) -> bool;

    /// Borrows a `Chars` reference.
    ///
    /// Panics: will panic if `&self` is not a `NodeData::Text` node
    fn borrow_chars(&self) -> Ref<Chars>;

    /// Borrows an `Element` reference
    ///
    /// Panics: will panic if `&self` is not a `NodeData::Element` node
    fn borrow_element(&self) -> Ref<Element>;

    /// Borrows an `Element` reference mutably
    ///
    /// Panics: will panic if `&self` is not a `NodeData::Element` node
    fn borrow_element_mut(&mut self) -> RefMut<Element>;
}

impl NodeBorrow for Node {
    fn is_element(&self) -> bool {
        match *self.borrow() {
            NodeData::Element(_) => true,
            _ => false,
        }
    }

    fn is_chars(&self) -> bool {
        match *self.borrow() {
            NodeData::Text(_) => true,
            _ => false,
        }
    }

    fn borrow_chars(&self) -> Ref<Chars> {
        Ref::map(self.borrow(), |n| match *n {
            NodeData::Text(ref c) => c,
            _ => panic!("tried to borrow_chars for a non-text node"),
        })
    }

    fn borrow_element(&self) -> Ref<Element> {
        Ref::map(self.borrow(), |n| match *n {
            NodeData::Element(ref e) => e,
            _ => panic!("tried to borrow_element for a non-element node"),
        })
    }

    fn borrow_element_mut(&mut self) -> RefMut<Element> {
        RefMut::map(self.borrow_mut(), |n| match *n {
            NodeData::Element(ref mut e) => e,
            _ => panic!("tried to borrow_element_mut for a non-element node"),
        })
    }
}

#[macro_export]
macro_rules! is_element_of_type {
    ($node:expr, $element_type:ident) => {
        matches::matches!(
            *$node.borrow_element(),
            crate::element::Element::$element_type(_)
        )
    };
}

#[macro_export]
macro_rules! borrow_element_as {
    ($node:expr, $element_type:ident) => {
        std::cell::Ref::map($node.borrow_element(), |e| match *e {
            crate::element::Element::$element_type(ref e) => &*e,
            _ => panic!("tried to borrow_element_as {}", stringify!($element_type)),
        })
    };
}

/// Helper trait for cascading recursively
pub trait NodeCascade {
    fn cascade(&mut self, values: &ComputedValues);
}

impl NodeCascade for Node {
    fn cascade(&mut self, values: &ComputedValues) {
        let mut values = values.clone();

        {
            let mut elt = self.borrow_element_mut();

            elt.get_specified_values().to_computed_values(&mut values);
            elt.set_computed_values(&values);
        }

        for mut child in self.children().filter(|c| c.is_element()) {
            child.cascade(&values);
        }
    }
}

/// Helper trait for drawing recursively
pub trait NodeDraw {
    fn draw(
        &self,
        acquired_nodes: &mut AcquiredNodes,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError>;

    fn draw_children(
        &self,
        acquired_nodes: &mut AcquiredNodes,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError>;
}

impl NodeDraw for Node {
    fn draw(
        &self,
        acquired_nodes: &mut AcquiredNodes,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError> {
        match *self.borrow() {
            NodeData::Element(ref e) => e.draw(self, acquired_nodes, cascaded, draw_ctx, clipping),
            _ => Ok(draw_ctx.empty_bbox()),
        }
    }

    fn draw_children(
        &self,
        acquired_nodes: &mut AcquiredNodes,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError> {
        let mut bbox = draw_ctx.empty_bbox();

        for child in self.children().filter(|c| c.is_element()) {
            let child_bbox = draw_ctx.draw_node_from_stack(
                &child,
                acquired_nodes,
                &CascadedValues::new(cascaded, &child),
                clipping,
            )?;
            bbox.insert(&child_bbox);
        }

        Ok(bbox)
    }
}
<commit_msg>node: fix comment<commit_after>//! Tree nodes, the representation of SVG elements.
//!
//! Librsvg uses the [rctree crate][rctree] to represent the SVG tree of elements.
//! Its [`Node`] struct provides a generic wrapper over nodes in a tree.
//! Librsvg puts a [`NodeData`] as the type parameter of [`Node`].  For convenience,
//! librsvg has a type alias `Node = Node<NodeData>`.
//!
//! Nodes are not constructed directly by callers;
//!
//! [rctree]: ../../rctree/index.html
//! [`Node`]: ../../rctree/struct.Node.html
//! [`NodeData`]: struct.NodeData.html

use markup5ever::QualName;
use std::cell::{Ref, RefMut};
use std::fmt;

use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::*;
use crate::error::*;
use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
use crate::text::Chars;

/// Strong reference to an element in the SVG tree.
///
/// See the [module documentation](index.html) for more information.
pub type Node = rctree::Node<NodeData>;

/// Weak reference to an element in the SVG tree.
///
/// See the [module documentation](index.html) for more information.
pub type WeakNode = rctree::WeakNode<NodeData>;

/// Data for a single DOM node.
///
/// ## Memory consumption
///
/// SVG files look like this, roughly:
///
/// ```xml
/// <svg>
///   <rect x="10" y="20"/>
///   <path d="..."/>
///   <text x="10" y="20">Hello</text>
///   <!-- etc -->
/// </svg>
/// ```
///
/// Each element has a bunch of data, including the styles, which is
/// the biggest consumer of memory within the `Element` struct.  But
/// between each element there is a text node; in the example above
/// there are a bunch of text nodes with just whitespace (newlines and
/// spaces), and a single text node with "`Hello`" in it from the
/// `<text>` element.
///
/// ## Accessing the node's contents
///
/// Code that traverses the DOM tree needs to find out at runtime what
/// each node stands for.  First, use the `is_chars` or `is_element`
/// methods from the `NodeBorrow` trait to see if you can then call
/// `borrow_chars`, `borrow_element`, or `borrow_element_mut`.
pub enum NodeData {
    Element(Element),
    Text(Chars),
}

impl NodeData {
    pub fn new_element(name: &QualName, pbag: &PropertyBag) -> NodeData {
        NodeData::Element(Element::new(name, pbag))
    }

    pub fn new_chars() -> NodeData {
        NodeData::Text(Chars::new())
    }
}

impl fmt::Display for NodeData {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            NodeData::Element(ref e) => {
                write!(f, "{}", e)?;
            }
            NodeData::Text(_) => {
                write!(f, "Chars")?;
            }
        }

        Ok(())
    }
}

/// Can obtain computed values from a node
///
/// In our tree of SVG elements (Node in our parlance), each node stores a `ComputedValues` that
/// gets computed during the initial CSS cascade.  However, sometimes nodes need to be rendered
/// outside the normal hierarchy.  For example, the `<use>` element can "instance" a subtree from
/// elsewhere in the SVG; it causes the instanced subtree to re-cascade from the computed values for
/// the `<use>` element.
///
/// You can then call the `get()` method on the resulting `CascadedValues` to get a
/// `&ComputedValues` whose fields you can access.
pub struct CascadedValues<'a> {
    inner: CascadedInner<'a>,
}

enum CascadedInner<'a> {
    FromNode(Ref<'a, Element>),
    FromValues(ComputedValues),
}

impl<'a> CascadedValues<'a> {
    /// Creates a `CascadedValues` that has the same cascading mode as &self
    ///
    /// This is what nodes should normally use to draw their children from their `draw()` method.
    /// Nodes that need to override the cascade for their children can use `new_from_values()`
    /// instead.
    pub fn new(&self, node: &'a Node) -> CascadedValues<'a> {
        match self.inner {
            CascadedInner::FromNode(_) => CascadedValues {
                inner: CascadedInner::FromNode(node.borrow_element()),
            },

            CascadedInner::FromValues(ref v) => CascadedValues::new_from_values(node, v),
        }
    }

    /// Creates a `CascadedValues` that will hold the `node`'s computed values
    ///
    /// This is to be used only in the toplevel drawing function, or in elements like `<marker>`
    /// that don't propagate their parent's cascade to their children.  All others should use
    /// `new()` to derive the cascade from an existing one.
    pub fn new_from_node(node: &Node) -> CascadedValues<'_> {
        CascadedValues {
            inner: CascadedInner::FromNode(node.borrow_element()),
        }
    }

    /// Creates a `CascadedValues` that will override the `node`'s cascade with the specified
    /// `values`
    ///
    /// This is for the `<use>` element, which draws the element which it references with the
    /// `<use>`'s own cascade, not wih the element's original cascade.
    pub fn new_from_values(node: &'a Node, values: &ComputedValues) -> CascadedValues<'a> {
        let mut v = values.clone();
        node.borrow_element()
            .get_specified_values()
            .to_computed_values(&mut v);

        CascadedValues {
            inner: CascadedInner::FromValues(v),
        }
    }

    /// Returns the cascaded `ComputedValues`.
    ///
    /// Nodes should use this from their `Draw::draw()` implementation to get the
    /// `ComputedValues` from the `CascadedValues` that got passed to `draw()`.
    pub fn get(&'a self) -> &'a ComputedValues {
        match self.inner {
            CascadedInner::FromNode(ref e) => e.get_computed_values(),
            CascadedInner::FromValues(ref v) => v,
        }
    }
}

/// Helper trait to get different NodeData variants
pub trait NodeBorrow {
    /// Returns `false` for NodeData::Text, `true` otherwise.
    fn is_element(&self) -> bool;

    /// Returns `true` for NodeData::Text, `false` otherwise.
    fn is_chars(&self) -> bool;

    /// Borrows a `Chars` reference.
    ///
    /// Panics: will panic if `&self` is not a `NodeData::Text` node
    fn borrow_chars(&self) -> Ref<Chars>;

    /// Borrows an `Element` reference
    ///
    /// Panics: will panic if `&self` is not a `NodeData::Element` node
    fn borrow_element(&self) -> Ref<Element>;

    /// Borrows an `Element` reference mutably
    ///
    /// Panics: will panic if `&self` is not a `NodeData::Element` node
    fn borrow_element_mut(&mut self) -> RefMut<Element>;
}

impl NodeBorrow for Node {
    fn is_element(&self) -> bool {
        match *self.borrow() {
            NodeData::Element(_) => true,
            _ => false,
        }
    }

    fn is_chars(&self) -> bool {
        match *self.borrow() {
            NodeData::Text(_) => true,
            _ => false,
        }
    }

    fn borrow_chars(&self) -> Ref<Chars> {
        Ref::map(self.borrow(), |n| match *n {
            NodeData::Text(ref c) => c,
            _ => panic!("tried to borrow_chars for a non-text node"),
        })
    }

    fn borrow_element(&self) -> Ref<Element> {
        Ref::map(self.borrow(), |n| match *n {
            NodeData::Element(ref e) => e,
            _ => panic!("tried to borrow_element for a non-element node"),
        })
    }

    fn borrow_element_mut(&mut self) -> RefMut<Element> {
        RefMut::map(self.borrow_mut(), |n| match *n {
            NodeData::Element(ref mut e) => e,
            _ => panic!("tried to borrow_element_mut for a non-element node"),
        })
    }
}

#[macro_export]
macro_rules! is_element_of_type {
    ($node:expr, $element_type:ident) => {
        matches::matches!(
            *$node.borrow_element(),
            crate::element::Element::$element_type(_)
        )
    };
}

#[macro_export]
macro_rules! borrow_element_as {
    ($node:expr, $element_type:ident) => {
        std::cell::Ref::map($node.borrow_element(), |e| match *e {
            crate::element::Element::$element_type(ref e) => &*e,
            _ => panic!("tried to borrow_element_as {}", stringify!($element_type)),
        })
    };
}

/// Helper trait for cascading recursively
pub trait NodeCascade {
    fn cascade(&mut self, values: &ComputedValues);
}

impl NodeCascade for Node {
    fn cascade(&mut self, values: &ComputedValues) {
        let mut values = values.clone();

        {
            let mut elt = self.borrow_element_mut();

            elt.get_specified_values().to_computed_values(&mut values);
            elt.set_computed_values(&values);
        }

        for mut child in self.children().filter(|c| c.is_element()) {
            child.cascade(&values);
        }
    }
}

/// Helper trait for drawing recursively
pub trait NodeDraw {
    fn draw(
        &self,
        acquired_nodes: &mut AcquiredNodes,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError>;

    fn draw_children(
        &self,
        acquired_nodes: &mut AcquiredNodes,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError>;
}

impl NodeDraw for Node {
    fn draw(
        &self,
        acquired_nodes: &mut AcquiredNodes,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError> {
        match *self.borrow() {
            NodeData::Element(ref e) => e.draw(self, acquired_nodes, cascaded, draw_ctx, clipping),
            _ => Ok(draw_ctx.empty_bbox()),
        }
    }

    fn draw_children(
        &self,
        acquired_nodes: &mut AcquiredNodes,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError> {
        let mut bbox = draw_ctx.empty_bbox();

        for child in self.children().filter(|c| c.is_element()) {
            let child_bbox = draw_ctx.draw_node_from_stack(
                &child,
                acquired_nodes,
                &CascadedValues::new(cascaded, &child),
                clipping,
            )?;
            bbox.insert(&child_bbox);
        }

        Ok(bbox)
    }
}
<|endoftext|>