<commit_before>extern crate holdem;
extern crate cards;

use holdem::{CardSlot, HandRankClass, hand_rank_to_class};
use cards::card::{Card, Value, Suit};

#[test]
fn borrow_card() {
    let card_slot = CardSlot::Dealt(Card(Value::Two, Suit::Hearts));
    let card = card_slot.expect_borrow();
    assert_eq!(card, &Card(Value::Two, Suit::Hearts));
}

#[test]
#[should_panic]
fn borrow_card_fail() {
    let card_slot = CardSlot::Empty;
    let _card = card_slot.expect_borrow();
}

#[test]
fn ordering_of_handrankclass() {
    assert!(HandRankClass::HighCard < HandRankClass::FullHouse);
    assert!(HandRankClass::StraightFlush == HandRankClass::StraightFlush);
}

#[test]
fn hand_rank_to_class_conversion() {
   assert_eq!(hand_rank_to_class(&0), HandRankClass::HighCard);
   assert_eq!(hand_rank_to_class(&1276), HandRankClass::HighCard);
   assert_eq!(hand_rank_to_class(&1277), HandRankClass::OnePair);
   assert_eq!(hand_rank_to_class(&(1277+2860)), HandRankClass::TwoPair);
   assert_eq!(hand_rank_to_class(&7451), HandRankClass::FourOfAKind);
   assert_eq!(hand_rank_to_class(&7461), HandRankClass::StraightFlush);
}
<commit_msg>Adjusted tests.<commit_after>extern crate holdem;
extern crate cards;

use holdem::{CardSlot, HandRankClass, hand_rank_to_class};
use cards::card::{Card, Value, Suit};

#[test]
fn borrow_card() {
    let card_slot = CardSlot::Dealt(Card(Value::Two, Suit::Hearts));
    let card = card_slot.expect_borrow();
    assert_eq!(card, &Card(Value::Two, Suit::Hearts));
}

#[test]
#[should_panic]
fn borrow_card_fail() {
    let card_slot = CardSlot::Empty;
    let _card = card_slot.expect_borrow();
}

#[test]
fn ordering_of_handrankclass() {
    assert!(HandRankClass::HighCard < HandRankClass::FullHouse);
    assert!(HandRankClass::StraightFlush == HandRankClass::StraightFlush);
}

#[test]
fn hand_rank_to_class_conversion() {
   assert_eq!(hand_rank_to_class(&0), HandRankClass::HighCard); // the worst hand rank
   assert_eq!(hand_rank_to_class(&1276), HandRankClass::HighCard);
   assert_eq!(hand_rank_to_class(&1277), HandRankClass::OnePair);
   assert_eq!(hand_rank_to_class(&(1277+2860)), HandRankClass::TwoPair);
   assert_eq!(hand_rank_to_class(&7451), HandRankClass::FourOfAKind);
   assert_eq!(hand_rank_to_class(&7461), HandRankClass::StraightFlush); // the best hand rank
}

#[test]
#[should_panic]
fn too_large_hand_rank() {
    hand_rank_to_class(&7462);
}
<|endoftext|>


<commit_before>extern crate nalgebra_lapack;
extern crate nalgebra as na;
extern crate num;

use nalgebra_lapack::{SVD, Eigensystem, Inverse, Cholesky};

use na::{DMatrix, DVector, Norm, ColumnSlice, Iterable, Eye, Transpose};
use num::complex::Complex;

#[test]
fn test_svd_wikipedia() {

    // Example from https://en.wikipedia.org/wiki/Singular_value_decomposition#Example

    let m = DMatrix::from_row_vector(4, 5,
                                     &[1.0, 0.0, 0.0, 0.0, 2.0,
                                       0.0, 0.0, 3.0, 0.0, 0.0,
                                       0.0, 0.0, 0.0, 0.0, 0.0,
                                       0.0, 4.0, 0.0, 0.0, 0.0]);

    let (u, s, vt) = m.svd().unwrap();

    let mut expected_u: DMatrix<f64> = DMatrix::new_zeros(4, 4);
    expected_u[(0, 2)] = 1.0;
    expected_u[(1, 1)] = 1.0;
    expected_u[(2, 3)] = -1.0;
    expected_u[(3, 0)] = 1.0;

    assert_eq!(u.nrows(), expected_u.nrows());
    assert_eq!(u.ncols(), expected_u.ncols());
    assert_eq!(u.as_vector(), expected_u.as_vector());

    let mut expected_s: DVector<f64> = DVector::from_element(4, 0.0);
    expected_s[0] = 4.0;
    expected_s[1] = 3.0;
    expected_s[2] = 5.0_f64.sqrt();

    assert_eq!(s.len(), expected_s.len());
    assert_eq!(s.as_ref(), expected_s.as_ref());

    let mut expected_vt: DMatrix<f64> = DMatrix::new_zeros(5, 5);
    expected_vt[(0, 1)] = 1.0;
    expected_vt[(1, 2)] = 1.0;
    expected_vt[(1, 2)] = 1.0;
    expected_vt[(2, 0)] = 0.2_f64.sqrt();
    expected_vt[(2, 4)] = 0.8_f64.sqrt();
    expected_vt[(3, 3)] = 1.0;
    expected_vt[(4, 0)] = -(0.8_f64.sqrt());
    expected_vt[(4, 4)] = 0.2_f64.sqrt();

    assert_eq!(vt.nrows(), expected_vt.nrows());
    assert_eq!(vt.ncols(), expected_vt.ncols());
    assert!(na::approx_eq(&vt, &expected_vt));
}

#[test]
fn test_svd_recomposition() {
    // The actual matrix contents and size should not matter.
    let m = DMatrix::from_row_vector(3, 5,
                                     &[-1.01, 0.86, -4.60, 3.31, -4.81,
                                        3.98, 0.53, -7.04, 5.29,  3.55,
                                        3.30, 8.26, -3.89, 8.20, -1.51]);
    let expected_m = m.clone(); // copy since original is moved into svd()
    let (u, s, vt) = m.svd().unwrap();

    let mut full_s = DMatrix::new_zeros(u.nrows(), vt.nrows());
    for i in 0..s.len() {
        full_s[(i, i)] = s[i];
    }
    let actual_m = u * (full_s * vt);

    assert!(na::approx_eq(&actual_m, &expected_m));
}

#[test]
fn test_svd_recomposition_complex() {

    // The actual matrix contents and size should not matter.
    let mr = DMatrix::from_row_vector(3, 5,
                                      &[-1.01, 0.86, -4.60, 3.31, -4.81,
                                         3.98, 0.53, -7.04, 5.29,  3.55,
                                         3.30, 8.26, -3.89, 8.20, -1.51]);

    let expected_m = mr.clone(); // copy since original is moved into svd()
    let m: DMatrix<Complex<f64>> =
        DMatrix::from_column_vector(mr.nrows(),
                                    mr.ncols(),
                                    &mr.as_vector()
                                        .iter()
                                        .map(|re| Complex { re: *re, im: 0.0 })
                                        .collect::<Vec<_>>());

    let (uc, s, vtc) = m.svd().unwrap();
    let u = real_only_mat(uc);
    let vt = real_only_mat(vtc);

    let mut full_s = DMatrix::new_zeros(u.nrows(), vt.nrows());
    for i in 0..s.len() {
        full_s[(i, i)] = s[i];
    }
    let actual_m = u * (full_s * vt);

    assert!(na::approx_eq(&actual_m, &expected_m));
}

fn real_only_mat(u: DMatrix<Complex<f64>>) -> DMatrix<f64> {
    DMatrix::from_column_vector(u.nrows(),
                                u.ncols(),
                                &u.as_vector()
                                    .iter()
                                    .map(|c| {
                                        assert!(c.im == 0.0);
                                        c.re
                                    })
                                    .collect::<Vec<_>>())
}

fn real_only(a: &DVector<Complex<f64>>) -> DVector<f64> {
    let v: Vec<_> = a.iter()
        .map(|cmplx| {
            assert!(cmplx.im == 0.0);
            cmplx.re
        })
        .collect();
    DVector { at: v }
}

fn na_position(a: &DVector<f64>, val: f64, eps: f64) -> Option<usize> {
    a.at.iter().position(|x| (*x - val).abs() < eps)
}

#[test]
fn test_eigenvalues_wikipedia_triangular() {

    // Based on example at
    // https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors#Triangular_matrices

    let n = 3;
    let mat = DMatrix::from_row_vector(n, n, &[1.0, 0.0, 0.0,
                                               1.0, 2.0, 0.0,
                                               2.0, 3.0, 3.0]);
    let (eigen_values, eigen_vectors) = mat.eigensystem().unwrap();

    assert!(eigen_values.len() == n);
    let ev = real_only(&eigen_values);
    let eps = 1e-16;

    // Check for eigvenvalue of 1.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 1.0, eps) {
        let expected = DVector { at: vec![1.0, -1.0, 0.5] }.normalize();
        let actual = real_only(&eigen_vectors.column_slice(i, 0, n));
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

    // Check for eigvenvalue of 2.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 2.0, eps) {
        let expected = DVector { at: vec![0.0, 1.0, -3.0] }.normalize();
        let actual = real_only(&eigen_vectors.column_slice(i, 0, n)).normalize();
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

    // Check for eigvenvalue of 3.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 3.0, eps) {
        let expected = DVector { at: vec![0.0, 0.0, 1.0] }.normalize();
        let actual = real_only(&eigen_vectors.column_slice(i, 0, n)).normalize();
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

}

