<commit_before>extern crate num;
extern crate portaudio;
extern crate rtlsdr;

use num::complex::Complex;
use num::{Num, Zero};
use pa::error::Error as PAError;
use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use std::cmp::min;
use std::env;
use std::error::Error;
use std::f32::consts::PI;
use std::sync::mpsc::channel;
use std::thread;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8. I want the buffer sizes between the SDR
// and the audio sizes to match, but since we get two samples per read the
// buffer size needs to be double.
const SDR_BUF_SIZE: usize = 262_144;

// The buffer size for the audio sink.
const AUDIO_BUF_SIZE: usize = 524_288;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SDR_SAMPLE_RATE: u32 = 2_400_000;

// Here is the sample rate of the output waveform we'll try to use.
const AUDIO_SAMPLE_RATE: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

// We set the gain manually right now since it seems to be a better option
// than using the AGC (the SDR gets blazing hot with the AGC on).
const SDR_GAIN: i32 = 496;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index.")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency in MHz.")
        .parse::<f32>()?;

    // Set up the threading channels for communication between our two threads.
    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    // This thread only collects data off of the SDR as quickly as possible and
    // sends it out.
    thread::spawn(move || {
        // Initialize the SDR based on the user's input parameters.
        let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
        let mut sdr = RTLSDR {
            rtlsdr: init_sdr(sdr_index, fm_freq).unwrap(),
        };

        loop {
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let iq_vec = samps_to_cmplx(bytes.as_slice()).unwrap();
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    // This thread does all of the signal processing required to demodulate
    // the signal and get it to a nice audio stream.
    thread::spawn(move || {
        // Decimating down to 100k samples seems to work the best. I don't
        // really quite get why that is, so I'll need to do more research.
        let dec_rate_filt = 6;
        let dec_rate_audio = 4;

        let taps_filt =
            windowed_sinc(SDR_SAMPLE_RATE as f32, 16, &hamming);
        let taps_audio = windowed_sinc(
            SDR_SAMPLE_RATE as f32 / dec_rate_filt as f32,
            16,
            &hamming,
        );

        let mut prev = Complex::zero();
        loop {
            // First, low_pass and decimate the raw IQ signal.
            let mut iq_vec = dongle_rx.recv().unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(&iq_vec, dec_rate_filt);

            // Next, demodulate the signal and filter the signal again. The
            // second filter seems to help with the noise after demodulation.
            let res = demod_fm(&iq_vec, prev);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            demod_iq = decimate(&demod_iq, dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    // Initialize the PortAudio class. We use a blocking stream since we're
    // doing processing on the signal and can't keep up with non-blocking
    // timing requirements.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        AUDIO_SAMPLE_RATE as f64,
        AUDIO_BUF_SIZE as u32
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    loop {
        let demod_iq = demod_rx.recv().unwrap();
        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let mut out_frames = 0;

        while out_frames < buffer_frames {
            out_frames = match stream.write_available() {
                Ok(available) => match available {
                    pa::StreamAvailable::Frames(frames) => frames as u32,
                    pa::StreamAvailable::InputOverflowed => {
                        return Err(Box::new(PAError::InputOverflowed))
                    }
                    pa::StreamAvailable::OutputUnderflowed => {
                        return Err(Box::new(PAError::OutputUnderflowed))
                    }
                },
                Err(e) => return Err(Box::new(e)),
            };
        }

        let n_write_samples = buffer_frames as usize * CHANNELS as usize;

        stream.write(buffer_frames, |output| {
            for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            }
        })?;
    }
}

fn init_sdr(sdr_index: i32, fm_freq: u32) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SDR_SAMPLE_RATE));
    try!(sdr.set_tuner_gain(SDR_GAIN));
    try!(sdr.set_agc_mode(false));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

/// Decimates a signal by an integer factor.
///
/// # Arguments
///
/// * `signal` - The signal to decimate
/// * `dec_rate` - The decimation factor
///
fn decimate<T: Copy>(signal: &[T], dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

/// Converts samples from the SDR into complex IQ pairs.
///
/// # Arguments
///
/// * `bytes` - The unsigned bytes from the SDR.
///
fn samps_to_cmplx(bytes: &[u8]) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;
    }

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new(
            (iq[0] as f32 - 127.0) / 127.0,
            (iq[1] as f32 - 127.0) / 127.0,
        );
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

/// Performs FM demodulation on a complex signal.
///
/// # Arguments
///
/// * `iq` - The IQ samples to demodulate.
/// * `prev` - The previous sample from the previous demodulation.
/// * `deviation` - The maximum frequency deviation in Hz.
///
fn demod_fm(
    iq: &[Complex<f32>],
    prev: Complex<f32>,
) -> (Vec<f32>, Complex<f32>) {
    let mut p = prev;
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    // Magic gain number. Would be nice to get something better.
    let gain = SDR_SAMPLE_RATE as f32 / (2.0 * PI * 75.0);

    for samp in iq {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

/// Filters a Complex vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The complex samples to filter
/// * `taps` - The taps of the filter
///
fn filter<T: Copy + Num + Zero>(
    samples: &[Complex<T>],
    taps: &[T],
) -> Vec<Complex<T>> {
    let mut filt_samps: Vec<Complex<T>> = Vec::with_capacity(samples.len());

    for samp in 0..samples.len() {
        let mut filt_val = Complex::zero();
        for filt in 0..min(samp, taps.len()) {
            filt_val = filt_val + samples[samp - filt] * taps[filt];
        }
        filt_samps.push(filt_val);
    }

    filt_samps
}

/// Filters a real vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The real samples to filter
/// * `taps` - The taps of the filter
///
fn filter_real<T: Copy + Num + Zero>(samples: &[T], taps: &[T]) -> Vec<T> {
    let mut filt_samps: Vec<T> = Vec::with_capacity(samples.len());

    for samp in 0..samples.len() {
        let mut filt_val = T::zero();
        for filt in 0..min(samp, taps.len()) {
            filt_val = filt_val + samples[samp - filt] * taps[filt];
        }
        filt_samps.push(filt_val);
    }

    filt_samps
}

/// Generates a vector containing the taps for a Hamming window.
///
/// # Arguments
///
/// * `ntaps` - The number of taps to generate for the filter
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

/// Generates filter taps for a sinc filter with a windowing function.
///
/// # Arguments
///
/// * `sample_rate` - The sample frequency in Hertz
/// * `ntaps` - The number of taps to generate for the window
/// * `window` - The windowing function used to generate the taps for the window
///
fn windowed_sinc(
    sample_rate: f32,
    ntaps: usize,
    window: &Fn(usize) -> Vec<f32>,
) -> Vec<f32> {
    let wc: f32 = 2.0 * PI / sample_rate;

    let win_taps: Vec<f32> = window(ntaps);
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);

    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f = ix as f32;

        // The windowed sinc function is undefined at zero, so set it to
        // something sensible here.
        let mut hi = if ix == 0 {
            wc
        } else {
            (ix_f * wc).sin() / (ix_f)
        };
        hi *= win_taps[(ix + m) as usize];
        taps.push(hi);
    }
    taps
}
<commit_msg>Minor update in comments to indicate why 100k is the right size<commit_after>extern crate num;
extern crate portaudio;
extern crate rtlsdr;

use num::complex::Complex;
use num::{Num, Zero};
use pa::error::Error as PAError;
use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use std::cmp::min;
use std::env;
use std::error::Error;
use std::f32::consts::PI;
use std::sync::mpsc::channel;
use std::thread;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8. I want the buffer sizes between the SDR
// and the audio sizes to match, but since we get two samples per read the
// buffer size needs to be double.
const SDR_BUF_SIZE: usize = 262_144;

// The buffer size for the audio sink.
const AUDIO_BUF_SIZE: usize = 524_288;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SDR_SAMPLE_RATE: u32 = 2_400_000;

// Here is the sample rate of the output waveform we'll try to use.
const AUDIO_SAMPLE_RATE: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

// We set the gain manually right now since it seems to be a better option
// than using the AGC (the SDR gets blazing hot with the AGC on).
const SDR_GAIN: i32 = 496;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index.")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency in MHz.")
        .parse::<f32>()?;

    // Set up the threading channels for communication between our two threads.
    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    // This thread only collects data off of the SDR as quickly as possible and
    // sends it out.
    thread::spawn(move || {
        // Initialize the SDR based on the user's input parameters.
        let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
        let mut sdr = RTLSDR {
            rtlsdr: init_sdr(sdr_index, fm_freq).unwrap(),
        };

        loop {
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let iq_vec = samps_to_cmplx(bytes.as_slice()).unwrap();
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    // This thread does all of the signal processing required to demodulate
    // the signal and get it to a nice audio stream.
    thread::spawn(move || {
        // We decimate down to 100k samples. This is close to the optimal value
        // of 96k samples, but provides just enough buffer to avoid overruns and
        // improves the audio quality substantially.
        let dec_rate_filt = 6;
        let dec_rate_audio = 4;

        let taps_filt =
            windowed_sinc(SDR_SAMPLE_RATE as f32, 16, &hamming);
        let taps_audio = windowed_sinc(
            SDR_SAMPLE_RATE as f32 / dec_rate_filt as f32,
            16,
            &hamming,
        );

        let mut prev = Complex::zero();
        loop {
            // First, low_pass and decimate the raw IQ signal.
            let mut iq_vec = dongle_rx.recv().unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(&iq_vec, dec_rate_filt);

            // Next, demodulate the signal and filter the signal again. The
            // second filter seems to help with the noise after demodulation.
            let res = demod_fm(&iq_vec, prev);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            demod_iq = decimate(&demod_iq, dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    // Initialize the PortAudio class. We use a blocking stream since we're
    // doing processing on the signal and can't keep up with non-blocking
    // timing requirements.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        AUDIO_SAMPLE_RATE as f64,
        AUDIO_BUF_SIZE as u32
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    loop {
        let demod_iq = demod_rx.recv().unwrap();
        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let mut out_frames = 0;

        while out_frames < buffer_frames {
            out_frames = match stream.write_available() {
                Ok(available) => match available {
                    pa::StreamAvailable::Frames(frames) => frames as u32,
                    pa::StreamAvailable::InputOverflowed => {
                        return Err(Box::new(PAError::InputOverflowed))
                    }
                    pa::StreamAvailable::OutputUnderflowed => {
                        return Err(Box::new(PAError::OutputUnderflowed))
                    }
                },
                Err(e) => return Err(Box::new(e)),
            };
        }

        let n_write_samples = buffer_frames as usize * CHANNELS as usize;

        stream.write(buffer_frames, |output| {
            for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            }
        })?;
    }
}

fn init_sdr(sdr_index: i32, fm_freq: u32) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SDR_SAMPLE_RATE));
    try!(sdr.set_tuner_gain(SDR_GAIN));
    try!(sdr.set_agc_mode(false));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

/// Decimates a signal by an integer factor.
///
/// # Arguments
///
/// * `signal` - The signal to decimate
/// * `dec_rate` - The decimation factor
///
fn decimate<T: Copy>(signal: &[T], dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

/// Converts samples from the SDR into complex IQ pairs.
///
/// # Arguments
///
/// * `bytes` - The unsigned bytes from the SDR.
///
fn samps_to_cmplx(bytes: &[u8]) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;
    }

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new(
            (iq[0] as f32 - 127.0) / 127.0,
            (iq[1] as f32 - 127.0) / 127.0,
        );
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

/// Performs FM demodulation on a complex signal.
///
/// # Arguments
///
/// * `iq` - The IQ samples to demodulate.
/// * `prev` - The previous sample from the previous demodulation.
/// * `deviation` - The maximum frequency deviation in Hz.
///
fn demod_fm(
    iq: &[Complex<f32>],
    prev: Complex<f32>,
) -> (Vec<f32>, Complex<f32>) {
    let mut p = prev;
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    // Magic gain number. Would be nice to get something better.
    let gain = SDR_SAMPLE_RATE as f32 / (2.0 * PI * 75.0);

    for samp in iq {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

/// Filters a Complex vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The complex samples to filter
/// * `taps` - The taps of the filter
///
fn filter<T: Copy + Num + Zero>(
    samples: &[Complex<T>],
    taps: &[T],
) -> Vec<Complex<T>> {
    let mut filt_samps: Vec<Complex<T>> = Vec::with_capacity(samples.len());

    for samp in 0..samples.len() {
        let mut filt_val = Complex::zero();
        for filt in 0..min(samp, taps.len()) {
            filt_val = filt_val + samples[samp - filt] * taps[filt];
        }
        filt_samps.push(filt_val);
    }

    filt_samps
}

/// Filters a real vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The real samples to filter
/// * `taps` - The taps of the filter
///
fn filter_real<T: Copy + Num + Zero>(samples: &[T], taps: &[T]) -> Vec<T> {
    let mut filt_samps: Vec<T> = Vec::with_capacity(samples.len());

    for samp in 0..samples.len() {
        let mut filt_val = T::zero();
        for filt in 0..min(samp, taps.len()) {
            filt_val = filt_val + samples[samp - filt] * taps[filt];
        }
        filt_samps.push(filt_val);
    }

    filt_samps
}

/// Generates a vector containing the taps for a Hamming window.
///
/// # Arguments
///
/// * `ntaps` - The number of taps to generate for the filter
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

/// Generates filter taps for a sinc filter with a windowing function.
///
/// # Arguments
///
/// * `sample_rate` - The sample frequency in Hertz
/// * `ntaps` - The number of taps to generate for the window
/// * `window` - The windowing function used to generate the taps for the window
///
fn windowed_sinc(
    sample_rate: f32,
    ntaps: usize,
    window: &Fn(usize) -> Vec<f32>,
) -> Vec<f32> {
    let wc: f32 = 2.0 * PI / sample_rate;

    let win_taps: Vec<f32> = window(ntaps);
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);

    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f = ix as f32;

        // The windowed sinc function is undefined at zero, so set it to
        // something sensible here.
        let mut hi = if ix == 0 {
            wc
        } else {
            (ix_f * wc).sin() / (ix_f)
        };
        hi *= win_taps[(ix + m) as usize];
        taps.push(hi);
    }
    taps
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1,101);

    println!("The secret number is:{}", secret_number);

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {}", guess);
}
<commit_msg>Comparing the number guessed to the number generated. Handling smaller than, greater than and equal values<commit_after>extern crate rand;

use std::io;
use std:cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1,101);

    println!("The secret number is:{}", secret_number);

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {}", guess);

    match guess.cmp(&secret_number) {
	Ordering::Less => println!("Too small!"),
	Ordering::Greater => println!("Too bit!"),
	Ordering::Equial => println!("You win!"),
    }
}
<|endoftext|>


<commit_before>use elem;
use error::CTResult;
use parser::Parser;
use database::ElemDatabase;

pub fn pretty_print_mass(formula: &str, db_path: &Path) -> CTResult<()> {
    let molecule = try!(Parser::new(formula).parse_molecule());
    let molecule = elem::group_elems(molecule);
    let mut db = try!(ElemDatabase::open(db_path));
    let elem_data = try!(db.get_data(&molecule));
    let total = elem_data.iter()
                         .zip(molecule.iter())
                         .fold(0f64, |t, (ref data, ref elem)| t + data.mass * elem.coef as f64);

    for (data, elem) in elem_data.iter().zip(molecule.iter()) {
        println!("{: <3}  {: >5}    {: >14}    {: ^12}    {: >3}",
                 data.short_name,
                 elem.coef,
                 // extra format, since println! does not right-align the number
                 // when we specify the precision
                 format!("{:3.10}", data.mass),
                 data.long_name,
                 data.atomic_num);
    }
    println!("Total: {}", total);
    Ok(())
}<commit_msg>Tweak output from mass calculation<commit_after>use elem;
use error::CTResult;
use parser::Parser;
use database::ElemDatabase;

pub fn pretty_print_mass(formula: &str, db_path: &Path) -> CTResult<()> {
    let molecule = try!(Parser::new(formula).parse_molecule());
    let molecule = elem::group_elems(molecule);
    let mut db = try!(ElemDatabase::open(db_path));
    let elem_data = try!(db.get_data(&molecule));
    let total = elem_data.iter()
                         .zip(molecule.iter())
                         .fold(0f64, |t, (ref data, ref elem)| t + data.mass * elem.coef as f64);

    println!("abbrv.     amt.          M             name          Z");
    println!("------------------------------------------------------");
    for (data, elem) in elem_data.iter().zip(molecule.iter()) {
        println!("{: <3}  {: >10}    {: >12}    {: ^12}    {: >3}",
                 data.short_name,
                 elem.coef,
                 // extra format, since println! does not right-align the number
                 // when we specify the precision
                 format!("{:3.8}", data.mass),
                 data.long_name,
                 data.atomic_num);
    }
    println!("Total: {}", total);
    Ok(())
}<|endoftext|>


<commit_before>use {Math, c64, c128, ffi};

impl Math<f32> for c64 {
    fn abs(self) -> f32 {
        unsafe { ffi::cabsf(self) }
    }

    fn acos(self) -> c64 {
        unsafe { ffi::cacosf(self) }
    }

    fn acosh(self) -> c64 {
        unsafe { ffi::cacoshf(self) }
    }

    fn arg(self) -> f32 {
        unsafe { ffi::cargf(self) }
    }

    fn asin(self) -> c64 {
        unsafe { ffi::casinf(self) }
    }

    fn asinh(self) -> c64 {
        unsafe { ffi::casinhf(self) }
    }

    fn atan(self) -> c64 {
        unsafe { ffi::catanf(self) }
    }

    fn atanh(self) -> c64 {
        unsafe { ffi::catanhf(self) }
    }

    fn cos(self) -> c64 {
        unsafe { ffi::ccosf(self) }
    }

    fn cosh(self) -> c64 {
        unsafe { ffi::ccoshf(self) }
    }

    fn exp(self) -> c64 {
        unsafe { ffi::cexpf(self) }
    }

    fn imag(self) -> f32 {
        unsafe { ffi::cimagf(self) }
    }

    fn log(self) -> c64 {
        unsafe { ffi::clogf(self) }
    }

    fn conj(self) -> c64 {
        unsafe { ffi::cconjf(self) }
    }

    fn pow(self, n: c64) -> c64 {
        unsafe { ffi::cpowf(self, n) }
    }

    fn proj(self) -> c64 {
        unsafe { ffi::cprojf(self) }
    }

    fn real(self) -> f32 {
        unsafe { ffi::crealf(self) }
    }

    fn sin(self) -> c64 {
        unsafe { ffi::csinf(self) }
    }

    fn sinh(self) -> c64 {
        unsafe { ffi::csinhf(self) }
    }

    fn sqrt(self) -> c64 {
        unsafe { ffi::csqrtf(self) }
    }

    fn tan(self) -> c64 {
        unsafe { ffi::ctanf(self) }
    }

    fn tanh(self) -> c64 {
        unsafe { ffi::ctanhf(self) }
    }
}

impl Math<f64> for c128 {
    fn abs(self) -> f64 {
        unsafe { ffi::cabs(self) }
    }

    fn acos(self) -> c128 {
        unsafe { ffi::cacos(self) }
    }

    fn acosh(self) -> c128 {
        unsafe { ffi::cacosh(self) }
    }

    fn arg(self) -> f64 {
        unsafe { ffi::carg(self) }
    }

    fn asin(self) -> c128 {
        unsafe { ffi::casin(self) }
    }

    fn asinh(self) -> c128 {
        unsafe { ffi::casinh(self) }
    }

    fn atan(self) -> c128 {
        unsafe { ffi::catan(self) }
    }

    fn atanh(self) -> c128 {
        unsafe { ffi::catanh(self) }
    }

    fn cos(self) -> c128 {
        unsafe { ffi::ccos(self) }
    }

    fn cosh(self) -> c128 {
        unsafe { ffi::ccosh(self) }
    }

    fn exp(self) -> c128 {
        unsafe { ffi::cexp(self) }
    }

    fn imag(self) -> f64 {
        unsafe { ffi::cimag(self) }
    }

    fn log(self) -> c128 {
        unsafe { ffi::clog(self) }
    }

    fn conj(self) -> c128 {
        unsafe { ffi::cconj(self) }
    }

    fn pow(self, n: c128) -> c128 {
        unsafe { ffi::cpow(self, n) }
    }

    fn proj(self) -> c128 {
        unsafe { ffi::cproj(self) }
    }

    fn real(self) -> f64 {
        unsafe { ffi::creal(self) }
    }

    fn sin(self) -> c128 {
        unsafe { ffi::csin(self) }
    }

    fn sinh(self) -> c128 {
        unsafe { ffi::csinh(self) }
    }

    fn sqrt(self) -> c128 {
        unsafe { ffi::csqrt(self) }
    }

    fn tan(self) -> c128 {
        unsafe { ffi::ctan(self) }
    }

    fn tanh(self) -> c128 {
        unsafe { ffi::ctanh(self) }
    }
}

#[cfg(test)]
mod test {
    macro_rules! test {
        ($($ty:ident),+) => {$(
            mod $ty {
                use std::num::Float;

                use Math;
                use $ty::I;

                #[test]
                fn abs() {
                    let z = I * 4. + 3.;
                    assert_eq!(z.abs(), 5.)
                }

                #[test]
                fn arg() {
                    let z = I + 1.;
                    assert_eq!(z.arg(), Float::frac_pi_4())
                }

                #[test]
                fn imag() {
                    let z = I + 2.;
                    assert_eq!(z.imag(), 1.)
                }

                #[test]
                fn real() {
                    let z = I + 2.;
                    assert_eq!(z.real(), 2.)
                }
            })+
         }
    }

    test!(f32, f64);
}
<commit_msg>fix(tests): replace `frac_pi_4()` with `FRAC_PI_4`<commit_after>use {Math, c64, c128, ffi};

impl Math<f32> for c64 {
    fn abs(self) -> f32 {
        unsafe { ffi::cabsf(self) }
    }

    fn acos(self) -> c64 {
        unsafe { ffi::cacosf(self) }
    }

    fn acosh(self) -> c64 {
        unsafe { ffi::cacoshf(self) }
    }

    fn arg(self) -> f32 {
        unsafe { ffi::cargf(self) }
    }

    fn asin(self) -> c64 {
        unsafe { ffi::casinf(self) }
    }

    fn asinh(self) -> c64 {
        unsafe { ffi::casinhf(self) }
    }

    fn atan(self) -> c64 {
        unsafe { ffi::catanf(self) }
    }

    fn atanh(self) -> c64 {
        unsafe { ffi::catanhf(self) }
    }

    fn cos(self) -> c64 {
        unsafe { ffi::ccosf(self) }
    }

    fn cosh(self) -> c64 {
        unsafe { ffi::ccoshf(self) }
    }

    fn exp(self) -> c64 {
        unsafe { ffi::cexpf(self) }
    }

    fn imag(self) -> f32 {
        unsafe { ffi::cimagf(self) }
    }

    fn log(self) -> c64 {
        unsafe { ffi::clogf(self) }
    }

    fn conj(self) -> c64 {
        unsafe { ffi::cconjf(self) }
    }

    fn pow(self, n: c64) -> c64 {
        unsafe { ffi::cpowf(self, n) }
    }

    fn proj(self) -> c64 {
        unsafe { ffi::cprojf(self) }
    }

    fn real(self) -> f32 {
        unsafe { ffi::crealf(self) }
    }

    fn sin(self) -> c64 {
        unsafe { ffi::csinf(self) }
    }

    fn sinh(self) -> c64 {
        unsafe { ffi::csinhf(self) }
    }

    fn sqrt(self) -> c64 {
        unsafe { ffi::csqrtf(self) }
    }

    fn tan(self) -> c64 {
        unsafe { ffi::ctanf(self) }
    }

    fn tanh(self) -> c64 {
        unsafe { ffi::ctanhf(self) }
    }
}

impl Math<f64> for c128 {
    fn abs(self) -> f64 {
        unsafe { ffi::cabs(self) }
    }

    fn acos(self) -> c128 {
        unsafe { ffi::cacos(self) }
    }

    fn acosh(self) -> c128 {
        unsafe { ffi::cacosh(self) }
    }

    fn arg(self) -> f64 {
        unsafe { ffi::carg(self) }
    }

    fn asin(self) -> c128 {
        unsafe { ffi::casin(self) }
    }

    fn asinh(self) -> c128 {
        unsafe { ffi::casinh(self) }
    }

    fn atan(self) -> c128 {
        unsafe { ffi::catan(self) }
    }

    fn atanh(self) -> c128 {
        unsafe { ffi::catanh(self) }
    }

    fn cos(self) -> c128 {
        unsafe { ffi::ccos(self) }
    }

    fn cosh(self) -> c128 {
        unsafe { ffi::ccosh(self) }
    }

    fn exp(self) -> c128 {
        unsafe { ffi::cexp(self) }
    }

    fn imag(self) -> f64 {
        unsafe { ffi::cimag(self) }
    }

    fn log(self) -> c128 {
        unsafe { ffi::clog(self) }
    }

    fn conj(self) -> c128 {
        unsafe { ffi::cconj(self) }
    }

    fn pow(self, n: c128) -> c128 {
        unsafe { ffi::cpow(self, n) }
    }

    fn proj(self) -> c128 {
        unsafe { ffi::cproj(self) }
    }

    fn real(self) -> f64 {
        unsafe { ffi::creal(self) }
    }

    fn sin(self) -> c128 {
        unsafe { ffi::csin(self) }
    }

    fn sinh(self) -> c128 {
        unsafe { ffi::csinh(self) }
    }

    fn sqrt(self) -> c128 {
        unsafe { ffi::csqrt(self) }
    }

    fn tan(self) -> c128 {
        unsafe { ffi::ctan(self) }
    }

    fn tanh(self) -> c128 {
        unsafe { ffi::ctanh(self) }
    }
}

#[cfg(test)]
mod test {
    macro_rules! test {
        ($($ty:ident),+) => {$(
            mod $ty {
                use std::num::Float;

                use Math;
                use $ty::I;

                #[test]
                fn abs() {
                    let z = I * 4. + 3.;
                    assert_eq!(z.abs(), 5.)
                }

                #[test]
                fn arg() {
                    let z = I + 1.;
                    assert_eq!(z.arg(), ::std::$ty::consts::FRAC_PI_4)
                }

                #[test]
                fn imag() {
                    let z = I + 2.;
                    assert_eq!(z.imag(), 1.)
                }

                #[test]
                fn real() {
                    let z = I + 2.;
                    assert_eq!(z.real(), 2.)
                }
            })+
         }
    }

    test!(f32, f64);
}
<|endoftext|>


<commit_before>#![deny(rust_2018_idioms)]

use cargo::{
    core::{
        compiler::{CompileKind, CompileTarget, TargetInfo},
        package::PackageSet,
        registry::PackageRegistry,
        resolver::{self, features::RequestedFeatures, ResolveOpts},
        source::SourceMap,
        Dependency, Package, Source, SourceId, TargetKind,
    },
    sources::RegistrySource,
    util::{Config, VersionExt},
};
use itertools::Itertools;
use semver::Version;
use serde::{Deserialize, Serialize};
use std::{
    collections::{BTreeMap, BTreeSet, HashSet},
    io::Read,
    task::Poll,
};

const PLAYGROUND_TARGET_PLATFORM: &str = "x86_64-unknown-linux-gnu";

/// The list of crates from crates.io
#[derive(Debug, Deserialize)]
struct TopCrates {
    crates: Vec<Crate>,
}

/// The shared description of a crate
#[derive(Debug, Deserialize)]
struct Crate {
    #[serde(rename = "id")]
    name: String,
}

/// A mapping of a crates name to its identifier used in source code
#[derive(Debug, Serialize)]
pub struct CrateInformation {
    pub name: String,
    pub version: Version,
    pub id: String,
}

/// Hand-curated changes to the crate list
#[derive(Debug, Default, Deserialize)]
pub struct Modifications {
    #[serde(default)]
    pub exclusions: Vec<String>,
    #[serde(default)]
    pub additions: BTreeSet<String>,
}

#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "kebab-case")]
pub struct DependencySpec {
    #[serde(skip_serializing_if = "String::is_empty")]
    pub package: String,
    #[serde(serialize_with = "exact_version")]
    pub version: Version,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    pub features: Vec<String>,
    #[serde(skip_serializing_if = "is_true")]
    pub default_features: bool,
}

fn exact_version<S>(version: &Version, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    semver::Comparator {
        op: semver::Op::Exact,
        major: version.major,
        minor: Some(version.minor),
        patch: Some(version.patch),
        pre: version.pre.clone(),
    }
    .serialize(serializer)
}

fn is_true(b: &bool) -> bool {
    *b
}

impl Modifications {
    fn excluded(&self, name: &str) -> bool {
        self.exclusions.iter().any(|n| n == name)
    }
}

fn simple_get(url: &str) -> reqwest::Result<reqwest::blocking::Response> {
    reqwest::blocking::ClientBuilder::new()
        .user_agent("Rust Playground - Top Crates Utility")
        .build()?
        .get(url)
        .send()
}

impl TopCrates {
    /// List top 100 crates by number of downloads on crates.io.
    fn download() -> TopCrates {
        let resp = simple_get("https://crates.io/api/v1/crates?page=1&per_page=100&sort=downloads")
            .expect("Could not fetch top crates");
        assert!(
            resp.status().is_success(),
            "Could not download top crates; HTTP status was {}",
            resp.status(),
        );

        serde_json::from_reader(resp).expect("Invalid JSON")
    }

    fn add_rust_cookbook_crates(&mut self) {
        let mut resp = simple_get(
            "https://raw.githubusercontent.com/rust-lang-nursery/rust-cookbook/master/Cargo.toml",
        )
        .expect("Could not fetch cookbook manifest");
        assert!(
            resp.status().is_success(),
            "Could not download cookbook; HTTP status was {}",
            resp.status(),
        );

        let mut content = String::new();
        resp.read_to_string(&mut content)
            .expect("could not read cookbook manifest");

        let manifest = content
            .parse::<toml::Value>()
            .expect("could not parse cookbook manifest");

        let dependencies = manifest["dependencies"]
            .as_table()
            .expect("no dependencies found for cookbook manifest");
        self.crates.extend({
            dependencies.iter().map(|(name, _)| Crate {
                name: name.to_string(),
            })
        })
    }

    /// Add crates that have been hand-picked
    fn add_curated_crates(&mut self, modifications: &Modifications) {
        self.crates.extend({
            modifications
                .additions
                .iter()
                .cloned()
                .map(|name| Crate { name })
        });
    }
}

/// Finds the features specified by the custom metadata of `pkg`.
///
/// Our custom metadata format looks like:
///
///     [package.metadata.playground]
///     default-features = true
///     features = ["std", "extra-traits"]
///     all-features = false
///
/// All fields are optional.
fn playground_metadata_features(pkg: &Package) -> Option<(Vec<String>, bool)> {
    let custom_metadata = pkg.manifest().custom_metadata()?;
    let playground_metadata = custom_metadata.get("playground")?;

    #[derive(Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    struct Metadata {
        features: Vec<String>,
        default_features: bool,
        all_features: bool,
    }

    impl Default for Metadata {
        fn default() -> Self {
            Metadata {
                features: Vec::new(),
                default_features: true,
                all_features: false,
            }
        }
    }

    let metadata = match playground_metadata.clone().try_into::<Metadata>() {
        Ok(metadata) => metadata,
        Err(err) => {
            eprintln!(
                "Failed to parse custom metadata for {} {}: {}",
                pkg.name(),
                pkg.version(),
                err
            );
            return None;
        }
    };

    // If `all-features` is set then we ignore `features`.
    let summary = pkg.summary();
    let mut enabled_features: BTreeSet<String> = if metadata.all_features {
        summary.features().keys().map(ToString::to_string).collect()
    } else {
        metadata.features.into_iter().collect()
    };

    // If not opting out of default features, remove default features from the
    // explicit features list. This avoids ongoing spurious diffs in our
    // generated Cargo.toml as default features are added to a library.
    if metadata.default_features {
        if let Some(default_feature_names) = summary.features().get("default") {
            enabled_features.remove("default");
            for feature in default_feature_names {
                enabled_features.remove(&feature.to_string());
            }
        }
    }

    if !enabled_features.is_empty() || !metadata.default_features {
        Some((
            enabled_features.into_iter().collect(),
            metadata.default_features,
        ))
    } else {
        None
    }
}

pub fn generate_info(
    modifications: &Modifications,
) -> (BTreeMap<String, DependencySpec>, Vec<CrateInformation>) {
    // Setup to interact with cargo.
    let config = Config::default().expect("Unable to create default Cargo config");
    let _lock = config.acquire_package_cache_lock();
    let crates_io = SourceId::crates_io(&config).expect("Unable to create crates.io source ID");
    let mut source = RegistrySource::remote(crates_io, &HashSet::new(), &config)
        .expect("Unable to create registry source");
    source.invalidate_cache();
    source
        .block_until_ready()
        .expect("Unable to wait for registry to be ready");

    let mut top = TopCrates::download();
    top.add_rust_cookbook_crates();
    top.add_curated_crates(modifications);

    // Find the newest (non-prerelease, non-yanked) versions of all
    // the interesting crates.
    let mut summaries = Vec::new();
    for Crate { name } in &top.crates {
        if modifications.excluded(name) {
            continue;
        }

        // Query the registry for a summary of this crate.
        // Usefully, this doesn't seem to include yanked versions
        let dep = Dependency::parse(name, None, crates_io)
            .unwrap_or_else(|e| panic!("Unable to parse dependency for {}: {}", name, e));

        let matches = match source.query_vec(&dep) {
            Poll::Ready(Ok(v)) => v,
            Poll::Ready(Err(e)) => panic!("Unable to query registry for {}: {}", name, e),
            Poll::Pending => panic!("Registry not ready to query"),
        };

        // Find the newest non-prelease version
        let summary = matches
            .into_iter()
            .filter(|summary| !summary.version().is_prerelease())
            .max_by_key(|summary| summary.version().clone())
            .unwrap_or_else(|| panic!("Registry has no viable versions of {}", name));

        // Add a dependency on this crate.
        summaries.push((
            summary,
            ResolveOpts {
                dev_deps: false,
                features: RequestedFeatures::DepFeatures {
                    features: Default::default(),
                    uses_default_features: true,
                },
            },
        ));
    }

    // Resolve transitive dependencies.
    let mut registry = PackageRegistry::new(&config).expect("Unable to create package registry");
    registry.lock_patches();
    let try_to_use = Default::default();
    let resolve = resolver::resolve(&summaries, &[], &mut registry, &try_to_use, None, true)
        .expect("Unable to resolve dependencies");

    // Find crates incompatible with the playground's platform
    let mut valid_for_our_platform: BTreeSet<_> =
        summaries.iter().map(|(s, _)| s.package_id()).collect();

    let compile_target =
        CompileTarget::new(PLAYGROUND_TARGET_PLATFORM).expect("Unable to create a CompileTarget");
    let compile_kind = CompileKind::Target(compile_target);
    let rustc = config
        .load_global_rustc(None)
        .expect("Unable to load the global rustc");

    let target_info = TargetInfo::new(&config, &[compile_kind], &rustc, compile_kind)
        .expect("Unable to create a TargetInfo");
    let cc = target_info.cfg();

    let mut to_visit = valid_for_our_platform.clone();

    while !to_visit.is_empty() {
        let mut visit_next = BTreeSet::new();

        for package_id in to_visit {
            for (dep_pkg, deps) in resolve.deps(package_id) {
                let for_this_platform = deps.iter().any(|dep| {
                    dep.platform().map_or(true, |platform| {
                        platform.matches(PLAYGROUND_TARGET_PLATFORM, cc)
                    })
                });

                if for_this_platform {
                    valid_for_our_platform.insert(dep_pkg);
                    visit_next.insert(dep_pkg);
                }
            }
        }

        to_visit = visit_next;
    }

    // Remove invalid and excluded packages that have been added due to resolution
    let package_ids: Vec<_> = resolve
        .iter()
        .filter(|pkg| valid_for_our_platform.contains(pkg))
        .filter(|pkg| !modifications.excluded(pkg.name().as_str()))
        .collect();

    let mut sources = SourceMap::new();
    sources.insert(Box::new(source));

    let package_set =
        PackageSet::new(&package_ids, sources, &config).expect("Unable to create a PackageSet");

    let mut packages = package_set
        .get_many(package_set.package_ids())
        .expect("Unable to download packages");

    // Sort all packages by name then version (descending), so that
    // when we group them we know we get all the same crates together
    // and the newest version first.
    packages.sort_by(|a, b| {
        a.name()
            .cmp(&b.name())
            .then(a.version().cmp(&b.version()).reverse())
    });

    let mut dependencies = BTreeMap::new();
    let mut infos = Vec::new();

    for (name, pkgs) in &packages.into_iter().group_by(|pkg| pkg.name()) {
        let mut first = true;

        for pkg in pkgs {
            let version = pkg.version();

            let crate_name = pkg
                .targets()
                .iter()
                .flat_map(|target| match target.kind() {
                    TargetKind::Lib(_) => Some(target.crate_name()),
                    _ => None,
                })
                .next()
                .unwrap_or_else(|| panic!("{} did not have a library", name));

            // We see the newest version first. Any subsequent
            // versions will have their version appended so that they
            // are uniquely named
            let exposed_name = if first {
                crate_name.clone()
            } else {
                format!(
                    "{}_{}_{}_{}",
                    crate_name, version.major, version.minor, version.patch
                )
            };

            let (features, default_features) =
                playground_metadata_features(&pkg).unwrap_or_else(|| (Vec::new(), true));

            dependencies.insert(
                exposed_name.clone(),
                DependencySpec {
                    package: name.to_string(),
                    version: version.clone(),
                    features,
                    default_features,
                },
            );

            infos.push(CrateInformation {
                name: name.to_string(),
                version: version.clone(),
                id: exposed_name,
            });

            first = false;
        }
    }

    (dependencies, infos)
}
<commit_msg>Factor out global Cargo state into a struct<commit_after>#![deny(rust_2018_idioms)]

use cargo::{
    core::{
        compiler::{CompileKind, CompileTarget, TargetInfo},
        package::PackageSet,
        registry::PackageRegistry,
        resolver::{self, features::RequestedFeatures, ResolveOpts},
        source::SourceMap,
        Dependency, Package, Source, SourceId, TargetKind,
    },
    sources::RegistrySource,
    util::{Config, VersionExt},
};
use itertools::Itertools;
use semver::Version;
use serde::{Deserialize, Serialize};
use std::{
    collections::{BTreeMap, BTreeSet, HashSet},
    io::Read,
    task::Poll,
};

const PLAYGROUND_TARGET_PLATFORM: &str = "x86_64-unknown-linux-gnu";

struct GlobalState<'cfg> {
    config: &'cfg Config,
    target_info: TargetInfo,
    registry: PackageRegistry<'cfg>,
    crates_io: SourceId,
    source: RegistrySource<'cfg>,
    modifications: &'cfg Modifications,
}

