<commit_before>//! The module that contains the code handling the HTTP response.

use std::convert::From;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::str;

use curl::easy::Easy;
use mime::Mime;

#[cfg(feature = "rustc-serialization")]
use rustc_serialize;

#[cfg(feature = "serde-serialization")]
use serde;
#[cfg(feature = "serde-serialization")]
use serde_json;

#[cfg(any(feature = "rustc-serialization", feature = "serde-serialization"))]
use std::io::{Error, ErrorKind};

/// Represents an HTTP response.
pub struct Response {
    body: Vec<u8>,
    handle: Easy,
    headers: Vec<(String, String)>,
    status_code: u16
}

impl Response {
    /// Creates a `Response` from the results of a successful request.
    ///
    /// You usually don't create a response this way, but get one as result
    /// from `Request.send(...)`.
    pub fn new(mut easy: Easy, headers: Vec<String>, body: Vec<u8>) -> Response {
        let headers =  {
            let mut vec = Vec::new();
            for header in headers {
                let splitted: Vec<_> = header.splitn(2, ": ")
                                             .map(|part| part.trim())
                                             .filter(|part| part.len() > 0)
                                             .collect();
                if splitted.len() != 2 {
                    continue;
                }

                vec.push((splitted[0].to_owned(), splitted[1].to_owned()));
            }
            vec
        };
        let status_code = easy.response_code().expect("Failed to get the response status code from cURL.") as u16;
        Response {
            body: body,
            handle: easy,
            headers: headers,
            status_code: status_code
        }
    }

    /// Gets the response body's bytes.
    pub fn body(&self) -> &[u8] {
        &self.body
    }

    /// Gets a mutable reference to the response body's bytes.
    pub fn body_mut(&mut self) -> &mut [u8] {
        &mut self.body
    }

    /// Attempts to read the body as UTF-8 string and returns the result.
    pub fn body_str(&self) -> Option<&str> {
        str::from_utf8(self.body()).ok()
    }

    /// Retreives the content type, if there is one.
    ///
    /// This function also returns none if there has been an error parsing
    /// the mime type.
    pub fn content_type(&self) -> Option<Mime> {
        self.header("Content-Type")
            .and_then(|h| h.parse::<Mime>().ok())
    }

    /// Attempts to get a single header value.
    ///
    /// If there are multiple headers with the same name, this method returns
    /// the first one. If you need to get access to the other values, use
    /// [`Response::headers()`](struct.Response.html#method.headers).
    pub fn header(&self, name: &str) -> Option<&String> {
        self.headers.iter().filter(|kvp| kvp.0 == name)
                           .nth(0)
                           .map(|kvp| &kvp.1)
    }

    /// Gets all response headers.
    pub fn headers(&self) -> &Vec<(String, String)> {
        &self.headers
    }

    /// Checks whether the returned status code represents a success
    /// (HTTP status code 2xx) or not.
    pub fn is_success(&self) -> bool {
        match self.status_code {
            200...299 => true,
            _ => false
        }
    }

