<commit_before>extern crate cbor;
extern crate quickcheck;
extern crate rand;
extern crate rustc_serialize;

use std::collections::HashMap;
use std::fmt::Debug;
use rand::thread_rng;
use rustc_serialize::{Decodable, Encodable};
use quickcheck::{QuickCheck, StdGen, Testable};

use cbor::{Encoder, Decoder, DirectDecoder, Cbor, CborBytes, CborTagEncode};

fn qc_sized<A: Testable>(f: A, size: u64) {
    QuickCheck::new()
        .gen(StdGen::new(thread_rng(), size as usize))
        .tests(1_00)
        .max_tests(10_000)
        .quickcheck(f);
}

fn round_trip<T>(v: T) -> bool
        where T: Decodable + Encodable + Debug + PartialEq {
    let backv: T = decode(&encode(&v));
    assert_eq!(backv, v);
    true
}

fn encode<T: Encodable>(v: T) -> Vec<u8> {
    let mut enc = Encoder::from_memory();
    enc.encode(&[v]).unwrap();
    enc.as_bytes().to_vec()
}

fn decode<T: Decodable>(bytes: &[u8]) -> T {
    Decoder::from_bytes(bytes).decode().next().unwrap().unwrap()
}

#[allow(dead_code)]
fn readone(bytes: &[u8]) -> Cbor {
    Decoder::from_bytes(bytes).items().next().unwrap().unwrap()
}

macro_rules! round_trip_num {
    ($name:ident, $ty:ident) => (
        #[test]
        fn $name() {
            #![allow(trivial_numeric_casts)]
            fn prop(n: $ty) -> bool { round_trip(n) }
            qc_sized(prop as fn($ty) -> bool, ::std::$ty::MAX as u64)
        }
    );
}

round_trip_num!(roundtrip_prop_usize, usize);
round_trip_num!(roundtrip_prop_u64, u64);
round_trip_num!(roundtrip_prop_u32, u32);
round_trip_num!(roundtrip_prop_u16, u16);
round_trip_num!(roundtrip_prop_u8, u8);
round_trip_num!(roundtrip_prop_isize, isize);
round_trip_num!(roundtrip_prop_i64, i64);
round_trip_num!(roundtrip_prop_i32, i32);
round_trip_num!(roundtrip_prop_i16, i16);
round_trip_num!(roundtrip_prop_i8, i8);

#[test]
fn roundtrip_prop_f32() {
    fn prop(n: f32) -> bool { round_trip(n) }
    qc_sized(prop as fn(f32) -> bool, ::std::u64::MAX)
}

#[test]
fn roundtrip_prop_f64() {
    fn prop(n: f64) -> bool { round_trip(n) }
    qc_sized(prop as fn(f64) -> bool, ::std::u64::MAX)
}

#[test]
fn roundtrip_f32_min() {
    round_trip(::std::f32::MIN);
}

#[test]
fn roundtrip_f32_max() {
    round_trip(::std::f32::MAX);
}

#[test]
fn roundtrip_f64_min() {
    round_trip(::std::f64::MIN);
}

#[test]
fn roundtrip_f64_max() {
    round_trip(::std::f64::MAX);
}

macro_rules! round_trip_any {
    ($name:ident, $ty:ty) => (
        #[test]
        fn $name() {
            fn prop(n: $ty) -> bool { round_trip(n) }
            QuickCheck::new().quickcheck(prop as fn($ty) -> bool)
        }
    );
}

round_trip_any!(roundtrip_prop_nil, ());
round_trip_any!(roundtrip_prop_bool, bool);
round_trip_any!(roundtrip_prop_tuple, (i32, u32));
round_trip_any!(roundtrip_prop_tuple_in_tuple, (i32, (u32, i32), u32));
round_trip_any!(roundtrip_prop_vec, Vec<i32>);
round_trip_any!(roundtrip_prop_vec_in_vec, Vec<Vec<i32>>);
round_trip_any!(roundtrip_prop_map, HashMap<String, i32>);
round_trip_any!(roundtrip_prop_vec_in_map, HashMap<String, Vec<i32>>);
// round_trip_any!(roundtrip_prop_map_in_map,
                // HashMap<String, HashMap<String, i32>>);

#[test]
fn roundtrip_prop_byte_string() {
    fn prop(n: Vec<u8>) -> bool { round_trip(CborBytes(n)) }
    QuickCheck::new().quickcheck(prop as fn(Vec<u8>) -> bool)
}

#[test]
fn roundtrip_enum() {
    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    enum Color { Red, Blue(String, i32), Green { s: String, n: i32 } }

    round_trip(Color::Red);
    round_trip(Color::Blue("hi".to_string(), 5));
    round_trip(Color::Green { s: "hi".to_string(), n: 5 });
}

#[test]
fn roundtrip_struct() {
    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    struct Vowels { s: String, n: u32 }

    round_trip(Vowels { s: "cwm".to_string(), n: 1 });
}

#[test]
#[should_panic]
fn invalid_map_key() {
    let mut map = HashMap::new();
    map.insert(5, 5);
    encode(map);
}

#[test]
fn roundtrip_prop_tag() {
    use rustc_serialize::{Decoder, Encoder};

    #[derive(Debug, PartialEq)]
    struct MyTag {
        num: u64,
        data: Vec<i32>,
    }
    impl Decodable for MyTag {
        fn decode<D: Decoder>(d: &mut D) -> Result<MyTag, D::Error> {
            let tag = try!(d.read_u64());
            Ok(MyTag { num: tag, data: try!(Decodable::decode(d)) })
        }
    }
    impl Encodable for MyTag {
        fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
            CborTagEncode::new(self.num, &self.data).encode(e)
        }
    }
    fn prop(num: u64, data: Vec<i32>) -> bool {
        round_trip(MyTag { num: num, data: data })
    }
    QuickCheck::new().quickcheck(prop as fn(u64, Vec<i32>) -> bool)
}

#[test]
fn roundtrip_tag_fancier_data() {
    use rustc_serialize::{Decoder, Encoder};

    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    struct DataName(Vec<u8>);

    #[derive(Debug, PartialEq)]
    struct CustomData {
        name: DataName,
        value: Vec<u8>,
    }

    impl Decodable for CustomData {
        fn decode<D: Decoder>(d: &mut D) -> Result<CustomData, D::Error> {
            let _ = try!(d.read_u64());
            let (name, value) = try!(Decodable::decode(d));
            Ok(CustomData { name: name, value: value })
        }
    }
    impl Encodable for CustomData {
        fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
            CborTagEncode::new(100_000, &(&self.name, &self.value)).encode(e)
        }
    }
    assert!(round_trip(CustomData {
        name: DataName(b"hello".to_vec()),
        value: vec![1, 2, 3, 4, 5],
    }));
}

#[test]
fn test_oom() {
   let bad = vec![155u8, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF];
   let mut dec = Decoder::from_bytes(bad);
   assert!(dec.decode::<Vec<u32>>().next().is_none());
}

// #[test]
// fn test_oom_direct() {
   // let bad = vec![155u8, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF];
   // assert!(Vec::<u32>::decode(&mut DirectDecoder::from_bytes(bad)).is_err());
// }
<commit_msg>Remove unused import.<commit_after>extern crate cbor;
extern crate quickcheck;
extern crate rand;
extern crate rustc_serialize;

use std::collections::HashMap;
use std::fmt::Debug;
use rand::thread_rng;
use rustc_serialize::{Decodable, Encodable};
use quickcheck::{QuickCheck, StdGen, Testable};

use cbor::{Encoder, Decoder, Cbor, CborBytes, CborTagEncode};

fn qc_sized<A: Testable>(f: A, size: u64) {
    QuickCheck::new()
        .gen(StdGen::new(thread_rng(), size as usize))
        .tests(1_00)
        .max_tests(10_000)
        .quickcheck(f);
}

fn round_trip<T>(v: T) -> bool
        where T: Decodable + Encodable + Debug + PartialEq {
    let backv: T = decode(&encode(&v));
    assert_eq!(backv, v);
    true
}

fn encode<T: Encodable>(v: T) -> Vec<u8> {
    let mut enc = Encoder::from_memory();
    enc.encode(&[v]).unwrap();
    enc.as_bytes().to_vec()
}

fn decode<T: Decodable>(bytes: &[u8]) -> T {
    Decoder::from_bytes(bytes).decode().next().unwrap().unwrap()
}

#[allow(dead_code)]
fn readone(bytes: &[u8]) -> Cbor {
    Decoder::from_bytes(bytes).items().next().unwrap().unwrap()
}

macro_rules! round_trip_num {
    ($name:ident, $ty:ident) => (
        #[test]
        fn $name() {
            #![allow(trivial_numeric_casts)]
            fn prop(n: $ty) -> bool { round_trip(n) }
            qc_sized(prop as fn($ty) -> bool, ::std::$ty::MAX as u64)
        }
    );
}

round_trip_num!(roundtrip_prop_usize, usize);
round_trip_num!(roundtrip_prop_u64, u64);
round_trip_num!(roundtrip_prop_u32, u32);
round_trip_num!(roundtrip_prop_u16, u16);
round_trip_num!(roundtrip_prop_u8, u8);
round_trip_num!(roundtrip_prop_isize, isize);
round_trip_num!(roundtrip_prop_i64, i64);
round_trip_num!(roundtrip_prop_i32, i32);
round_trip_num!(roundtrip_prop_i16, i16);
round_trip_num!(roundtrip_prop_i8, i8);

#[test]
fn roundtrip_prop_f32() {
    fn prop(n: f32) -> bool { round_trip(n) }
    qc_sized(prop as fn(f32) -> bool, ::std::u64::MAX)
}

#[test]
fn roundtrip_prop_f64() {
    fn prop(n: f64) -> bool { round_trip(n) }
    qc_sized(prop as fn(f64) -> bool, ::std::u64::MAX)
}

#[test]
fn roundtrip_f32_min() {
    round_trip(::std::f32::MIN);
}

#[test]
fn roundtrip_f32_max() {
    round_trip(::std::f32::MAX);
}

#[test]
fn roundtrip_f64_min() {
    round_trip(::std::f64::MIN);
}

#[test]
fn roundtrip_f64_max() {
    round_trip(::std::f64::MAX);
}

macro_rules! round_trip_any {
    ($name:ident, $ty:ty) => (
        #[test]
        fn $name() {
            fn prop(n: $ty) -> bool { round_trip(n) }
            QuickCheck::new().quickcheck(prop as fn($ty) -> bool)
        }
    );
}

round_trip_any!(roundtrip_prop_nil, ());
round_trip_any!(roundtrip_prop_bool, bool);
round_trip_any!(roundtrip_prop_tuple, (i32, u32));
round_trip_any!(roundtrip_prop_tuple_in_tuple, (i32, (u32, i32), u32));
round_trip_any!(roundtrip_prop_vec, Vec<i32>);
round_trip_any!(roundtrip_prop_vec_in_vec, Vec<Vec<i32>>);
round_trip_any!(roundtrip_prop_map, HashMap<String, i32>);
round_trip_any!(roundtrip_prop_vec_in_map, HashMap<String, Vec<i32>>);
// round_trip_any!(roundtrip_prop_map_in_map,
                // HashMap<String, HashMap<String, i32>>);

#[test]
fn roundtrip_prop_byte_string() {
    fn prop(n: Vec<u8>) -> bool { round_trip(CborBytes(n)) }
    QuickCheck::new().quickcheck(prop as fn(Vec<u8>) -> bool)
}

#[test]
fn roundtrip_enum() {
    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    enum Color { Red, Blue(String, i32), Green { s: String, n: i32 } }

    round_trip(Color::Red);
    round_trip(Color::Blue("hi".to_string(), 5));
    round_trip(Color::Green { s: "hi".to_string(), n: 5 });
}

#[test]
fn roundtrip_struct() {
    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    struct Vowels { s: String, n: u32 }

    round_trip(Vowels { s: "cwm".to_string(), n: 1 });
}

#[test]
#[should_panic]
fn invalid_map_key() {
    let mut map = HashMap::new();
    map.insert(5, 5);
    encode(map);
}