/// The list of crates from crates.io
#[derive(Debug, Deserialize)]
struct TopCrates {
    crates: Vec<Crate>,
}

/// The shared description of a crate
#[derive(Debug, Deserialize)]
struct Crate {
    #[serde(rename = "id")]
    name: String,
}

/// A mapping of a crates name to its identifier used in source code
#[derive(Debug, Serialize)]
pub struct CrateInformation {
    pub name: String,
    pub version: Version,
    pub id: String,
}

/// Hand-curated changes to the crate list
#[derive(Debug, Default, Deserialize)]
pub struct Modifications {
    #[serde(default)]
    pub exclusions: Vec<String>,
    #[serde(default)]
    pub additions: BTreeSet<String>,
}

#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "kebab-case")]
pub struct DependencySpec {
    #[serde(skip_serializing_if = "String::is_empty")]
    pub package: String,
    #[serde(serialize_with = "exact_version")]
    pub version: Version,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    pub features: Vec<String>,
    #[serde(skip_serializing_if = "is_true")]
    pub default_features: bool,
}

fn exact_version<S>(version: &Version, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    semver::Comparator {
        op: semver::Op::Exact,
        major: version.major,
        minor: Some(version.minor),
        patch: Some(version.patch),
        pre: version.pre.clone(),
    }
    .serialize(serializer)
}

