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

use std::io::Result as IoResult;
use std::io::Read;
use std::io::Error as IoError;
use std::io::ErrorKind;
use std::fmt;
use std::error::Error;

/// Reads HTTP chunks and sends back real data.
///
/// # Example
///
/// ```
/// use chunked_transfer::Decoder;
/// use std::io::Read;
///
/// let encoded = b"3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n";
/// let mut decoded = String::new();
///
/// let mut decoder = Decoder::new(encoded as &[u8]);
/// decoder.read_to_string(&mut decoded);
///
/// assert_eq!(decoded, "hello world!!!");
/// ```
pub struct Decoder<R> {
    // where the chunks come from
    source: R,

    // remaining size of the chunk being read
    // none if we are not in a chunk
    remaining_chunks_size: Option<usize>,
}

impl<R> Decoder<R> where R: Read {
    pub fn new(source: R) -> Decoder<R> {
        Decoder {
            source: source,
            remaining_chunks_size: None,
        }
    }
}

impl<R> Read for Decoder<R> where R: Read {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        let remaining_chunks_size = match self.remaining_chunks_size {
            Some(c) => c,
            None => {
                // first possibility: we are not in a chunk, so we'll attempt to determine
                // the chunks size
                let mut chunk_size = Vec::new();

                loop {
                    let byte = match self.source.by_ref().bytes().next() {
                        Some(b) => try!(b),
                        None => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
                    };

                    if byte == b'\r' {
                        break;
                    }

                    chunk_size.push(byte);
                }

                match self.source.by_ref().bytes().next() {
                    Some(Ok(b'\n')) => (),
                    _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
                }

                let chunk_size = match String::from_utf8(chunk_size) {
                    Ok(c) => c,
                    Err(_) => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
                };

                let chunk_size = match usize::from_str_radix(&chunk_size, 16) {
                    Ok(c) => c,
                    Err(_) => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
                };

                // if the chunk size is 0, we are at EOF
                if chunk_size == 0 {
                    match self.source.by_ref().bytes().next() {
                        Some(Ok(b'\r')) => (),
                        _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
                    }

                    match self.source.by_ref().bytes().next() {
                        Some(Ok(b'\n')) => (),
                        _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
                    }

                    return Ok(0);
                }

                // now that we now the current chunk size, calling ourselves recursively
                self.remaining_chunks_size = Some(chunk_size);
                return self.read(buf);
            }
        };

        // second possibility: we continue reading from a chunk
        if buf.len() < remaining_chunks_size {
            let read = try!(self.source.read(buf));
            self.remaining_chunks_size = Some(remaining_chunks_size - read);
            return Ok(read);
        }

        // third possibility: the read request goes further than the current chunk
        // we simply read until the end of the chunk and return
        assert!(buf.len() >= remaining_chunks_size);

        let buf = &mut buf[.. remaining_chunks_size];
        let read = try!(self.source.read(buf));

        self.remaining_chunks_size = if read == remaining_chunks_size {
            match self.source.by_ref().bytes().next() {
                Some(Ok(b'\r')) => (),
                _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
            }

            match self.source.by_ref().bytes().next() {
                Some(Ok(b'\n')) => (),
                _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
            }

            None
        } else {
            Some(remaining_chunks_size - read)
        };

        return Ok(read);
    }
}

#[derive(Debug, Copy, Clone)]
struct DecoderError;

impl fmt::Display for DecoderError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "Error while decoding chunks")
    }
}

impl Error for DecoderError {
    fn description(&self) -> &str {
        "Error while decoding chunks"
    }
}

#[cfg(test)]
mod test {
    use super::Decoder;
    use std::io;
    use std::io::Read;

    #[test]
    fn test_valid_chunk_decode() {
        let source = io::Cursor::new("3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).unwrap();

        assert_eq!(string, "hello world!!!");
    }

    #[test]
    fn test_decode_zero_length() {
        let mut decoder = Decoder::new(b"0\r\n\r\n" as &[u8]);

        let mut decoded = String::new();
        decoder.read_to_string(&mut decoded).unwrap();

        assert_eq!(decoded, "");
    }

    #[test]
    fn test_decode_invalid_chunk_length() {
        let mut decoder = Decoder::new(b"m\r\n\r\n" as &[u8]);

        let mut decoded = String::new();
        assert!(decoder.read_to_string(&mut decoded).is_err());
    }

    #[test]
    fn invalid_input1() {
        let source = io::Cursor::new("2\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).is_err();
    }

    #[test]
    fn invalid_input2() {
        let source = io::Cursor::new("3\rhel\r\nb\r\nlo world!!!\r\n0\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).is_err();
    }
}
<commit_msg>Extract logic out of read()<commit_after>// Copyright 2015 The tiny-http Contributors
// Copyright 2015 The rust-chunked-transfer Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::Result as IoResult;
use std::io::Read;
use std::io::Error as IoError;
use std::io::ErrorKind;
use std::fmt;
use std::error::Error;

/// Reads HTTP chunks and sends back real data.
///
/// # Example
///
/// ```
/// use chunked_transfer::Decoder;
/// use std::io::Read;
///
/// let encoded = b"3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n";
/// let mut decoded = String::new();
///
/// let mut decoder = Decoder::new(encoded as &[u8]);
/// decoder.read_to_string(&mut decoded);
///
/// assert_eq!(decoded, "hello world!!!");
/// ```
pub struct Decoder<R> {
    // where the chunks come from
    source: R,

    // remaining size of the chunk being read
    // none if we are not in a chunk
    remaining_chunks_size: Option<usize>,
}

impl<R> Decoder<R> where R: Read {
    pub fn new(source: R) -> Decoder<R> {
        Decoder {
            source: source,
            remaining_chunks_size: None,
        }
    }

    fn read_chunk_size(&mut self) -> Result<usize, IoError> {
        let mut chunk_size = Vec::new();

        loop {
            let byte = match self.source.by_ref().bytes().next() {
                Some(b) => try!(b),
                None => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
            };

            if byte == b'\r' {
                break;
            }

            chunk_size.push(byte);
        }

        match self.source.by_ref().bytes().next() {
            Some(Ok(b'\n')) => (),
            _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
        }

        let chunk_size = match String::from_utf8(chunk_size) {
            Ok(c) => c,
            Err(_) => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
        };

        let chunk_size = match usize::from_str_radix(&chunk_size, 16) {
            Ok(c) => c,
            Err(_) => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
        };

        Ok(chunk_size)
    }
}

impl<R> Read for Decoder<R> where R: Read {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        let remaining_chunks_size = match self.remaining_chunks_size {
            Some(c) => c,
            None => {
                // first possibility: we are not in a chunk, so we'll attempt to determine
                // the chunks size
                let chunk_size = try!(self.read_chunk_size());

                // if the chunk size is 0, we are at EOF
                if chunk_size == 0 {
                    match self.source.by_ref().bytes().next() {
                        Some(Ok(b'\r')) => (),
                        _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
                    }

                    match self.source.by_ref().bytes().next() {
                        Some(Ok(b'\n')) => (),
                        _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
                    }

                    return Ok(0);
                }

                // now that we now the current chunk size, calling ourselves recursively
                self.remaining_chunks_size = Some(chunk_size);
                return self.read(buf);
            }
        };

        // second possibility: we continue reading from a chunk
        if buf.len() < remaining_chunks_size {
            let read = try!(self.source.read(buf));
            self.remaining_chunks_size = Some(remaining_chunks_size - read);
            return Ok(read);
        }

        // third possibility: the read request goes further than the current chunk
        // we simply read until the end of the chunk and return
        assert!(buf.len() >= remaining_chunks_size);

        let buf = &mut buf[.. remaining_chunks_size];
        let read = try!(self.source.read(buf));

        self.remaining_chunks_size = if read == remaining_chunks_size {
            match self.source.by_ref().bytes().next() {
                Some(Ok(b'\r')) => (),
                _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
            }

            match self.source.by_ref().bytes().next() {
                Some(Ok(b'\n')) => (),
                _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
            }

            None
        } else {
            Some(remaining_chunks_size - read)
        };

        return Ok(read);
    }
}

#[derive(Debug, Copy, Clone)]
struct DecoderError;

impl fmt::Display for DecoderError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "Error while decoding chunks")
    }
}

impl Error for DecoderError {
    fn description(&self) -> &str {
        "Error while decoding chunks"
    }
}

#[cfg(test)]
mod test {
    use super::Decoder;
    use std::io;
    use std::io::Read;