#[test]
fn roundtrip_prop_tag() {
    use rustc_serialize::{Decoder, Encoder};

    #[derive(Debug, PartialEq)]
    struct MyTag {
        num: u64,
        data: Vec<i32>,
    }
    impl Decodable for MyTag {
        fn decode<D: Decoder>(d: &mut D) -> Result<MyTag, D::Error> {
            let tag = try!(d.read_u64());
            Ok(MyTag { num: tag, data: try!(Decodable::decode(d)) })
        }
    }
    impl Encodable for MyTag {
        fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
            CborTagEncode::new(self.num, &self.data).encode(e)
        }
    }
    fn prop(num: u64, data: Vec<i32>) -> bool {
        round_trip(MyTag { num: num, data: data })
    }
    QuickCheck::new().quickcheck(prop as fn(u64, Vec<i32>) -> bool)
}

#[test]
fn roundtrip_tag_fancier_data() {
    use rustc_serialize::{Decoder, Encoder};

    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    struct DataName(Vec<u8>);

    #[derive(Debug, PartialEq)]
    struct CustomData {
        name: DataName,
        value: Vec<u8>,
    }

    impl Decodable for CustomData {
        fn decode<D: Decoder>(d: &mut D) -> Result<CustomData, D::Error> {
            let _ = try!(d.read_u64());
            let (name, value) = try!(Decodable::decode(d));
            Ok(CustomData { name: name, value: value })
        }
    }
    impl Encodable for CustomData {
        fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
            CborTagEncode::new(100_000, &(&self.name, &self.value)).encode(e)
        }
    }
    assert!(round_trip(CustomData {
        name: DataName(b"hello".to_vec()),
        value: vec![1, 2, 3, 4, 5],
    }));
}

#[test]
fn test_oom() {
   let bad = vec![155u8, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF];
   let mut dec = Decoder::from_bytes(bad);
   assert!(dec.decode::<Vec<u32>>().next().is_none());
}

// #[test]
// fn test_oom_direct() {
   // let bad = vec![155u8, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF];
   // assert!(Vec::<u32>::decode(&mut DirectDecoder::from_bytes(bad)).is_err());
// }
<|endoftext|>


<commit_before>use std::fs::{copy, File};
use std::io::Read;
use std::path::Path;
use std::process::Command;

use assert_cmd::prelude::*;
use nom_bibtex::Bibtex;

use tempdir::TempDir;

mod text;

fn check_output_aux_bibtex(bibtex: &Bibtex<'_>) {
    let bib = bibtex.bibliographies();
    assert_eq!(2, bib.len());

    // Output could conceivably change in future, so just check that some things are right
    assert_eq!(bib[0].entry_type(), "article");
    assert_eq!(bib[0].citation_key(), "Higgs:2014aqa");
    assert_eq!(
        bib[0].tags()[0],
        ("author".into(), "Higgs, Peter W.".into())
    );
    assert_eq!(
        bib[0].tags()[1],
        (
            "title".into(),
            "{Nobel Lecture: Evading the Goldstone theorem}".into(),
        )
    );
    assert_eq!(bib[0].tags()[4], ("year".into(), "2014".into()));

    assert_eq!(bib[1].entry_type(), "article");
    assert_eq!(bib[1].citation_key(), "Higgs:2015mei");
    assert_eq!(bib[1].tags()[0], ("author".into(), "Higgs, P. W.".into()));
    assert_eq!(
        bib[1].tags()[1],
        ("title".into(), "{Evading the Goldstone theorem}".into(),)
    );
    assert_eq!(bib[1].tags()[4], ("year".into(), "2015".into()));
}

fn check_output_aux_biblatex(bibtex: &Bibtex<'_>) {
    let bib = bibtex.bibliographies();
    assert_eq!(4, bib.len());

    // Output could conceivably change in future, so just check that some things are right
    assert_eq!(bib[2].entry_type(), "article");
    assert_eq!(bib[2].citation_key(), "Guth:1980zm");
    assert_eq!(bib[2].tags()[0], ("author".into(), "Guth, Alan H.".into()));
    assert_eq!(bib[2].tags()[1], (
        "title".into(),
        "{The Inflationary Universe: A Possible Solution to the\n                        Horizon and Flatness Problems}"
            .into(),
    ));
    assert_eq!(bib[2].tags()[4], ("year".into(), "1981".into()));

    assert_eq!(bib[0].entry_type(), "ARTICLE");
    assert_eq!(bib[0].citation_key(), "1982PhRvL..48.1220A");
    assert_eq!(
        bib[0].tags()[1],
        (
            "title".into(),
            "{Cosmology for grand unified theories with radiatively induced symmetry breaking}"
                .into(),
        )
    );
    assert_eq!(bib[0].tags()[4], ("year".into(), "1982".into()));
}

fn check_output_blg_bibtex(bibtex: &Bibtex<'_>) {
    let bib = bibtex.bibliographies();
    assert_eq!(2, bib.len());

    // Output could conceivably change in future, so just check that some things are right
    assert_eq!(bib[0].entry_type(), "article");
    assert_eq!(bib[0].citation_key(), "Higgs:2014aqa");
    assert_eq!(
        bib[0].tags()[0],
        ("author".into(), "Higgs, Peter W.".into())
    );
    assert_eq!(
        bib[0].tags()[1],
        (
            "title".into(),
            "{Nobel Lecture: Evading the Goldstone theorem}".into(),
        )
    );
    assert_eq!(bib[0].tags()[4], ("year".into(), "2014".into()));

    assert_eq!(bib[1].entry_type(), "article");
    assert_eq!(bib[1].citation_key(), "Higgs:2015mei");
    assert_eq!(bib[1].tags()[0], ("author".into(), "Higgs, P. W.".into()));
    assert_eq!(
        bib[1].tags()[1],
        ("title".into(), "{Evading the Goldstone theorem}".into(),)
    );
    assert_eq!(bib[1].tags()[4], ("year".into(), "2015".into()));
}

fn check_output_blg_biblatex(bibtex: &Bibtex<'_>) {
    let bib = bibtex.bibliographies();
    assert_eq!(4, bib.len());

    // Output could conceivably change in future, so just check that some things are right
    assert_eq!(bib[2].entry_type(), "article");
    assert_eq!(bib[2].citation_key(), "Guth:1980zm");
    assert_eq!(bib[2].tags()[0], ("author".into(), "Guth, Alan H.".into()));
    assert_eq!(bib[2].tags()[1], (
        "title".into(),
        "{The Inflationary Universe: A Possible Solution to the\n                        Horizon and Flatness Problems}"
            .into(),
    ));
    assert_eq!(bib[2].tags()[4], ("year".into(), "1981".into()));

    assert_eq!(bib[0].entry_type(), "ARTICLE");
    assert_eq!(bib[0].citation_key(), "1982PhRvL..48.1220A");
    assert_eq!(
        bib[0].tags()[1],
        (
            "title".into(),
            "{Cosmology for grand unified theories with radiatively induced symmetry breaking}"
                .into(),
        )
    );
    assert_eq!(bib[0].tags()[4], ("year".into(), "1982".into()));
}

#[cfg(not(windows))]
#[test]
fn aux2bib_runs() {
    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.arg("--help");
    cmd.assert().success();
}

#[cfg(not(windows))]
#[test]
fn blg2bib_runs() {
    let mut cmd = Command::cargo_bin("blg2bib").unwrap();
    cmd.arg("--help");
    cmd.assert().success();
}

#[cfg(not(windows))]
#[test]
fn aux2bib_stdin_stdout_empty() {
    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.with_stdin().buffer("");

    cmd.assert().success().stdout("");
}

#[cfg(not(windows))]
#[test]
fn blg2bib_stdin_stdout_empty() {
    let mut cmd = Command::cargo_bin("blg2bib").unwrap();
    cmd.with_stdin().buffer("");

    cmd.assert().success().stdout("");
}

#[cfg(not(windows))]
#[test]
fn aux2bib_stdin_stdout_bibtex() {
    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    let path = Path::new("example_files").join("test_bibtex.aux");

    let assert = cmd
        .with_stdin()
        .path(path)
        .expect("example input file exists")
        .assert()
        .success();

    let bibtex = Bibtex::parse(std::str::from_utf8(&assert.get_output().stdout).unwrap())
        .expect("Valid bibtex file content");

    check_output_aux_bibtex(&bibtex);
}

#[cfg(not(windows))]
#[test]
fn aux2bib_stdin_stdout_biblatex() {
    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    let path = Path::new("example_files").join("test_biber.aux");

    let assert = cmd
        .with_stdin()
        .path(path)
        .expect("example input file exists")
        .assert()
        .success();

    let bibtex_raw = &[
        text::MONTH_STRINGS,
        std::str::from_utf8(&assert.get_output().stdout).unwrap(),
    ]
    .join("\n");
    let bibtex = Bibtex::parse(bibtex_raw).expect("Valid bibtex file content");

    check_output_aux_biblatex(&bibtex);
}

#[cfg(not(windows))]
#[test]
fn blg2bib_stdin_stdout_bibtex() {
    let mut cmd = Command::cargo_bin("blg2bib").unwrap();
    let path = Path::new("example_files").join("test_bibtex.blg");

    let assert = cmd
        .with_stdin()
        .path(path)
        .expect("example input file exists")
        .assert()
        .success();

    let bibtex = Bibtex::parse(std::str::from_utf8(&assert.get_output().stdout).unwrap())
        .expect("Valid bibtex file content");

    check_output_blg_bibtex(&bibtex);
}

#[cfg(not(windows))]
#[test]
fn blg2bib_stdin_stdout_biblatex() {
    let mut cmd = Command::cargo_bin("blg2bib").unwrap();
    let path = Path::new("example_files").join("test_biber.blg");

    let assert = cmd
        .with_stdin()
        .path(path)
        .expect("example input file exists")
        .assert()
        .success();

    let bibtex_raw = &[
        text::MONTH_STRINGS,
        std::str::from_utf8(&assert.get_output().stdout).unwrap(),
    ]
    .join("\n");
    let bibtex = Bibtex::parse(bibtex_raw).expect("Valid bibtex file content");

    check_output_blg_biblatex(&bibtex);
}

#[cfg(not(windows))]
#[test]
fn aux2bib_file_stdout_bibtex() {
    let filename_in = "test_bibtex.aux";

    let tmp_dir = TempDir::new("inspirer_test").expect("Failed to create tmp_dir");
    copy(
        Path::new("example_files").join(filename_in),
        tmp_dir.path().join(filename_in),
    )
    .expect("Failed to copy test input");

    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.current_dir(tmp_dir.path()).arg(filename_in);

    let assert = cmd.assert().success();

    let bibtex = Bibtex::parse(std::str::from_utf8(&assert.get_output().stdout).unwrap())
        .expect("Valid bibtex file content");

    check_output_aux_bibtex(&bibtex);
}

#[cfg(not(windows))]
#[test]
/// Test for panic when the input file does not exist
fn aux2bib_file_stdout_bibtex_input_no_exist() {
    let filename_in = "test_bibtex.aux";

    let tmp_dir = TempDir::new("inspirer_test").expect("Failed to create tmp_dir");

    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.current_dir(tmp_dir.path()).arg(filename_in);

    cmd.assert().failure().code(1).stdout("");
}

#[cfg(not(windows))]
#[test]
/// Test reading from file and outputting to another file
fn aux2bib_file_file_bibtex() {
    let filename_in = "test_bibtex.aux";
    let filename_out = "autobib.bib";

    let tmp_dir = TempDir::new("inspirer_test").expect("Failed to create tmp_dir");
    copy(
        Path::new("example_files").join(filename_in),
        tmp_dir.path().join(filename_in),
    )
    .expect("Failed to copy test input");

    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.current_dir(tmp_dir.path())
        .arg(filename_in)
        .arg(filename_out);

    cmd.assert().success().stdout("");

    let mut output_string = String::new();
    let mut output_file =
        File::open(tmp_dir.path().join(filename_out)).expect("Output file not written");
    output_file
        .read_to_string(&mut output_string)
        .expect("Failed to read output file");

    let bibtex = Bibtex::parse(&output_string).expect("Valid bibtex file content");

    check_output_aux_bibtex(&bibtex);
}
<commit_msg>test: Enable integration tests on windows<commit_after>use std::fs::{copy, File};
use std::io::Read;
use std::path::Path;
use std::process::Command;

