<commit_before>use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
use rustc::hir::*;
use syntax::ast::RangeLimits;
use syntax::source_map::Spanned;
use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then, snippet_opt};
use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
use crate::utils::sugg::Sugg;

/// **What it does:** Checks for calling `.step_by(0)` on iterators,
/// which never terminates.
///
/// **Why is this bad?** This very much looks like an oversight, since with
/// `loop { .. }` there is an obvious better way to endlessly loop.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// for x in (5..5).step_by(0) { .. }
/// ```
declare_clippy_lint! {
    pub ITERATOR_STEP_BY_ZERO,
    correctness,
    "using `Iterator::step_by(0)`, which produces an infinite iterator"
}

/// **What it does:** Checks for zipping a collection with the range of
/// `0.._.len()`.
///
/// **Why is this bad?** The code is better expressed with `.enumerate()`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// x.iter().zip(0..x.len())
/// ```
declare_clippy_lint! {
    pub RANGE_ZIP_WITH_LEN,
    complexity,
    "zipping iterator with a range when `enumerate()` would do"
}

/// **What it does:** Checks for exclusive ranges where 1 is added to the
/// upper bound, e.g. `x..(y+1)`.
///
/// **Why is this bad?** The code is more readable with an inclusive range
/// like `x..=y`.
///
/// **Known problems:** Will add unnecessary pair of parentheses when the
/// expression is not wrapped in a pair but starts with a opening parenthesis
/// and ends with a closing one.
/// I.e: `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
///
/// **Example:**
/// ```rust
/// for x..(y+1) { .. }
/// ```
declare_clippy_lint! {
    pub RANGE_PLUS_ONE,
    complexity,
    "`x..(y+1)` reads better as `x..=y`"
}

/// **What it does:** Checks for inclusive ranges where 1 is subtracted from
/// the upper bound, e.g. `x..=(y-1)`.
///
/// **Why is this bad?** The code is more readable with an exclusive range
/// like `x..y`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// for x..=(y-1) { .. }
/// ```
declare_clippy_lint! {
    pub RANGE_MINUS_ONE,
    complexity,
    "`x..=(y-1)` reads better as `x..y`"
}

#[derive(Copy, Clone)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(ITERATOR_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN, RANGE_PLUS_ONE, RANGE_MINUS_ONE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let ExprKind::MethodCall(ref path, _, ref args) = expr.node {
            let name = path.ident.as_str();

            // Range with step_by(0).
            if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) {
                use crate::consts::{constant, Constant};
                if let Some((Constant::Int(0), _)) = constant(cx, cx.tables, &args[1]) {
                    span_lint(
                        cx,
                        ITERATOR_STEP_BY_ZERO,
                        expr.span,
                        "Iterator::step_by(0) will panic at runtime",
                    );
                }
            } else if name == "zip" && args.len() == 2 {
                let iter = &args[0].node;
                let zip_arg = &args[1];
                if_chain! {
                    // .iter() call
                    if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter;
                    if iter_path.ident.name == "iter";
                    // range expression in .zip() call: 0..x.len()
                    if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
                    if is_integer_literal(start, 0);
                    // .len() call
                    if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.node;
                    if len_path.ident.name == "len" && len_args.len() == 1;
                    // .iter() and .len() called on same Path
                    if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].node;
                    if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].node;
                    if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);
                     then {
                         span_lint(cx,
                                   RANGE_ZIP_WITH_LEN,
                                   expr.span,
                                   &format!("It is more idiomatic to use {}.iter().enumerate()",
                                            snippet(cx, iter_args[0].span, "_")));
                    }
                }
            }
        }

        // exclusive range plus one: x..(y+1)
        if_chain! {
            if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(cx, expr);
            if let Some(y) = y_plus_one(end);
            then {
                span_lint_and_then(
                    cx,
                    RANGE_PLUS_ONE,
                    expr.span,
                    "an inclusive range would be more readable",
                    |db| {
                        let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string());
                        let end = Sugg::hir(cx, y, "y");
                        if let Some(is_wrapped) = &snippet_opt(cx, expr.span) {
                            if is_wrapped.starts_with("(") && is_wrapped.ends_with(")") {
                                db.span_suggestion(expr.span,
                                           "use",
                                           format!("({}..={})", start, end));
                            } else {
                                db.span_suggestion(expr.span,
                                           "use",
                                           format!("{}..={}", start, end));
                            }
                        }
                    },
                );
            }
        }

        // inclusive range minus one: x..=(y-1)
        if_chain! {
            if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr);
            if let Some(y) = y_minus_one(end);
            then {
                span_lint_and_then(
                    cx,
                    RANGE_MINUS_ONE,
                    expr.span,
                    "an exclusive range would be more readable",
                    |db| {
                        let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string());
                        let end = Sugg::hir(cx, y, "y");
                        db.span_suggestion(expr.span,
                                           "use",
                                           format!("{}..{}", start, end));
                    },
                );
            }
        }
    }
}

fn has_step_by(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
    // No need for walk_ptrs_ty here because step_by moves self, so it
    // can't be called on a borrowed range.
    let ty = cx.tables.expr_ty_adjusted(expr);

    get_trait_def_id(cx, &paths::ITERATOR).map_or(false, |iterator_trait| implements_trait(cx, ty, iterator_trait, &[]))
}

fn y_plus_one(expr: &Expr) -> Option<&Expr> {
    match expr.node {
        ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) {
            Some(rhs)
        } else if is_integer_literal(rhs, 1) {
            Some(lhs)
        } else {
            None
        },
        _ => None,
    }
}

fn y_minus_one(expr: &Expr) -> Option<&Expr> {
    match expr.node {
        ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs),
        _ => None,
    }
}
<commit_msg>switched to ticks for chars<commit_after>use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
use rustc::hir::*;
use syntax::ast::RangeLimits;
use syntax::source_map::Spanned;
use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then, snippet_opt};
use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
use crate::utils::sugg::Sugg;

/// **What it does:** Checks for calling `.step_by(0)` on iterators,
/// which never terminates.
///
/// **Why is this bad?** This very much looks like an oversight, since with
/// `loop { .. }` there is an obvious better way to endlessly loop.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// for x in (5..5).step_by(0) { .. }
/// ```
declare_clippy_lint! {
    pub ITERATOR_STEP_BY_ZERO,
    correctness,
    "using `Iterator::step_by(0)`, which produces an infinite iterator"
}

/// **What it does:** Checks for zipping a collection with the range of
/// `0.._.len()`.
///
/// **Why is this bad?** The code is better expressed with `.enumerate()`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// x.iter().zip(0..x.len())
/// ```
declare_clippy_lint! {
    pub RANGE_ZIP_WITH_LEN,
    complexity,
    "zipping iterator with a range when `enumerate()` would do"
}

/// **What it does:** Checks for exclusive ranges where 1 is added to the
/// upper bound, e.g. `x..(y+1)`.
///
/// **Why is this bad?** The code is more readable with an inclusive range
/// like `x..=y`.
///
/// **Known problems:** Will add unnecessary pair of parentheses when the
/// expression is not wrapped in a pair but starts with a opening parenthesis
/// and ends with a closing one.
/// I.e: `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
///
/// **Example:**
/// ```rust
/// for x..(y+1) { .. }
/// ```
declare_clippy_lint! {
    pub RANGE_PLUS_ONE,
    complexity,
    "`x..(y+1)` reads better as `x..=y`"
}

/// **What it does:** Checks for inclusive ranges where 1 is subtracted from
/// the upper bound, e.g. `x..=(y-1)`.
///
/// **Why is this bad?** The code is more readable with an exclusive range
/// like `x..y`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// for x..=(y-1) { .. }
/// ```
declare_clippy_lint! {
    pub RANGE_MINUS_ONE,
    complexity,
    "`x..=(y-1)` reads better as `x..y`"
}

#[derive(Copy, Clone)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(ITERATOR_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN, RANGE_PLUS_ONE, RANGE_MINUS_ONE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let ExprKind::MethodCall(ref path, _, ref args) = expr.node {
            let name = path.ident.as_str();

            // Range with step_by(0).
            if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) {
                use crate::consts::{constant, Constant};
                if let Some((Constant::Int(0), _)) = constant(cx, cx.tables, &args[1]) {
                    span_lint(
                        cx,
                        ITERATOR_STEP_BY_ZERO,
                        expr.span,
                        "Iterator::step_by(0) will panic at runtime",
                    );
                }
            } else if name == "zip" && args.len() == 2 {
                let iter = &args[0].node;
                let zip_arg = &args[1];
                if_chain! {
                    // .iter() call
                    if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter;
                    if iter_path.ident.name == "iter";
                    // range expression in .zip() call: 0..x.len()
                    if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
                    if is_integer_literal(start, 0);
                    // .len() call
                    if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.node;
                    if len_path.ident.name == "len" && len_args.len() == 1;
                    // .iter() and .len() called on same Path
                    if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].node;
                    if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].node;
                    if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);
                     then {
                         span_lint(cx,
                                   RANGE_ZIP_WITH_LEN,
                                   expr.span,
                                   &format!("It is more idiomatic to use {}.iter().enumerate()",
                                            snippet(cx, iter_args[0].span, "_")));
                    }
                }
            }
        }

        // exclusive range plus one: x..(y+1)
        if_chain! {
            if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(cx, expr);
            if let Some(y) = y_plus_one(end);
            then {
                span_lint_and_then(
                    cx,
                    RANGE_PLUS_ONE,
                    expr.span,
                    "an inclusive range would be more readable",
                    |db| {
                        let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string());
                        let end = Sugg::hir(cx, y, "y");
                        if let Some(is_wrapped) = &snippet_opt(cx, expr.span) {
                            if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
                                db.span_suggestion(expr.span,
                                           "use",
                                           format!("({}..={})", start, end));
                            } else {
                                db.span_suggestion(expr.span,
                                           "use",
                                           format!("{}..={}", start, end));
                            }
                        }
                    },
                );
            }
        }

        // inclusive range minus one: x..=(y-1)
        if_chain! {
            if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr);
            if let Some(y) = y_minus_one(end);
            then {
                span_lint_and_then(
                    cx,
                    RANGE_MINUS_ONE,
                    expr.span,
                    "an exclusive range would be more readable",
                    |db| {
                        let start = start.map_or("".to_owned(), |x| Sugg::hir(cx, x, "x").to_string());
                        let end = Sugg::hir(cx, y, "y");
                        db.span_suggestion(expr.span,
                                           "use",
                                           format!("{}..{}", start, end));
                    },
                );
            }
        }
    }
}

