<commit_before>use checksum::Crc8Reader;
use error::{FlacError, FlacResult};

#[deriving(Copy)]
enum BlockingStrategy {
    Fixed,
    Variable
}

#[deriving(Copy)]
enum BlockTime {
    FrameNumber(u32),
    SampleNumber(u64)
}

#[deriving(Copy)]
enum ChannelMode {
    /// The channels are coded as-is.
    Raw,
    /// Channel 0 is the left channel, channel 1 is the side channel.
    LeftSideStereo,
    /// Channel 0 is the side channel, channel 1 is the right channel.
    RightSideStereo,
    /// Channel 0 is the mid channel, channel 1 is the side channel.
    MidSideStereo
}

#[deriving(Copy)]
struct FrameHeader {
    pub block_time: BlockTime,
    pub block_size: u16,
    pub sample_rate: Option<u32>,
    pub n_channels: u8,
    pub channel_mode: ChannelMode,
    pub bits_per_sample: Option<u8>
    // TODO: there is also a sample or frame number.
}

/// Reads a variable-length integer encoded as what is called "UTF-8" coding
/// in the specification. (It is not real UTF-8.) This function can read
/// integers encoded in this way up to 36-bit integers.
fn read_var_length_int(input: &mut Reader) -> FlacResult<u64> {
    use std::iter::range_step_inclusive;
    use std::io::stdio::flush;
    // The number of consecutive 1s followed by a 0 is the number of additional
    // bytes to read.
    let first = try!(input.read_byte());
    let mut read_additional = 0u;
    let mut mask_data = 0b0111_1111u8;
    let mut mask_mark = 0b1000_0000u8;

    // Determine the number of leading 1s.
    while first & mask_mark != 0 {
        read_additional = read_additional + 1;
        mask_data = mask_data >> 1;
        mask_mark = mask_mark >> 1;
    }

    // A single leading 1 is a follow-up byte and thus invalid.
    if read_additional > 0 {
        if read_additional == 1 {
            return Err(FlacError::InvalidVarLengthInt);
        } else {
            // The number of 1s (if > 1) is the total number of bytes, not the
            // number of additional bytes.
            read_additional = read_additional - 1;
        }
    }

    // Each additional byte will yield 6 extra bits, so shift the most
    // significant bits into the correct position.
    let mut result = (first & mask_data) as u64 << (6 * read_additional);
    println!("result = {:b}, read_a = {}\n", result, read_additional);
    for i in range_step_inclusive(read_additional as int - 1, 0, -1) {
        let byte = try!(input.read_byte());

        // The two most significant bits _must_ be 10.
        if byte & 0b1100_0000 != 0b1000_0000 {
            return Err(FlacError::InvalidVarLengthInt);
        }
        println!("adding bits {:b}\n", (byte & 0b0011_1111));
        flush();
        result = result | ((byte & 0b0011_1111) as u64 << (6 * i as uint));
    }

    Ok(result)
}

#[test]
fn verify_read_var_length_int() {
    use std::io::MemReader;

    let mut reader = MemReader::new(vec!(0x24, 0xc2, 0xa2, 0xe2, 0x82, 0xac,
                                         0xf0, 0x90, 0x8d, 0x88, 0xc2, 0x00,
                                         0x80));
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x24);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0xa2);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x20ac);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x010348);
    // Two-byte integer with invalid continuation byte should fail.
    assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
               FlacError::InvalidVarLengthInt);
    // Continuation byte can never be the first byte.
    assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
               FlacError::InvalidVarLengthInt);
}

fn read_frame_header(input: &mut Reader) -> FlacResult<FrameHeader> {
    // The frame header includes a CRC-8 at the end. It can be computed
    // automatically while reading, by wrapping the input reader in a reader
    // that computes the CRC.
    let mut crc_input = Crc8Reader::new(input);

    // First are 14 bits frame sync code, a reserved bit, and blocking stategy.
    let sync_res_block = try!(crc_input.read_be_u16());

    // The first 14 bits must be 11111111111110.
    let sync_code = sync_res_block & 0b1111_1111_1111_1100;
    if sync_code != 0b1111_1111_1111_1000 {
        return Err(FlacError::MissingFrameSyncCode);
    }

    // The next bit has a mandatory value of 0 (at the moment of writing, if
    // the bit has a different value, it could be a future stream that we
    // cannot read).
    if sync_res_block & 0b0000_0000_0000_0010 != 0 {
        return Err(FlacError::InvalidFrameHeader);
    }

    // The final bit determines the blocking strategy.
    let blocking_strategy = if sync_res_block & 0b0000_0000_0000_0001 == 0 {
        BlockingStrategy::Fixed
    } else {
        BlockingStrategy::Variable
    };

    // Next are 4 bits block size and 4 bits sample rate.
    let bs_sr = try!(crc_input.read_byte());
    let mut block_size = 0u16;
    let mut read_8bit_bs = false;
    let mut read_16bit_bs = false;

    // There are some pre-defined bit patterns. Some mean 'get from end of
    // header instead'.
    match bs_sr >> 4 {
        // The value 0000 is reserved.
        0b0000 => return Err(FlacError::InvalidFrameHeader),
        0b0001 => block_size = 192,
        n if 0b0010 <= n && n <= 0b0101 => block_size = 576 * (1 << (n - 2) as uint),
        0b0110 => read_8bit_bs = true,
        0b0111 => read_16bit_bs = true,
        n => block_size = 256 * (1 << (n - 8) as uint)
    }

    // For the sample rate there is a number of pre-defined bit patterns as
    // well. Again, some mean 'get from end of header instead'.
    let mut sample_rate = None;
    let mut read_8bit_sr = false;
    let mut read_16bit_sr = false;
    let mut read_16bit_sr_ten = false;

    match bs_sr & 0b0000_1111 {
        0b0000 => sample_rate = None, // 0000 means 'get from streaminfo block'.
        0b0001 => sample_rate = Some( 88_200),
        0b0010 => sample_rate = Some(176_400),
        0b0011 => sample_rate = Some(192_000),
        0b0100 => sample_rate = Some(  8_000),
        0b0101 => sample_rate = Some( 16_000),
        0b0110 => sample_rate = Some( 22_050),
        0b0111 => sample_rate = Some( 24_000),
        0b1000 => sample_rate = Some( 32_000),
        0b1001 => sample_rate = Some( 44_100),
        0b1010 => sample_rate = Some( 48_000),
        0b1011 => sample_rate = Some( 96_000),
        0b1100 => read_8bit_sr = true, // Read Hz from end of header.
        0b1101 => read_16bit_sr = true, // Read Hz from end of header.
        0b1110 => read_16bit_sr_ten = true, // Read tens of Hz from end of header.
        // 1111 is invalid to prevent sync-fooling.
        // Other values are impossible at this point.
        _ => return Err(FlacError::InvalidFrameHeader)
    }

    // Next are 4 bits channel assignment, 3 bits sample size, and 1 reserved bit.
    let chan_bps_res = try!(crc_input.read_byte());

    // The most significant 4 bits determine channel assignment.
    let (n_channels, channel_mode) = match chan_bps_res >> 4 {
        // Values 0 through 7 indicate n + 1 channels without mixing.
        n if n < 8 => (n + 1, ChannelMode::Raw),
        0b1000 => (2, ChannelMode::LeftSideStereo),
        0b1001 => (2, ChannelMode::RightSideStereo),
        0b1010 => (2, ChannelMode::MidSideStereo),
        // Values 1011 through 1111 are reserved and thus invalid.
        _ => return Err(FlacError::InvalidFrameHeader)
    };

    // The next three bits indicate bits per sample.
    let bits_per_sample = match (chan_bps_res & 0b0000_1110) >> 1 {
        0b000 => None, // 000 means 'get from streaminfo block'.
        0b001 => Some(8),
        0b010 => Some(12),
        0b100 => Some(16),
        0b101 => Some(20),
        0b110 => Some(24),
        // Values 011 and 111 are reserved. Other values are impossible.
        _ => return Err(FlacError::InvalidFrameHeader)
    };

    // The final bit has a mandatory value of 0.
    if chan_bps_res & 0b0000_0001 != 0 {
        return Err(FlacError::InvalidFrameHeader);
    }

    let block_time = match blocking_strategy {
        BlockingStrategy::Variable => {
            // The sample number is encoded in 8-56 bits, at most a 36-bit int.
            let sample = try!(read_var_length_int(&mut crc_input));
            BlockTime::SampleNumber(sample)
        },
        BlockingStrategy::Fixed => {
            // The frame number is encoded in 8-48 bits, at most a 31-bit int.
            let frame = try!(read_var_length_int(&mut crc_input));
            // A frame number larger than 31 bits is therefore invalid.
            if frame > 0x7fffffff {
                return Err(FlacError::InvalidFrameHeader);
            }
            BlockTime::FrameNumber(frame as u32)
        }
    };

    if read_8bit_bs {
        // 8 bit block size - 1 is stored.
        let bs = try!(crc_input.read_byte());
        block_size = bs as u16 + 1;
    }
    if read_16bit_bs {
        // 16-bit block size - 1 is stored. Note that the max block size that
        // can be indicated in the streaminfo block is a 16-bit number, so a
        // value of 0xffff would be invalid because it exceeds the max block
        // size, though this is not mentioned explicitly in the specification.
        let bs = try!(crc_input.read_be_u16());
        if bs == 0xffff { return Err(FlacError::InvalidBlockSize); }
        block_size = bs + 1;
    }

    if read_8bit_sr {
        let sr = try!(crc_input.read_byte());
        sample_rate = Some(sr as u32);
    }
    if read_16bit_sr {
        let sr = try!(crc_input.read_be_u16());
        sample_rate = Some(sr as u32);
    }
    if read_16bit_sr_ten {
        let sr_ten = try!(crc_input.read_be_u16());
        sample_rate = Some(sr_ten as u32 * 10);
    }

    // Next is an 8-bit CRC that is computed over the entire header so far.
    let computed_crc = crc_input.crc();
    let presumed_crc = try!(crc_input.read_byte());

    if computed_crc != presumed_crc {
        return Err(FlacError::FrameHeaderCrcMismatch);
    }

    let frame_header = FrameHeader {
       block_time: block_time,
       block_size: block_size,
       sample_rate: sample_rate,
       n_channels: n_channels,
       channel_mode: channel_mode,
       bits_per_sample: bits_per_sample
    };
    Ok(frame_header)
}