    /// Attempts to decode the response body from JSON to an
    /// object of the given type.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "rustc-serialization")]
    pub fn json<T: rustc_serialize::Decodable>(&self) -> Result<T, Error> {
        let string = try!(str::from_utf8(&self.body).map_err(|err| Error::new(ErrorKind::InvalidData, err)));
        rustc_serialize::json::decode(string).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON to an
    /// object of the given type.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "serde-serialization")]
    pub fn json<T: serde::Deserialize>(&self) -> Result<T, Error> {
        serde_json::from_slice(self.body()).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON into an abstract
    /// JSON representation.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "rustc-serialization")]
    pub fn json_value(&self) -> Result<rustc_serialize::json::Json, Error> {
        let string = try!(str::from_utf8(&self.body).map_err(|err| Error::new(ErrorKind::InvalidData, err)));
        rustc_serialize::json::Json::from_str(string).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON into an abstract
    /// JSON representation.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "serde-serialization")]
    pub fn json_value(&self) -> Result<serde_json::Value, Error> {
        self.json::<serde_json::Value>()
    }

    /// Consumes the response and returns the underlying cURL handle
    /// used for the request so that it can be reused.
    ///
    /// Calling `from()` or `into()` does the same.
    pub fn reuse(self) -> Easy {
        self.handle
    }

    /// Gets the response status code.
    pub fn status_code(&self) -> u16 {
        self.status_code
    }
}

impl Debug for Response {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.debug_struct(stringify!(Response))
            .field("body_str", &self.body_str())
            .field("headers", &self.headers)
            .field("status_code", &self.status_code)
            .finish()
    }
}

impl From<Response> for Easy {
    fn from(response: Response) -> Self {
        response.reuse()
    }
}

impl From<Response> for Vec<u8> {
    fn from(response: Response) -> Self {
        response.body
    }
}

#[cfg(feature = "response-to-string")]
impl ::std::convert::TryFrom<Response> for String {
    type Err = ::std::string::FromUtf8Error;

    fn try_from(response: Response) -> Result<Self, Self::Err> {
        String::from_utf8(response.body)
    }
}<commit_msg>Add method to ensure a successful status code<commit_after>//! The module that contains the code handling the HTTP response.

use std::convert::From;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::str;

use curl::easy::Easy;
use mime::Mime;

#[cfg(feature = "rustc-serialization")]
use rustc_serialize;

#[cfg(feature = "serde-serialization")]
use serde;
#[cfg(feature = "serde-serialization")]
use serde_json;

#[cfg(any(feature = "rustc-serialization", feature = "serde-serialization"))]
use std::io::{Error, ErrorKind};

/// Represents an HTTP response.
pub struct Response {
    body: Vec<u8>,
    handle: Easy,
    headers: Vec<(String, String)>,
    status_code: u16
}

impl Response {
    /// Creates a `Response` from the results of a successful request.
    ///
    /// You usually don't create a response this way, but get one as result
    /// from `Request.send(...)`.
    pub fn new(mut easy: Easy, headers: Vec<String>, body: Vec<u8>) -> Response {
        let headers =  {
            let mut vec = Vec::new();
            for header in headers {
                let splitted: Vec<_> = header.splitn(2, ": ")
                                             .map(|part| part.trim())
                                             .filter(|part| part.len() > 0)
                                             .collect();
                if splitted.len() != 2 {
                    continue;
                }

                vec.push((splitted[0].to_owned(), splitted[1].to_owned()));
            }
            vec
        };
        let status_code = easy.response_code().expect("Failed to get the response status code from cURL.") as u16;
        Response {
            body: body,
            handle: easy,
            headers: headers,
            status_code: status_code
        }
    }

    /// Gets the response body's bytes.
    pub fn body(&self) -> &[u8] {
        &self.body
    }

    /// Gets a mutable reference to the response body's bytes.
    pub fn body_mut(&mut self) -> &mut [u8] {
        &mut self.body
    }

    /// Attempts to read the body as UTF-8 string and returns the result.
    pub fn body_str(&self) -> Option<&str> {
        str::from_utf8(self.body()).ok()
    }

    /// Retreives the content type, if there is one.
    ///
    /// This function also returns none if there has been an error parsing
    /// the mime type.
    pub fn content_type(&self) -> Option<Mime> {
        self.header("Content-Type")
            .and_then(|h| h.parse::<Mime>().ok())
    }

    /// Ensures a successful response status code.
    ///
    /// Otherwise returns `ErrorKind::InvalidData`.
    pub fn ensure_success(self) -> Result<Response, Error> {
        if self.is_success() {
            Ok(self)
        } else {
            let msg: &str = &format!("HTTP status code did not indicate success: {}.", self.status_code());
            Err(Error::new(ErrorKind::InvalidData, msg))
        }
    }

    /// Attempts to get a single header value.
    ///
    /// If there are multiple headers with the same name, this method returns
    /// the first one. If you need to get access to the other values, use
    /// [`Response::headers()`](struct.Response.html#method.headers).
    pub fn header(&self, name: &str) -> Option<&String> {
        self.headers.iter().filter(|kvp| kvp.0 == name)
                           .nth(0)
                           .map(|kvp| &kvp.1)
    }

    /// Gets all response headers.
    pub fn headers(&self) -> &Vec<(String, String)> {
        &self.headers
    }

    /// Checks whether the returned status code represents a success
    /// (HTTP status code 2xx) or not.
    pub fn is_success(&self) -> bool {
        match self.status_code {
            200...299 => true,
            _ => false
        }
    }

    /// Attempts to decode the response body from JSON to an
    /// object of the given type.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "rustc-serialization")]
    pub fn json<T: rustc_serialize::Decodable>(&self) -> Result<T, Error> {
        let string = try!(str::from_utf8(&self.body).map_err(|err| Error::new(ErrorKind::InvalidData, err)));
        rustc_serialize::json::decode(string).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON to an
    /// object of the given type.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "serde-serialization")]
    pub fn json<T: serde::Deserialize>(&self) -> Result<T, Error> {
        serde_json::from_slice(self.body()).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON into an abstract
    /// JSON representation.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "rustc-serialization")]
    pub fn json_value(&self) -> Result<rustc_serialize::json::Json, Error> {
        let string = try!(str::from_utf8(&self.body).map_err(|err| Error::new(ErrorKind::InvalidData, err)));
        rustc_serialize::json::Json::from_str(string).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON into an abstract
    /// JSON representation.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "serde-serialization")]
    pub fn json_value(&self) -> Result<serde_json::Value, Error> {
        self.json::<serde_json::Value>()
    }

    /// Gets the response status code.
    pub fn status_code(&self) -> u16 {
        self.status_code
    }
}

impl Debug for Response {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.debug_struct(stringify!(Response))
            .field("body_str", &self.body_str())
            .field("headers", &self.headers)
            .field("status_code", &self.status_code)
            .finish()
    }
}

impl From<Response> for Easy {
    /// Consumes the response and returns the underlying cURL handle
    /// used for the request so that it can be reused.
    fn from(response: Response) -> Self {
        response.handle
    }
}

impl From<Response> for Vec<u8> {
    fn from(response: Response) -> Self {
        response.body
    }
}

#[cfg(feature = "response-to-string")]
impl ::std::convert::TryFrom<Response> for String {
    type Err = ::std::string::FromUtf8Error;

    fn try_from(response: Response) -> Result<Self, Self::Err> {
        String::from_utf8(response.body)
    }
}<|endoftext|>


<commit_before>#![feature(collections, step_by)]
#![cfg_attr(test, feature(test))]

mod vec;
mod primitive;
mod group;
mod render;

pub use render::{Scene, Renderer, RenderOptions, PPMStdoutRGBABufferWriter, FileOrAnyWriter};

<commit_msg>fix(lib): work with latest nightly<commit_after>#![feature(step_by, clone_from_slice)]
#![cfg_attr(test, feature(test))]

mod vec;
mod primitive;
mod group;
mod render;

pub use render::{Scene, Renderer, RenderOptions, PPMStdoutRGBABufferWriter, FileOrAnyWriter};
<|endoftext|>


<commit_before>// Snow -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015  Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::num::{NumCast, Int, UnsignedInt};
use bitstream::Bitstream;
use error::{FlacError, FlacResult};

#[deriving(Copy, Show)] // TODO: this should not implement Show.
enum SubframeType {
    Constant,
    Verbatim,
    Fixed(u8),
    Lpc(u8)
}

#[deriving(Copy)]
struct SubframeHeader {
    sf_type: SubframeType,
    wasted_bits_per_sample: u8
}

fn read_subframe_header(input: &mut Bitstream) -> FlacResult<SubframeHeader> {
    // The first bit must be a 0 padding bit.
    if 0 != try!(input.read_leq_u8(1)) {
        return Err(FlacError::InvalidSubframeHeader);
    }

    // Next is a 6-bit subframe type.
    let sf_type = match try!(input.read_leq_u8(6)) {
        0 => SubframeType::Constant,
        1 => SubframeType::Verbatim,

        // Bit patterns 00001x, 0001xx and 01xxxx are reserved, this library
        // would not know how to handle them, so this is an error.
        n if (n & 0b111_110 == 0b000_010)
          || (n & 0b111_100 == 0b000_100)
          || (n & 0b110_000 == 0b010_000) => {
            return Err(FlacError::InvalidSubframeHeader);
        }

        n if n & 0b111_000 == 0b001_000 => {
            let order = n & 0b000_111;

            // A fixed frame has order up to 4, other bit patterns are reserved.
            if order > 4 { return Err(FlacError::InvalidSubframeHeader); }

            SubframeType::Fixed(order)
        }

        // The only possibility left is bit pattern 1xxxxx, an LPC subframe.
        n => {
            // The xxxxx bits are the order minus one.
            let order_mo = n & 0b011_111;
            SubframeType::Lpc(order_mo + 1)
        }
    };

    // Next bits indicates whether there are wasted bits per sample.
    let wastes_bits = 1 == try!(input.read_leq_u8(1));

    // If so, k - 1 zero bits follow, where k is the number of wasted bits.
    let wasted_bits = if !wastes_bits {
        0
    } else {
        let mut wbits = 1;
        while 1 != try!(input.read_leq_u8(1)) {
            wbits = wbits + 1;
        }
        wbits
    };

    let subframe_header = SubframeHeader {
        sf_type: sf_type,
        wasted_bits_per_sample: wasted_bits
    };
    Ok(subframe_header)
}

/// Given a signed two's complement integer in the `bits` least significant
/// bits of `val`, extends the sign bit to a valid 16-bit signed integer.
fn extend_sign(val: u16, bits: u8) -> i16 {
    let sign_bit = val >> (bits as uint - 1);

    // Extend the sign bit into the remaining bits.
    let sign_extension = range(bits as uint, 16)
                         .fold(0, |s, i| s | (sign_bit << i));

    // Note: overflow in the cast is intended.
    (val | sign_extension) as i16
}

/// Decodes a signed number from Rice coding to the two's complement.
///
/// The Rice coding used by FLAC operates on unsigned integers, but the
/// residual is signed. The mapping is done as follows:
///
///      0 -> 0
///     -1 -> 1
///      1 -> 2
///     -2 -> 3
///      2 -> 4
///      etc.
///
/// This function takes the unsigned value and converts it into a signed
/// number. The return type still has unsigned type, because arithmetic relies
/// on overflow.
fn rice_to_signed<Sample>(val: Sample) -> Sample where Sample: UnsignedInt {
    // This uses bitwise arithmetic, because a literal cannot have type `Sample`,
    // I believe this is the most concise way to express the decoding.
    let sample_max: Sample = Int::max_value();
    if val & Int::one() == Int::one() {
        val >> 1
    } else {
        sample_max - (val >> 1)
    }
}

pub struct SubframeDecoder<'r, Sample> {
    bits_per_sample: u8,
    input: &'r mut Bitstream<'r>
}

impl<'r, Sample> SubframeDecoder<'r, Sample> where Sample: UnsignedInt {
    /// Creates a new subframe decoder capable of decoding several subframes.
    ///
    /// The size of the `Sample` type must be wide enough to accomodate for
    /// `bits_per_sample` bits per sample.
    pub fn new(bits_per_sample: u8, input: &'r mut Bitstream<'r>)
               -> SubframeDecoder<'r, Sample> {
        // The sample type should be wide enough to accomodate for all bits of
        // the stream, but this can be verified at a higher level than here.
        // Still, it is a good idea to make the assumption explicit.
        use std::mem::size_of;
        debug_assert!(bits_per_sample as uint <= size_of::<Sample>() * 8);

        SubframeDecoder { bits_per_sample: bits_per_sample, input: input }
    }

    /// Decodes the subframe into the provided block-size buffer.
    ///
    /// It is assumed that the length of the buffer is the block size.
    pub fn decode(&mut self, buffer: &mut [Sample]) -> FlacResult<()> {
        // First up is the subframe header.
        let header = try!(read_subframe_header(self.input));

        // Then decode the subframe, properly per type.
        println!("encountered subframe of type {}",
                 header.sf_type); // TODO: Remove this.
        match header.sf_type {
            SubframeType::Constant => try!(self.decode_constant(buffer)),
            SubframeType::Verbatim => try!(self.decode_verbatim(buffer)),
            SubframeType::Lpc(ord) => try!(self.decode_lpc(ord, buffer)),
            _ => { } // TODO: implement other decoders
        }

        // Finally, everything must be shifted by 'wasted bits per sample' to
        // the left. Note: it might be better performance-wise to do this on
        // the fly while decoding, that could be done if this is a bottleneck.
        if header.wasted_bits_per_sample > 0 {
            for s in buffer.iter_mut() {
                *s = *s << header.wasted_bits_per_sample as uint;
            }
        }

        println!("subframe decoded"); // TODO: Remove this.
        Ok(())
    }

    fn decode_residual(&mut self, block_size: u16,
                       buffer: &mut [Sample]) -> FlacResult<()> {
        // Residual starts with two bits of coding method.
        let method = try!(self.input.read_leq_u8(2));
        match method {
            0b00 => self.decode_partitioned_rice(block_size, buffer),
            0b01 => self.decode_partitioned_rice2(block_size, buffer),
            _ => Err(FlacError::InvalidResidual) // 10 and 11 are reserved.
        }
    }

    fn decode_partitioned_rice(&mut self, block_size: u16,
                               buffer: &mut [Sample]) -> FlacResult<()> {
        println!("  decoding partitioned Rice, bs = {}, buffer.len = {}",
                block_size, buffer.len()); // TODO: remove this.

        // First are 4 bits partition order.
        let order = try!(self.input.read_leq_u8(4));

        // There are 2^order partitions. Note: the specification states a 4-bit
        // partition order, so the order is at most 31, so there could be 2^31
        // partitions, but the block size is a 16-bit number, so there are at
        // most 2^16 - 1 samples in the block. No values have been marked as
        // invalid by the specification though. Therefore use an u32 for the
        // number of partitions, to avoid division by 0 in the number of samples.
        let n_partitions = 1u32 << order as uint;
        let n_samples = block_size as uint / n_partitions as uint;
        let n_warm_up = block_size as uint - buffer.len();

        // The partition size must be at least as big as the number of warm-up
        // samples.
        if n_warm_up > n_samples { return Err(FlacError::InvalidResidual); }

        println!("  order: {}, partitions: {}, samples: {}",
                 order, n_partitions, n_samples); // TODO: Remove this.

        let mut start = 0u;
        for i in range(0, n_partitions) {
            let partition_size = n_samples - if i == 0 { n_warm_up } else { 0 };
            println!("  > decoding partition {}, from {} to {}",
                     i, start, start + partition_size); // TODO: Remove this.
            try!(self.decode_rice_partition(buffer.slice_mut(start,
                                            start + partition_size)));
            start = start + partition_size;
        }

        Ok(())
    }

    fn decode_rice_partition(&mut self,
                             buffer: &mut [Sample]) -> FlacResult<()> {
        // The Rice partition starts with 4 bits Rice parameter.
        let rice_param = try!(self.input.read_leq_u8(4));

        // 1111 is an escape code that indicates unencoded binary.
        if rice_param == 0b1111 {
            // For unencoded binary, there are five bits indicating bits-per-sample.
            let bps = try!(self.input.read_leq_u8(5));

            // There cannot be more bits per sample than the sample type.
            if self.bits_per_sample < bps {
                return Err(FlacError::InvalidBitsPerSample);
            }

            panic!("unencoded binary is not yet implemented"); // TODO
        } else {
            let one: Sample = Int::one();
            let factor = one << rice_param as uint;
            let max_sample: Sample = Int::max_value();
            let max_q = max_sample / factor;

            // TODO: It is possible for the rice_param to be larger than the
            // sample width, which would be invalid. Check for that.

            for sample in buffer.iter_mut() {
                // First part of the sample is the quotient, unary encoded.
                // This means that there are q zeroes, and then a one. There
                // should not be more than max_q consecutive zeroes.
                let mut q: Sample = Int::zero();
                while try!(self.input.read_leq_u8(1)) == 0 {
                    if q == max_q { return Err(FlacError::InvalidRiceCode); }
                    q = q + Int::one();
                }

                // What follows is the remainder in `rice_param` bits. The
                // unwrap is safe, because any integer is at least 8-bit. Also,
                // r < factor because we read `rice_param` bits.
                let r_u8 = try!(self.input.read_leq_u8(rice_param));
                let r: Sample = NumCast::from(r_u8).unwrap();
                // TODO: use std::num::Cast instead of NumCast::from.

                *sample = rice_to_signed(q * factor + r);
            }
        }

        Ok(())
    }

    fn decode_partitioned_rice2(&mut self, block_size: u16,
                                buffer: &mut [Sample]) -> FlacResult<()> {
        println!("  decoding partitioned Rice 2"); // TODO: Remove this.
        panic!("partitioned_rice2 is not yet implemented"); // TODO
        Ok(())
    }

    fn decode_constant(&mut self, buffer: &mut [Sample]) -> FlacResult<()> {
        // A constant block has <bits per sample> bits: the value of all
        // samples. The unwrap is safe, because it has been verified before
        // that the `Sample` type is wide enough for the bits per sample.
        let sample_u32 = try!(self.input.read_leq_u32(self.bits_per_sample));
        let sample = NumCast::from(sample_u32).unwrap();

        for s in buffer.iter_mut() {
            *s = sample;
        }

        Ok(())
    }

    fn decode_verbatim(&mut self, buffer: &mut [Sample]) -> FlacResult<()> {
        // A verbatim block stores samples without encoding whatsoever.
        for s in buffer.iter_mut() {
            // The unwrap is safe, because it has been verified before that the
            // `Sample` type is wide enough for the bits per sample.
            let sample_u32 = try!(self.input.read_leq_u32(self.bits_per_sample));
            *s = NumCast::from(sample_u32).unwrap();
        }

        Ok(())
    }

    fn decode_lpc(&mut self, order: u8, buffer: &mut [Sample])
                  -> FlacResult<()> {
        println!("begin decoding of LPC subframe"); // TODO: Remove this.
        // There are order * bits per sample unencoded warm-up sample bits.
        for i in range(0, order as uint) {
            // The unwrap is safe, because it has been verified before that the
            // `Sample` type is wide enough for the bits per sample.
            let sample_u32 = try!(self.input.read_leq_u32(self.bits_per_sample));
            buffer[i] = NumCast::from(sample_u32).unwrap();
        }

        // Next are four bits quantised linear predictor coefficient precision - 1.
        let qlp_precision = try!(self.input.read_leq_u8(4)) + 1;

        // The bit pattern 1111 is invalid.
        if qlp_precision - 1 == 0b1111 {
            return Err(FlacError::InvalidSubframe);
        }

        // Next are five bits quantized linear predictor coefficient shift,
        // in signed two's complement. Read 5 bits and then extend the sign bit.
        let qlp_shift_unsig = try!(self.input.read_leq_u16(5));
        let qlp_shift = extend_sign(qlp_shift_unsig, 5) as uint;

        println!("  lpc: qlp_precision = {}, qlp_shift = {}",
                 qlp_precision, qlp_shift); // TODO: Remove this.

        // Finally, the coefficients themselves.
        // TODO: get rid of the allocation by pre-allocating a vector in the decoder.
        let mut coefficients = Vec::new();
        for _ in range(0, order) {
            let coef_unsig = try!(self.input.read_leq_u16(qlp_precision));
            let coef = extend_sign(coef_unsig, qlp_precision);
            coefficients.push(coef);
            println!("  > coef = {}", coef); // TODO: Remove this.
        }

        // Next up is the residual. We decode it into the buffer directly, the
        // predictor contributions will be added in a second pass. The first
        // `order` samples have been decoded already, so continue after that.
        try!(self.decode_residual(buffer.len() as u16,
                                  buffer.slice_from_mut(order as uint)));

        // TODO: do prediction.

        Ok(())
    }
}
<commit_msg>do not use verbatim markup for example in comment<commit_after>// Snow -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015  Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::num::{NumCast, Int, UnsignedInt};
use bitstream::Bitstream;
use error::{FlacError, FlacResult};

#[deriving(Copy, Show)] // TODO: this should not implement Show.
enum SubframeType {
    Constant,
    Verbatim,
    Fixed(u8),
    Lpc(u8)
}

#[deriving(Copy)]
struct SubframeHeader {
    sf_type: SubframeType,
    wasted_bits_per_sample: u8
}

fn read_subframe_header(input: &mut Bitstream) -> FlacResult<SubframeHeader> {
    // The first bit must be a 0 padding bit.
    if 0 != try!(input.read_leq_u8(1)) {
        return Err(FlacError::InvalidSubframeHeader);
    }

    // Next is a 6-bit subframe type.
    let sf_type = match try!(input.read_leq_u8(6)) {
        0 => SubframeType::Constant,
        1 => SubframeType::Verbatim,

        // Bit patterns 00001x, 0001xx and 01xxxx are reserved, this library
        // would not know how to handle them, so this is an error.
        n if (n & 0b111_110 == 0b000_010)
          || (n & 0b111_100 == 0b000_100)
          || (n & 0b110_000 == 0b010_000) => {
            return Err(FlacError::InvalidSubframeHeader);
        }

        n if n & 0b111_000 == 0b001_000 => {
            let order = n & 0b000_111;

            // A fixed frame has order up to 4, other bit patterns are reserved.
            if order > 4 { return Err(FlacError::InvalidSubframeHeader); }

            SubframeType::Fixed(order)
        }

        // The only possibility left is bit pattern 1xxxxx, an LPC subframe.
        n => {
            // The xxxxx bits are the order minus one.
            let order_mo = n & 0b011_111;
            SubframeType::Lpc(order_mo + 1)
        }
    };

    // Next bits indicates whether there are wasted bits per sample.
    let wastes_bits = 1 == try!(input.read_leq_u8(1));

    // If so, k - 1 zero bits follow, where k is the number of wasted bits.
    let wasted_bits = if !wastes_bits {
        0
    } else {
        let mut wbits = 1;
        while 1 != try!(input.read_leq_u8(1)) {
            wbits = wbits + 1;
        }
        wbits
    };

    let subframe_header = SubframeHeader {
        sf_type: sf_type,
        wasted_bits_per_sample: wasted_bits
    };
    Ok(subframe_header)
}

/// Given a signed two's complement integer in the `bits` least significant
/// bits of `val`, extends the sign bit to a valid 16-bit signed integer.
fn extend_sign(val: u16, bits: u8) -> i16 {
    let sign_bit = val >> (bits as uint - 1);

    // Extend the sign bit into the remaining bits.
    let sign_extension = range(bits as uint, 16)
                         .fold(0, |s, i| s | (sign_bit << i));

    // Note: overflow in the cast is intended.
    (val | sign_extension) as i16
}

/// Decodes a signed number from Rice coding to the two's complement.
///
/// The Rice coding used by FLAC operates on unsigned integers, but the
/// residual is signed. The mapping is done as follows:
///
///  0 -> 0
/// -1 -> 1
///  1 -> 2
/// -2 -> 3
///  2 -> 4
///  etc.
///
/// This function takes the unsigned value and converts it into a signed
/// number. The return type still has unsigned type, because arithmetic relies
/// on overflow.
fn rice_to_signed<Sample>(val: Sample) -> Sample where Sample: UnsignedInt {
    // This uses bitwise arithmetic, because a literal cannot have type `Sample`,
    // I believe this is the most concise way to express the decoding.
    let sample_max: Sample = Int::max_value();
    if val & Int::one() == Int::one() {
        val >> 1
    } else {
        sample_max - (val >> 1)
    }
}

pub struct SubframeDecoder<'r, Sample> {
    bits_per_sample: u8,
    input: &'r mut Bitstream<'r>
}

impl<'r, Sample> SubframeDecoder<'r, Sample> where Sample: UnsignedInt {
    /// Creates a new subframe decoder capable of decoding several subframes.
    ///
    /// The size of the `Sample` type must be wide enough to accomodate for
    /// `bits_per_sample` bits per sample.
    pub fn new(bits_per_sample: u8, input: &'r mut Bitstream<'r>)
               -> SubframeDecoder<'r, Sample> {
        // The sample type should be wide enough to accomodate for all bits of
        // the stream, but this can be verified at a higher level than here.
        // Still, it is a good idea to make the assumption explicit.
        use std::mem::size_of;
        debug_assert!(bits_per_sample as uint <= size_of::<Sample>() * 8);