use assert_cmd::prelude::*;
use nom_bibtex::Bibtex;

use tempdir::TempDir;

mod text;

fn check_output_aux_bibtex(bibtex: &Bibtex<'_>) {
    let bib = bibtex.bibliographies();
    assert_eq!(2, bib.len());

    // Output could conceivably change in future, so just check that some things are right
    assert_eq!(bib[0].entry_type(), "article");
    assert_eq!(bib[0].citation_key(), "Higgs:2014aqa");
    assert_eq!(
        bib[0].tags()[0],
        ("author".into(), "Higgs, Peter W.".into())
    );
    assert_eq!(
        bib[0].tags()[1],
        (
            "title".into(),
            "{Nobel Lecture: Evading the Goldstone theorem}".into(),
        )
    );
    assert_eq!(bib[0].tags()[4], ("year".into(), "2014".into()));

    assert_eq!(bib[1].entry_type(), "article");
    assert_eq!(bib[1].citation_key(), "Higgs:2015mei");
    assert_eq!(bib[1].tags()[0], ("author".into(), "Higgs, P. W.".into()));
    assert_eq!(
        bib[1].tags()[1],
        ("title".into(), "{Evading the Goldstone theorem}".into(),)
    );
    assert_eq!(bib[1].tags()[4], ("year".into(), "2015".into()));
}

fn check_output_aux_biblatex(bibtex: &Bibtex<'_>) {
    let bib = bibtex.bibliographies();
    assert_eq!(4, bib.len());

    // Output could conceivably change in future, so just check that some things are right
    assert_eq!(bib[2].entry_type(), "article");
    assert_eq!(bib[2].citation_key(), "Guth:1980zm");
    assert_eq!(bib[2].tags()[0], ("author".into(), "Guth, Alan H.".into()));
    assert_eq!(bib[2].tags()[1], (
        "title".into(),
        "{The Inflationary Universe: A Possible Solution to the\n                        Horizon and Flatness Problems}"
            .into(),
    ));
    assert_eq!(bib[2].tags()[4], ("year".into(), "1981".into()));

    assert_eq!(bib[0].entry_type(), "ARTICLE");
    assert_eq!(bib[0].citation_key(), "1982PhRvL..48.1220A");
    assert_eq!(
        bib[0].tags()[1],
        (
            "title".into(),
            "{Cosmology for grand unified theories with radiatively induced symmetry breaking}"
                .into(),
        )
    );
    assert_eq!(bib[0].tags()[4], ("year".into(), "1982".into()));
}

fn check_output_blg_bibtex(bibtex: &Bibtex<'_>) {
    let bib = bibtex.bibliographies();
    assert_eq!(2, bib.len());

    // Output could conceivably change in future, so just check that some things are right
    assert_eq!(bib[0].entry_type(), "article");
    assert_eq!(bib[0].citation_key(), "Higgs:2014aqa");
    assert_eq!(
        bib[0].tags()[0],
        ("author".into(), "Higgs, Peter W.".into())
    );
    assert_eq!(
        bib[0].tags()[1],
        (
            "title".into(),
            "{Nobel Lecture: Evading the Goldstone theorem}".into(),
        )
    );
    assert_eq!(bib[0].tags()[4], ("year".into(), "2014".into()));

    assert_eq!(bib[1].entry_type(), "article");
    assert_eq!(bib[1].citation_key(), "Higgs:2015mei");
    assert_eq!(bib[1].tags()[0], ("author".into(), "Higgs, P. W.".into()));
    assert_eq!(
        bib[1].tags()[1],
        ("title".into(), "{Evading the Goldstone theorem}".into(),)
    );
    assert_eq!(bib[1].tags()[4], ("year".into(), "2015".into()));
}

fn check_output_blg_biblatex(bibtex: &Bibtex<'_>) {
    let bib = bibtex.bibliographies();
    assert_eq!(4, bib.len());

    // Output could conceivably change in future, so just check that some things are right
    assert_eq!(bib[2].entry_type(), "article");
    assert_eq!(bib[2].citation_key(), "Guth:1980zm");
    assert_eq!(bib[2].tags()[0], ("author".into(), "Guth, Alan H.".into()));
    assert_eq!(bib[2].tags()[1], (
        "title".into(),
        "{The Inflationary Universe: A Possible Solution to the\n                        Horizon and Flatness Problems}"
            .into(),
    ));
    assert_eq!(bib[2].tags()[4], ("year".into(), "1981".into()));

    assert_eq!(bib[0].entry_type(), "ARTICLE");
    assert_eq!(bib[0].citation_key(), "1982PhRvL..48.1220A");
    assert_eq!(
        bib[0].tags()[1],
        (
            "title".into(),
            "{Cosmology for grand unified theories with radiatively induced symmetry breaking}"
                .into(),
        )
    );
    assert_eq!(bib[0].tags()[4], ("year".into(), "1982".into()));
}

#[test]
fn aux2bib_runs() {
    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.arg("--help");
    cmd.assert().success();
}

#[test]
fn blg2bib_runs() {
    let mut cmd = Command::cargo_bin("blg2bib").unwrap();
    cmd.arg("--help");
    cmd.assert().success();
}

#[test]
fn aux2bib_stdin_stdout_empty() {
    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.with_stdin().buffer("");

    cmd.assert().success().stdout("");
}

#[test]
fn blg2bib_stdin_stdout_empty() {
    let mut cmd = Command::cargo_bin("blg2bib").unwrap();
    cmd.with_stdin().buffer("");

    cmd.assert().success().stdout("");
}

#[test]
fn aux2bib_stdin_stdout_bibtex() {
    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    let path = Path::new("example_files").join("test_bibtex.aux");

    let assert = cmd
        .with_stdin()
        .path(path)
        .expect("example input file exists")
        .assert()
        .success();

    let bibtex = Bibtex::parse(std::str::from_utf8(&assert.get_output().stdout).unwrap())
        .expect("Valid bibtex file content");

    check_output_aux_bibtex(&bibtex);
}

#[test]
fn aux2bib_stdin_stdout_biblatex() {
    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    let path = Path::new("example_files").join("test_biber.aux");

    let assert = cmd
        .with_stdin()
        .path(path)
        .expect("example input file exists")
        .assert()
        .success();

    let bibtex_raw = &[
        text::MONTH_STRINGS,
        std::str::from_utf8(&assert.get_output().stdout).unwrap(),
    ]
    .join("\n");
    let bibtex = Bibtex::parse(bibtex_raw).expect("Valid bibtex file content");

    check_output_aux_biblatex(&bibtex);
}

#[test]
fn blg2bib_stdin_stdout_bibtex() {
    let mut cmd = Command::cargo_bin("blg2bib").unwrap();
    let path = Path::new("example_files").join("test_bibtex.blg");

    let assert = cmd
        .with_stdin()
        .path(path)
        .expect("example input file exists")
        .assert()
        .success();

    let bibtex = Bibtex::parse(std::str::from_utf8(&assert.get_output().stdout).unwrap())
        .expect("Valid bibtex file content");

    check_output_blg_bibtex(&bibtex);
}

#[test]
fn blg2bib_stdin_stdout_biblatex() {
    let mut cmd = Command::cargo_bin("blg2bib").unwrap();
    let path = Path::new("example_files").join("test_biber.blg");

    let assert = cmd
        .with_stdin()
        .path(path)
        .expect("example input file exists")
        .assert()
        .success();

    let bibtex_raw = &[
        text::MONTH_STRINGS,
        std::str::from_utf8(&assert.get_output().stdout).unwrap(),
    ]
    .join("\n");
    let bibtex = Bibtex::parse(bibtex_raw).expect("Valid bibtex file content");

    check_output_blg_biblatex(&bibtex);
}

#[test]
fn aux2bib_file_stdout_bibtex() {
    let filename_in = "test_bibtex.aux";

    let tmp_dir = TempDir::new("inspirer_test").expect("Failed to create tmp_dir");
    copy(
        Path::new("example_files").join(filename_in),
        tmp_dir.path().join(filename_in),
    )
    .expect("Failed to copy test input");

    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.current_dir(tmp_dir.path()).arg(filename_in);

    let assert = cmd.assert().success();

    let bibtex = Bibtex::parse(std::str::from_utf8(&assert.get_output().stdout).unwrap())
        .expect("Valid bibtex file content");

    check_output_aux_bibtex(&bibtex);
}

#[test]
/// Test for panic when the input file does not exist
fn aux2bib_file_stdout_bibtex_input_no_exist() {
    let filename_in = "test_bibtex.aux";

    let tmp_dir = TempDir::new("inspirer_test").expect("Failed to create tmp_dir");

    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.current_dir(tmp_dir.path()).arg(filename_in);

    cmd.assert().failure().code(1).stdout("");
}

#[test]
/// Test reading from file and outputting to another file
fn aux2bib_file_file_bibtex() {
    let filename_in = "test_bibtex.aux";
    let filename_out = "autobib.bib";

    let tmp_dir = TempDir::new("inspirer_test").expect("Failed to create tmp_dir");
    copy(
        Path::new("example_files").join(filename_in),
        tmp_dir.path().join(filename_in),
    )
    .expect("Failed to copy test input");

    let mut cmd = Command::cargo_bin("aux2bib").unwrap();
    cmd.current_dir(tmp_dir.path())
        .arg(filename_in)
        .arg(filename_out);

    cmd.assert().success().stdout("");

    let mut output_string = String::new();
    let mut output_file =
        File::open(tmp_dir.path().join(filename_out)).expect("Output file not written");
    output_file
        .read_to_string(&mut output_string)
        .expect("Failed to read output file");

    let bibtex = Bibtex::parse(&output_string).expect("Valid bibtex file content");

    check_output_aux_bibtex(&bibtex);
}
<|endoftext|>


<commit_before>extern crate cbor;
extern crate quickcheck;
extern crate rand;
extern crate "rustc-serialize" as rustc_serialize;

use std::collections::HashMap;
use std::fmt::Debug;
use rand::thread_rng;
use rustc_serialize::{Decodable, Encodable};
use quickcheck::{QuickCheck, StdGen, Testable};

use cbor::{Encoder, Decoder, Cbor, CborBytes, CborTagEncode};

fn qc_sized<A: Testable>(f: A, size: u64) {
    QuickCheck::new()
        .gen(StdGen::new(thread_rng(), size as usize))
        .tests(1_00)
        .max_tests(10_000)
        .quickcheck(f);
}

fn round_trip<T>(v: T) -> bool
        where T: Decodable + Encodable + Debug + PartialEq {
    let backv: T = decode(&encode(&v));
    assert_eq!(backv, v);
    true
}

fn encode<T: Encodable>(v: T) -> Vec<u8> {
    let mut enc = Encoder::from_memory();
    enc.encode(&[v]).unwrap();
    enc.as_bytes().to_vec()
}

fn decode<T: Decodable>(bytes: &[u8]) -> T {
    Decoder::from_bytes(bytes).decode().next().unwrap().unwrap()
}

#[allow(dead_code)]
fn readone(bytes: &[u8]) -> Cbor {
    Decoder::from_bytes(bytes).items().next().unwrap().unwrap()
}

macro_rules! round_trip_num {
    ($name:ident, $ty:ident) => (
        #[test]
        fn $name() {
            fn prop(n: $ty) -> bool { round_trip(n) }
            qc_sized(prop as fn($ty) -> bool, ::std::$ty::MAX as u64)
        }
    );
}

round_trip_num!(roundtrip_prop_usize, usize);
round_trip_num!(roundtrip_prop_u64, u64);
round_trip_num!(roundtrip_prop_u32, u32);
round_trip_num!(roundtrip_prop_u16, u16);
round_trip_num!(roundtrip_prop_u8, u8);
round_trip_num!(roundtrip_prop_isize, isize);
round_trip_num!(roundtrip_prop_i64, i64);
round_trip_num!(roundtrip_prop_i32, i32);
round_trip_num!(roundtrip_prop_i16, i16);
round_trip_num!(roundtrip_prop_i8, i8);

#[test]
fn roundtrip_prop_f32() {
    fn prop(n: f32) -> bool { round_trip(n) }
    qc_sized(prop as fn(f32) -> bool, ::std::f32::MAX as u64 - 1)
}