/// Reads frames from a stream and exposes them as an iterator.
///
/// TODO: for now, it is assumes that the reader starts at a frame header;
/// no searching for a sync code is performed at the moment.
pub struct FrameReader<'r> {
    input: &'r mut (Reader + 'r),
}

/// TODO
struct Frame;

/// Either a `Frame` or a `FlacError`.
pub type FrameResult = FlacResult<Frame>;

impl<'r> FrameReader<'r> {

    /// Creates a new frame reader that will yield at least one element.
    pub fn new(input: &'r mut Reader) -> FrameReader<'r> {
        FrameReader { input: input }
    }

    fn read_next(&mut self) -> FrameResult {
        let header = try!(read_frame_header(self.input));
        // TODO: read the subframes and padding
        // TODO: read frame footer

        Ok(Frame)
    }
}

impl<'r> Iterator<FrameResult> for FrameReader<'r> {
    fn next(&mut self) -> Option<FrameResult> {
        // TODO: there needs to be a way to determine whether stream has ended.
        // In that case, we need to know the stream lengh, so we need to know
        // the streaminfo (which we might need anyway) ...
        Some(self.read_next())
    }

    // TODO: it would be possible to give quite an accurate size hint.
}
<commit_msg>remove debug printing in varlength int reading<commit_after>use checksum::Crc8Reader;
use error::{FlacError, FlacResult};

#[deriving(Copy)]
enum BlockingStrategy {
    Fixed,
    Variable
}

#[deriving(Copy)]
enum BlockTime {
    FrameNumber(u32),
    SampleNumber(u64)
}

#[deriving(Copy)]
enum ChannelMode {
    /// The channels are coded as-is.
    Raw,
    /// Channel 0 is the left channel, channel 1 is the side channel.
    LeftSideStereo,
    /// Channel 0 is the side channel, channel 1 is the right channel.
    RightSideStereo,
    /// Channel 0 is the mid channel, channel 1 is the side channel.
    MidSideStereo
}

#[deriving(Copy)]
struct FrameHeader {
    pub block_time: BlockTime,
    pub block_size: u16,
    pub sample_rate: Option<u32>,
    pub n_channels: u8,
    pub channel_mode: ChannelMode,
    pub bits_per_sample: Option<u8>
    // TODO: there is also a sample or frame number.
}

/// Reads a variable-length integer encoded as what is called "UTF-8" coding
/// in the specification. (It is not real UTF-8.) This function can read
/// integers encoded in this way up to 36-bit integers.
fn read_var_length_int(input: &mut Reader) -> FlacResult<u64> {
    use std::iter::range_step_inclusive;
    use std::io::stdio::flush;
    // The number of consecutive 1s followed by a 0 is the number of additional
    // bytes to read.
    let first = try!(input.read_byte());
    let mut read_additional = 0u;
    let mut mask_data = 0b0111_1111u8;
    let mut mask_mark = 0b1000_0000u8;

    // Determine the number of leading 1s.
    while first & mask_mark != 0 {
        read_additional = read_additional + 1;
        mask_data = mask_data >> 1;
        mask_mark = mask_mark >> 1;
    }

    // A single leading 1 is a follow-up byte and thus invalid.
    if read_additional > 0 {
        if read_additional == 1 {
            return Err(FlacError::InvalidVarLengthInt);
        } else {
            // The number of 1s (if > 1) is the total number of bytes, not the
            // number of additional bytes.
            read_additional = read_additional - 1;
        }
    }

    // Each additional byte will yield 6 extra bits, so shift the most
    // significant bits into the correct position.
    let mut result = (first & mask_data) as u64 << (6 * read_additional);
    for i in range_step_inclusive(read_additional as int - 1, 0, -1) {
        let byte = try!(input.read_byte());

        // The two most significant bits _must_ be 10.
        if byte & 0b1100_0000 != 0b1000_0000 {
            return Err(FlacError::InvalidVarLengthInt);
        }

        result = result | ((byte & 0b0011_1111) as u64 << (6 * i as uint));
    }

    Ok(result)
}

#[test]
fn verify_read_var_length_int() {
    use std::io::MemReader;

    let mut reader = MemReader::new(vec!(0x24, 0xc2, 0xa2, 0xe2, 0x82, 0xac,
                                         0xf0, 0x90, 0x8d, 0x88, 0xc2, 0x00,
                                         0x80));
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x24);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0xa2);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x20ac);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x010348);
    // Two-byte integer with invalid continuation byte should fail.
    assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
               FlacError::InvalidVarLengthInt);
    // Continuation byte can never be the first byte.
    assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
               FlacError::InvalidVarLengthInt);
}

