<commit_before>use crate::common::State;
use crate::http::{http_main_server, http_redirect_server};
use anyhow::Result;
use extendedmind_engine::tcp;
use std::path::PathBuf;
use tide_acme::rustls_acme::caches::DirCache;
use tide_acme::{AcmeConfig, TideRustlsExt};

fn setup_logging(log_to_stderr: bool) {
    let base_config = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug);
    let std_config = if log_to_stderr {
        fern::Dispatch::new().chain(std::io::stderr())
    } else {
        fern::Dispatch::new().chain(std::io::stdout())
    };

    base_config.chain(std_config).apply().unwrap();
}

pub async fn start_server(
    initial_state: State,
    static_root_dir: Option<PathBuf>,
    http_port: Option<u16>,
    https_port: Option<u16>,
    domain: Option<String>,
    acme_email: Option<String>,
    acme_dir: Option<String>,
    tcp_port: Option<u16>,
    skip_compress_mime: Option<Vec<String>>,
    cache_ttl_sec: Option<u64>,
    cache_tti_sec: Option<u64>,
    inline_css_path: Option<Vec<String>>,
    immutable_path: Option<Vec<String>>,
) -> Result<()> {
    let engine = initial_state.engine.clone();

    if let Some(http_port) = http_port {
        let main_server = http_main_server(
            initial_state,
            static_root_dir,
            skip_compress_mime,
            cache_ttl_sec,
            cache_tti_sec,
            inline_css_path,
            immutable_path,
        )
        .unwrap();
        if let Some(https_port) = https_port {
            if domain.is_none() || acme_dir.is_none() || acme_email.is_none() {
                anyhow::bail!(
                    "With --https-port also --domain, --acme-email and --acme-dir are required"
                );
            }
            let domain = domain.unwrap();
            let acme_dir = acme_dir.unwrap();
            let acme_email = acme_email.unwrap();
            let redirect_server =
                http_redirect_server(format!("https://{}:{}", &domain, &https_port).as_str())
                    .unwrap();
            let redirect_listener = redirect_server.listen(format!("0.0.0.0:{}", &http_port));
            let main_listener = main_server.listen(
                tide_rustls::TlsListener::build()
                    .addrs(format!("0.0.0.0:{}", &https_port))
                    .acme(
                        AcmeConfig::new(vec![domain])
                            .contact_push(acme_email)
                            .cache(DirCache::new(acme_dir)),
                    ),
            );

            if let Some(tcp_port) = tcp_port {
                let tcp_listener = tcp::listen(format!("0.0.0.0:{}", tcp_port), engine);
                futures::try_join!(main_listener, redirect_listener, tcp_listener)?;
            } else {
                futures::try_join!(main_listener, redirect_listener)?;
            }

            // TODO
        } else {
            let main_listener = main_server.listen(format!("0.0.0.0:{}", &http_port));
            if let Some(tcp_port) = tcp_port {
                let tcp_listener = tcp::listen(format!("0.0.0.0:{}", tcp_port), engine);
                futures::try_join!(main_listener, tcp_listener)?;
            } else {
                main_listener.await?;
            }
        }
    } else {
        if let Some(tcp_port) = tcp_port {
            tcp::listen(format!("0.0.0.0:{}", tcp_port), engine).await?;
        } else {
            anyhow::bail!("Either --tcp-port or --http-port is mandatory");
        };
    }

    Ok(())
}
<commit_msg>Fix format of contact<commit_after>use crate::common::State;
use crate::http::{http_main_server, http_redirect_server};
use anyhow::Result;
use extendedmind_engine::tcp;
use std::path::PathBuf;
use tide_acme::rustls_acme::caches::DirCache;
use tide_acme::{AcmeConfig, TideRustlsExt};

fn setup_logging(log_to_stderr: bool) {
    let base_config = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug);
    let std_config = if log_to_stderr {
        fern::Dispatch::new().chain(std::io::stderr())
    } else {
        fern::Dispatch::new().chain(std::io::stdout())
    };

    base_config.chain(std_config).apply().unwrap();
}

pub async fn start_server(
    initial_state: State,
    static_root_dir: Option<PathBuf>,
    http_port: Option<u16>,
    https_port: Option<u16>,
    domain: Option<String>,
    acme_email: Option<String>,
    acme_dir: Option<String>,
    tcp_port: Option<u16>,
    skip_compress_mime: Option<Vec<String>>,
    cache_ttl_sec: Option<u64>,
    cache_tti_sec: Option<u64>,
    inline_css_path: Option<Vec<String>>,
    immutable_path: Option<Vec<String>>,
) -> Result<()> {
    let engine = initial_state.engine.clone();

    if let Some(http_port) = http_port {
        let main_server = http_main_server(
            initial_state,
            static_root_dir,
            skip_compress_mime,
            cache_ttl_sec,
            cache_tti_sec,
            inline_css_path,
            immutable_path,
        )
        .unwrap();
        if let Some(https_port) = https_port {
            if domain.is_none() || acme_dir.is_none() || acme_email.is_none() {
                anyhow::bail!(
                    "With --https-port also --domain, --acme-email and --acme-dir are required"
                );
            }
            let domain = domain.unwrap();
            let acme_dir = acme_dir.unwrap();
            let acme_email = acme_email.unwrap();
            let redirect_server =
                http_redirect_server(format!("https://{}:{}", &domain, &https_port).as_str())
                    .unwrap();
            let redirect_listener = redirect_server.listen(format!("0.0.0.0:{}", &http_port));
            let main_listener = main_server.listen(
                tide_rustls::TlsListener::build()
                    .addrs(format!("0.0.0.0:{}", &https_port))
                    .acme(
                        AcmeConfig::new(vec![domain])
                            .contact_push(format!("mailto:{}", acme_email))
                            .cache(DirCache::new(acme_dir)),
                    ),
            );

            if let Some(tcp_port) = tcp_port {
                let tcp_listener = tcp::listen(format!("0.0.0.0:{}", tcp_port), engine);
                futures::try_join!(main_listener, redirect_listener, tcp_listener)?;
            } else {
                futures::try_join!(main_listener, redirect_listener)?;
            }

            // TODO
        } else {
            let main_listener = main_server.listen(format!("0.0.0.0:{}", &http_port));
            if let Some(tcp_port) = tcp_port {
                let tcp_listener = tcp::listen(format!("0.0.0.0:{}", tcp_port), engine);
                futures::try_join!(main_listener, tcp_listener)?;
            } else {
                main_listener.await?;
            }
        }
    } else {
        if let Some(tcp_port) = tcp_port {
            tcp::listen(format!("0.0.0.0:{}", tcp_port), engine).await?;
        } else {
            anyhow::bail!("Either --tcp-port or --http-port is mandatory");
        };
    }

    Ok(())
}
<|endoftext|>


<commit_before>extern mod rsfml;

use rsfml::window::{ContextSettings, VideoMode};
use rsfml::graphics::{RenderWindow, sfClose};

mod cpu;

#[cfg(target_os="macos")]
#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn main() {
    // Create the window of the application
    let setting = ContextSettings::default();
    let mut window = match RenderWindow::new(VideoMode::new_init(320, 160, 32), ~"SFML Example", sfClose, &setting) {
        Some(window) => window,
        None => fail!("Cannot create a new Render Window.")
    };

	let mut system = ::cpu::Cpu::new();

	system.load("/Users/derekguenther/Downloads/c8games/TETRIS");
	//system.print_mem();

    loop {
		system.cycle();
        system.draw(&mut window);
	}

}<commit_msg>Check for window events so we don't lock up the program<commit_after>extern mod rsfml;

use rsfml::window::{ContextSettings, VideoMode, event};
use rsfml::graphics::{RenderWindow, sfClose};

mod cpu;

#[cfg(target_os="macos")]
#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn main() {
    // Create the window of the application
    let setting = ContextSettings::default();
    let mut window = match RenderWindow::new(VideoMode::new_init(320, 160, 32), ~"rustchip", sfClose, &setting) {
        Some(window) => window,
        None => fail!("Cannot create a new Render Window.")
    };
    window.set_framerate_limit(60);
	let mut system = ::cpu::Cpu::new();

	system.load("/Users/derekguenther/Downloads/c8games/TETRIS");
	//system.print_mem();

    while window.is_open() {
        loop {
            match window.poll_event() {
                event::Closed => { window.close()}
                event::NoEvent => { break }
                _ => {}
            }
        }
		system.cycle();
        system.draw(&mut window);
    }

}<|endoftext|>


<commit_before>use std::sync::Arc;

use num_complex::Complex;
use num_traits::Zero;
use strength_reduce::StrengthReducedUsize;

use common::FFTnum;

use math_utils;
use ::{Length, IsInverse, Fft};

/// Implementation of Rader's Algorithm
///
/// This algorithm computes a prime-sized FFT in O(nlogn) time. It does this by converting this size n FFT into a
/// size (n - 1) which is guaranteed to be composite.
///
/// The worst case for this algorithm is when (n - 1) is 2 * prime, resulting in a
/// [Cunningham Chain](https://en.wikipedia.org/wiki/Cunningham_chain)
///
/// ~~~
/// // Computes a forward FFT of size 1201 (prime number), using Rader's Algorithm
/// use rustfft::algorithm::RadersAlgorithm;
/// use rustfft::{Fft, FFTplanner};
/// use rustfft::num_complex::Complex;
/// use rustfft::num_traits::Zero;
///
/// let mut input:  Vec<Complex<f32>> = vec![Zero::zero(); 1201];
/// let mut output: Vec<Complex<f32>> = vec![Zero::zero(); 1201];
///
/// // plan a FFT of size n - 1 = 1200
/// let mut planner = FFTplanner::new(false);
/// let inner_fft = planner.plan_fft(1200);
///
/// let fft = RadersAlgorithm::new(1201, inner_fft);
/// fft.process(&mut input, &mut output);
/// ~~~
///
/// Rader's Algorithm is relatively expensive compared to other FFT algorithms. Benchmarking shows that it is up to
/// an order of magnitude slower than similar composite sizes. In the example size above of 1201, benchmarking shows
/// that it takes 2.5x more time to compute than a FFT of size 1200.

pub struct RadersAlgorithm<T> {
    inner_fft: Arc<Fft<T>>,
    inner_fft_data: Box<[Complex<T>]>,

    primitive_root: usize,
    primitive_root_inverse: usize,

    len: StrengthReducedUsize,
    inplace_scratch_len: usize,
    outofplace_scratch_len: usize,
    inverse: bool,
}