#[test]
fn roundtrip_prop_f64() {
    fn prop(n: f64) -> bool { round_trip(n) }
    qc_sized(prop as fn(f64) -> bool, ::std::f64::MAX as u64 - 1)
}

macro_rules! round_trip_any {
    ($name:ident, $ty:ty) => (
        #[test]
        fn $name() {
            fn prop(n: $ty) -> bool { round_trip(n) }
            QuickCheck::new().quickcheck(prop as fn($ty) -> bool)
        }
    );
}

round_trip_any!(roundtrip_prop_nil, ());
round_trip_any!(roundtrip_prop_bool, bool);
round_trip_any!(roundtrip_prop_tuple, (i32, u32));
round_trip_any!(roundtrip_prop_tuple_in_tuple, (i32, (u32, i32), u32));
round_trip_any!(roundtrip_prop_vec, Vec<i32>);
round_trip_any!(roundtrip_prop_vec_in_vec, Vec<Vec<i32>>);
round_trip_any!(roundtrip_prop_map, HashMap<String, i32>);
round_trip_any!(roundtrip_prop_vec_in_map, HashMap<String, Vec<i32>>);
// round_trip_any!(roundtrip_prop_map_in_map,
                // HashMap<String, HashMap<String, i32>>);

#[test]
fn roundtrip_prop_byte_string() {
    fn prop(n: Vec<u8>) -> bool { round_trip(CborBytes(n)) }
    QuickCheck::new().quickcheck(prop as fn(Vec<u8>) -> bool)
}

#[test]
fn roundtrip_enum() {
    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    enum Color { Red, Blue(String, i32), Green { s: String, n: i32 } }

    round_trip(Color::Red);
    round_trip(Color::Blue("hi".to_string(), 5));
    round_trip(Color::Green { s: "hi".to_string(), n: 5 });
}

#[test]
fn roundtrip_struct() {
    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    struct Vowels { s: String, n: u32 }

    round_trip(Vowels { s: "cwm".to_string(), n: 1 });
}

#[test]
#[should_fail]
fn invalid_map_key() {
    let mut map = HashMap::new();
    map.insert(5, 5);
    encode(map);
}

#[test]
fn roundtrip_prop_tag() {
    use rustc_serialize::{Decoder, Encoder};

    #[derive(Debug, PartialEq)]
    struct MyTag {
        num: u64,
        data: Vec<i32>,
    }
    impl Decodable for MyTag {
        fn decode<D: Decoder>(d: &mut D) -> Result<MyTag, D::Error> {
            let tag = try!(d.read_u64());
            Ok(MyTag { num: tag, data: try!(Decodable::decode(d)) })
        }
    }
    impl Encodable for MyTag {
        fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
            CborTagEncode {
                tag: self.num,
                data: &self.data,
            }.encode(e)
        }
    }
    fn prop(num: u64, data: Vec<i32>) -> bool {
        round_trip(MyTag { num: num, data: data })
    }
    QuickCheck::new().quickcheck(prop as fn(u64, Vec<i32>) -> bool)
}
<commit_msg>rustup<commit_after>extern crate cbor;
extern crate quickcheck;
extern crate rand;
extern crate "rustc-serialize" as rustc_serialize;

use std::collections::HashMap;
use std::fmt::Debug;
use rand::thread_rng;
use rustc_serialize::{Decodable, Encodable};
use quickcheck::{QuickCheck, StdGen, Testable};

use cbor::{Encoder, Decoder, Cbor, CborBytes, CborTagEncode};

fn qc_sized<A: Testable>(f: A, size: u64) {
    QuickCheck::new()
        .gen(StdGen::new(thread_rng(), size as usize))
        .tests(1_00)
        .max_tests(10_000)
        .quickcheck(f);
}

fn round_trip<T>(v: T) -> bool
        where T: Decodable + Encodable + Debug + PartialEq {
    let backv: T = decode(&encode(&v));
    assert_eq!(backv, v);
    true
}

fn encode<T: Encodable>(v: T) -> Vec<u8> {
    let mut enc = Encoder::from_memory();
    enc.encode(&[v]).unwrap();
    enc.as_bytes().to_vec()
}

fn decode<T: Decodable>(bytes: &[u8]) -> T {
    Decoder::from_bytes(bytes).decode().next().unwrap().unwrap()
}

#[allow(dead_code)]
fn readone(bytes: &[u8]) -> Cbor {
    Decoder::from_bytes(bytes).items().next().unwrap().unwrap()
}

macro_rules! round_trip_num {
    ($name:ident, $ty:ident) => (
        #[test]
        fn $name() {
            fn prop(n: $ty) -> bool { round_trip(n) }
            qc_sized(prop as fn($ty) -> bool, ::std::$ty::MAX as u64)
        }
    );
}

round_trip_num!(roundtrip_prop_usize, usize);
round_trip_num!(roundtrip_prop_u64, u64);
round_trip_num!(roundtrip_prop_u32, u32);
round_trip_num!(roundtrip_prop_u16, u16);
round_trip_num!(roundtrip_prop_u8, u8);
round_trip_num!(roundtrip_prop_isize, isize);
round_trip_num!(roundtrip_prop_i64, i64);
round_trip_num!(roundtrip_prop_i32, i32);
round_trip_num!(roundtrip_prop_i16, i16);
round_trip_num!(roundtrip_prop_i8, i8);

#[test]
fn roundtrip_prop_f32() {
    fn prop(n: f32) -> bool { round_trip(n) }
    qc_sized(prop as fn(f32) -> bool, ::std::f32::MAX as u64 - 1)
}

#[test]
fn roundtrip_prop_f64() {
    fn prop(n: f64) -> bool { round_trip(n) }
    qc_sized(prop as fn(f64) -> bool, ::std::f64::MAX as u64 - 1)
}

macro_rules! round_trip_any {
    ($name:ident, $ty:ty) => (
        #[test]
        fn $name() {
            fn prop(n: $ty) -> bool { round_trip(n) }
            QuickCheck::new().quickcheck(prop as fn($ty) -> bool)
        }
    );
}

round_trip_any!(roundtrip_prop_nil, ());
round_trip_any!(roundtrip_prop_bool, bool);
round_trip_any!(roundtrip_prop_tuple, (i32, u32));
round_trip_any!(roundtrip_prop_tuple_in_tuple, (i32, (u32, i32), u32));
round_trip_any!(roundtrip_prop_vec, Vec<i32>);
round_trip_any!(roundtrip_prop_vec_in_vec, Vec<Vec<i32>>);
round_trip_any!(roundtrip_prop_map, HashMap<String, i32>);
round_trip_any!(roundtrip_prop_vec_in_map, HashMap<String, Vec<i32>>);
// round_trip_any!(roundtrip_prop_map_in_map,
                // HashMap<String, HashMap<String, i32>>);

#[test]
fn roundtrip_prop_byte_string() {
    fn prop(n: Vec<u8>) -> bool { round_trip(CborBytes(n)) }
    QuickCheck::new().quickcheck(prop as fn(Vec<u8>) -> bool)
}

#[test]
fn roundtrip_enum() {
    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    enum Color { Red, Blue(String, i32), Green { s: String, n: i32 } }

    round_trip(Color::Red);
    round_trip(Color::Blue("hi".to_string(), 5));
    round_trip(Color::Green { s: "hi".to_string(), n: 5 });
}

#[test]
fn roundtrip_struct() {
    #[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)]
    struct Vowels { s: String, n: u32 }

    round_trip(Vowels { s: "cwm".to_string(), n: 1 });
}

#[test]
#[should_panic]
fn invalid_map_key() {
    let mut map = HashMap::new();
    map.insert(5, 5);
    encode(map);
}

#[test]
fn roundtrip_prop_tag() {
    use rustc_serialize::{Decoder, Encoder};

    #[derive(Debug, PartialEq)]
    struct MyTag {
        num: u64,
        data: Vec<i32>,
    }
    impl Decodable for MyTag {
        fn decode<D: Decoder>(d: &mut D) -> Result<MyTag, D::Error> {
            let tag = try!(d.read_u64());
            Ok(MyTag { num: tag, data: try!(Decodable::decode(d)) })
        }
    }
    impl Encodable for MyTag {
        fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
            CborTagEncode {
                tag: self.num,
                data: &self.data,
            }.encode(e)
        }
    }
    fn prop(num: u64, data: Vec<i32>) -> bool {
        round_trip(MyTag { num: num, data: data })
    }
    QuickCheck::new().quickcheck(prop as fn(u64, Vec<i32>) -> bool)
}
<|endoftext|>


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

//! NbetStream module.
//! This is a Non-blocking file descriptor stream designed to be used with
//! Linux epoll in EdgeTriggered mode.

use std::{mem, ptr};
use std::result::Result;
use std::net::TcpStream;
use std::os::unix::io::{RawFd, AsRawFd};

use super::libc;
use super::errno::errno;
use super::libc::consts::os::posix88;
use super::libc::{size_t, c_void, c_int, ssize_t};
use super::readbuffer::ReadBuffer;

use self::util::*;

pub mod util;

extern "C" {
    fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t;
    fn write(fd: c_int, buffer: *const c_void, cout: size_t) -> ssize_t;
}

/// Represents the result of trying to create a new NbetStream
pub type CreateResult = Result<NbetStream, FnctlError>;

/// Represents the result of attempting a read on the underlying file descriptor
pub type ReadResult = Result<(), ReadError>;

/// Represents the result attempting a write on the underlying fild descriptor
pub type WriteResult = Result<u16, WriteError>;

/// States the current stream can be in
#[derive(PartialEq, Clone)]
enum ReadState {
    /// Currently reading the payload length
    PayloadLen,
    /// Currently reading the payload
    Payload
}

/// Struct representing a simple messaging protocol over Tcp sockets
pub struct NbetStream {
    /// Current state
    state: ReadState,
    /// Underlying std::net::TcpStream
    stream: TcpStream,
    /// Message buffer
    buffer: ReadBuffer
}

impl NbetStream {

    /// Attempts to create a new NbetStream from a TcpStream
    pub fn new(stream: TcpStream) -> CreateResult {
        let fd = stream.as_raw_fd();
        let mut response;
        unsafe {
            response = libc::fcntl(
                fd,
                libc::consts::os::posix01::F_SETFL,
                libc::consts::os::extra::O_NONBLOCK);
        }

        if response < 0 {
            let errno = errno().0 as i32;
            return match errno {
                posix88::EAGAIN     => Err(FnctlError::EAGAIN),
                posix88::EBADF      => Err(FnctlError::EBADF),
                posix88::EDEADLK    => Err(FnctlError::EDEADLK),
                posix88::EFAULT     => Err(FnctlError::EFAULT),
                posix88::EINTR      => Err(FnctlError::EINTR),
                posix88::EINVAL     => Err(FnctlError::EINVAL),
                posix88::EMFILE     => Err(FnctlError::EMFILE),
                posix88::ENOLCK     => Err(FnctlError::ENOLCK),
                posix88::EPERM      => Err(FnctlError::EPERM),
                _ => panic!("Unexpected errno: {}", errno)
            };
        }

        Ok(NbetStream {
            state: ReadState::PayloadLen,
            stream: stream,
            buffer: ReadBuffer::new()
        })
    }

    /// Performs a read on the underlying fd. Places all received messages into
    /// the queue in the ReadBuffer. Reads until EAGAIN is hit.
    pub fn read(&mut self) -> ReadResult {
        // We need to loop until EAGAIN is hit from read_num_bytes.
        // Epoll is set to EdgeTrigged mode, which will let us known when there
        // is data to be read on the file descriptor, but if we do not clear it
        // all in this run we will lose whatever we do not grab.
        loop {
            let count = self.buffer.remaining();
            let result = self.read_num_bytes(count);
            if result.is_err() {
                let err = result.unwrap_err();
                match err {
                    ReadError::EAGAIN => {
                        return Ok(())
                    }
                    _ => return Err(err)
                }
            }

            if self.buffer.remaining() == 0 {
                if self.state == ReadState::PayloadLen {
                    self.buffer.calc_payload_len();
                    let p_len = self.buffer.payload_len();
                    self.buffer.set_capacity(p_len);
                    self.state = ReadState::Payload;
                } else { // Payload completely read
                    self.buffer.reset();
                    self.state = ReadState::PayloadLen;
                }
            }
        }
    }