        SubframeDecoder { bits_per_sample: bits_per_sample, input: input }
    }

    /// Decodes the subframe into the provided block-size buffer.
    ///
    /// It is assumed that the length of the buffer is the block size.
    pub fn decode(&mut self, buffer: &mut [Sample]) -> FlacResult<()> {
        // First up is the subframe header.
        let header = try!(read_subframe_header(self.input));

        // Then decode the subframe, properly per type.
        println!("encountered subframe of type {}",
                 header.sf_type); // TODO: Remove this.
        match header.sf_type {
            SubframeType::Constant => try!(self.decode_constant(buffer)),
            SubframeType::Verbatim => try!(self.decode_verbatim(buffer)),
            SubframeType::Lpc(ord) => try!(self.decode_lpc(ord, buffer)),
            _ => { } // TODO: implement other decoders
        }

        // Finally, everything must be shifted by 'wasted bits per sample' to
        // the left. Note: it might be better performance-wise to do this on
        // the fly while decoding, that could be done if this is a bottleneck.
        if header.wasted_bits_per_sample > 0 {
            for s in buffer.iter_mut() {
                *s = *s << header.wasted_bits_per_sample as uint;
            }
        }

        println!("subframe decoded"); // TODO: Remove this.
        Ok(())
    }

    fn decode_residual(&mut self, block_size: u16,
                       buffer: &mut [Sample]) -> FlacResult<()> {
        // Residual starts with two bits of coding method.
        let method = try!(self.input.read_leq_u8(2));
        match method {
            0b00 => self.decode_partitioned_rice(block_size, buffer),
            0b01 => self.decode_partitioned_rice2(block_size, buffer),
            _ => Err(FlacError::InvalidResidual) // 10 and 11 are reserved.
        }
    }

    fn decode_partitioned_rice(&mut self, block_size: u16,
                               buffer: &mut [Sample]) -> FlacResult<()> {
        println!("  decoding partitioned Rice, bs = {}, buffer.len = {}",
                block_size, buffer.len()); // TODO: remove this.

        // First are 4 bits partition order.
        let order = try!(self.input.read_leq_u8(4));

        // There are 2^order partitions. Note: the specification states a 4-bit
        // partition order, so the order is at most 31, so there could be 2^31
        // partitions, but the block size is a 16-bit number, so there are at
        // most 2^16 - 1 samples in the block. No values have been marked as
        // invalid by the specification though. Therefore use an u32 for the
        // number of partitions, to avoid division by 0 in the number of samples.
        let n_partitions = 1u32 << order as uint;
        let n_samples = block_size as uint / n_partitions as uint;
        let n_warm_up = block_size as uint - buffer.len();

        // The partition size must be at least as big as the number of warm-up
        // samples.
        if n_warm_up > n_samples { return Err(FlacError::InvalidResidual); }

        println!("  order: {}, partitions: {}, samples: {}",
                 order, n_partitions, n_samples); // TODO: Remove this.

        let mut start = 0u;
        for i in range(0, n_partitions) {
            let partition_size = n_samples - if i == 0 { n_warm_up } else { 0 };
            println!("  > decoding partition {}, from {} to {}",
                     i, start, start + partition_size); // TODO: Remove this.
            try!(self.decode_rice_partition(buffer.slice_mut(start,
                                            start + partition_size)));
            start = start + partition_size;
        }

        Ok(())
    }