impl<T: FFTnum> RadersAlgorithm<T> {
    /// Creates a FFT instance which will process inputs/outputs of size `len`. `inner_fft.len()` must be `len - 1`
    ///
    /// Note that this constructor is quite expensive to run; This algorithm must run a FFT of size n - 1 within the
    /// constructor. This further underlines the fact that Rader's Algorithm is more expensive to run than other
    /// FFT algorithms
    ///
    /// Note also that if `len` is not prime, this algorithm may silently produce garbage output
    pub fn new(len: usize, inner_fft: Arc<Fft<T>>) -> Self {
        assert_eq!(len - 1, inner_fft.len(), "For raders algorithm, inner_fft.len() must be self.len() - 1. Expected {}, got {}", len - 1, inner_fft.len());

        let inverse = inner_fft.is_inverse();
        let inner_fft_len = len - 1;
        let reduced_len = StrengthReducedUsize::new(len);

        // compute the primitive root and its inverse for this size
        let primitive_root = math_utils::primitive_root(len as u64).unwrap() as usize;
        let primitive_root_inverse = math_utils::multiplicative_inverse(primitive_root as usize, len);

        // precompute the coefficients to use inside the process method
        let unity_scale = T::from_f64(1f64 / inner_fft_len as f64).unwrap();
        let mut inner_fft_input = vec![Complex::zero(); inner_fft_len];
        let mut twiddle_input = 1;
        for input_cell in &mut inner_fft_input {
            let twiddle = T::generate_twiddle_factor(twiddle_input, len, inverse);
            *input_cell = twiddle * unity_scale;

            twiddle_input = (twiddle_input * primitive_root_inverse) % reduced_len;
        }

        let required_inner_scratch = inner_fft.get_inplace_scratch_len();
        let extra_inner_scratch = if required_inner_scratch <= inner_fft_len { 0 } else { required_inner_scratch };

        //precompute a FFT of our reordered twiddle factors
        let mut inner_fft_scratch = vec![Zero::zero(); required_inner_scratch];
        inner_fft.process_inplace_with_scratch(&mut inner_fft_input, &mut inner_fft_scratch);

        Self {
            inner_fft: inner_fft,
            inner_fft_data: inner_fft_input.into_boxed_slice(),

            primitive_root,
            primitive_root_inverse,

            len: reduced_len,
            inplace_scratch_len: inner_fft_len + extra_inner_scratch,
            outofplace_scratch_len: extra_inner_scratch,
            inverse,
        }
    }

    fn perform_fft_out_of_place(&self, input: &mut [Complex<T>], output: &mut [Complex<T>], scratch: &mut [Complex<T>]) {

        // The first output element is just the sum of all the input elements, and we need to store off the first input value
        let (output_first, output) = output.split_first_mut().unwrap();
        let (input_first, input) = input.split_first_mut().unwrap();
        let first_input_val = *input_first;
        *output_first = *input_first;

        // copy the inout into the output, reordering as we go. also compute a sum of all elements
        let mut input_index = 1;
        for output_element in output.iter_mut() {
            input_index = (input_index * self.primitive_root) % self.len;

            let input_element = input[input_index - 1];
            *output_first = *output_first + input_element;
            *output_element = input_element;
        }

        // perform the first of two inner FFTs
        let inner_scratch = if scratch.len() > 0 { &mut scratch[..] } else { &mut input[..] };
        self.inner_fft.process_inplace_with_scratch(output, inner_scratch);

        // multiply the inner result with our cached setup data
        // also conjugate every entry. this sets us up to do an inverse FFT
        // (because an inverse FFT is equivalent to a normal FFT where you conjugate both the inputs and outputs)
        for ((output_cell, input_cell), &multiple) in output.iter().zip(input.iter_mut()).zip(self.inner_fft_data.iter()) {
            *input_cell = (*output_cell * multiple).conj();
        }

        // execute the second FFT
        let inner_scratch = if scratch.len() > 0 { scratch } else { &mut output[..] };
        self.inner_fft.process_inplace_with_scratch(input, inner_scratch);

        // copy the final values into the output, reordering as we go
        let mut output_index = 1;
        for input_element in input {
            output_index = (output_index * self.primitive_root_inverse) % self.len;
            output[output_index - 1] = input_element.conj() + first_input_val;
        }
    }
    fn perform_fft_inplace(&self, buffer: &mut [Complex<T>], scratch: &mut [Complex<T>]) {

        // The first output element is just the sum of all the input elements, and we need to store off the first input value
        let (buffer_first, buffer) = buffer.split_first_mut().unwrap();
        let buffer_first_val = *buffer_first;

        // copy the buffer into the scratch, reordering as we go. also compute a sum of all elements
        let mut input_index = 1;
        for scratch_element in scratch.iter_mut() {
            input_index = (input_index * self.primitive_root) % self.len;

            let buffer_element = buffer[input_index - 1];
            *buffer_first = *buffer_first + buffer_element;
            *scratch_element = buffer_element;
        }

        // perform the first of two inner FFTs
        self.inner_fft.process_inplace_with_scratch(scratch, buffer);

        // multiply the inner result with our cached setup data
        // also conjugate every entry. this sets us up to do an inverse FFT
        // (because an inverse FFT is equivalent to a normal FFT where you conjugate both the inputs and outputs)
        for (scratch_cell, &twiddle) in scratch.iter_mut().zip(self.inner_fft_data.iter()) {
            *scratch_cell = (*scratch_cell * twiddle).conj();
        }

        // execute the second FFT
        self.inner_fft.process_inplace_with_scratch(scratch, buffer);

        // copy the final values into the output, reordering as we go
        let mut output_index = 1;
        for scratch_element in scratch {
            output_index = (output_index * self.primitive_root_inverse) % self.len;
            buffer[output_index - 1] = scratch_element.conj() + buffer_first_val;
        }
    }
}
boilerplate_fft!(RadersAlgorithm,
    |this: &RadersAlgorithm<_>| this.len.get(),
    |this: &RadersAlgorithm<_>| this.inplace_scratch_len,
    |this: &RadersAlgorithm<_>| this.outofplace_scratch_len
);

#[cfg(test)]
mod unit_tests {
    use super::*;
    use std::sync::Arc;
    use test_utils::check_fft_algorithm;
    use algorithm::DFT;

    #[test]
    fn test_raders() {
        for &len in &[3,5,7,11,13] {
            test_raders_with_length(len, false);
            test_raders_with_length(len, true);
        }
    }

    fn test_raders_with_length(len: usize, inverse: bool) {
        let inner_fft = Arc::new(DFT::new(len - 1, inverse));
        let fft = RadersAlgorithm::new(len, inner_fft);

        check_fft_algorithm(&fft, len, inverse);
    }
}
<commit_msg>Updated rader's algorithm to correctly forward its scratch<commit_after>use std::sync::Arc;

use num_complex::Complex;
use num_traits::Zero;
use strength_reduce::StrengthReducedUsize;

use common::FFTnum;

use math_utils;
use ::{Length, IsInverse, Fft};

/// Implementation of Rader's Algorithm
///
/// This algorithm computes a prime-sized FFT in O(nlogn) time. It does this by converting this size n FFT into a
/// size (n - 1) which is guaranteed to be composite.
///
/// The worst case for this algorithm is when (n - 1) is 2 * prime, resulting in a
/// [Cunningham Chain](https://en.wikipedia.org/wiki/Cunningham_chain)
///
/// ~~~
/// // Computes a forward FFT of size 1201 (prime number), using Rader's Algorithm
/// use rustfft::algorithm::RadersAlgorithm;
/// use rustfft::{Fft, FFTplanner};
/// use rustfft::num_complex::Complex;
/// use rustfft::num_traits::Zero;
///
/// let mut input:  Vec<Complex<f32>> = vec![Zero::zero(); 1201];
/// let mut output: Vec<Complex<f32>> = vec![Zero::zero(); 1201];
///
/// // plan a FFT of size n - 1 = 1200
/// let mut planner = FFTplanner::new(false);
/// let inner_fft = planner.plan_fft(1200);
///
/// let fft = RadersAlgorithm::new(1201, inner_fft);
/// fft.process(&mut input, &mut output);
/// ~~~
///
/// Rader's Algorithm is relatively expensive compared to other FFT algorithms. Benchmarking shows that it is up to
/// an order of magnitude slower than similar composite sizes. In the example size above of 1201, benchmarking shows
/// that it takes 2.5x more time to compute than a FFT of size 1200.

pub struct RadersAlgorithm<T> {
    inner_fft: Arc<Fft<T>>,
    inner_fft_data: Box<[Complex<T>]>,

    primitive_root: usize,
    primitive_root_inverse: usize,

    len: StrengthReducedUsize,
    inplace_scratch_len: usize,
    outofplace_scratch_len: usize,
    inverse: bool,
}

impl<T: FFTnum> RadersAlgorithm<T> {
    /// Creates a FFT instance which will process inputs/outputs of size `len`. `inner_fft.len()` must be `len - 1`
    ///
    /// Note that this constructor is quite expensive to run; This algorithm must run a FFT of size n - 1 within the
    /// constructor. This further underlines the fact that Rader's Algorithm is more expensive to run than other
    /// FFT algorithms
    ///
    /// Note also that if `len` is not prime, this algorithm may silently produce garbage output
    pub fn new(len: usize, inner_fft: Arc<Fft<T>>) -> Self {
        assert_eq!(len - 1, inner_fft.len(), "For raders algorithm, inner_fft.len() must be self.len() - 1. Expected {}, got {}", len - 1, inner_fft.len());

        let inverse = inner_fft.is_inverse();
        let inner_fft_len = len - 1;
        let reduced_len = StrengthReducedUsize::new(len);

        // compute the primitive root and its inverse for this size
        let primitive_root = math_utils::primitive_root(len as u64).unwrap() as usize;
        let primitive_root_inverse = math_utils::multiplicative_inverse(primitive_root as usize, len);

        // precompute the coefficients to use inside the process method
        let unity_scale = T::from_f64(1f64 / inner_fft_len as f64).unwrap();
        let mut inner_fft_input = vec![Complex::zero(); inner_fft_len];
        let mut twiddle_input = 1;
        for input_cell in &mut inner_fft_input {
            let twiddle = T::generate_twiddle_factor(twiddle_input, len, inverse);
            *input_cell = twiddle * unity_scale;

            twiddle_input = (twiddle_input * primitive_root_inverse) % reduced_len;
        }

        let required_inner_scratch = inner_fft.get_inplace_scratch_len();
        let extra_inner_scratch = if required_inner_scratch <= inner_fft_len { 0 } else { required_inner_scratch };

        //precompute a FFT of our reordered twiddle factors
        let mut inner_fft_scratch = vec![Zero::zero(); required_inner_scratch];
        inner_fft.process_inplace_with_scratch(&mut inner_fft_input, &mut inner_fft_scratch);

        Self {
            inner_fft: inner_fft,
            inner_fft_data: inner_fft_input.into_boxed_slice(),

            primitive_root,
            primitive_root_inverse,

            len: reduced_len,
            inplace_scratch_len: inner_fft_len + extra_inner_scratch,
            outofplace_scratch_len: extra_inner_scratch,
            inverse,
        }
    }