    #[test]
    fn test_valid_chunk_decode() {
        let source = io::Cursor::new("3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).unwrap();

        assert_eq!(string, "hello world!!!");
    }

    #[test]
    fn test_decode_zero_length() {
        let mut decoder = Decoder::new(b"0\r\n\r\n" as &[u8]);

        let mut decoded = String::new();
        decoder.read_to_string(&mut decoded).unwrap();

        assert_eq!(decoded, "");
    }

    #[test]
    fn test_decode_invalid_chunk_length() {
        let mut decoder = Decoder::new(b"m\r\n\r\n" as &[u8]);

        let mut decoded = String::new();
        assert!(decoder.read_to_string(&mut decoded).is_err());
    }

    #[test]
    fn invalid_input1() {
        let source = io::Cursor::new("2\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).is_err();
    }

    #[test]
    fn invalid_input2() {
        let source = io::Cursor::new("3\rhel\r\nb\r\nlo world!!!\r\n0\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).is_err();
    }
}
<|endoftext|>


<commit_before>//! Total Variation 1D Denoising Algorithms.
//!

#![deny(missing_docs)]

use num;
use std::cmp;
use std::fmt;
use std::iter;
use std::ops;
use utils::*;

/// Denoise an array of data points given a `lambda`, which decides
/// the degree of denoising.
///
/// A very large `lambda` will create a denoised output, in which
/// every value is equivalent to the average of the input data points.
/// A very small `lambda` (i.e. 0) will not denoise the input at all,
/// creating an output that is the same as the input.
///
/// This algorithm was first described by Laurent Condat in 2013 in
/// his paper "A Direct Algorithm for 1D Total Variation Denoising."
pub fn condat_denoise<T>(input: &Vec<T>, lambda: T) -> Vec<T>
    where T: num::Num + num::FromPrimitive + cmp::PartialOrd
    + ops::Neg + ops::Add<Output=T> + ops::Neg<Output=T>
    + ops::AddAssign<T> + Sized + fmt::Debug + Copy
{
    assert!(input.len() > 0,
            "Input list should have at least one value.");

    let width = input.len();
    let mut output = Vec::new();

    // k: current sample location
    let mut k = 0;
    // k0: beginning of current segment
    let mut k0 = 0;

    let twolambda = T::from_u8(2).expect("Unable to transform `2` to T.") * lambda;
    let minlambda = -lambda;
    // umin and umax are used for keeping track of previous data
    // points we have seen.
    let mut umin = lambda;
    let mut umax = minlambda;
    // boundaries of the segment's value
    let mut segment_lower_bound = input[0] - lambda;
    let mut segment_upper_bound = input[0] + lambda;

    // last position where umax = -lambda
    let mut kplus = 0;
    // last position where umin = lambda
    let mut kminus = 0;

    loop {
        if k == (width - 1) {
            if umin < num::zero() {
                // if segment_lower_bound is too high,
                // jump down.
                output.extend(iter::repeat(segment_lower_bound).take(kminus - k0 + 1));
                k0 = kminus + 1;
                sync_values(k0, &mut [&mut k, &mut kminus]);
                segment_lower_bound = input[kminus];
                umin = lambda;
                umax = segment_lower_bound + umin - segment_upper_bound;
            } else if umax > num::zero() {
                // if segment_upper_bound is too low,
                // jump up.
                output.extend(iter::repeat(segment_upper_bound).take(kplus - k0 + 1));
                k0 = kplus + 1;
                sync_values(k0, &mut [&mut k, &mut kplus]);
                segment_upper_bound = input[kplus];
                umax = minlambda;
                umin = segment_upper_bound + umax - segment_lower_bound;
            } else {
                // segment_lower_bound and segment_upper_bound is appropriate.
                segment_lower_bound += umin /
                                       num::FromPrimitive::from_usize(k - k0 + 1)
                    .expect("Unable to convert usize to num::FromPrimitive.");
                output.extend(iter::repeat(segment_lower_bound).take(k - k0 + 1));
                return output;
            }
        } else {
            umin += input[k + 1] - segment_lower_bound; // input 0 and 1
            umax += input[k + 1] - segment_upper_bound; // input 0 and 1
            if umin < minlambda {
                output.extend(iter::repeat(segment_lower_bound).take(kminus - k0 + 1));
                k0 = kminus + 1;
                sync_values(k0, &mut [&mut k, &mut kminus, &mut kplus]);
                segment_lower_bound = input[kplus];
                segment_upper_bound = segment_lower_bound + twolambda;
                umin = lambda;
                umax = minlambda;
            } else if umax > lambda {
                output.extend(iter::repeat(segment_upper_bound).take(kplus - k0 + 1));
                k0 = kplus + 1;
                sync_values(k0, &mut [&mut k, &mut kminus, &mut kplus]);
                segment_upper_bound = input[kplus];
                segment_lower_bound = segment_upper_bound - twolambda;
                umin = lambda;
                umax = minlambda;
            } else {
                k += 1;
                if umin >= lambda {
                    kminus = k;
                    segment_lower_bound = (segment_lower_bound + (umin - lambda)) /
                                          num::FromPrimitive::from_usize(kminus - k0 + 1)
                        .expect("Unable to convert usize to num::FromPrimitive.");
                    umin = lambda;
                }
                if umax <= minlambda {
                    kplus = k;
                    segment_upper_bound += (umax + lambda) /
                                           num::FromPrimitive::from_usize(kplus - k0 + 1)
                        .expect("Unable to convert usize to num::FromPrimitive.");
                    umax = minlambda;
                }
            }
        }
    }
}

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

    #[test]
    fn tautstring_test_input_output_length() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = tautstring_denoise(&input, 0.0);
        assert_eq!(input.len(), output.len());
    }

    #[test]
    fn tautstring_test_zero_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = tautstring_denoise(&input, 0.0);
        let output_expected = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.0001);
        }
    }

    #[test]
    fn tautstring_test_large_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = tautstring_denoise(&input, 100.0);
        // The expected output is taken from the Laurent Condat's C
        // implementation.
        let output_expected = vec![4.925, 4.925, 4.925, 4.925, 4.925, 4.925, 4.925, 4.925];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.0001);
        }
    }

    #[test]
    fn tautstring_test_moderate_lambda() {
        let input = vec![111.0, 422.1, 145.2, 248.2, 871.4, 675.2, 436.2, 310.1];
        let output = tautstring_denoise(&input, 5.0);
        // The expected output is taken from the Laurent Condat's C
        // implementation.
        let output_expected = vec![116.0, 412.100006, 155.199997, 248.199997, 861.400024,
                                   675.200012, 436.200012, 315.100006];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.0001);
        }
    }

    #[test]
    fn condat_test_input_output_length() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = condat_denoise(&input, 0.0);
        assert_eq!(input.len(), output.len());
    }

    #[test]
    fn condat_test_zero_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = condat_denoise(&input, 0.0);
        let output_expected = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        assert_eq!(output, output_expected);
    }

    #[test]
    fn condat_test_large_lambda() {
        let input = vec![111.0, 422.1, 145.2, 248.2, 871.4, 675.2, 436.2, 310.1];
        let output = condat_denoise(&input, 10000.0);
        // The expected output is taken from the Laurent Condat's C
        // implementation.
        let output_expected = vec![402.425049, 402.425049, 402.425049, 402.425049, 402.425049,
                                   402.425049, 402.425049, 402.425049];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.0001);
        }
    }

    #[test]
    fn condat_test_moderate_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = condat_denoise(&input, 3.0);
        // The expected output is taken from the Laurent Condat's C
        // implementation.
        let output_expected = vec![3.050000, 3.050000, 4.933333, 4.933333, 4.933333, 5.200000,
                                   6.200000, 7.100000];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.000001);
        }
    }

    #[test]
    #[should_panic]
    fn condat_test_negative_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        condat_denoise(&input, -1.0);
    }

    #[test]
    #[should_panic]
    fn condat_test_empty_input() {
        let input = vec![];
        condat_denoise(&input, 1.0);
    }
}
<commit_msg>Add tautstring denoising algorithm as a comment<commit_after>//! Total Variation 1D Denoising Algorithms.
//!

#![deny(missing_docs)]

use num;
use std::cmp;
use std::fmt;
use std::iter;
use std::ops;
use utils::*;

// TODO change tautstring to be generic
/// TODO
/// Note: numerical blow-up if floattype=float for N>=10^6
/// because the algorithm is based on the running sum of the signal
/// values.
// pub fn tautstring_denoise(input: &Vec<f64>, lambda: f64) -> Vec<f64> {
//     assert!(input.len() > 0, "Input list should have at least one value.");
//     let mut output = vec![0.0; input.len()];
//     let width = input.len() + 1;