    fn decode_rice_partition(&mut self,
                             buffer: &mut [Sample]) -> FlacResult<()> {
        // The Rice partition starts with 4 bits Rice parameter.
        let rice_param = try!(self.input.read_leq_u8(4));

        // 1111 is an escape code that indicates unencoded binary.
        if rice_param == 0b1111 {
            // For unencoded binary, there are five bits indicating bits-per-sample.
            let bps = try!(self.input.read_leq_u8(5));

            // There cannot be more bits per sample than the sample type.
            if self.bits_per_sample < bps {
                return Err(FlacError::InvalidBitsPerSample);
            }

            panic!("unencoded binary is not yet implemented"); // TODO
        } else {
            let one: Sample = Int::one();
            let factor = one << rice_param as uint;
            let max_sample: Sample = Int::max_value();
            let max_q = max_sample / factor;

            // TODO: It is possible for the rice_param to be larger than the
            // sample width, which would be invalid. Check for that.

            for sample in buffer.iter_mut() {
                // First part of the sample is the quotient, unary encoded.
                // This means that there are q zeroes, and then a one. There
                // should not be more than max_q consecutive zeroes.
                let mut q: Sample = Int::zero();
                while try!(self.input.read_leq_u8(1)) == 0 {
                    if q == max_q { return Err(FlacError::InvalidRiceCode); }
                    q = q + Int::one();
                }

                // What follows is the remainder in `rice_param` bits. The
                // unwrap is safe, because any integer is at least 8-bit. Also,
                // r < factor because we read `rice_param` bits.
                let r_u8 = try!(self.input.read_leq_u8(rice_param));
                let r: Sample = NumCast::from(r_u8).unwrap();
                // TODO: use std::num::Cast instead of NumCast::from.

                *sample = rice_to_signed(q * factor + r);
            }
        }

        Ok(())
    }

    fn decode_partitioned_rice2(&mut self, block_size: u16,
                                buffer: &mut [Sample]) -> FlacResult<()> {
        println!("  decoding partitioned Rice 2"); // TODO: Remove this.
        panic!("partitioned_rice2 is not yet implemented"); // TODO
        Ok(())
    }

    fn decode_constant(&mut self, buffer: &mut [Sample]) -> FlacResult<()> {
        // A constant block has <bits per sample> bits: the value of all
        // samples. The unwrap is safe, because it has been verified before
        // that the `Sample` type is wide enough for the bits per sample.
        let sample_u32 = try!(self.input.read_leq_u32(self.bits_per_sample));
        let sample = NumCast::from(sample_u32).unwrap();

        for s in buffer.iter_mut() {
            *s = sample;
        }

        Ok(())
    }

    fn decode_verbatim(&mut self, buffer: &mut [Sample]) -> FlacResult<()> {
        // A verbatim block stores samples without encoding whatsoever.
        for s in buffer.iter_mut() {
            // The unwrap is safe, because it has been verified before that the
            // `Sample` type is wide enough for the bits per sample.
            let sample_u32 = try!(self.input.read_leq_u32(self.bits_per_sample));
            *s = NumCast::from(sample_u32).unwrap();
        }

        Ok(())
    }

    fn decode_lpc(&mut self, order: u8, buffer: &mut [Sample])
                  -> FlacResult<()> {
        println!("begin decoding of LPC subframe"); // TODO: Remove this.
        // There are order * bits per sample unencoded warm-up sample bits.
        for i in range(0, order as uint) {
            // The unwrap is safe, because it has been verified before that the
            // `Sample` type is wide enough for the bits per sample.
            let sample_u32 = try!(self.input.read_leq_u32(self.bits_per_sample));
            buffer[i] = NumCast::from(sample_u32).unwrap();
        }

        // Next are four bits quantised linear predictor coefficient precision - 1.
        let qlp_precision = try!(self.input.read_leq_u8(4)) + 1;

        // The bit pattern 1111 is invalid.
        if qlp_precision - 1 == 0b1111 {
            return Err(FlacError::InvalidSubframe);
        }

        // Next are five bits quantized linear predictor coefficient shift,
        // in signed two's complement. Read 5 bits and then extend the sign bit.
        let qlp_shift_unsig = try!(self.input.read_leq_u16(5));
        let qlp_shift = extend_sign(qlp_shift_unsig, 5) as uint;

        println!("  lpc: qlp_precision = {}, qlp_shift = {}",
                 qlp_precision, qlp_shift); // TODO: Remove this.

        // Finally, the coefficients themselves.
        // TODO: get rid of the allocation by pre-allocating a vector in the decoder.
        let mut coefficients = Vec::new();
        for _ in range(0, order) {
            let coef_unsig = try!(self.input.read_leq_u16(qlp_precision));
            let coef = extend_sign(coef_unsig, qlp_precision);
            coefficients.push(coef);
            println!("  > coef = {}", coef); // TODO: Remove this.
        }

        // Next up is the residual. We decode it into the buffer directly, the
        // predictor contributions will be added in a second pass. The first
        // `order` samples have been decoded already, so continue after that.
        try!(self.decode_residual(buffer.len() as u16,
                                  buffer.slice_from_mut(order as uint)));

        // TODO: do prediction.

        Ok(())
    }
}
<|endoftext|>


<commit_before>//! The interface for interacting with TMUX sessions. All the commands that are
/// built up during the parsing phase get matched to functions here. The
/// functions in this module all build up strings the get passed to a private
/// call. The private call converts them to CStrings and makes an "unsafe" system
/// call. All functions go through this `call` function as a common gateway to
/// system calls and can all be easily logged there.

use libc::system;
use std::ffi::CString;

/// The program to call commands on.
static TMUX_NAME: &'static str = "tmux";

/// The gateway to calling any functions on tmux. All public functions in this
/// module will be fed through this `call` function. This functions purpose is to
/// turn string based tmux function calls in to a `CString` and call out to the
/// system with it.
///
/// command: The command we will send to tmux on the host system for execution.
///
/// # Examples
///
/// ```
/// call("new-window -t muxed -c ~/Projects/muxed/".to_string());
/// ```
///
/// # Safety
///
/// This function will make an `unsafe` call out to the system to execute tmux
/// related commands.
fn call(command: String) -> () {
    let line = format!("{} {}", TMUX_NAME, command);
    let system_call = CString::new(line.clone()).unwrap();
    //println!("{}", line.clone());
    unsafe { system(system_call.as_ptr()); };
}

/// Attach is called as the last function in a set of commands. After the tmux
/// env has been setup by all previous commands this attaches the user to their
/// daemonized tmux session.
///
/// # Examples
///
/// ```
/// let session_name = "muxed".to_string();
/// tmux::attach(muxed);
/// ```
pub fn attach(session_name: &String) -> () {
    call(format!("attach -t {}", session_name));
}

/// New session is the first call made in any sequence of commands. It initiates
/// a new tmux session with a default first window name.
/// *Why a randomized first window name?*
///   This is because the `new-session` tmux command does not support the `-c`
/// flag as `new-window` and `split-window` do. So if the first window requires
/// being changed to a default directory `send-keys` must be used after the
/// session and first window are opened. This means the first window is treated in
/// a different code path than any other window that is opened.
/// Instead I've opted to open the session with a randomized (no conflicts)
/// named window, and we close this window out before attaching the user. This
/// allows for us to treat all user defined windows the same.
///
/// session_name: The name of the session being created.
/// tmp_name: The named first window that we will close out.
///
/// # Examples
///
/// ```
/// use rand::random;
///
/// let session_name = "muxed".to_string();
/// let tmp_window_name = random::<u16>().to_string();
/// tmux::new_session(session_name, tmp_window_name);
/// ```
pub fn new_session(session_name: &String, tmp_name: &String) -> () {
    call(format!("new -d -s {} -n {}", session_name, tmp_name));
}

/// Split window acts as the command to target named windows in a session to
/// send a make separate a single pane into two panes. Split window should target
/// a specific pane even if only a single pane exists.
///
/// # Examples
///
/// ```
/// let target = "muxed:cargo.0".to_string();
/// tmux::split_window(target, None);
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// root: An `Option<String>` passed to the -c argument to change the current
/// directory.
pub fn split_window(target: &String, root: &Option<String>) -> () {
    call(match root {
        &Some(ref r) => format!("split-window -t {} -c {}", target, r),
        &None        => format!("split-window -t {}", target)
    });
}

/// New window opens a new window in the named session with the provided window
/// name.
///
/// # Examples
///
/// ```
/// tmux::new_window("muxed".to_string(), "vim".to_string(), None);
/// ```
///
/// session_name: The active tmux session name.
/// window_name: The desired window name for the new window.
/// root: An `Option<String>` passed to the -c argument to change the current
/// directory.
pub fn new_window(session_name: &String, window_name: &String, root: &Option<String>) -> () {
    call(match root {
        &Some(ref r) => format!("new-window -t {} -n {} -c {}", session_name, window_name, r),
        &None        => format!("new-window -t {} -n {}", session_name, window_name)
    });
}

/// The layout function will adjust the layout of a tmux window that already has
/// multiple panes. Currently it will only accept standard tmux layout types.
///
/// Possible layout options: even-horizontal, even-vertical, main-horizontal,
/// main-vertical, or tiled.
///
/// # Examples
///
/// ```
/// tmux::layout("muxed:cargo.0".to_string(), "main-vertical".to_string(), None);
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// layout: The predefined tmux named layout.
pub fn layout(target: &String, layout: &String) -> () {
    call(format!("select-layout -t {} {}", target, layout));
}

/// Send Keys executes literal key commands in specified target windows. This is
/// the execution method to perform actions like tailing logs, starting servers,
/// or opening editors.
///
/// `KPEnter` represent the keyboard press of the "Enter" key. So the execution
/// is a user input command followed by "enter"
///
/// # Examples
///
/// ```
/// tmux::send_keys("muxed:cargo.0".to_string(), "vim .".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// exec: The system command to be executed in a particular pane.
pub fn send_keys(target: &String, exec: &String) -> () {
    call(format!("send-keys -t {} '{}' KPEnter", target, exec));
}

/// Kill Window is only used to elimiate the default window opened with a
/// randomized name when a new session is started.
///
/// # Examples
///
/// ```
/// tmux::kill_window("muxed:cargo".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}
/// exec: The system command to be executed in a particular pane.
pub fn kill_window(target: &String) -> () {
    call(format!("kill-window -t {}", target));
}
<commit_msg>Add variable definitions to function docs in tmux module.<commit_after>//! The interface for interacting with TMUX sessions. All the commands that are
/// built up during the parsing phase get matched to functions here. The
/// functions in this module all build up strings the get passed to a private
/// call. The private call converts them to CStrings and makes an "unsafe" system
/// call. All functions go through this `call` function as a common gateway to
/// system calls and can all be easily logged there.

use libc::system;
use std::ffi::CString;

/// The program to call commands on.
static TMUX_NAME: &'static str = "tmux";

/// The gateway to calling any functions on tmux. All public functions in this
/// module will be fed through this `call` function. This functions purpose is to
/// turn string based tmux function calls in to a `CString` and call out to the
/// system with it.
///
/// command: The command we will send to tmux on the host system for execution.
///
/// # Examples
///
/// ```
/// call("new-window -t muxed -c ~/Projects/muxed/".to_string());
/// ```
///
/// # Safety
///
/// This function will make an `unsafe` call out to the system to execute tmux
/// related commands.
fn call(command: String) -> () {
    let line = format!("{} {}", TMUX_NAME, command);
    let system_call = CString::new(line.clone()).unwrap();
    //println!("{}", line.clone());
    unsafe { system(system_call.as_ptr()); };
}