    fn perform_fft_out_of_place(&self, input: &mut [Complex<T>], output: &mut [Complex<T>], scratch: &mut [Complex<T>]) {

        // The first output element is just the sum of all the input elements, and we need to store off the first input value
        let (output_first, output) = output.split_first_mut().unwrap();
        let (input_first, input) = input.split_first_mut().unwrap();
        let first_input_val = *input_first;
        *output_first = *input_first;

        // copy the inout into the output, reordering as we go. also compute a sum of all elements
        let mut input_index = 1;
        for output_element in output.iter_mut() {
            input_index = (input_index * self.primitive_root) % self.len;

            let input_element = input[input_index - 1];
            *output_first = *output_first + input_element;
            *output_element = input_element;
        }

        // perform the first of two inner FFTs
        let inner_scratch = if scratch.len() > 0 { &mut scratch[..] } else { &mut input[..] };
        self.inner_fft.process_inplace_with_scratch(output, inner_scratch);

        // multiply the inner result with our cached setup data
        // also conjugate every entry. this sets us up to do an inverse FFT
        // (because an inverse FFT is equivalent to a normal FFT where you conjugate both the inputs and outputs)
        for ((output_cell, input_cell), &multiple) in output.iter().zip(input.iter_mut()).zip(self.inner_fft_data.iter()) {
            *input_cell = (*output_cell * multiple).conj();
        }

        // execute the second FFT
        let inner_scratch = if scratch.len() > 0 { scratch } else { &mut output[..] };
        self.inner_fft.process_inplace_with_scratch(input, inner_scratch);

        // copy the final values into the output, reordering as we go
        let mut output_index = 1;
        for input_element in input {
            output_index = (output_index * self.primitive_root_inverse) % self.len;
            output[output_index - 1] = input_element.conj() + first_input_val;
        }
    }
    fn perform_fft_inplace(&self, buffer: &mut [Complex<T>], scratch: &mut [Complex<T>]) {

        // The first output element is just the sum of all the input elements, and we need to store off the first input value
        let (buffer_first, buffer) = buffer.split_first_mut().unwrap();
        let buffer_first_val = *buffer_first;

        let (scratch, extra_scratch) = scratch.split_at_mut(self.len() - 1);

        // copy the buffer into the scratch, reordering as we go. also compute a sum of all elements
        let mut input_index = 1;
        for scratch_element in scratch.iter_mut() {
            input_index = (input_index * self.primitive_root) % self.len;

            let buffer_element = buffer[input_index - 1];
            *buffer_first = *buffer_first + buffer_element;
            *scratch_element = buffer_element;
        }

        // perform the first of two inner FFTs
        let inner_scratch = if extra_scratch.len() > 0 { extra_scratch } else { &mut buffer[..] };
        self.inner_fft.process_inplace_with_scratch(scratch, inner_scratch);

        // multiply the inner result with our cached setup data
        // also conjugate every entry. this sets us up to do an inverse FFT
        // (because an inverse FFT is equivalent to a normal FFT where you conjugate both the inputs and outputs)
        for (scratch_cell, &twiddle) in scratch.iter_mut().zip(self.inner_fft_data.iter()) {
            *scratch_cell = (*scratch_cell * twiddle).conj();
        }

        // execute the second FFT
        self.inner_fft.process_inplace_with_scratch(scratch, inner_scratch);

        // copy the final values into the output, reordering as we go
        let mut output_index = 1;
        for scratch_element in scratch {
            output_index = (output_index * self.primitive_root_inverse) % self.len;
            buffer[output_index - 1] = scratch_element.conj() + buffer_first_val;
        }
    }
}
boilerplate_fft!(RadersAlgorithm,
    |this: &RadersAlgorithm<_>| this.len.get(),
    |this: &RadersAlgorithm<_>| this.inplace_scratch_len,
    |this: &RadersAlgorithm<_>| this.outofplace_scratch_len
);

#[cfg(test)]
mod unit_tests {
    use super::*;
    use std::sync::Arc;
    use test_utils::check_fft_algorithm;
    use algorithm::DFT;

    #[test]
    fn test_raders() {
        for &len in &[3,5,7,11,13] {
            test_raders_with_length(len, false);
            test_raders_with_length(len, true);
        }
    }

    fn test_raders_with_length(len: usize, inverse: bool) {
        let inner_fft = Arc::new(DFT::new(len - 1, inverse));
        let fft = RadersAlgorithm::new(len, inner_fft);

        check_fft_algorithm(&fft, len, inverse);
    }
}
<|endoftext|>


<commit_before>use tokio::sync::watch;
use tokio_stream::wrappers::WatchStream;
use tokio_stream::StreamExt;

#[tokio::test]
async fn message_not_twice() {
    let (tx, rx) = watch::channel("hello");

    let mut counter = 0;
    let mut stream = WatchStream::new(rx).map(move |payload| {
        println!("{}", payload);
        if payload == "goodbye" {
            counter += 1;
        }
        if counter >= 2 {
            panic!("too many goodbyes");
        }
    });

    let task = tokio::spawn(async move { while stream.next().await.is_some() {} });

    // Send goodbye just once
    tx.send("goodbye").unwrap();

    drop(tx);
    task.await.unwrap();
}
<commit_msg>tests: add `#[cfg(sync)]` to watch test (#4183)<commit_after>#![cfg(feature = "sync")]

use tokio::sync::watch;
use tokio_stream::wrappers::WatchStream;
use tokio_stream::StreamExt;

#[tokio::test]
async fn message_not_twice() {
    let (tx, rx) = watch::channel("hello");

    let mut counter = 0;
    let mut stream = WatchStream::new(rx).map(move |payload| {
        println!("{}", payload);
        if payload == "goodbye" {
            counter += 1;
        }
        if counter >= 2 {
            panic!("too many goodbyes");
        }
    });

    let task = tokio::spawn(async move { while stream.next().await.is_some() {} });

    // Send goodbye just once
    tx.send("goodbye").unwrap();

    drop(tx);
    task.await.unwrap();
}
<|endoftext|>


<commit_before>use common::*;
use polynomial::Polynomial;
use vector_monomial::VectorMonomial;

// An FENum identifies a finite element in the mesh.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone,IterBytes)]
pub struct FENum(uint);

// An NBSideNum identifies a mesh side among all sides in the mesh.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone,IterBytes)]
pub struct NBSideNum(uint);

// A SideFace identifies a side within the context of a single oriented shape
// or finite element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone,IterBytes)]
pub struct SideFace(uint);

/// A Face locally identifies either the interior or a side in the context of a single
/// oriented shape or finite element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub enum Face {
  Interior,
  Side(SideFace)
}

/// An identifier for the shape of a finite element together with the orientation
/// of the shape (rotation will yield a different oriented shape). Many calculations
/// on a finite element can be expressed in element-local coordinates and will only
/// depend on the oriented shape of the element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct OShape(uint);

/// The representations of a non-boundary side as a pair of finite element faces.
/// The elements are arranged so that fe1 < fe2.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct NBSideInclusions {
  nb_side_num: NBSideNum,

  fe1: FENum,
  side_face_in_fe1: SideFace,

  fe2: FENum,
  side_face_in_fe2: SideFace
}

pub trait Mesh<Mon> {

  fn num_fes(&self) -> uint;

  fn num_nb_sides(&self) -> uint;

  fn num_oriented_element_shapes(&self) -> uint;

  fn oriented_shape_for_fe(&self, fe: FENum) -> OShape;

  fn num_side_faces_for_fe(&self, fe: FENum) -> uint;

  fn num_side_faces_for_shape(&self, oshape: OShape) -> uint;

  // The dependent dim is, for a given side, the dimension j which is affine-
  // dependent on the other dimensions on the side. That is, the function
  // returns a j for which c_0,...,c_d exist such that
  //   x_j = c_0 + sum_{i=1..d} c_i x_i for all (x_1,...,x_d) in the side.
  // There may be more than one such coordinate number, in which case any
  // one of these may be returned depending on the mesh implementation.
  fn dependent_dim_for_oshape_side(&self, oshape: OShape, side_face: SideFace) -> Dim;

  fn fe_inclusions_of_nb_side(&self, side_num: NBSideNum) -> NBSideInclusions;

  // Return non-boundary side number of the indicated fe relative side.
  fn nb_side_num_for_fe_side(&self, fe: FENum, side_face: SideFace) -> NBSideNum;

  fn is_boundary_side(&self, fe: FENum, side_face: SideFace) -> bool;

  fn num_boundary_sides(&self) -> uint;

  fn boundary_fes_by_oshape_side(&self) -> ~[~[~[FENum]]]; // oshape, side face -> fes

  fn shape_diameter_inv(&self, oshape: OShape) -> R;

  fn max_fe_diameter(&self) -> R;

  fn num_nb_sides_for_fe(&self, fe: FENum) -> uint;

  fn max_num_shape_sides(&self) -> uint;

  // integration functions

  fn intg_global_fn_on_fe_int(&self,
       g: |&[R]| -> R,
       fe: FENum) -> R;

  fn intg_global_fn_x_facerel_mon_on_fe_int(&self,
       g: |&[R]| -> R,
       mon: Mon,
       fe: FENum) -> R;

  fn intg_global_fn_x_facerel_mon_on_fe_side(&self,
       g: |&[R]| -> R,
       mon: Mon,
       fe: FENum,
       side_face: SideFace) -> R;

  fn intg_mixed_global_and_facerel_fn_on_fe_int(&self,
       f: |&[R], &[R]|->R,
       fe: FENum) -> R;