fn read_frame_header(input: &mut Reader) -> FlacResult<FrameHeader> {
    // The frame header includes a CRC-8 at the end. It can be computed
    // automatically while reading, by wrapping the input reader in a reader
    // that computes the CRC.
    let mut crc_input = Crc8Reader::new(input);

    // First are 14 bits frame sync code, a reserved bit, and blocking stategy.
    let sync_res_block = try!(crc_input.read_be_u16());

    // The first 14 bits must be 11111111111110.
    let sync_code = sync_res_block & 0b1111_1111_1111_1100;
    if sync_code != 0b1111_1111_1111_1000 {
        return Err(FlacError::MissingFrameSyncCode);
    }

    // The next bit has a mandatory value of 0 (at the moment of writing, if
    // the bit has a different value, it could be a future stream that we
    // cannot read).
    if sync_res_block & 0b0000_0000_0000_0010 != 0 {
        return Err(FlacError::InvalidFrameHeader);
    }

    // The final bit determines the blocking strategy.
    let blocking_strategy = if sync_res_block & 0b0000_0000_0000_0001 == 0 {
        BlockingStrategy::Fixed
    } else {
        BlockingStrategy::Variable
    };

    // Next are 4 bits block size and 4 bits sample rate.
    let bs_sr = try!(crc_input.read_byte());
    let mut block_size = 0u16;
    let mut read_8bit_bs = false;
    let mut read_16bit_bs = false;

    // There are some pre-defined bit patterns. Some mean 'get from end of
    // header instead'.
    match bs_sr >> 4 {
        // The value 0000 is reserved.
        0b0000 => return Err(FlacError::InvalidFrameHeader),
        0b0001 => block_size = 192,
        n if 0b0010 <= n && n <= 0b0101 => block_size = 576 * (1 << (n - 2) as uint),
        0b0110 => read_8bit_bs = true,
        0b0111 => read_16bit_bs = true,
        n => block_size = 256 * (1 << (n - 8) as uint)
    }

    // For the sample rate there is a number of pre-defined bit patterns as
    // well. Again, some mean 'get from end of header instead'.
    let mut sample_rate = None;
    let mut read_8bit_sr = false;
    let mut read_16bit_sr = false;
    let mut read_16bit_sr_ten = false;

    match bs_sr & 0b0000_1111 {
        0b0000 => sample_rate = None, // 0000 means 'get from streaminfo block'.
        0b0001 => sample_rate = Some( 88_200),
        0b0010 => sample_rate = Some(176_400),
        0b0011 => sample_rate = Some(192_000),
        0b0100 => sample_rate = Some(  8_000),
        0b0101 => sample_rate = Some( 16_000),
        0b0110 => sample_rate = Some( 22_050),
        0b0111 => sample_rate = Some( 24_000),
        0b1000 => sample_rate = Some( 32_000),
        0b1001 => sample_rate = Some( 44_100),
        0b1010 => sample_rate = Some( 48_000),
        0b1011 => sample_rate = Some( 96_000),
        0b1100 => read_8bit_sr = true, // Read Hz from end of header.
        0b1101 => read_16bit_sr = true, // Read Hz from end of header.
        0b1110 => read_16bit_sr_ten = true, // Read tens of Hz from end of header.
        // 1111 is invalid to prevent sync-fooling.
        // Other values are impossible at this point.
        _ => return Err(FlacError::InvalidFrameHeader)
    }

    // Next are 4 bits channel assignment, 3 bits sample size, and 1 reserved bit.
    let chan_bps_res = try!(crc_input.read_byte());

    // The most significant 4 bits determine channel assignment.
    let (n_channels, channel_mode) = match chan_bps_res >> 4 {
        // Values 0 through 7 indicate n + 1 channels without mixing.
        n if n < 8 => (n + 1, ChannelMode::Raw),
        0b1000 => (2, ChannelMode::LeftSideStereo),
        0b1001 => (2, ChannelMode::RightSideStereo),
        0b1010 => (2, ChannelMode::MidSideStereo),
        // Values 1011 through 1111 are reserved and thus invalid.
        _ => return Err(FlacError::InvalidFrameHeader)
    };

    // The next three bits indicate bits per sample.
    let bits_per_sample = match (chan_bps_res & 0b0000_1110) >> 1 {
        0b000 => None, // 000 means 'get from streaminfo block'.
        0b001 => Some(8),
        0b010 => Some(12),
        0b100 => Some(16),
        0b101 => Some(20),
        0b110 => Some(24),
        // Values 011 and 111 are reserved. Other values are impossible.
        _ => return Err(FlacError::InvalidFrameHeader)
    };

    // The final bit has a mandatory value of 0.
    if chan_bps_res & 0b0000_0001 != 0 {
        return Err(FlacError::InvalidFrameHeader);
    }

    let block_time = match blocking_strategy {
        BlockingStrategy::Variable => {
            // The sample number is encoded in 8-56 bits, at most a 36-bit int.
            let sample = try!(read_var_length_int(&mut crc_input));
            BlockTime::SampleNumber(sample)
        },
        BlockingStrategy::Fixed => {
            // The frame number is encoded in 8-48 bits, at most a 31-bit int.
            let frame = try!(read_var_length_int(&mut crc_input));
            // A frame number larger than 31 bits is therefore invalid.
            if frame > 0x7fffffff {
                return Err(FlacError::InvalidFrameHeader);
            }
            BlockTime::FrameNumber(frame as u32)
        }
    };

    if read_8bit_bs {
        // 8 bit block size - 1 is stored.
        let bs = try!(crc_input.read_byte());
        block_size = bs as u16 + 1;
    }
    if read_16bit_bs {
        // 16-bit block size - 1 is stored. Note that the max block size that
        // can be indicated in the streaminfo block is a 16-bit number, so a
        // value of 0xffff would be invalid because it exceeds the max block
        // size, though this is not mentioned explicitly in the specification.
        let bs = try!(crc_input.read_be_u16());
        if bs == 0xffff { return Err(FlacError::InvalidBlockSize); }
        block_size = bs + 1;
    }

    if read_8bit_sr {
        let sr = try!(crc_input.read_byte());
        sample_rate = Some(sr as u32);
    }
    if read_16bit_sr {
        let sr = try!(crc_input.read_be_u16());
        sample_rate = Some(sr as u32);
    }
    if read_16bit_sr_ten {
        let sr_ten = try!(crc_input.read_be_u16());
        sample_rate = Some(sr_ten as u32 * 10);
    }

    // Next is an 8-bit CRC that is computed over the entire header so far.
    let computed_crc = crc_input.crc();
    let presumed_crc = try!(crc_input.read_byte());

    if computed_crc != presumed_crc {
        return Err(FlacError::FrameHeaderCrcMismatch);
    }

    let frame_header = FrameHeader {
       block_time: block_time,
       block_size: block_size,
       sample_rate: sample_rate,
       n_channels: n_channels,
       channel_mode: channel_mode,
       bits_per_sample: bits_per_sample
    };
    Ok(frame_header)
}

/// Reads frames from a stream and exposes them as an iterator.
///
/// TODO: for now, it is assumes that the reader starts at a frame header;
/// no searching for a sync code is performed at the moment.
pub struct FrameReader<'r> {
    input: &'r mut (Reader + 'r),
}

/// TODO
struct Frame;

/// Either a `Frame` or a `FlacError`.
pub type FrameResult = FlacResult<Frame>;

impl<'r> FrameReader<'r> {

    /// Creates a new frame reader that will yield at least one element.
    pub fn new(input: &'r mut Reader) -> FrameReader<'r> {
        FrameReader { input: input }
    }

    fn read_next(&mut self) -> FrameResult {
        let header = try!(read_frame_header(self.input));
        // TODO: read the subframes and padding
        // TODO: read frame footer

        Ok(Frame)
    }
}

impl<'r> Iterator<FrameResult> for FrameReader<'r> {
    fn next(&mut self) -> Option<FrameResult> {
        // TODO: there needs to be a way to determine whether stream has ended.
        // In that case, we need to know the stream lengh, so we need to know
        // the streaminfo (which we might need anyway) ...
        Some(self.read_next())
    }

    // TODO: it would be possible to give quite an accurate size hint.
}
<|endoftext|>


<commit_before>//! An emulated 128 bit unsigned integer.
//!
//! This module provides [`Emu128`], a 128 bit unsigned integer emulated
//! from two standard `u64` types. This is useful for operations on IPv6
//! address, which are 128 bit unsigned integers at heart.
//!
//! `Emu128` only implements operations that have been useful for
//! building the `Ipv6Net` type. It's not intended to be a full `u128`
//! implementation.
//!
//! [`Emu128`]: struct.Emu128.html

use std;
use std::ops::{BitAnd, BitOr, Shr, Shl};

/// An emulated 128 bit unsigned integer.
///
/// This module provides `Emu128`, a 128 bit unsigned integer emulated
/// from two standard `u64` types. This is useful for operations on IPv6
/// address, which are 128 bit unsigned integers at heart.
///
/// `Emu128` only implements operations that have been useful for
/// building the `Ipv6Net` type. It's not intended to be a full `u128`
/// implementation.
///
/// # Examples
///
/// ```
/// use ipnet::Emu128;
///
///
/// let i0 = Emu128::min_value();
/// let i1 = Emu128 { hi: 1, lo: 1 };
/// let i2 = Emu128::max_value();
/// let i3 = Emu128 { hi: 1, lo: std::u64::MAX };
///
/// assert_eq!(i0, Emu128 { hi: 0, lo: 0 });
/// assert_eq!(i2, Emu128 { hi: std::u64::MAX, lo: std::u64::MAX });
/// assert_eq!(i0.saturating_sub(i2), Emu128::min_value());
/// assert_eq!(i2.saturating_add(i2), Emu128::max_value());
/// assert_eq!(i1.saturating_add(i1), Emu128 { hi: 2, lo: 2 });
/// assert_eq!(i2.saturating_sub(i1), Emu128 { hi: std::u64::MAX-1, lo: std::u64::MAX-1 });
/// assert_eq!(i3.saturating_add(i1), Emu128 { hi: 3, lo: 0 });
/// assert_eq!(i3.saturating_sub(i1), Emu128 { hi: 0, lo: std::u64::MAX-1 });
/// assert_eq!(i1 << 1, Emu128 { hi: 2, lo: 2 });
/// assert_eq!(i1 << 63, Emu128 { hi: 1 << 63, lo: 1 << 63 });
/// assert_eq!(i1 << 127, Emu128 { hi: 1 << 63, lo: 0 });
/// assert_eq!(i1 >> 1, Emu128 { hi: 0, lo: 1u64 << 63 });
/// assert_eq!(i1 >> 63, Emu128 { hi: 0, lo: 2 });
/// assert_eq!(i1 >> 127, Emu128 { hi: 0, lo: 0 });
/// assert_eq!(i0 | i1, Emu128 { hi: 1, lo: 1 });
/// assert_eq!(i1 & i1, Emu128 { hi: 1, lo: 1 });
/// assert_eq!(i1 & i3, Emu128 { hi: 1, lo: 1 });
/// assert_eq!(i1 | i3, Emu128 { hi: 1, lo: std::u64::MAX });
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Emu128 {
    pub hi: u64,
    pub lo: u64,
}

impl Emu128 {
    pub fn min_value() -> Emu128 {
        Emu128 { hi: 0, lo: 0 }
    }

    pub fn max_value() -> Emu128 {
        Emu128 { hi: std::u64::MAX, lo: std::u64::MAX }
    }