    /// Attempts to read num bytes from the underlying file descriptor.
    fn read_num_bytes(&mut self, num: u16) -> ReadResult {
        let fd = self.stream.as_raw_fd();

        // Create a buffer, size num
        let mut buffer;
        unsafe {
            buffer = libc::calloc(num as size_t,
                mem::size_of::<u8>() as size_t);
        }

        // Ensure system gave up dynamic memory
        if buffer.is_null() {
            return Err(ReadError::ENOMEM)
        }

        // Attempt to read available data into buffer
        let mut num_read;
        unsafe {
            num_read = read(fd, buffer, num as size_t);
        }

        // Return on error
        if num_read < 0 {
            unsafe { libc::free(buffer); }
            let errno = errno().0 as i32;
            return match errno {
                posix88::ENOMEM         => Err(ReadError::ENOMEM),
                posix88::EBADF          => Err(ReadError::EBADF),
                posix88::EFAULT         => Err(ReadError::EFAULT),
                posix88::EINTR          => Err(ReadError::EINTR),
                posix88::EINVAL         => Err(ReadError::EINVAL),
                posix88::EIO            => Err(ReadError::EIO),
                posix88::EISDIR         => Err(ReadError::EISDIR),

                // These two constants can have the same value on some systems,
                // but different values on others, so we can't use a match
                // clause
                x if x == posix88::EAGAIN || x == posix88::EWOULDBLOCK =>
                    Err(ReadError::EAGAIN),

                _ => panic!("Unexpected errno during read: {}", errno)
            };
        }

        // Check for EOF
        if num_read == 0 {
            unsafe { libc::free(buffer); }
            return Err(ReadError::EOF);
        }

        // Add bytes to msg buffer
        for x in 0..num_read as isize {
            unsafe {
                self.buffer.push(ptr::read(buffer.offset(x)) as u8);
            }
        }

        // Free buffer and return Ok
        unsafe { libc::free(buffer); }
        Ok(())
    }

    /// Attempts to write the buffer to the underlying file descriptor
    pub fn write(&mut self, buffer: &Vec<u8>) -> WriteResult {
        let mut plen_buf = [0u8; 2];
        plen_buf[0] = (buffer.len() as u16 & 0b1111_1111u16 << 8) as u8;
        plen_buf[1] = (buffer.len() as u16 & 0b1111_1111u16) as u8;

        let mut n_buffer = Vec::<u8>::with_capacity(buffer.len() + 2);
        n_buffer.push(plen_buf[0]);
        n_buffer.push(plen_buf[1]);

        for x in 0..buffer.len() {
            n_buffer.push(buffer[x]);
        }

        self.write_bytes(&mut n_buffer)
    }

    /// Attempts to write the passed buffer to the underlying file descriptor
    fn write_bytes(&mut self, buffer: &mut Vec<u8>) -> WriteResult {
        let fd = self.stream.as_raw_fd();

        let mut num_written;
        unsafe {
            let buf_slc = &buffer[..];
            let buf_ptr = buf_slc.as_ptr();
            let v_ptr: *const c_void = mem::transmute(buf_ptr);
            num_written = write(fd,
                v_ptr,
                buffer.len() as size_t);
        }

        if num_written < 0 {
            let errno = errno().0 as i32;
            return match errno {
                posix88::EBADF          => Err(WriteError::EBADF),
                posix88::EDESTADDRREQ   => Err(WriteError::EDESTADDRREQ),
                posix88::EDQUOT         => Err(WriteError::EDQUOT),
                posix88::EFAULT         => Err(WriteError::EFAULT),
                posix88::EFBIG          => Err(WriteError::EFBIG),
                posix88::EINTR          => Err(WriteError::EINTR),
                posix88::EINVAL         => Err(WriteError::EINVAL),
                posix88::EIO            => Err(WriteError::EIO),
                posix88::ENOSPC         => Err(WriteError::ENOSPC),
                posix88::EPIPE          => Err(WriteError::EPIPE),

                // These two constants can have the same value on some systems,
                // but different values on others, so we can't use a match
                // clause
                x if x == posix88::EAGAIN || x == posix88::EWOULDBLOCK =>
                    Err(WriteError::EAGAIN),

                _ => panic!("Unknown errno during write: {}", errno),
            }
        }

        Ok(num_written as u16)
    }

    /// Returns the underlying file descriptor
    pub fn raw_fd(&self) -> RawFd {
        self.stream.as_raw_fd()
    }

    /// Returns a mutable reference to the internal ReadBuffer
    pub fn buffer_as_mut(&mut self) -> &mut ReadBuffer {
        &mut self.buffer
    }
}

impl Clone for NbetStream {
    fn clone(&self) -> NbetStream {
        NbetStream {
            state: self.state.clone(),
            stream: self.stream.try_clone().unwrap(),
            buffer: self.buffer.clone()
        }
    }
}
<commit_msg>Debugging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

//! NbetStream module.
//! This is a Non-blocking file descriptor stream designed to be used with
//! Linux epoll in EdgeTriggered mode.

use std::{mem, ptr};
use std::result::Result;
use std::net::TcpStream;
use std::os::unix::io::{RawFd, AsRawFd};

use super::libc;
use super::errno::errno;
use super::libc::consts::os::posix88;
use super::libc::{size_t, c_void, c_int, ssize_t};
use super::readbuffer::ReadBuffer;

use self::util::*;

pub mod util;

extern "C" {
    fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t;
    fn write(fd: c_int, buffer: *const c_void, cout: size_t) -> ssize_t;
}

/// Represents the result of trying to create a new NbetStream
pub type CreateResult = Result<NbetStream, FnctlError>;

/// Represents the result of attempting a read on the underlying file descriptor
pub type ReadResult = Result<(), ReadError>;

/// Represents the result attempting a write on the underlying fild descriptor
pub type WriteResult = Result<u16, WriteError>;

/// States the current stream can be in
#[derive(PartialEq, Clone)]
enum ReadState {
    /// Currently reading the payload length
    PayloadLen,
    /// Currently reading the payload
    Payload
}

/// Struct representing a simple messaging protocol over Tcp sockets
pub struct NbetStream {
    /// Current state
    state: ReadState,
    /// Underlying std::net::TcpStream
    stream: TcpStream,
    /// Message buffer
    buffer: ReadBuffer
}

impl NbetStream {

    /// Attempts to create a new NbetStream from a TcpStream
    pub fn new(stream: TcpStream) -> CreateResult {
        let fd = stream.as_raw_fd();
        let mut response;
        unsafe {
            response = libc::fcntl(
                fd,
                libc::consts::os::posix01::F_SETFL,
                libc::consts::os::extra::O_NONBLOCK);
        }

        if response < 0 {
            let errno = errno().0 as i32;
            return match errno {
                posix88::EAGAIN     => Err(FnctlError::EAGAIN),
                posix88::EBADF      => Err(FnctlError::EBADF),
                posix88::EDEADLK    => Err(FnctlError::EDEADLK),
                posix88::EFAULT     => Err(FnctlError::EFAULT),
                posix88::EINTR      => Err(FnctlError::EINTR),
                posix88::EINVAL     => Err(FnctlError::EINVAL),
                posix88::EMFILE     => Err(FnctlError::EMFILE),
                posix88::ENOLCK     => Err(FnctlError::ENOLCK),
                posix88::EPERM      => Err(FnctlError::EPERM),
                _ => panic!("Unexpected errno: {}", errno)
            };
        }

        Ok(NbetStream {
            state: ReadState::PayloadLen,
            stream: stream,
            buffer: ReadBuffer::new()
        })
    }

    /// Performs a read on the underlying fd. Places all received messages into
    /// the queue in the ReadBuffer. Reads until EAGAIN is hit.
    pub fn read(&mut self) -> ReadResult {
        // We need to loop until EAGAIN is hit from read_num_bytes.
        // Epoll is set to EdgeTrigged mode, which will let us known when there
        // is data to be read on the file descriptor, but if we do not clear it
        // all in this run we will lose whatever we do not grab.
        loop {
            let count = self.buffer.remaining();
            let result = self.read_num_bytes(count);
            if result.is_err() {
                let err = result.unwrap_err();
                match err {
                    ReadError::EAGAIN => {
                        return Ok(())
                    }
                    _ => return Err(err)
                }
            }

            if self.buffer.remaining() == 0 {

                println!("buffer.remaining == 0");

                if self.state == ReadState::PayloadLen {
                    println!("state was PayloadLen");

                    self.buffer.calc_payload_len();
                    let p_len = self.buffer.payload_len();
                    self.buffer.set_capacity(p_len);
                    self.state = ReadState::Payload;
                } else { // Payload completely read
                    println!("state was payload");
                    self.buffer.reset();
                    self.state = ReadState::PayloadLen;
                }
            }
        }
    }

    /// Attempts to read num bytes from the underlying file descriptor.
    fn read_num_bytes(&mut self, num: u16) -> ReadResult {
        let fd = self.stream.as_raw_fd();

        // Create a buffer, size num
        let mut buffer;
        unsafe {
            buffer = libc::calloc(num as size_t,
                mem::size_of::<u8>() as size_t);
        }

        // Ensure system gave up dynamic memory
        if buffer.is_null() {
            return Err(ReadError::ENOMEM)
        }

        // Attempt to read available data into buffer
        let mut num_read;
        unsafe {
            num_read = read(fd, buffer, num as size_t);
        }

        println!("read_num_bytes.num_read: {}", num_read);

        // Return on error
        if num_read < 0 {
            unsafe { libc::free(buffer); }
            let errno = errno().0 as i32;
            return match errno {
                posix88::ENOMEM         => Err(ReadError::ENOMEM),
                posix88::EBADF          => Err(ReadError::EBADF),
                posix88::EFAULT         => Err(ReadError::EFAULT),
                posix88::EINTR          => Err(ReadError::EINTR),
                posix88::EINVAL         => Err(ReadError::EINVAL),
                posix88::EIO            => Err(ReadError::EIO),
                posix88::EISDIR         => Err(ReadError::EISDIR),

                // These two constants can have the same value on some systems,
                // but different values on others, so we can't use a match
                // clause
                x if x == posix88::EAGAIN || x == posix88::EWOULDBLOCK =>
                    Err(ReadError::EAGAIN),

                _ => panic!("Unexpected errno during read: {}", errno)
            };
        }

        // Check for EOF
        if num_read == 0 {
            unsafe { libc::free(buffer); }
            return Err(ReadError::EOF);
        }

        // Add bytes to msg buffer
        for x in 0..num_read as isize {
            unsafe {
                self.buffer.push(ptr::read(buffer.offset(x)) as u8);
            }
        }

        // Free buffer and return Ok
        unsafe { libc::free(buffer); }
        Ok(())
    }

    /// Attempts to write the buffer to the underlying file descriptor
    pub fn write(&mut self, buffer: &Vec<u8>) -> WriteResult {
        let mut plen_buf = [0u8; 2];
        plen_buf[0] = (buffer.len() as u16 & 0b1111_1111u16 << 8) as u8;
        plen_buf[1] = (buffer.len() as u16 & 0b1111_1111u16) as u8;

        let mut n_buffer = Vec::<u8>::with_capacity(buffer.len() + 2);
        n_buffer.push(plen_buf[0]);
        n_buffer.push(plen_buf[1]);

        for x in 0..buffer.len() {
            n_buffer.push(buffer[x]);
        }

        self.write_bytes(&mut n_buffer)
    }