  fn intg_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       p: &P,
       oshape: OShape) -> R;

  fn intg_facerel_poly_x_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       p1: &P,
       p2: &P,
       oshape: OShape) -> R;

  fn intg_facerel_poly_x_facerel_poly_on_oshape_side<P:Polynomial<Mon>>(&self,
       p1: &P,
       p2: &P,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_facerel_mon_on_oshape_int(&self,
       mon: Mon,
       oshape: OShape) -> R;

  fn intg_facerel_mon_on_oshape_side(&self,
       mon: Mon,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_facerel_mon_x_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       mon: Mon,
       p: &P,
       oshape: OShape) -> R;

  fn intg_facerel_mon_x_facerel_poly_on_oshape_side<P:Polynomial<Mon>>(&self,
       mon: Mon,
       p: &P,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_intrel_mon_x_siderel_mon_on_oshape_side(&self,
       int_mon: Mon,
       side_mon: Mon, oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_siderel_mon_x_intrel_vmon_dot_normal_on_oshape_side(&self,
       mon: Mon,
       q: &VectorMonomial<Mon>,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_siderel_poly_x_intrel_vmon_dot_normal_on_oshape_side<P:Polynomial<Mon>>(&self,
       p: &P,
       q: &VectorMonomial<Mon>,
       oshape: OShape,
       side_face: SideFace) -> R;

}

<commit_msg>Remove unused Face type.<commit_after>use common::*;
use polynomial::Polynomial;
use vector_monomial::VectorMonomial;

// An FENum identifies a finite element in the mesh.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone,IterBytes)]
pub struct FENum(uint);

// An NBSideNum identifies a mesh side among all sides in the mesh.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone,IterBytes)]
pub struct NBSideNum(uint);

// A SideFace identifies a side within the context of a single oriented shape
// or finite element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone,IterBytes)]
pub struct SideFace(uint);

/// An identifier for the shape of a finite element together with the orientation
/// of the shape (rotation will yield a different oriented shape). Many calculations
/// on a finite element can be expressed in element-local coordinates and will only
/// depend on the oriented shape of the element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct OShape(uint);

/// The representations of a non-boundary side as a pair of finite element faces.
/// The elements are arranged so that fe1 < fe2.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct NBSideInclusions {
  nb_side_num: NBSideNum,

  fe1: FENum,
  side_face_in_fe1: SideFace,

  fe2: FENum,
  side_face_in_fe2: SideFace
}

pub trait Mesh<Mon> {

  fn num_fes(&self) -> uint;

  fn num_nb_sides(&self) -> uint;

  fn num_oriented_element_shapes(&self) -> uint;

  fn oriented_shape_for_fe(&self, fe: FENum) -> OShape;

  fn num_side_faces_for_fe(&self, fe: FENum) -> uint;

  fn num_side_faces_for_shape(&self, oshape: OShape) -> uint;

  // The dependent dim is, for a given side, the dimension j which is affine-
  // dependent on the other dimensions on the side. That is, the function
  // returns a j for which c_0,...,c_d exist such that
  //   x_j = c_0 + sum_{i=1..d} c_i x_i for all (x_1,...,x_d) in the side.
  // There may be more than one such coordinate number, in which case any
  // one of these may be returned depending on the mesh implementation.
  fn dependent_dim_for_oshape_side(&self, oshape: OShape, side_face: SideFace) -> Dim;

  fn fe_inclusions_of_nb_side(&self, side_num: NBSideNum) -> NBSideInclusions;

  // Return non-boundary side number of the indicated fe relative side.
  fn nb_side_num_for_fe_side(&self, fe: FENum, side_face: SideFace) -> NBSideNum;

  fn is_boundary_side(&self, fe: FENum, side_face: SideFace) -> bool;

  fn num_boundary_sides(&self) -> uint;

  fn boundary_fes_by_oshape_side(&self) -> ~[~[~[FENum]]]; // oshape, side face -> fes

  fn shape_diameter_inv(&self, oshape: OShape) -> R;

  fn max_fe_diameter(&self) -> R;

  fn num_nb_sides_for_fe(&self, fe: FENum) -> uint;

  fn max_num_shape_sides(&self) -> uint;

  // integration functions

  fn intg_global_fn_on_fe_int(&self,
       g: |&[R]| -> R,
       fe: FENum) -> R;

  fn intg_global_fn_x_facerel_mon_on_fe_int(&self,
       g: |&[R]| -> R,
       mon: Mon,
       fe: FENum) -> R;

  fn intg_global_fn_x_facerel_mon_on_fe_side(&self,
       g: |&[R]| -> R,
       mon: Mon,
       fe: FENum,
       side_face: SideFace) -> R;

  fn intg_mixed_global_and_facerel_fn_on_fe_int(&self,
       f: |&[R], &[R]| -> R,
       fe: FENum) -> R;

  fn intg_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       p: &P,
       oshape: OShape) -> R;

  fn intg_facerel_poly_x_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       p1: &P,
       p2: &P,
       oshape: OShape) -> R;

  fn intg_facerel_poly_x_facerel_poly_on_oshape_side<P:Polynomial<Mon>>(&self,
       p1: &P,
       p2: &P,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_facerel_mon_on_oshape_int(&self,
       mon: Mon,
       oshape: OShape) -> R;

  fn intg_facerel_mon_on_oshape_side(&self,
       mon: Mon,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_facerel_mon_x_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       mon: Mon,
       p: &P,
       oshape: OShape) -> R;

  fn intg_facerel_mon_x_facerel_poly_on_oshape_side<P:Polynomial<Mon>>(&self,
       mon: Mon,
       p: &P,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_intrel_mon_x_siderel_mon_on_oshape_side(&self,
       int_mon: Mon,
       side_mon: Mon, oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_siderel_mon_x_intrel_vmon_dot_normal_on_oshape_side(&self,
       mon: Mon,
       q: &VectorMonomial<Mon>,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_siderel_poly_x_intrel_vmon_dot_normal_on_oshape_side<P:Polynomial<Mon>>(&self,
       p: &P,
       q: &VectorMonomial<Mon>,
       oshape: OShape,
       side_face: SideFace) -> R;

}

<|endoftext|>


<commit_before>use common::*;
use polynomial::Polynomial;
use vector_monomial::VectorMonomial;

// An FENum identifies a finite element in the mesh.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct FENum(uint);

// An NBSideNum identifies a mesh side among all sides in the mesh.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct NBSideNum(uint);

// A SideFace identifies a side within the context of a single oriented shape
// or finite element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct SideFace(uint);

// A Face locally identifies either the interior or a side in the
// context of a single oriented shape or finite element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub enum Face {
  Interior,
  Side(SideFace)
}

// An identifier for the shape of a finite element together with the orientation
// of the shape (rotation will yield a different oriented shape). Many calculations
// on a finite element can be expressed in element-local coordinates and will only
// depend on the oriented shape of the element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct OShape(uint);

#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct NBSideInclusions {
  nb_side_num: NBSideNum,

  fe1: FENum,
  sideface_in_fe1: SideFace,

  fe2: FENum,
  sideface_in_fe2: SideFace
}

pub trait Mesh<Mon> {

  fn num_fes(&self) -> uint;

  fn num_nb_sides(&self) -> uint;

  fn num_oriented_element_shapes(&self) -> uint;

  fn oriented_shape_for_fe(&self, fe: FENum) -> OShape;

  fn num_side_faces_for_fe(&self, fe: FENum) -> uint;

  fn num_side_faces_for_shape(&self, oshape: OShape) -> uint;

  // The dependent dim is, for a given side, the dimension j which is affine-
  // dependent on the other dimensions on the side. That is, the function
  // returns a j for which c_0,...,c_d exist such that
  //   x_j = c_0 + sum_{i=1..d} c_i x_i for all (x_1,...,x_d) in the side.
  // There may be more than one such coordinate number, in which case any
  // one of these may be returned depending on the mesh implementation.
  fn dependent_dim_for_oshape_side(&self, oshape: OShape, side_face: SideFace) -> Dim;

  fn fe_inclusions_of_nb_side(&self, side_num: NBSideNum) -> NBSideInclusions;

  // Return non-boundary side number of the indicated fe relative side.
  fn nb_side_num_for_fe_side(&self, fe: FENum, side_face: SideFace) -> NBSideNum;

  fn is_boundary_side(&self, fe: FENum, side_face: SideFace) -> bool;

  fn num_boundary_sides(&self) -> uint;

  fn shape_diameter_inv(&self, oshape: OShape) -> R;

  fn max_fe_diameter(&self) -> R;

  fn num_non_boundary_sides_for_fe(&self, fe: FENum) -> uint;

  fn max_num_shape_sides(&self) -> uint;

  // integration functions

  fn intg_global_fn_on_fe_int(&self,
       g: &fn(&[R]) -> R,
       fe: FENum) -> R;

  fn intg_global_fn_x_facerel_mon_on_fe_int(&self,
       g: &fn(&[R]) -> R,
       mon: Mon,
       fe: FENum) -> R;

  fn intg_global_fn_x_facerel_mon_on_fe_side(&self,
       g: &fn(&[R]) -> R,
       mon: Mon,
       fe: FENum,
       side_face: SideFace) -> R;

  fn intg_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       p: &P,
       oshape: OShape) -> R;

  fn intg_facerel_poly_x_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       p1: &P,
       p2: &P,
       oshape: OShape) -> R;

  fn intg_facerel_poly_x_facerel_poly_on_oshape_side<P:Polynomial<Mon>>(&self,
       p1: &P,
       p2: &P,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_facerel_mon_on_oshape_int(&self,
       mon: Mon,
       oshape: OShape) -> R;

  fn intg_facerel_mon_on_oshape_side(&self,
       mon: Mon,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_facerel_mon_x_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       mon: Mon,
       p: &P,
       oshape: OShape) -> R;

  fn intg_facerel_mon_x_facerel_poly_on_oshape_side<P:Polynomial<Mon>>(&self,
       mon: Mon,
       p: &P,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_intrel_mon_x_siderel_mon_on_oshape_side(&self,
       int_mon: Mon,
       side_mon: Mon, oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_siderel_mon_x_intrel_vmon_dot_normal_on_oshape_side(&self,
       mon: Mon,
       q: &VectorMonomial<Mon>,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_siderel_poly_x_intrel_vmon_dot_normal_on_oshape_side<P:Polynomial<Mon>>(&self,
       p: &P,
       q: &VectorMonomial<Mon>,
       oshape: OShape,
       side_face: SideFace) -> R;

}

<commit_msg>Replace 'non_boundary' with 'nb' in fn name for consistency.<commit_after>use common::*;
use polynomial::Polynomial;
use vector_monomial::VectorMonomial;

// An FENum identifies a finite element in the mesh.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct FENum(uint);

// An NBSideNum identifies a mesh side among all sides in the mesh.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct NBSideNum(uint);

// A SideFace identifies a side within the context of a single oriented shape
// or finite element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct SideFace(uint);

// A Face locally identifies either the interior or a side in the
// context of a single oriented shape or finite element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub enum Face {
  Interior,
  Side(SideFace)
}

// An identifier for the shape of a finite element together with the orientation
// of the shape (rotation will yield a different oriented shape). Many calculations
// on a finite element can be expressed in element-local coordinates and will only
// depend on the oriented shape of the element.
#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct OShape(uint);

#[deriving(Eq,TotalEq,Ord,TotalOrd,Clone)]
pub struct NBSideInclusions {
  nb_side_num: NBSideNum,

  fe1: FENum,
  sideface_in_fe1: SideFace,

  fe2: FENum,
  sideface_in_fe2: SideFace
}

pub trait Mesh<Mon> {

  fn num_fes(&self) -> uint;

  fn num_nb_sides(&self) -> uint;

  fn num_oriented_element_shapes(&self) -> uint;

  fn oriented_shape_for_fe(&self, fe: FENum) -> OShape;

  fn num_side_faces_for_fe(&self, fe: FENum) -> uint;

  fn num_side_faces_for_shape(&self, oshape: OShape) -> uint;

  // The dependent dim is, for a given side, the dimension j which is affine-
  // dependent on the other dimensions on the side. That is, the function
  // returns a j for which c_0,...,c_d exist such that
  //   x_j = c_0 + sum_{i=1..d} c_i x_i for all (x_1,...,x_d) in the side.
  // There may be more than one such coordinate number, in which case any
  // one of these may be returned depending on the mesh implementation.
  fn dependent_dim_for_oshape_side(&self, oshape: OShape, side_face: SideFace) -> Dim;

  fn fe_inclusions_of_nb_side(&self, side_num: NBSideNum) -> NBSideInclusions;

  // Return non-boundary side number of the indicated fe relative side.
  fn nb_side_num_for_fe_side(&self, fe: FENum, side_face: SideFace) -> NBSideNum;

  fn is_boundary_side(&self, fe: FENum, side_face: SideFace) -> bool;

  fn num_boundary_sides(&self) -> uint;

  fn shape_diameter_inv(&self, oshape: OShape) -> R;

  fn max_fe_diameter(&self) -> R;

  fn num_nb_sides_for_fe(&self, fe: FENum) -> uint;

  fn max_num_shape_sides(&self) -> uint;

  // integration functions

  fn intg_global_fn_on_fe_int(&self,
       g: &fn(&[R]) -> R,
       fe: FENum) -> R;

  fn intg_global_fn_x_facerel_mon_on_fe_int(&self,
       g: &fn(&[R]) -> R,
       mon: Mon,
       fe: FENum) -> R;

  fn intg_global_fn_x_facerel_mon_on_fe_side(&self,
       g: &fn(&[R]) -> R,
       mon: Mon,
       fe: FENum,
       side_face: SideFace) -> R;

  fn intg_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       p: &P,
       oshape: OShape) -> R;

  fn intg_facerel_poly_x_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       p1: &P,
       p2: &P,
       oshape: OShape) -> R;

  fn intg_facerel_poly_x_facerel_poly_on_oshape_side<P:Polynomial<Mon>>(&self,
       p1: &P,
       p2: &P,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_facerel_mon_on_oshape_int(&self,
       mon: Mon,
       oshape: OShape) -> R;

  fn intg_facerel_mon_on_oshape_side(&self,
       mon: Mon,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_facerel_mon_x_facerel_poly_on_oshape_int<P:Polynomial<Mon>>(&self,
       mon: Mon,
       p: &P,
       oshape: OShape) -> R;

  fn intg_facerel_mon_x_facerel_poly_on_oshape_side<P:Polynomial<Mon>>(&self,
       mon: Mon,
       p: &P,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_intrel_mon_x_siderel_mon_on_oshape_side(&self,
       int_mon: Mon,
       side_mon: Mon, oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_siderel_mon_x_intrel_vmon_dot_normal_on_oshape_side(&self,
       mon: Mon,
       q: &VectorMonomial<Mon>,
       oshape: OShape,
       side_face: SideFace) -> R;

  fn intg_siderel_poly_x_intrel_vmon_dot_normal_on_oshape_side<P:Polynomial<Mon>>(&self,
       p: &P,
       q: &VectorMonomial<Mon>,
       oshape: OShape,
       side_face: SideFace) -> R;

}

<|endoftext|>


<commit_before>use cpu::common_defs::OpcodeExecInfo;
use cpu::CpuState;
use cpu::DecodeRegister;
use memory::Memory;
use std::collections::HashMap;

pub struct CpuExecutor {
    op_table: HashMap<u8,OpcodeExecInfo>,
}

impl CpuExecutor {
    pub fn new(opcodes: Vec<OpcodeExecInfo> ) -> CpuExecutor {
        // Construct the HashMap and copy it over to CpuExecutor's constructor.
        let mut op_table_temp: HashMap<u8, OpcodeExecInfo> = HashMap::new();
        for oc in opcodes {
            if op_table_temp.contains_key(&oc.opcode) {
                println!("Encountered duplicate opcode: {:#x}", oc.opcode);
                println!("Replacing previous opcode, which was {{ opcode: {:#x}, len: {}, cycles: {}, page_cycles: {} }}", oc.opcode, oc.len, oc.cycles, oc.page_cycles);
            }
            op_table_temp.insert(oc.opcode, oc);
        }

        CpuExecutor {
            op_table: op_table_temp,
        }
    }

    pub fn reset(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        cpu_state.pc = mem.read16(0xFFFC).unwrap();
        cpu_state.sp = 0xFD;
        cpu_state.pack_flags(0x24);
    }

    pub fn fetch_and_decode(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        cpu_state.instruction_register = mem.read8(cpu_state.pc).unwrap();
        cpu_state.pc=cpu_state.pc+1;
    }
    pub fn execute(self: &CpuExecutor, mut cpu_state: &CpuState,mut mem:&Memory) {
    }
    pub fn step(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        self.fetch_and_decode(cpu_state,mem);
        self.execute(cpu_state,mem);
    }
}
<commit_msg>stubbed out decode function<commit_after>use cpu::common_defs::OpcodeExecInfo;
use cpu::CpuState;
use cpu::DecodeRegister;
use cpu::common_defs::address_mode::AddressMode;
use memory::Memory;
use std::collections::HashMap;

pub struct CpuExecutor {
    op_table: HashMap<u8,OpcodeExecInfo>,
}

impl CpuExecutor {
    pub fn new(opcodes: Vec<OpcodeExecInfo> ) -> CpuExecutor {
        // Construct the HashMap and copy it over to CpuExecutor's constructor.
        let mut op_table_temp: HashMap<u8, OpcodeExecInfo> = HashMap::new();
        for oc in opcodes {
            if op_table_temp.contains_key(&oc.opcode) {
                println!("Encountered duplicate opcode: {:#x}", oc.opcode);
                println!("Replacing previous opcode, which was {{ opcode: {:#x}, len: {}, cycles: {}, page_cycles: {} }}", oc.opcode, oc.len, oc.cycles, oc.page_cycles);
            }
            op_table_temp.insert(oc.opcode, oc);
        }

        CpuExecutor {
            op_table: op_table_temp,
        }
    }

    pub fn reset(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        cpu_state.pc = mem.read16(0xFFFC).unwrap();
        cpu_state.sp = 0xFD;
        cpu_state.pack_flags(0x24);
    }

    pub fn fetch_and_decode(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        cpu_state.instruction_register = mem.read8(cpu_state.pc).unwrap();
        cpu_state.pc=cpu_state.pc+1;
    }
    pub fn execute(self: &CpuExecutor, mut cpu_state: &CpuState,mut mem:&Memory) {
    }
    pub fn step(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        self.fetch_and_decode(cpu_state,mem);
        self.execute(cpu_state,mem);
    }

    fn decode(self: &CpuExecutor, cpu_state: &CpuState, mem: &Memory) -> DecodeRegister {
        let dr = DecodeRegister {
            info : self.op_table[&cpu_state.instruction_register].clone(),
            ..Default::default()
        };
        match dr.info.address_mode {
            AddressMode::Absolute        => { },
            AddressMode::AbsoluteX       => { },
            AddressMode::AbsoluteY       => { },
            AddressMode::Accumulator     => { },
            AddressMode::Immediate       => { },
            AddressMode::Implied         => { },
            AddressMode::Indirect        => { },
            AddressMode::IndexedIndirect => { },
            AddressMode::IndirectIndexed => { },
            AddressMode::Relative        => { },
            AddressMode::ZeroPage        => { },
            AddressMode::ZeroPageX       => { },
            AddressMode::ZeroPageY       => { },
            _ => panic!("unrecognized addressing mode while decoding instruction_register!")
        }

        return dr;
    }
}

<|endoftext|>


<commit_before><commit_msg>CairoRenderer: Make dimensions() and render_cairo_sub() test functions only<commit_after><|endoftext|>


<commit_before>use std::collections::hash_map::Entry::*;
use std::sync::Arc;

use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
use rustc::session::config;
use rustc::ty::query::Providers;
use rustc::ty::subst::SubstsRef;
use rustc::ty::Instance;
use rustc::ty::{SymbolName, TyCtxt};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::Node;
use rustc_index::vec::IndexVec;
use syntax::expand::allocator::ALLOCATOR_METHODS;

pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportLevel)>>>;

pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
    crates_export_threshold(&tcx.sess.crate_types.borrow())
}

fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel {
    match crate_type {
        config::CrateType::Executable
        | config::CrateType::Staticlib
        | config::CrateType::ProcMacro
        | config::CrateType::Cdylib => SymbolExportLevel::C,
        config::CrateType::Rlib | config::CrateType::Dylib => SymbolExportLevel::Rust,
    }
}

pub fn crates_export_threshold(crate_types: &[config::CrateType]) -> SymbolExportLevel {
    if crate_types
        .iter()
        .any(|&crate_type| crate_export_threshold(crate_type) == SymbolExportLevel::Rust)
    {
        SymbolExportLevel::Rust
    } else {
        SymbolExportLevel::C
    }
}

fn reachable_non_generics_provider(
    tcx: TyCtxt<'_>,
    cnum: CrateNum,
) -> &DefIdMap<SymbolExportLevel> {
    assert_eq!(cnum, LOCAL_CRATE);

    if !tcx.sess.opts.output_types.should_codegen() {
        return tcx.arena.alloc(Default::default());
    }

    // Check to see if this crate is a "special runtime crate". These
    // crates, implementation details of the standard library, typically
    // have a bunch of `pub extern` and `#[no_mangle]` functions as the
    // ABI between them. We don't want their symbols to have a `C`
    // export level, however, as they're just implementation details.
    // Down below we'll hardwire all of the symbols to the `Rust` export
    // level instead.
    let special_runtime_crate =
        tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE);

    let mut reachable_non_generics: DefIdMap<_> = tcx
        .reachable_set(LOCAL_CRATE)
        .iter()
        .filter_map(|&hir_id| {
            // We want to ignore some FFI functions that are not exposed from
            // this crate. Reachable FFI functions can be lumped into two
            // categories:
            //
            // 1. Those that are included statically via a static library
            // 2. Those included otherwise (e.g., dynamically or via a framework)
            //
            // Although our LLVM module is not literally emitting code for the
            // statically included symbols, it's an export of our library which
            // needs to be passed on to the linker and encoded in the metadata.
            //
            // As a result, if this id is an FFI item (foreign item) then we only
            // let it through if it's included statically.
            match tcx.hir().get(hir_id) {
                Node::ForeignItem(..) => {
                    let def_id = tcx.hir().local_def_id(hir_id);
                    tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
                }

                // Only consider nodes that actually have exported symbols.
                Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })
                | Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
                | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(..), .. }) => {
                    let def_id = tcx.hir().local_def_id(hir_id);
                    let generics = tcx.generics_of(def_id);
                    if !generics.requires_monomorphization(tcx) &&
                        // Functions marked with #[inline] are only ever codegened
                        // with "internal" linkage and are never exported.
                        !Instance::mono(tcx, def_id).def.requires_local(tcx)
                    {
                        Some(def_id)
                    } else {
                        None
                    }
                }

                _ => None,
            }
        })
        .map(|def_id| {
            let export_level = if special_runtime_crate {
                let name = tcx.symbol_name(Instance::mono(tcx, def_id)).name.as_str();
                // We can probably do better here by just ensuring that
                // it has hidden visibility rather than public
                // visibility, as this is primarily here to ensure it's
                // not stripped during LTO.
                //
                // In general though we won't link right if these
                // symbols are stripped, and LTO currently strips them.
                if name == "rust_eh_personality"
                    || name == "rust_eh_register_frames"
                    || name == "rust_eh_unregister_frames"
                {
                    SymbolExportLevel::C
                } else {
                    SymbolExportLevel::Rust
                }
            } else {
                symbol_export_level(tcx, def_id)
            };
            debug!(
                "EXPORTED SYMBOL (local): {} ({:?})",
                tcx.symbol_name(Instance::mono(tcx, def_id)),
                export_level
            );
            (def_id, export_level)
        })
        .collect();

    if let Some(id) = tcx.proc_macro_decls_static(LOCAL_CRATE) {
        reachable_non_generics.insert(id, SymbolExportLevel::C);
    }

    if let Some(id) = tcx.plugin_registrar_fn(LOCAL_CRATE) {
        reachable_non_generics.insert(id, SymbolExportLevel::C);
    }

    tcx.arena.alloc(reachable_non_generics)
}