fn is_true(b: &bool) -> bool {
    *b
}

impl Modifications {
    fn excluded(&self, name: &str) -> bool {
        self.exclusions.iter().any(|n| n == name)
    }
}

fn simple_get(url: &str) -> reqwest::Result<reqwest::blocking::Response> {
    reqwest::blocking::ClientBuilder::new()
        .user_agent("Rust Playground - Top Crates Utility")
        .build()?
        .get(url)
        .send()
}

impl TopCrates {
    /// List top 100 crates by number of downloads on crates.io.
    fn download() -> TopCrates {
        let resp = simple_get("https://crates.io/api/v1/crates?page=1&per_page=100&sort=downloads")
            .expect("Could not fetch top crates");
        assert!(
            resp.status().is_success(),
            "Could not download top crates; HTTP status was {}",
            resp.status(),
        );

        serde_json::from_reader(resp).expect("Invalid JSON")
    }

    fn add_rust_cookbook_crates(&mut self) {
        let mut resp = simple_get(
            "https://raw.githubusercontent.com/rust-lang-nursery/rust-cookbook/master/Cargo.toml",
        )
        .expect("Could not fetch cookbook manifest");
        assert!(
            resp.status().is_success(),
            "Could not download cookbook; HTTP status was {}",
            resp.status(),
        );

        let mut content = String::new();
        resp.read_to_string(&mut content)
            .expect("could not read cookbook manifest");

        let manifest = content
            .parse::<toml::Value>()
            .expect("could not parse cookbook manifest");

        let dependencies = manifest["dependencies"]
            .as_table()
            .expect("no dependencies found for cookbook manifest");
        self.crates.extend({
            dependencies.iter().map(|(name, _)| Crate {
                name: name.to_string(),
            })
        })
    }