    /// Attempts to write the passed buffer to the underlying file descriptor
    fn write_bytes(&mut self, buffer: &mut Vec<u8>) -> WriteResult {
        let fd = self.stream.as_raw_fd();

        let mut num_written;
        unsafe {
            let buf_slc = &buffer[..];
            let buf_ptr = buf_slc.as_ptr();
            let v_ptr: *const c_void = mem::transmute(buf_ptr);
            num_written = write(fd,
                v_ptr,
                buffer.len() as size_t);
        }

        if num_written < 0 {
            let errno = errno().0 as i32;
            return match errno {
                posix88::EBADF          => Err(WriteError::EBADF),
                posix88::EDESTADDRREQ   => Err(WriteError::EDESTADDRREQ),
                posix88::EDQUOT         => Err(WriteError::EDQUOT),
                posix88::EFAULT         => Err(WriteError::EFAULT),
                posix88::EFBIG          => Err(WriteError::EFBIG),
                posix88::EINTR          => Err(WriteError::EINTR),
                posix88::EINVAL         => Err(WriteError::EINVAL),
                posix88::EIO            => Err(WriteError::EIO),
                posix88::ENOSPC         => Err(WriteError::ENOSPC),
                posix88::EPIPE          => Err(WriteError::EPIPE),

                // These two constants can have the same value on some systems,
                // but different values on others, so we can't use a match
                // clause
                x if x == posix88::EAGAIN || x == posix88::EWOULDBLOCK =>
                    Err(WriteError::EAGAIN),

                _ => panic!("Unknown errno during write: {}", errno),
            }
        }

        Ok(num_written as u16)
    }

    /// Returns the underlying file descriptor
    pub fn raw_fd(&self) -> RawFd {
        self.stream.as_raw_fd()
    }

    /// Returns a mutable reference to the internal ReadBuffer
    pub fn buffer_as_mut(&mut self) -> &mut ReadBuffer {
        &mut self.buffer
    }
}

impl Clone for NbetStream {
    fn clone(&self) -> NbetStream {
        NbetStream {
            state: self.state.clone(),
            stream: self.stream.try_clone().unwrap(),
            buffer: self.buffer.clone()
        }
    }
}
<|endoftext|>


<commit_before>use super::asset::Asset;
use super::animation_data::AnimationData;

use glm;
use moho::frame_animator::FrameAnimator;
use moho::tile_sheet::TileSheet;

use std::time::Duration;

#[derive(Clone)]
pub struct Animation {
    pub asset: Asset,
    sheet: TileSheet,
    animator: FrameAnimator,
}

impl Animation {
    pub fn from_data(data: AnimationData, center: glm::IVec2, scale: glm::DVec2) -> Animation {
        let scale = glm::dvec2(1. / data.animator.num_frames() as f64, 1.) * scale;
        let asset = Asset::scaled_texture(&data.texture, center, scale);
        Self::new(asset, data.sheet.clone(), data.animator)
    }

    pub fn new(asset: Asset, sheet: TileSheet, animator: FrameAnimator) -> Self {
        Animation {
            asset: asset,
            sheet: sheet,
            animator: animator,
        }
    }

    pub fn update(&mut self, delta: Duration) {
        if self.is_active() {
            self.animator.animate(delta);
        } else {
            self.animator.start();
        }
        if let Some(frame) = self.animator.frame() {
            let src_rect = self.sheet.uv(frame);
            self.asset.src_rect = Some(src_rect);
        }
    }

    pub fn is_active(&self) -> bool {
        self.animator.frame().is_some()
    }
}
<commit_msg>added active flag to animation<commit_after>use super::asset::Asset;
use super::animation_data::AnimationData;

use glm;
use moho::frame_animator::FrameAnimator;
use moho::tile_sheet::TileSheet;

use std::time::Duration;

#[derive(Clone)]
pub struct Animation {
    pub asset: Asset,
    sheet: TileSheet,
    animator: FrameAnimator,
    active: bool,
}

impl Animation {
    pub fn from_data(data: AnimationData, center: glm::IVec2, scale: glm::DVec2) -> Animation {
        let scale = glm::dvec2(1. / data.animator.num_frames() as f64, 1.) * scale;
        let asset = Asset::scaled_texture(&data.texture, center, scale);
        Self::new(asset, data.sheet.clone(), data.animator)
    }

    pub fn new(asset: Asset, sheet: TileSheet, animator: FrameAnimator) -> Self {
        Animation {
            asset: asset,
            sheet: sheet,
            animator: animator,
            active: true,
        }
    }

    pub fn update(&mut self, delta: Duration) {
        if self.is_active() {
            self.animator.animate(delta);
        } else if self.active {
            self.animator.start();
        }
        if let Some(frame) = self.animator.frame() {
            let src_rect = self.sheet.uv(frame);
            self.asset.src_rect = Some(src_rect);
        } else {
            self.active = false;
        }
    }

    pub fn is_active(&self) -> bool {
        self.active && self.animator.frame().is_some()
    }
}
<|endoftext|>


<commit_before>use PT_FIRSTMACH;

pub type c_long = i64;
pub type c_ulong = u64;
pub type c_char = i8;
pub type c___greg_t = u64;
pub type __cpu_simple_lock_nv_t = ::c_uchar;

s! {
    #[repr(align(16))]
    pub struct mcontext_t {
        pub __gregs: [c___greg_t; 26],
        pub _mc_tlsbase: c___greg_t,
        pub __fpregs: [[::c_char;32]; 16],
    }

    pub struct ucontext_t {
        pub uc_flags: ::c_uint,
        pub uc_link: *mut ::ucontext_t,
        pub uc_sigmask: ::sigset_t,
        pub uc_stack: ::stack_t,
        pub uc_mcontext: ::mcontext_t,
    }
}

// should be pub(crate), but that requires Rust 1.18.0
cfg_if! {
    if #[cfg(libc_const_size_of)] {
        #[doc(hidden)]
        pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1;
    } else {
        #[doc(hidden)]
        pub const _ALIGNBYTES: usize = 8 - 1;
    }
}

pub const PT_STEP: ::c_int = PT_FIRSTMACH + 0;
pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 1;
pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 2;
pub const PT_GETFPREGS: ::c_int = PT_FIRSTMACH + 3;
pub const PT_SETFPREGS: ::c_int = PT_FIRSTMACH + 4;
<commit_msg>remove alignment for older rust releases<commit_after>use PT_FIRSTMACH;

pub type c_long = i64;
pub type c_ulong = u64;
pub type c_char = i8;
pub type c___greg_t = u64;
pub type __cpu_simple_lock_nv_t = ::c_uchar;

s! {
    pub struct mcontext_t {
        pub __gregs: [c___greg_t; 26],
        pub _mc_tlsbase: c___greg_t,
        pub __fpregs: [[::c_char;32]; 16],
    }

    pub struct ucontext_t {
        pub uc_flags: ::c_uint,
        pub uc_link: *mut ::ucontext_t,
        pub uc_sigmask: ::sigset_t,
        pub uc_stack: ::stack_t,
        pub uc_mcontext: ::mcontext_t,
    }
}

// should be pub(crate), but that requires Rust 1.18.0
cfg_if! {
    if #[cfg(libc_const_size_of)] {
        #[doc(hidden)]
        pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1;
    } else {
        #[doc(hidden)]
        pub const _ALIGNBYTES: usize = 8 - 1;
    }
}

pub const PT_STEP: ::c_int = PT_FIRSTMACH + 0;
pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 1;
pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 2;
pub const PT_GETFPREGS: ::c_int = PT_FIRSTMACH + 3;
pub const PT_SETFPREGS: ::c_int = PT_FIRSTMACH + 4;
<|endoftext|>


<commit_before>use crate::runtime::task::RawTask;

use std::fmt;
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};

doc_rt_core! {
    /// An owned permission to join on a task (await its termination).
    ///
    /// This can be thought of as the equivalent of [`std::thread::JoinHandle`] for
    /// a task rather than a thread.
    ///
    /// A `JoinHandle` *detaches* the associated task when it is dropped, which
    /// means that there is no longer any handle to the task, and no way to `join`
    /// on it.
    ///
    /// This `struct` is created by the [`task::spawn`] and [`task::spawn_blocking`]
    /// functions.
    ///
    /// # Examples
    ///
    /// Creation from [`task::spawn`]:
    ///
    /// ```
    /// use tokio::task;
    ///
    /// # async fn doc() {
    /// let join_handle: task::JoinHandle<_> = task::spawn(async {
    ///     // some work here
    /// });
    /// # }
    /// ```
    ///
    /// Creation from [`task::spawn_blocking`]:
    ///
    /// ```
    /// use tokio::task;
    ///
    /// # async fn doc() {
    /// let join_handle: task::JoinHandle<_> = task::spawn_blocking(|| {
    ///     // some blocking work here
    /// });
    /// # }
    /// ```
    ///
    /// Child being detached and outliving its parent:
    ///
    /// ```no_run
    /// use tokio::task;
    /// use tokio::time;
    /// use std::time::Duration;
    ///
    /// # #[tokio::main] async fn main() {
    /// let original_task = task::spawn(async {
    ///     let _detached_task = task::spawn(async {
    ///         // Here we sleep to make sure that the first task returns before.
    ///         time::delay_for(Duration::from_millis(10)).await;
    ///         // This will be called, even though the JoinHandle is dropped.
    ///         println!("♫ Still alive ♫");
    ///     });
    /// });
    ///
    /// original_task.await.expect("The task being joined has panicked");
    /// println!("Original task is joined.");
    ///
    /// // We make sure that the new task has time to run, before the main
    /// // task returns.
    ///
    /// time::delay_for(Duration::from_millis(1000)).await;
    /// # }
    /// ```
    ///
    /// [`task::spawn`]: crate::task::spawn()
    /// [`task::spawn_blocking`]: crate::task::spawn_blocking
    /// [`std::thread::JoinHandle`]: std::thread::JoinHandle
    pub struct JoinHandle<T> {
        raw: Option<RawTask>,
        _p: PhantomData<T>,
    }
}

unsafe impl<T: Send> Send for JoinHandle<T> {}
unsafe impl<T: Send> Sync for JoinHandle<T> {}

impl<T> JoinHandle<T> {
    pub(super) fn new(raw: RawTask) -> JoinHandle<T> {
        JoinHandle {
            raw: Some(raw),
            _p: PhantomData,
        }
    }
}

impl<T> Unpin for JoinHandle<T> {}

impl<T> Future for JoinHandle<T> {
    type Output = super::Result<T>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut ret = Poll::Pending;

        // Keep track of task budget
        let coop = ready!(crate::coop::poll_proceed(cx));

        // Raw should always be set. If it is not, this is due to polling after
        // completion
        let raw = self
            .raw
            .as_ref()
            .expect("polling after `JoinHandle` already completed");

        // Try to read the task output. If the task is not yet complete, the
        // waker is stored and is notified once the task does complete.
        //
        // The function must go via the vtable, which requires erasing generic
        // types. To do this, the function "return" is placed on the stack
        // **before** calling the function and is passed into the function using
        // `*mut ()`.
        //
        // Safety:
        //
        // The type of `T` must match the task's output type.
        unsafe {
            raw.try_read_output(&mut ret as *mut _ as *mut (), cx.waker());
        }

        if ret.is_ready() {
            coop.made_progress();
        }

        ret
    }
}

impl<T> Drop for JoinHandle<T> {
    fn drop(&mut self) {
        if let Some(raw) = self.raw.take() {
            if raw.header().state.drop_join_handle_fast().is_ok() {
                return;
            }

            raw.drop_join_handle_slow();
        }
    }
}

impl<T> fmt::Debug for JoinHandle<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("JoinHandle").finish()
    }
}
<commit_msg>runtime: mention on JoinHandle that the generic parameter is the return type (#2819)<commit_after>use crate::runtime::task::RawTask;

use std::fmt;
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};