fn is_reachable_non_generic_provider_local(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    let export_threshold = threshold(tcx);

    if let Some(&level) = tcx.reachable_non_generics(def_id.krate).get(&def_id) {
        level.is_below_threshold(export_threshold)
    } else {
        false
    }
}

fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
}

fn exported_symbols_provider_local(
    tcx: TyCtxt<'_>,
    cnum: CrateNum,
) -> Arc<Vec<(ExportedSymbol<'_>, SymbolExportLevel)>> {
    assert_eq!(cnum, LOCAL_CRATE);

    if !tcx.sess.opts.output_types.should_codegen() {
        return Arc::new(vec![]);
    }

    let mut symbols: Vec<_> = tcx
        .reachable_non_generics(LOCAL_CRATE)
        .iter()
        .map(|(&def_id, &level)| (ExportedSymbol::NonGeneric(def_id), level))
        .collect();

    if tcx.entry_fn(LOCAL_CRATE).is_some() {
        let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new("main"));

        symbols.push((exported_symbol, SymbolExportLevel::C));
    }

    if tcx.allocator_kind().is_some() {
        for method in ALLOCATOR_METHODS {
            let symbol_name = format!("__rust_{}", method.name);
            let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));

            symbols.push((exported_symbol, SymbolExportLevel::Rust));
        }
    }

    if tcx.sess.opts.cg.profile_generate.enabled() {
        // These are weak symbols that point to the profile version and the
        // profile name, which need to be treated as exported so LTO doesn't nix
        // them.
        const PROFILER_WEAK_SYMBOLS: [&str; 2] =
            ["__llvm_profile_raw_version", "__llvm_profile_filename"];

        symbols.extend(PROFILER_WEAK_SYMBOLS.iter().map(|sym| {
            let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(sym));
            (exported_symbol, SymbolExportLevel::C)
        }));
    }

    if tcx.sess.crate_types.borrow().contains(&config::CrateType::Dylib) {
        let symbol_name = metadata_symbol_name(tcx);
        let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));

        symbols.push((exported_symbol, SymbolExportLevel::Rust));
    }

    if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() {
        use rustc::mir::mono::{Linkage, MonoItem, Visibility};
        use rustc::ty::InstanceDef;

        // Normally, we require that shared monomorphizations are not hidden,
        // because if we want to re-use a monomorphization from a Rust dylib, it
        // needs to be exported.
        // However, on platforms that don't allow for Rust dylibs, having
        // external linkage is enough for monomorphization to be linked to.
        let need_visibility = tcx.sess.target.target.options.dynamic_linking
            && !tcx.sess.target.target.options.only_cdylib;

        let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);

        for (mono_item, &(linkage, visibility)) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
            if linkage != Linkage::External {
                // We can only re-use things with external linkage, otherwise
                // we'll get a linker error
                continue;
            }

            if need_visibility && visibility == Visibility::Hidden {
                // If we potentially share things from Rust dylibs, they must
                // not be hidden
                continue;
            }

            if let &MonoItem::Fn(Instance { def: InstanceDef::Item(def_id), substs }) = mono_item {
                if substs.non_erasable_generics().next().is_some() {
                    symbols
                        .push((ExportedSymbol::Generic(def_id, substs), SymbolExportLevel::Rust));
                }
            }
        }
    }

    // Sort so we get a stable incr. comp. hash.
    symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
        symbol1.compare_stable(tcx, symbol2)
    });

    Arc::new(symbols)
}