    pub fn saturating_add(self, other: Emu128) -> Emu128 {
        let (lo, ov) = self.lo.overflowing_add(other.lo);
        let res = self.hi.checked_add(other.hi).and_then(|x| x.checked_add(if ov { 1 } else { 0 }));
        match res {
            Some(hi) => Emu128 { hi: hi, lo: lo },
            None => Emu128::max_value(),
        }
    }

    pub fn saturating_sub(self, other: Emu128) -> Emu128 {
        let (lo, ov) = self.lo.overflowing_sub(other.lo);
        let res = self.hi.checked_sub(other.hi).and_then(|x| x.checked_sub(if ov { 1 } else { 0 }));
        match res {
            Some(hi) => Emu128 { hi: hi, lo: lo },
            None => Emu128::min_value(),
        }
    }

    pub fn leading_zeros(self) -> u32 {
        if self.hi > 0 { self.hi.leading_zeros() } else { self.lo.leading_zeros() + 64 }
    }

    pub fn trailing_zeros(self) -> u32 {
        if self.lo > 0 { self.lo.trailing_zeros() } else { self.hi.trailing_zeros() + 64 }
    }
}

impl Shl<u8> for Emu128 {
    type Output = Self;

    fn shl(self, rhs: u8) -> Emu128 {
        if rhs < 64 {
            Emu128 {
                hi: self.hi << rhs | self.lo >> (64-rhs),
                lo: self.lo << rhs
            }
        }
        else {
            Emu128 {
                hi: self.lo << (rhs-64),
                lo: 0
            }
        }
    }
}

impl Shr<u8> for Emu128 {
    type Output = Self;

    fn shr(self, rhs: u8) -> Emu128 {
        if rhs < 64 {
            Emu128 {
                hi: self.hi >> rhs,
                lo: self.lo >> rhs | self.hi << (64-rhs),
            }
        }
        else {
            Emu128 {
                hi: 0,
                lo: self.hi >> (rhs-64),
            }
        }
    }
}

impl BitAnd for Emu128 {
    type Output = Self;
    fn bitand(self, rhs: Emu128) -> Emu128 {
        Emu128 {
            hi: self.hi & rhs.hi,
            lo: self.lo & rhs.lo,
        }
    }
}

impl BitOr for Emu128 {
    type Output = Self;
    fn bitor(self, rhs: Emu128) -> Emu128 {
        Emu128 {
            hi: self.hi | rhs.hi,
            lo: self.lo | rhs.lo,
        }
    }
}
<commit_msg>Adding conversions between Emu128 and a slice of two u64s.<commit_after>//! An emulated 128 bit unsigned integer.
//!
//! This module provides [`Emu128`], a 128 bit unsigned integer that is
//! emulated using two `u64` types. This is useful for operations on
//! IPv6 address, which are 128 bit unsigned integers.
//!
//! Currently `Emu128` only implements those operations that are useful
//! for the `Ipv6Net` type. It is not intended to become a full `u128`
//! implementation.
//!
//! [`Emu128`]: struct.Emu128.html

use std;
use std::ops::{BitAnd, BitOr, Shr, Shl};

/// An emulated 128 bit unsigned integer.
///
/// This module provides [`Emu128`], a 128 bit unsigned integer that is
/// emulated using two `u64` types. This is useful for operations on
/// IPv6 address, which are 128 bit unsigned integers.
///
/// Currently `Emu128` only implements those operations that are useful
/// for the `Ipv6Net` type. It is not intended to become a full `u128`
/// implementation.
///
/// # Examples
///
/// ```
/// use std::u64;
/// use ipnet::Emu128;
///
/// let i0 = Emu128::min_value();
/// let i1 = Emu128::from([1, 1]);
/// let i2 = Emu128::max_value();
/// let i3 = Emu128::from([1, u64::MAX]);
///
/// assert_eq!(i0, Emu128 { hi: 0, lo: 0 });
/// assert_eq!(i2, Emu128 { hi: std::u64::MAX, lo: std::u64::MAX });
/// assert_eq!(i0.saturating_sub(i2), Emu128::min_value());
/// assert_eq!(i2.saturating_add(i2), Emu128::max_value());
/// assert_eq!(i1.saturating_add(i1), Emu128 { hi: 2, lo: 2 });
/// assert_eq!(i2.saturating_sub(i1), Emu128 { hi: std::u64::MAX-1, lo: std::u64::MAX-1 });
/// assert_eq!(i3.saturating_add(i1), Emu128 { hi: 3, lo: 0 });
/// assert_eq!(i3.saturating_sub(i1), Emu128 { hi: 0, lo: std::u64::MAX-1 });
/// assert_eq!(i1 << 1, Emu128 { hi: 2, lo: 2 });
/// assert_eq!(i1 << 63, Emu128 { hi: 1 << 63, lo: 1 << 63 });
/// assert_eq!(i1 << 127, Emu128 { hi: 1 << 63, lo: 0 });
/// assert_eq!(i1 >> 1, Emu128 { hi: 0, lo: 1u64 << 63 });
/// assert_eq!(i1 >> 63, Emu128 { hi: 0, lo: 2 });
/// assert_eq!(i1 >> 127, Emu128 { hi: 0, lo: 0 });
/// assert_eq!(i0 | i1, Emu128 { hi: 1, lo: 1 });
/// assert_eq!(i1 & i1, Emu128 { hi: 1, lo: 1 });
/// assert_eq!(i1 & i3, Emu128 { hi: 1, lo: 1 });
/// assert_eq!(i1 | i3, Emu128 { hi: 1, lo: std::u64::MAX });
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Emu128 {
    pub hi: u64,
    pub lo: u64,
}

impl Emu128 {
    pub fn min_value() -> Emu128 {
        Emu128 { hi: 0, lo: 0 }
    }

    pub fn max_value() -> Emu128 {
        Emu128 { hi: std::u64::MAX, lo: std::u64::MAX }
    }

    pub fn saturating_add(self, other: Emu128) -> Emu128 {
        let (lo, ov) = self.lo.overflowing_add(other.lo);
        let res = self.hi.checked_add(other.hi).and_then(|x| x.checked_add(if ov { 1 } else { 0 }));
        match res {
            Some(hi) => Emu128 { hi: hi, lo: lo },
            None => Emu128::max_value(),
        }
    }

    pub fn saturating_sub(self, other: Emu128) -> Emu128 {
        let (lo, ov) = self.lo.overflowing_sub(other.lo);
        let res = self.hi.checked_sub(other.hi).and_then(|x| x.checked_sub(if ov { 1 } else { 0 }));
        match res {
            Some(hi) => Emu128 { hi: hi, lo: lo },
            None => Emu128::min_value(),
        }
    }

    pub fn leading_zeros(self) -> u32 {
        if self.hi > 0 { self.hi.leading_zeros() } else { self.lo.leading_zeros() + 64 }
    }

    pub fn trailing_zeros(self) -> u32 {
        if self.lo > 0 { self.lo.trailing_zeros() } else { self.hi.trailing_zeros() + 64 }
    }
}

impl Shl<u8> for Emu128 {
    type Output = Self;

    fn shl(self, rhs: u8) -> Emu128 {
        if rhs < 64 {
            Emu128 {
                hi: self.hi << rhs | self.lo >> (64-rhs),
                lo: self.lo << rhs
            }
        }
        else {
            Emu128 {
                hi: self.lo << (rhs-64),
                lo: 0
            }
        }
    }
}

impl Shr<u8> for Emu128 {
    type Output = Self;