doc_rt_core! {
    /// An owned permission to join on a task (await its termination).
    ///
    /// This can be thought of as the equivalent of [`std::thread::JoinHandle`] for
    /// a task rather than a thread.
    ///
    /// A `JoinHandle` *detaches* the associated task when it is dropped, which
    /// means that there is no longer any handle to the task, and no way to `join`
    /// on it.
    ///
    /// This `struct` is created by the [`task::spawn`] and [`task::spawn_blocking`]
    /// functions.
    ///
    /// # Examples
    ///
    /// Creation from [`task::spawn`]:
    ///
    /// ```
    /// use tokio::task;
    ///
    /// # async fn doc() {
    /// let join_handle: task::JoinHandle<_> = task::spawn(async {
    ///     // some work here
    /// });
    /// # }
    /// ```
    ///
    /// Creation from [`task::spawn_blocking`]:
    ///
    /// ```
    /// use tokio::task;
    ///
    /// # async fn doc() {
    /// let join_handle: task::JoinHandle<_> = task::spawn_blocking(|| {
    ///     // some blocking work here
    /// });
    /// # }
    /// ```
    ///
    /// The generic parameter `T` in `JoinHandle<T>` is the return type of the spawned task.
    /// If the return value is an i32, the join handle has type `JoinHandle<i32>`:
    ///
    /// ```
    /// use tokio::task;
    ///
    /// # async fn doc() {
    /// let join_handle: task::JoinHandle<i32> = task::spawn(async {
    ///     5 + 3
    /// });
    /// # }
    ///
    /// ```
    ///
    /// If the task does not have a return value, the join handle has type `JoinHandle<()>`:
    ///
    /// ```
    /// use tokio::task;
    ///
    /// # async fn doc() {
    /// let join_handle: task::JoinHandle<()> = task::spawn(async {
    ///     println!("I return nothing.");
    /// });
    /// # }
    /// ```
    ///
    /// Note that `handle.await` doesn't give you the return type directly. It is wrapped in a
    /// `Result` because panics in the spawned task are caught by Tokio. The `?` operator has
    /// to be double chained to extract the returned value:
    ///
    /// ```
    /// use tokio::task;
    /// use std::io;
    ///
    /// #[tokio::main]
    /// async fn main() -> io::Result<()> {
    ///     let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async {
    ///         Ok(5 + 3)
    ///     });
    ///
    ///     let result = join_handle.await??;
    ///     assert_eq!(result, 8);
    ///     Ok(())
    /// }
    /// ```
    ///
    /// If the task panics, the error is a [`JoinError`] that contains the panic:
    ///
    /// ```
    /// use tokio::task;
    /// use std::io;
    /// use std::panic;
    ///
    /// #[tokio::main]
    /// async fn main() -> io::Result<()> {
    ///     let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async {
    ///         panic!("boom");
    ///     });
    ///
    ///     let err = join_handle.await.unwrap_err();
    ///     assert!(err.is_panic());
    ///     Ok(())
    /// }
    ///
    /// ```
    /// Child being detached and outliving its parent:
    ///
    /// ```no_run
    /// use tokio::task;
    /// use tokio::time;
    /// use std::time::Duration;
    ///
    /// # #[tokio::main] async fn main() {
    /// let original_task = task::spawn(async {
    ///     let _detached_task = task::spawn(async {
    ///         // Here we sleep to make sure that the first task returns before.
    ///         time::delay_for(Duration::from_millis(10)).await;
    ///         // This will be called, even though the JoinHandle is dropped.
    ///         println!("♫ Still alive ♫");
    ///     });
    /// });
    ///
    /// original_task.await.expect("The task being joined has panicked");
    /// println!("Original task is joined.");
    ///
    /// // We make sure that the new task has time to run, before the main
    /// // task returns.
    ///
    /// time::delay_for(Duration::from_millis(1000)).await;
    /// # }
    /// ```
    ///
    /// [`task::spawn`]: crate::task::spawn()
    /// [`task::spawn_blocking`]: crate::task::spawn_blocking
    /// [`std::thread::JoinHandle`]: std::thread::JoinHandle
    /// [`JoinError`]: crate::task::JoinError
    pub struct JoinHandle<T> {
        raw: Option<RawTask>,
        _p: PhantomData<T>,
    }
}

unsafe impl<T: Send> Send for JoinHandle<T> {}
unsafe impl<T: Send> Sync for JoinHandle<T> {}

impl<T> JoinHandle<T> {
    pub(super) fn new(raw: RawTask) -> JoinHandle<T> {
        JoinHandle {
            raw: Some(raw),
            _p: PhantomData,
        }
    }
}

impl<T> Unpin for JoinHandle<T> {}

impl<T> Future for JoinHandle<T> {
    type Output = super::Result<T>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut ret = Poll::Pending;

        // Keep track of task budget
        let coop = ready!(crate::coop::poll_proceed(cx));

        // Raw should always be set. If it is not, this is due to polling after
        // completion
        let raw = self
            .raw
            .as_ref()
            .expect("polling after `JoinHandle` already completed");

        // Try to read the task output. If the task is not yet complete, the
        // waker is stored and is notified once the task does complete.
        //
        // The function must go via the vtable, which requires erasing generic
        // types. To do this, the function "return" is placed on the stack
        // **before** calling the function and is passed into the function using
        // `*mut ()`.
        //
        // Safety:
        //
        // The type of `T` must match the task's output type.
        unsafe {
            raw.try_read_output(&mut ret as *mut _ as *mut (), cx.waker());
        }

        if ret.is_ready() {
            coop.made_progress();
        }

        ret
    }
}

impl<T> Drop for JoinHandle<T> {
    fn drop(&mut self) {
        if let Some(raw) = self.raw.take() {
            if raw.header().state.drop_join_handle_fast().is_ok() {
                return;
            }

            raw.drop_join_handle_slow();
        }
    }
}

impl<T> fmt::Debug for JoinHandle<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("JoinHandle").finish()
    }
}
<|endoftext|>


<commit_before>use super::{EddingtonFinkelstein, Mass};
use diffgeom::coordinates::{ConversionTo, CoordinateSystem, Point};
use diffgeom::metric::MetricSystem;
use diffgeom::tensors::{ContravariantIndex, CovariantIndex, InvTwoForm, Matrix, Tensor, TwoForm};
use std::marker::PhantomData;
use typenum::consts::U4;

pub struct Schwarzschild<M: Mass> {
    _m: PhantomData<M>,
}

impl<M: Mass> CoordinateSystem for Schwarzschild<M> {
    type Dimension = U4;
}

impl<M: Mass> MetricSystem for Schwarzschild<M> {
    fn g(x: &Point<Self>) -> TwoForm<Self> {
        let r = x[1];
        let th = x[2];
        let m = M::mass();
        let coeff = 1.0 - 2.0 * m / r;
        TwoForm::new(
            x.clone(),
            arr![f64;
                coeff, 0.0, 0.0, 0.0,
                0.0, -1.0/coeff, 0.0, 0.0,
                0.0, 0.0, -r*r, 0.0,
                0.0, 0.0, 0.0, -r*r*th.sin()*th.sin()
            ],
        )
    }

    fn inv_g(x: &Point<Self>) -> InvTwoForm<Self> {
        let r = x[1];
        let th = x[2];
        let m = M::mass();
        let coeff = 1.0 - 2.0 * m / r;
        InvTwoForm::new(
            x.clone(),
            arr![f64;
                1.0 / coeff, 0.0, 0.0, 0.0,
                0.0, -coeff, 0.0, 0.0,
                0.0, 0.0, -1.0/(r*r), 0.0,
                0.0, 0.0, 0.0, -1.0/(r*r*th.sin()*th.sin())
            ],
        )
    }

    fn christoffel(
        x: &Point<Self>,
    ) -> Tensor<Self, (ContravariantIndex, (CovariantIndex, CovariantIndex))> {
        let r = x[1];
        let th = x[2];
        let m = M::mass();
        let mr = m / r;
        let r2m = r - 2.0 * m;
        Tensor::<Self, (ContravariantIndex, (CovariantIndex, CovariantIndex))>::new(
            x.clone(),
            arr![f64;
                0.0, mr/r2m, 0.0, 0.0,
                mr/r2m, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0,

                mr*r2m/r/r, 0.0, 0.0, 0.0,
                0.0, -mr/r2m, 0.0, 0.0,
                0.0, 0.0, -r2m, 0.0,
                0.0, 0.0, 0.0, -r2m*th.sin()*th.sin(),

                0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 1.0/r, 0.0,
                0.0, 1.0/r, 0.0, 0.0,
                0.0, 0.0, 0.0, -th.sin()*th.cos(),

                0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 1.0/r,
                0.0, 0.0, 0.0, th.cos()/th.sin(),
                0.0, 1.0/r, th.cos()/th.sin(), 0.0
            ],
        )
    }

    // TODO
    //fn dg(x: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>
    //fn covariant_christoffel(x: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>
}

// Conversions

impl<M: Mass + 'static> ConversionTo<EddingtonFinkelstein<M>> for Schwarzschild<M> {
    fn convert_point(p: &Point<Self>) -> Point<EddingtonFinkelstein<M>> {
        let t = p[0];
        let r = p[1];
        let m = M::mass();
        let u = t + r + (0.5 * (r - 2.0 * m) / m).ln() * 2.0 * m;
        Point::new(arr![f64; u, r, p[2], p[3]])
    }

    fn jacobian(p: &Point<Self>) -> Matrix<EddingtonFinkelstein<M>> {
        let r = p[1];
        let m = M::mass();
        let dudr = r / (r - 2.0 * m);
        Matrix::new(
            Self::convert_point(p),
            arr![f64;
                1.0, dudr, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                0.0, 0.0, 0.0, 1.0,
            ],
        )
    }

    fn inv_jacobian(
        p: &Point<Self>,
    ) -> Tensor<EddingtonFinkelstein<M>, (CovariantIndex, ContravariantIndex)> {
        let r = p[1];
        let m = M::mass();
        let dudr = r / (r - 2.0 * m);
        Tensor::<EddingtonFinkelstein<M>, (CovariantIndex, ContravariantIndex)>::new(
            Self::convert_point(p),
            arr![f64;
                1.0, -dudr, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                0.0, 0.0, 0.0, 1.0,
            ],
        )
    }
}
<commit_msg>coords/schw: conversions from Schwarzschild to near-pole coords<commit_after>use super::{EddingtonFinkelstein, Mass, NearPole0Schw, NearPolePiSchw};
use diffgeom::coordinates::{ConversionTo, CoordinateSystem, Point};
use diffgeom::metric::MetricSystem;
use diffgeom::tensors::{ContravariantIndex, CovariantIndex, InvTwoForm, Matrix, Tensor, TwoForm};
use std::f64::consts::PI;
use std::marker::PhantomData;
use typenum::consts::U4;

pub struct Schwarzschild<M: Mass> {
    _m: PhantomData<M>,
}

impl<M: Mass> CoordinateSystem for Schwarzschild<M> {
    type Dimension = U4;
}

impl<M: Mass> MetricSystem for Schwarzschild<M> {
    fn g(x: &Point<Self>) -> TwoForm<Self> {
        let r = x[1];
        let th = x[2];
        let m = M::mass();
        let coeff = 1.0 - 2.0 * m / r;
        TwoForm::new(
            x.clone(),
            arr![f64;
                coeff, 0.0, 0.0, 0.0,
                0.0, -1.0/coeff, 0.0, 0.0,
                0.0, 0.0, -r*r, 0.0,
                0.0, 0.0, 0.0, -r*r*th.sin()*th.sin()
            ],
        )
    }

    fn inv_g(x: &Point<Self>) -> InvTwoForm<Self> {
        let r = x[1];
        let th = x[2];
        let m = M::mass();
        let coeff = 1.0 - 2.0 * m / r;
        InvTwoForm::new(
            x.clone(),
            arr![f64;
                1.0 / coeff, 0.0, 0.0, 0.0,
                0.0, -coeff, 0.0, 0.0,
                0.0, 0.0, -1.0/(r*r), 0.0,
                0.0, 0.0, 0.0, -1.0/(r*r*th.sin()*th.sin())
            ],
        )
    }

    fn christoffel(
        x: &Point<Self>,
    ) -> Tensor<Self, (ContravariantIndex, (CovariantIndex, CovariantIndex))> {
        let r = x[1];
        let th = x[2];
        let m = M::mass();
        let mr = m / r;
        let r2m = r - 2.0 * m;
        Tensor::<Self, (ContravariantIndex, (CovariantIndex, CovariantIndex))>::new(
            x.clone(),
            arr![f64;
                0.0, mr/r2m, 0.0, 0.0,
                mr/r2m, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0,

                mr*r2m/r/r, 0.0, 0.0, 0.0,
                0.0, -mr/r2m, 0.0, 0.0,
                0.0, 0.0, -r2m, 0.0,
                0.0, 0.0, 0.0, -r2m*th.sin()*th.sin(),

                0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 1.0/r, 0.0,
                0.0, 1.0/r, 0.0, 0.0,
                0.0, 0.0, 0.0, -th.sin()*th.cos(),

                0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 1.0/r,
                0.0, 0.0, 0.0, th.cos()/th.sin(),
                0.0, 1.0/r, th.cos()/th.sin(), 0.0
            ],
        )
    }