fn upstream_monomorphizations_provider(
    tcx: TyCtxt<'_>,
    cnum: CrateNum,
) -> &DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> {
    debug_assert!(cnum == LOCAL_CRATE);

    let cnums = tcx.all_crate_nums(LOCAL_CRATE);

    let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();

    let cnum_stable_ids: IndexVec<CrateNum, Fingerprint> = {
        let mut cnum_stable_ids = IndexVec::from_elem_n(Fingerprint::ZERO, cnums.len() + 1);

        for &cnum in cnums.iter() {
            cnum_stable_ids[cnum] =
                tcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).0;
        }

        cnum_stable_ids
    };

    for &cnum in cnums.iter() {
        for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
            if let &ExportedSymbol::Generic(def_id, substs) = exported_symbol {
                let substs_map = instances.entry(def_id).or_default();

                match substs_map.entry(substs) {
                    Occupied(mut e) => {
                        // If there are multiple monomorphizations available,
                        // we select one deterministically.
                        let other_cnum = *e.get();
                        if cnum_stable_ids[other_cnum] > cnum_stable_ids[cnum] {
                            e.insert(cnum);
                        }
                    }
                    Vacant(e) => {
                        e.insert(cnum);
                    }
                }
            }
        }
    }

    tcx.arena.alloc(instances)
}

fn upstream_monomorphizations_for_provider(
    tcx: TyCtxt<'_>,
    def_id: DefId,
) -> Option<&FxHashMap<SubstsRef<'_>, CrateNum>> {
    debug_assert!(!def_id.is_local());
    tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id)
}

fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
        !tcx.reachable_set(LOCAL_CRATE).contains(&hir_id)
    } else {
        bug!("is_unreachable_local_definition called with non-local DefId: {:?}", def_id)
    }
}

pub fn provide(providers: &mut Providers<'_>) {
    providers.reachable_non_generics = reachable_non_generics_provider;
    providers.is_reachable_non_generic = is_reachable_non_generic_provider_local;
    providers.exported_symbols = exported_symbols_provider_local;
    providers.upstream_monomorphizations = upstream_monomorphizations_provider;
    providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
}

pub fn provide_extern(providers: &mut Providers<'_>) {
    providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
    providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider;
}

fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel {
    // We export anything that's not mangled at the "C" layer as it probably has
    // to do with ABI concerns. We do not, however, apply such treatment to
    // special symbols in the standard library for various plumbing between
    // core/std/allocators/etc. For example symbols used to hook up allocation
    // are not considered for export
    let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
    let is_extern = codegen_fn_attrs.contains_extern_indicator();
    let std_internal =
        codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);

    if is_extern && !std_internal {
        let target = &tcx.sess.target.target.llvm_target;
        // WebAssembly cannot export data symbols, so reduce their export level
        if target.contains("wasm32") || target.contains("emscripten") {
            if let Some(Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })) =
                tcx.hir().get_if_local(sym_def_id)
            {
                let export_level = if tcx.type_of(sym_def_id).is_scalar() {
                    SymbolExportLevel::C
                } else {
                    SymbolExportLevel::Rust
                };
                return export_level;
            }
        }

        SymbolExportLevel::C
    } else {
        SymbolExportLevel::Rust
    }
}
<commit_msg>Always export static variables as SymbolExportLevel::C in wasm<commit_after>use std::collections::hash_map::Entry::*;
use std::sync::Arc;

use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
use rustc::session::config;
use rustc::ty::query::Providers;
use rustc::ty::subst::SubstsRef;
use rustc::ty::Instance;
use rustc::ty::{SymbolName, TyCtxt};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::Node;
use rustc_index::vec::IndexVec;
use syntax::expand::allocator::ALLOCATOR_METHODS;

pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportLevel)>>>;

pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
    crates_export_threshold(&tcx.sess.crate_types.borrow())
}

fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel {
    match crate_type {
        config::CrateType::Executable
        | config::CrateType::Staticlib
        | config::CrateType::ProcMacro
        | config::CrateType::Cdylib => SymbolExportLevel::C,
        config::CrateType::Rlib | config::CrateType::Dylib => SymbolExportLevel::Rust,
    }
}

pub fn crates_export_threshold(crate_types: &[config::CrateType]) -> SymbolExportLevel {
    if crate_types
        .iter()
        .any(|&crate_type| crate_export_threshold(crate_type) == SymbolExportLevel::Rust)
    {
        SymbolExportLevel::Rust
    } else {
        SymbolExportLevel::C
    }
}

fn reachable_non_generics_provider(
    tcx: TyCtxt<'_>,
    cnum: CrateNum,
) -> &DefIdMap<SymbolExportLevel> {
    assert_eq!(cnum, LOCAL_CRATE);

    if !tcx.sess.opts.output_types.should_codegen() {
        return tcx.arena.alloc(Default::default());
    }

    // Check to see if this crate is a "special runtime crate". These
    // crates, implementation details of the standard library, typically
    // have a bunch of `pub extern` and `#[no_mangle]` functions as the
    // ABI between them. We don't want their symbols to have a `C`
    // export level, however, as they're just implementation details.
    // Down below we'll hardwire all of the symbols to the `Rust` export
    // level instead.
    let special_runtime_crate =
        tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE);

    let mut reachable_non_generics: DefIdMap<_> = tcx
        .reachable_set(LOCAL_CRATE)
        .iter()
        .filter_map(|&hir_id| {
            // We want to ignore some FFI functions that are not exposed from
            // this crate. Reachable FFI functions can be lumped into two
            // categories:
            //
            // 1. Those that are included statically via a static library
            // 2. Those included otherwise (e.g., dynamically or via a framework)
            //
            // Although our LLVM module is not literally emitting code for the
            // statically included symbols, it's an export of our library which
            // needs to be passed on to the linker and encoded in the metadata.
            //
            // As a result, if this id is an FFI item (foreign item) then we only
            // let it through if it's included statically.
            match tcx.hir().get(hir_id) {
                Node::ForeignItem(..) => {
                    let def_id = tcx.hir().local_def_id(hir_id);
                    tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
                }

                // Only consider nodes that actually have exported symbols.
                Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })
                | Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
                | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(..), .. }) => {
                    let def_id = tcx.hir().local_def_id(hir_id);
                    let generics = tcx.generics_of(def_id);
                    if !generics.requires_monomorphization(tcx) &&
                        // Functions marked with #[inline] are only ever codegened
                        // with "internal" linkage and are never exported.
                        !Instance::mono(tcx, def_id).def.requires_local(tcx)
                    {
                        Some(def_id)
                    } else {
                        None
                    }
                }

                _ => None,
            }
        })
        .map(|def_id| {
            let export_level = if special_runtime_crate {
                let name = tcx.symbol_name(Instance::mono(tcx, def_id)).name.as_str();
                // We can probably do better here by just ensuring that
                // it has hidden visibility rather than public
                // visibility, as this is primarily here to ensure it's
                // not stripped during LTO.
                //
                // In general though we won't link right if these
                // symbols are stripped, and LTO currently strips them.
                if name == "rust_eh_personality"
                    || name == "rust_eh_register_frames"
                    || name == "rust_eh_unregister_frames"
                {
                    SymbolExportLevel::C
                } else {
                    SymbolExportLevel::Rust
                }
            } else {
                symbol_export_level(tcx, def_id)
            };
            debug!(
                "EXPORTED SYMBOL (local): {} ({:?})",
                tcx.symbol_name(Instance::mono(tcx, def_id)),
                export_level
            );
            (def_id, export_level)
        })
        .collect();

    if let Some(id) = tcx.proc_macro_decls_static(LOCAL_CRATE) {
        reachable_non_generics.insert(id, SymbolExportLevel::C);
    }

    if let Some(id) = tcx.plugin_registrar_fn(LOCAL_CRATE) {
        reachable_non_generics.insert(id, SymbolExportLevel::C);
    }

    tcx.arena.alloc(reachable_non_generics)
}

fn is_reachable_non_generic_provider_local(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    let export_threshold = threshold(tcx);

    if let Some(&level) = tcx.reachable_non_generics(def_id.krate).get(&def_id) {
        level.is_below_threshold(export_threshold)
    } else {
        false
    }
}

fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
}