fn has_step_by(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
    // No need for walk_ptrs_ty here because step_by moves self, so it
    // can't be called on a borrowed range.
    let ty = cx.tables.expr_ty_adjusted(expr);

    get_trait_def_id(cx, &paths::ITERATOR).map_or(false, |iterator_trait| implements_trait(cx, ty, iterator_trait, &[]))
}

fn y_plus_one(expr: &Expr) -> Option<&Expr> {
    match expr.node {
        ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) {
            Some(rhs)
        } else if is_integer_literal(rhs, 1) {
            Some(lhs)
        } else {
            None
        },
        _ => None,
    }
}

fn y_minus_one(expr: &Expr) -> Option<&Expr> {
    match expr.node {
        ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs),
        _ => None,
    }
}
<|endoftext|>


<commit_before>extern crate quickcheck;
extern crate libc;
extern crate lzf;

pub mod sys {
    use libc::{c_uint,c_void};
    use lzf::{LzfError, LzfResult};
    use std::io::Error;

    extern {
        fn lzf_compress(in_data: *const c_void, in_len: c_uint,
                        out_data: *const c_void, out_len: c_uint) -> c_uint;
        fn lzf_decompress(in_data: *const c_void, in_len: c_uint,
                          out_data: *const c_void, out_len: c_uint) -> c_uint;
    }

    pub fn compress(data: &[u8]) -> LzfResult<Vec<u8>> {
        let data_len = data.len();
        let mut out : Vec<u8> = Vec::with_capacity(data_len);

        let result = unsafe { lzf_compress(data.as_ptr() as *const c_void, data_len as c_uint,
        out.as_ptr() as *const c_void, data_len as c_uint) };

        match result {
            0 => Err(LzfError::NoCompressionPossible),
            _ => {
                unsafe { out.set_len(result as usize) };
                Ok(out)
            }
        }
    }