    /// Add crates that have been hand-picked
    fn add_curated_crates(&mut self, modifications: &Modifications) {
        self.crates.extend({
            modifications
                .additions
                .iter()
                .cloned()
                .map(|name| Crate { name })
        });
    }
}

/// Finds the features specified by the custom metadata of `pkg`.
///
/// Our custom metadata format looks like:
///
///     [package.metadata.playground]
///     default-features = true
///     features = ["std", "extra-traits"]
///     all-features = false
///
/// All fields are optional.
fn playground_metadata_features(pkg: &Package) -> Option<(Vec<String>, bool)> {
    let custom_metadata = pkg.manifest().custom_metadata()?;
    let playground_metadata = custom_metadata.get("playground")?;

    #[derive(Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    struct Metadata {
        features: Vec<String>,
        default_features: bool,
        all_features: bool,
    }

    impl Default for Metadata {
        fn default() -> Self {
            Metadata {
                features: Vec::new(),
                default_features: true,
                all_features: false,
            }
        }
    }

    let metadata = match playground_metadata.clone().try_into::<Metadata>() {
        Ok(metadata) => metadata,
        Err(err) => {
            eprintln!(
                "Failed to parse custom metadata for {} {}: {}",
                pkg.name(),
                pkg.version(),
                err
            );
            return None;
        }
    };

    // If `all-features` is set then we ignore `features`.
    let summary = pkg.summary();
    let mut enabled_features: BTreeSet<String> = if metadata.all_features {
        summary.features().keys().map(ToString::to_string).collect()
    } else {
        metadata.features.into_iter().collect()
    };

    // If not opting out of default features, remove default features from the
    // explicit features list. This avoids ongoing spurious diffs in our
    // generated Cargo.toml as default features are added to a library.
    if metadata.default_features {
        if let Some(default_feature_names) = summary.features().get("default") {
            enabled_features.remove("default");
            for feature in default_feature_names {
                enabled_features.remove(&feature.to_string());
            }
        }
    }

    if !enabled_features.is_empty() || !metadata.default_features {
        Some((
            enabled_features.into_iter().collect(),
            metadata.default_features,
        ))
    } else {
        None
    }
}