    fn shr(self, rhs: u8) -> Emu128 {
        if rhs < 64 {
            Emu128 {
                hi: self.hi >> rhs,
                lo: self.lo >> rhs | self.hi << (64-rhs),
            }
        }
        else {
            Emu128 {
                hi: 0,
                lo: self.hi >> (rhs-64),
            }
        }
    }
}

impl BitAnd for Emu128 {
    type Output = Self;
    fn bitand(self, rhs: Emu128) -> Emu128 {
        Emu128 {
            hi: self.hi & rhs.hi,
            lo: self.lo & rhs.lo,
        }
    }
}

impl BitOr for Emu128 {
    type Output = Self;
    fn bitor(self, rhs: Emu128) -> Emu128 {
        Emu128 {
            hi: self.hi | rhs.hi,
            lo: self.lo | rhs.lo,
        }
    }
}

/// Convert an a `[u64; 2]` slice into an `Emu128`.
///
/// # Examples
///
/// ```
/// use ipnet::Emu128;
///
/// let u = Emu128::from([123u64, 123u64]);
/// let v: [u64; 2] = u.into();
/// assert_eq!(v, [123u64, 123u64]);
/// ```
impl From<[u64; 2]> for Emu128 {
    fn from(slice: [u64; 2]) -> Self {
        Emu128 {
            hi: slice[0],
            lo: slice[1],
        }
    }
}

/// Convert an Emu128 into a `[u64; 2]` slice.
///
/// # Examples
///
/// ```
/// use ipnet::Emu128;
///
/// let u = Emu128::from([123u64, 123u64]);
/// let v: [u64; 2] = u.into();
/// assert_eq!(v, [123u64, 123u64]);
/// ```
impl From<Emu128> for [u64; 2] {
    fn from(u: Emu128) -> Self {
        [u.hi, u.lo]
    }
}
<|endoftext|>


<commit_before>use libc::{c_int, c_uint, c_ulonglong, size_t};
use ffi::{core, target};
use ffi::execution_engine as engine;
use ffi::execution_engine::*;
use ffi::target_machine::LLVMCodeModel;
use std::marker::PhantomData;
use std::{mem, ptr};
use std::ops::*;
use compile::Compile;
use context::Context;
use module::Module;
use util::{self, CBox};
use value::{Function, Value};

/// Runs the module
pub trait ExecutionEngine<'a, 'b:'a> where LLVMExecutionEngineRef:From<&'b Self> {
    /// The options given to this upon creation
    type Options : Copy;
    fn new(module: &'a Module, options: Self::Options) -> Result<Self, CBox<'a, str>>;

    /// Add a module to the list of modules
    fn add_module(&'b self, module: &'a Module) {
        unsafe { engine::LLVMAddModule(self.into(), (&*module).into()) }
    }
    /// Remove a module from the list of modules
    fn remove_module(&'b self, module: &'a Module) -> &'a Module {
        unsafe {
            let mut out = mem::uninitialized();
            engine::LLVMRemoveModule(self.into(), module.into(), &mut out, ptr::null_mut());
            out.into()
        }
    }
    /// Execute all of the static constructors for this program
    fn run_static_constructors(&'b self) {
        unsafe { engine::LLVMRunStaticConstructors(self.into()) }
    }
    /// Execute all of the static destructors for this program
    fn run_static_destructors(&'b self) {
        unsafe { engine::LLVMRunStaticDestructors(self.into()) }
    }

    fn find_function(&'b self, name: &str) -> Option<&'a Function> {
        util::with_cstr(name, |c_name| unsafe {
            let mut out = mem::zeroed();
            engine::LLVMFindFunction(self.into(), c_name, &mut out);
            mem::transmute(out)
        })
    }

    /// Get a pointer to the global value given
    unsafe fn get_pointer<T>(&'b self, global: &'a Value) -> &'b T {
        mem::transmute(engine::LLVMGetPointerToGlobal(self.into(), global.into()))
    }
}

#[derive(Copy, Clone)]
pub struct JitOptions {
    pub opt_level: usize
}
pub struct JitEngine<'a> {
    engine: LLVMExecutionEngineRef,
    marker: PhantomData<&'a ()>
}
native_ref!{contra JitEngine, engine: LLVMExecutionEngineRef}
impl<'a, 'b> JitEngine<'a> {
    pub fn with_function<C, A, R>(&self, function: &'b Function, cb: C) where C:FnOnce(extern fn(A) -> R) {
        unsafe {
            let ptr:&u8 = self.get_pointer(function);
            cb(mem::transmute(ptr));
        }
    }
}
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for JitEngine<'a> {
    type Options = JitOptions;
    fn new(module: &'a Module, options: JitOptions) -> Result<JitEngine<'a>, CBox<'a, str>> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();
            engine::LLVMLinkInMCJIT();
            if target::LLVM_InitializeNativeTarget() == 1 {
                return Err("failed to initialize native target".into())
            }
            if target::LLVM_InitializeNativeAsmPrinter() == 1 {
                return Err("failed to initialize native asm printer".into())
            }
            let mut options = LLVMMCJITCompilerOptions {
                OptLevel: options.opt_level as c_uint,
                CodeModel: LLVMCodeModel::LLVMCodeModelDefault,
                NoFramePointerElim: 0,
                EnableFastISel: 1,
                MCJMM: ptr::null_mut()
            };
            let size = mem::size_of::<LLVMMCJITCompilerOptions>();
            let result = engine::LLVMCreateMCJITCompilerForModule(&mut ee, (&*module).into(), &mut options, size as size_t, &mut out);
            if result == 0 {
                Ok(ee.into())
            } else {
                Err(CBox::new(out))
            }
        }
    }
}
pub struct Interpreter<'a> {
    engine: LLVMExecutionEngineRef,
    marker: PhantomData<&'a ()>
}
native_ref!{contra Interpreter, engine: LLVMExecutionEngineRef}
impl<'a> Interpreter<'a> {
    /// Run `function` with the `args` given
    pub fn run_function(&self, function: &'a Function, args: &[GenericValue<'a>]) -> GenericValue<'a> {
        let ptr = args.as_ptr() as *mut LLVMGenericValueRef;
        unsafe { engine::LLVMRunFunction(self.into(), function.into(), args.len() as c_uint, ptr).into() }
    }
}
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for Interpreter<'a> {
    type Options = ();
    fn new(module: &'a Module, _: ()) -> Result<Interpreter<'a>, CBox<'a, str>> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();
            engine::LLVMLinkInInterpreter();
            let result = engine::LLVMCreateInterpreterForModule(&mut ee, (&*module).into(), &mut out);
            if result == 0 {
                Ok(ee.into())
            } else {
                Err(CBox::new(out))
            }
        }
    }
}
pub struct GenericValue<'a> {
    value: LLVMGenericValueRef,
    marker: PhantomData<&'a ()>
}
native_ref!(contra GenericValue, value: LLVMGenericValueRef);
impl<'a> Drop for GenericValue<'a> {
    fn drop(&mut self) {
        unsafe {
            engine::LLVMDisposeGenericValue(self.value)
        }
    }
}

pub trait GenericValueCast<'a> {
    fn to_generic(self, context: &'a Context) -> GenericValue<'a>;
    fn from_generic(value: GenericValue<'a>, context: &'a Context) -> Self;
}

impl<'a> GenericValueCast<'a> for f64 {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = core::LLVMDoubleTypeInContext(ctx.into());
            engine::LLVMCreateGenericValueOfFloat(ty, self).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, ctx: &'a Context) -> f64 {
        unsafe {
            let ty = core::LLVMDoubleTypeInContext(ctx.into());
            engine::LLVMGenericValueToFloat(ty, value.into())
        }
    }
}
impl<'a> GenericValueCast<'a> for f32 {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = core::LLVMFloatTypeInContext(ctx.into());
            engine::LLVMCreateGenericValueOfFloat(ty, self as f64).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, ctx: &'a Context) -> f32 {
        unsafe {
            let ty = core::LLVMFloatTypeInContext(ctx.into());
            engine::LLVMGenericValueToFloat(ty, value.into()) as f32
        }
    }
}
macro_rules! generic_int(
    ($ty:ty, $signed:expr) => (
        impl<'a> GenericValueCast<'a> for $ty {
            fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
                unsafe {
                    let ty = <Self as Compile<'a>>::get_type(ctx);
                    engine::LLVMCreateGenericValueOfInt(ty.into(), self as c_ulonglong, $signed as c_int).into()
                }
            }
            fn from_generic(value: GenericValue<'a>, _: &'a Context) -> $ty {
                unsafe {
                    engine::LLVMGenericValueToInt(value.into(), $signed as c_int) as $ty
                }
            }
        }
    );
    (some $signed:ty, $unsigned:ty) => (
        generic_int!{$signed, true}
        generic_int!{$unsigned, false}
    );
);

impl<'a> GenericValueCast<'a> for bool {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = <Self as Compile<'a>>::get_type(ctx);
            engine::LLVMCreateGenericValueOfInt(ty.into(), self as c_ulonglong, 0).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, _: &'a Context) -> bool {
        unsafe {
            engine::LLVMGenericValueToInt(value.into(), 0) != 0
        }
    }
}
generic_int!{some i8, u8}
generic_int!{some i16, u16}
generic_int!{some i32, u32}
generic_int!{some i64, u64}