    pub fn decompress(data: &[u8], out_len: usize) -> LzfResult<Vec<u8>> {
        let mut out : Vec<u8> = Vec::with_capacity(out_len);

        let result = unsafe { lzf_decompress(data.as_ptr() as *const c_void, data.len() as c_uint,
        out.as_ptr() as *const c_void, out_len as c_uint) };
        match result {
            0 => {
                match Error::last_os_error().raw_os_error() {
                    Some(7)  => Err(LzfError::BufferTooSmall),
                    Some(22) => Err(LzfError::DataCorrupted),
                    Some(e)  => Err(LzfError::UnknownError(e)),
                    None     => Err(LzfError::UnknownError(0)),
                }
            },
            _ => {
                unsafe { out.set_len(result as usize) };
                Ok(out)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::sys;
    use lzf::LzfError;

    #[test]
    fn test_compress_skips_short() {
        match sys::compress("foo".as_bytes()) {
            Ok(_) => panic!("Compression did _something_, with is wrong for 'foo'"),
            Err(err) => assert_eq!(LzfError::NoCompressionPossible, err)
        }
    }

    #[test]
    fn test_compress_lorem() {
        let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";

        match sys::compress(lorem.as_bytes()) {
            Ok(compressed) => {
                assert_eq!(272, compressed.len())
            }
            Err(err) => panic!("Compression failed with error {:?}", err)
        }
    }

    #[test]
    fn test_compress_decompress_lorem_round() {
        let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";

        let compressed = match sys::compress(lorem.as_bytes()) {
            Ok(c) => c,
            Err(err) => panic!("Compression failed with error {:?}", err)
        };

        match sys::decompress(&compressed, lorem.len()) {
            Ok(decompressed) => {
                assert_eq!(lorem.len(), decompressed.len());
                assert_eq!(lorem.as_bytes(), &decompressed[..]);
            },
            Err(err) => panic!("Decompression failed with error {:?}", err)
        };
    }

    #[test]
    fn test_decompress_fails_with_short_buffer() {
        let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";

        let compressed = match sys::compress(lorem.as_bytes()) {
            Ok(c) => c,
            Err(err) => panic!("Compression failed with error {:?}", err)
        };

        match sys::decompress(&compressed, 10) {
            Ok(_) => panic!("Decompression worked. That should not happen"),
            Err(err) => assert_eq!(LzfError::BufferTooSmall, err)
        }
    }

    #[test]
    fn test_decompress_fails_for_corrupted_data() {
        let lorem = "Lorem ipsum dolor sit amet";

        match sys::decompress(lorem.as_bytes(), lorem.len()) {
            Ok(_) => panic!("Decompression worked. That should not happen"),
            Err(err) => assert_eq!(LzfError::DataCorrupted, err)
        }
    }
}

#[cfg(test)]
mod quickcheck_test {
    use super::sys;
    use quickcheck::{quickcheck, TestResult};
    use lzf::{self, LzfError};

    fn roundtrip_native(data: Vec<u8>) -> TestResult {
        let compr = match sys::compress(&data) {
            Ok(compr) => compr,
            Err(LzfError::NoCompressionPossible) => return TestResult::discard(),
            Err(LzfError::DataCorrupted) => return TestResult::discard(),
            e @ _ => panic!(e),
        };
        let decompr = sys::decompress(&compr, data.len()).unwrap();
        TestResult::from_bool(data == decompr)
    }

    #[test]
    fn qc_native_roundtrip() {
        quickcheck(roundtrip_native as fn(_) -> _);
    }

    fn compare_compress(data: Vec<u8>) -> TestResult {
        let rust_compr = lzf::compress(&data);
        let native_compr = sys::compress(&data);
        TestResult::from_bool(rust_compr == native_compr)
    }

    #[test]
    fn qc_native_matches_rust() {
        quickcheck(compare_compress as fn(_) -> _);
    }

    fn native_compress_rust_decompress(data: Vec<u8>) -> TestResult {
        let compr = match sys::compress(&data) {
            Ok(compr) => compr,
            Err(LzfError::NoCompressionPossible) => return TestResult::discard(),
            Err(LzfError::DataCorrupted) => return TestResult::discard(),
            e @ _ => panic!(e),
        };

        let decompr = lzf::decompress(&compr, data.len()).unwrap();
        TestResult::from_bool(data == decompr)
    }

    fn rust_compress_native_decompress(data: Vec<u8>) -> TestResult {
        let compr = match lzf::compress(&data) {
            Ok(compr) => compr,
            Err(LzfError::NoCompressionPossible) => return TestResult::discard(),
            Err(LzfError::DataCorrupted) => return TestResult::discard(),
            e @ _ => panic!(e),
        };

        let decompr = sys::decompress(&compr, data.len()).unwrap();
        TestResult::from_bool(data == decompr)
    }

    #[test]
    fn qc_native_compress_rust_decompress() {
        quickcheck(native_compress_rust_decompress as fn(_) -> _);
    }

    #[test]
    fn qc_rust_compress_native_decompress() {
        quickcheck(rust_compress_native_decompress as fn(_) -> _);
    }
}
<commit_msg>test: Quickcheck decompression<commit_after>extern crate quickcheck;
extern crate libc;
extern crate lzf;

pub mod sys {
    use libc::{c_uint,c_void};
    use lzf::{LzfError, LzfResult};
    use std::io::Error;

    extern {
        fn lzf_compress(in_data: *const c_void, in_len: c_uint,
                        out_data: *const c_void, out_len: c_uint) -> c_uint;
        fn lzf_decompress(in_data: *const c_void, in_len: c_uint,
                          out_data: *const c_void, out_len: c_uint) -> c_uint;
    }

    pub fn compress(data: &[u8]) -> LzfResult<Vec<u8>> {
        let data_len = data.len();
        let mut out : Vec<u8> = Vec::with_capacity(data_len);

        let result = unsafe { lzf_compress(data.as_ptr() as *const c_void, data_len as c_uint,
        out.as_ptr() as *const c_void, data_len as c_uint) };

        match result {
            0 => Err(LzfError::NoCompressionPossible),
            _ => {
                unsafe { out.set_len(result as usize) };
                Ok(out)
            }
        }
    }

    pub fn decompress(data: &[u8], out_len: usize) -> LzfResult<Vec<u8>> {
        let mut out : Vec<u8> = Vec::with_capacity(out_len);

        let result = unsafe { lzf_decompress(data.as_ptr() as *const c_void, data.len() as c_uint,
        out.as_ptr() as *const c_void, out_len as c_uint) };
        match result {
            0 => {
                match Error::last_os_error().raw_os_error() {
                    Some(7)  => Err(LzfError::BufferTooSmall),
                    Some(22) => Err(LzfError::DataCorrupted),
                    Some(e)  => Err(LzfError::UnknownError(e)),
                    None     => Err(LzfError::UnknownError(0)),
                }
            },
            _ => {
                unsafe { out.set_len(result as usize) };
                Ok(out)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::sys;
    use lzf::LzfError;

    #[test]
    fn test_compress_skips_short() {
        match sys::compress("foo".as_bytes()) {
            Ok(_) => panic!("Compression did _something_, with is wrong for 'foo'"),
            Err(err) => assert_eq!(LzfError::NoCompressionPossible, err)
        }
    }

    #[test]
    fn test_compress_lorem() {
        let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";

        match sys::compress(lorem.as_bytes()) {
            Ok(compressed) => {
                assert_eq!(272, compressed.len())
            }
            Err(err) => panic!("Compression failed with error {:?}", err)
        }
    }

    #[test]
    fn test_compress_decompress_lorem_round() {
        let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";

        let compressed = match sys::compress(lorem.as_bytes()) {
            Ok(c) => c,
            Err(err) => panic!("Compression failed with error {:?}", err)
        };

        match sys::decompress(&compressed, lorem.len()) {
            Ok(decompressed) => {
                assert_eq!(lorem.len(), decompressed.len());
                assert_eq!(lorem.as_bytes(), &decompressed[..]);
            },
            Err(err) => panic!("Decompression failed with error {:?}", err)
        };
    }

    #[test]
    fn test_decompress_fails_with_short_buffer() {
        let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";

        let compressed = match sys::compress(lorem.as_bytes()) {
            Ok(c) => c,
            Err(err) => panic!("Compression failed with error {:?}", err)
        };

        match sys::decompress(&compressed, 10) {
            Ok(_) => panic!("Decompression worked. That should not happen"),
            Err(err) => assert_eq!(LzfError::BufferTooSmall, err)
        }
    }

    #[test]
    fn test_decompress_fails_for_corrupted_data() {
        let lorem = "Lorem ipsum dolor sit amet";

        match sys::decompress(lorem.as_bytes(), lorem.len()) {
            Ok(_) => panic!("Decompression worked. That should not happen"),
            Err(err) => assert_eq!(LzfError::DataCorrupted, err)
        }
    }
}

#[cfg(test)]
mod quickcheck_test {
    use super::sys;
    use quickcheck::{quickcheck, TestResult};
    use lzf::{self, LzfError};

    fn roundtrip_native(data: Vec<u8>) -> TestResult {
        let compr = match sys::compress(&data) {
            Ok(compr) => compr,
            Err(LzfError::NoCompressionPossible) => return TestResult::discard(),
            Err(LzfError::DataCorrupted) => return TestResult::discard(),
            e @ _ => panic!(e),
        };
        let decompr = sys::decompress(&compr, data.len()).unwrap();
        TestResult::from_bool(data == decompr)
    }

    #[test]
    fn qc_native_roundtrip() {
        quickcheck(roundtrip_native as fn(_) -> _);
    }

    fn compare_compress(data: Vec<u8>) -> TestResult {
        let rust_compr = lzf::compress(&data);
        let native_compr = sys::compress(&data);
        TestResult::from_bool(rust_compr == native_compr)
    }

    #[test]
    fn qc_native_matches_rust() {
        quickcheck(compare_compress as fn(_) -> _);
    }

    fn compare_decompress(data: Vec<u8>) -> TestResult {
        let rust_decompr = lzf::decompress(&data, data.len()*2);
        let native_decompr = sys::decompress(&data, data.len()*2);
        TestResult::from_bool(rust_decompr == native_decompr)
    }

    #[test]
    fn qc_native_decompress_matches_rust() {
        quickcheck(compare_decompress as fn(_) -> _);
    }

    fn native_compress_rust_decompress(data: Vec<u8>) -> TestResult {
        let compr = match sys::compress(&data) {
            Ok(compr) => compr,
            Err(LzfError::NoCompressionPossible) => return TestResult::discard(),
            Err(LzfError::DataCorrupted) => return TestResult::discard(),
            e @ _ => panic!(e),
        };

        let decompr = lzf::decompress(&compr, data.len()).unwrap();
        TestResult::from_bool(data == decompr)
    }

    fn rust_compress_native_decompress(data: Vec<u8>) -> TestResult {
        let compr = match lzf::compress(&data) {
            Ok(compr) => compr,
            Err(LzfError::NoCompressionPossible) => return TestResult::discard(),
            Err(LzfError::DataCorrupted) => return TestResult::discard(),
            e @ _ => panic!(e),
        };

        let decompr = sys::decompress(&compr, data.len()).unwrap();
        TestResult::from_bool(data == decompr)
    }

    #[test]
    fn qc_native_compress_rust_decompress() {
        quickcheck(native_compress_rust_decompress as fn(_) -> _);
    }

    #[test]
    fn qc_rust_compress_native_decompress() {
        quickcheck(rust_compress_native_decompress as fn(_) -> _);
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;

// TODO : Using an Observer requires a &mut reference, and should have the "No races!" property:
// TODO : If you hold a &mut ref, no one else can call open/push/shut. Don't let go of that &mut!
// TODO : Probably a good place to insist on RAII... (see ObserverSession)

// observer trait
pub trait Observer {
    type Time;
    type Data;
    fn open(&mut self, time: &Self::Time);   // new punctuation, essentially ...
    fn show(&mut self, data: &Self::Data);   // shows data to the observer.
    fn give(&mut self, data:  Self::Data);   // gives data to the observer.
    fn shut(&mut self, time: &Self::Time);   // indicates that we are done for now.
}

// extension trait for creating an RAII observer session from any observer
pub trait ObserverSessionExt : Observer {
    fn session<'a>(&'a mut self, time: &'a Self::Time) -> ObserverSession<'a, Self>;
    // TODO : Rust doesn't like this; "can't find show()/give()", so probably some type constraints not met?
    // TODO : All those lifetime bounds are just things I put in to try to help, not actually clearly important.
    fn show_at<'a, I: Iterator<Item=&'a Self::Data>>(&'a mut self, time: &'a Self::Time, iter: I) where Self: 'a, Self::Time : 'a;
    fn give_at<'a, I: Iterator<Item=Self::Data>>(&'a mut self, time: &'a Self::Time, iter: I) where Self: 'a, Self::Time : 'a;
}

impl<O: Observer> ObserverSessionExt for O {
    #[inline(always)] fn session<'a>(&'a mut self, time: &'a O::Time) -> ObserverSession<'a, O> {
        self.open(time);
        ObserverSession { observer: self, time: time }
    }
    fn show_at<'a, I: Iterator<Item=&'a O::Data>>(&'a mut self, time: &'a O::Time, iter: I) where Self: 'a, O::Time : 'a, O::Data: 'a {
        let mut session = self.session(time);
        for item in iter { session.show(item); }
    }
    fn give_at<'a, I: Iterator<Item=O::Data>>(&'a mut self, time: &'a O::Time, iter: I) where O: 'a, O::Time : 'a {
        let mut session = self.session(time);
        for item in iter { session.give(item); }
    }}

// Attempt at RAII for observers. Intended to prevent mis-sequencing of open/push/shut.
pub struct ObserverSession<'a, O:Observer+'a> where O::Time: 'a {
    observer:   &'a mut O,
    time:       &'a O::Time,
}

impl<'a, O:Observer> Drop for ObserverSession<'a, O> where O::Time: 'a {
    #[inline(always)] fn drop(&mut self) { self.observer.shut(self.time); }
}

impl<'a, O:Observer> ObserverSession<'a, O> where O::Time: 'a {
    #[inline(always)] pub fn show(&mut self, data: &O::Data) { self.observer.show(data); }
    #[inline(always)] pub fn give(&mut self, data:  O::Data) { self.observer.give(data); }
}

// blanket implementation for Rc'd observers
impl<O: Observer> Observer for Rc<RefCell<O>> {
    type Time = O::Time;
    type Data = O::Data;
    #[inline(always)] fn open(&mut self, time: &O::Time) { self.borrow_mut().open(time); }
    #[inline(always)] fn show(&mut self, data: &O::Data) { self.borrow_mut().show(data); }
    #[inline(always)] fn give(&mut self, data:  O::Data) { self.borrow_mut().give(data); }
    #[inline(always)] fn shut(&mut self, time: &O::Time) { self.borrow_mut().shut(time); }
}

// blanket implementation for Box'd observers
impl<O: ?Sized + Observer> Observer for Box<O> {
    type Time = O::Time;
    type Data = O::Data;
    #[inline(always)] fn open(&mut self, time: &O::Time) { (**self).open(time); }
    #[inline(always)] fn show(&mut self, data: &O::Data) { (**self).show(data); }
    #[inline(always)] fn give(&mut self, data:  O::Data) { (**self).give(data); }
    #[inline(always)] fn shut(&mut self, time: &O::Time) { (**self).shut(time); }
}
// an observer broadcasting to many observers
pub struct BroadcastObserver<O: Observer> {
    observers:  Vec<O>,
}

impl<O: Observer> BroadcastObserver<O> {
    pub fn new() -> BroadcastObserver<O> { BroadcastObserver { observers: Vec::new() }}
    pub fn add(&mut self, observer: O) { self.observers.push(observer); }
}

impl<O: Observer> Observer for BroadcastObserver<O> {
    type Time = O::Time;
    type Data = O::Data;
    #[inline(always)] fn open(&mut self, time: &O::Time) { for observer in self.observers.iter_mut() { observer.open(time); } }
    #[inline(always)] fn show(&mut self, data: &O::Data) { for observer in self.observers.iter_mut() { observer.show(data); } }
    #[inline(always)] fn give(&mut self, data:  O::Data) {
        // TODO : Hand ownership to the last observer
        for index in (0..self.observers.len() - 1) { self.observers[index].show(&data); }
        if self.observers.len() > 0 {
            let last = self.observers.len() - 1;
            self.observers[last].give(data);
        }
    }
    #[inline(always)] fn shut(&mut self, time: &O::Time) { for observer in self.observers.iter_mut() { observer.shut(time); } }
}

// an observer routing between many observers
pub struct ExchangeObserver<O: Observer, H: Fn(&O::Data) -> u64> {
    pub observers:  Vec<O>,
    pub hash_func:  H,
}

impl<O: Observer, H: Fn(&O::Data) -> u64+'static> Observer for ExchangeObserver<O, H> where O::Data : Clone {
    type Time = O::Time;
    type Data = O::Data;
    #[inline(always)] fn open(&mut self, time: &O::Time) -> () { for observer in self.observers.iter_mut() { observer.open(time); } }
    #[inline(always)] fn show(&mut self, data: &O::Data) -> () {
        let dst = (self.hash_func)(data) % self.observers.len() as u64;
        self.observers[dst as usize].show(data);
    }
    #[inline(always)] fn give(&mut self, data:  O::Data) -> () {
        let dst = (self.hash_func)(&data) % self.observers.len() as u64;
        self.observers[dst as usize].give(data);
    }
    #[inline(always)] fn shut(&mut self, time: &O::Time) -> () { for observer in self.observers.iter_mut() { observer.shut(time); } }
}

// an observer buffering records before sending
pub struct BufferedObserver<D, O: Observer> {
    limit:      u64,
    buffer:     Vec<D>,
    observer:   O,
}

impl<D, O: Observer<Data = Vec<D>>> BufferedObserver<D, O> {
    pub fn inner(&self) -> &O { &self.observer }
    pub fn inner_mut(&mut self) -> &mut O { &mut self.observer }
    pub fn new(limit: u64, observer: O) -> BufferedObserver<D, O> {
        BufferedObserver {
            limit: limit,
            buffer: Vec::with_capacity(limit as usize),
            observer: observer,
        }
    }
}