    // TODO
    //fn dg(x: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>
    //fn covariant_christoffel(x: &Point<Self>) -> Tensor<Self, (CovariantIndex, (CovariantIndex, CovariantIndex))>
}

// Conversions

impl<M: Mass + 'static> ConversionTo<EddingtonFinkelstein<M>> for Schwarzschild<M> {
    fn convert_point(p: &Point<Self>) -> Point<EddingtonFinkelstein<M>> {
        let t = p[0];
        let r = p[1];
        let m = M::mass();
        let u = t + r + (0.5 * (r - 2.0 * m) / m).ln() * 2.0 * m;
        Point::new(arr![f64; u, r, p[2], p[3]])
    }

    fn jacobian(p: &Point<Self>) -> Matrix<EddingtonFinkelstein<M>> {
        let r = p[1];
        let m = M::mass();
        let dudr = r / (r - 2.0 * m);
        Matrix::new(
            Self::convert_point(p),
            arr![f64;
                1.0, dudr, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                0.0, 0.0, 0.0, 1.0,
            ],
        )
    }

    fn inv_jacobian(
        p: &Point<Self>,
    ) -> Tensor<EddingtonFinkelstein<M>, (CovariantIndex, ContravariantIndex)> {
        let r = p[1];
        let m = M::mass();
        let dudr = r / (r - 2.0 * m);
        Tensor::<EddingtonFinkelstein<M>, (CovariantIndex, ContravariantIndex)>::new(
            Self::convert_point(p),
            arr![f64;
                1.0, -dudr, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                0.0, 0.0, 0.0, 1.0,
            ],
        )
    }
}

impl<M: Mass + 'static> ConversionTo<NearPole0Schw<M>> for Schwarzschild<M> {
    fn convert_point(p: &Point<Self>) -> Point<NearPole0Schw<M>> {
        let th = p[2];
        let ph = p[3];
        let x = (th / 2.0).tan() * ph.cos();
        let y = (th / 2.0).tan() * ph.sin();
        Point::new(arr![f64; p[0], p[1], x, y])
    }

    fn jacobian(p: &Point<Self>) -> Matrix<NearPole0Schw<M>> {
        let t2 = p[2] / 2.0;
        let ph = p[3];
        let tan2th1 = 1.0 + t2.tan() * t2.tan();
        Matrix::new(
            Self::convert_point(p),
            arr![f64;
                1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 2.0 * ph.cos() / tan2th1, 2.0 * ph.sin() / tan2th1,
                0.0, 0.0, -ph.sin() / t2.tan(), ph.cos() / t2.tan(),
            ],
        )
    }

    fn inv_jacobian(
        p: &Point<Self>,
    ) -> Tensor<NearPole0Schw<M>, (CovariantIndex, ContravariantIndex)> {
        let t2 = p[2] / 2.0;
        let ph = p[3];
        let cos2t2 = t2.cos() * t2.cos();
        Tensor::<NearPole0Schw<M>, (CovariantIndex, ContravariantIndex)>::new(
            Self::convert_point(p),
            arr![f64;
                1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 0.5 * ph.cos() / cos2t2, -t2.tan() * ph.sin(),
                0.0, 0.0, 0.5 * ph.sin() / cos2t2, t2.tan() * ph.cos(),
            ],
        )
    }
}

impl<M: Mass + 'static> ConversionTo<NearPolePiSchw<M>> for Schwarzschild<M> {
    fn convert_point(p: &Point<Self>) -> Point<NearPolePiSchw<M>> {
        let th = p[2];
        let ph = p[3];
        let x = ((PI - th) / 2.0).tan() * ph.cos();
        let y = ((PI - th) / 2.0).tan() * ph.sin();
        Point::new(arr![f64; p[0], p[1], x, y])
    }

    fn jacobian(p: &Point<Self>) -> Matrix<NearPolePiSchw<M>> {
        let t2 = p[2] / 2.0;
        let ph = p[3];
        let tan2th1 = 1.0 + t2.tan() * t2.tan();
        Matrix::new(
            Self::convert_point(p),
            arr![f64;
                1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, -2.0 * ph.cos() / tan2th1, -2.0 * ph.sin() / tan2th1,
                0.0, 0.0, -ph.sin() / t2.tan(), ph.cos() / t2.tan(),
            ],
        )
    }

    fn inv_jacobian(
        p: &Point<Self>,
    ) -> Tensor<NearPolePiSchw<M>, (CovariantIndex, ContravariantIndex)> {
        let t2 = p[2] / 2.0;
        let ph = p[3];
        let cos2t2 = t2.cos() * t2.cos();
        Tensor::<NearPolePiSchw<M>, (CovariantIndex, ContravariantIndex)>::new(
            Self::convert_point(p),
            arr![f64;
                1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, -0.5 * ph.cos() / cos2t2, -t2.tan() * ph.sin(),
                0.0, 0.0, -0.5 * ph.sin() / cos2t2, t2.tan() * ph.cos(),
            ],
        )
    }
}
<|endoftext|>


<commit_before>use std::io::net::ip::{Ipv4Addr, SocketAddr};

mod libtorresmo {
    extern crate time;

    use std::io::net::udp::UdpSocket;
    use std::io::net::ip::SocketAddr;
    use std::io::IoResult;
    use std::mem::{to_be32, to_be16, transmute};
    use std::rand::random;

    #[allow(dead_code,non_camel_case_types)]
    enum UtpPacketType {
        ST_DATA  = 0,
        ST_FIN   = 1,
        ST_STATE = 2,
        ST_RESET = 3,
        ST_SYN   = 4,
    }

    #[allow(dead_code)]
    struct UtpPacketHeader {
        type_ver: u8, // type: u4, ver: u4
        extension: u8,
        connection_id: u16,
        timestamp_microseconds: u32,
        timestamp_difference_microseconds: u32,
        wnd_size: u32,
        seq_nr: u16,
        ack_nr: u16,
    }

    impl UtpPacketHeader {
        fn bytes(&self) -> &[u8] {
            unsafe {
                let buf: &[u8, ..20] = transmute(self);
                return buf.as_slice();
            }
        }

        fn len(&self) -> uint {
            let header_size = 20;
            return header_size;
        }
    }

    #[allow(dead_code)]
    struct UtpPacket {
        header: UtpPacketHeader,
        payload: Vec<u8>,
    }

    impl UtpPacket {
        /// Constructs a new, empty UtpPacket.
        fn new() -> UtpPacket {
            UtpPacket {
                header: UtpPacketHeader {
                    type_ver: ST_DATA as u8 << 4 | 1,
                    extension: 0,
                    connection_id: 0,
                    timestamp_microseconds: 0,
                    timestamp_difference_microseconds: 0,
                    wnd_size: 0,
                    seq_nr: 0,
                    ack_nr: 0,
                },
                payload: Vec::new(),
            }
        }

        fn bytes(&self) -> Vec<u8> {
            let mut buf: Vec<u8> = Vec::with_capacity(self.len());
            buf.push_all(self.header.bytes());
            buf.push_all(self.payload.as_slice());
            return buf;
        }

        fn len(&self) -> uint {
            self.header.len() + self.payload.len()
        }
    }

    pub struct UtpSocket {
        skt: UdpSocket,
        seq_nr: u16,
    }

    impl UtpSocket {
        pub fn bind(addr: SocketAddr) -> IoResult<UtpSocket> {
            let skt = UdpSocket::bind(addr);
            match skt {
                Ok(x)  => Ok(UtpSocket { skt: x, seq_nr: 1 }),
                Err(e) => Err(e)
            }
        }

        pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
            let mut packet = UtpPacket::new();
            packet.payload = Vec::from_slice(buf);
            packet.header.seq_nr = to_be16(self.seq_nr);
            packet.header.connection_id = to_be16(random());
            let t = time::get_time();
            packet.header.timestamp_microseconds = to_be32((t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32);

            // Send packet
            let result = self.skt.sendto(packet.bytes().as_slice(), dst);

            self.seq_nr += 1;
            result
        }

        pub fn recvfrom(&mut self, buf: &mut[u8]) -> IoResult<(uint,SocketAddr)> {
            self.skt.recvfrom(buf)
        }
    }
}

fn main() {
    let mut buf = [0, ..512];
    let mut sock = libtorresmo::UtpSocket::bind(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 }).unwrap();

    loop {
        match sock.recvfrom(buf) {
            Ok((_, src)) => {
                let payload = String::from_str("Hello\n").into_bytes();

                // Send uTP packet
                let _ = sock.sendto(payload.as_slice(), src);
            }
            Err(_) => {}
        }
    }
    drop(sock);
}
<commit_msg>Rename field.<commit_after>use std::io::net::ip::{Ipv4Addr, SocketAddr};

mod libtorresmo {
    extern crate time;

    use std::io::net::udp::UdpSocket;
    use std::io::net::ip::SocketAddr;
    use std::io::IoResult;
    use std::mem::{to_be32, to_be16, transmute};
    use std::rand::random;

    #[allow(dead_code,non_camel_case_types)]
    enum UtpPacketType {
        ST_DATA  = 0,
        ST_FIN   = 1,
        ST_STATE = 2,
        ST_RESET = 3,
        ST_SYN   = 4,
    }

    #[allow(dead_code)]
    struct UtpPacketHeader {
        type_ver: u8, // type: u4, ver: u4
        extension: u8,
        connection_id: u16,
        timestamp_microseconds: u32,
        timestamp_difference_microseconds: u32,
        wnd_size: u32,
        seq_nr: u16,
        ack_nr: u16,
    }

    impl UtpPacketHeader {
        fn bytes(&self) -> &[u8] {
            unsafe {
                let buf: &[u8, ..20] = transmute(self);
                return buf.as_slice();
            }
        }

        fn len(&self) -> uint {
            let header_size = 20;
            return header_size;
        }
    }

    #[allow(dead_code)]
    struct UtpPacket {
        header: UtpPacketHeader,
        payload: Vec<u8>,
    }

    impl UtpPacket {
        /// Constructs a new, empty UtpPacket.
        fn new() -> UtpPacket {
            UtpPacket {
                header: UtpPacketHeader {
                    type_ver: ST_DATA as u8 << 4 | 1,
                    extension: 0,
                    connection_id: 0,
                    timestamp_microseconds: 0,
                    timestamp_difference_microseconds: 0,
                    wnd_size: 0,
                    seq_nr: 0,
                    ack_nr: 0,
                },
                payload: Vec::new(),
            }
        }

        fn bytes(&self) -> Vec<u8> {
            let mut buf: Vec<u8> = Vec::with_capacity(self.len());
            buf.push_all(self.header.bytes());
            buf.push_all(self.payload.as_slice());
            return buf;
        }

        fn len(&self) -> uint {
            self.header.len() + self.payload.len()
        }
    }

    pub struct UtpSocket {
        socket: UdpSocket,
        seq_nr: u16,
    }

    impl UtpSocket {
        pub fn bind(addr: SocketAddr) -> IoResult<UtpSocket> {
            let skt = UdpSocket::bind(addr);
            match skt {
                Ok(x)  => Ok(UtpSocket { socket: x, seq_nr: 1 }),
                Err(e) => Err(e)
            }
        }

        pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
            let mut packet = UtpPacket::new();
            packet.payload = Vec::from_slice(buf);
            packet.header.seq_nr = to_be16(self.seq_nr);
            packet.header.connection_id = to_be16(random());
            let t = time::get_time();
            packet.header.timestamp_microseconds = to_be32((t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32);

            // Send packet
            let result = self.socket.sendto(packet.bytes().as_slice(), dst);

            self.seq_nr += 1;
            result
        }

        pub fn recvfrom(&mut self, buf: &mut[u8]) -> IoResult<(uint,SocketAddr)> {
            self.socket.recvfrom(buf)
        }
    }
}

fn main() {
    let mut buf = [0, ..512];
    let mut sock = libtorresmo::UtpSocket::bind(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 }).unwrap();

    loop {
        match sock.recvfrom(buf) {
            Ok((_, src)) => {
                let payload = String::from_str("Hello\n").into_bytes();

                // Send uTP packet
                let _ = sock.sendto(payload.as_slice(), src);
            }
            Err(_) => {}
        }
    }
    drop(sock);
}
<|endoftext|>