/// Attach is called as the last function in a set of commands. After the tmux
/// env has been setup by all previous commands this attaches the user to their
/// daemonized tmux session.
///
/// # Examples
///
/// ```
/// let session_name = "muxed".to_string();
/// tmux::attach(muxed);
/// ```
/// session_name: The active tmux session name.
pub fn attach(session_name: &String) -> () {
    call(format!("attach -t {}", session_name));
}

/// New session is the first call made in any sequence of commands. It initiates
/// a new tmux session with a default first window name.
/// *Why a randomized first window name?*
///   This is because the `new-session` tmux command does not support the `-c`
/// flag as `new-window` and `split-window` do. So if the first window requires
/// being changed to a default directory `send-keys` must be used after the
/// session and first window are opened. This means the first window is treated in
/// a different code path than any other window that is opened.
/// Instead I've opted to open the session with a randomized (no conflicts)
/// named window, and we close this window out before attaching the user. This
/// allows for us to treat all user defined windows the same.
///
/// session_name: The name of the session being created.
/// tmp_name: The named first window that we will close out.
///
/// # Examples
///
/// ```
/// use rand::random;
///
/// let session_name = "muxed".to_string();
/// let tmp_window_name = random::<u16>().to_string();
/// tmux::new_session(session_name, tmp_window_name);
/// ```
///
/// session_name: The active tmux session name.
/// tmp_name: The name for the temp initial window that is created with a new
/// session.
pub fn new_session(session_name: &String, tmp_name: &String) -> () {
    call(format!("new -d -s {} -n {}", session_name, tmp_name));
}

/// Split window acts as the command to target named windows in a session to
/// send a make separate a single pane into two panes. Split window should target
/// a specific pane even if only a single pane exists.
///
/// # Examples
///
/// ```
/// let target = "muxed:cargo.0".to_string();
/// tmux::split_window(target, None);
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// root: An `Option<String>` passed to the -c argument to change the current
/// directory.
pub fn split_window(target: &String, root: &Option<String>) -> () {
    call(match root {
        &Some(ref r) => format!("split-window -t {} -c {}", target, r),
        &None        => format!("split-window -t {}", target)
    });
}

/// New window opens a new window in the named session with the provided window
/// name.
///
/// # Examples
///
/// ```
/// tmux::new_window("muxed".to_string(), "vim".to_string(), None);
/// ```
///
/// session_name: The active tmux session name.
/// window_name: The desired window name for the new window.
/// root: An `Option<String>` passed to the -c argument to change the current
/// directory.
pub fn new_window(session_name: &String, window_name: &String, root: &Option<String>) -> () {
    call(match root {
        &Some(ref r) => format!("new-window -t {} -n {} -c {}", session_name, window_name, r),
        &None        => format!("new-window -t {} -n {}", session_name, window_name)
    });
}

/// The layout function will adjust the layout of a tmux window that already has
/// multiple panes. Currently it will only accept standard tmux layout types.
///
/// Possible layout options: even-horizontal, even-vertical, main-horizontal,
/// main-vertical, or tiled.
///
/// # Examples
///
/// ```
/// tmux::layout("muxed:cargo.0".to_string(), "main-vertical".to_string(), None);
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// layout: The predefined tmux named layout.
pub fn layout(target: &String, layout: &String) -> () {
    call(format!("select-layout -t {} {}", target, layout));
}

/// Send Keys executes literal key commands in specified target windows. This is
/// the execution method to perform actions like tailing logs, starting servers,
/// or opening editors.
///
/// `KPEnter` represent the keyboard press of the "Enter" key. So the execution
/// is a user input command followed by "enter"
///
/// # Examples
///
/// ```
/// tmux::send_keys("muxed:cargo.0".to_string(), "vim .".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// exec: The system command to be executed in a particular pane.
pub fn send_keys(target: &String, exec: &String) -> () {
    call(format!("send-keys -t {} '{}' KPEnter", target, exec));
}

/// Kill Window is only used to elimiate the default window opened with a
/// randomized name when a new session is started.
///
/// # Examples
///
/// ```
/// tmux::kill_window("muxed:cargo".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}
/// exec: The system command to be executed in a particular pane.
pub fn kill_window(target: &String) -> () {
    call(format!("kill-window -t {}", target));
}
<|endoftext|>


<commit_before>use std::io;
use std::rc::Rc;

use hbs;
use serde::Serialize;
use futures::{Future, future};

use rigging::Error;
use rigging::http;
use rigging::environment::Environment;
use rigging::format::*;
use rigging::method::Method;
use rigging::resource::ResourceEndpoint;

const MIME: &'static str = "text/plain; charset=utf-8";

pub struct Handlebars {
    registry: hbs::Handlebars,
}

impl<T, R, M> Format<T, R, M> for Handlebars
where
    T: ResourceEndpoint,
    M: ?Sized + Method<T, Request = ()>,
    R: Serialize,
{
    type ReqFuture = future::FutureResult<(), Error>;

    fn receive_request(_: &Rc<Self>, _: http::Request, _: &mut Environment) -> Self::ReqFuture {
        future::ok(())
    }

    fn present_unit(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where
        M: Method<T, Response = ()>
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|_| this.registry.render(&key.to_string(), &()).map_err(|_| Error)) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_resource(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where M: Method<T, Response = R>,
        R: ResourceEndpoint
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|resource| this.registry.render(&key.to_string(), &resource).map_err(|_| Error)) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_collection(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where
        M: Method<T, Response = Vec<R>>,
        R: ResourceEndpoint
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|resources| this.registry.render(&key.to_string(), &resources).map_err(|_| Error)) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_error(_: &Rc<Self>, error: Error, _: &mut Environment) -> http::BoxFuture {
        Box::new(future::ok(respond_with_err(error)))
    }
}

impl BuildFormat for Handlebars {
    fn build(templates: &[Template]) -> Result<Self, io::Error> {
        let mut hbs = Handlebars { registry: hbs::Handlebars::new() };
        for template in templates {
            hbs.registry.register_template_string(&template.key.to_string(), template.template).map_err(|_| -> io::Error { unimplemented!() })?;
        }
        Ok(hbs)
    }
}

fn respond_with(body: String) -> http::Response {
    let status = if body.len() == 0 { http::StatusCode::NoContent } else { http::StatusCode::Ok };
    http::Response::new().with_status(status)
                         .with_header(http::headers::ContentLength(body.len() as u64))
                         .with_header(http::headers::ContentType(MIME.parse().unwrap()))
                         .with_body(body)
}

fn respond_with_err(_: Error) -> http::Response {
    http::Response::new().with_status(http::StatusCode::InternalServerError)
}
<commit_msg>Namespace handlebars accessors.<commit_after>use std::io;
use std::rc::Rc;

use hbs;
use serde::Serialize;
use futures::{Future, future};

use rigging::Error;
use rigging::http;
use rigging::environment::Environment;
use rigging::format::*;
use rigging::method::Method;
use rigging::resource::ResourceEndpoint;

const MIME: &'static str = "text/plain; charset=utf-8";

pub struct Handlebars {
    registry: hbs::Handlebars,
}

#[derive(Serialize)]
struct Object<T: Serialize> {
    resource: T,
}

#[derive(Serialize)]
struct Objects<T: Serialize> {
    resources: T,
}

impl<T, R, M> Format<T, R, M> for Handlebars
where
    T: ResourceEndpoint,
    M: ?Sized + Method<T, Request = ()>,
    R: Serialize,
{
    type ReqFuture = future::FutureResult<(), Error>;

    fn receive_request(_: &Rc<Self>, _: http::Request, _: &mut Environment) -> Self::ReqFuture {
        future::ok(())
    }

    fn present_unit(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where
        M: Method<T, Response = ()>
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|_| this.registry.render(&key.to_string(), &()).map_err(|_| Error)) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_resource(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where M: Method<T, Response = R>,
        R: ResourceEndpoint
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|resource| this.registry.render(&key.to_string(), &Object { resource }).map_err(|_| Error)) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_collection(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where
        M: Method<T, Response = Vec<R>>,
        R: ResourceEndpoint
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|resources| this.registry.render(&key.to_string(), &Objects { resources }).map_err(|_| Error)) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_error(_: &Rc<Self>, error: Error, _: &mut Environment) -> http::BoxFuture {
        Box::new(future::ok(respond_with_err(error)))
    }
}

impl BuildFormat for Handlebars {
    fn build(templates: &[Template]) -> Result<Self, io::Error> {
        let mut hbs = Handlebars { registry: hbs::Handlebars::new() };
        for template in templates {
            hbs.registry.register_template_string(&template.key.to_string(), template.template).map_err(|_| -> io::Error { unimplemented!() })?;
        }
        Ok(hbs)
    }
}

fn respond_with(body: String) -> http::Response {
    let status = if body.len() == 0 { http::StatusCode::NoContent } else { http::StatusCode::Ok };
    http::Response::new().with_status(status)
                         .with_header(http::headers::ContentLength(body.len() as u64))
                         .with_header(http::headers::ContentType(MIME.parse().unwrap()))
                         .with_body(body)
}

fn respond_with_err(_: Error) -> http::Response {
    http::Response::new().with_status(http::StatusCode::InternalServerError)
}
<|endoftext|>


<commit_before>use formatter::Formatter;
use std::old_io;

pub struct Plain {
    out: Box<Writer+'static>
}

impl Plain {
    pub fn new() -> Plain {
        let out = Box::new(old_io::stdout());
        Plain { out: out }
    }
}

impl Formatter for Plain {
    fn start_rdb(&mut self) {
        println!("Start of RDB");
    }

    fn end_rdb(&mut self) {
        println!("End of RDB");
    }

    fn checksum(&mut self, checksum: &[u8]) {
        let _ = self.out.write_str("Checksum: ");
        let _ = self.out.write(checksum.as_slice());
        let _ = self.out.write_str("\n");
    }

    fn start_database(&mut self, db_number: u32) {
        println!("SELECTDB: {}", db_number);
    }

    fn end_database(&mut self, db_number: u32) {
        println!("END_DB: {}", db_number);
    }

    fn set(&mut self, key: &[u8], value: &[u8], _expiry: Option<u64>) {
        let _ = self.out.write(key.as_slice());
        let _ = self.out.write_str(": ");

        let _ = self.out.write(value.as_slice());
        let _ = self.out.write_str("\n");
        let _ = self.out.flush();
    }