fn make_global_state<'cfg>(
    config: &'cfg Config,
    modifications: &'cfg Modifications,
) -> GlobalState<'cfg> {
    // Information about the playground's target platform.
    let compile_target =
        CompileTarget::new(PLAYGROUND_TARGET_PLATFORM).expect("Unable to create a CompileTarget");
    let compile_kind = CompileKind::Target(compile_target);
    let rustc = config
        .load_global_rustc(None)
        .expect("Unable to load the global rustc");
    let target_info = TargetInfo::new(config, &[compile_kind], &rustc, compile_kind)
        .expect("Unable to create a TargetInfo");

    // Registry of known packages.
    let mut registry = PackageRegistry::new(config).expect("Unable to create package registry");
    registry.lock_patches();

    // Source for obtaining packages from the crates.io registry.
    let crates_io = SourceId::crates_io(config).expect("Unable to create crates.io source ID");
    let mut source = RegistrySource::remote(crates_io, &HashSet::new(), config)
        .expect("Unable to create registry source");
    source.invalidate_cache();
    source
        .block_until_ready()
        .expect("Unable to wait for registry to be ready");

    GlobalState {
        config,
        target_info,
        registry,
        crates_io,
        source,
        modifications,
    }
}

pub fn generate_info(
    modifications: &Modifications,
) -> (BTreeMap<String, DependencySpec>, Vec<CrateInformation>) {
    // Setup to interact with cargo.
    let config = Config::default().expect("Unable to create default Cargo config");
    let _lock = config.acquire_package_cache_lock();
    let mut global = make_global_state(&config, modifications);

    let mut top = TopCrates::download();
    top.add_rust_cookbook_crates();
    top.add_curated_crates(global.modifications);

    // Find the newest (non-prerelease, non-yanked) versions of all
    // the interesting crates.
    let mut summaries = Vec::new();
    for Crate { name } in &top.crates {
        if global.modifications.excluded(name) {
            continue;
        }

        // Query the registry for a summary of this crate.
        // Usefully, this doesn't seem to include yanked versions
        let dep = Dependency::parse(name, None, global.crates_io)
            .unwrap_or_else(|e| panic!("Unable to parse dependency for {}: {}", name, e));

        let matches = match global.source.query_vec(&dep) {
            Poll::Ready(Ok(v)) => v,
            Poll::Ready(Err(e)) => panic!("Unable to query registry for {}: {}", name, e),
            Poll::Pending => panic!("Registry not ready to query"),
        };

        // Find the newest non-prelease version
        let summary = matches
            .into_iter()
            .filter(|summary| !summary.version().is_prerelease())
            .max_by_key(|summary| summary.version().clone())
            .unwrap_or_else(|| panic!("Registry has no viable versions of {}", name));

        // Add a dependency on this crate.
        summaries.push((
            summary,
            ResolveOpts {
                dev_deps: false,
                features: RequestedFeatures::DepFeatures {
                    features: Default::default(),
                    uses_default_features: true,
                },
            },
        ));
    }

    // Resolve transitive dependencies.
    let try_to_use = Default::default();
    let resolve = resolver::resolve(
        &summaries,
        &[],
        &mut global.registry,
        &try_to_use,
        None,
        true,
    )
    .expect("Unable to resolve dependencies");

    // Find crates incompatible with the playground's platform
    let mut valid_for_our_platform: BTreeSet<_> =
        summaries.iter().map(|(s, _)| s.package_id()).collect();

    let mut to_visit = valid_for_our_platform.clone();

    while !to_visit.is_empty() {
        let mut visit_next = BTreeSet::new();

        for package_id in to_visit {
            for (dep_pkg, deps) in resolve.deps(package_id) {
                let for_this_platform = deps.iter().any(|dep| {
                    dep.platform().map_or(true, |platform| {
                        platform.matches(PLAYGROUND_TARGET_PLATFORM, global.target_info.cfg())
                    })
                });

                if for_this_platform {
                    valid_for_our_platform.insert(dep_pkg);
                    visit_next.insert(dep_pkg);
                }
            }
        }

        to_visit = visit_next;
    }

    // Remove invalid and excluded packages that have been added due to resolution
    let package_ids: Vec<_> = resolve
        .iter()
        .filter(|pkg| valid_for_our_platform.contains(pkg))
        .filter(|pkg| !global.modifications.excluded(pkg.name().as_str()))
        .collect();

    let mut sources = SourceMap::new();
    sources.insert(Box::new(&mut global.source));

    let package_set = PackageSet::new(&package_ids, sources, global.config)
        .expect("Unable to create a PackageSet");

    let mut packages = package_set
        .get_many(package_set.package_ids())
        .expect("Unable to download packages");

    // Sort all packages by name then version (descending), so that
    // when we group them we know we get all the same crates together
    // and the newest version first.
    packages.sort_by(|a, b| {
        a.name()
            .cmp(&b.name())
            .then(a.version().cmp(&b.version()).reverse())
    });

    let mut dependencies = BTreeMap::new();
    let mut infos = Vec::new();

    for (name, pkgs) in &packages.into_iter().group_by(|pkg| pkg.name()) {
        let mut first = true;

        for pkg in pkgs {
            let version = pkg.version();

            let crate_name = pkg
                .targets()
                .iter()
                .flat_map(|target| match target.kind() {
                    TargetKind::Lib(_) => Some(target.crate_name()),
                    _ => None,
                })
                .next()
                .unwrap_or_else(|| panic!("{} did not have a library", name));

            // We see the newest version first. Any subsequent
            // versions will have their version appended so that they
            // are uniquely named
            let exposed_name = if first {
                crate_name.clone()
            } else {
                format!(
                    "{}_{}_{}_{}",
                    crate_name, version.major, version.minor, version.patch
                )
            };

            let (features, default_features) =
                playground_metadata_features(&pkg).unwrap_or_else(|| (Vec::new(), true));

            dependencies.insert(
                exposed_name.clone(),
                DependencySpec {
                    package: name.to_string(),
                    version: version.clone(),
                    features,
                    default_features,
                },
            );

            infos.push(CrateInformation {
                name: name.to_string(),
                version: version.clone(),
                id: exposed_name,
            });

            first = false;
        }
    }

    (dependencies, infos)
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate rustbox;
use std::comm::{Receiver, Sender};
use std::io::{File, BufferedReader};

macro_rules! some {
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => return None
        }
    )
}

pub struct Editor {
    pub sender: Sender<rustbox::Event>,
    pub events: Receiver<rustbox::Event>,
    pub buffers: Vec<Buf>
}

pub struct Buf {
    pub first_line: Line,
    pub last_line: Line,
    pub active: bool,
}

#[deriving(Clone)]
pub struct Line {
    pub data: Vec<u8>,
    pub prev: Option<Box<Line>>,
    pub next: Option<Box<Line>>,
}