#[test]
fn test_inverse_2d() {
    let a = DMatrix::from_row_vector(2, 2, &[1.0, 2.0, 3.0, 4.0]);
    let a_inv = a.clone().inv().unwrap();

    let eye_actual = a * a_inv;
    let eye_expected = DMatrix::new_identity(2);

    assert!(na::approx_eq(&eye_actual, &eye_expected));
}

#[test]
fn test_inverse_3d() {
    let a = DMatrix::from_row_vector(3, 3,
        &[1.0, 2.0, 0.0,
          0.0, 5.0, 6.0,
          7.0, 8.0, 9.0]);
    let a_inv = a.clone().inv().unwrap();

    let eye_actual = a * a_inv;
    let eye_expected = DMatrix::new_identity(3);

    assert!(na::approx_eq(&eye_actual, &eye_expected));
}

#[test]
fn test_complex_inverse_2d() {
    let ar = DMatrix::from_row_vector(2, 2,
        &[1.0, 2.0,
          3.0, 4.0]);
    let a: DMatrix<Complex<f64>> =
        DMatrix::from_column_vector(ar.nrows(),
                                    ar.ncols(),
                                    &ar.as_vector()
                                        .iter()
                                        .map(|re| Complex { re: *re, im: 0.0 })
                                        .collect::<Vec<_>>());
    let a_inv = a.clone().inv().unwrap();

    let eye_actual_complex = a * a_inv;
    let eye_actual = real_only_mat(eye_actual_complex);
    let eye_expected = DMatrix::new_identity(2);

    assert!(na::approx_eq(&eye_actual, &eye_expected));
}

#[test]
fn test_complex_inverse_3d() {
    let ar = DMatrix::from_row_vector(3, 3,
        &[1.0, 2.0, 0.0,
          0.0, 5.0, 6.0,
          7.0, 8.0, 9.0]);
    let a: DMatrix<Complex<f64>> =
        DMatrix::from_column_vector(ar.nrows(),
                                    ar.ncols(),
                                    &ar.as_vector()
                                        .iter()
                                        .map(|re| Complex { re: *re, im: 0.0 })
                                        .collect::<Vec<_>>());
    let a_inv = a.clone().inv().unwrap();

    let eye_actual_complex = a * a_inv;
    let eye_actual = real_only_mat(eye_actual_complex);
    let eye_expected = DMatrix::new_identity(3);

    assert!(na::approx_eq(&eye_actual, &eye_expected));
}

#[test]
fn test_cholesky() {
    let a = DMatrix::from_row_vector(3, 3,
        &[2.0, -1.0, 0.0,
         -1.0, 2.0, -1.0,
          0.0, -1.0, 2.0]);
    let lo = a.clone().cholesky().unwrap();
    let lot = lo.transpose(); // conjugate transpose for all real is simply the transpose
    let a_recomposed = &lo * &lot;
    assert!(na::approx_eq(&a, &a_recomposed));
}

#[test]
fn test_cholesky_complex() {
    let ar = DMatrix::from_row_vector(3, 3,
        &[2.0, -1.0, 0.0,
         -1.0, 2.0, -1.0,
         0.0, -1.0, 2.0]);
    let a: DMatrix<Complex<f64>> =
        DMatrix::from_column_vector(ar.nrows(),
                                    ar.ncols(),
                                    &ar.as_vector()
                                        .iter()
                                        .map(|re| Complex { re: *re, im: 0.0 })
                                        .collect::<Vec<_>>());
    let lo = a.clone().cholesky().unwrap();
    let lot = lo.transpose(); // conjugate transpose for all real is simply the transpose
    let a_recomposed_complex = &lo * &lot;
    let a_recomposed = real_only_mat(a_recomposed_complex);
    assert!(na::approx_eq(&ar, &a_recomposed));
}
<commit_msg>use conjugate transpose for complex matrix<commit_after>extern crate nalgebra_lapack;
extern crate nalgebra as na;
extern crate num;

use nalgebra_lapack::{SVD, Eigensystem, Inverse, Cholesky};

use na::{DMatrix, DVector, Norm, ColumnSlice, Iterable, Eye, Transpose};
use num::complex::Complex;

#[test]
fn test_svd_wikipedia() {

    // Example from https://en.wikipedia.org/wiki/Singular_value_decomposition#Example

    let m = DMatrix::from_row_vector(4, 5,
                                     &[1.0, 0.0, 0.0, 0.0, 2.0,
                                       0.0, 0.0, 3.0, 0.0, 0.0,
                                       0.0, 0.0, 0.0, 0.0, 0.0,
                                       0.0, 4.0, 0.0, 0.0, 0.0]);

    let (u, s, vt) = m.svd().unwrap();

    let mut expected_u: DMatrix<f64> = DMatrix::new_zeros(4, 4);
    expected_u[(0, 2)] = 1.0;
    expected_u[(1, 1)] = 1.0;
    expected_u[(2, 3)] = -1.0;
    expected_u[(3, 0)] = 1.0;

    assert_eq!(u.nrows(), expected_u.nrows());
    assert_eq!(u.ncols(), expected_u.ncols());
    assert_eq!(u.as_vector(), expected_u.as_vector());

    let mut expected_s: DVector<f64> = DVector::from_element(4, 0.0);
    expected_s[0] = 4.0;
    expected_s[1] = 3.0;
    expected_s[2] = 5.0_f64.sqrt();

    assert_eq!(s.len(), expected_s.len());
    assert_eq!(s.as_ref(), expected_s.as_ref());

    let mut expected_vt: DMatrix<f64> = DMatrix::new_zeros(5, 5);
    expected_vt[(0, 1)] = 1.0;
    expected_vt[(1, 2)] = 1.0;
    expected_vt[(1, 2)] = 1.0;
    expected_vt[(2, 0)] = 0.2_f64.sqrt();
    expected_vt[(2, 4)] = 0.8_f64.sqrt();
    expected_vt[(3, 3)] = 1.0;
    expected_vt[(4, 0)] = -(0.8_f64.sqrt());
    expected_vt[(4, 4)] = 0.2_f64.sqrt();

    assert_eq!(vt.nrows(), expected_vt.nrows());
    assert_eq!(vt.ncols(), expected_vt.ncols());
    assert!(na::approx_eq(&vt, &expected_vt));
}

#[test]
fn test_svd_recomposition() {
    // The actual matrix contents and size should not matter.
    let m = DMatrix::from_row_vector(3, 5,
                                     &[-1.01, 0.86, -4.60, 3.31, -4.81,
                                        3.98, 0.53, -7.04, 5.29,  3.55,
                                        3.30, 8.26, -3.89, 8.20, -1.51]);
    let expected_m = m.clone(); // copy since original is moved into svd()
    let (u, s, vt) = m.svd().unwrap();

    let mut full_s = DMatrix::new_zeros(u.nrows(), vt.nrows());
    for i in 0..s.len() {
        full_s[(i, i)] = s[i];
    }
    let actual_m = u * (full_s * vt);

    assert!(na::approx_eq(&actual_m, &expected_m));
}

#[test]
fn test_svd_recomposition_complex() {

    // The actual matrix contents and size should not matter.
    let mr = DMatrix::from_row_vector(3, 5,
                                      &[-1.01, 0.86, -4.60, 3.31, -4.81,
                                         3.98, 0.53, -7.04, 5.29,  3.55,
                                         3.30, 8.26, -3.89, 8.20, -1.51]);

    let expected_m = mr.clone(); // copy since original is moved into svd()
    let m: DMatrix<Complex<f64>> =
        DMatrix::from_column_vector(mr.nrows(),
                                    mr.ncols(),
                                    &mr.as_vector()
                                        .iter()
                                        .map(|re| Complex { re: *re, im: 0.0 })
                                        .collect::<Vec<_>>());

    let (uc, s, vtc) = m.svd().unwrap();
    let u = real_only_mat(uc);
    let vt = real_only_mat(vtc);

    let mut full_s = DMatrix::new_zeros(u.nrows(), vt.nrows());
    for i in 0..s.len() {
        full_s[(i, i)] = s[i];
    }
    let actual_m = u * (full_s * vt);

    assert!(na::approx_eq(&actual_m, &expected_m));
}

fn real_only_mat(u: DMatrix<Complex<f64>>) -> DMatrix<f64> {
    DMatrix::from_column_vector(u.nrows(),
                                u.ncols(),
                                &u.as_vector()
                                    .iter()
                                    .map(|c| {
                                        assert!(c.im == 0.0);
                                        c.re
                                    })
                                    .collect::<Vec<_>>())
}

fn real_only(a: &DVector<Complex<f64>>) -> DVector<f64> {
    let v: Vec<_> = a.iter()
        .map(|cmplx| {
            assert!(cmplx.im == 0.0);
            cmplx.re
        })
        .collect();
    DVector { at: v }
}

fn na_position(a: &DVector<f64>, val: f64, eps: f64) -> Option<usize> {
    a.at.iter().position(|x| (*x - val).abs() < eps)
}