    fn aux_field(&mut self, key: &[u8], value: &[u8]) {
        let _ = self.out.write_str("[aux] ");
        let _ = self.out.write(key.as_slice());
        let _ = self.out.write_str(": ");
        let _ = self.out.write(value.as_slice());
        let _ = self.out.write_str("\n");
        let _ = self.out.flush();
    }
}
<commit_msg>Finish plain formatter to match old `diff` output<commit_after>#![allow(unused_must_use)]
use formatter::Formatter;
use std::old_io;
use serialize::hex::ToHex;
use types::EncodingType;

pub struct Plain {
    out: Box<Writer+'static>,
    dbnum: u32,
    index: u32
}

impl Plain {
    pub fn new() -> Plain {
        let out = Box::new(old_io::stdout());
        Plain { out: out, dbnum: 0, index: 0 }
    }

    fn write_line_start(&mut self) {
        self.out.write_str(format!("db={} ", self.dbnum).as_slice());
    }
}

impl Formatter for Plain {
    fn checksum(&mut self, checksum: &[u8]) {
        self.out.write_str("checksum ");
        self.out.write_str(checksum.to_hex().as_slice());
        self.out.write_str("\n");
    }

    fn start_database(&mut self, db_number: u32) {
        self.dbnum = db_number;
    }

    fn set(&mut self, key: &[u8], value: &[u8], _expiry: Option<u64>) {
        self.write_line_start();
        self.out.write(key.as_slice());
        self.out.write_str(" -> ");

        self.out.write(value.as_slice());
        self.out.write_str("\n");
        self.out.flush();
    }

    fn aux_field(&mut self, key: &[u8], value: &[u8]) {
        self.out.write_str("aux ");
        self.out.write(key.as_slice());
        self.out.write_str(" -> ");
        self.out.write(value.as_slice());
        self.out.write_str("\n");
        self.out.flush();
    }

    fn hash_element(&mut self, key: &[u8], field: &[u8], value: &[u8]) {
        self.write_line_start();

        self.out.write(key.as_slice());
        self.out.write_str(" . ");
        self.out.write(field.as_slice());
        self.out.write_str(" -> ");
        self.out.write(value.as_slice());
        self.out.write_str("\n");
        self.out.flush();
    }

    fn set_element(&mut self, key: &[u8], member: &[u8]) {
        self.write_line_start();

        self.out.write(key.as_slice());
        self.out.write_str(" { ");
        self.out.write(member.as_slice());
        self.out.write_str(" } ");
        self.out.write_str("\n");
        self.out.flush();
    }

    fn start_list(&mut self, _key: &[u8], _length: u32,
                  _expiry: Option<u64>, _info: EncodingType) {
        self.index = 0;
    }
    fn list_element(&mut self, key: &[u8], value: &[u8]) {
        self.write_line_start();

        self.out.write(key.as_slice());
        self.out.write_str(format!("[{}]", self.index).as_slice());
        self.out.write_str(" -> ");
        self.out.write(value.as_slice());
        self.out.write_str("\n");
        self.out.flush();
        self.index += 1;
    }

    fn start_sorted_set(&mut self, _key: &[u8], _length: u32,
                        _expiry: Option<u64>, _info: EncodingType) {
        self.index = 0;
    }

    fn sorted_set_element(&mut self, key: &[u8],
                          score: f64, member: &[u8]) {
        self.write_line_start();

        self.out.write(key.as_slice());
        self.out.write_str(format!("[{}]", self.index).as_slice());
        self.out.write_str(" -> {");
        self.out.write(member.as_slice());
        self.out.write_str(format!(", score={}", score).as_slice());
        self.out.write_str("}\n");
        self.out.flush();
        self.index += 1;
    }
}
<|endoftext|>


<commit_before>use std;
use std::io::{Chars, Read, Write};
use std::sync;
use std::sync::atomic;
use libc;
use nix;
use nix::poll;
use nix::sys::signal;
use nix::sys::termios;

use consts::{self, KeyPress};
use ::Result;
use ::error;
use super::RawReader;

pub type Mode = termios::Termios;
const STDIN_FILENO: libc::c_int = libc::STDIN_FILENO;
const STDOUT_FILENO: libc::c_int = libc::STDOUT_FILENO;

/// Unsupported Terminals that don't support RAW mode
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb", "cons25", "emacs"];

#[cfg(any(target_os = "macos", target_os = "freebsd"))]
const TIOCGWINSZ: libc::c_ulong = 0x40087468;

#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_os = "android"))]
const TIOCGWINSZ: libc::c_ulong = 0x5413;

#[cfg(all(target_os = "linux", target_env = "musl"))]
const TIOCGWINSZ: libc::c_int = 0x5413;

/// Try to get the number of columns in the current terminal,
/// or assume 80 if it fails.
fn get_columns() -> usize {
    let (cols, _) = get_win_size();
    cols
}

/// Try to get the number of rows in the current terminal,
/// or assume 24 if it fails.
fn get_rows() -> usize {
    let (_, rows) = get_win_size();
    rows
}

fn get_win_size() -> (usize, usize) {
    use std::mem::zeroed;
    use libc::c_ushort;

    unsafe {
        #[repr(C)]
        struct winsize {
            ws_row: c_ushort,
            ws_col: c_ushort,
            ws_xpixel: c_ushort,
            ws_ypixel: c_ushort,
        }

        let mut size: winsize = zeroed();
        match libc::ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut size) {
            0 => (size.ws_col as usize, size.ws_row as usize), // TODO getCursorPosition
            _ => (80, 24),
        }
    }
}

/// Check TERM environment variable to see if current term is in our
/// unsupported list
fn is_unsupported_term() -> bool {
    use std::ascii::AsciiExt;
    match std::env::var("TERM") {
        Ok(term) => {
            let mut unsupported = false;
            for iter in &UNSUPPORTED_TERM {
                unsupported = (*iter).eq_ignore_ascii_case(&term)
            }
            unsupported
        }
        Err(_) => false,
    }
}

/// Return whether or not STDIN, STDOUT or STDERR is a TTY
fn is_a_tty(fd: libc::c_int) -> bool {
    unsafe { libc::isatty(fd) != 0 }
}

/// Enable RAW mode for the terminal.
pub fn enable_raw_mode() -> Result<Mode> {
    use nix::errno::Errno::ENOTTY;
    use nix::sys::termios::{BRKINT, CS8, ECHO, ICANON, ICRNL, IEXTEN, INPCK, ISIG, ISTRIP, IXON,
                            /* OPOST, */ VMIN, VTIME};
    if !is_a_tty(STDIN_FILENO) {
        try!(Err(nix::Error::from_errno(ENOTTY)));
    }
    let original_mode = try!(termios::tcgetattr(STDIN_FILENO));
    let mut raw = original_mode;
    // disable BREAK interrupt, CR to NL conversion on input,
    // input parity check, strip high bit (bit 8), output flow control
    raw.c_iflag = raw.c_iflag & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    // we don't want raw output, it turns newlines into straight linefeeds
    // raw.c_oflag = raw.c_oflag & !(OPOST); // disable all output processing
    raw.c_cflag = raw.c_cflag | (CS8); // character-size mark (8 bits)
    // disable echoing, canonical mode, extended input processing and signals
    raw.c_lflag = raw.c_lflag & !(ECHO | ICANON | IEXTEN | ISIG);
    raw.c_cc[VMIN] = 1; // One character-at-a-time input
    raw.c_cc[VTIME] = 0; // with blocking read
    try!(termios::tcsetattr(STDIN_FILENO, termios::TCSAFLUSH, &raw));
    Ok(original_mode)
}

/// Disable RAW mode for the terminal.
pub fn disable_raw_mode(original_mode: Mode) -> Result<()> {
    try!(termios::tcsetattr(STDIN_FILENO, termios::TCSAFLUSH, &original_mode));
    Ok(())
}

fn clear_screen(w: &mut Write) -> Result<()> {
    try!(w.write_all(b"\x1b[H\x1b[2J"));
    try!(w.flush());
    Ok(())
}

/// Console input reader
pub struct PosixRawReader {
    chars: Chars<std::io::Stdin>,
}

impl PosixRawReader {
    pub fn new(stdin: std::io::Stdin) -> Result<PosixRawReader> {
        Ok(PosixRawReader { chars: stdin.chars() })
    }

    fn escape_sequence(&mut self) -> Result<KeyPress> {
        // Read the next two bytes representing the escape sequence.
        let seq1 = try!(self.next_char());
        if seq1 == '[' {
            // ESC [ sequences.
            let seq2 = try!(self.next_char());
            if seq2.is_digit(10) {
                // Extended escape, read additional byte.
                let seq3 = try!(self.next_char());
                if seq3 == '~' {
                    match seq2 {
                        // '1' => Ok(KeyPress::Home),
                        '3' => Ok(KeyPress::Delete),
                        // '4' => Ok(KeyPress::End),
                        '5' => Ok(KeyPress::PageUp),
                        '6' => Ok(KeyPress::PageDown),
                        '7' => Ok(KeyPress::Home),
                        '8' => Ok(KeyPress::End),
                        _ => Ok(KeyPress::UnknownEscSeq),
                    }
                } else {
                    Ok(KeyPress::UnknownEscSeq)
                }
            } else {
                match seq2 {
                    'A' => Ok(KeyPress::Up), // ANSI
                    'B' => Ok(KeyPress::Down),
                    'C' => Ok(KeyPress::Right),
                    'D' => Ok(KeyPress::Left),
                    'F' => Ok(KeyPress::End),
                    'H' => Ok(KeyPress::Home),
                    _ => Ok(KeyPress::UnknownEscSeq),
                }
            }
        } else if seq1 == 'O' {
            // ESC O sequences.
            let seq2 = try!(self.next_char());
            match seq2 {
                'A' => Ok(KeyPress::Up),
                'B' => Ok(KeyPress::Down),
                'C' => Ok(KeyPress::Right),
                'D' => Ok(KeyPress::Left),
                'F' => Ok(KeyPress::End),
                'H' => Ok(KeyPress::Home),
                _ => Ok(KeyPress::UnknownEscSeq),
            }
        } else {
            // TODO ESC-N (n): search history forward not interactively
            // TODO ESC-P (p): search history backward not interactively
            // TODO ESC-R (r): Undo all changes made to this line.
            match seq1 {
                '\x08' => Ok(KeyPress::Meta('\x08')), // Backspace
                '<' => Ok(KeyPress::Meta('<')),
                '>' => Ok(KeyPress::Meta('>')),
                'b' | 'B' => Ok(KeyPress::Meta('B')),
                'c' | 'C' => Ok(KeyPress::Meta('C')),
                'd' | 'D' => Ok(KeyPress::Meta('D')),
                'f' | 'F' => Ok(KeyPress::Meta('F')),
                'l' | 'L' => Ok(KeyPress::Meta('L')),
                't' | 'T' => Ok(KeyPress::Meta('T')),
                'u' | 'U' => Ok(KeyPress::Meta('U')),
                'y' | 'Y' => Ok(KeyPress::Meta('Y')),
                '\x7f' => Ok(KeyPress::Meta('\x7f')), // Delete
                _ => {
                    // writeln!(io::stderr(), "key: {:?}, seq1: {:?}", KeyPress::Esc, seq1).unwrap();
                    Ok(KeyPress::UnknownEscSeq)
                }
            }
        }
    }
}