pub trait Args<'a> {
    fn cast(self, context: &'a Context) -> Vec<GenericValue<'a>>;
}
impl<'a> Args<'a> for () {
    fn cast(self, _: &'a Context) -> Vec<GenericValue<'a>> {
        Vec::new()
    }
}
impl<'a, T> Args<'a> for (T) where T:GenericValueCast<'a> {
    fn cast(self, ctx: &'a Context) -> Vec<GenericValue<'a>> {
        vec![self.to_generic(ctx)]
    }
}
impl<'a, A, B> Args<'a> for (A, B) where A:GenericValueCast<'a>, B:GenericValueCast<'a> {
    fn cast(self, ctx: &'a Context) -> Vec<GenericValue<'a>> {
        vec![self.0.to_generic(ctx), self.1.to_generic(ctx)]
    }
}
<commit_msg>Improve documentation<commit_after>use libc::{c_int, c_uint, c_ulonglong, size_t};
use ffi::{core, target};
use ffi::execution_engine as engine;
use ffi::execution_engine::*;
use ffi::target_machine::LLVMCodeModel;
use std::marker::PhantomData;
use std::{mem, ptr};
use std::ops::*;
use compile::Compile;
use context::Context;
use module::Module;
use util::{self, CBox};
use value::{Function, Value};

/// Runs the module
pub trait ExecutionEngine<'a, 'b:'a> where LLVMExecutionEngineRef:From<&'b Self> {
    /// The options given to this upon creation
    type Options : Copy;
    /// Create a new execution engine with the given `Module` and options, or return a
    /// description of the error
    fn new(module: &'a Module, options: Self::Options) -> Result<Self, CBox<'a, str>>;

    /// Add a module to the list of modules
    fn add_module(&'b self, module: &'a Module) {
        unsafe { engine::LLVMAddModule(self.into(), (&*module).into()) }
    }
    /// Remove a module from the list of modules
    fn remove_module(&'b self, module: &'a Module) -> &'a Module {
        unsafe {
            let mut out = mem::uninitialized();
            engine::LLVMRemoveModule(self.into(), module.into(), &mut out, ptr::null_mut());
            out.into()
        }
    }
    /// Execute all of the static constructors for this program
    fn run_static_constructors(&'b self) {
        unsafe { engine::LLVMRunStaticConstructors(self.into()) }
    }
    /// Execute all of the static destructors for this program
    fn run_static_destructors(&'b self) {
        unsafe { engine::LLVMRunStaticDestructors(self.into()) }
    }

    fn find_function(&'b self, name: &str) -> Option<&'a Function> {
        util::with_cstr(name, |c_name| unsafe {
            let mut out = mem::zeroed();
            engine::LLVMFindFunction(self.into(), c_name, &mut out);
            mem::transmute(out)
        })
    }

    /// Get a pointer to the global value given
    unsafe fn get_pointer<T>(&'b self, global: &'a Value) -> &'b T {
        mem::transmute(engine::LLVMGetPointerToGlobal(self.into(), global.into()))
    }
}

/// The options to pass to the MCJIT backend
#[derive(Copy, Clone)]
pub struct JitOptions {
    /// The degree to which optimisations should be done, between 0 and 3
    pub opt_level: usize
}
/// The MCJIT backend, which compiles functions into machine code
pub struct JitEngine<'a> {
    engine: LLVMExecutionEngineRef,
    marker: PhantomData<&'a ()>
}
native_ref!{contra JitEngine, engine: LLVMExecutionEngineRef}
impl<'a, 'b> JitEngine<'a> {
    /// Run `cb` with the machine code for the `function`
    pub fn with_function<C, A, R>(&self, function: &'b Function, cb: C) where C:FnOnce(extern fn(A) -> R) {
        unsafe {
            let ptr:&u8 = self.get_pointer(function);
            cb(mem::transmute(ptr));
        }
    }
}
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for JitEngine<'a> {
    type Options = JitOptions;
    fn new(module: &'a Module, options: JitOptions) -> Result<JitEngine<'a>, CBox<'a, str>> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();
            engine::LLVMLinkInMCJIT();
            if target::LLVM_InitializeNativeTarget() == 1 {
                return Err("failed to initialize native target".into())
            }
            if target::LLVM_InitializeNativeAsmPrinter() == 1 {
                return Err("failed to initialize native asm printer".into())
            }
            let mut options = LLVMMCJITCompilerOptions {
                OptLevel: options.opt_level as c_uint,
                CodeModel: LLVMCodeModel::LLVMCodeModelDefault,
                NoFramePointerElim: 0,
                EnableFastISel: 1,
                MCJMM: ptr::null_mut()
            };
            let size = mem::size_of::<LLVMMCJITCompilerOptions>();
            let result = engine::LLVMCreateMCJITCompilerForModule(&mut ee, (&*module).into(), &mut options, size as size_t, &mut out);
            if result == 0 {
                Ok(ee.into())
            } else {
                Err(CBox::new(out))
            }
        }
    }
}
/// The interpreter backend
pub struct Interpreter<'a> {
    engine: LLVMExecutionEngineRef,
    marker: PhantomData<&'a ()>
}
native_ref!{contra Interpreter, engine: LLVMExecutionEngineRef}
impl<'a> Interpreter<'a> {
    /// Run `function` with the `args` given
    pub fn run_function(&self, function: &'a Function, args: &[GenericValue<'a>]) -> GenericValue<'a> {
        let ptr = args.as_ptr() as *mut LLVMGenericValueRef;
        unsafe { engine::LLVMRunFunction(self.into(), function.into(), args.len() as c_uint, ptr).into() }
    }
}
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for Interpreter<'a> {
    type Options = ();
    fn new(module: &'a Module, _: ()) -> Result<Interpreter<'a>, CBox<'a, str>> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();
            engine::LLVMLinkInInterpreter();
            let result = engine::LLVMCreateInterpreterForModule(&mut ee, (&*module).into(), &mut out);
            if result == 0 {
                Ok(ee.into())
            } else {
                Err(CBox::new(out))
            }
        }
    }
}
/// A wrapped value that can be passed to an interpreter function or returned from one
pub struct GenericValue<'a> {
    value: LLVMGenericValueRef,
    marker: PhantomData<&'a ()>
}
native_ref!(contra GenericValue, value: LLVMGenericValueRef);
impl<'a> Drop for GenericValue<'a> {
    fn drop(&mut self) {
        unsafe {
            engine::LLVMDisposeGenericValue(self.value)
        }
    }
}

/// A value that can be cast into a `GenericValue` and that a generic value can be cast into
pub trait GenericValueCast<'a> {
    /// Create a `GenericValue` from this value
    fn to_generic(self, context: &'a Context) -> GenericValue<'a>;
    /// Convert the `GenericValue` into a value of this type again
    fn from_generic(value: GenericValue<'a>, context: &'a Context) -> Self;
}

impl<'a> GenericValueCast<'a> for f64 {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = core::LLVMDoubleTypeInContext(ctx.into());
            engine::LLVMCreateGenericValueOfFloat(ty, self).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, ctx: &'a Context) -> f64 {
        unsafe {
            let ty = core::LLVMDoubleTypeInContext(ctx.into());
            engine::LLVMGenericValueToFloat(ty, value.into())
        }
    }
}
impl<'a> GenericValueCast<'a> for f32 {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = core::LLVMFloatTypeInContext(ctx.into());
            engine::LLVMCreateGenericValueOfFloat(ty, self as f64).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, ctx: &'a Context) -> f32 {
        unsafe {
            let ty = core::LLVMFloatTypeInContext(ctx.into());
            engine::LLVMGenericValueToFloat(ty, value.into()) as f32
        }
    }
}
macro_rules! generic_int(
    ($ty:ty, $signed:expr) => (
        impl<'a> GenericValueCast<'a> for $ty {
            fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
                unsafe {
                    let ty = <Self as Compile<'a>>::get_type(ctx);
                    engine::LLVMCreateGenericValueOfInt(ty.into(), self as c_ulonglong, $signed as c_int).into()
                }
            }
            fn from_generic(value: GenericValue<'a>, _: &'a Context) -> $ty {
                unsafe {
                    engine::LLVMGenericValueToInt(value.into(), $signed as c_int) as $ty
                }
            }
        }
    );
    (some $signed:ty, $unsigned:ty) => (
        generic_int!{$signed, true}
        generic_int!{$unsigned, false}
    );
);

impl<'a> GenericValueCast<'a> for bool {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = <Self as Compile<'a>>::get_type(ctx);
            engine::LLVMCreateGenericValueOfInt(ty.into(), self as c_ulonglong, 0).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, _: &'a Context) -> bool {
        unsafe {
            engine::LLVMGenericValueToInt(value.into(), 0) != 0
        }
    }
}
generic_int!{some i8, u8}
generic_int!{some i16, u16}
generic_int!{some i32, u32}
generic_int!{some i64, u64}
<|endoftext|>


<commit_before>//! Define results and error. `Result<T, CabotError>`
use std::error::Error;
use std::fmt::{self, Display};
use std::io::Error as IOError;
use std::string::FromUtf8Error;

use rustls::TLSError;
use url;

#[derive(Debug)]
/// Errors in cabot
pub enum CabotError {
    IOError(IOError),
    DNSLookupError(String),
    CertificateError(TLSError),
    SchemeError(String),
    HostnameParseError(String),
    OpaqueUrlError(String),
    UrlParseError(url::ParseError),
    HttpResponseParseError(String),
    EncodingError(FromUtf8Error),
}