#[test]
fn test_eigenvalues_wikipedia_triangular() {

    // Based on example at
    // https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors#Triangular_matrices

    let n = 3;
    let mat = DMatrix::from_row_vector(n, n, &[1.0, 0.0, 0.0,
                                               1.0, 2.0, 0.0,
                                               2.0, 3.0, 3.0]);
    let (eigen_values, eigen_vectors) = mat.eigensystem().unwrap();

    assert!(eigen_values.len() == n);
    let ev = real_only(&eigen_values);
    let eps = 1e-16;

    // Check for eigvenvalue of 1.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 1.0, eps) {
        let expected = DVector { at: vec![1.0, -1.0, 0.5] }.normalize();
        let actual = real_only(&eigen_vectors.column_slice(i, 0, n));
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

    // Check for eigvenvalue of 2.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 2.0, eps) {
        let expected = DVector { at: vec![0.0, 1.0, -3.0] }.normalize();
        let actual = real_only(&eigen_vectors.column_slice(i, 0, n)).normalize();
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

    // Check for eigvenvalue of 3.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 3.0, eps) {
        let expected = DVector { at: vec![0.0, 0.0, 1.0] }.normalize();
        let actual = real_only(&eigen_vectors.column_slice(i, 0, n)).normalize();
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

}

#[test]
fn test_inverse_2d() {
    let a = DMatrix::from_row_vector(2, 2, &[1.0, 2.0, 3.0, 4.0]);
    let a_inv = a.clone().inv().unwrap();

    let eye_actual = a * a_inv;
    let eye_expected = DMatrix::new_identity(2);

    assert!(na::approx_eq(&eye_actual, &eye_expected));
}

#[test]
fn test_inverse_3d() {
    let a = DMatrix::from_row_vector(3, 3,
        &[1.0, 2.0, 0.0,
          0.0, 5.0, 6.0,
          7.0, 8.0, 9.0]);
    let a_inv = a.clone().inv().unwrap();

    let eye_actual = a * a_inv;
    let eye_expected = DMatrix::new_identity(3);

    assert!(na::approx_eq(&eye_actual, &eye_expected));
}

#[test]
fn test_complex_inverse_2d() {
    let ar = DMatrix::from_row_vector(2, 2,
        &[1.0, 2.0,
          3.0, 4.0]);
    let a: DMatrix<Complex<f64>> =
        DMatrix::from_column_vector(ar.nrows(),
                                    ar.ncols(),
                                    &ar.as_vector()
                                        .iter()
                                        .map(|re| Complex { re: *re, im: 0.0 })
                                        .collect::<Vec<_>>());
    let a_inv = a.clone().inv().unwrap();

    let eye_actual_complex = a * a_inv;
    let eye_actual = real_only_mat(eye_actual_complex);
    let eye_expected = DMatrix::new_identity(2);

    assert!(na::approx_eq(&eye_actual, &eye_expected));
}

#[test]
fn test_complex_inverse_3d() {
    let ar = DMatrix::from_row_vector(3, 3,
        &[1.0, 2.0, 0.0,
          0.0, 5.0, 6.0,
          7.0, 8.0, 9.0]);
    let a: DMatrix<Complex<f64>> =
        DMatrix::from_column_vector(ar.nrows(),
                                    ar.ncols(),
                                    &ar.as_vector()
                                        .iter()
                                        .map(|re| Complex { re: *re, im: 0.0 })
                                        .collect::<Vec<_>>());
    let a_inv = a.clone().inv().unwrap();

    let eye_actual_complex = a * a_inv;
    let eye_actual = real_only_mat(eye_actual_complex);
    let eye_expected = DMatrix::new_identity(3);

    assert!(na::approx_eq(&eye_actual, &eye_expected));
}

#[test]
fn test_cholesky() {
    let a = DMatrix::from_row_vector(3, 3,
        &[2.0, -1.0, 0.0,
         -1.0, 2.0, -1.0,
          0.0, -1.0, 2.0]);
    let lo = a.clone().cholesky().unwrap();
    let lot = lo.transpose(); // conjugate transpose for all real is simply the transpose
    let a_recomposed = &lo * &lot;
    assert!(na::approx_eq(&a, &a_recomposed));
}

fn conjugate_transpose(a: &DMatrix<Complex<f64>>) -> DMatrix<Complex<f64>> {
    let mut b = DMatrix::new_zeros(a.ncols(), a.nrows());
    for i in 0..a.nrows() {
        for j in 0..a.ncols() {
            let c = a[(i,j)];
            b[(j,i)] = Complex {re: c.re, im: -c.im};
        }
    }
    b
}

#[test]
fn test_cholesky_complex() {
    let ar = DMatrix::from_row_vector(3, 3,
        &[2.0, -1.0, 0.0,
         -1.0, 2.0, -1.0,
         0.0, -1.0, 2.0]);
    let a: DMatrix<Complex<f64>> =
        DMatrix::from_column_vector(ar.nrows(),
                                    ar.ncols(),
                                    &ar.as_vector()
                                        .iter()
                                        .map(|re| Complex { re: *re, im: 0.0 })
                                        .collect::<Vec<_>>());
    let lo = a.clone().cholesky().unwrap();
    let lot = conjugate_transpose(&lo);
    let a_recomposed_complex = &lo * &lot;
    let a_recomposed = real_only_mat(a_recomposed_complex);
    assert!(na::approx_eq(&ar, &a_recomposed));
}
<|endoftext|>


<commit_before>#![recursion_limit="128"]
#![no_std]
#[macro_use]
extern crate generic_array;
use core::cell::Cell;
use core::ops::Drop;
use generic_array::GenericArray;
use generic_array::typenum::{U1, U3, U97};

#[test]
fn test() {
    let mut list97 = [0; 97];
    for i in 0..97 {
        list97[i] = i as i32;
    }
    let l: GenericArray<i32, U97> = GenericArray::clone_from_slice(&list97);
    assert_eq!(l[0], 0);
    assert_eq!(l[1], 1);
    assert_eq!(l[32], 32);
    assert_eq!(l[56], 56);
}

#[test]
fn test_drop() {
    #[derive(Clone)]
    struct TestDrop<'a>(&'a Cell<u32>);

    impl<'a> Drop for TestDrop<'a> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    let drop_counter = Cell::new(0);
    {
        let _: GenericArray<TestDrop, U3> = arr![TestDrop; TestDrop(&drop_counter), TestDrop(&drop_counter), TestDrop(&drop_counter)];
    }
    assert_eq!(drop_counter.get(), 3);
}

#[test]
fn test_arr() {
    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
    assert_eq!(test[1], 2);
}

#[test]
fn test_copy() {
    let test = arr![u32; 1, 2, 3];
    let test2 = test;
    // if GenericArray is not copy, this should fail as a use of a moved value
    assert_eq!(test[1], 2);
    assert_eq!(test2[0], 1);
}

#[test]
fn test_iter_flat_map() {
    assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
}

#[derive(Debug, PartialEq, Eq)]
struct NoClone<T>(T);

#[test]
fn test_from_slice() {
    let arr = [1, 2, 3, 4];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
    let arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
}

#[test]
fn test_from_mut_slice() {
    let mut arr = [1, 2, 3, 4];
    {
        let mut gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = 10;
    }
    assert_eq!(arr, [1, 2, 10, 4]);
    let mut arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    {
        let mut gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = NoClone(10);
    }
    assert_eq!(arr, [NoClone(1), NoClone(2), NoClone(10), NoClone(4)]);
}

#[test]
fn test_default() {
    let arr = GenericArray::<u8, U1>::default();
    assert_eq!(arr[0], 0);
}

#[test]
fn test_unit_macro() {
    let arr = arr![f32; 3.14];
    assert_eq!(arr[0], 3.14);
}

#[test]
fn test_empty_macro() {
    let arr = arr![f32;];
}

/// This test should cause a helpful compile error if uncommented.
// #[test]
// fn test_empty_macro2(){
//     let arr = arr![];
// }
#[cfg(feature = "serde")]
mod impl_serde {
    extern crate serde_json;

    use generic_array::GenericArray;
    use generic_array::typenum::U6;

    #[test]
    fn test_serde_implementation() {
        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
        let string = serde_json::to_string(&array).unwrap();
        assert_eq!(string, "[0.0,5.0,3.0,7.07192,76.0,-9.0]");

        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
        assert_eq!(test_array, array);
    }
}
<commit_msg>Add more tests<commit_after>#![recursion_limit="128"]
#![no_std]
#[macro_use]
extern crate generic_array;
use core::cell::Cell;
use core::ops::Drop;
use generic_array::GenericArray;
use generic_array::typenum::{U1, U3, U4, U97};

#[test]
fn test() {
    let mut list97 = [0; 97];
    for i in 0..97 {
        list97[i] = i as i32;
    }
    let l: GenericArray<i32, U97> = GenericArray::clone_from_slice(&list97);
    assert_eq!(l[0], 0);
    assert_eq!(l[1], 1);
    assert_eq!(l[32], 32);
    assert_eq!(l[56], 56);
}

#[test]
fn test_drop() {
    #[derive(Clone)]
    struct TestDrop<'a>(&'a Cell<u32>);

    impl<'a> Drop for TestDrop<'a> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    let drop_counter = Cell::new(0);
    {
        let _: GenericArray<TestDrop, U3> =
            arr![TestDrop; TestDrop(&drop_counter),
                           TestDrop(&drop_counter),
                           TestDrop(&drop_counter)];
    }
    assert_eq!(drop_counter.get(), 3);
}

#[test]
fn test_arr() {
    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
    assert_eq!(test[1], 2);
}