impl RawReader for PosixRawReader {
    // As there is no read timeout to properly handle single ESC key,
    // we make possible to deactivate escape sequence processing.
    fn next_key(&mut self, esc_seq: bool) -> Result<KeyPress> {
        let c = try!(self.next_char());

        let mut key = consts::char_to_key_press(c);
        if key == KeyPress::Esc {
            if esc_seq {
                // escape sequence
                key = try!(self.escape_sequence());
            } else {
                let mut fds =
                    [poll::PollFd::new(STDIN_FILENO, poll::POLLIN, poll::EventFlags::empty())];
                match poll::poll(&mut fds, 500) {
                    Ok(n) if n == 0 => {
                        // single escape
                    }
                    Ok(_) => {
                        // escape sequence
                        key = try!(self.escape_sequence())
                    }
                    // Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
                    Err(e) => return Err(e.into()),
                }
            }
        }
        Ok(key)
    }

    fn next_char(&mut self) -> Result<char> {
        match self.chars.next() {
            Some(c) => Ok(try!(c)),
            None => Err(error::ReadlineError::Eof),
        }
    }
}

static SIGWINCH_ONCE: sync::Once = sync::ONCE_INIT;
static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;

fn install_sigwinch_handler() {
    SIGWINCH_ONCE.call_once(|| unsafe {
        let sigwinch = signal::SigAction::new(signal::SigHandler::Handler(sigwinch_handler),
                                              signal::SaFlags::empty(),
                                              signal::SigSet::empty());
        let _ = signal::sigaction(signal::SIGWINCH, &sigwinch);
    });
}

extern "C" fn sigwinch_handler(_: libc::c_int) {
    SIGWINCH.store(true, atomic::Ordering::SeqCst);
}

pub type Terminal = PosixTerminal;

#[derive(Clone, Debug)]
pub struct PosixTerminal {
    unsupported: bool,
    stdin_isatty: bool,
}

impl PosixTerminal {
    pub fn new() -> PosixTerminal {
        let term = PosixTerminal {
            unsupported: is_unsupported_term(),
            stdin_isatty: is_a_tty(STDIN_FILENO),
        };
        if !term.unsupported && term.stdin_isatty && is_a_tty(STDOUT_FILENO) {
            install_sigwinch_handler();
        }
        term
    }

    // Init checks:

    /// Check if current terminal can provide a rich line-editing user interface.
    pub fn is_unsupported(&self) -> bool {
        self.unsupported
    }

    /// check if stdin is connected to a terminal.
    pub fn is_stdin_tty(&self) -> bool {
        self.stdin_isatty
    }

    // Interactive loop:

    /// Get the number of columns in the current terminal.
    pub fn get_columns(&self) -> usize {
        get_columns()
    }

    /// Get the number of rows in the current terminal.
    pub fn get_rows(&self) -> usize {
        get_rows()
    }

    /// Create a RAW reader
    pub fn create_reader(&self) -> Result<PosixRawReader> {
        PosixRawReader::new(std::io::stdin())
    }

    /// Check if a SIGWINCH signal has been received
    pub fn sigwinch(&self) -> bool {
        SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst)
    }

    /// Clear the screen. Used to handle ctrl+l
    pub fn clear_screen(&mut self, w: &mut Write) -> Result<()> {
        clear_screen(w)
    }
}
<commit_msg>Polling Stdin is useless<commit_after>use std;
use std::io::{Chars, Read, Write};
use std::sync;
use std::sync::atomic;
use libc;
use nix;
use nix::sys::signal;
use nix::sys::termios;

use consts::{self, KeyPress};
use ::Result;
use ::error;
use super::RawReader;

pub type Mode = termios::Termios;
const STDIN_FILENO: libc::c_int = libc::STDIN_FILENO;
const STDOUT_FILENO: libc::c_int = libc::STDOUT_FILENO;

/// Unsupported Terminals that don't support RAW mode
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb", "cons25", "emacs"];

#[cfg(any(target_os = "macos", target_os = "freebsd"))]
const TIOCGWINSZ: libc::c_ulong = 0x40087468;

#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_os = "android"))]
const TIOCGWINSZ: libc::c_ulong = 0x5413;

#[cfg(all(target_os = "linux", target_env = "musl"))]
const TIOCGWINSZ: libc::c_int = 0x5413;

/// Try to get the number of columns in the current terminal,
/// or assume 80 if it fails.
fn get_columns() -> usize {
    let (cols, _) = get_win_size();
    cols
}

/// Try to get the number of rows in the current terminal,
/// or assume 24 if it fails.
fn get_rows() -> usize {
    let (_, rows) = get_win_size();
    rows
}

fn get_win_size() -> (usize, usize) {
    use std::mem::zeroed;
    use libc::c_ushort;

    unsafe {
        #[repr(C)]
        struct winsize {
            ws_row: c_ushort,
            ws_col: c_ushort,
            ws_xpixel: c_ushort,
            ws_ypixel: c_ushort,
        }

        let mut size: winsize = zeroed();
        match libc::ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut size) {
            0 => (size.ws_col as usize, size.ws_row as usize), // TODO getCursorPosition
            _ => (80, 24),
        }
    }
}

/// Check TERM environment variable to see if current term is in our
/// unsupported list
fn is_unsupported_term() -> bool {
    use std::ascii::AsciiExt;
    match std::env::var("TERM") {
        Ok(term) => {
            let mut unsupported = false;
            for iter in &UNSUPPORTED_TERM {
                unsupported = (*iter).eq_ignore_ascii_case(&term)
            }
            unsupported
        }
        Err(_) => false,
    }
}

/// Return whether or not STDIN, STDOUT or STDERR is a TTY
fn is_a_tty(fd: libc::c_int) -> bool {
    unsafe { libc::isatty(fd) != 0 }
}

/// Enable RAW mode for the terminal.
pub fn enable_raw_mode() -> Result<Mode> {
    use nix::errno::Errno::ENOTTY;
    use nix::sys::termios::{BRKINT, CS8, ECHO, ICANON, ICRNL, IEXTEN, INPCK, ISIG, ISTRIP, IXON,
                            /* OPOST, */ VMIN, VTIME};
    if !is_a_tty(STDIN_FILENO) {
        try!(Err(nix::Error::from_errno(ENOTTY)));
    }
    let original_mode = try!(termios::tcgetattr(STDIN_FILENO));
    let mut raw = original_mode;
    // disable BREAK interrupt, CR to NL conversion on input,
    // input parity check, strip high bit (bit 8), output flow control
    raw.c_iflag = raw.c_iflag & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    // we don't want raw output, it turns newlines into straight linefeeds
    // raw.c_oflag = raw.c_oflag & !(OPOST); // disable all output processing
    raw.c_cflag = raw.c_cflag | (CS8); // character-size mark (8 bits)
    // disable echoing, canonical mode, extended input processing and signals
    raw.c_lflag = raw.c_lflag & !(ECHO | ICANON | IEXTEN | ISIG);
    raw.c_cc[VMIN] = 1; // One character-at-a-time input
    raw.c_cc[VTIME] = 0; // with blocking read
    try!(termios::tcsetattr(STDIN_FILENO, termios::TCSAFLUSH, &raw));
    Ok(original_mode)
}

/// Disable RAW mode for the terminal.
pub fn disable_raw_mode(original_mode: Mode) -> Result<()> {
    try!(termios::tcsetattr(STDIN_FILENO, termios::TCSAFLUSH, &original_mode));
    Ok(())
}

fn clear_screen(w: &mut Write) -> Result<()> {
    try!(w.write_all(b"\x1b[H\x1b[2J"));
    try!(w.flush());
    Ok(())
}

/// Console input reader
pub struct PosixRawReader {
    chars: Chars<std::io::Stdin>,
}

impl PosixRawReader {
    pub fn new(stdin: std::io::Stdin) -> Result<PosixRawReader> {
        Ok(PosixRawReader { chars: stdin.chars() })
    }

    fn escape_sequence(&mut self) -> Result<KeyPress> {
        // Read the next two bytes representing the escape sequence.
        let seq1 = try!(self.next_char());
        if seq1 == '[' {
            // ESC [ sequences.
            let seq2 = try!(self.next_char());
            if seq2.is_digit(10) {
                // Extended escape, read additional byte.
                let seq3 = try!(self.next_char());
                if seq3 == '~' {
                    match seq2 {
                        // '1' => Ok(KeyPress::Home),
                        '3' => Ok(KeyPress::Delete),
                        // '4' => Ok(KeyPress::End),
                        '5' => Ok(KeyPress::PageUp),
                        '6' => Ok(KeyPress::PageDown),
                        '7' => Ok(KeyPress::Home),
                        '8' => Ok(KeyPress::End),
                        _ => Ok(KeyPress::UnknownEscSeq),
                    }
                } else {
                    Ok(KeyPress::UnknownEscSeq)
                }
            } else {
                match seq2 {
                    'A' => Ok(KeyPress::Up), // ANSI
                    'B' => Ok(KeyPress::Down),
                    'C' => Ok(KeyPress::Right),
                    'D' => Ok(KeyPress::Left),
                    'F' => Ok(KeyPress::End),
                    'H' => Ok(KeyPress::Home),
                    _ => Ok(KeyPress::UnknownEscSeq),
                }
            }
        } else if seq1 == 'O' {
            // ESC O sequences.
            let seq2 = try!(self.next_char());
            match seq2 {
                'A' => Ok(KeyPress::Up),
                'B' => Ok(KeyPress::Down),
                'C' => Ok(KeyPress::Right),
                'D' => Ok(KeyPress::Left),
                'F' => Ok(KeyPress::End),
                'H' => Ok(KeyPress::Home),
                _ => Ok(KeyPress::UnknownEscSeq),
            }
        } else {
            // TODO ESC-N (n): search history forward not interactively
            // TODO ESC-P (p): search history backward not interactively
            // TODO ESC-R (r): Undo all changes made to this line.
            match seq1 {
                '\x08' => Ok(KeyPress::Meta('\x08')), // Backspace
                '<' => Ok(KeyPress::Meta('<')),
                '>' => Ok(KeyPress::Meta('>')),
                'b' | 'B' => Ok(KeyPress::Meta('B')),
                'c' | 'C' => Ok(KeyPress::Meta('C')),
                'd' | 'D' => Ok(KeyPress::Meta('D')),
                'f' | 'F' => Ok(KeyPress::Meta('F')),
                'l' | 'L' => Ok(KeyPress::Meta('L')),
                't' | 'T' => Ok(KeyPress::Meta('T')),
                'u' | 'U' => Ok(KeyPress::Meta('U')),
                'y' | 'Y' => Ok(KeyPress::Meta('Y')),
                '\x7f' => Ok(KeyPress::Meta('\x7f')), // Delete
                _ => {
                    // writeln!(io::stderr(), "key: {:?}, seq1: {:?}", KeyPress::Esc, seq1).unwrap();
                    Ok(KeyPress::UnknownEscSeq)
                }
            }
        }
    }
}