//     let mut index_low = vec![0; width];
//     let mut slope_low = vec![0.0; width];
//     let mut index_up = vec![0; width];
//     let mut slope_up = vec![0.0; width];
//     let mut index = vec![0; width];

//     let mut z = vec![0.0; width];
//     // Lower and upper boundaries
//     let mut y_low = vec![0.0; width];
//     let mut y_up = vec![0.0; width];
//     let mut s_low = 0;
//     let mut c_low = 0;
//     let mut s_up = 0;
//     let mut c_up = 0;
//     let mut c = 0;
//     let mut i = 2;

//     // The boundaries are first defined by the input values.
//     y_low[1] = input[0] - lambda;
//     y_up[1] = input[0] + lambda;
//     // Based on the input values, get culmulative sums.
//     while i < width {
//         y_low[i] = y_low[i - 1] + input[i - 1];
//         y_up[i] = y_up[i - 1] + input[i - 1];
//         i += 1;
//     }

//     // The last value's lower boundary is elevated by lambda.
//     y_low[width - 1] += lambda;
//     // The last value's lower boundary is decreased by lambda.
//     y_up[width - 1] -= lambda;

//     slope_low[0] = f64::INFINITY;
//     slope_up[0] = f64::NEG_INFINITY;

//     // z is first set to be the first lower boundary.
//     z[0] = y_low[0];

//     for i in 1..width {
//         c_low += 1;
//         c_up += 1;

//         index_low[c_low] = i;
//         index_up[c_up] = i;
//         slope_low[c_low] = y_low[i] - y_low[i - 1];

//         // c_low is too large. Decrease it by one.
//         while (c_low > s_low + 1) && (slope_low[cmp::max(s_low, c_low - 1)]
// <= slope_low[c_low]) {
//             c_low -= 1;
//             index_low[c_low] = i;
//             if c_low > s_low + 1 {
//                 slope_low[c_low] = (y_low[i] - y_low[index_low[c_low - 1]]) /
//                     (i as f64 - index_low[c_low - 1] as f64);
//             } else {
//                 slope_low[c_low] = (y_low[i] - z[c]) /
//                     (i as f64 - index[c] as f64);
//             }
//         }

//         slope_up[c_up] = y_up[i] - y_up[i - 1];
//         while (c_up > s_up + 1) && (slope_up[cmp::max(c_up - 1, s_up)] >= slope_up[c_up]) {
//             c_up -= 1;
//             index_up[c_up] = i;
//             if c_up > s_up+1 {
//                 slope_up[c_up] = (y_up[i] - y_up[index_up[c_up - 1]]) /
//                     (i as f64 - index_up[c_up - 1] as f64);
//             } else {
//                 slope_up[c_up] = (y_up[i] - z[c]) / (i as f64 - index[c] as f64);
//             }
//         }
//         while (c_low == s_low + 1) &&
//             (c_up > s_up+1) &&
//             (slope_low[c_low] >= slope_up[s_up + 1]) {
//                 c += 1;
//                 s_up += 1;
//                 index[c] = index_up[s_up];
//                 z[c] = y_up[index[c]];
//                 index_low[s_low] = index[c];
//                 slope_low[c_low] = (y_low[i] - z[c]) / (i as f64 - index[c] as f64);
//             }
//         while (c_up == s_up + 1) &&
//             (c_low > s_low + 1) &&
//             (slope_up[c_up] <= slope_low[s_low + 1]) {
//                 c += 1;
//                 s_low += 1;
//                 index[c] = index_low[s_low];
//                 z[c] = y_low[index[c]];
//                 index_up[s_up] = index[c];
//                 slope_up[c_up] = (y_up[i] - z[c]) / (i as f64 - index[c] as f64);
//             }
//     }
//     for i in 1..(c_low - s_low + 1) {
//         index[c + i] = index_low[s_low + i];
//         z[c + i]=y_low[index[c + i]];
//     }
//     c += c_low - s_low;
//     let mut j = 0;
//     let mut a;
//     i = 1;

//     while i <= c {
//         a = (z[i] - z[i - 1]) / (index[i] as f64 - index[i - 1] as f64);
//         while j < index[i] {
//             output[j] = a;
//             j += 1;
//         }
//         i += 1;
//     }
//     output
// }
/// Denoise an array of data points given a `lambda`, which decides
/// the degree of denoising.
///
/// A very large `lambda` will create a denoised output, in which
/// every value is equivalent to the average of the input data points.
/// A very small `lambda` (i.e. 0) will not denoise the input at all,
/// creating an output that is the same as the input.
///
/// This algorithm was first described by Laurent Condat in 2013 in
/// his paper "A Direct Algorithm for 1D Total Variation Denoising."
pub fn condat_denoise<T>(input: &Vec<T>, lambda: T) -> Vec<T>
    where T: num::Num + num::FromPrimitive + cmp::PartialOrd
    + ops::Neg + ops::Add<Output=T> + ops::Neg<Output=T>
    + ops::AddAssign<T> + Sized + fmt::Debug + Copy
{
    assert!(input.len() > 0,
            "Input list should have at least one value.");

    let width = input.len();
    let mut output = Vec::new();

    // k: current sample location
    let mut k = 0;
    // k0: beginning of current segment
    let mut k0 = 0;

    let twolambda = T::from_u8(2).expect("Unable to transform `2` to T.") * lambda;
    let minlambda = -lambda;
    // umin and umax are used for keeping track of previous data
    // points we have seen.
    let mut umin = lambda;
    let mut umax = minlambda;
    // boundaries of the segment's value
    let mut segment_lower_bound = input[0] - lambda;
    let mut segment_upper_bound = input[0] + lambda;

    // last position where umax = -lambda
    let mut kplus = 0;
    // last position where umin = lambda
    let mut kminus = 0;

    loop {
        if k == (width - 1) {
            if umin < num::zero() {
                // if segment_lower_bound is too high,
                // jump down.
                output.extend(iter::repeat(segment_lower_bound).take(kminus - k0 + 1));
                k0 = kminus + 1;
                sync_values(k0, &mut [&mut k, &mut kminus]);
                segment_lower_bound = input[kminus];
                umin = lambda;
                umax = segment_lower_bound + umin - segment_upper_bound;
            } else if umax > num::zero() {
                // if segment_upper_bound is too low,
                // jump up.
                output.extend(iter::repeat(segment_upper_bound).take(kplus - k0 + 1));
                k0 = kplus + 1;
                sync_values(k0, &mut [&mut k, &mut kplus]);
                segment_upper_bound = input[kplus];
                umax = minlambda;
                umin = segment_upper_bound + umax - segment_lower_bound;
            } else {
                // segment_lower_bound and segment_upper_bound is appropriate.
                segment_lower_bound += umin /
                                       num::FromPrimitive::from_usize(k - k0 + 1)
                    .expect("Unable to convert usize to num::FromPrimitive.");
                output.extend(iter::repeat(segment_lower_bound).take(k - k0 + 1));
                return output;
            }
        } else {
            umin += input[k + 1] - segment_lower_bound; // input 0 and 1
            umax += input[k + 1] - segment_upper_bound; // input 0 and 1
            if umin < minlambda {
                output.extend(iter::repeat(segment_lower_bound).take(kminus - k0 + 1));
                k0 = kminus + 1;
                sync_values(k0, &mut [&mut k, &mut kminus, &mut kplus]);
                segment_lower_bound = input[kplus];
                segment_upper_bound = segment_lower_bound + twolambda;
                umin = lambda;
                umax = minlambda;
            } else if umax > lambda {
                output.extend(iter::repeat(segment_upper_bound).take(kplus - k0 + 1));
                k0 = kplus + 1;
                sync_values(k0, &mut [&mut k, &mut kminus, &mut kplus]);
                segment_upper_bound = input[kplus];
                segment_lower_bound = segment_upper_bound - twolambda;
                umin = lambda;
                umax = minlambda;
            } else {
                k += 1;
                if umin >= lambda {
                    kminus = k;
                    segment_lower_bound = (segment_lower_bound + (umin - lambda)) /
                                          num::FromPrimitive::from_usize(kminus - k0 + 1)
                        .expect("Unable to convert usize to num::FromPrimitive.");
                    umin = lambda;
                }
                if umax <= minlambda {
                    kplus = k;
                    segment_upper_bound += (umax + lambda) /
                                           num::FromPrimitive::from_usize(kplus - k0 + 1)
                        .expect("Unable to convert usize to num::FromPrimitive.");
                    umax = minlambda;
                }
            }
        }
    }
}

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

    #[test]
    fn tautstring_test_input_output_length() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = tautstring_denoise(&input, 0.0);
        assert_eq!(input.len(), output.len());
    }

    #[test]
    fn tautstring_test_zero_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = tautstring_denoise(&input, 0.0);
        let output_expected = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.0001);
        }
    }

    #[test]
    fn tautstring_test_large_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = tautstring_denoise(&input, 100.0);
        // The expected output is taken from the Laurent Condat's C
        // implementation.
        let output_expected = vec![4.925, 4.925, 4.925, 4.925, 4.925, 4.925, 4.925, 4.925];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.0001);
        }
    }

    #[test]
    fn tautstring_test_moderate_lambda() {
        let input = vec![111.0, 422.1, 145.2, 248.2, 871.4, 675.2, 436.2, 310.1];
        let output = tautstring_denoise(&input, 5.0);
        // The expected output is taken from the Laurent Condat's C
        // implementation.
        let output_expected = vec![116.0, 412.100006, 155.199997, 248.199997, 861.400024,
                                   675.200012, 436.200012, 315.100006];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.0001);
        }
    }

    #[test]
    fn condat_test_input_output_length() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = condat_denoise(&input, 0.0);
        assert_eq!(input.len(), output.len());
    }

    #[test]
    fn condat_test_zero_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = condat_denoise(&input, 0.0);
        let output_expected = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        assert_eq!(output, output_expected);
    }

    #[test]
    fn condat_test_large_lambda() {
        let input = vec![111.0, 422.1, 145.2, 248.2, 871.4, 675.2, 436.2, 310.1];
        let output = condat_denoise(&input, 10000.0);
        // The expected output is taken from the Laurent Condat's C
        // implementation.
        let output_expected = vec![402.425049, 402.425049, 402.425049, 402.425049, 402.425049,
                                   402.425049, 402.425049, 402.425049];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.0001);
        }
    }

    #[test]
    fn condat_test_moderate_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        let output = condat_denoise(&input, 3.0);
        // The expected output is taken from the Laurent Condat's C
        // implementation.
        let output_expected = vec![3.050000, 3.050000, 4.933333, 4.933333, 4.933333, 5.200000,
                                   6.200000, 7.100000];
        for i in 0..input.len() {
            let output_data = output[i] as f64;
            let expected_data = output_expected[i] as f64;
            assert!((output_data - expected_data).abs() <= 0.000001);
        }
    }

    #[test]
    #[should_panic]
    fn condat_test_negative_lambda() {
        let input = vec![1.0, 2.1, 5.2, 8.2, 1.4, 5.2, 6.2, 10.1];
        condat_denoise(&input, -1.0);
    }

    #[test]
    #[should_panic]
    fn condat_test_empty_input() {
        let input = vec![];
        condat_denoise(&input, 1.0);
    }
}
<|endoftext|>