#[test]
fn test_copy() {
    let test = arr![u32; 1, 2, 3];
    let test2 = test;
    // if GenericArray is not copy, this should fail as a use of a moved value
    assert_eq!(test[1], 2);
    assert_eq!(test2[0], 1);
}

#[test]
fn test_iter_flat_map() {
    assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
}

#[derive(Debug, PartialEq, Eq)]
struct NoClone<T>(T);

#[test]
fn test_from_slice() {
    let arr = [1, 2, 3, 4];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
    let arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
}

#[test]
fn test_from_mut_slice() {
    let mut arr = [1, 2, 3, 4];
    {
        let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = 10;
    }
    assert_eq!(arr, [1, 2, 10, 4]);
    let mut arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    {
        let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = NoClone(10);
    }
    assert_eq!(arr, [NoClone(1), NoClone(2), NoClone(10), NoClone(4)]);
}

#[test]
fn test_default() {
    let arr = GenericArray::<u8, U1>::default();
    assert_eq!(arr[0], 0);
}

#[test]
fn test_unit_macro() {
    let arr = arr![f32; 3.14];
    assert_eq!(arr[0], 3.14);
}

#[test]
fn test_empty_macro() {
    let _arr = arr![f32;];
}

/// This test should cause a helpful compile error if uncommented.
// #[test]
// fn test_empty_macro2(){
//     let arr = arr![];
// }
#[cfg(feature = "serde")]
mod impl_serde {
    extern crate serde_json;

    use generic_array::GenericArray;
    use generic_array::typenum::U6;

    #[test]
    fn test_serde_implementation() {
        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
        let string = serde_json::to_string(&array).unwrap();
        assert_eq!(string, "[0.0,5.0,3.0,7.07192,76.0,-9.0]");

        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
        assert_eq!(test_array, array);
    }
}

#[test]
fn test_map() {
    let b: GenericArray<i32, U4> = GenericArray::generate(|i| i as i32 * 4).map(|x| x - 3);

    assert_eq!(b, arr![i32; -3, 1, 5, 9]);
}

#[test]
fn test_zip() {
    let a: GenericArray<_, U4> = GenericArray::generate(|i| i + 1);
    let b: GenericArray<_, U4> = GenericArray::generate(|i| i as i32 * 4);

    let c = a.zip(b, |r, l| r as i32 + l);

    assert_eq!(c, arr![i32; 1, 6, 11, 16]);
}

#[test]
fn test_from_iter() {
    use core::iter::repeat;

    let a: GenericArray<_, U4> = repeat(11).take(3).collect();

    assert_eq!(a, arr![i32; 11, 11, 11, 0]);
}

#[test]
fn test_cmp() {
    arr![u8; 0x00].cmp(&arr![u8; 0x00]);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      }
    }
  }
}

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

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

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

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

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

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

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

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

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

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<commit_msg>load more of the file at once<commit_after>#[macro_use]
extern crate nom;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      }
    }
  }
}

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

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

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

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

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

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

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

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

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

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


<commit_before><commit_msg>Add `#[rustc_args_required_const]` to `simd_shuffle`<commit_after><|endoftext|>


<commit_before>//! Configure the process resource limits.
use cfg_if::cfg_if;

use crate::errno::Errno;
use crate::Result;
pub use libc::rlim_t;
use std::mem;

cfg_if! {
    if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
        use libc::{__rlimit_resource_t, rlimit};
    } else if #[cfg(any(
        target_os = "freebsd",
        target_os = "openbsd",
        target_os = "netbsd",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
        target_os = "dragonfly",
        all(target_os = "linux", not(target_env = "gnu"))
    ))]{
        use libc::{c_int, rlimit};
    }
}

libc_enum! {
    /// Types of process resources.
    ///
    /// The Resource enum is platform dependent. Check different platform
    /// manuals for more details. Some platform links have been provided for
    /// easier reference (non-exhaustive).
    ///
    /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html)
    /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit)
    /// * [NetBSD](https://man.netbsd.org/setrlimit.2)

    // linux-gnu uses u_int as resource enum, which is implemented in libc as
    // well.
    //
    // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html
    // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs
    #[cfg_attr(all(target_os = "linux", target_env = "gnu"), repr(u32))]
    #[cfg_attr(any(
            target_os = "freebsd",
            target_os = "openbsd",
            target_os = "netbsd",
            target_os = "macos",
            target_os = "ios",
            target_os = "android",
            target_os = "dragonfly",
            all(target_os = "linux", not(target_env = "gnu"))
        ), repr(i32))]
    #[non_exhaustive]
    pub enum Resource {
        #[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum amount (in bytes) of virtual memory the process is
        /// allowed to map.
        RLIMIT_AS,
        /// The largest size (in bytes) core(5) file that may be created.
        RLIMIT_CORE,
        /// The maximum amount of cpu time (in seconds) to be used by each
        /// process.
        RLIMIT_CPU,
        /// The maximum size (in bytes) of the data segment for a process
        RLIMIT_DATA,
        /// The largest size (in bytes) file that may be created.
        RLIMIT_FSIZE,
        /// The maximum number of open files for this process.
        RLIMIT_NOFILE,
        /// The maximum size (in bytes) of the stack segment for a process.
        RLIMIT_STACK,

        #[cfg(target_os = "freebsd")]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum number of kqueues this user id is allowed to create.
        RLIMIT_KQUEUES,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A limit on the combined number of flock locks and fcntl leases that
        /// this process may establish.
        RLIMIT_LOCKS,

        #[cfg(any(
            target_os = "android",
            target_os = "freebsd",
            target_os = "openbsd",
            target_os = "linux",
            target_os = "netbsd"
        ))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum size (in bytes) which a process may lock into memory
        /// using the mlock(2) system call.
        RLIMIT_MEMLOCK,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A limit on the number of bytes that can be allocated for POSIX
        /// message queues  for  the  real  user  ID  of  the  calling process.
        RLIMIT_MSGQUEUE,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A ceiling to which the process's nice value can be raised using
        /// setpriority or nice.
        RLIMIT_NICE,

        #[cfg(any(
            target_os = "android",
            target_os = "freebsd",
            target_os = "netbsd",
            target_os = "openbsd",
            target_os = "linux",
        ))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum number of simultaneous processes for this user id.
        RLIMIT_NPROC,

        #[cfg(target_os = "freebsd")]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum number of pseudo-terminals this user id is allowed to
        /// create.
        RLIMIT_NPTS,

        #[cfg(any(target_os = "android",
            target_os = "freebsd",
            target_os = "netbsd",
            target_os = "openbsd",
            target_os = "linux",
        ))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// When there is memory pressure and swap is available, prioritize
        /// eviction of a process' resident pages beyond this amount (in bytes).
        RLIMIT_RSS,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A ceiling on the real-time priority that may be set for this process
        /// using sched_setscheduler and  sched_set‐ param.
        RLIMIT_RTPRIO,

        #[cfg(any(target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A limit (in microseconds) on the amount of CPU time that a process
        /// scheduled under a real-time scheduling policy may con‐ sume without
        /// making a blocking system call.
        RLIMIT_RTTIME,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A limit on the number of signals that may be queued for the real
        /// user ID of the  calling  process.
        RLIMIT_SIGPENDING,

        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum size (in bytes) of socket buffer usage for this user.
        RLIMIT_SBSIZE,

        #[cfg(target_os = "freebsd")]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum size (in bytes) of the swap space that may be reserved
        /// or used by all of this user id's processes.
        RLIMIT_SWAP,

        #[cfg(target_os = "freebsd")]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// An alias for RLIMIT_AS.
        RLIMIT_VMEM,
    }
}

/// Get the current processes resource limits
///
/// The special value `RLIM_INFINITY` indicates that no limit will be
/// enforced.
///
/// # Parameters
///
/// * `resource`: The [`Resource`] that we want to get the limits of.
///
/// # Examples
///
/// ```
/// # use nix::sys::resource::{getrlimit, Resource};
///
/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
/// println!("current soft_limit: {}", soft_limit);
/// println!("current hard_limit: {}", hard_limit);
/// ```
///
/// # References
///
/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
///
/// [`Resource`]: enum.Resource.html
pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
    let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();

    cfg_if! {
        if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
            let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
        } else {
            let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
        }
    }

    Errno::result(res).map(|_| {
        let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() };
        (rlim_cur, rlim_max)
    })
}