// TODO : These clones are really expensive. Hard to avoid, because we can't stash references.
impl<D: Clone+'static, O: Observer<Data = Vec<D>>> Observer for BufferedObserver<D, O> {
    type Time = O::Time;
    type Data = D;
    #[inline(always)] fn open(&mut self, time: &O::Time) { self.observer.open(time); }
    #[inline(always)] fn show(&mut self, data: &D) { self.give(data.clone()); }
    #[inline(always)] fn give(&mut self, data:  D) {
        self.buffer.push(data);
        if self.buffer.len() as u64 > self.limit {
            self.observer.show(&mut self.buffer);
            self.buffer.clear();
        }
    }
    #[inline(always)] fn shut(&mut self, time: &O::Time) {
        if self.buffer.len() > 0 {
            self.observer.show(&self.buffer);
            self.buffer.clear();
        }
        self.observer.shut(time);
    }
}

// dual to BufferedObserver, flattens out buffers
pub struct FlattenedObserver<O: Observer> {
    observer:   O,
}

impl<O: Observer> FlattenedObserver<O> {
    pub fn new(observer: O) -> FlattenedObserver<O> { FlattenedObserver { observer: observer }}
}

impl<O: Observer> Observer for FlattenedObserver<O> {
    type Time = O::Time;
    type Data = Vec<O::Data>;
    #[inline(always)] fn open(&mut self, time: &O::Time) -> () { self.observer.open(time); }
    #[inline(always)] fn show(&mut self, data: &Vec<O::Data>) -> () { for datum in data { self.observer.show(datum); } }
    #[inline(always)] fn give(&mut self, data:  Vec<O::Data>) -> () { for datum in data { self.observer.give(datum); } }
    #[inline(always)] fn shut(&mut self, time: &O::Time) -> () { self.observer.shut(time); }
}

// // discriminated union of two observers
// pub enum ObserverPair<O1: Observer, O2: Observer> {
//     Type1(O1),
//     Type2(O2),
// }
//
// impl<T, D, O1: Observer<Time=T, Data=D>, O2: Observer<Time=T, Data=D>> Observer for ObserverPair<O1, O2> {
//     type Time = T;
//     type Data = D;
//     #[inline(always)]
//     fn open(&mut self, time: &T) {
//         match *self {
//             ObserverPair::Type1(ref mut observer) => observer.open(time),
//             ObserverPair::Type2(ref mut observer) => observer.open(time),
//         }
//     }
//     #[inline(always)]
//     fn push(&mut self, data: &D) {
//         match *self {
//             ObserverPair::Type1(ref mut observer) => observer.push(data),
//             ObserverPair::Type2(ref mut observer) => observer.push(data),
//         }
//     }
//     #[inline(always)]
//     fn shut(&mut self, time: &T) {
//         match *self {
//             ObserverPair::Type1(ref mut observer) => observer.shut(time),
//             ObserverPair::Type2(ref mut observer) => observer.shut(time),
//         }
//     }
// }
<commit_msg>simplified show_at and give_at<commit_after>use std::rc::Rc;
use std::cell::RefCell;

// TODO : Using an Observer requires a &mut reference, and should have the "No races!" property:
// TODO : If you hold a &mut ref, no one else can call open/push/shut. Don't let go of that &mut!
// TODO : Probably a good place to insist on RAII... (see ObserverSession)

// observer trait
pub trait Observer {
    type Time;
    type Data;
    fn open(&mut self, time: &Self::Time);   // new punctuation, essentially ...
    fn show(&mut self, data: &Self::Data);   // shows data to the observer.
    fn give(&mut self, data:  Self::Data);   // gives data to the observer.
    fn shut(&mut self, time: &Self::Time);   // indicates that we are done for now.
}

// extension trait for creating an RAII observer session from any observer
pub trait ObserverSessionExt : Observer {
    fn session<'a>(&'a mut self, time: &'a Self::Time) -> ObserverSession<'a, Self>;
    fn show_at<'a, I: Iterator<Item=&'a Self::Data>>(&mut self, time: &Self::Time, iter: I) where Self::Data: 'a;
    fn give_at<I: Iterator<Item=Self::Data>>(&mut self, time: &Self::Time, iter: I);
}

impl<O: Observer> ObserverSessionExt for O {
    #[inline(always)] fn session<'a>(&'a mut self, time: &'a O::Time) -> ObserverSession<'a, O> {
        self.open(time);
        ObserverSession { observer: self, time: time }
    }
    fn show_at<'a, I: Iterator<Item=&'a O::Data>>(&mut self, time: &O::Time, iter: I) where O::Data: 'a {
        self.open(time);
        for item in iter { self.show(item); }
        self.shut(time);
    }
    fn give_at<I: Iterator<Item=O::Data>>(&mut self, time: &O::Time, iter: I) {
        self.open(time);
        for item in iter { self.give(item); }
        self.shut(time);
    }}

// Attempt at RAII for observers. Intended to prevent mis-sequencing of open/push/shut.
pub struct ObserverSession<'a, O:Observer+'a> where O::Time: 'a {
    observer:   &'a mut O,
    time:       &'a O::Time,
}

impl<'a, O:Observer> Drop for ObserverSession<'a, O> where O::Time: 'a {
    #[inline(always)] fn drop(&mut self) { self.observer.shut(self.time); }
}

impl<'a, O:Observer> ObserverSession<'a, O> where O::Time: 'a {
    #[inline(always)] pub fn show(&mut self, data: &O::Data) { self.observer.show(data); }
    #[inline(always)] pub fn give(&mut self, data:  O::Data) { self.observer.give(data); }
}

// blanket implementation for Rc'd observers
impl<O: Observer> Observer for Rc<RefCell<O>> {
    type Time = O::Time;
    type Data = O::Data;
    #[inline(always)] fn open(&mut self, time: &O::Time) { self.borrow_mut().open(time); }
    #[inline(always)] fn show(&mut self, data: &O::Data) { self.borrow_mut().show(data); }
    #[inline(always)] fn give(&mut self, data:  O::Data) { self.borrow_mut().give(data); }
    #[inline(always)] fn shut(&mut self, time: &O::Time) { self.borrow_mut().shut(time); }
}

// blanket implementation for Box'd observers
impl<O: ?Sized + Observer> Observer for Box<O> {
    type Time = O::Time;
    type Data = O::Data;
    #[inline(always)] fn open(&mut self, time: &O::Time) { (**self).open(time); }
    #[inline(always)] fn show(&mut self, data: &O::Data) { (**self).show(data); }
    #[inline(always)] fn give(&mut self, data:  O::Data) { (**self).give(data); }
    #[inline(always)] fn shut(&mut self, time: &O::Time) { (**self).shut(time); }
}
// an observer broadcasting to many observers
pub struct BroadcastObserver<O: Observer> {
    observers:  Vec<O>,
}

impl<O: Observer> BroadcastObserver<O> {
    pub fn new() -> BroadcastObserver<O> { BroadcastObserver { observers: Vec::new() }}
    pub fn add(&mut self, observer: O) { self.observers.push(observer); }
}

impl<O: Observer> Observer for BroadcastObserver<O> {
    type Time = O::Time;
    type Data = O::Data;
    #[inline(always)] fn open(&mut self, time: &O::Time) { for observer in self.observers.iter_mut() { observer.open(time); } }
    #[inline(always)] fn show(&mut self, data: &O::Data) { for observer in self.observers.iter_mut() { observer.show(data); } }
    #[inline(always)] fn give(&mut self, data:  O::Data) {
        // TODO : Hand ownership to the last observer
        for index in (0..self.observers.len() - 1) { self.observers[index].show(&data); }
        if self.observers.len() > 0 {
            let last = self.observers.len() - 1;
            self.observers[last].give(data);
        }
    }
    #[inline(always)] fn shut(&mut self, time: &O::Time) { for observer in self.observers.iter_mut() { observer.shut(time); } }
}

// an observer routing between many observers
pub struct ExchangeObserver<O: Observer, H: Fn(&O::Data) -> u64> {
    pub observers:  Vec<O>,
    pub hash_func:  H,
}

impl<O: Observer, H: Fn(&O::Data) -> u64+'static> Observer for ExchangeObserver<O, H> where O::Data : Clone {
    type Time = O::Time;
    type Data = O::Data;
    #[inline(always)] fn open(&mut self, time: &O::Time) -> () { for observer in self.observers.iter_mut() { observer.open(time); } }
    #[inline(always)] fn show(&mut self, data: &O::Data) -> () {
        let dst = (self.hash_func)(data) % self.observers.len() as u64;
        self.observers[dst as usize].show(data);
    }
    #[inline(always)] fn give(&mut self, data:  O::Data) -> () {
        let dst = (self.hash_func)(&data) % self.observers.len() as u64;
        self.observers[dst as usize].give(data);
    }
    #[inline(always)] fn shut(&mut self, time: &O::Time) -> () { for observer in self.observers.iter_mut() { observer.shut(time); } }
}

// an observer buffering records before sending
pub struct BufferedObserver<D, O: Observer> {
    limit:      u64,
    buffer:     Vec<D>,
    observer:   O,
}

impl<D, O: Observer<Data = Vec<D>>> BufferedObserver<D, O> {
    pub fn inner(&self) -> &O { &self.observer }
    pub fn inner_mut(&mut self) -> &mut O { &mut self.observer }
    pub fn new(limit: u64, observer: O) -> BufferedObserver<D, O> {
        BufferedObserver {
            limit: limit,
            buffer: Vec::with_capacity(limit as usize),
            observer: observer,
        }
    }
}

// TODO : These clones are really expensive. Hard to avoid, because we can't stash references.
impl<D: Clone+'static, O: Observer<Data = Vec<D>>> Observer for BufferedObserver<D, O> {
    type Time = O::Time;
    type Data = D;
    #[inline(always)] fn open(&mut self, time: &O::Time) { self.observer.open(time); }
    #[inline(always)] fn show(&mut self, data: &D) { self.give(data.clone()); }
    #[inline(always)] fn give(&mut self, data:  D) {
        self.buffer.push(data);
        if self.buffer.len() as u64 > self.limit {
            self.observer.show(&mut self.buffer);
            self.buffer.clear();
        }
    }
    #[inline(always)] fn shut(&mut self, time: &O::Time) {
        if self.buffer.len() > 0 {
            self.observer.show(&self.buffer);
            self.buffer.clear();
        }
        self.observer.shut(time);
    }
}