fn exported_symbols_provider_local(
    tcx: TyCtxt<'_>,
    cnum: CrateNum,
) -> Arc<Vec<(ExportedSymbol<'_>, SymbolExportLevel)>> {
    assert_eq!(cnum, LOCAL_CRATE);

    if !tcx.sess.opts.output_types.should_codegen() {
        return Arc::new(vec![]);
    }

    let mut symbols: Vec<_> = tcx
        .reachable_non_generics(LOCAL_CRATE)
        .iter()
        .map(|(&def_id, &level)| (ExportedSymbol::NonGeneric(def_id), level))
        .collect();

    if tcx.entry_fn(LOCAL_CRATE).is_some() {
        let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new("main"));

        symbols.push((exported_symbol, SymbolExportLevel::C));
    }

    if tcx.allocator_kind().is_some() {
        for method in ALLOCATOR_METHODS {
            let symbol_name = format!("__rust_{}", method.name);
            let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));

            symbols.push((exported_symbol, SymbolExportLevel::Rust));
        }
    }

    if tcx.sess.opts.cg.profile_generate.enabled() {
        // These are weak symbols that point to the profile version and the
        // profile name, which need to be treated as exported so LTO doesn't nix
        // them.
        const PROFILER_WEAK_SYMBOLS: [&str; 2] =
            ["__llvm_profile_raw_version", "__llvm_profile_filename"];

        symbols.extend(PROFILER_WEAK_SYMBOLS.iter().map(|sym| {
            let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(sym));
            (exported_symbol, SymbolExportLevel::C)
        }));
    }

    if tcx.sess.crate_types.borrow().contains(&config::CrateType::Dylib) {
        let symbol_name = metadata_symbol_name(tcx);
        let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));

        symbols.push((exported_symbol, SymbolExportLevel::Rust));
    }

    if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() {
        use rustc::mir::mono::{Linkage, MonoItem, Visibility};
        use rustc::ty::InstanceDef;

        // Normally, we require that shared monomorphizations are not hidden,
        // because if we want to re-use a monomorphization from a Rust dylib, it
        // needs to be exported.
        // However, on platforms that don't allow for Rust dylibs, having
        // external linkage is enough for monomorphization to be linked to.
        let need_visibility = tcx.sess.target.target.options.dynamic_linking
            && !tcx.sess.target.target.options.only_cdylib;

        let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);

        for (mono_item, &(linkage, visibility)) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
            if linkage != Linkage::External {
                // We can only re-use things with external linkage, otherwise
                // we'll get a linker error
                continue;
            }

            if need_visibility && visibility == Visibility::Hidden {
                // If we potentially share things from Rust dylibs, they must
                // not be hidden
                continue;
            }

            if let &MonoItem::Fn(Instance { def: InstanceDef::Item(def_id), substs }) = mono_item {
                if substs.non_erasable_generics().next().is_some() {
                    symbols
                        .push((ExportedSymbol::Generic(def_id, substs), SymbolExportLevel::Rust));
                }
            }
        }
    }

    // Sort so we get a stable incr. comp. hash.
    symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
        symbol1.compare_stable(tcx, symbol2)
    });

    Arc::new(symbols)
}

fn upstream_monomorphizations_provider(
    tcx: TyCtxt<'_>,
    cnum: CrateNum,
) -> &DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> {
    debug_assert!(cnum == LOCAL_CRATE);

    let cnums = tcx.all_crate_nums(LOCAL_CRATE);

    let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();

    let cnum_stable_ids: IndexVec<CrateNum, Fingerprint> = {
        let mut cnum_stable_ids = IndexVec::from_elem_n(Fingerprint::ZERO, cnums.len() + 1);

        for &cnum in cnums.iter() {
            cnum_stable_ids[cnum] =
                tcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).0;
        }

        cnum_stable_ids
    };

    for &cnum in cnums.iter() {
        for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
            if let &ExportedSymbol::Generic(def_id, substs) = exported_symbol {
                let substs_map = instances.entry(def_id).or_default();

                match substs_map.entry(substs) {
                    Occupied(mut e) => {
                        // If there are multiple monomorphizations available,
                        // we select one deterministically.
                        let other_cnum = *e.get();
                        if cnum_stable_ids[other_cnum] > cnum_stable_ids[cnum] {
                            e.insert(cnum);
                        }
                    }
                    Vacant(e) => {
                        e.insert(cnum);
                    }
                }
            }
        }
    }

    tcx.arena.alloc(instances)
}

fn upstream_monomorphizations_for_provider(
    tcx: TyCtxt<'_>,
    def_id: DefId,
) -> Option<&FxHashMap<SubstsRef<'_>, CrateNum>> {
    debug_assert!(!def_id.is_local());
    tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id)
}

fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
        !tcx.reachable_set(LOCAL_CRATE).contains(&hir_id)
    } else {
        bug!("is_unreachable_local_definition called with non-local DefId: {:?}", def_id)
    }
}

pub fn provide(providers: &mut Providers<'_>) {
    providers.reachable_non_generics = reachable_non_generics_provider;
    providers.is_reachable_non_generic = is_reachable_non_generic_provider_local;
    providers.exported_symbols = exported_symbols_provider_local;
    providers.upstream_monomorphizations = upstream_monomorphizations_provider;
    providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
}

pub fn provide_extern(providers: &mut Providers<'_>) {
    providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
    providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider;
}

fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel {
    // We export anything that's not mangled at the "C" layer as it probably has
    // to do with ABI concerns. We do not, however, apply such treatment to
    // special symbols in the standard library for various plumbing between
    // core/std/allocators/etc. For example symbols used to hook up allocation
    // are not considered for export
    let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
    let is_extern = codegen_fn_attrs.contains_extern_indicator();
    let std_internal =
        codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);

    if is_extern && !std_internal {
        let target = &tcx.sess.target.target.llvm_target;
        // WebAssembly cannot export data symbols, so reduce their export level
        if target.contains("emscripten") {
            if let Some(Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })) =
                tcx.hir().get_if_local(sym_def_id)
            {
                return SymbolExportLevel::Rust;
            }
        }

        SymbolExportLevel::C
    } else {
        SymbolExportLevel::Rust
    }
}
<|endoftext|>


<commit_before>//! This module is UNSTABLE, the reason is - recently added.

use std::convert::From;
use std::io::{self, Read, BufRead};
use std::str::{from_utf8, Utf8Error};

use super::{read_marker};
use super::{
    ReadError,
    MarkerReadError,
};
use super::{BigEndianRead};

use super::super::init::Marker;
use super::super::value::ValueRef;

trait USizeCast {
    fn from(v: Self) -> Option<usize> where Self: Sized;
}

impl USizeCast for u8 {
    fn from(v: u8) -> Option<usize> {
        // Impossible to panic, since u8 always fits in usize.
        Some(v as usize)
    }
}

impl USizeCast for u16 {
    fn from(v: u16) -> Option<usize> {
        // TODO: This can overflow on 8-bit systems.
        Some(v as usize)
    }
}

impl USizeCast for u32 {
    fn from(v: u32) -> Option<usize> {
        // TODO: This can overflow on 8- and 16-bit systems.
        Some(v as usize)
    }
}

// TODO: Display trait.
#[derive(Debug)]
pub enum Error<'r> {
    /// Failed to fill the internal reader buffer.
    ///
    /// RMP tries to obtain the buffer at the beginning of read operation using `read_buf` function.
    ///
    /// According to the Rust documentation, `fill_buf` function will return an I/O error if the
    /// underlying reader was read, but returned an error.
    InvalidBufferFill(io::Error),
    /// Failed to read the type marker value.
    InvalidMarkerRead(ReadError),
    /// Failed to read string/array/map size.
    InvalidLengthRead(ReadError),
    /// Failed to read packed non-marker data.
    InvalidDataRead(ReadError),

    /// Failed to cast the length read to machine size.
    InvalidLengthSize,

    /// Failed to interpret a byte slice as a UTF-8 string.
    ///
    /// Contains untouched bytearray with the underlying decoding error.
    InvalidUtf8(&'r [u8], Utf8Error),
}

impl<'r> From<MarkerReadError> for Error<'r> {
    fn from(err: MarkerReadError) -> Error<'r> {
        Error::InvalidMarkerRead(From::from(err))
    }
}

fn read_length<R, D>(rd: &mut R) -> Result<D, ReadError>
    where R: Read,
          D: BigEndianRead
{
    D::read(rd).map_err(From::from)
}

fn read_str(buf: &[u8], len: usize) -> Result<&str, Error> {
    if len > buf.len() {
        return Err(Error::InvalidDataRead(ReadError::UnexpectedEOF));
    }

    // Take a slice.
    let buf = &buf[..len];

    // Try to decode sliced buffer as UTF-8.
    let res = try!(from_utf8(buf).map_err(|err| Error::InvalidUtf8(buf, err)));

    Ok(res)
}

fn read_bin(buf: &[u8], len: usize) -> Result<&[u8], Error> {
    if len > buf.len() {
        return Err(Error::InvalidDataRead(ReadError::UnexpectedEOF));
    }

    // Take a slice.
    let buf = &buf[..len];

    Ok(buf)
}

#[inline]
fn read_str_value<U>(buf: &[u8], len: U) -> Result<ValueRef, Error>
    where U: USizeCast
{
    let len = try!(U::from(len).ok_or(Error::InvalidLengthSize));
    let res = try!(read_str(buf, len));

    Ok(ValueRef::String(res))
}

#[inline]
fn read_bin_value<U>(buf: &[u8], len: U) -> Result<ValueRef, Error>
    where U: USizeCast
{
    let len = try!(U::from(len).ok_or(Error::InvalidLengthSize));
    let res = try!(read_bin(buf, len));

    Ok(ValueRef::Binary(res))
}

// NOTE: Consumes nothing from the given `BufRead` both on success and fail.
pub fn read_value_ref<R>(rd: &mut R) -> Result<ValueRef, Error>
    where R: BufRead
{
    let mut buf = try!(rd.fill_buf().map_err(|err| Error::InvalidBufferFill(err)));

    // Reading the marker involves either 1 byte read or nothing. On success consumes strictly
    // 1 byte from the `buf`, not from the `rd`.
    let marker = try!(read_marker(&mut buf));

    let val = match marker {
        Marker::FixedString(len) => {
            try!(read_str_value(buf, len))
        }
        Marker::Str8 => {
            let len: u8 = try!(read_length(&mut buf).map_err(|err| Error::InvalidLengthRead(err)));
            try!(read_str_value(buf, len))
        }
        Marker::Str16 => {
            let len: u16 = try!(read_length(&mut buf).map_err(|err| Error::InvalidLengthRead(err)));
            try!(read_str_value(buf, len))
        }
        Marker::Str32 => {
            let len: u32 = try!(read_length(&mut buf).map_err(|err| Error::InvalidLengthRead(err)));
            try!(read_str_value(buf, len))
        }
        Marker::Bin8 => {
            let len: u8 = try!(read_length(&mut buf).map_err(|err| Error::InvalidLengthRead(err)));
            try!(read_bin_value(buf, len))
        }
        Marker::Bin16 => {
            unimplemented!();
        }
        Marker::Bin32 => {
            unimplemented!();
        }
        _ => unimplemented!(),
    };

    Ok(val)
}

// TODO: Concepts: less code; more tests; fast refactoring after each test; no more than 5 min for
// each red-yellow-green.
<commit_msg>Misc: code reuse.<commit_after>//! This module is UNSTABLE, the reason is - recently added.

use std::convert::From;
use std::io::{self, Read, BufRead};
use std::str::{from_utf8, Utf8Error};

use super::{read_marker};
use super::{
    ReadError,
    MarkerReadError,
};
use super::{BigEndianRead};

use super::super::init::Marker;
use super::super::value::ValueRef;

trait USizeCast {
    fn from(v: Self) -> Option<usize> where Self: Sized;
}

impl USizeCast for u8 {
    fn from(v: u8) -> Option<usize> {
        // Impossible to panic, since u8 always fits in usize.
        Some(v as usize)
    }
}

impl USizeCast for u16 {
    fn from(v: u16) -> Option<usize> {
        // TODO: This can overflow on 8-bit systems.
        Some(v as usize)
    }
}

impl USizeCast for u32 {
    fn from(v: u32) -> Option<usize> {
        // TODO: This can overflow on 8- and 16-bit systems.
        Some(v as usize)
    }
}

// TODO: Display trait.
#[derive(Debug)]
pub enum Error<'r> {
    /// Failed to fill the internal reader buffer.
    ///
    /// RMP tries to obtain the buffer at the beginning of read operation using `read_buf` function.
    ///
    /// According to the Rust documentation, `fill_buf` function will return an I/O error if the
    /// underlying reader was read, but returned an error.
    InvalidBufferFill(io::Error),
    /// Failed to read the type marker value.
    InvalidMarkerRead(ReadError),
    /// Failed to read string/array/map size.
    InvalidLengthRead(ReadError),
    /// Failed to read packed non-marker data.
    InvalidDataRead(ReadError),
    /// Failed to cast the length read to machine size.
    InvalidLengthSize,
    /// Failed to interpret a byte slice as a UTF-8 string.
    ///
    /// Contains untouched bytearray with the underlying decoding error.
    InvalidUtf8(&'r [u8], Utf8Error),
}