/// Set the current processes resource limits
///
/// # Parameters
///
/// * `resource`: The [`Resource`] that we want to set the limits of.
/// * `soft_limit`: The value that the kernel enforces for the corresponding
///   resource.
/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to
///   the current hard limit for non-root users.
///
/// The special value `RLIM_INFINITY` indicates that no limit will be
/// enforced.
///
/// # Examples
///
/// ```
/// # use nix::sys::resource::{setrlimit, Resource};
///
/// let soft_limit = 512;
/// let hard_limit = 1024;
/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
/// ```
///
/// # References
///
/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
///
/// [`Resource`]: enum.Resource.html
///
/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`.
pub fn setrlimit(
    resource: Resource,
    soft_limit: rlim_t,
    hard_limit: rlim_t,
) -> Result<()> {
    let new_rlim = rlimit {
        rlim_cur: soft_limit,
        rlim_max: hard_limit,
    };
    cfg_if! {
        if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
            let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
        }else{
            let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
        }
    }

    Errno::result(res).map(drop)
}
<commit_msg>uclibc uses a u32 for RLIMIT definitions<commit_after>//! Configure the process resource limits.
use cfg_if::cfg_if;

use crate::errno::Errno;
use crate::Result;
pub use libc::rlim_t;
use std::mem;

cfg_if! {
    if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
        use libc::{__rlimit_resource_t, rlimit};
    } else if #[cfg(any(
        target_os = "freebsd",
        target_os = "openbsd",
        target_os = "netbsd",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
        target_os = "dragonfly",
        all(target_os = "linux", not(target_env = "gnu"))
    ))]{
        use libc::{c_int, rlimit};
    }
}

libc_enum! {
    /// Types of process resources.
    ///
    /// The Resource enum is platform dependent. Check different platform
    /// manuals for more details. Some platform links have been provided for
    /// easier reference (non-exhaustive).
    ///
    /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html)
    /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit)
    /// * [NetBSD](https://man.netbsd.org/setrlimit.2)

    // linux-gnu uses u_int as resource enum, which is implemented in libc as
    // well.
    //
    // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html
    // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs
    #[cfg_attr(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), repr(u32))]
    #[cfg_attr(any(
            target_os = "freebsd",
            target_os = "openbsd",
            target_os = "netbsd",
            target_os = "macos",
            target_os = "ios",
            target_os = "android",
            target_os = "dragonfly",
            all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc")))
        ), repr(i32))]
    #[non_exhaustive]
    pub enum Resource {
        #[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum amount (in bytes) of virtual memory the process is
        /// allowed to map.
        RLIMIT_AS,
        /// The largest size (in bytes) core(5) file that may be created.
        RLIMIT_CORE,
        /// The maximum amount of cpu time (in seconds) to be used by each
        /// process.
        RLIMIT_CPU,
        /// The maximum size (in bytes) of the data segment for a process
        RLIMIT_DATA,
        /// The largest size (in bytes) file that may be created.
        RLIMIT_FSIZE,
        /// The maximum number of open files for this process.
        RLIMIT_NOFILE,
        /// The maximum size (in bytes) of the stack segment for a process.
        RLIMIT_STACK,

        #[cfg(target_os = "freebsd")]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum number of kqueues this user id is allowed to create.
        RLIMIT_KQUEUES,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A limit on the combined number of flock locks and fcntl leases that
        /// this process may establish.
        RLIMIT_LOCKS,

        #[cfg(any(
            target_os = "android",
            target_os = "freebsd",
            target_os = "openbsd",
            target_os = "linux",
            target_os = "netbsd"
        ))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum size (in bytes) which a process may lock into memory
        /// using the mlock(2) system call.
        RLIMIT_MEMLOCK,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A limit on the number of bytes that can be allocated for POSIX
        /// message queues  for  the  real  user  ID  of  the  calling process.
        RLIMIT_MSGQUEUE,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A ceiling to which the process's nice value can be raised using
        /// setpriority or nice.
        RLIMIT_NICE,

        #[cfg(any(
            target_os = "android",
            target_os = "freebsd",
            target_os = "netbsd",
            target_os = "openbsd",
            target_os = "linux",
        ))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum number of simultaneous processes for this user id.
        RLIMIT_NPROC,

        #[cfg(target_os = "freebsd")]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum number of pseudo-terminals this user id is allowed to
        /// create.
        RLIMIT_NPTS,

        #[cfg(any(target_os = "android",
            target_os = "freebsd",
            target_os = "netbsd",
            target_os = "openbsd",
            target_os = "linux",
        ))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// When there is memory pressure and swap is available, prioritize
        /// eviction of a process' resident pages beyond this amount (in bytes).
        RLIMIT_RSS,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A ceiling on the real-time priority that may be set for this process
        /// using sched_setscheduler and  sched_set‐ param.
        RLIMIT_RTPRIO,

        #[cfg(any(target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A limit (in microseconds) on the amount of CPU time that a process
        /// scheduled under a real-time scheduling policy may con‐ sume without
        /// making a blocking system call.
        RLIMIT_RTTIME,

        #[cfg(any(target_os = "android", target_os = "linux"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// A limit on the number of signals that may be queued for the real
        /// user ID of the  calling  process.
        RLIMIT_SIGPENDING,

        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum size (in bytes) of socket buffer usage for this user.
        RLIMIT_SBSIZE,

        #[cfg(target_os = "freebsd")]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// The maximum size (in bytes) of the swap space that may be reserved
        /// or used by all of this user id's processes.
        RLIMIT_SWAP,

        #[cfg(target_os = "freebsd")]
        #[cfg_attr(docsrs, doc(cfg(all())))]
        /// An alias for RLIMIT_AS.
        RLIMIT_VMEM,
    }
}

/// Get the current processes resource limits
///
/// The special value `RLIM_INFINITY` indicates that no limit will be
/// enforced.
///
/// # Parameters
///
/// * `resource`: The [`Resource`] that we want to get the limits of.
///
/// # Examples
///
/// ```
/// # use nix::sys::resource::{getrlimit, Resource};
///
/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
/// println!("current soft_limit: {}", soft_limit);
/// println!("current hard_limit: {}", hard_limit);
/// ```
///
/// # References
///
/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
///
/// [`Resource`]: enum.Resource.html
pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
    let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();

    cfg_if! {
        if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
            let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
        } else {
            let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
        }
    }

    Errno::result(res).map(|_| {
        let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() };
        (rlim_cur, rlim_max)
    })
}