impl Display for CabotError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let description = match self {
            CabotError::SchemeError(scheme) => format!("Unmanaged Scheme: {}", scheme),
            CabotError::OpaqueUrlError(url) => format!("Opaque URL Error: {}", url),
            CabotError::HostnameParseError(name) => format!("Invalid Hostname: {}", name),
            CabotError::UrlParseError(err) => format!("URL Parse Error: {}", err),
            CabotError::IOError(err) => format!("IO Error: {:?}", err),
            CabotError::DNSLookupError(err) => format!("DNS Lookup Error: {}", err),
            CabotError::CertificateError(err) => format!("Certificate Error: {}", err),
            // Unexpexcted Error, not used
            CabotError::HttpResponseParseError(err) => format!("HTTP Response Parse Error: {}", err),
            CabotError::EncodingError(err) => format!("Utf8 Encoding Error: {}", err),
        };
        write!(f, "{:?}: {}", self, description)
    }
}

impl Error for CabotError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        None
    }
}
<commit_msg>Fix the source implementation since there is errors<commit_after>//! Define results and error. `Result<T, CabotError>`
use std::error::Error;
use std::fmt::{self, Display};
use std::io::Error as IOError;
use std::string::FromUtf8Error;

use rustls::TLSError;
use url;

#[derive(Debug)]
/// Errors in cabot
pub enum CabotError {
    IOError(IOError),
    DNSLookupError(String),
    CertificateError(TLSError),
    SchemeError(String),
    HostnameParseError(String),
    OpaqueUrlError(String),
    UrlParseError(url::ParseError),
    HttpResponseParseError(String),
    EncodingError(FromUtf8Error),
}

impl Display for CabotError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let description = match self {
            CabotError::SchemeError(scheme) => format!("Unmanaged Scheme: {}", scheme),
            CabotError::OpaqueUrlError(url) => format!("Opaque URL Error: {}", url),
            CabotError::HostnameParseError(name) => format!("Invalid Hostname: {}", name),
            CabotError::UrlParseError(err) => format!("URL Parse Error: {}", err),
            CabotError::IOError(err) => format!("IO Error: {:?}", err),
            CabotError::DNSLookupError(err) => format!("DNS Lookup Error: {}", err),
            CabotError::CertificateError(err) => format!("Certificate Error: {}", err),
            // Unexpexcted Error, not used
            CabotError::HttpResponseParseError(err) => format!("HTTP Response Parse Error: {}", err),
            CabotError::EncodingError(err) => format!("Utf8 Encoding Error: {}", err),
        };
        write!(f, "{:?}: {}", self, description)
    }
}

impl Error for CabotError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        let err: Option<&(dyn Error + 'static)> = match self {
            CabotError::UrlParseError(err) => Some(err),
            CabotError::IOError(err) => Some(err),
            CabotError::CertificateError(err) => Some(err),
            CabotError::EncodingError(err) => Some(err),
            _ => None
        };
        err
    }
}
<|endoftext|>


<commit_before>use reqwest;
use serde_json;

#[derive(Debug)]
pub enum Error {
    SerdeError(serde_json::Error),
    ReqwestError(reqwest::Error),
    Generic(String),
}

impl From<reqwest::Error> for Error {
    fn from(err: reqwest::Error) -> Error {
        Error::ReqwestError(err)
    }
}

impl From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Error {
        Error::SerdeError(err)
    }
}

impl From<String> for Error {
    fn from(err: String) -> Error {
        Error::Generic(err)
    }
}

/*
impl RustixError {
    #[allow(dead_code)]
    pub fn to_string(self) -> String {
        use self::RustixError::*;

        match self {
            Generic(s) => String::from(s),
            Reqwest(e) => e.to_string(),
        }
    }
}
*/
<commit_msg>Add From<&str> for Error<commit_after>use reqwest;
use serde_json;

#[derive(Debug)]
pub enum Error {
    SerdeError(serde_json::Error),
    ReqwestError(reqwest::Error),
    Generic(String),
}

impl From<reqwest::Error> for Error {
    fn from(err: reqwest::Error) -> Error {
        Error::ReqwestError(err)
    }
}

impl From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Error {
        Error::SerdeError(err)
    }
}

impl From<String> for Error {
    fn from(err: String) -> Error {
        Error::Generic(err)
    }
}

impl<'a> From<&'a str> for Error {
    fn from(err: &str) -> Error {
        Error::Generic(err.into())
    }
}

/*
impl RustixError {
    #[allow(dead_code)]
    pub fn to_string(self) -> String {
        use self::RustixError::*;

        match self {
            Generic(s) => String::from(s),
            Reqwest(e) => e.to_string(),
        }
    }
}
*/
<|endoftext|>


<commit_before>//! Send record(s) into Fluentd.

use std::net::ToSocketAddrs;
use std::convert::AsRef;
use std::net;
use std::io::Write;
use record::{FluentError, Record};
use retry_conf::RetryConf;
use forwardable::forward::Forward;
use rustc_serialize::Encodable;
use rmp_serialize::Encoder;

#[derive(Debug, Clone, PartialEq)]
pub struct Fluent
    where A: ToSocketAddrs
{
    addr: A,
    tag: String,
    conf: RetryConf,
}

impl Fluent {
    /// Create Fluent type.
    ///
    /// ### Usage
    ///
    /// ```
    /// use fruently::fluent::Fluent;
    /// let fruently_with_str_tag = Fluent::new("0.0.0.0:24224", "test");
    /// let fruently_with_string_tag = Fluent::new("0.0.0.0:24224", "test".to_string());
    /// ```
    pub fn new<T>(addr: A, tag: T) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: RetryConf::new(),
        }
    }

    pub fn new_with_conf<T>(addr: A, tag: T, conf: RetryConf) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: conf,
        }
    }

    #[doc(hidden)]
    pub fn get_addr(&self) -> &A {
        &self.addr
    }

    #[doc(hidden)]
    pub fn get_tag(&self) -> String {
        self.tag.clone()
    }

    #[doc(hidden)]
    pub fn get_conf(&self) -> RetryConf {
        self.conf.clone()
    }

    #[doc(hidden)]
    /// For internal usage.
    pub fn closure_send_as_json(addr: &A, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    #[doc(hidden)]
    /// For internal usage.
    pub fn closure_send_as_msgpack<T: Encodable>(addr: &A,
                                                 record: &Record<T>)
                                                 -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let mut encoder = Encoder::new(&mut stream);
        let result = record.encode(&mut encoder);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    #[doc(hidden)]
    /// For internal usage.
    pub fn closure_send_as_forward<T: Encodable>(addr: &A,
                                                 forward: &Forward<T>)
                                                 -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let mut encoder = Encoder::new(&mut stream);
        let result = forward.encode(&mut encoder);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }
}

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

    #[test]
    fn create_fruently() {
        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let expected = Fluent {
            addr: "0.0.0.0:24224",
            tag: "test".to_string(),
            conf: RetryConf::new(),
        };
        assert_eq!(expected, fruently);
    }
}
<commit_msg>Suppress useless format! warnings<commit_after>//! Send record(s) into Fluentd.

use std::net::ToSocketAddrs;
use std::convert::AsRef;
use std::net;
use std::io::Write;
use record::{FluentError, Record};
use retry_conf::RetryConf;
use forwardable::forward::Forward;
use rustc_serialize::Encodable;
use rmp_serialize::Encoder;

#[derive(Debug, Clone, PartialEq)]
pub struct Fluent
    where A: ToSocketAddrs
{
    addr: A,
    tag: String,
    conf: RetryConf,
}

impl Fluent {
    /// Create Fluent type.
    ///
    /// ### Usage
    ///
    /// ```
    /// use fruently::fluent::Fluent;
    /// let fruently_with_str_tag = Fluent::new("0.0.0.0:24224", "test");
    /// let fruently_with_string_tag = Fluent::new("0.0.0.0:24224", "test".to_string());
    /// ```
    pub fn new<T>(addr: A, tag: T) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: tag.as_ref().to_owned(),
            conf: RetryConf::new(),
        }
    }

    pub fn new_with_conf<T>(addr: A, tag: T, conf: RetryConf) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: tag.as_ref().to_owned(),
            conf: conf,
        }
    }

    #[doc(hidden)]
    pub fn get_addr(&self) -> &A {
        &self.addr
    }

    #[doc(hidden)]
    pub fn get_tag(&self) -> String {
        self.tag.clone()
    }

    #[doc(hidden)]
    pub fn get_conf(&self) -> RetryConf {
        self.conf.clone()
    }

    #[doc(hidden)]
    /// For internal usage.
    pub fn closure_send_as_json(addr: &A, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    #[doc(hidden)]
    /// For internal usage.
    pub fn closure_send_as_msgpack<T: Encodable>(addr: &A,
                                                 record: &Record<T>)
                                                 -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let mut encoder = Encoder::new(&mut stream);
        let result = record.encode(&mut encoder);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    #[doc(hidden)]
    /// For internal usage.
    pub fn closure_send_as_forward<T: Encodable>(addr: &A,
                                                 forward: &Forward<T>)
                                                 -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let mut encoder = Encoder::new(&mut stream);
        let result = forward.encode(&mut encoder);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }
}

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

    #[test]
    fn create_fruently() {
        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let expected = Fluent {
            addr: "0.0.0.0:24224",
            tag: "test".to_string(),
            conf: RetryConf::new(),
        };
        assert_eq!(expected, fruently);
    }
}
<|endoftext|>