pub enum Response {
    Continue,
    Quit,
}

impl Buf {
    pub fn new() -> Buf {
        Buf {
            first_line: Line::new(),
            last_line: Line::new(),
            active: false,
        }
    }

    pub fn new_from_file(filename: &String) -> Buf {
        let path = Path::new(filename.to_string());
        let file = match File::open(&path) {
            Ok(f) => f,
            Err(_) => fail!("Not implemented!"),
        };

        let mut new_buffer = Buf {
            first_line: Line::new(),
            last_line: Line::new(),
            active: false,
        };

        let mut br = BufferedReader::new(file);
        let mut blank_line = Line::new();

        new_buffer.first_line = blank_line.clone();
        loop {
            match br.read_line() {
                Ok(l) => {
                    blank_line.data = l.into_bytes();

                    if new_buffer.first_line.data.len() == 0 {
                        new_buffer.first_line.data = blank_line.data
                    }

                    blank_line.next = Some(box Line::new());
                },
                Err(_) => {
                    break;
                },
            }
            blank_line = *match blank_line.next {
                Some(l) => l.clone(),
                None => box Line::new(),
            };
        }
        new_buffer.last_line = blank_line;
        new_buffer
    }
}

impl Line {
    pub fn new() -> Line {
        Line {
            data: Vec::new(),
            prev: None,
            next: None,
        }
    }
}

impl Editor {
    pub fn new(filenames: Vec<String>) -> Editor {
        let mut buffers = Vec::new();

        if filenames.len() > 1 {
            for filename in filenames.iter() {
                let mut b = Buf::new_from_file(filename);
                b.active = true;
                buffers.push(b);
            }
        }

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            buffers: buffers,
        }
    }

    pub fn handle_key_event(&self, ch: u32) -> Response {
        match std::char::from_u32(ch) {
            Some('q') => Quit,
            _ => Continue,
        }
    }

    pub fn draw(&mut self) {
        for mut b in self.buffers.iter() {
            if b.active {
                let ref line = b.first_line;
                let line_data = std::str::from_utf8(line.data.as_slice());
                match line_data {
                    Some(text) => {
                        rustbox::print(1, 1, rustbox::Bold, rustbox::White, rustbox::Black, text.to_string());
                    },
                    None => {}
                }
            }
       }
    }

    pub fn start(&mut self) -> bool {
        loop {
            self.draw();
            rustbox::present();
            let status = match self.events.recv() {
                rustbox::KeyEvent(_, _, ch) => {
                    let status = self.handle_key_event(ch);
                    match status {
                        Quit => { false },
                        _ => { true },
                    }
                },
                _ => { true }
            };
            if status == false {
                return false;
            }
        }
    }

}

<commit_msg>Saving snapshot<commit_after>#![feature(macro_rules)]

extern crate rustbox;
use std::comm::{Receiver, Sender};
use std::io::{File, BufferedReader};
use std::str::from_utf8;

macro_rules! some {
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => return None
        }
    )
}

pub struct Editor {
    pub sender: Sender<rustbox::Event>,
    pub events: Receiver<rustbox::Event>,
    pub buffers: Vec<Buf>
}

pub struct Buf {
    pub first_line: Option<Box<Line>>,
    pub last_line: Option<Box<Line>>,
    pub active: bool,
    pub num_lines: int,
}

#[deriving(Clone)]
pub struct Line {
    pub data: Vec<u8>,
    pub prev: Option<Box<Line>>,
    pub next: Option<Box<Line>>,
}

pub enum Response {
    Continue,
    Quit,
}

impl Buf {
    pub fn new() -> Buf {
        Buf {
            first_line: Some(box Line::new()),
            last_line: Some(box Line::new()),
            active: false,
            num_lines: 0,
        }
    }

    pub fn new_from_file(filename: &String) -> Buf {
        let path = Path::new(filename.to_string());
        let file = match File::open(&path) {
            Ok(f) => f,
            Err(_) => fail!("Not implemented!"),
        };

        let mut new_buffer = Buf::new();
        let mut br = BufferedReader::new(file);
        let mut blank_line = Some(box Line::new());

        new_buffer.first_line = blank_line.clone();
        loop {
            match br.read_line() {
                Ok(ln) => {
                    match blank_line {
                        Some(ref mut line) => {
                            line.data = ln.into_bytes();
                            line.next = Some(box Line::new());

                            // rustbox::print(1, 10, rustbox::Bold, rustbox::White, rustbox::Black, line.data.to_string());
                        },
                        None => {}
                    }
                },
                Err(_) => { break; },
            }
            new_buffer.num_lines += 1;
            blank_line = match blank_line {
                Some(line) => line.next,
                None => None
            };
        }
        new_buffer.last_line = blank_line;
        new_buffer
    }
}

impl Line {
    pub fn new() -> Line {
        Line {
            data: Vec::new(),
            prev: None,
            next: None,
        }
    }
}

impl Editor {
    pub fn new(filenames: Vec<String>) -> Editor {
        let mut buffers = Vec::new();

        if filenames.len() > 1 {
            for filename in filenames.iter() {
                let mut b = Buf::new_from_file(filename);
                b.active = true;
                buffers.push(b);
            }
        }

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            buffers: buffers,
        }
    }

    pub fn handle_key_event(&self, ch: u32) -> Response {
        match std::char::from_u32(ch) {
            Some('q') => Quit,
            _ => Continue,
        }
    }

    pub fn draw(&mut self) {
        for mut b in self.buffers.iter() {
            let ref mut line = b.first_line;
            let i = 1;
            loop {
                match line {
                    Some(ref mut l) => {
                        let line_data = from_utf8(l.data.as_slice());
                        match line_data {
                            Some(text) => {
                                rustbox::print(1, i, rustbox::Bold, rustbox::White, rustbox::Black, line_data.to_string());
                            },
                            None => {}
                        }
                        let line = l.next;
                        i += 1;
                    },
                    None => { break; }
                }
            }
            // match b.first_line {
            //     Some(ref l) => {
            //         let line_data = from_utf8(l.data.as_slice());
            //         match line_data {
            //             Some(text) => {
            //                 rustbox::print(1, 8, rustbox::Bold, rustbox::White, rustbox::Black, b.num_lines.to_string());
            //                 rustbox::print(1, 9, rustbox::Bold, rustbox::White, rustbox::Black, line_data.to_string());
            //             },
            //             None => {}
            //         }
            //     },
            //     None => {}
            // }
        }
    }

    pub fn start(&mut self) -> bool {
        loop {
            self.draw();
            rustbox::present();
            let status = match self.events.recv() {
                rustbox::KeyEvent(_, _, ch) => {
                    let status = self.handle_key_event(ch);
                    match status {
                        Quit => { false },
                        _ => { true },
                    }
                },
                _ => { true }
            };
            if status == false {
                return false;
            }
        }
    }

}

<|endoftext|>


<commit_before>use parser::{Expression, WhileCondition, Statement};
use instructions::Instructions;
use memory::MemoryLayout;

use super::errors::Error;
use super::statements::expand;
use super::input::read_input;

pub fn while_loop(
    instructions: &mut Instructions,
    mem: &mut MemoryLayout,
    condition: WhileCondition,
    body: Vec<Statement>,
) -> Result<(), Error> {
    loop_condition(instructions, mem, &condition)?;

    instructions.jump_forward_if_zero();

    loop_body(instructions, mem, body)?;

    loop_condition(instructions, mem, &condition)?;

    instructions.jump_backward_unless_zero();

    Ok(())
}

pub fn loop_condition(
    instructions: &mut Instructions,
    mem: &mut MemoryLayout,
    condition: &WhileCondition,
) -> Result<(), Error> {
    let size = match condition {
        &WhileCondition::Input {ref name, slice} => {
            // We only need to undeclare if we did the declaration in the loop condition
            if slice.is_some() {
                // Since we're going to read input anyway, we don't need to
                // zero out this cell because it will be completely overwritten in the read
                mem.undeclare(name);
            }

            read_input(instructions, mem, name.clone(), slice)?;
            let (_, size) = mem.get_cell_contents(name).expect("read_input didn't declare name");
            size
        },
        &WhileCondition::Expression(Expression::StringLiteral(_)) => {
            return Err(Error::LoopStringLiteralUnsupported {});
        },
        &WhileCondition::Expression(Expression::Identifier(ref name)) => {
            let (_, size) = mem.get_cell_contents(name).ok_or_else(|| Error::UndeclaredIdentifier {name: name.clone()})?;
            size
        },
    };

    if size != 1 {
        return Err(Error::ConditionSizeInvalid {
            expected: 1,
            actual: size,
        });
    }

    Ok(())
}

fn loop_body(
    instructions: &mut Instructions,
    mem: &mut MemoryLayout,
    body: Vec<Statement>,
) -> Result<(), Error> {
    for stmt in body {
        expand(instructions, mem, stmt)?;
    }

    Ok(())
}
<commit_msg>Fixed severe bug with incomplete codegeneration in while loops<commit_after>use parser::{Expression, WhileCondition, Statement};
use instructions::Instructions;
use memory::MemoryLayout;

use super::errors::Error;
use super::statements::expand;
use super::input::read_input;

pub fn while_loop(
    instructions: &mut Instructions,
    mem: &mut MemoryLayout,
    condition: WhileCondition,
    body: Vec<Statement>,
) -> Result<(), Error> {
    loop_condition(instructions, mem, &condition)?;

    instructions.jump_forward_if_zero();

    loop_body(instructions, mem, body)?;

    loop_condition(instructions, mem, &condition)?;

    instructions.jump_backward_unless_zero();

    Ok(())
}

pub fn loop_condition(
    instructions: &mut Instructions,
    mem: &mut MemoryLayout,
    condition: &WhileCondition,
) -> Result<(), Error> {
    let size = match condition {
        &WhileCondition::Input {ref name, slice} => {
            // We only need to undeclare if we did the declaration in the loop condition
            if slice.is_some() {
                // Since we're going to read input anyway, we don't need to
                // zero out this cell because it will be completely overwritten in the read
                mem.undeclare(name);
            }

            read_input(instructions, mem, name.clone(), slice)?;
            let (position, size) = mem.get_cell_contents(name).expect("read_input didn't declare name");
            // Make sure we're at the right cell for the result of the condition
            instructions.move_right_by(position);
            size
        },
        &WhileCondition::Expression(Expression::StringLiteral(_)) => {
            return Err(Error::LoopStringLiteralUnsupported {});
        },
        &WhileCondition::Expression(Expression::Identifier(ref name)) => {
            let (position, size) = mem.get_cell_contents(name).ok_or_else(|| Error::UndeclaredIdentifier {name: name.clone()})?;
            // Make sure we're at the right cell for the result of the condition
            instructions.move_right_by(position);
            size
        },
    };

    if size != 1 {
        return Err(Error::ConditionSizeInvalid {
            expected: 1,
            actual: size,
        });
    }

    Ok(())
}