/// Set the current processes resource limits
///
/// # Parameters
///
/// * `resource`: The [`Resource`] that we want to set the limits of.
/// * `soft_limit`: The value that the kernel enforces for the corresponding
///   resource.
/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to
///   the current hard limit for non-root users.
///
/// The special value `RLIM_INFINITY` indicates that no limit will be
/// enforced.
///
/// # Examples
///
/// ```
/// # use nix::sys::resource::{setrlimit, Resource};
///
/// let soft_limit = 512;
/// let hard_limit = 1024;
/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
/// ```
///
/// # References
///
/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
///
/// [`Resource`]: enum.Resource.html
///
/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`.
pub fn setrlimit(
    resource: Resource,
    soft_limit: rlim_t,
    hard_limit: rlim_t,
) -> Result<()> {
    let new_rlim = rlimit {
        rlim_cur: soft_limit,
        rlim_max: hard_limit,
    };
    cfg_if! {
        if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
            let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
        }else{
            let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
        }
    }

    Errno::result(res).map(drop)
}
<|endoftext|>


<commit_before>use tensor::{Tensor, NumLimits, THVec, THVecGeneric, THDims};
use num::NumCast;

impl<T: NumLimits> THVec<T> {
    pub fn new(dims: Vec<usize>, data: Vec<T>) -> Self {
        THVec {
            dims: dims,
            data: data,
        }
    }
}
impl THVecGeneric {
    pub fn new(dims: Vec<usize>, data: Vec<i64>) -> Self {
        THVecGeneric {
            dims: dims,
            data: data,
        }
    }
}
impl THDims {
    fn new(dims: Vec<usize>) -> Self {
        THDims { dims: dims }
    }
}
impl<T: NumLimits> From<Vec<Vec<Vec<T>>>> for THVec<T> {
    fn from(input: Vec<Vec<Vec<T>>>) -> Self {
        let dims = vec![input.len(), input[0].len(), input[0][0].len()];
        let v = input
            .iter()
            .flat_map(|d| d.iter())
            .flat_map(|d| d.iter())
            .map(|d| *d)
            .collect();
        THVec::new(dims, v)
    }
}
impl<T: NumLimits> From<Vec<Vec<T>>> for THVec<T> {
    fn from(input: Vec<Vec<T>>) -> Self {
        let dims = vec![input.len(), input[0].len()];
        let v = input.iter().flat_map(|d| d.iter()).map(|d| *d).collect();
        THVec::new(dims, v)
    }
}
impl<T: NumLimits> From<Vec<T>> for THVec<T> {
    fn from(input: Vec<T>) -> Self {
        let dims = vec![input.len()];
        THVec::new(dims, input)
    }
}
impl<T: NumLimits> From<T> for THVec<T> {
    fn from(input: T) -> Self {
        let v = vec![input];
        THVec::new(vec![], v)
    }
}
impl<T: NumLimits> From<T> for THVecGeneric {
    fn from(input: T) -> Self {
        let v: Vec<i64> = vec![<i64 as NumCast>::from(input).unwrap()];
        THVecGeneric::new(vec![], v)
    }
}

#[allow(unused_variables)]
impl<T: NumLimits> From<()> for THVec<T> {
    fn from(input: ()) -> Self {
        THVec::new(vec![], vec![])
    }
}
#[allow(unused_variables)]
impl From<()> for THVecGeneric {
    fn from(input: ()) -> Self {
        THVecGeneric::new(vec![], vec![])
    }
}
#[allow(unused_variables)]
impl From<()> for THDims {
    fn from(input: ()) -> Self {
        THDims::new(vec![])
    }
}
impl<T: NumLimits> From<(usize, usize)> for THVec<T> {
    fn from(input: (usize, usize)) -> Self {
        THVec::new(vec![input.0, input.1], vec![])
    }
}
impl From<(usize, usize)> for THVecGeneric {
    fn from(input: (usize, usize)) -> Self {

        THVecGeneric::new(vec![input.0, input.1], vec![])
    }
}
impl From<(usize)> for THVecGeneric {
    fn from(input: (usize)) -> Self {

        THVecGeneric::new(vec![input], vec![])
    }
}
impl<T: NumLimits> From<(usize)> for THVec<T> {
    fn from(input: (usize)) -> Self {
        THVec::new(vec![input], vec![])
    }
}
impl<T: NumLimits> From<Vec<usize>> for THVec<T> {
    fn from(input: Vec<usize>) -> Self {
        THVec::new(input, vec![])
    }
}
impl From<Vec<usize>> for THVecGeneric {
    fn from(input: Vec<usize>) -> Self {
        THVecGeneric::new(input, vec![])
    }
}
impl From<Vec<usize>> for THDims {
    fn from(input: Vec<usize>) -> Self {
        THDims::new(input)
    }
}
impl<T: NumLimits> From<Vec<Tensor<T>>> for THVec<T> {
    fn from(input: Vec<Tensor<T>>) -> Self {
        /*
        let v = input.iter().flat_map(|d| d.iter()).map(|d| *d).collect();
        THVec::new(2, v)
        */
        unimplemented!()
    }
}
impl From<THVecGeneric> for THVec<u8> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<u8> = input
            .data
            .iter()
            .map(|t| <u8 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}
impl From<THVecGeneric> for THVec<f32> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<f32> = input
            .data
            .iter()
            .map(|t| <f32 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}
impl From<THVecGeneric> for THVec<i64> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<i64> = input
            .data
            .iter()
            .map(|t| <i64 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}

impl<T: NumLimits> From<THVec<T>> for THDims {
    fn from(input: THVec<T>) -> Self {
        THDims::new(input.dims.clone())
    }
}
impl From<THVecGeneric> for THDims {
    fn from(input: THVecGeneric) -> Self {
        THDims::new(input.dims.clone())
    }
}

trait TensorNew<T: NumLimits> {
    fn tensor_new(arg: THDims) -> Tensor<T>;
}

impl<T: NumLimits> TensorNew<T> for Tensor<T> {
    #[allow(unused_variables)]
    default fn tensor_new(arg: THDims) -> Tensor<T> {
        unreachable!()
    }
}

impl TensorNew<u8> for Tensor<u8> {
    fn tensor_new(arg: THDims) -> Tensor<u8> {
        let t = ::RcMutNew(::tensor::ByteTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<i64> for Tensor<i64> {
    fn tensor_new(arg: THDims) -> Tensor<i64> {
        let t = ::RcMutNew(::tensor::LongTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<f32> for Tensor<f32> {
    fn tensor_new(arg: THDims) -> Tensor<f32> {
        let t = ::RcMutNew(::tensor::FloatTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<f64> for Tensor<f64> {
    fn tensor_new(arg: THDims) -> Tensor<f64> {
        let t = ::RcMutNew(::tensor::DoubleTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}

pub fn byte_tensor<T>(arg: T) -> Tensor<u8>
    where T: Into<THVec<u8>>
{
    tensor(arg)
}
pub fn long_tensor<T>(arg: T) -> Tensor<i64>
    where T: Into<THVec<i64>>
{
    tensor(arg)
}
pub fn float_tensor<T>(arg: T) -> Tensor<f32>
    where T: Into<THVec<f32>>
{
    tensor(arg)
}
pub fn double_tensor<T>(arg: T) -> Tensor<f64>
    where T: Into<THVec<f64>>
{
    tensor(arg)
}
pub fn tensor<S, T>(arg: S) -> Tensor<T>
    where T: NumLimits,
          S: Into<THVec<T>>
{
    let t: THVec<T> = arg.into();
    Tensor::tensor_new(t.into())
}
<commit_msg>allow source type to be different from destination type<commit_after>use tensor::{Tensor, NumLimits, THVec, THVecGeneric, THDims};
use num::NumCast;

impl<T: NumLimits> THVec<T> {
    pub fn new(dims: Vec<usize>, data: Vec<T>) -> Self {
        THVec {
            dims: dims,
            data: data,
        }
    }
}
impl THVecGeneric {
    pub fn new(dims: Vec<usize>, data: Vec<i64>) -> Self {
        THVecGeneric {
            dims: dims,
            data: data,
        }
    }
}
impl THDims {
    fn new(dims: Vec<usize>) -> Self {
        THDims { dims: dims }
    }
}
impl<T: NumLimits> From<Vec<Vec<Vec<T>>>> for THVec<T> {
    fn from(input: Vec<Vec<Vec<T>>>) -> Self {
        let dims = vec![input.len(), input[0].len(), input[0][0].len()];
        let v = input
            .iter()
            .flat_map(|d| d.iter())
            .flat_map(|d| d.iter())
            .map(|d| *d)
            .collect();
        THVec::new(dims, v)
    }
}
impl<T: NumLimits> From<Vec<Vec<T>>> for THVec<T> {
    fn from(input: Vec<Vec<T>>) -> Self {
        let dims = vec![input.len(), input[0].len()];
        let v = input.iter().flat_map(|d| d.iter()).map(|d| *d).collect();
        THVec::new(dims, v)
    }
}
impl<T: NumLimits> From<Vec<T>> for THVec<T> {
    fn from(input: Vec<T>) -> Self {
        let dims = vec![input.len()];
        THVec::new(dims, input)
    }
}
impl<T: NumLimits> From<T> for THVec<T> {
    fn from(input: T) -> Self {
        let v = vec![input];
        THVec::new(vec![], v)
    }
}
impl<T: NumLimits> From<T> for THVecGeneric {
    fn from(input: T) -> Self {
        let v: Vec<i64> = vec![<i64 as NumCast>::from(input).unwrap()];
        THVecGeneric::new(vec![], v)
    }
}

#[allow(unused_variables)]
impl<T: NumLimits> From<()> for THVec<T> {
    fn from(input: ()) -> Self {
        THVec::new(vec![], vec![])
    }
}
#[allow(unused_variables)]
impl From<()> for THVecGeneric {
    fn from(input: ()) -> Self {
        THVecGeneric::new(vec![], vec![])
    }
}
#[allow(unused_variables)]
impl From<()> for THDims {
    fn from(input: ()) -> Self {
        THDims::new(vec![])
    }
}
impl<T: NumLimits> From<(usize, usize)> for THVec<T> {
    fn from(input: (usize, usize)) -> Self {
        THVec::new(vec![input.0, input.1], vec![])
    }
}
impl From<(usize, usize)> for THVecGeneric {
    fn from(input: (usize, usize)) -> Self {

        THVecGeneric::new(vec![input.0, input.1], vec![])
    }
}
impl From<(usize)> for THVecGeneric {
    fn from(input: (usize)) -> Self {

        THVecGeneric::new(vec![input], vec![])
    }
}
impl<T: NumLimits> From<(usize)> for THVec<T> {
    fn from(input: (usize)) -> Self {
        THVec::new(vec![input], vec![])
    }
}
impl<T: NumLimits> From<Vec<usize>> for THVec<T> {
    fn from(input: Vec<usize>) -> Self {
        THVec::new(input, vec![])
    }
}
impl From<Vec<usize>> for THVecGeneric {
    fn from(input: Vec<usize>) -> Self {
        THVecGeneric::new(input, vec![])
    }
}
impl From<Vec<usize>> for THDims {
    fn from(input: Vec<usize>) -> Self {
        THDims::new(input)
    }
}
impl<S: NumLimits, D: NumLimits> From<Vec<Tensor<S>>> for THVec<D> {
    fn from(input: Vec<Tensor<S>>) -> Self {
        /*
        let v = input.iter().flat_map(|d| d.iter()).map(|d| *d).collect();
        THVec::new(2, v)
        */
        unimplemented!()
    }
}
impl From<THVecGeneric> for THVec<u8> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<u8> = input
            .data
            .iter()
            .map(|t| <u8 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}
impl From<THVecGeneric> for THVec<f32> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<f32> = input
            .data
            .iter()
            .map(|t| <f32 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}
impl From<THVecGeneric> for THVec<i64> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<i64> = input
            .data
            .iter()
            .map(|t| <i64 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}

impl<T: NumLimits> From<THVec<T>> for THDims {
    fn from(input: THVec<T>) -> Self {
        THDims::new(input.dims.clone())
    }
}
impl From<THVecGeneric> for THDims {
    fn from(input: THVecGeneric) -> Self {
        THDims::new(input.dims.clone())
    }
}

trait TensorNew<T: NumLimits> {
    fn tensor_new(arg: THDims) -> Tensor<T>;
}

impl<T: NumLimits> TensorNew<T> for Tensor<T> {
    #[allow(unused_variables)]
    default fn tensor_new(arg: THDims) -> Tensor<T> {
        unreachable!()
    }
}

impl TensorNew<u8> for Tensor<u8> {
    fn tensor_new(arg: THDims) -> Tensor<u8> {
        let t = ::RcMutNew(::tensor::ByteTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<i64> for Tensor<i64> {
    fn tensor_new(arg: THDims) -> Tensor<i64> {
        let t = ::RcMutNew(::tensor::LongTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<f32> for Tensor<f32> {
    fn tensor_new(arg: THDims) -> Tensor<f32> {
        let t = ::RcMutNew(::tensor::FloatTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<f64> for Tensor<f64> {
    fn tensor_new(arg: THDims) -> Tensor<f64> {
        let t = ::RcMutNew(::tensor::DoubleTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}

pub fn byte_tensor<T>(arg: T) -> Tensor<u8>
    where T: Into<THVec<u8>>
{
    tensor(arg)
}
pub fn long_tensor<T>(arg: T) -> Tensor<i64>
    where T: Into<THVec<i64>>
{
    tensor(arg)
}
pub fn float_tensor<T>(arg: T) -> Tensor<f32>
    where T: Into<THVec<f32>>
{
    tensor(arg)
}
pub fn double_tensor<T>(arg: T) -> Tensor<f64>
    where T: Into<THVec<f64>>
{
    tensor(arg)
}
pub fn tensor<S, T>(arg: S) -> Tensor<T>
    where T: NumLimits,
          S: Into<THVec<T>>
{
    let t: THVec<T> = arg.into();
    Tensor::tensor_new(t.into())
}
<|endoftext|>


<commit_before>use std::ops::Deref;

/// `Index` type is arbitrary. Keeping it 32-bits allows for
/// a single 64-bits word per `Handle`.
pub type Index = u32;

/// `Handle` is made up of two field, `index` and `version`. `index` are
/// usually used to indicated address into some kind of space. This value
/// is recycled when an `Handle` is freed to save address. However, this
/// means that you could end up with two different `Handle` with identical
/// indices. We solve this by introducing `version`.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Handle {
    index: Index,
    version: Index,
}

impl Handle {
    /// Constructs a new `Handle`.
    #[inline]
    pub fn new(index: Index, version: Index) -> Self {
        Handle {
            index: index,
            version: version,
        }
    }

    /// Constructs a nil/uninitialized `Handle`.
    #[inline]
    pub fn nil() -> Self {
        Handle {
            index: 0,
            version: 0,
        }
    }

    /// Returns true if this `Handle` has been initialized.
    #[inline]
    pub fn is_valid(&self) -> bool {
        self.index > 0 || self.version > 0
    }

    /// Invalidate this `Handle` to default value.
    #[inline]
    pub fn invalidate(&mut self) {
        self.index = 0;
        self.version = 0;
    }

    /// Returns index value.
    #[inline]
    pub fn index(&self) -> Index {
        self.index
    }

    /// Returns version value.
    #[inline]
    pub fn version(&self) -> Index {
        self.version
    }
}

impl Deref for Handle {
    type Target = Index;

    fn deref(&self) -> &Index {
        &self.index
    }
}

/// `HandleSet` manages the manipulations of a `Handle` collection, which are
/// created with a continuous `index` field. It also have the ability to find
/// out the current status of a specified `Handle`.
pub struct HandleSet {
    versions: Vec<Index>,
    frees: Vec<Index>,
}

impl HandleSet {
    /// Constructs a new, empty `HandleSet`.
    pub fn new() -> HandleSet {
        HandleSet {
            versions: Vec::new(),
            frees: Vec::new(),
        }
    }

    /// Constructs a new `HandleSet` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> HandleSet {
        let versions = Vec::with_capacity(capacity);
        let mut frees = Vec::with_capacity(capacity);
        for i in 0..versions.len() {
            frees.push(i as Index);
        }

        HandleSet {
            versions: versions,
            frees: frees,
        }
    }

    /// Creates a unused `Handle`.
    pub fn create(&mut self) -> Handle {
        if self.frees.len() > 0 {
            // If we have available free slots.
            let index = self.frees.pop().unwrap() as usize;
            self.versions[index] += 1;
            Handle::new(index as Index, self.versions[index])
        } else {
            // Or we just spawn a new index and corresponding version.
            self.versions.push(1);
            Handle::new(self.versions.len() as Index - 1, 1)
        }
    }

    /// Returns true if this `Handle` was created by `HandleSet`, and has not been
    /// freed yet.
    pub fn is_alive(&self, handle: Handle) -> bool {
        let index = handle.index as usize;
        (index < self.versions.len()) && ((self.versions[index] & 0x1) == 1) &&
        (self.versions[index] == handle.version)
    }

    /// Recycles the `Handle` index, and mark its version as dead.
    pub fn free(&mut self, handle: Handle) -> bool {
        if !self.is_alive(handle) {
            false
        } else {
            self.versions[handle.index as usize] += 1;
            self.frees.push(handle.index);
            true
        }
    }

    /// Returns the total number of alive handle in this `HandleSet`.
    pub fn size(&self) -> usize {
        self.versions.len() - self.frees.len()
    }
}

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

    #[test]
    fn basic() {
        let mut h2 = Handle::new(2, 4);
        assert_eq!(h2.index, 2);
        assert_eq!(h2.version, 4);
        assert!(h2.is_valid());
        assert_eq!(*h2, 2);

        h2.invalidate();
        assert_eq!(h2.index, 0);
        assert_eq!(h2.version, 0);
        assert!(!h2.is_valid());
        assert_eq!(*h2, 0);
    }

    #[test]
    fn set() {
        let mut set = HandleSet::new();
        assert_eq!(set.size(), 0);

        // Spawn entities.
        let e1 = set.create();
        assert!(e1.is_valid());
        assert!(set.is_alive(e1));
        assert_eq!(set.size(), 1);

        let mut e2 = e1;
        assert!(set.is_alive(e2));
        assert_eq!(set.size(), 1);

        // Invalidate entities.
        e2.invalidate();
        assert!(!e2.is_valid());
        assert!(!set.is_alive(e2));
        assert!(set.is_alive(e1));

        // Free entities.
        let e2 = e1;
        set.free(e2);
        assert!(!set.is_alive(e2));
        assert!(!set.is_alive(e1));
        assert_eq!(set.size(), 0);
    }

    #[test]
    fn index_reuse() {
        let mut set = HandleSet::new();

        assert_eq!(set.size(), 0);

        let mut v = vec![];
        for _ in 0..10 {
            v.push(set.create());
        }

        assert_eq!(set.size(), 10);
        for e in v.iter() {
            set.free(*e);
        }

        for _ in 0..10 {
            let e = set.create();
            assert!((*e as usize) < v.len());
            assert!(v[*e as usize].version() != e.version());
        }
    }
}
<commit_msg>Handle derive `Hash` trait as default, then we can use it with hashable containers.<commit_after>use std::ops::Deref;

/// `Index` type is arbitrary. Keeping it 32-bits allows for
/// a single 64-bits word per `Handle`.
pub type Index = u32;

/// `Handle` is made up of two field, `index` and `version`. `index` are
/// usually used to indicated address into some kind of space. This value
/// is recycled when an `Handle` is freed to save address. However, this
/// means that you could end up with two different `Handle` with identical
/// indices. We solve this by introducing `version`.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Handle {
    index: Index,
    version: Index,
}

impl Handle {
    /// Constructs a new `Handle`.
    #[inline]
    pub fn new(index: Index, version: Index) -> Self {
        Handle {
            index: index,
            version: version,
        }
    }

    /// Constructs a nil/uninitialized `Handle`.
    #[inline]
    pub fn nil() -> Self {
        Handle {
            index: 0,
            version: 0,
        }
    }

    /// Returns true if this `Handle` has been initialized.
    #[inline]
    pub fn is_valid(&self) -> bool {
        self.index > 0 || self.version > 0
    }

    /// Invalidate this `Handle` to default value.
    #[inline]
    pub fn invalidate(&mut self) {
        self.index = 0;
        self.version = 0;
    }

    /// Returns index value.
    #[inline]
    pub fn index(&self) -> Index {
        self.index
    }

    /// Returns version value.
    #[inline]
    pub fn version(&self) -> Index {
        self.version
    }
}

impl Deref for Handle {
    type Target = Index;

    fn deref(&self) -> &Index {
        &self.index
    }
}

/// `HandleSet` manages the manipulations of a `Handle` collection, which are
/// created with a continuous `index` field. It also have the ability to find
/// out the current status of a specified `Handle`.
pub struct HandleSet {
    versions: Vec<Index>,
    frees: Vec<Index>,
}

impl HandleSet {
    /// Constructs a new, empty `HandleSet`.
    pub fn new() -> HandleSet {
        HandleSet {
            versions: Vec::new(),
            frees: Vec::new(),
        }
    }

    /// Constructs a new `HandleSet` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> HandleSet {
        let versions = Vec::with_capacity(capacity);
        let mut frees = Vec::with_capacity(capacity);
        for i in 0..versions.len() {
            frees.push(i as Index);
        }

        HandleSet {
            versions: versions,
            frees: frees,
        }
    }

    /// Creates a unused `Handle`.
    pub fn create(&mut self) -> Handle {
        if self.frees.len() > 0 {
            // If we have available free slots.
            let index = self.frees.pop().unwrap() as usize;
            self.versions[index] += 1;
            Handle::new(index as Index, self.versions[index])
        } else {
            // Or we just spawn a new index and corresponding version.
            self.versions.push(1);
            Handle::new(self.versions.len() as Index - 1, 1)
        }
    }

    /// Returns true if this `Handle` was created by `HandleSet`, and has not been
    /// freed yet.
    pub fn is_alive(&self, handle: Handle) -> bool {
        let index = handle.index as usize;
        (index < self.versions.len()) && ((self.versions[index] & 0x1) == 1) &&
        (self.versions[index] == handle.version)
    }

    /// Recycles the `Handle` index, and mark its version as dead.
    pub fn free(&mut self, handle: Handle) -> bool {
        if !self.is_alive(handle) {
            false
        } else {
            self.versions[handle.index as usize] += 1;
            self.frees.push(handle.index);
            true
        }
    }

    /// Returns the total number of alive handle in this `HandleSet`.
    pub fn size(&self) -> usize {
        self.versions.len() - self.frees.len()
    }
}

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

    #[test]
    fn basic() {
        let mut h2 = Handle::new(2, 4);
        assert_eq!(h2.index, 2);
        assert_eq!(h2.version, 4);
        assert!(h2.is_valid());
        assert_eq!(*h2, 2);

        h2.invalidate();
        assert_eq!(h2.index, 0);
        assert_eq!(h2.version, 0);
        assert!(!h2.is_valid());
        assert_eq!(*h2, 0);
    }

    #[test]
    fn container() {
        use std::collections::HashSet;
        let h1 = Handle::new(1, 1);
        let h2 = Handle::new(1, 2);
        let h3 = Handle::new(2, 2);
        let h4 = Handle::new(1, 1);

        let mut map = HashSet::new();
        assert_eq!(map.insert(h1), true);
        assert_eq!(map.contains(&h1), true);
        assert_eq!(map.insert(h4), false);
        assert_eq!(map.contains(&h4), true);
        assert_eq!(map.insert(h2), true);
        assert_eq!(map.insert(h3), true);
    }

    #[test]
    fn handle_set() {
        let mut set = HandleSet::new();
        assert_eq!(set.size(), 0);

        // Spawn entities.
        let e1 = set.create();
        assert!(e1.is_valid());
        assert!(set.is_alive(e1));
        assert_eq!(set.size(), 1);

        let mut e2 = e1;
        assert!(set.is_alive(e2));
        assert_eq!(set.size(), 1);

        // Invalidate entities.
        e2.invalidate();
        assert!(!e2.is_valid());
        assert!(!set.is_alive(e2));
        assert!(set.is_alive(e1));

        // Free entities.
        let e2 = e1;
        set.free(e2);
        assert!(!set.is_alive(e2));
        assert!(!set.is_alive(e1));
        assert_eq!(set.size(), 0);
    }

    #[test]
    fn index_reuse() {
        let mut set = HandleSet::new();

        assert_eq!(set.size(), 0);

        let mut v = vec![];
        for _ in 0..10 {
            v.push(set.create());
        }

        assert_eq!(set.size(), 10);
        for e in v.iter() {
            set.free(*e);
        }

        for _ in 0..10 {
            let e = set.create();
            assert!((*e as usize) < v.len());
            assert!(v[*e as usize].version() != e.version());
        }
    }
}
<|endoftext|>


<commit_before>use std::old_io;
use std::str;

use rustc_serialize::json;

use hyper;
use hyper::header;

use url;

use api;

fn make_mixes_url(smart_id: &str) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/mix_sets/{}.json?include=mixes[likes_count]",
                           smart_id).as_slice()).unwrap()
}

fn make_play_token_url() -> url::Url {
    url::Url::parse("http://8tracks.com/sets/new.json").unwrap()
}

fn make_play_url(pt: &api::PlayToken, mix: &api::Mix) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/sets/{}/play.json?mix_id={}",
                            pt.s, mix.id).as_slice()).unwrap()
}

fn make_next_track_url(pt: &api::PlayToken, mix: &api::Mix) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/sets/{}/next.json?mix_id={}",
                            pt.s, mix.id).as_slice()).unwrap()
}

fn make_skip_track_url(pt: &api::PlayToken, mix: &api::Mix) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/sets/{}/skip.json?mix_id={}",
                            pt.s, mix.id).as_slice()).unwrap()
}

fn make_report_url(pt: &api::PlayToken, track_id: u32, mix_id: u32) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/sets/{}/report.json?track_id={}&mix_id={}",
                            pt.s, track_id, mix_id).as_slice()).unwrap()
}

pub fn get_data_from_url_str(s: &str) -> hyper::HttpResult<Vec<u8>> {
    let u = url::Url::parse(s).unwrap();
    get_data_from_url(u)
}

fn get_data_from_url(u: url::Url) -> hyper::HttpResult<Vec<u8>> {
    debug!("fetching data from `{}`", u);
    let cc = header::CacheControl(
        vec![
            header::CacheDirective::Extension(
                "X-Api-Key".to_string(), Some(api::API_KEY.to_string())),
            header::CacheDirective::Extension(
                "X-Api-Version".to_string(), Some(api::API_VERSION.to_string())),
        ]
    );
    let client = hyper::Client::new();
    let response = try!(client.get(u).header(cc).send());
    response.read_to_end().map_err(|io_err| hyper::HttpError::HttpIoError(io_err))
}

fn get_json_from_url(u: url::Url) -> hyper::HttpResult<json::Json> {
    let data = try!(get_data_from_url(u));
    Ok(json::Json::from_str(str::from_utf8(data.as_slice()).unwrap()).unwrap())
}

pub fn get_mix_set(smart_id: &str) -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_mixes_url(smart_id))
}

pub fn get_play_token() -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_play_token_url())
}

pub fn get_play_state(pt: &api::PlayToken, mix: &api::Mix) -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_play_url(pt, mix))
}

pub fn get_next_track(pt: &api::PlayToken, mix: &api::Mix) -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_next_track_url(pt, mix))
}

pub fn get_skip_track(pt: &api::PlayToken, mix: &api::Mix) -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_skip_track_url(pt, mix))
}

/// Ignoring returned json, if it doesn't work, meh
pub fn report_track(pt: &api::PlayToken, track_id: u32, mix_id: u32) {
    let resp = get_json_from_url(make_report_url(pt, track_id, mix_id));
    debug!("reported track, response was {:?}", resp);
}
<commit_msg>use "correct" headers<commit_after>use std::fmt;
use std::old_io;
use std::str;

use rustc_serialize::json;

use hyper;
use hyper::header;

use url;

use api;

#[derive(Clone)]
struct ApiVersionHeader;

impl header::Header for ApiVersionHeader {
    fn header_name() -> &'static str { "X-Api-Version" }
    fn parse_header(raw: &[Vec<u8>]) -> Option<ApiVersionHeader> {
        // TODO fix this up, maybe
        None
    }
}

impl header::HeaderFormat for ApiVersionHeader {
    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", api::API_VERSION)
    }
}

#[derive(Clone)]
struct ApiKeyHeader;

impl header::Header for ApiKeyHeader {
    fn header_name() -> &'static str { "X-Api-Key" }
    fn parse_header(raw: &[Vec<u8>]) -> Option<ApiKeyHeader> {
        // TODO fix this, maybe
        None
    }
}

impl header::HeaderFormat for ApiKeyHeader {
    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", api::API_KEY)
    }
}

fn make_mixes_url(smart_id: &str) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/mix_sets/{}.json?include=mixes[likes_count]",
                           smart_id).as_slice()).unwrap()
}

fn make_play_token_url() -> url::Url {
    url::Url::parse("http://8tracks.com/sets/new.json").unwrap()
}

fn make_play_url(pt: &api::PlayToken, mix: &api::Mix) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/sets/{}/play.json?mix_id={}",
                            pt.s, mix.id).as_slice()).unwrap()
}

fn make_next_track_url(pt: &api::PlayToken, mix: &api::Mix) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/sets/{}/next.json?mix_id={}",
                            pt.s, mix.id).as_slice()).unwrap()
}

fn make_skip_track_url(pt: &api::PlayToken, mix: &api::Mix) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/sets/{}/skip.json?mix_id={}",
                            pt.s, mix.id).as_slice()).unwrap()
}

fn make_report_url(pt: &api::PlayToken, track_id: u32, mix_id: u32) -> url::Url {
    url::Url::parse(format!("http://8tracks.com/sets/{}/report.json?track_id={}&mix_id={}",
                            pt.s, track_id, mix_id).as_slice()).unwrap()
}

pub fn get_data_from_url_str(s: &str) -> hyper::HttpResult<Vec<u8>> {
    let u = url::Url::parse(s).unwrap();
    get_data_from_url(u)
}

fn get_data_from_url(u: url::Url) -> hyper::HttpResult<Vec<u8>> {
    debug!("fetching data from `{}`", u);
    let mut client = hyper::Client::new();
    let mut response = try!(client.get(u)
                            .header(ApiVersionHeader)
                            .header(ApiKeyHeader)
                            .send());
    response.read_to_end().map_err(|io_err| hyper::HttpError::HttpIoError(io_err))
}

fn get_json_from_url(u: url::Url) -> hyper::HttpResult<json::Json> {
    let data = try!(get_data_from_url(u));
    let s = str::from_utf8(&data[]).unwrap();
    debug!("got data: {}", s);
    Ok(json::Json::from_str(s).unwrap())
}

pub fn get_mix_set(smart_id: &str) -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_mixes_url(smart_id))
}

pub fn get_play_token() -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_play_token_url())
}

pub fn get_play_state(pt: &api::PlayToken, mix: &api::Mix) -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_play_url(pt, mix))
}

pub fn get_next_track(pt: &api::PlayToken, mix: &api::Mix) -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_next_track_url(pt, mix))
}

pub fn get_skip_track(pt: &api::PlayToken, mix: &api::Mix) -> hyper::HttpResult<json::Json> {
    get_json_from_url(make_skip_track_url(pt, mix))
}

/// Ignoring returned json, if it doesn't work, meh
pub fn report_track(pt: &api::PlayToken, track_id: u32, mix_id: u32) {
    let resp = get_json_from_url(make_report_url(pt, track_id, mix_id));
    debug!("reported track, response was {:?}", resp);
}
<|endoftext|>