<commit_before>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use BuildQuery;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Option<Pagination>,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                client: {:?}, pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
               self.client,
               self.pagination)
    }
}

impl GitLab {
    pub fn _new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
            pagination: None,
        }
    }

    pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
        warn!("Using insecure http:// protocol: Token will be sent in clear!");
        GitLab::_new("http", domain, 80, private_token)
    }

    pub fn new(domain: &str, private_token: &str) -> GitLab {
        GitLab::_new("https", domain, 443, private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:\
    ///                     443/api/v3/groups?order_by=path&private_token=XXXXXXXXXXXXX";
    ///
    /// let gl = GitLab::new("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let params_splitter = if query.find('?').is_some() { "&" } else { "?" };
        let mut url = format!("{}://{}:{}/api/v{}/{}{}private_token={}",
                              self.scheme,
                              self.domain,
                              self.port,
                              API_VERSION,
                              query,
                              params_splitter,
                              self.private_token);

        self.pagination.as_ref().map(|pagination| {
            url.push_str(&format!("&page={}&per_page={}", pagination.page, pagination.per_page));
        });

        url
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        self.client.get(&url).header(hyper::header::Connection::close()).send()
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = Some(pagination);
    }

    pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
        where T: serde::Deserialize
    {
        let url = self.build_url(query);
        info!("url: {:?}", url);
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .unwrap();
        info!("res.status: {:?}", res.status);
        debug!("res.headers: {:?}", res.headers);
        debug!("res.url: {:?}", res.url);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        debug!("body:\n{:?}", body);

        // FIXME: Properly handle the error. Will require defining our own errors...
        assert_eq!(res.status, hyper::status::StatusCode::Ok);

        serde_json::from_str(body.as_str())
    }

    // pub fn version(&self) -> Result<Version, serde_json::Error> {
    //     self.get("version")
    // }
    //
    // pub fn groups(&self) -> Result<Groups, serde_json::Error> {
    //     self.get("groups")
    // }
    //
    // pub fn projects(&self) -> Result<Projects, serde_json::Error> {
    //     self.get("projects")
    // }

    pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
        let query = listing.build_query();
        self.get(&query)
    }

    pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
        let query = ::groups::owned_groups::Listing::new().build_query();
        info!("query: {:?}", query);
        self.get(&query)
    }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<commit_msg>Re-define GitLab::projects() to return a `ProjectsLister`<commit_after>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use BuildQuery;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Option<Pagination>,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                client: {:?}, pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
               self.client,
               self.pagination)
    }
}

impl GitLab {
    pub fn _new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
            pagination: None,
        }
    }

    pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
        warn!("Using insecure http:// protocol: Token will be sent in clear!");
        GitLab::_new("http", domain, 80, private_token)
    }

    pub fn new(domain: &str, private_token: &str) -> GitLab {
        GitLab::_new("https", domain, 443, private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:\
    ///                     443/api/v3/groups?order_by=path&private_token=XXXXXXXXXXXXX";
    ///
    /// let gl = GitLab::new("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let params_splitter = if query.find('?').is_some() { "&" } else { "?" };
        let mut url = format!("{}://{}:{}/api/v{}/{}{}private_token={}",
                              self.scheme,
                              self.domain,
                              self.port,
                              API_VERSION,
                              query,
                              params_splitter,
                              self.private_token);

        self.pagination.as_ref().map(|pagination| {
            url.push_str(&format!("&page={}&per_page={}", pagination.page, pagination.per_page));
        });

        url
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        self.client.get(&url).header(hyper::header::Connection::close()).send()
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = Some(pagination);
    }

    pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
        where T: serde::Deserialize
    {
        let url = self.build_url(query);
        info!("url: {:?}", url);
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .unwrap();
        info!("res.status: {:?}", res.status);
        debug!("res.headers: {:?}", res.headers);
        debug!("res.url: {:?}", res.url);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        debug!("body:\n{:?}", body);

        // FIXME: Properly handle the error. Will require defining our own errors...
        assert_eq!(res.status, hyper::status::StatusCode::Ok);

        serde_json::from_str(body.as_str())
    }

    // pub fn version(&self) -> Result<Version, serde_json::Error> {
    //     self.get("version")
    // }
    //
    // pub fn groups(&self) -> Result<Groups, serde_json::Error> {
    //     self.get("groups")
    // }

    pub fn projects(&self) -> ::projects::ProjectsLister {
        Default::default()
    }

    pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
        let query = listing.build_query();
        self.get(&query)
    }

    pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
        let query = ::groups::owned_groups::Listing::new().build_query();
        info!("query: {:?}", query);
        self.get(&query)
    }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<|endoftext|>


<commit_before>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use Version;
use Projects;
use BuildQuery;
use Groups;
// use Listing;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                client: {:?}, pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
               self.client,
               self.pagination)
    }
}

impl GitLab {
    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
            pagination: Pagination {
                page: 1,
                per_page: 20,
            },
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", domain, 443, &private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:\
    ///                     443/api/v3/groups?\
    ///                     order_by=path&private_token=XXXXXXXXXXXXX&page=1&per_page=20";
    ///
    /// let gl = GitLab::new_https("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let expected_url = "https://gitlab.example.com:\
                            443/api/v3/groups?\
                            order_by=path&private_token=XXXXXXXXXXXXX&page=1&per_page=20";

        let mut params_splitter = "?";
        if query.find("?").is_some() {
            params_splitter = "&";
        }
        format!("{}://{}:{}/api/v{}/{}{}private_token={}&page={}&per_page={}",
                self.scheme,
                self.domain,
                self.port,
                API_VERSION,
                query,
                params_splitter,
                self.private_token,
                self.pagination.page,
                self.pagination.per_page)
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        self.client.get(&url).header(hyper::header::Connection::close()).send()
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
        where T: serde::Deserialize
    {
        let url = self.build_url(&query);
        info!("url: {:?}", url);
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        debug!("body: {:?}", body);

        // FIXME: Properly handle the error. Will require defining our own errors...
        assert_eq!(res.status, hyper::status::StatusCode::Ok);

        serde_json::from_str(&body.as_str())
    }

    // pub fn version(&self) -> Result<Version, serde_json::Error> {
    //     self.get("version")
    // }
    //
    // pub fn groups(&self) -> Result<Groups, serde_json::Error> {
    //     self.get("groups")
    // }
    //
    // pub fn projects(&self) -> Result<Projects, serde_json::Error> {
    //     self.get("projects")
    // }

    pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
        let query = listing.build_query();
        self.get(&query)
    }

    pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
        let query = ::groups::owned_groups::Listing::new().build_query();
        info!("query: {:?}", query);
        self.get(&query)
    }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<commit_msg>Cleanup uses<commit_after>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use BuildQuery;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                client: {:?}, pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
               self.client,
               self.pagination)
    }
}

impl GitLab {
    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
            pagination: Pagination {
                page: 1,
                per_page: 20,
            },
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", domain, 443, &private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:\
    ///                     443/api/v3/groups?\
    ///                     order_by=path&private_token=XXXXXXXXXXXXX&page=1&per_page=20";
    ///
    /// let gl = GitLab::new_https("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let expected_url = "https://gitlab.example.com:\
                            443/api/v3/groups?\
                            order_by=path&private_token=XXXXXXXXXXXXX&page=1&per_page=20";

        let mut params_splitter = "?";
        if query.find("?").is_some() {
            params_splitter = "&";
        }
        format!("{}://{}:{}/api/v{}/{}{}private_token={}&page={}&per_page={}",
                self.scheme,
                self.domain,
                self.port,
                API_VERSION,
                query,
                params_splitter,
                self.private_token,
                self.pagination.page,
                self.pagination.per_page)
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        self.client.get(&url).header(hyper::header::Connection::close()).send()
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
        where T: serde::Deserialize
    {
        let url = self.build_url(&query);
        info!("url: {:?}", url);
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        debug!("body: {:?}", body);

        // FIXME: Properly handle the error. Will require defining our own errors...
        assert_eq!(res.status, hyper::status::StatusCode::Ok);

        serde_json::from_str(&body.as_str())
    }

    // pub fn version(&self) -> Result<Version, serde_json::Error> {
    //     self.get("version")
    // }
    //
    // pub fn groups(&self) -> Result<Groups, serde_json::Error> {
    //     self.get("groups")
    // }
    //
    // pub fn projects(&self) -> Result<Projects, serde_json::Error> {
    //     self.get("projects")
    // }

    pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
        let query = listing.build_query();
        self.get(&query)
    }

    pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
        let query = ::groups::owned_groups::Listing::new().build_query();
        info!("query: {:?}", query);
        self.get(&query)
    }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<|endoftext|>