// dual to BufferedObserver, flattens out buffers
pub struct FlattenedObserver<O: Observer> {
    observer:   O,
}

impl<O: Observer> FlattenedObserver<O> {
    pub fn new(observer: O) -> FlattenedObserver<O> { FlattenedObserver { observer: observer }}
}

impl<O: Observer> Observer for FlattenedObserver<O> {
    type Time = O::Time;
    type Data = Vec<O::Data>;
    #[inline(always)] fn open(&mut self, time: &O::Time) -> () { self.observer.open(time); }
    #[inline(always)] fn show(&mut self, data: &Vec<O::Data>) -> () { for datum in data { self.observer.show(datum); } }
    #[inline(always)] fn give(&mut self, data:  Vec<O::Data>) -> () { for datum in data { self.observer.give(datum); } }
    #[inline(always)] fn shut(&mut self, time: &O::Time) -> () { self.observer.shut(time); }
}

// // discriminated union of two observers
// pub enum ObserverPair<O1: Observer, O2: Observer> {
//     Type1(O1),
//     Type2(O2),
// }
//
// impl<T, D, O1: Observer<Time=T, Data=D>, O2: Observer<Time=T, Data=D>> Observer for ObserverPair<O1, O2> {
//     type Time = T;
//     type Data = D;
//     #[inline(always)]
//     fn open(&mut self, time: &T) {
//         match *self {
//             ObserverPair::Type1(ref mut observer) => observer.open(time),
//             ObserverPair::Type2(ref mut observer) => observer.open(time),
//         }
//     }
//     #[inline(always)]
//     fn push(&mut self, data: &D) {
//         match *self {
//             ObserverPair::Type1(ref mut observer) => observer.push(data),
//             ObserverPair::Type2(ref mut observer) => observer.push(data),
//         }
//     }
//     #[inline(always)]
//     fn shut(&mut self, time: &T) {
//         match *self {
//             ObserverPair::Type1(ref mut observer) => observer.shut(time),
//             ObserverPair::Type2(ref mut observer) => observer.shut(time),
//         }
//     }
// }
<|endoftext|>


<commit_before>#![crate_id="fibonacci#1.1"]
#![crate_type = "lib"]
#![license = "MIT"]
#![desc = "Fibonacci library" ]
#![comment = "Example of library: compute Fibonacci"]
#![deny(missing_doc)]
//! Compute fibonacci.
//!
//! The Fibonacci sequence is a sequence of numbers starting with 0 and 1 where every subsequent number is the sum of the previous two numbers.
//!
//! @license MIT license <http://www.opensource.org/licenses/mit-license.php>
//!
//! @author Eliovir <http://github.com/~eliovir>

extern crate test;

#[cfg(test)]
use test::Bencher;

/**
* Calcule les elements de la suite de Fibonnaci.
*
* REGLE RG024 Le projet permet de calculer les membres de la Suite de
* Fibonacci.
*
* REGLE RG024.1 : f(1) = 1
* REGLE RG024.2 : f(2) = 1
*
* REGLE RG024.3 : f(n) = f(n-1) + f(n-2) si n > 2
*
* REGLE RG024.4 : il n'est pas possible de calculer la valeur de la Suite
* de Fibonacci pour un rang negatif.
*
* REGLE RG024.5 : le calcul de n'importe quel element de la Suite de
* Fibonacci doit s'effectuer en moins de deux secondes.
*
* REGLE RG024.6 : le calcul de n'importe quel element de la Suite de
* Fibonacci, pour un rang inferieur a 50, doit s'effectuer en moins d'une
* seconde.
*
* @param n le rang pour lequel on calcule le membre.
* @return Le membre de rang n dans la Suite.
*/
pub fn fibonacci_reccursive(n: int) -> uint {
	if n < 0 {
		fail!("{:d} is negative!", n);
	}
	match n {
		0     => fail!("zero is not a right argument to fibonacci_reccursive()!"),
		1 | 2 => 1,
		3     => 2,
		/*
		50    => 12586269025,
		*/
		_     => fibonacci(n - 1) + fibonacci(n - 2)
	}
}

/**
 * Non reccursive function.
 */
pub fn fibonacci(n: int) -> uint {
	if n < 0 {
		fail!("{:d} is negative!", n);
	} else if n == 0 {
		fail!("zero is not a right argument to fibonacci()!");
	} else if n == 1 {
		return 1u;
	}
	let mut i = 0;
	let mut sum = 0;
	let mut last = 0;
	let mut curr = 1;
	while i < n - 1 {
		sum = last + curr;
		last = curr;
		curr = sum;
		i += 1;
	}
	sum
}