fn loop_body(
    instructions: &mut Instructions,
    mem: &mut MemoryLayout,
    body: Vec<Statement>,
) -> Result<(), Error> {
    for stmt in body {
        expand(instructions, mem, stmt)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::result::Result;
pub trait ProgramFragment {
    fn run(&self) -> Result<(), &'static str>;
}

pub trait Configurable {
    fn set_flag(&self) -> bool;
    fn set_arg(&self, key:&str, value:&str) -> &str;
}
<commit_msg>Configurable now describles Builder function<commit_after>use std::result::Result;
pub trait ProgramFragment {
    fn run(&self) -> Result<(), &'static str>;
}

pub trait Configurable<T> {
    fn set_flag(&self, key:&str, value:bool) -> &Self;
    fn set_arg(&self, key:&str, value:&str) -> &Self;
    fn config(&self) -> T;
}
<|endoftext|>


<commit_before>//! Query result rows.

use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt;
use std::ops::Deref;
use std::slice;

use {Result, Transaction, read_rows, DbErrorNew, SessionInfoNew, RowsNew, LazyRowsNew,
     StatementInternals, WrongTypeNew};
use types::{FromSql, SessionInfo, WrongType};
use stmt::{Statement, Column};
use error::Error;
use message::FrontendMessage::*;

enum StatementContainer<'a> {
    Borrowed(&'a Statement<'a>),
    Owned(Statement<'a>),
}

impl<'a> Deref for StatementContainer<'a> {
    type Target = Statement<'a>;

    fn deref(&self) -> &Statement<'a> {
        match *self {
            StatementContainer::Borrowed(s) => s,
            StatementContainer::Owned(ref s) => s,
        }
    }
}

/// The resulting rows of a query.
pub struct Rows<'stmt> {
    stmt: StatementContainer<'stmt>,
    data: Vec<Vec<Option<Vec<u8>>>>,
}

impl<'a> RowsNew<'a> for Rows<'a> {
    fn new(stmt: &'a Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
        Rows {
            stmt: StatementContainer::Borrowed(stmt),
            data: data,
        }
    }

    fn new_owned(stmt: Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
        Rows {
            stmt: StatementContainer::Owned(stmt),
            data: data,
        }
    }
}

impl<'a> fmt::Debug for Rows<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Rows")
           .field("columns", &self.columns())
           .field("rows", &self.data.len())
           .finish()
    }
}

impl<'stmt> Rows<'stmt> {
    /// Returns a slice describing the columns of the `Rows`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Returns the number of rows present.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Returns a specific `Row`.
    ///
    /// # Panics
    ///
    /// Panics if `idx` is out of bounds.
    pub fn get<'a>(&'a self, idx: usize) -> Row<'a> {
        Row {
            stmt: &*self.stmt,
            data: Cow::Borrowed(&self.data[idx]),
        }
    }

    /// Returns an iterator over the `Row`s.
    pub fn iter<'a>(&'a self) -> Iter<'a> {
        Iter {
            stmt: &*self.stmt,
            iter: self.data.iter(),
        }
    }
}

impl<'a> IntoIterator for &'a Rows<'a> {
    type Item = Row<'a>;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// An iterator over `Row`s.
pub struct Iter<'a> {
    stmt: &'a Statement<'a>,
    iter: slice::Iter<'a, Vec<Option<Vec<u8>>>>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Row<'a>;

    fn next(&mut self) -> Option<Row<'a>> {
        self.iter.next().map(|row| {
            Row {
                stmt: &*self.stmt,
                data: Cow::Borrowed(row),
            }
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<Row<'a>> {
        self.iter.next_back().map(|row| {
            Row {
                stmt: &*self.stmt,
                data: Cow::Borrowed(row),
            }
        })
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {}

/// A single result row of a query.
pub struct Row<'a> {
    stmt: &'a Statement<'a>,
    data: Cow<'a, [Option<Vec<u8>>]>,
}

impl<'a> fmt::Debug for Row<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Row")
           .field("statement", self.stmt)
           .finish()
    }
}

impl<'a> Row<'a> {
    /// Returns the number of values in the row.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Returns a slice describing the columns of the `Row`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column or the return type is
    /// not compatible with the Postgres type.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// # use postgres::{Connection, SslMode};
    /// # let conn = Connection::connect("", SslMode::None).unwrap();
    /// let stmt = conn.prepare("SELECT foo, bar from BAZ").unwrap();
    /// for row in &stmt.query(&[]).unwrap() {
    ///     let foo: i32 = row.get(0);
    ///     let bar: String = row.get("bar");
    ///     println!("{}: {}", foo, bar);
    /// }
    /// ```
    pub fn get<I, T>(&self, idx: I) -> T
        where I: RowIndex + fmt::Debug,
              T: FromSql
    {
        match self.get_inner(&idx) {
            Some(Ok(ok)) => ok,
            Some(Err(err)) => panic!("error retrieving column {:?}: {:?}", idx, err),
            None => panic!("no such column {:?}"),
        }
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// Returns `None` if the index does not reference a column, `Some(Err(..))`
    /// if there was an error converting the result value, and `Some(Ok(..))`
    /// on success.
    pub fn get_opt<I, T>(&self, idx: I) -> Option<Result<T>>
        where I: RowIndex,
              T: FromSql
    {
        self.get_inner(&idx)
    }

    fn get_inner<I, T>(&self, idx: &I) -> Option<Result<T>>
        where I: RowIndex,
              T: FromSql
    {
        let idx = match idx.idx(self.stmt) {
            Some(idx) => idx,
            None => return None,
        };

        let ty = self.stmt.columns()[idx].type_();
        if !<T as FromSql>::accepts(ty) {
            return Some(Err(Error::Conversion(Box::new(WrongType::new(ty.clone())))));
        }
        let conn = self.stmt.conn().conn.borrow();
        let value = match self.data[idx] {
            Some(ref data) => FromSql::from_sql(ty, &mut &**data, &SessionInfo::new(&*conn)),
            None => FromSql::from_sql_null(ty, &SessionInfo::new(&*conn)),
        };
        Some(value)
    }

    /// Retrieves the specified field as a raw buffer of Postgres data.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column.
    pub fn get_bytes<I>(&self, idx: I) -> Option<&[u8]>
        where I: RowIndex + fmt::Debug
    {
        match idx.idx(self.stmt) {
            Some(idx) => self.data[idx].as_ref().map(|e| &**e),
            None => panic!("invalid index {:?}", idx),
        }
    }
}

/// A trait implemented by types that can index into columns of a row.
pub trait RowIndex {
    /// Returns the index of the appropriate column, or `None` if no such
    /// column exists.
    fn idx(&self, stmt: &Statement) -> Option<usize>;
}

impl RowIndex for usize {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Option<usize> {
        if *self >= stmt.columns().len() {
            None
        } else {
            Some(*self)
        }
    }
}

impl<'a> RowIndex for &'a str {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Option<usize> {
        if let Some(idx) = stmt.columns().iter().position(|d| d.name() == *self) {
            return Some(idx);
        };

        // FIXME ASCII-only case insensitivity isn't really the right thing to
        // do. Postgres itself uses a dubious wrapper around tolower and JDBC
        // uses the US locale.
        stmt.columns().iter().position(|d| d.name().eq_ignore_ascii_case(*self))
    }
}

/// A lazily-loaded iterator over the resulting rows of a query.
pub struct LazyRows<'trans, 'stmt> {
    stmt: &'stmt Statement<'stmt>,
    data: VecDeque<Vec<Option<Vec<u8>>>>,
    name: String,
    row_limit: i32,
    more_rows: bool,
    finished: bool,
    _trans: &'trans Transaction<'trans>,
}

impl<'trans, 'stmt> LazyRowsNew<'trans, 'stmt> for LazyRows<'trans, 'stmt> {
    fn new(stmt: &'stmt Statement<'stmt>,
           data: VecDeque<Vec<Option<Vec<u8>>>>,
           name: String,
           row_limit: i32,
           more_rows: bool,
           finished: bool,
           trans: &'trans Transaction<'trans>)
           -> LazyRows<'trans, 'stmt> {
        LazyRows {
            stmt: stmt,
            data: data,
            name: name,
            row_limit: row_limit,
            more_rows: more_rows,
            finished: finished,
            _trans: trans,
        }
    }
}

impl<'a, 'b> Drop for LazyRows<'a, 'b> {
    fn drop(&mut self) {
        if !self.finished {
            let _ = self.finish_inner();
        }
    }
}

impl<'a, 'b> fmt::Debug for LazyRows<'a, 'b> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("LazyRows")
           .field("name", &self.name)
           .field("row_limit", &self.row_limit)
           .field("remaining_rows", &self.data.len())
           .field("more_rows", &self.more_rows)
           .finish()
    }
}

impl<'trans, 'stmt> LazyRows<'trans, 'stmt> {
    fn finish_inner(&mut self) -> Result<()> {
        let mut conn = self.stmt.conn().conn.borrow_mut();
        check_desync!(conn);
        conn.close_statement(&self.name, b'P')
    }

    fn execute(&mut self) -> Result<()> {
        let mut conn = self.stmt.conn().conn.borrow_mut();

        try!(conn.write_messages(&[Execute {
                                       portal: &self.name,
                                       max_rows: self.row_limit,
                                   },
                                   Sync]));
        read_rows(&mut conn, &mut self.data).map(|more_rows| self.more_rows = more_rows)
    }

    /// Returns a slice describing the columns of the `LazyRows`.
    pub fn columns(&self) -> &'stmt [Column] {
        self.stmt.columns()
    }

    /// Consumes the `LazyRows`, cleaning up associated state.
    ///
    /// Functionally identical to the `Drop` implementation on `LazyRows`
    /// except that it returns any error to the caller.
    pub fn finish(mut self) -> Result<()> {
        self.finish_inner()
    }
}