impl RawReader for PosixRawReader {
    // As there is no read timeout to properly handle single ESC key,
    // we make possible to deactivate escape sequence processing.
    fn next_key(&mut self, esc_seq: bool) -> Result<KeyPress> {
        // FIXME Stdin is buffered, so polling after reading an ESC char is useless (next available chars are already buffered)...
        let c = try!(self.next_char());

        let mut key = consts::char_to_key_press(c);
        if key == KeyPress::Esc && esc_seq {
            // escape sequence
            key = try!(self.escape_sequence());
        }
        Ok(key)
    }

    fn next_char(&mut self) -> Result<char> {
        match self.chars.next() {
            Some(c) => Ok(try!(c)),
            None => Err(error::ReadlineError::Eof),
        }
    }
}

static SIGWINCH_ONCE: sync::Once = sync::ONCE_INIT;
static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;

fn install_sigwinch_handler() {
    SIGWINCH_ONCE.call_once(|| unsafe {
        let sigwinch = signal::SigAction::new(signal::SigHandler::Handler(sigwinch_handler),
                                              signal::SaFlags::empty(),
                                              signal::SigSet::empty());
        let _ = signal::sigaction(signal::SIGWINCH, &sigwinch);
    });
}

extern "C" fn sigwinch_handler(_: libc::c_int) {
    SIGWINCH.store(true, atomic::Ordering::SeqCst);
}

pub type Terminal = PosixTerminal;

#[derive(Clone, Debug)]
pub struct PosixTerminal {
    unsupported: bool,
    stdin_isatty: bool,
}

impl PosixTerminal {
    pub fn new() -> PosixTerminal {
        let term = PosixTerminal {
            unsupported: is_unsupported_term(),
            stdin_isatty: is_a_tty(STDIN_FILENO),
        };
        if !term.unsupported && term.stdin_isatty && is_a_tty(STDOUT_FILENO) {
            install_sigwinch_handler();
        }
        term
    }

    // Init checks:

    /// Check if current terminal can provide a rich line-editing user interface.
    pub fn is_unsupported(&self) -> bool {
        self.unsupported
    }

    /// check if stdin is connected to a terminal.
    pub fn is_stdin_tty(&self) -> bool {
        self.stdin_isatty
    }

    // Interactive loop:

    /// Get the number of columns in the current terminal.
    pub fn get_columns(&self) -> usize {
        get_columns()
    }

    /// Get the number of rows in the current terminal.
    pub fn get_rows(&self) -> usize {
        get_rows()
    }

    /// Create a RAW reader
    pub fn create_reader(&self) -> Result<PosixRawReader> {
        PosixRawReader::new(std::io::stdin())
    }

    /// Check if a SIGWINCH signal has been received
    pub fn sigwinch(&self) -> bool {
        SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst)
    }

    /// Clear the screen. Used to handle ctrl+l
    pub fn clear_screen(&mut self, w: &mut Write) -> Result<()> {
        clear_screen(w)
    }
}
<|endoftext|>


<commit_before>//! The `Default` trait for types which may have meaningful default values.

#![stable(feature = "rust1", since = "1.0.0")]

/// A trait for giving a type a useful default value.
///
/// Sometimes, you want to fall back to some kind of default value, and
/// don't particularly care what it is. This comes up often with `struct`s
/// that define a set of options:
///
/// ```
/// # #[allow(dead_code)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
/// ```
///
/// How can we define some default values? You can use `Default`:
///
/// ```
/// # #[allow(dead_code)]
/// #[derive(Default)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
///
/// fn main() {
///     let options: SomeOptions = Default::default();
/// }
/// ```
///
/// Now, you get all of the default values. Rust implements `Default` for various primitives types.
///
/// If you want to override a particular option, but still retain the other defaults:
///
/// ```
/// # #[allow(dead_code)]
/// # #[derive(Default)]
/// # struct SomeOptions {
/// #     foo: i32,
/// #     bar: f32,
/// # }
/// fn main() {
///     let options = SomeOptions { foo: 42, ..Default::default() };
/// }
/// ```
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all of the type's fields implement
/// `Default`. When `derive`d, it will use the default value for each field's type.
///
/// ## How can I implement `Default`?
///
/// Provides an implementation for the `default()` method that returns the value of
/// your type that should be the default:
///
/// ```
/// # #![allow(dead_code)]
/// enum Kind {
///     A,
///     B,
///     C,
/// }
///
/// impl Default for Kind {
///     fn default() -> Self { Kind::A }
/// }
/// ```
///
/// # Examples
///
/// ```
/// # #[allow(dead_code)]
/// #[derive(Default)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Default: Sized {
    /// Returns the "default value" for a type.
    ///
    /// Default values are often some kind of initial value, identity value, or anything else that
    /// may make sense as a default.
    ///
    /// # Examples
    ///
    /// Using built-in default values:
    ///
    /// ```
    /// let i: i8 = Default::default();
    /// let (x, y): (Option<String>, f64) = Default::default();
    /// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default();
    /// ```
    ///
    /// Making your own:
    ///
    /// ```
    /// # #[allow(dead_code)]
    /// enum Kind {
    ///     A,
    ///     B,
    ///     C,
    /// }
    ///
    /// impl Default for Kind {
    ///     fn default() -> Self { Kind::A }
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Self;
}

/// Derive macro generating an impl of the trait `Default`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Default($item:item) {
    /* compiler built-in */
}

macro_rules! default_impl {
    ($t:ty, $v:expr, $doc:tt) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Default for $t {
            #[inline]
            #[doc = $doc]
            fn default() -> $t { $v }
        }
    }
}

default_impl! { (), (), "Returns the default value of `()`" }
default_impl! { bool, false, "Returns the default value of `false`" }
default_impl! { char, '\x00', "Returns the default value of `\\x00`" }

default_impl! { usize, 0, "Returns the default value of `0`" }
default_impl! { u8, 0, "Returns the default value of `0`" }
default_impl! { u16, 0, "Returns the default value of `0`" }
default_impl! { u32, 0, "Returns the default value of `0`" }
default_impl! { u64, 0, "Returns the default value of `0`" }
default_impl! { u128, 0, "Returns the default value of `0`" }

default_impl! { isize, 0, "Returns the default value of `0`" }
default_impl! { i8, 0, "Returns the default value of `0`" }
default_impl! { i16, 0, "Returns the default value of `0`" }
default_impl! { i32, 0, "Returns the default value of `0`" }
default_impl! { i64, 0, "Returns the default value of `0`" }
default_impl! { i128, 0, "Returns the default value of `0`" }

default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" }
default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" }
<commit_msg>Fix typo in Default trait docs: Provides -> Provide<commit_after>//! The `Default` trait for types which may have meaningful default values.

#![stable(feature = "rust1", since = "1.0.0")]

/// A trait for giving a type a useful default value.
///
/// Sometimes, you want to fall back to some kind of default value, and
/// don't particularly care what it is. This comes up often with `struct`s
/// that define a set of options:
///
/// ```
/// # #[allow(dead_code)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
/// ```
///
/// How can we define some default values? You can use `Default`:
///
/// ```
/// # #[allow(dead_code)]
/// #[derive(Default)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
///
/// fn main() {
///     let options: SomeOptions = Default::default();
/// }
/// ```
///
/// Now, you get all of the default values. Rust implements `Default` for various primitives types.
///
/// If you want to override a particular option, but still retain the other defaults:
///
/// ```
/// # #[allow(dead_code)]
/// # #[derive(Default)]
/// # struct SomeOptions {
/// #     foo: i32,
/// #     bar: f32,
/// # }
/// fn main() {
///     let options = SomeOptions { foo: 42, ..Default::default() };
/// }
/// ```
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all of the type's fields implement
/// `Default`. When `derive`d, it will use the default value for each field's type.
///
/// ## How can I implement `Default`?
///
/// Provide an implementation for the `default()` method that returns the value of
/// your type that should be the default:
///
/// ```
/// # #![allow(dead_code)]
/// enum Kind {
///     A,
///     B,
///     C,
/// }
///
/// impl Default for Kind {
///     fn default() -> Self { Kind::A }
/// }
/// ```
///
/// # Examples
///
/// ```
/// # #[allow(dead_code)]
/// #[derive(Default)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Default: Sized {
    /// Returns the "default value" for a type.
    ///
    /// Default values are often some kind of initial value, identity value, or anything else that
    /// may make sense as a default.
    ///
    /// # Examples
    ///
    /// Using built-in default values:
    ///
    /// ```
    /// let i: i8 = Default::default();
    /// let (x, y): (Option<String>, f64) = Default::default();
    /// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default();
    /// ```
    ///
    /// Making your own:
    ///
    /// ```
    /// # #[allow(dead_code)]
    /// enum Kind {
    ///     A,
    ///     B,
    ///     C,
    /// }
    ///
    /// impl Default for Kind {
    ///     fn default() -> Self { Kind::A }
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Self;
}

/// Derive macro generating an impl of the trait `Default`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Default($item:item) {
    /* compiler built-in */
}

macro_rules! default_impl {
    ($t:ty, $v:expr, $doc:tt) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Default for $t {
            #[inline]
            #[doc = $doc]
            fn default() -> $t { $v }
        }
    }
}

default_impl! { (), (), "Returns the default value of `()`" }
default_impl! { bool, false, "Returns the default value of `false`" }
default_impl! { char, '\x00', "Returns the default value of `\\x00`" }

default_impl! { usize, 0, "Returns the default value of `0`" }
default_impl! { u8, 0, "Returns the default value of `0`" }
default_impl! { u16, 0, "Returns the default value of `0`" }
default_impl! { u32, 0, "Returns the default value of `0`" }
default_impl! { u64, 0, "Returns the default value of `0`" }
default_impl! { u128, 0, "Returns the default value of `0`" }

default_impl! { isize, 0, "Returns the default value of `0`" }
default_impl! { i8, 0, "Returns the default value of `0`" }
default_impl! { i16, 0, "Returns the default value of `0`" }
default_impl! { i32, 0, "Returns the default value of `0`" }
default_impl! { i64, 0, "Returns the default value of `0`" }
default_impl! { i128, 0, "Returns the default value of `0`" }

default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" }
default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" }
<|endoftext|>