<commit_before>mod reader;
mod writer;

use tracker::{self, Announce, Response, TrackerResponse, Result, ResultExt, Error, ErrorKind, dns};
use std::time::{Instant, Duration};
use std::mem;
use {PEER_ID, bencode, amy};
use self::writer::Writer;
use self::reader::Reader;
use std::io;
use std::collections::HashMap;
use std::net::SocketAddr;
use url::percent_encoding::percent_encode_byte;
use url::Url;
use slog::Logger;
use socket::TSocket;

const TIMEOUT_MS: u64 = 5_000;

pub struct Handler {
    reg: amy::Registrar,
    connections: HashMap<usize, Tracker>,
    l: Logger,
}

enum Event {
    DNSResolved(dns::QueryResponse),
    Readable,
    Writable,
}

struct Tracker {
    torrent: usize,
    last_updated: Instant,
    state: TrackerState,
}

enum TrackerState {
    Error,
    ResolvingDNS {
        sock: TSocket,
        req: Vec<u8>,
        port: u16,
    },
    Writing { sock: TSocket, writer: Writer },
    Reading { sock: TSocket, reader: Reader },
    Complete(TrackerResponse),
}

impl TrackerState {
    fn new(sock: TSocket, req: Vec<u8>, port: u16) -> TrackerState {
        TrackerState::ResolvingDNS { sock, req, port }
    }

    fn handle(&mut self, event: Event) -> Result<Option<TrackerResponse>> {
        let s = mem::replace(self, TrackerState::Error);
        let n = s.next(event)?;
        if let TrackerState::Complete(r) = n {
            Ok(Some(r))
        } else {
            mem::replace(self, n);
            Ok(None)
        }
    }

    fn next(self, event: Event) -> Result<TrackerState> {
        match (self, event) {
            (TrackerState::ResolvingDNS { sock, req, port }, Event::DNSResolved(r)) => {
                let addr = SocketAddr::new(r.res?, port);
                sock.connect(addr).chain_err(|| ErrorKind::IO)?;
                Ok(TrackerState::Writing {
                    sock,
                    writer: Writer::new(req),
                }.next(Event::Writable)?)
            }
            (TrackerState::Writing {
                 mut sock,
                 mut writer,
             },
             Event::Writable) => {
                match writer.writable(&mut sock.conn)? {
                    Some(()) => {
                        let r = Reader::new();
                        Ok(TrackerState::Reading { sock, reader: r }.next(Event::Readable)?)
                    }
                    None => Ok(TrackerState::Writing { sock, writer }),
                }
            }
            (TrackerState::Reading {
                 mut sock,
                 mut reader,
             },
             Event::Readable) => {
                if reader.readable(&mut sock.conn)? {
                    let data = reader.consume();
                    let content = bencode::decode_buf(&data).chain_err(|| {
                        ErrorKind::InvalidResponse("Invalid BEncoded response!")
                    })?;
                    let resp = TrackerResponse::from_bencode(content)?;
                    Ok(TrackerState::Complete(resp))
                } else {
                    Ok(TrackerState::Reading { sock, reader })
                }
            }
            (s @ TrackerState::Writing { .. }, _) |
            (s @ TrackerState::Reading { .. }, _) |
            (s @ TrackerState::ResolvingDNS { .. }, _) => Ok(s),
            _ => bail!("Unknown state transition encountered!"),
        }
    }
}

impl Handler {
    pub fn new(reg: &amy::Registrar, l: Logger) -> io::Result<Handler> {
        Ok(Handler {
            reg: reg.try_clone()?,
            connections: HashMap::new(),
            l,
        })
    }

    pub fn active_requests(&self) -> usize {
        self.connections.len()
    }

    pub fn complete(&self) -> bool {
        self.connections.is_empty()
    }

    pub fn contains(&self, id: usize) -> bool {
        self.connections.contains_key(&id)
    }