impl<'r> From<MarkerReadError> for Error<'r> {
    fn from(err: MarkerReadError) -> Error<'r> {
        Error::InvalidMarkerRead(From::from(err))
    }
}

fn read_length<R, D>(rd: &mut R) -> Result<D, ReadError>
    where R: Read,
          D: BigEndianRead
{
    D::read(rd).map_err(From::from)
}

fn read_str(buf: &[u8], len: usize) -> Result<&str, Error> {
    let buf = try!(read_bin(buf, len));

    // Try to decode sliced buffer as UTF-8.
    let res = try!(from_utf8(buf).map_err(|err| Error::InvalidUtf8(buf, err)));

    Ok(res)
}

fn read_bin(buf: &[u8], len: usize) -> Result<&[u8], Error> {
    if len > buf.len() {
        return Err(Error::InvalidDataRead(ReadError::UnexpectedEOF));
    }

    // Take a slice.
    let buf = &buf[..len];

    Ok(buf)
}

#[inline]
fn read_str_value<U>(buf: &[u8], len: U) -> Result<ValueRef, Error>
    where U: USizeCast
{
    let len = try!(U::from(len).ok_or(Error::InvalidLengthSize));
    let res = try!(read_str(buf, len));

    Ok(ValueRef::String(res))
}

#[inline]
fn read_bin_value<U>(buf: &[u8], len: U) -> Result<ValueRef, Error>
    where U: USizeCast
{
    let len = try!(U::from(len).ok_or(Error::InvalidLengthSize));
    let res = try!(read_bin(buf, len));

    Ok(ValueRef::Binary(res))
}

// NOTE: Consumes nothing from the given `BufRead` both on success and fail.
pub fn read_value_ref<R>(rd: &mut R) -> Result<ValueRef, Error>
    where R: BufRead
{
    let mut buf = try!(rd.fill_buf().map_err(|err| Error::InvalidBufferFill(err)));

    // Reading the marker involves either 1 byte read or nothing. On success consumes strictly
    // 1 byte from the `buf`, not from the `rd`.
    let marker = try!(read_marker(&mut buf));

    let val = match marker {
        Marker::FixedString(len) => {
            try!(read_str_value(buf, len))
        }
        Marker::Str8 => {
            let len: u8 = try!(read_length(&mut buf).map_err(|err| Error::InvalidLengthRead(err)));
            try!(read_str_value(buf, len))
        }
        Marker::Str16 => {
            let len: u16 = try!(read_length(&mut buf).map_err(|err| Error::InvalidLengthRead(err)));
            try!(read_str_value(buf, len))
        }
        Marker::Str32 => {
            let len: u32 = try!(read_length(&mut buf).map_err(|err| Error::InvalidLengthRead(err)));
            try!(read_str_value(buf, len))
        }
        Marker::Bin8 => {
            let len: u8 = try!(read_length(&mut buf).map_err(|err| Error::InvalidLengthRead(err)));
            try!(read_bin_value(buf, len))
        }
        Marker::Bin16 => {
            unimplemented!();
        }
        Marker::Bin32 => {
            unimplemented!();
        }
        _ => unimplemented!(),
    };

    Ok(val)
}

// TODO: Concepts: less code; more tests; fast refactoring after each test; no more than 5 min for
// each red-yellow-green.
<|endoftext|>


<commit_before>//! Updates crates.io index and builds new packages

use super::DocBuilder;
use DocBuilderError;
use rustc_serialize::json::Json;
use git2;
use db::connect_db;

impl DocBuilder {
    /// Updates crates.io-index repository and adds new crates into build queue
    pub fn get_new_crates(&self) -> Result<(), DocBuilderError> {

        let repo = try!(git2::Repository::open(&self.options.crates_io_index_path));

        let old_tree = try!(self.head_tree(&repo));
        try!(self.update_repo(&repo));
        let new_tree = try!(self.head_tree(&repo));

        let diff = try!(repo.diff_tree_to_tree(Some(&old_tree), Some(&new_tree), None));
        let conn = try!(connect_db());

        try!(diff.print(git2::DiffFormat::Patch, |_, _, diffline| -> bool {
            let line = String::from_utf8_lossy(diffline.content()).into_owned();
            // crate strings starts with '{'
            // skip if line is not a crate string
            if line.chars().nth(0) != Some('{') {
                return true;
            }
            let json = match Json::from_str(&line[..]) {
                Ok(j) => j,
                Err(err) => {
                    error!("Failed to parse crate string: {}", err);
                    // just continue even if we get an error for a crate
                    return true;
                }
            };

            if let Some((krate, version)) = json.as_object()
                                                .map(|obj| {
                                                    (obj.get("name")
                                                        .and_then(|n| n.as_string()),
                                                     obj.get("vers")
                                                        .and_then(|n| n.as_string()))
                                                }) {

                // Skip again if we can't get crate name and version
                if krate.is_none() || version.is_none() {
                    return true;
                }

                let _ = conn.execute("INSERT INTO queue (name, version) VALUES ($1, $2)",
                                     &[&krate.unwrap(), &version.unwrap()]);
            }

            true
        }));

        Ok(())
    }

    fn update_repo(&self, repo: &git2::Repository) -> Result<(), git2::Error> {
        let mut remote = try!(repo.find_remote("origin"));
        try!(remote.fetch(&["refs/heads/*:refs/remotes/origin/*"], None, None));

        // checkout master
        try!(repo.refname_to_id("refs/remotes/origin/master")
                 .and_then(|oid| repo.find_object(oid, None))
                 .and_then(|object| repo.reset(&object, git2::ResetType::Hard, None)));

        Ok(())
    }

    fn head_tree<'a>(&'a self, repo: &'a git2::Repository) -> Result<git2::Tree, git2::Error> {
        repo.head()
            .ok()
            .and_then(|head| head.target())
            .ok_or(git2::Error::from_str("HEAD SHA1 not found"))
            .and_then(|oid| repo.find_commit(oid))
            .and_then(|commit| commit.tree())
    }

    /// Builds packages from queue
    pub fn build_packages_queue(&mut self) -> Result<(), DocBuilderError> {
        let conn = try!(connect_db());

        for row in &try!(conn.query("SELECT id, name, version FROM queue ORDER BY id ASC", &[])) {
            let id: i32 = row.get(0);
            let name: String = row.get(1);
            let version: String = row.get(2);

            if let Ok(_) = self.build_package(&name[..], &version[..]) {
                // remove package from que
                let _ = conn.execute("DELETE FROM queue WHERE id = $1", &[&id]);
            } else {
                warn!("Failed to build package {}-{} from queue", name, version);
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use std::path::PathBuf;
    use {DocBuilder, DocBuilderOptions};

    #[test]
    #[ignore]
    fn test_get_new_crates() {
        let _ = env_logger::init();
        let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
        let docbuilder = DocBuilder::new(options);
        assert!(docbuilder.get_new_crates().is_ok());
    }

    #[test]
    #[ignore]
    fn test_build_packages_queue() {
        let _ = env_logger::init();
        let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
        let mut docbuilder = DocBuilder::new(options);
        assert!(docbuilder.build_packages_queue().is_ok());
    }
}
<commit_msg>Show error detail if a package fails to build in que<commit_after>//! Updates crates.io index and builds new packages

use super::DocBuilder;
use DocBuilderError;
use rustc_serialize::json::Json;
use git2;
use db::connect_db;

impl DocBuilder {
    /// Updates crates.io-index repository and adds new crates into build queue
    pub fn get_new_crates(&self) -> Result<(), DocBuilderError> {

        let repo = try!(git2::Repository::open(&self.options.crates_io_index_path));

        let old_tree = try!(self.head_tree(&repo));
        try!(self.update_repo(&repo));
        let new_tree = try!(self.head_tree(&repo));

        let diff = try!(repo.diff_tree_to_tree(Some(&old_tree), Some(&new_tree), None));
        let conn = try!(connect_db());

        try!(diff.print(git2::DiffFormat::Patch, |_, _, diffline| -> bool {
            let line = String::from_utf8_lossy(diffline.content()).into_owned();
            // crate strings starts with '{'
            // skip if line is not a crate string
            if line.chars().nth(0) != Some('{') {
                return true;
            }
            let json = match Json::from_str(&line[..]) {
                Ok(j) => j,
                Err(err) => {
                    error!("Failed to parse crate string: {}", err);
                    // just continue even if we get an error for a crate
                    return true;
                }
            };

            if let Some((krate, version)) = json.as_object()
                                                .map(|obj| {
                                                    (obj.get("name")
                                                        .and_then(|n| n.as_string()),
                                                     obj.get("vers")
                                                        .and_then(|n| n.as_string()))
                                                }) {

                // Skip again if we can't get crate name and version
                if krate.is_none() || version.is_none() {
                    return true;
                }

                let _ = conn.execute("INSERT INTO queue (name, version) VALUES ($1, $2)",
                                     &[&krate.unwrap(), &version.unwrap()]);
            }

            true
        }));

        Ok(())
    }

    fn update_repo(&self, repo: &git2::Repository) -> Result<(), git2::Error> {
        let mut remote = try!(repo.find_remote("origin"));
        try!(remote.fetch(&["refs/heads/*:refs/remotes/origin/*"], None, None));

        // checkout master
        try!(repo.refname_to_id("refs/remotes/origin/master")
                 .and_then(|oid| repo.find_object(oid, None))
                 .and_then(|object| repo.reset(&object, git2::ResetType::Hard, None)));

        Ok(())
    }

    fn head_tree<'a>(&'a self, repo: &'a git2::Repository) -> Result<git2::Tree, git2::Error> {
        repo.head()
            .ok()
            .and_then(|head| head.target())
            .ok_or(git2::Error::from_str("HEAD SHA1 not found"))
            .and_then(|oid| repo.find_commit(oid))
            .and_then(|commit| commit.tree())
    }

    /// Builds packages from queue
    pub fn build_packages_queue(&mut self) -> Result<(), DocBuilderError> {
        let conn = try!(connect_db());

        for row in &try!(conn.query("SELECT id, name, version FROM queue ORDER BY id ASC", &[])) {
            let id: i32 = row.get(0);
            let name: String = row.get(1);
            let version: String = row.get(2);

            match self.build_package(&name[..], &version[..]) {
                Ok(_) => { let _ = conn.execute("DELETE FROM queue WHERE id = $1", &[&id]); },
                Err(e) => error!("Failed to build package {}-{} from queue: {}", name, version, e),
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use std::path::PathBuf;
    use {DocBuilder, DocBuilderOptions};

    #[test]
    #[ignore]
    fn test_get_new_crates() {
        let _ = env_logger::init();
        let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
        let docbuilder = DocBuilder::new(options);
        assert!(docbuilder.get_new_crates().is_ok());
    }

    #[test]
    #[ignore]
    fn test_build_packages_queue() {
        let _ = env_logger::init();
        let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
        let mut docbuilder = DocBuilder::new(options);
        assert!(docbuilder.build_packages_queue().is_ok());
    }
}
<|endoftext|>