impl<'trans, 'stmt> Iterator for LazyRows<'trans, 'stmt> {
    type Item = Result<Row<'stmt>>;

    fn next(&mut self) -> Option<Result<Row<'stmt>>> {
        if self.data.is_empty() && self.more_rows {
            if let Err(err) = self.execute() {
                return Some(Err(err));
            }
        }

        self.data.pop_front().map(|r| {
            Ok(Row {
                stmt: self.stmt,
                data: Cow::Owned(r),
            })
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let lower = self.data.len();
        let upper = if self.more_rows {
            None
        } else {
            Some(lower)
        };
        (lower, upper)
    }
}
<commit_msg>Tweak a lifetime<commit_after>//! Query result rows.

use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt;
use std::ops::Deref;
use std::slice;

use {Result, Transaction, read_rows, DbErrorNew, SessionInfoNew, RowsNew, LazyRowsNew,
     StatementInternals, WrongTypeNew};
use types::{FromSql, SessionInfo, WrongType};
use stmt::{Statement, Column};
use error::Error;
use message::FrontendMessage::*;

enum StatementContainer<'a> {
    Borrowed(&'a Statement<'a>),
    Owned(Statement<'a>),
}

impl<'a> Deref for StatementContainer<'a> {
    type Target = Statement<'a>;

    fn deref(&self) -> &Statement<'a> {
        match *self {
            StatementContainer::Borrowed(s) => s,
            StatementContainer::Owned(ref s) => s,
        }
    }
}

/// The resulting rows of a query.
pub struct Rows<'stmt> {
    stmt: StatementContainer<'stmt>,
    data: Vec<Vec<Option<Vec<u8>>>>,
}

impl<'a> RowsNew<'a> for Rows<'a> {
    fn new(stmt: &'a Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
        Rows {
            stmt: StatementContainer::Borrowed(stmt),
            data: data,
        }
    }

    fn new_owned(stmt: Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
        Rows {
            stmt: StatementContainer::Owned(stmt),
            data: data,
        }
    }
}

impl<'a> fmt::Debug for Rows<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Rows")
           .field("columns", &self.columns())
           .field("rows", &self.data.len())
           .finish()
    }
}

impl<'stmt> Rows<'stmt> {
    /// Returns a slice describing the columns of the `Rows`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Returns the number of rows present.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Returns a specific `Row`.
    ///
    /// # Panics
    ///
    /// Panics if `idx` is out of bounds.
    pub fn get<'a>(&'a self, idx: usize) -> Row<'a> {
        Row {
            stmt: &*self.stmt,
            data: Cow::Borrowed(&self.data[idx]),
        }
    }

    /// Returns an iterator over the `Row`s.
    pub fn iter<'a>(&'a self) -> Iter<'a> {
        Iter {
            stmt: &*self.stmt,
            iter: self.data.iter(),
        }
    }
}

impl<'a> IntoIterator for &'a Rows<'a> {
    type Item = Row<'a>;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// An iterator over `Row`s.
pub struct Iter<'a> {
    stmt: &'a Statement<'a>,
    iter: slice::Iter<'a, Vec<Option<Vec<u8>>>>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Row<'a>;

    fn next(&mut self) -> Option<Row<'a>> {
        self.iter.next().map(|row| {
            Row {
                stmt: &*self.stmt,
                data: Cow::Borrowed(row),
            }
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<Row<'a>> {
        self.iter.next_back().map(|row| {
            Row {
                stmt: &*self.stmt,
                data: Cow::Borrowed(row),
            }
        })
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {}

/// A single result row of a query.
pub struct Row<'a> {
    stmt: &'a Statement<'a>,
    data: Cow<'a, [Option<Vec<u8>>]>,
}

impl<'a> fmt::Debug for Row<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Row")
           .field("statement", self.stmt)
           .finish()
    }
}

impl<'a> Row<'a> {
    /// Returns the number of values in the row.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Returns a slice describing the columns of the `Row`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column or the return type is
    /// not compatible with the Postgres type.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// # use postgres::{Connection, SslMode};
    /// # let conn = Connection::connect("", SslMode::None).unwrap();
    /// let stmt = conn.prepare("SELECT foo, bar from BAZ").unwrap();
    /// for row in &stmt.query(&[]).unwrap() {
    ///     let foo: i32 = row.get(0);
    ///     let bar: String = row.get("bar");
    ///     println!("{}: {}", foo, bar);
    /// }
    /// ```
    pub fn get<I, T>(&self, idx: I) -> T
        where I: RowIndex + fmt::Debug,
              T: FromSql
    {
        match self.get_inner(&idx) {
            Some(Ok(ok)) => ok,
            Some(Err(err)) => panic!("error retrieving column {:?}: {:?}", idx, err),
            None => panic!("no such column {:?}"),
        }
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// Returns `None` if the index does not reference a column, `Some(Err(..))`
    /// if there was an error converting the result value, and `Some(Ok(..))`
    /// on success.
    pub fn get_opt<I, T>(&self, idx: I) -> Option<Result<T>>
        where I: RowIndex,
              T: FromSql
    {
        self.get_inner(&idx)
    }

    fn get_inner<I, T>(&self, idx: &I) -> Option<Result<T>>
        where I: RowIndex,
              T: FromSql
    {
        let idx = match idx.idx(self.stmt) {
            Some(idx) => idx,
            None => return None,
        };

        let ty = self.stmt.columns()[idx].type_();
        if !<T as FromSql>::accepts(ty) {
            return Some(Err(Error::Conversion(Box::new(WrongType::new(ty.clone())))));
        }
        let conn = self.stmt.conn().conn.borrow();
        let value = match self.data[idx] {
            Some(ref data) => FromSql::from_sql(ty, &mut &**data, &SessionInfo::new(&*conn)),
            None => FromSql::from_sql_null(ty, &SessionInfo::new(&*conn)),
        };
        Some(value)
    }

    /// Retrieves the specified field as a raw buffer of Postgres data.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column.
    pub fn get_bytes<I>(&self, idx: I) -> Option<&[u8]>
        where I: RowIndex + fmt::Debug
    {
        match idx.idx(self.stmt) {
            Some(idx) => self.data[idx].as_ref().map(|e| &**e),
            None => panic!("invalid index {:?}", idx),
        }
    }
}

/// A trait implemented by types that can index into columns of a row.
pub trait RowIndex {
    /// Returns the index of the appropriate column, or `None` if no such
    /// column exists.
    fn idx(&self, stmt: &Statement) -> Option<usize>;
}

impl RowIndex for usize {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Option<usize> {
        if *self >= stmt.columns().len() {
            None
        } else {
            Some(*self)
        }
    }
}

impl<'a> RowIndex for &'a str {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Option<usize> {
        if let Some(idx) = stmt.columns().iter().position(|d| d.name() == *self) {
            return Some(idx);
        };

        // FIXME ASCII-only case insensitivity isn't really the right thing to
        // do. Postgres itself uses a dubious wrapper around tolower and JDBC
        // uses the US locale.
        stmt.columns().iter().position(|d| d.name().eq_ignore_ascii_case(*self))
    }
}

/// A lazily-loaded iterator over the resulting rows of a query.
pub struct LazyRows<'trans, 'stmt> {
    stmt: &'stmt Statement<'stmt>,
    data: VecDeque<Vec<Option<Vec<u8>>>>,
    name: String,
    row_limit: i32,
    more_rows: bool,
    finished: bool,
    _trans: &'trans Transaction<'trans>,
}

impl<'trans, 'stmt> LazyRowsNew<'trans, 'stmt> for LazyRows<'trans, 'stmt> {
    fn new(stmt: &'stmt Statement<'stmt>,
           data: VecDeque<Vec<Option<Vec<u8>>>>,
           name: String,
           row_limit: i32,
           more_rows: bool,
           finished: bool,
           trans: &'trans Transaction<'trans>)
           -> LazyRows<'trans, 'stmt> {
        LazyRows {
            stmt: stmt,
            data: data,
            name: name,
            row_limit: row_limit,
            more_rows: more_rows,
            finished: finished,
            _trans: trans,
        }
    }
}

impl<'a, 'b> Drop for LazyRows<'a, 'b> {
    fn drop(&mut self) {
        if !self.finished {
            let _ = self.finish_inner();
        }
    }
}

impl<'a, 'b> fmt::Debug for LazyRows<'a, 'b> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("LazyRows")
           .field("name", &self.name)
           .field("row_limit", &self.row_limit)
           .field("remaining_rows", &self.data.len())
           .field("more_rows", &self.more_rows)
           .finish()
    }
}

impl<'trans, 'stmt> LazyRows<'trans, 'stmt> {
    fn finish_inner(&mut self) -> Result<()> {
        let mut conn = self.stmt.conn().conn.borrow_mut();
        check_desync!(conn);
        conn.close_statement(&self.name, b'P')
    }

    fn execute(&mut self) -> Result<()> {
        let mut conn = self.stmt.conn().conn.borrow_mut();

        try!(conn.write_messages(&[Execute {
                                       portal: &self.name,
                                       max_rows: self.row_limit,
                                   },
                                   Sync]));
        read_rows(&mut conn, &mut self.data).map(|more_rows| self.more_rows = more_rows)
    }

    /// Returns a slice describing the columns of the `LazyRows`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Consumes the `LazyRows`, cleaning up associated state.
    ///
    /// Functionally identical to the `Drop` implementation on `LazyRows`
    /// except that it returns any error to the caller.
    pub fn finish(mut self) -> Result<()> {
        self.finish_inner()
    }
}

impl<'trans, 'stmt> Iterator for LazyRows<'trans, 'stmt> {
    type Item = Result<Row<'stmt>>;

    fn next(&mut self) -> Option<Result<Row<'stmt>>> {
        if self.data.is_empty() && self.more_rows {
            if let Err(err) = self.execute() {
                return Some(Err(err));
            }
        }

        self.data.pop_front().map(|r| {
            Ok(Row {
                stmt: self.stmt,
                data: Cow::Owned(r),
            })
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let lower = self.data.len();
        let upper = if self.more_rows {
            None
        } else {
            Some(lower)
        };
        (lower, upper)
    }
}
<|endoftext|>