    pub fn dns_resolved(&mut self, resp: dns::QueryResponse) -> Option<Response> {
        let id = resp.id;
        debug!(self.l, "Received a DNS resp for {:?}", id);
        let resp = if let Some(trk) = self.connections.get_mut(&id) {
            trk.last_updated = Instant::now();
            match trk.state.handle(Event::DNSResolved(resp)) {
                Ok(_) => None,
                Err(e) => Some((trk.torrent, Err(e))),
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
        }
        resp
    }

    pub fn writable(&mut self, id: usize) -> Option<Response> {
        let resp = if let Some(trk) = self.connections.get_mut(&id) {
            trk.last_updated = Instant::now();
            match trk.state.handle(Event::Writable) {
                Ok(_) => None,
                Err(e) => Some((trk.torrent, Err(e))),
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
        }
        resp
    }

    pub fn readable(&mut self, id: usize) -> Option<Response> {
        let resp = if let Some(trk) = self.connections.get_mut(&id) {
            trk.last_updated = Instant::now();
            match trk.state.handle(Event::Readable) {
                Ok(Some(r)) => {
                    debug!(
                        self.l,
                        "Announce response received for {:?} succesfully",
                        id
                    );
                    Some((trk.torrent, Ok(r)))
                }
                Ok(None) => None,
                Err(e) => Some((trk.torrent, Err(e))),
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
        }
        resp
    }

    pub fn tick(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        let l = &self.l;
        self.connections.retain(
            |id, trk| if trk.last_updated.elapsed() >
                Duration::from_millis(TIMEOUT_MS)
            {
                resps.push((trk.torrent, Err(ErrorKind::Timeout.into())));
                debug!(l, "Announce {:?} timed out", id);
                false
            } else {
                true
            },
        );
        resps
    }

    pub fn new_announce(
        &mut self,
        req: Announce,
        url: &Url,
        dns: &mut dns::Resolver,
    ) -> Result<()> {
        debug!(self.l, "Received a new announce req for {:?}", url);
        let mut http_req = Vec::with_capacity(50);
        // Encode GET req
        http_req.extend_from_slice(b"GET ");

        // Encode the URL
        http_req.extend_from_slice(url.path().as_bytes());
        http_req.extend_from_slice(b"?");
        append_query_pair(&mut http_req, "info_hash", &encode_param(&req.hash));
        append_query_pair(&mut http_req, "peer_id", &encode_param(&PEER_ID[..]));
        append_query_pair(&mut http_req, "uploaded", &req.uploaded.to_string());
        append_query_pair(&mut http_req, "downloaded", &req.downloaded.to_string());
        append_query_pair(&mut http_req, "left", &req.left.to_string());
        append_query_pair(&mut http_req, "compact", "1");
        append_query_pair(&mut http_req, "port", &req.port.to_string());
        if let Some(nw) = req.num_want {
            append_query_pair(&mut http_req, "numwant", &nw.to_string());
        }
        match req.event {
            Some(tracker::Event::Started) => {
                append_query_pair(&mut http_req, "event", "started");
            }
            Some(tracker::Event::Stopped) => {
                append_query_pair(&mut http_req, "event", "stopped");
            }
            Some(tracker::Event::Completed) => {
                append_query_pair(&mut http_req, "event", "completed");
            }
            None => {}
        }

        // Encode HTTP protocol
        http_req.extend_from_slice(b" HTTP/1.1\r\n");
        // Encode host header
        http_req.extend_from_slice(b"Host: ");
        let host = url.host_str().ok_or_else(|| {
            Error::from(ErrorKind::InvalidRequest(
                "Tracker announce url has no host!".to_owned(),
            ))
        })?;
        let port = url.port().unwrap_or(80);
        http_req.extend_from_slice(host.as_bytes());
        http_req.extend_from_slice(b"\r\n");
        // Encode empty line to terminate request
        http_req.extend_from_slice(b"\r\n");

        // Setup actual connection and start DNS query
        let (id, sock) = TSocket::new_v4(&self.reg).chain_err(|| ErrorKind::IO)?;
        self.connections.insert(
            id,
            Tracker {
                last_updated: Instant::now(),
                torrent: req.id,
                state: TrackerState::new(sock, http_req, port),
            },
        );

        debug!(self.l, "Dispatching DNS req, id {:?}", id);
        dns.new_query(id, host);

        Ok(())
    }
}

fn append_query_pair(s: &mut Vec<u8>, k: &str, v: &str) {
    s.extend_from_slice(k.as_bytes());
    s.extend_from_slice(b"=");
    s.extend_from_slice(v.as_bytes());
    s.extend_from_slice(b"&");
}

fn encode_param(data: &[u8]) -> String {
    let mut resp = String::new();
    for byte in data {
        resp.push_str(percent_encode_byte(*byte));
    }
    resp
}
<commit_msg>Properly URL encode client ID in HTTP announce<commit_after>mod reader;
mod writer;

use tracker::{self, Announce, Response, TrackerResponse, Result, ResultExt, Error, ErrorKind, dns};
use std::time::{Instant, Duration};
use std::mem;
use {PEER_ID, bencode, amy};
use self::writer::Writer;
use self::reader::Reader;
use std::io;
use std::collections::HashMap;
use std::net::SocketAddr;
use url::percent_encoding::{percent_encode, DEFAULT_ENCODE_SET};
use url::Url;
use slog::Logger;
use socket::TSocket;

const TIMEOUT_MS: u64 = 5_000;

pub struct Handler {
    reg: amy::Registrar,
    connections: HashMap<usize, Tracker>,
    l: Logger,
}

enum Event {
    DNSResolved(dns::QueryResponse),
    Readable,
    Writable,
}

struct Tracker {
    torrent: usize,
    last_updated: Instant,
    state: TrackerState,
}

enum TrackerState {
    Error,
    ResolvingDNS {
        sock: TSocket,
        req: Vec<u8>,
        port: u16,
    },
    Writing { sock: TSocket, writer: Writer },
    Reading { sock: TSocket, reader: Reader },
    Complete(TrackerResponse),
}

impl TrackerState {
    fn new(sock: TSocket, req: Vec<u8>, port: u16) -> TrackerState {
        TrackerState::ResolvingDNS { sock, req, port }
    }

    fn handle(&mut self, event: Event) -> Result<Option<TrackerResponse>> {
        let s = mem::replace(self, TrackerState::Error);
        let n = s.next(event)?;
        if let TrackerState::Complete(r) = n {
            Ok(Some(r))
        } else {
            mem::replace(self, n);
            Ok(None)
        }
    }

    fn next(self, event: Event) -> Result<TrackerState> {
        match (self, event) {
            (TrackerState::ResolvingDNS { sock, req, port }, Event::DNSResolved(r)) => {
                let addr = SocketAddr::new(r.res?, port);
                sock.connect(addr).chain_err(|| ErrorKind::IO)?;
                Ok(TrackerState::Writing {
                    sock,
                    writer: Writer::new(req),
                }.next(Event::Writable)?)
            }
            (TrackerState::Writing {
                 mut sock,
                 mut writer,
             },
             Event::Writable) => {
                match writer.writable(&mut sock.conn)? {
                    Some(()) => {
                        let r = Reader::new();
                        Ok(TrackerState::Reading { sock, reader: r }.next(Event::Readable)?)
                    }
                    None => Ok(TrackerState::Writing { sock, writer }),
                }
            }
            (TrackerState::Reading {
                 mut sock,
                 mut reader,
             },
             Event::Readable) => {
                if reader.readable(&mut sock.conn)? {
                    let data = reader.consume();
                    let content = bencode::decode_buf(&data).chain_err(|| {
                        ErrorKind::InvalidResponse("Invalid BEncoded response!")
                    })?;
                    let resp = TrackerResponse::from_bencode(content)?;
                    Ok(TrackerState::Complete(resp))
                } else {
                    Ok(TrackerState::Reading { sock, reader })
                }
            }
            (s @ TrackerState::Writing { .. }, _) |
            (s @ TrackerState::Reading { .. }, _) |
            (s @ TrackerState::ResolvingDNS { .. }, _) => Ok(s),
            _ => bail!("Unknown state transition encountered!"),
        }
    }
}

impl Handler {
    pub fn new(reg: &amy::Registrar, l: Logger) -> io::Result<Handler> {
        Ok(Handler {
            reg: reg.try_clone()?,
            connections: HashMap::new(),
            l,
        })
    }

    pub fn active_requests(&self) -> usize {
        self.connections.len()
    }

    pub fn complete(&self) -> bool {
        self.connections.is_empty()
    }

    pub fn contains(&self, id: usize) -> bool {
        self.connections.contains_key(&id)
    }

    pub fn dns_resolved(&mut self, resp: dns::QueryResponse) -> Option<Response> {
        let id = resp.id;
        debug!(self.l, "Received a DNS resp for {:?}", id);
        let resp = if let Some(trk) = self.connections.get_mut(&id) {
            trk.last_updated = Instant::now();
            match trk.state.handle(Event::DNSResolved(resp)) {
                Ok(_) => None,
                Err(e) => Some((trk.torrent, Err(e))),
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
        }
        resp
    }

    pub fn writable(&mut self, id: usize) -> Option<Response> {
        let resp = if let Some(trk) = self.connections.get_mut(&id) {
            trk.last_updated = Instant::now();
            match trk.state.handle(Event::Writable) {
                Ok(_) => None,
                Err(e) => Some((trk.torrent, Err(e))),
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
        }
        resp
    }

    pub fn readable(&mut self, id: usize) -> Option<Response> {
        let resp = if let Some(trk) = self.connections.get_mut(&id) {
            trk.last_updated = Instant::now();
            match trk.state.handle(Event::Readable) {
                Ok(Some(r)) => {
                    debug!(
                        self.l,
                        "Announce response received for {:?} succesfully",
                        id
                    );
                    Some((trk.torrent, Ok(r)))
                }
                Ok(None) => None,
                Err(e) => Some((trk.torrent, Err(e))),
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
        }
        resp
    }

    pub fn tick(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        let l = &self.l;
        self.connections.retain(
            |id, trk| if trk.last_updated.elapsed() >
                Duration::from_millis(TIMEOUT_MS)
            {
                resps.push((trk.torrent, Err(ErrorKind::Timeout.into())));
                debug!(l, "Announce {:?} timed out", id);
                false
            } else {
                true
            },
        );
        resps
    }

    pub fn new_announce(
        &mut self,
        req: Announce,
        url: &Url,
        dns: &mut dns::Resolver,
    ) -> Result<()> {
        debug!(self.l, "Received a new announce req for {:?}", url);
        let mut http_req = Vec::with_capacity(50);
        // Encode GET req
        http_req.extend_from_slice(b"GET ");

        // Encode the URL
        http_req.extend_from_slice(url.path().as_bytes());
        http_req.extend_from_slice(b"?");
        append_query_pair(&mut http_req, "info_hash", &encode_param(&req.hash));
        append_query_pair(&mut http_req, "peer_id", &encode_param(&PEER_ID[..]));
        append_query_pair(&mut http_req, "uploaded", &req.uploaded.to_string());
        append_query_pair(&mut http_req, "downloaded", &req.downloaded.to_string());
        append_query_pair(&mut http_req, "left", &req.left.to_string());
        append_query_pair(&mut http_req, "compact", "1");
        append_query_pair(&mut http_req, "port", &req.port.to_string());
        if let Some(nw) = req.num_want {
            append_query_pair(&mut http_req, "numwant", &nw.to_string());
        }
        match req.event {
            Some(tracker::Event::Started) => {
                append_query_pair(&mut http_req, "event", "started");
            }
            Some(tracker::Event::Stopped) => {
                append_query_pair(&mut http_req, "event", "stopped");
            }
            Some(tracker::Event::Completed) => {
                append_query_pair(&mut http_req, "event", "completed");
            }
            None => {}
        }

        // Encode HTTP protocol
        http_req.extend_from_slice(b" HTTP/1.1\r\n");
        // Encode host header
        http_req.extend_from_slice(b"Host: ");
        let host = url.host_str().ok_or_else(|| {
            Error::from(ErrorKind::InvalidRequest(
                "Tracker announce url has no host!".to_owned(),
            ))
        })?;
        let port = url.port().unwrap_or(80);
        http_req.extend_from_slice(host.as_bytes());
        http_req.extend_from_slice(b"\r\n");
        // Encode empty line to terminate request
        http_req.extend_from_slice(b"\r\n");

        // Setup actual connection and start DNS query
        let (id, sock) = TSocket::new_v4(&self.reg).chain_err(|| ErrorKind::IO)?;
        self.connections.insert(
            id,
            Tracker {
                last_updated: Instant::now(),
                torrent: req.id,
                state: TrackerState::new(sock, http_req, port),
            },
        );

        debug!(self.l, "Dispatching DNS req, id {:?}", id);
        dns.new_query(id, host);

        Ok(())
    }
}

fn append_query_pair(s: &mut Vec<u8>, k: &str, v: &str) {
    s.extend_from_slice(k.as_bytes());
    s.extend_from_slice(b"=");
    s.extend_from_slice(v.as_bytes());
    s.extend_from_slice(b"&");
}

fn encode_param(data: &[u8]) -> String {
    percent_encode(data, DEFAULT_ENCODE_SET).to_string()
}
<|endoftext|>


<commit_before>extern crate sha1;

use bencode;
use bencode::{Bencode, FromBencode};
use bencode::util::ByteString;
use std::net::Ipv4Addr;

use decoder;

#[derive(PartialEq, Debug)]
pub struct TrackerResponse {
    pub interval: u32,
    pub min_interval: Option<u32>,
    pub complete: u32,
    pub incomplete: u32,
    pub downloaded: u32,
    pub peers: Vec<Peer>,
}

impl TrackerResponse {
    pub fn parse(bytes: &[u8]) -> Result<TrackerResponse, decoder::Error> {
        let bencode = try!(bencode::from_buffer(bytes));
        FromBencode::from_bencode(&bencode)
    }
}

impl FromBencode for TrackerResponse {
    type Err = decoder::Error;

    fn from_bencode(bencode: &bencode::Bencode) -> Result<TrackerResponse, decoder::Error> {
        match bencode {
            &Bencode::Dict(ref m) => {
                let peers = get_field_as_bytes!(m, "peers").chunks(6).map(Peer::from_bytes).collect();

                let response = TrackerResponse{
                    interval: get_field!(m, "interval"),
                    min_interval: get_optional_field!(m, "min interval"),
                    complete: get_field!(m, "complete"),
                    incomplete: get_field!(m, "incomplete"),
                    downloaded: get_field!(m, "downloaded"),
                    peers: peers,
                };
                Ok(response)
            }
            _ => Err(decoder::Error::NotADict)
        }
    }
}

#[derive(PartialEq, Debug)]
pub struct Peer {
    pub ip: Ipv4Addr,
    pub port: u16,
}

impl Peer {
    fn from_bytes(v: &[u8]) -> Peer {
        let ip = Ipv4Addr::new(v[0], v[1], v[2], v[3]);
        let port = (v[4] as u16) * 256 + (v[5] as u16);
        Peer{ ip: ip, port: port }
    }
}
<commit_msg>Removed downloaded attribute from TrackerResponse, since it is not in the Spec<commit_after>extern crate sha1;

use bencode;
use bencode::{Bencode, FromBencode};
use bencode::util::ByteString;
use std::net::Ipv4Addr;

use decoder;

#[derive(PartialEq, Debug)]
pub struct TrackerResponse {
    pub interval: u32,
    pub min_interval: Option<u32>,
    pub complete: u32,
    pub incomplete: u32,
    pub peers: Vec<Peer>,
}

impl TrackerResponse {
    pub fn parse(bytes: &[u8]) -> Result<TrackerResponse, decoder::Error> {
        let bencode = try!(bencode::from_buffer(bytes));
        FromBencode::from_bencode(&bencode)
    }
}

impl FromBencode for TrackerResponse {
    type Err = decoder::Error;

    fn from_bencode(bencode: &bencode::Bencode) -> Result<TrackerResponse, decoder::Error> {
        match bencode {
            &Bencode::Dict(ref m) => {
                let peers = get_field_as_bytes!(m, "peers").chunks(6).map(Peer::from_bytes).collect();

                let response = TrackerResponse{
                    interval: get_field!(m, "interval"),
                    min_interval: get_optional_field!(m, "min interval"),
                    complete: get_field!(m, "complete"),
                    incomplete: get_field!(m, "incomplete"),
                    peers: peers,
                };
                Ok(response)
            }
            _ => Err(decoder::Error::NotADict)
        }
    }
}

#[derive(PartialEq, Debug)]
pub struct Peer {
    pub ip: Ipv4Addr,
    pub port: u16,
}

impl Peer {
    fn from_bytes(v: &[u8]) -> Peer {
        let ip = Ipv4Addr::new(v[0], v[1], v[2], v[3]);
        let port = (v[4] as u16) * 256 + (v[5] as u16);
        Peer{ ip: ip, port: port }
    }
}
<|endoftext|>


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

#![crate_name = "gfx"]
#![comment = "A lightweight graphics device manager for Rust"]
#![license = "ASL2"]
#![crate_type = "lib"]

#![feature(phase)]

//! An efficient, low-level, bindless graphics API for Rust. See [the
//! blog](http://gfx-rs.github.io/) for explanations and annotated examples.

#[phase(plugin, link)] extern crate log;
extern crate libc;

extern crate device;
extern crate render;

// public re-exports
pub use render::{DeviceHelper, Renderer};
pub use render::batch;
pub use render::mesh::{Attribute, Mesh, VertexFormat};
pub use render::mesh::{Slice, ToSlice};
pub use render::mesh::{VertexSlice, IndexSlice8, IndexSlice16, IndexSlice32};
pub use render::state::{DrawState, BlendAdditive, BlendAlpha};
pub use render::shade;
pub use render::target::{Frame, Plane, PlaneSurface, PlaneTexture};
pub use device::Device;
pub use device::{attrib, state, tex};
pub use device::with_slice;
pub use device::{BufferHandle, BufferInfo, RawBufferHandle, ShaderHandle};
pub use device::{ProgramHandle, SurfaceHandle, TextureHandle};
pub use device::{BufferUsage, UsageStatic, UsageDynamic, UsageStream};
pub use device::{VertexCount, InstanceCount};
pub use device::{PrimitiveType, Point, Line, LineStrip,
    TriangleList, TriangleStrip, TriangleFan};
pub use device::draw::CommandBuffer;
pub use device::shade::UniformValue;
pub use device::shade::{ValueI32, ValueF32};
pub use device::shade::{ValueI32Vector2, ValueI32Vector3, ValueI32Vector4};
pub use device::shade::{ValueF32Vector2, ValueF32Vector3, ValueF32Vector4};
pub use device::shade::{ValueF32Matrix2, ValueF32Matrix3, ValueF32Matrix4};
pub use device::shade::{ShaderSource, ProgramInfo};
pub use device::target::{ColorValue, ClearData, Mask, Layer, Level, Rect, Target};
pub use device::target::{COLOR, DEPTH, STENCIL};

// TODO: Remove this re-export once `gl_device` becomes a separate crate.
pub use device::gl_device::{GlDevice, GlCommandBuffer};

use render::batch::Context as BatchContext;
use render::batch::RefBatch;

/// A convenient wrapper suitable for single-threaded operation.
pub struct Graphics<D, C: device::draw::CommandBuffer> {
    /// Graphics device.
    pub device: D,
    /// Renderer front-end.
    pub renderer: Renderer<C>,
    /// Hidden batch context.
    context: BatchContext,
}

impl<D: device::Device<C>, C: device::draw::CommandBuffer> Graphics<D, C> {
    /// Create a new graphics wrapper.
    pub fn new(mut device: D) -> Graphics<D, C> {
        let rend = device.create_renderer();
        Graphics {
            device: device,
            renderer: rend,
            context: BatchContext::new(),
        }
    }

    /// Create a new ref batch.
    pub fn make_batch<L, T: shade::ShaderParam<L>>(&mut self,
                      program: &ProgramHandle,
                      mesh: &Mesh,
                      slice: Slice,
                      state: &DrawState)
                      -> Result<RefBatch<L, T>, batch::BatchError> {
        self.context.batch(mesh, slice, program, state)
    }

    /// Clear the `Frame` as the `ClearData` specifies.
    pub fn clear(&mut self, data: ClearData, mask: Mask, frame: &Frame) {
        self.renderer.clear(data, mask, frame);
        self.device.submit(self.renderer.as_buffer());
        self.renderer.reset();
    }

    /// Draw a ref batch.
    pub fn draw<'a, L, T: shade::ShaderParam<L>>(&'a mut self,
        batch: &'a RefBatch<L, T>, data: &'a T, frame: &Frame) {
        self.renderer.draw(&(batch, data, &self.context), frame);
        self.device.submit(self.renderer.as_buffer());
        self.renderer.reset();
    }

    /// Submit the internal command buffer and reset for the next frame.
    pub fn end_frame(&mut self) { }
}
<commit_msg>Revert "Make `Graphics` submit all calls instantly"<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_name = "gfx"]
#![comment = "A lightweight graphics device manager for Rust"]
#![license = "ASL2"]
#![crate_type = "lib"]

#![feature(phase)]

//! An efficient, low-level, bindless graphics API for Rust. See [the
//! blog](http://gfx-rs.github.io/) for explanations and annotated examples.

#[phase(plugin, link)] extern crate log;
extern crate libc;

extern crate device;
extern crate render;

// public re-exports
pub use render::{DeviceHelper, Renderer};
pub use render::batch;
pub use render::mesh::{Attribute, Mesh, VertexFormat};
pub use render::mesh::{Slice, ToSlice};
pub use render::mesh::{VertexSlice, IndexSlice8, IndexSlice16, IndexSlice32};
pub use render::state::{DrawState, BlendAdditive, BlendAlpha};
pub use render::shade;
pub use render::target::{Frame, Plane, PlaneSurface, PlaneTexture};
pub use device::Device;
pub use device::{attrib, state, tex};
pub use device::with_slice;
pub use device::{BufferHandle, BufferInfo, RawBufferHandle, ShaderHandle};
pub use device::{ProgramHandle, SurfaceHandle, TextureHandle};
pub use device::{BufferUsage, UsageStatic, UsageDynamic, UsageStream};
pub use device::{VertexCount, InstanceCount};
pub use device::{PrimitiveType, Point, Line, LineStrip,
    TriangleList, TriangleStrip, TriangleFan};
pub use device::draw::CommandBuffer;
pub use device::shade::UniformValue;
pub use device::shade::{ValueI32, ValueF32};
pub use device::shade::{ValueI32Vector2, ValueI32Vector3, ValueI32Vector4};
pub use device::shade::{ValueF32Vector2, ValueF32Vector3, ValueF32Vector4};
pub use device::shade::{ValueF32Matrix2, ValueF32Matrix3, ValueF32Matrix4};
pub use device::shade::{ShaderSource, ProgramInfo};
pub use device::target::{ColorValue, ClearData, Mask, Layer, Level, Rect, Target};
pub use device::target::{COLOR, DEPTH, STENCIL};

// TODO: Remove this re-export once `gl_device` becomes a separate crate.
pub use device::gl_device::{GlDevice, GlCommandBuffer};

use render::batch::Context as BatchContext;
use render::batch::RefBatch;

/// A convenient wrapper suitable for single-threaded operation.
pub struct Graphics<D, C: device::draw::CommandBuffer> {
    /// Graphics device.
    pub device: D,
    /// Renderer front-end.
    pub renderer: Renderer<C>,
    /// Hidden batch context.
    context: BatchContext,
}

impl<D: device::Device<C>, C: device::draw::CommandBuffer> Graphics<D, C> {
    /// Create a new graphics wrapper.
    pub fn new(mut device: D) -> Graphics<D, C> {
        let rend = device.create_renderer();
        Graphics {
            device: device,
            renderer: rend,
            context: BatchContext::new(),
        }
    }

    /// Create a new ref batch.
    pub fn make_batch<L, T: shade::ShaderParam<L>>(&mut self,
                      program: &ProgramHandle,
                      mesh: &Mesh,
                      slice: Slice,
                      state: &DrawState)
                      -> Result<RefBatch<L, T>, batch::BatchError> {
        self.context.batch(mesh, slice, program, state)
    }

    /// Clear the `Frame` as the `ClearData` specifies.
    pub fn clear(&mut self, data: ClearData, mask: Mask, frame: &Frame) {
        self.renderer.clear(data, mask, frame)
    }

    /// Draw a ref batch.
    pub fn draw<'a, L, T: shade::ShaderParam<L>>(&'a mut self,
        batch: &'a RefBatch<L, T>, data: &'a T, frame: &Frame) {
        self.renderer.draw(&(batch, data, &self.context), frame)
    }

    /// Submit the internal command buffer and reset for the next frame.
    pub fn end_frame(&mut self) {
        self.device.submit(self.renderer.as_buffer());
        self.renderer.reset();
    }
}
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Derek Chiang <derekchiang93@gmail.com>
// (c) Christopher Brown <ccbrown112@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::io::{self, Write};
use std::iter::Peekable;
use std::str::Chars;
use uucore::InvalidEncodingHandling;

const NAME: &str = "echo";
const SUMMARY: &str = "display a line of text";
const USAGE: &str = "[OPTIONS]... [STRING]...";
const AFTER_HELP: &str = r#"
 Echo the STRING(s) to standard output.

 If -e is in effect, the following sequences are recognized:

 \\\\      backslash
 \\a      alert (BEL)
 \\b      backspace
 \\c      produce no further output
 \\e      escape
 \\f      form feed
 \\n      new line
 \\r      carriage return
 \\t      horizontal tab
 \\v      vertical tab
 \\0NNN   byte with octal value NNN (1 to 3 digits)
 \\xHH    byte with hexadecimal value HH (1 to 2 digits)
"#;

mod options {
    pub const STRING: &str = "STRING";
    pub const NO_NEWLINE: &str = "no_newline";
    pub const ENABLE_BACKSLASH_ESCAPE: &str = "enable_backslash_escape";
    pub const DISABLE_BACKSLASH_ESCAPE: &str = "disable_backslash_escape";
}

fn parse_code(
    input: &mut Peekable<Chars>,
    base: u32,
    max_digits: u32,
    bits_per_digit: u32,
) -> Option<char> {
    let mut ret = 0x8000_0000;
    for _ in 0..max_digits {
        match input.peek().and_then(|c| c.to_digit(base)) {
            Some(n) => ret = (ret << bits_per_digit) | n,
            None => break,
        }
        input.next();
    }
    std::char::from_u32(ret)
}

fn print_escaped(input: &str, mut output: impl Write) -> io::Result<bool> {
    let mut should_stop = false;

    let mut buffer = ['\\'; 2];

    let mut iter = input.chars().peekable();
    while let Some(mut c) = iter.next() {
        let mut start = 1;

        if c == '\\' {
            if let Some(next) = iter.next() {
                c = match next {
                    '\\' => '\\',
                    'a' => '\x07',
                    'b' => '\x08',
                    'c' => {
                        should_stop = true;
                        break;
                    }
                    'e' => '\x1b',
                    'f' => '\x0c',
                    'n' => '\n',
                    'r' => '\r',
                    't' => '\t',
                    'v' => '\x0b',
                    'x' => parse_code(&mut iter, 16, 2, 4).unwrap_or_else(|| {
                        start = 0;
                        next
                    }),
                    '0' => parse_code(&mut iter, 8, 3, 3).unwrap_or_else(|| {
                        start = 0;
                        next
                    }),
                    _ => {
                        start = 0;
                        next
                    }
                };
            }
        }

        buffer[1] = c;

        // because printing char slices is apparently not available in the standard library
        for ch in &buffer[start..] {
            write!(output, "{}", ch)?;
        }
    }

    Ok(should_stop)
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();
    let matches = App::new(executable!())
        .name(NAME)
        // TrailingVarArg specifies the final positional argument is a VarArg
        // and it doesn't attempts the parse any further args.
        // Final argument must have multiple(true) or the usage string equivalent.
        .setting(clap::AppSettings::TrailingVarArg)
        .setting(clap::AppSettings::AllowLeadingHyphen)
        .version(crate_version!())
        .about(SUMMARY)
        .after_help(AFTER_HELP)
        .usage(USAGE)
        .arg(
            Arg::with_name(options::NO_NEWLINE)
                .short("n")
                .help("do not output the trailing newline")
                .takes_value(false)
                .display_order(1),
        )
        .arg(
            Arg::with_name(options::ENABLE_BACKSLASH_ESCAPE)
                .short("e")
                .help("enable interpretation of backslash escapes")
                .takes_value(false)
                .display_order(2),
        )
        .arg(
            Arg::with_name(options::DISABLE_BACKSLASH_ESCAPE)
                .short("E")
                .help("disable interpretation of backslash escapes (default)")
                .takes_value(false)
                .display_order(3),
        )
        .arg(
            Arg::with_name(options::STRING)
                .multiple(true)
                .allow_hyphen_values(true),
        )
        .get_matches_from(args);

    let no_newline = matches.is_present(options::NO_NEWLINE);
    let escaped = matches.is_present(options::ENABLE_BACKSLASH_ESCAPE);
    let values: Vec<String> = match matches.values_of(options::STRING) {
        Some(s) => s.map(|s| s.to_string()).collect(),
        None => vec!["".to_string()],
    };

    match execute(no_newline, escaped, values) {
        Ok(_) => 0,
        Err(f) => {
            show_error!("{}", f);
            1
        }
    }
}

fn execute(no_newline: bool, escaped: bool, free: Vec<String>) -> io::Result<()> {
    let stdout = io::stdout();
    let mut output = stdout.lock();

    for (i, input) in free.iter().enumerate() {
        if i > 0 {
            write!(output, " ")?;
        }
        if escaped {
            let should_stop = print_escaped(&input, &mut output)?;
            if should_stop {
                break;
            }
        } else {
            write!(output, "{}", input)?;
        }
    }

    if !no_newline {
        writeln!(output)?;
    }

    Ok(())
}
<commit_msg>refactor/echo ~ fix `cargo clippy` complaint (clippy::needless_borrow)<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Derek Chiang <derekchiang93@gmail.com>
// (c) Christopher Brown <ccbrown112@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::io::{self, Write};
use std::iter::Peekable;
use std::str::Chars;
use uucore::InvalidEncodingHandling;

const NAME: &str = "echo";
const SUMMARY: &str = "display a line of text";
const USAGE: &str = "[OPTIONS]... [STRING]...";
const AFTER_HELP: &str = r#"
 Echo the STRING(s) to standard output.

 If -e is in effect, the following sequences are recognized:

 \\\\      backslash
 \\a      alert (BEL)
 \\b      backspace
 \\c      produce no further output
 \\e      escape
 \\f      form feed
 \\n      new line
 \\r      carriage return
 \\t      horizontal tab
 \\v      vertical tab
 \\0NNN   byte with octal value NNN (1 to 3 digits)
 \\xHH    byte with hexadecimal value HH (1 to 2 digits)
"#;

mod options {
    pub const STRING: &str = "STRING";
    pub const NO_NEWLINE: &str = "no_newline";
    pub const ENABLE_BACKSLASH_ESCAPE: &str = "enable_backslash_escape";
    pub const DISABLE_BACKSLASH_ESCAPE: &str = "disable_backslash_escape";
}

fn parse_code(
    input: &mut Peekable<Chars>,
    base: u32,
    max_digits: u32,
    bits_per_digit: u32,
) -> Option<char> {
    let mut ret = 0x8000_0000;
    for _ in 0..max_digits {
        match input.peek().and_then(|c| c.to_digit(base)) {
            Some(n) => ret = (ret << bits_per_digit) | n,
            None => break,
        }
        input.next();
    }
    std::char::from_u32(ret)
}

fn print_escaped(input: &str, mut output: impl Write) -> io::Result<bool> {
    let mut should_stop = false;

    let mut buffer = ['\\'; 2];

    let mut iter = input.chars().peekable();
    while let Some(mut c) = iter.next() {
        let mut start = 1;

        if c == '\\' {
            if let Some(next) = iter.next() {
                c = match next {
                    '\\' => '\\',
                    'a' => '\x07',
                    'b' => '\x08',
                    'c' => {
                        should_stop = true;
                        break;
                    }
                    'e' => '\x1b',
                    'f' => '\x0c',
                    'n' => '\n',
                    'r' => '\r',
                    't' => '\t',
                    'v' => '\x0b',
                    'x' => parse_code(&mut iter, 16, 2, 4).unwrap_or_else(|| {
                        start = 0;
                        next
                    }),
                    '0' => parse_code(&mut iter, 8, 3, 3).unwrap_or_else(|| {
                        start = 0;
                        next
                    }),
                    _ => {
                        start = 0;
                        next
                    }
                };
            }
        }

        buffer[1] = c;

        // because printing char slices is apparently not available in the standard library
        for ch in &buffer[start..] {
            write!(output, "{}", ch)?;
        }
    }

    Ok(should_stop)
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();
    let matches = App::new(executable!())
        .name(NAME)
        // TrailingVarArg specifies the final positional argument is a VarArg
        // and it doesn't attempts the parse any further args.
        // Final argument must have multiple(true) or the usage string equivalent.
        .setting(clap::AppSettings::TrailingVarArg)
        .setting(clap::AppSettings::AllowLeadingHyphen)
        .version(crate_version!())
        .about(SUMMARY)
        .after_help(AFTER_HELP)
        .usage(USAGE)
        .arg(
            Arg::with_name(options::NO_NEWLINE)
                .short("n")
                .help("do not output the trailing newline")
                .takes_value(false)
                .display_order(1),
        )
        .arg(
            Arg::with_name(options::ENABLE_BACKSLASH_ESCAPE)
                .short("e")
                .help("enable interpretation of backslash escapes")
                .takes_value(false)
                .display_order(2),
        )
        .arg(
            Arg::with_name(options::DISABLE_BACKSLASH_ESCAPE)
                .short("E")
                .help("disable interpretation of backslash escapes (default)")
                .takes_value(false)
                .display_order(3),
        )
        .arg(
            Arg::with_name(options::STRING)
                .multiple(true)
                .allow_hyphen_values(true),
        )
        .get_matches_from(args);

    let no_newline = matches.is_present(options::NO_NEWLINE);
    let escaped = matches.is_present(options::ENABLE_BACKSLASH_ESCAPE);
    let values: Vec<String> = match matches.values_of(options::STRING) {
        Some(s) => s.map(|s| s.to_string()).collect(),
        None => vec!["".to_string()],
    };

    match execute(no_newline, escaped, values) {
        Ok(_) => 0,
        Err(f) => {
            show_error!("{}", f);
            1
        }
    }
}

fn execute(no_newline: bool, escaped: bool, free: Vec<String>) -> io::Result<()> {
    let stdout = io::stdout();
    let mut output = stdout.lock();

    for (i, input) in free.iter().enumerate() {
        if i > 0 {
            write!(output, " ")?;
        }
        if escaped {
            let should_stop = print_escaped(input, &mut output)?;
            if should_stop {
                break;
            }
        } else {
            write!(output, "{}", input)?;
        }
    }

    if !no_newline {
        writeln!(output)?;
    }

    Ok(())
}
<|endoftext|>