/*
#[cfg(test)]
mod tests {
}
*/
#[cfg(test)]
fn RG024_x(n: int, expected: uint) {
	let mut found = fibonacci_reccursive(n);
	assert!(expected == found, format!("fibibonacci_reccursive({:d}): expected ({:u}) != found ({:u})", n, expected, found));
	found = fibonacci(n);
	assert!(expected == found, format!("fibibonacci({:d}): expected ({:u}) != found ({:u})", n, expected, found));
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.1 : f(1) = 1
 */
#[test]
fn RG024_1() {
	RG024_x(1, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.2 : f(2) = 1
 */
#[test]
fn RG024_2() {
	RG024_x(2, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.3.a : f(3) = 2
 */
#[test]
fn RG024_3_a() {
	RG024_x(3, 2);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.4.a : il n'est pas possible de calculer la valeur de la Suite
 * de Fibonacci pour un rang negatif ou nul.
 */
#[test]
#[should_fail]
fn RG024_4_a() {
	fibonacci(-1);
	fibonacci(0);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.5 : f(55) = 139583862445
 */
#[test]
fn RG024_5() {
	/*RG024_x(55, 139583862445);*/
	RG024_x(30, 832040);
}
#[bench]
fn bench_fibonacci_reccursive_20(b: &mut Bencher) {
	b.iter(|| {
		fibonacci_reccursive(20);
	});
}
#[bench]
fn bench_fibonacci_20(b: &mut Bencher) {
	b.iter(|| {
		fibonacci(20);
	});
}
<commit_msg>fibonacci.rs : add Iterator example<commit_after>#![crate_id="fibonacci#1.1"]
#![crate_type = "lib"]
#![license = "MIT"]
#![desc = "Fibonacci library" ]
#![comment = "Example of library: compute Fibonacci"]
#![deny(missing_doc)]
//! Compute fibonacci.
//!
//! The Fibonacci sequence is a sequence of numbers starting with 0 and 1 where every subsequent number is the sum of the previous two numbers.
//!
//! @license MIT license <http://www.opensource.org/licenses/mit-license.php>
//!
//! @author Eliovir <http://github.com/~eliovir>

extern crate test;

use std::mem::replace;

#[cfg(test)]
use test::Bencher;

// bench: find the `BENCH_SIZE` first terms of the fibonacci sequence
#[cfg(test)]
static BENCH_SIZE: uint = 20;
#[cfg(test)]
static BENCH_SIZE_INT: int = 20;

/**
* Calcule les elements de la suite de Fibonnaci.
*
* REGLE RG024 Le projet permet de calculer les membres de la Suite de
* Fibonacci.
*
* REGLE RG024.1 : f(1) = 1
* REGLE RG024.2 : f(2) = 1
*
* REGLE RG024.3 : f(n) = f(n-1) + f(n-2) si n > 2
*
* REGLE RG024.4 : il n'est pas possible de calculer la valeur de la Suite
* de Fibonacci pour un rang negatif.
*
* REGLE RG024.5 : le calcul de n'importe quel element de la Suite de
* Fibonacci doit s'effectuer en moins de deux secondes.
*
* REGLE RG024.6 : le calcul de n'importe quel element de la Suite de
* Fibonacci, pour un rang inferieur a 50, doit s'effectuer en moins d'une
* seconde.
*
* @param n le rang pour lequel on calcule le membre.
* @return Le membre de rang n dans la Suite.
*/
pub fn fibonacci_reccursive(n: int) -> uint {
	if n < 0 {
		fail!("{:d} is negative!", n);
	}
	match n {
		0     => fail!("zero is not a right argument to fibonacci_reccursive()!"),
		1 | 2 => 1,
		3     => 2,
		/*
		50    => 12586269025,
		*/
		_     => fibonacci(n - 1) + fibonacci(n - 2)
	}
}

/**
 * Non reccursive function.
 */
pub fn fibonacci(n: int) -> uint {
	if n < 0 {
		fail!("{:d} is negative!", n);
	} else if n == 0 {
		fail!("zero is not a right argument to fibonacci()!");
	} else if n == 1 {
		return 1u;
	}
	let mut i = 0;
	let mut sum = 0;
	let mut last = 0;
	let mut curr = 1;
	while i < n - 1 {
		sum = last + curr;
		last = curr;
		curr = sum;
		i += 1;
	}
	sum
}

/**
 * Iiterative fibonacci
 * https://github.com/japaric/rust-by-example
 */
pub struct Fibonacci {
	curr: uint,
	next: uint,
}

impl Iterator<uint> for Fibonacci {
	fn next(&mut self) -> Option<uint> {
		let new_next = self.curr + self.next;
		let new_curr = replace(&mut self.next, new_next);

		Some(replace(&mut self.curr, new_curr))
	}
}

/**
 * A "constructor" for Iiterative fibonacci
 */
pub fn iterative_fibonacci() -> Fibonacci {
	Fibonacci { curr: 1, next: 1 }
}

#[cfg(test)]
fn RG024_x(n: int, expected: uint) {
	let mut found = fibonacci_reccursive(n);
	assert!(expected == found, format!("fibibonacci_reccursive({:d}): expected ({:u}) != found ({:u})", n, expected, found));
	found = fibonacci(n);
	assert!(expected == found, format!("fibibonacci({:d}): expected ({:u}) != found ({:u})", n, expected, found));
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.1 : f(1) = 1
 */
#[test]
fn RG024_1() {
	RG024_x(1, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.2 : f(2) = 1
 */
#[test]
fn RG024_2() {
	RG024_x(2, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.3.a : f(3) = 2
 */
#[test]
fn RG024_3_a() {
	RG024_x(3, 2);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.4.a : il n'est pas possible de calculer la valeur de la Suite
 * de Fibonacci pour un rang negatif ou nul.
 */
#[test]
#[should_fail]
fn RG024_4_a() {
	fibonacci(-1);
	fibonacci(0);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.5 : f(55) = 139583862445
 */
#[test]
fn RG024_5() {
	/*RG024_x(55, 139583862445);*/
	RG024_x(30, 832040);
}
#[bench]
fn bench_fibonacci_reccursive(b: &mut Bencher) {
	b.iter(|| {
		fibonacci_reccursive(BENCH_SIZE_INT);
	});
}
#[bench]
fn bench_fibonacci(b: &mut Bencher) {
	b.iter(|| {
		fibonacci(BENCH_SIZE_INT);
	});
}
#[bench]
fn bench_iterative_fibonacci(b: &mut Bencher) {
	b.iter(|| {
		// http://static.rust-lang.org/doc/master/std/iter/trait.Iterator.html#method.take
		iterative_fibonacci().take(BENCH_SIZE).last().unwrap()
		//iterative_fibonacci().take(BENCH_SIZE).collect::<Vec<uint>>()
	})
}
<|endoftext|>


<commit_before>use crate::spec::{LinkerFlavor, Target, TargetResult, PanicStrategy};

pub fn target() -> TargetResult {
    let mut base = super::windows_msvc_base::opts();
    base.max_atomic_width = Some(64);
    base.has_elf_tls = true;

    // FIXME: this shouldn't be panic=abort, it should be panic=unwind
    base.panic_strategy = PanicStrategy::Abort;

    Ok(Target {
        llvm_target: "aarch64-pc-windows-msvc".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "64".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
        arch: "aarch64".to_string(),
        target_os: "windows".to_string(),
        target_env: "msvc".to_string(),
        target_vendor: "pc".to_string(),
        linker_flavor: LinkerFlavor::Msvc,
        options: base,
    })
}
<commit_msg>Rollup merge of #66711 - mattico:aarch-msvc-fp, r=nagisa<commit_after>use crate::spec::{LinkerFlavor, Target, TargetResult, PanicStrategy};

pub fn target() -> TargetResult {
    let mut base = super::windows_msvc_base::opts();
    base.max_atomic_width = Some(64);
    base.has_elf_tls = true;
    base.features = "+neon,+fp-armv8".to_string();

    // FIXME: this shouldn't be panic=abort, it should be panic=unwind
    base.panic_strategy = PanicStrategy::Abort;

    Ok(Target {
        llvm_target: "aarch64-pc-windows-msvc".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "64".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
        arch: "aarch64".to_string(),
        target_os: "windows".to_string(),
        target_env: "msvc".to_string(),
        target_vendor: "pc".to_string(),
        linker_flavor: LinkerFlavor::Msvc,
        options: base,
    })
}
<|endoftext|>


<commit_before>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::BufferedStream;
use std::string::String;

fn main () {

    let listener = TcpListener::bind("127.0.0.1", 8099).unwrap();
    let mut acceptor = listener.listen().unwrap();

    fn handle_client(mut stream: BufferedStream<TcpStream>) {

        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }
            body = body + cur_line + "
";
            if cur_line.len() == 2 { // TODO: make this check for \n\n explicitly
                break;
            }
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\n").unwrap(); // byte literal
        stream.write(b"Content-type: text/html\n").unwrap();
        stream.write(b"X-header: from bytes\n");
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\n\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<commit_msg>add .unwrap() to remove warning<commit_after>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::BufferedStream;
use std::string::String;

fn main () {

    let listener = TcpListener::bind("127.0.0.1", 8099).unwrap();
    let mut acceptor = listener.listen().unwrap();

    fn handle_client(mut stream: BufferedStream<TcpStream>) {

        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }
            body = body + cur_line + "
";
            if cur_line.len() == 2 { // TODO: make this check for \n\n explicitly
                break;
            }
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\n").unwrap(); // byte literal
        stream.write(b"Content-type: text/html\n").unwrap();
        stream.write(b"X-header: from bytes\n").unwrap();
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\n\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<|endoftext|>


<commit_before>extern crate "rust-crypto" as rust_crypto;
extern crate serialize;

use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::{File, BufferedStream};
use std::string::String;
use std::os;
use std::vec::Vec;

use rust_crypto::sha1::Sha1;
use rust_crypto::digest::Digest;
use serialize::base64::{ToBase64, STANDARD};

use std::io::Timer;
use std::io::timer;
use std::time::duration::Duration;

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const COLON: u8 = b':';
pub const CRLF: &'static [u8] = &[CR,LF];

struct RequestedRoute {
    method: String,
    pathname: String
}

struct ClientHeader {
    key: String,
    value: String
}

enum Payload {
    Text(String),
    Binary(Vec<u8>),
    Empty
}

enum Opcode {
    EmptyOp = 0x0,
    TextOp = 0x1,
    BinaryOp = 0x2,
    CloseOp = 0x8,
}

struct Message {
    payload: Payload,
    opcode: Opcode,
    fin: u8
 }

impl Message {

    fn from_payload (payload: Payload, fin: u8) -> Message {
        let opcode: Opcode = match payload {
            Payload::Text(_) => Opcode::TextOp,
            Payload::Binary(_) => Opcode::BinaryOp,
            Payload::Empty => Opcode::EmptyOp
        };
        return Message {payload: payload, opcode: opcode, fin: fin};
    }

    fn continue_from_payload (payload: Payload) -> Message {
        let opcode = Opcode::EmptyOp;
        let fin = 0x0;
        return Message {payload: payload, opcode: opcode, fin: fin};
    }

    fn send (&self,
            mut stream: &mut BufferedStream<TcpStream>) {
        let msg = match self.payload {
            Payload::Text(ref s) => s.as_bytes(),
            Payload::Binary(ref s) => s.as_slice(),
            Payload::Empty => "".as_bytes(),
        };

        let length = msg.len() as u8;

        println!("fin: {}, msg: {}, opcode: {}", self.fin, msg, self.opcode as u8);

        stream.write_u8(self.fin | self.opcode as u8).unwrap();
        stream.write_u8(length).unwrap();
        stream.write(msg).unwrap();
        stream.flush();
    }

    fn from_buffer (buf: &[u8]) {
        let fin = buf[0] & 0b1000_0000;
        let rsv = buf[0] & 0b0111_0000;
        let opc = buf[0] & 0b0000_1111;
        let msk = buf[0] & 0b0000_0001;
        let len = (buf[1] & 0b0111_1111) as uint;
        let mskkey = buf.slice(2, 6);

        let mut msg = Vec::new();
        for ii in range(0u, len) {
            let ch = mskkey[ii % 4] ^ buf[6 + ii];
            msg.push(ch);
        }

        println!(
            "fin {}, rsv {}, msk {}, opcode {}, len {}, mskkey {}, msg {}, \nbuf {}",
            fin, rsv, msk, opc, len, mskkey, String::from_utf8(msg),  buf.as_slice());
    }

    fn from_stream(mut stream: &mut BufferedStream<TcpStream>) -> Message {
        let cur_byte: u8 = stream.read_byte().unwrap();

        let fin = cur_byte & 0b1000_0000;
        let rsv = cur_byte & 0b0111_0000;
        let opc = cur_byte & 0b0000_1111;
        let msk = cur_byte & 0b0000_0001;

        let cur_byte: u8 = stream.read_byte().unwrap();
        let len = (cur_byte & 0b0111_1111) as uint;

        let mskkey = stream.read_exact(4).unwrap();

        let mut msg = Vec::new();
        for ii in range(0u, len) {
            let cur_byte: u8 = stream.read_byte().unwrap();
            let ch = mskkey[ii % 4] ^ cur_byte;
            msg.push(ch);
        }

        let utf8_msg = match String::from_utf8(msg) {
            Ok(m) => m,
            Err(_) => panic!("I don't know how to ut8 that")
        };

        println!(
            "fin {}, rsv {}, msk {}, opcode {}, len {}, mskkey {}, msg {}",
            fin, rsv, msk, opc, len, mskkey, utf8_msg);

        let payload = Payload::Text(utf8_msg);
        return Message::from_payload(payload, fin);
    }
}

fn get_header_by_name (header: &[u8], headers: &Vec<ClientHeader>) -> String {
    let mut result = String::new();

    for h in headers.iter() {
        if h.key.as_bytes() == header {
            result = h.value.clone();
            break;
        }
    }

    return result;
}

fn parse_request_line (header: &str) -> RequestedRoute {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    return RequestedRoute {method: method, pathname: pathname};
}

fn parse_normal_header (header: &str) -> ClientHeader {
    let mut lhs = String::new(); // lhs of ':' in header
    let mut rhs = String::new(); // rhs of ':' in header
    let mut found_colon = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];
        if !found_colon && cbyte == COLON {
            found_colon = true;
            continue;
        }

        if cbyte == CR || cbyte == LF {
            continue;
        }

        if !found_colon {
            lhs.push_str(ch);
        } else {
            rhs.push_str(ch);
        }
    }

    return ClientHeader {
        key:lhs.trim().to_string(),
        value:rhs.trim().to_string()
    };
}

fn get_normal_body (path_on_disk: &str) -> String {
    let path = Path::new(path_on_disk);
    let display = path.display();
    let mut file = match File::open(&path) {
        Ok(f) => f,
        Err(err) => panic!("file error: {}", err)
    };

    let content = match file.read_to_end() {
        Ok(c) => c,
        Err(err) => panic!("{}", err)
    };

    let s = String::from_utf8(content).unwrap();
    return s;
}

fn sec_handshake (from_server: &[u8]) -> String {

    // from rfc6455 [page 6]
    let guid = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    let mut sha = Sha1::new();

    sha.input(from_server);
    sha.input(guid);
    let mut out = [0u8, ..20];
    sha.result(out.as_mut_slice());

    return out.to_base64(STANDARD);
}

fn ws_handshake (mut stream: BufferedStream<TcpStream>,
                 headers: Vec<ClientHeader>) {

    let header_sec_key = b"Sec-WebSocket-Key";

    let from_server = get_header_by_name(header_sec_key, &headers);
    let accept = sec_handshake(from_server.as_bytes());

    let sec_header = format!("Sec-WebSocket-Accept: {}\r\n", accept);

    stream.write(b"HTTP/1.1 101 Switching Protocols\r\n").unwrap();
    stream.write(b"Upgrade: websocket\r\n").unwrap();
    stream.write(b"Connection: Upgrade\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Version: 13\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Protocol: protocolOne\r\n").unwrap();
    stream.write(sec_header.as_bytes()).unwrap();
    stream.write(b"\r\n");

    ws_listen(stream, headers);
}

fn ws_listen(mut stream: BufferedStream<TcpStream>,
             mut headers: Vec<ClientHeader>) {

    let payload = Payload::Text("text ".to_string());
    let msg = Message::from_payload(payload, 0b0000_0000);
    msg.send(&mut stream);

    let payload = Payload::Text("here".to_string());
    let msg = Message::continue_from_payload(payload);
    let mut stream2 = stream;
    msg.send(&mut stream2);

    let payload = Payload::Empty;
    let msg = Message::from_payload(payload, 0b1000_0000);
    let mut stream3 = stream2;
    msg.send(&mut stream3);

    println!("done sending");

    /*
    let mut timer = Timer::new().unwrap();
    let interval = Duration::milliseconds(5000);
    timer::sleep(interval);
    */

    let mut stream4 = stream3;
    Message::from_stream(&mut stream4);

    let mut stream5 = stream4;
    let echo_msg = Message::from_stream(&mut stream5);

    echo_msg.send(&mut stream5);

    /*
    let mut timer = Timer::new().unwrap();
    let interval = Duration::milliseconds(5000);
    timer::sleep(interval);
    */

    /*
    let mut stream4 = stream3;
    let mut buf = [0, ..100];
    match stream4.read(&mut buf) {
        Ok(nread) => println!("Read {} bytes", nread),
        Err(e) => println!("error reading: {}", e)
    }

    Message::from_buffer(&buf);

     */

}

fn main () {

    for argument in os::args().iter() {
        println!("arg: {}", argument);
    }

    let addr = "127.0.0.1:8099";

    let listener = TcpListener::bind(addr).unwrap();
    let mut acceptor = listener.listen().unwrap();
    println!("Listening on {}", addr);

    fn handle_client(mut stream: BufferedStream<TcpStream>) {
        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;
        let mut req: RequestedRoute = RequestedRoute {
            pathname: String::new(),
            method: String::new()
        };

        let mut headers: Vec<ClientHeader> = Vec::new();
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }

            if ii == 0u { // the Request-Line is always the first line
                req = parse_request_line(cur_line.as_slice());
                println!("{}", req.pathname);
                ii += 1;
            } else { // this should be  "normal" key-value type header
                headers.push(parse_normal_header(cur_line.as_slice()));
            }

        }

        println!("pathname {} method {}", req.pathname, req.method);

        if req.pathname.as_bytes() == b"/" {
            body = get_normal_body("./html/ws1.html");
        } else if req.pathname.as_bytes() == b"/ws1.js" {
            body = get_normal_body("./html/ws1.js");
        } else if req.pathname.as_bytes() == b"/ws" {
            ws_handshake(stream, headers);
            return;
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap();
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.as_bytes()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.as_bytes()).unwrap();
        stream.flush().unwrap();

        println!("Done handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<commit_msg>double echo<commit_after>extern crate "rust-crypto" as rust_crypto;
extern crate serialize;

use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::{File, BufferedStream};
use std::string::String;
use std::os;
use std::vec::Vec;

use rust_crypto::sha1::Sha1;
use rust_crypto::digest::Digest;
use serialize::base64::{ToBase64, STANDARD};

use std::io::Timer;
use std::io::timer;
use std::time::duration::Duration;

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const COLON: u8 = b':';
pub const CRLF: &'static [u8] = &[CR,LF];

struct RequestedRoute {
    method: String,
    pathname: String
}

struct ClientHeader {
    key: String,
    value: String
}

enum Payload {
    Text(String),
    Binary(Vec<u8>),
    Empty
}

enum Opcode {
    EmptyOp = 0x0,
    TextOp = 0x1,
    BinaryOp = 0x2,
    CloseOp = 0x8,
}

struct Message {
    payload: Payload,
    opcode: Opcode,
    fin: u8
 }

impl Message {

    fn from_payload (payload: Payload, fin: u8) -> Message {
        let opcode: Opcode = match payload {
            Payload::Text(_) => Opcode::TextOp,
            Payload::Binary(_) => Opcode::BinaryOp,
            Payload::Empty => Opcode::EmptyOp
        };
        return Message {payload: payload, opcode: opcode, fin: fin};
    }

    fn continue_from_payload (payload: Payload) -> Message {
        let opcode = Opcode::EmptyOp;
        let fin = 0x0;
        return Message {payload: payload, opcode: opcode, fin: fin};
    }

    fn send (&self,
            mut stream: &mut BufferedStream<TcpStream>) {
        let msg = match self.payload {
            Payload::Text(ref s) => s.as_bytes(),
            Payload::Binary(ref s) => s.as_slice(),
            Payload::Empty => "".as_bytes(),
        };

        let length = msg.len() as u8;

        println!("fin: {}, msg: {}, opcode: {}", self.fin, msg, self.opcode as u8);

        stream.write_u8(self.fin | self.opcode as u8).unwrap();
        stream.write_u8(length).unwrap();
        stream.write(msg).unwrap();
        stream.flush();
    }

    fn from_stream(mut stream: &mut BufferedStream<TcpStream>) -> Message {
        let cur_byte: u8 = stream.read_byte().unwrap();

        let fin = cur_byte & 0b1000_0000;
        let rsv = cur_byte & 0b0111_0000;
        let opc = cur_byte & 0b0000_1111;
        let msk = cur_byte & 0b0000_0001;

        let cur_byte: u8 = stream.read_byte().unwrap();
        let len = (cur_byte & 0b0111_1111) as uint;

        let mskkey = stream.read_exact(4).unwrap();

        let mut msg = Vec::new();
        for ii in range(0u, len) {
            let cur_byte: u8 = stream.read_byte().unwrap();
            let ch = mskkey[ii % 4] ^ cur_byte;
            msg.push(ch);
        }

        let utf8_msg = match String::from_utf8(msg) {
            Ok(m) => m,
            Err(_) => panic!("I don't know how to ut8 that")
        };

        println!(
            "fin {}, rsv {}, msk {}, opcode {}, len {}, mskkey {}, msg {}",
            fin, rsv, msk, opc, len, mskkey, utf8_msg);

        let payload = Payload::Text(utf8_msg);
        return Message::from_payload(payload, fin);
    }

    fn from_buffer (buf: &[u8]) {
        let fin = buf[0] & 0b1000_0000;
        let rsv = buf[0] & 0b0111_0000;
        let opc = buf[0] & 0b0000_1111;
        let msk = buf[0] & 0b0000_0001;
        let len = (buf[1] & 0b0111_1111) as uint;
        let mskkey = buf.slice(2, 6);

        let mut msg = Vec::new();
        for ii in range(0u, len) {
            let ch = mskkey[ii % 4] ^ buf[6 + ii];
            msg.push(ch);
        }

        println!(
            "fin {}, rsv {}, msk {}, opcode {}, len {}, mskkey {}, msg {}, \nbuf {}",
            fin, rsv, msk, opc, len, mskkey, String::from_utf8(msg),  buf.as_slice());
    }
}

fn get_header_by_name (header: &[u8], headers: &Vec<ClientHeader>) -> String {
    let mut result = String::new();

    for h in headers.iter() {
        if h.key.as_bytes() == header {
            result = h.value.clone();
            break;
        }
    }

    return result;
}

fn parse_request_line (header: &str) -> RequestedRoute {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    return RequestedRoute {method: method, pathname: pathname};
}

fn parse_normal_header (header: &str) -> ClientHeader {
    let mut lhs = String::new(); // lhs of ':' in header
    let mut rhs = String::new(); // rhs of ':' in header
    let mut found_colon = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];
        if !found_colon && cbyte == COLON {
            found_colon = true;
            continue;
        }

        if cbyte == CR || cbyte == LF {
            continue;
        }

        if !found_colon {
            lhs.push_str(ch);
        } else {
            rhs.push_str(ch);
        }
    }

    return ClientHeader {
        key:lhs.trim().to_string(),
        value:rhs.trim().to_string()
    };
}

fn get_normal_body (path_on_disk: &str) -> String {
    let path = Path::new(path_on_disk);
    let display = path.display();
    let mut file = match File::open(&path) {
        Ok(f) => f,
        Err(err) => panic!("file error: {}", err)
    };

    let content = match file.read_to_end() {
        Ok(c) => c,
        Err(err) => panic!("{}", err)
    };

    let s = String::from_utf8(content).unwrap();
    return s;
}

fn sec_handshake (from_server: &[u8]) -> String {

    // from rfc6455 [page 6]
    let guid = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    let mut sha = Sha1::new();

    sha.input(from_server);
    sha.input(guid);
    let mut out = [0u8, ..20];
    sha.result(out.as_mut_slice());

    return out.to_base64(STANDARD);
}

fn ws_handshake (mut stream: BufferedStream<TcpStream>,
                 headers: Vec<ClientHeader>) {

    let header_sec_key = b"Sec-WebSocket-Key";

    let from_server = get_header_by_name(header_sec_key, &headers);
    let accept = sec_handshake(from_server.as_bytes());

    let sec_header = format!("Sec-WebSocket-Accept: {}\r\n", accept);

    stream.write(b"HTTP/1.1 101 Switching Protocols\r\n").unwrap();
    stream.write(b"Upgrade: websocket\r\n").unwrap();
    stream.write(b"Connection: Upgrade\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Version: 13\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Protocol: protocolOne\r\n").unwrap();
    stream.write(sec_header.as_bytes()).unwrap();
    stream.write(b"\r\n");

    ws_listen(stream, headers);
}

fn ws_listen(mut stream: BufferedStream<TcpStream>,
             mut headers: Vec<ClientHeader>) {

    let payload = Payload::Text("text ".to_string());
    let msg = Message::from_payload(payload, 0b0000_0000);
    msg.send(&mut stream);

    let payload = Payload::Text("here".to_string());
    let msg = Message::continue_from_payload(payload);
    let mut stream2 = stream;
    msg.send(&mut stream2);

    let payload = Payload::Empty;
    let msg = Message::from_payload(payload, 0b1000_0000);
    let mut stream3 = stream2;
    msg.send(&mut stream3);

    println!("done sending");

    let mut stream4 = stream3;
    Message::from_stream(&mut stream4);

    let mut stream5 = stream4;
    let echo_msg = Message::from_stream(&mut stream5);

    echo_msg.send(&mut stream5);

    echo_msg.send(&mut stream5);

    /*
    let mut timer = Timer::new().unwrap();
    let interval = Duration::milliseconds(5000);
    timer::sleep(interval);
    */

    /*
    let mut stream4 = stream3;
    let mut buf = [0, ..100];
    match stream4.read(&mut buf) {
        Ok(nread) => println!("Read {} bytes", nread),
        Err(e) => println!("error reading: {}", e)
    }

    Message::from_buffer(&buf);

     */

}

fn main () {

    for argument in os::args().iter() {
        println!("arg: {}", argument);
    }

    let addr = "127.0.0.1:8099";

    let listener = TcpListener::bind(addr).unwrap();
    let mut acceptor = listener.listen().unwrap();
    println!("Listening on {}", addr);

    fn handle_client(mut stream: BufferedStream<TcpStream>) {
        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;
        let mut req: RequestedRoute = RequestedRoute {
            pathname: String::new(),
            method: String::new()
        };

        let mut headers: Vec<ClientHeader> = Vec::new();
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }

            if ii == 0u { // the Request-Line is always the first line
                req = parse_request_line(cur_line.as_slice());
                println!("{}", req.pathname);
                ii += 1;
            } else { // this should be  "normal" key-value type header
                headers.push(parse_normal_header(cur_line.as_slice()));
            }

        }

        println!("pathname {} method {}", req.pathname, req.method);

        if req.pathname.as_bytes() == b"/" {
            body = get_normal_body("./html/ws1.html");
        } else if req.pathname.as_bytes() == b"/ws1.js" {
            body = get_normal_body("./html/ws1.js");
        } else if req.pathname.as_bytes() == b"/ws" {
            ws_handshake(stream, headers);
            return;
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap();
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.as_bytes()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.as_bytes()).unwrap();
        stream.flush().unwrap();

        println!("Done handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use spec::{LinkerFlavor, LldFlavor, PanicStrategy,
           Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
        llvm_target: "riscv32".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: String::new(),
        target_vendor: "unknown".to_string(),
        arch: "riscv32".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),

        options: TargetOptions {
            linker: Some("rust-lld".to_string()),
            cpu: "generic-rv32".to_string(),
            max_atomic_width: Some(32),
            atomic_cas: false, // incomplete +a extension
            features: "+m,+a,+c".to_string(),
            executables: true,
            panic_strategy: PanicStrategy::Abort,
            relocation_model: "static".to_string(),
            emit_debug_gdb_scripts: false,
            abi_blacklist: super::riscv_base::abi_blacklist(),
            .. Default::default()
        },
    })
}
<commit_msg>Enable RISC-V atomic compare and swap<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use spec::{LinkerFlavor, LldFlavor, PanicStrategy,
           Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
        llvm_target: "riscv32".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: String::new(),
        target_vendor: "unknown".to_string(),
        arch: "riscv32".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),

        options: TargetOptions {
            linker: Some("rust-lld".to_string()),
            cpu: "generic-rv32".to_string(),
            max_atomic_width: Some(32),
            atomic_cas: true,
            features: "+m,+a,+c".to_string(),
            executables: true,
            panic_strategy: PanicStrategy::Abort,
            relocation_model: "static".to_string(),
            emit_debug_gdb_scripts: false,
            abi_blacklist: super::riscv_base::abi_blacklist(),
            .. Default::default()
        },
    })
}
<|endoftext|>


<commit_before>use std::ops::Add;
use std::marker::PhantomData;

/// 创建空枚举来定义单位类型。
#[derive(Debug, Clone, Copy)]
enum Inch {}
#[derive(Debug, Clone, Copy)]
enum Mm {}

/// `Length` 是一个带有虚位类型参量的 `Unit`（单位）。
///
/// `f64` 已经实现了 `Clone` 和 `Copy` trait.
#[derive(Debug, Clone, Copy)]
struct Length<Unit>(f64,PhantomData<Unit>);

/// `Add` trait 定义了 `+` 运算符的行为。
impl<Unit> Add for Length<Unit> {
     type Output = Length<Unit>;

    // add() 返回一个全新的包含总和的 `Length` 结构体。
    fn add(self, rhs: Length<Unit>) -> Length<Unit> {
        // `+` 调用了针对 `f64` 类型的 `Add` 实现。
        Length(self.0 + rhs.0, PhantomData)
    }
}

fn main() {
    // 指出 `one_foot` 拥有虚位类型参量 `Inch`。
    let one_foot:  Length<Inch> = Length(12.0, PhantomData);
    // `one_meter` 拥有虚位类型参量 `Mm`。
    let one_meter: Length<Mm>   = Length(1000.0, PhantomData);

    // `+` 调用了 `add()` 方法，该方法对 `Length<Unit>` 进行了实现。
    //
    // 由于 `Length` 了实现了 `Copy`，于是 `add()` 不会消费 `one_foot`
    // 和 `one_meter`，但会复制它们到 `self` 和 `rhs`。
    let two_feet = one_foot + one_foot;
    let two_meters = one_meter + one_meter;

    // 加法正常执行。
    println!("one foot + one_foot = {:?}", two_feet);
    println!("one meter + one_meter = {:?}", two_meters);

    // 无意义的操作将会失败，因为它们会导致：
    // 编译期报错：类型不匹配（Compile-time Error: type mismatch.）。
    //let one_feter = one_foot + one_meter;
}

<commit_msg>More info in Length doc and final printed messages<commit_after>use std::ops::Add;
use std::marker::PhantomData;

/// 创建空枚举来定义单位类型。
#[derive(Debug, Clone, Copy)]
enum Inch {}
#[derive(Debug, Clone, Copy)]
enum Mm {}

/// `Length` 是一个带有虚位类型参量的 `Unit`（单位），
/// 而且不是关于长类型（即 `f64`）的泛型。
///
/// `f64` 已经实现了 `Clone` 和 `Copy` trait.
#[derive(Debug, Clone, Copy)]
struct Length<Unit>(f64, PhantomData<Unit>);

/// `Add` trait 定义了 `+` 运算符的行为。
impl<Unit> Add for Length<Unit> {
     type Output = Length<Unit>;

    // add() 返回一个全新的包含总和的 `Length` 结构体。
    fn add(self, rhs: Length<Unit>) -> Length<Unit> {
        // `+` 调用了针对 `f64` 类型的 `Add` 实现。
        Length(self.0 + rhs.0, PhantomData)
    }
}

fn main() {
    // 指出 `one_foot` 拥有虚位类型参量 `Inch`。
    let one_foot:  Length<Inch> = Length(12.0, PhantomData);
    // `one_meter` 拥有虚位类型参量 `Mm`。
    let one_meter: Length<Mm>   = Length(1000.0, PhantomData);

    // `+` 调用了 `add()` 方法，该方法对 `Length<Unit>` 进行了实现。
    //
    // 由于 `Length` 了实现了 `Copy`，于是 `add()` 不会消费 `one_foot`
    // 和 `one_meter`，但会复制它们到 `self` 和 `rhs`。
    let two_feet = one_foot + one_foot;
    let two_meters = one_meter + one_meter;

    // 加法正常执行。
    println!("one foot + one_foot = {:?} in", two_feet.0);
    println!("one meter + one_meter = {:?} mm", two_meters.0);

    // 无意义的操作将会失败，因为它们会导致：
    // 编译期报错：类型不匹配（Compile-time Error: type mismatch.）。
    //let one_feter = one_foot + one_meter;
}

<|endoftext|>


<commit_before>fn is_narc(x: u32) -> bool {
    let digits: Vec<u32> = x
        .to_string()
        .chars()
        .map(|c| c.to_digit(10).unwrap())
        .collect();

    digits
        .iter()
        .map(|d| d.pow(digits.len() as u32))
        .sum::<u32>()
        == x
}

fn main() {
    let mut counter = 0;
    let mut i = 0;
    while counter < 25 {
        if is_narc(i) {
            println!("{}", i);
            counter += 1;
        }
        i += 1;
    }
}

#[cfg(test)]
mod tests {
    use super::is_narc;
    #[test]
    fn test_is_narc() {
        let input = 0;
        let output = is_narc(input);
        assert_eq!(output, true);

        let input = 1;
        let output = is_narc(input);
        assert_eq!(output, true);

        let input = 153;
        let output = is_narc(input);
        assert_eq!(output, true);
    }
    #[test]
    fn test_not_is_narc() {
        let input = 10;
        let output = is_narc(input);
        assert_eq!(output, false);

        let input = 999999999;
        let output = is_narc(input);
        assert_eq!(output, false);
    }
}
<commit_msg>Rename function<commit_after>fn is_narcissistic(x: u32) -> bool {
    let digits: Vec<u32> = x
        .to_string()
        .chars()
        .map(|c| c.to_digit(10).unwrap())
        .collect();

    digits
        .iter()
        .map(|d| d.pow(digits.len() as u32))
        .sum::<u32>()
        == x
}

fn main() {
    let mut counter = 0;
    let mut i = 0;
    while counter < 25 {
        if is_narcissistic(i) {
            println!("{}", i);
            counter += 1;
        }
        i += 1;
    }
}

#[cfg(test)]
mod tests {
    use super::is_narcissistic;
    #[test]
    fn test_is_narc() {
        let input = 0;
        let output = is_narcissistic(input);
        assert_eq!(output, true);

        let input = 1;
        let output = is_narcissistic(input);
        assert_eq!(output, true);

        let input = 153;
        let output = is_narcissistic(input);
        assert_eq!(output, true);
    }
    #[test]
    fn test_not_is_narc() {
        let input = 10;
        let output = is_narcissistic(input);
        assert_eq!(output, false);

        let input = 999999999;
        let output = is_narcissistic(input);
        assert_eq!(output, false);
    }
}
<|endoftext|>