<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use super::query_builder::{get_all_roots, get_watchman_expr};
use super::{Clock, WatchmanFile};
use crate::errors::{Error, Result};
use crate::{compiler_state::CompilerState, config::Config, saved_state::SavedStateLoader};
use common::{PerfLogEvent, PerfLogger};
use log::{debug, info, warn};
use serde_bser::value::Value;
use watchman_client::prelude::*;
use watchman_client::{Subscription as WatchmanSubscription, SubscriptionData};

pub struct FileSource<'config> {
    client: Client,
    config: &'config Config,
    resolved_root: ResolvedRoot,
}

#[derive(Debug)]
pub enum FileSourceSubscriptionNextChange {
    Result(FileSourceResult),
    SourceControlUpdateEnter,
    SourceControlUpdateLeave,
    None,
}

#[derive(Debug)]
pub struct FileSourceResult {
    pub files: Vec<WatchmanFile>,
    pub resolved_root: ResolvedRoot,
    pub clock: Clock,
    pub saved_state_info: Option<Value>,
}

impl<'config> FileSource<'config> {
    pub async fn connect(
        config: &'config Config,
        perf_logger_event: &impl PerfLogEvent,
    ) -> Result<FileSource<'config>> {
        let connect_timer = perf_logger_event.start("file_source_connect_time");
        let client = Connector::new().connect().await?;
        let canonical_root = CanonicalPath::canonicalize(&config.root_dir).map_err(|err| {
            Error::CanonicalizeRoot {
                root: config.root_dir.clone(),
                source: err,
            }
        })?;
        let resolved_root = client.resolve_root(canonical_root).await?;
        perf_logger_event.stop(connect_timer);

        Ok(Self {
            client,
            config,
            resolved_root,
        })
    }

    /// Executes a point query (as opposed to a subscription) to find all files
    /// to compile and returns the result.
    pub async fn query(
        &self,
        perf_logger_event: &impl PerfLogEvent,
        perf_logger: &impl PerfLogger,
    ) -> Result<CompilerState> {
        info!("querying files to compile...");
        let query_time = perf_logger_event.start("file_source_query_time");
        // If the saved state flag is passed, load from it or fail.
        if let Some(saved_state_path) = &self.config.load_saved_state_file {
            let mut compiler_state = perf_logger_event.time("deserialize_saved_state", || {
                CompilerState::deserialize_from_file(&saved_state_path)
            })?;
            let file_source_result = self
                .query_file_result(Some(compiler_state.clock.clone()), perf_logger_event)
                .await?;
            compiler_state
                .pending_file_source_changes
                .write()
                .unwrap()
                .push(file_source_result);
            compiler_state.merge_file_source_changes(
                &self.config,
                perf_logger_event,
                perf_logger,
                true,
            )?;
            perf_logger_event.stop(query_time);
            return Ok(compiler_state);
        }

        // If saved state is configured, try using saved state unless the config
        // forces a full build.
        if let Config {
            compile_everything: false,
            saved_state_config: Some(saved_state_config),
            saved_state_loader: Some(saved_state_loader),
            saved_state_version,
            ..
        } = self.config
        {
            match self
                .try_saved_state(
                    perf_logger,
                    perf_logger_event,
                    saved_state_config.clone(),
                    saved_state_loader,
                    saved_state_version,
                )
                .await
            {
                Ok(load_result) => {
                    perf_logger_event.stop(query_time);
                    return load_result;
                }
                Err(saved_state_failure) => {
                    warn!(
                        "Unable to load saved state, falling back to full build: {}",
                        saved_state_failure
                    );
                }
            }
        }

        // Finally, do a simple full query.
        let file_source_result = self.query_file_result(None, perf_logger_event).await?;
        let compiler_state = perf_logger_event.time("from_file_source_changes", || {
            CompilerState::from_file_source_changes(
                &self.config,
                &file_source_result,
                perf_logger_event,
                perf_logger,
            )
        })?;
        perf_logger_event.stop(query_time);
        Ok(compiler_state)
    }

    /// Starts a subscription sending updates since the given clock.
    pub async fn subscribe(
        self,
        perf_logger_event: &impl PerfLogEvent,
        perf_logger: &impl PerfLogger,
    ) -> Result<(CompilerState, FileSourceSubscription)> {
        let timer = perf_logger_event.start("file_source_subscribe_time");
        let compiler_state = self.query(perf_logger_event, perf_logger).await?;

        let expression = get_watchman_expr(&self.config);

        let file_source_result = self
            .query_file_result(Some(compiler_state.clock.clone()), perf_logger_event)
            .await?;

        let (subscription, _initial) = self
            .client
            .subscribe::<WatchmanFile>(
                &self.resolved_root,
                SubscribeRequest {
                    expression: Some(expression),
                    since: Some(file_source_result.clock.clone()),
                    drop: vec!["hg.update"],
                    ..Default::default()
                },
            )
            .await?;

        perf_logger_event.stop(timer);

        Ok((
            compiler_state,
            FileSourceSubscription {
                resolved_root: self.resolved_root.clone(),
                subscription,
            },
        ))
    }

    /// Internal method to issue a watchman query, returning a raw
    /// FileSourceResult.
    async fn query_file_result(
        &self,
        since_clock: Option<Clock>,
        perf_logger_event: &impl PerfLogEvent,
    ) -> Result<FileSourceResult> {
        let expression = get_watchman_expr(&self.config);

        let query_timer = perf_logger_event.start("watchman_query_time");
        // If `since` is available, we should not pass the `path` parameter.
        // Watchman ignores `since` parameter if both `path` and `since` are
        // passed as the request params
        let request = if since_clock.is_some() {
            QueryRequestCommon {
                expression: Some(expression),
                since: since_clock,
                ..Default::default()
            }
        } else {
            let query_roots = get_all_roots(&self.config)
                .into_iter()
                .map(PathGeneratorElement::RecursivePath)
                .collect();
            QueryRequestCommon {
                expression: Some(expression),
                path: Some(query_roots),
                ..Default::default()
            }
        };
        let query_result = self
            .client
            .query::<WatchmanFile>(&self.resolved_root, request)
            .await?;
        perf_logger_event.stop(query_timer);

        let files = query_result.files.ok_or_else(|| Error::EmptyQueryResult)?;
        Ok(FileSourceResult {
            files,
            resolved_root: self.resolved_root.clone(),
            clock: query_result.clock,
            saved_state_info: query_result.saved_state_info,
        })
    }

    /// Tries to load saved state with a watchman query.
    /// The return value is a nested Result:
    /// The outer Result indicates the result of a possible saved state infrastructure failure.
    /// The inner Result is a potential parse error.
    async fn try_saved_state(
        &self,
        perf_logger: &impl PerfLogger,
        perf_logger_event: &impl PerfLogEvent,
        saved_state_config: ScmAwareClockData,
        saved_state_loader: &Box<dyn SavedStateLoader + Send + Sync>,
        saved_state_version: &str,
    ) -> std::result::Result<Result<CompilerState>, &'static str> {
        let scm_since = Clock::ScmAware(FatClockData {
            clock: ClockSpec::null(),
            scm: Some(saved_state_config),
        });
        let file_source_result = self
            .query_file_result(Some(scm_since), perf_logger_event)
            .await
            .map_err(|_| "query failed")?;
        let saved_state_info = file_source_result
            .saved_state_info
            .as_ref()
            .ok_or("no saved state in watchman response")?;
        let saved_state_path = perf_logger_event.time("saved_state_loading_time", || {
            saved_state_loader
                .load(&saved_state_info)
                .ok_or("unable to load")
        })?;
        let mut compiler_state = perf_logger_event
            .time("deserialize_saved_state", || {
                CompilerState::deserialize_from_file(&saved_state_path)
            })
            .map_err(|err| {
                let error_event = perf_logger.create_event("saved_state_loader_error");
                error_event.string("error", format!("Failed to deserialize: {}", err));
                perf_logger.complete_event(error_event);
                perf_logger.flush();
                "failed to deserialize"
            })?;
        if compiler_state.saved_state_version != saved_state_version {
            return Err("Saved state version doesn't match.");
        }
        compiler_state
            .pending_file_source_changes
            .write()
            .unwrap()
            .push(file_source_result);
        if let Err(parse_error) = perf_logger_event.time("merge_file_source_changes", || {
            compiler_state.merge_file_source_changes(
                &self.config,
                perf_logger_event,
                perf_logger,
                true,
            )
        }) {
            Ok(Err(parse_error))
        } else {
            Ok(Ok(compiler_state))
        }
    }
}

pub struct FileSourceSubscription {
    resolved_root: ResolvedRoot,
    subscription: WatchmanSubscription<WatchmanFile>,
}

impl FileSourceSubscription {
    /// Awaits changes from Watchman and provides the next set of changes
    /// if there were any changes to files
    pub async fn next_change(&mut self) -> Result<FileSourceSubscriptionNextChange> {
        match self.subscription.next().await? {
            SubscriptionData::FilesChanged(changes) => {
                if let Some(files) = changes.files {
                    debug!("number of files in this update: {}", files.len());
                    return Ok(FileSourceSubscriptionNextChange::Result(FileSourceResult {
                        files,
                        resolved_root: self.resolved_root.clone(),
                        clock: changes.clock,
                        saved_state_info: None,
                    }));
                }
            }
            SubscriptionData::StateEnter { state_name, .. } => {
                if state_name == "hg.update" {
                    debug!("hg.update started");
                    return Ok(FileSourceSubscriptionNextChange::SourceControlUpdateEnter);
                }
            }
            SubscriptionData::StateLeave { state_name, .. } => {
                if state_name == "hg.update" {
                    debug!("hg.update completed");
                    return Ok(FileSourceSubscriptionNextChange::SourceControlUpdateLeave);
                }
            }
            SubscriptionData::Canceled => {
                return Err(Error::WatchmanSubscriptionCanceled);
            }
        }
        Ok(FileSourceSubscriptionNextChange::None)
    }
}
<commit_msg>Add new flag RELAY_COMPILER_IGNORE_SAVED_STATE_VERSION<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use super::query_builder::{get_all_roots, get_watchman_expr};
use super::{Clock, WatchmanFile};
use crate::errors::{Error, Result};
use crate::{compiler_state::CompilerState, config::Config, saved_state::SavedStateLoader};
use common::{PerfLogEvent, PerfLogger};
use log::{debug, info, warn};
use serde_bser::value::Value;
use watchman_client::prelude::*;
use watchman_client::{Subscription as WatchmanSubscription, SubscriptionData};

pub struct FileSource<'config> {
    client: Client,
    config: &'config Config,
    resolved_root: ResolvedRoot,
}

#[derive(Debug)]
pub enum FileSourceSubscriptionNextChange {
    Result(FileSourceResult),
    SourceControlUpdateEnter,
    SourceControlUpdateLeave,
    None,
}

#[derive(Debug)]
pub struct FileSourceResult {
    pub files: Vec<WatchmanFile>,
    pub resolved_root: ResolvedRoot,
    pub clock: Clock,
    pub saved_state_info: Option<Value>,
}

impl<'config> FileSource<'config> {
    pub async fn connect(
        config: &'config Config,
        perf_logger_event: &impl PerfLogEvent,
    ) -> Result<FileSource<'config>> {
        let connect_timer = perf_logger_event.start("file_source_connect_time");
        let client = Connector::new().connect().await?;
        let canonical_root = CanonicalPath::canonicalize(&config.root_dir).map_err(|err| {
            Error::CanonicalizeRoot {
                root: config.root_dir.clone(),
                source: err,
            }
        })?;
        let resolved_root = client.resolve_root(canonical_root).await?;
        perf_logger_event.stop(connect_timer);

        Ok(Self {
            client,
            config,
            resolved_root,
        })
    }

    /// Executes a point query (as opposed to a subscription) to find all files
    /// to compile and returns the result.
    pub async fn query(
        &self,
        perf_logger_event: &impl PerfLogEvent,
        perf_logger: &impl PerfLogger,
    ) -> Result<CompilerState> {
        info!("querying files to compile...");
        let query_time = perf_logger_event.start("file_source_query_time");
        // If the saved state flag is passed, load from it or fail.
        if let Some(saved_state_path) = &self.config.load_saved_state_file {
            let mut compiler_state = perf_logger_event.time("deserialize_saved_state", || {
                CompilerState::deserialize_from_file(&saved_state_path)
            })?;
            let file_source_result = self
                .query_file_result(Some(compiler_state.clock.clone()), perf_logger_event)
                .await?;
            compiler_state
                .pending_file_source_changes
                .write()
                .unwrap()
                .push(file_source_result);
            compiler_state.merge_file_source_changes(
                &self.config,
                perf_logger_event,
                perf_logger,
                true,
            )?;
            perf_logger_event.stop(query_time);
            return Ok(compiler_state);
        }

        // If saved state is configured, try using saved state unless the config
        // forces a full build.
        if let Config {
            compile_everything: false,
            saved_state_config: Some(saved_state_config),
            saved_state_loader: Some(saved_state_loader),
            saved_state_version,
            ..
        } = self.config
        {
            match self
                .try_saved_state(
                    perf_logger,
                    perf_logger_event,
                    saved_state_config.clone(),
                    saved_state_loader,
                    saved_state_version,
                )
                .await
            {
                Ok(load_result) => {
                    perf_logger_event.stop(query_time);
                    return load_result;
                }
                Err(saved_state_failure) => {
                    warn!(
                        "Unable to load saved state, falling back to full build: {}",
                        saved_state_failure
                    );
                }
            }
        }

        // Finally, do a simple full query.
        let file_source_result = self.query_file_result(None, perf_logger_event).await?;
        let compiler_state = perf_logger_event.time("from_file_source_changes", || {
            CompilerState::from_file_source_changes(
                &self.config,
                &file_source_result,
                perf_logger_event,
                perf_logger,
            )
        })?;
        perf_logger_event.stop(query_time);
        Ok(compiler_state)
    }

    /// Starts a subscription sending updates since the given clock.
    pub async fn subscribe(
        self,
        perf_logger_event: &impl PerfLogEvent,
        perf_logger: &impl PerfLogger,
    ) -> Result<(CompilerState, FileSourceSubscription)> {
        let timer = perf_logger_event.start("file_source_subscribe_time");
        let compiler_state = self.query(perf_logger_event, perf_logger).await?;

        let expression = get_watchman_expr(&self.config);

        let file_source_result = self
            .query_file_result(Some(compiler_state.clock.clone()), perf_logger_event)
            .await?;

        let (subscription, _initial) = self
            .client
            .subscribe::<WatchmanFile>(
                &self.resolved_root,
                SubscribeRequest {
                    expression: Some(expression),
                    since: Some(file_source_result.clock.clone()),
                    drop: vec!["hg.update"],
                    ..Default::default()
                },
            )
            .await?;

        perf_logger_event.stop(timer);

        Ok((
            compiler_state,
            FileSourceSubscription {
                resolved_root: self.resolved_root.clone(),
                subscription,
            },
        ))
    }

    /// Internal method to issue a watchman query, returning a raw
    /// FileSourceResult.
    async fn query_file_result(
        &self,
        since_clock: Option<Clock>,
        perf_logger_event: &impl PerfLogEvent,
    ) -> Result<FileSourceResult> {
        let expression = get_watchman_expr(&self.config);

        let query_timer = perf_logger_event.start("watchman_query_time");
        // If `since` is available, we should not pass the `path` parameter.
        // Watchman ignores `since` parameter if both `path` and `since` are
        // passed as the request params
        let request = if since_clock.is_some() {
            QueryRequestCommon {
                expression: Some(expression),
                since: since_clock,
                ..Default::default()
            }
        } else {
            let query_roots = get_all_roots(&self.config)
                .into_iter()
                .map(PathGeneratorElement::RecursivePath)
                .collect();
            QueryRequestCommon {
                expression: Some(expression),
                path: Some(query_roots),
                ..Default::default()
            }
        };
        let query_result = self
            .client
            .query::<WatchmanFile>(&self.resolved_root, request)
            .await?;
        perf_logger_event.stop(query_timer);

        let files = query_result.files.ok_or_else(|| Error::EmptyQueryResult)?;
        Ok(FileSourceResult {
            files,
            resolved_root: self.resolved_root.clone(),
            clock: query_result.clock,
            saved_state_info: query_result.saved_state_info,
        })
    }

    /// Tries to load saved state with a watchman query.
    /// The return value is a nested Result:
    /// The outer Result indicates the result of a possible saved state infrastructure failure.
    /// The inner Result is a potential parse error.
    async fn try_saved_state(
        &self,
        perf_logger: &impl PerfLogger,
        perf_logger_event: &impl PerfLogEvent,
        saved_state_config: ScmAwareClockData,
        saved_state_loader: &Box<dyn SavedStateLoader + Send + Sync>,
        saved_state_version: &str,
    ) -> std::result::Result<Result<CompilerState>, &'static str> {
        let scm_since = Clock::ScmAware(FatClockData {
            clock: ClockSpec::null(),
            scm: Some(saved_state_config),
        });
        let file_source_result = self
            .query_file_result(Some(scm_since), perf_logger_event)
            .await
            .map_err(|_| "query failed")?;
        let saved_state_info = file_source_result
            .saved_state_info
            .as_ref()
            .ok_or("no saved state in watchman response")?;
        let saved_state_path = perf_logger_event.time("saved_state_loading_time", || {
            saved_state_loader
                .load(&saved_state_info)
                .ok_or("unable to load")
        })?;
        let mut compiler_state = perf_logger_event
            .time("deserialize_saved_state", || {
                CompilerState::deserialize_from_file(&saved_state_path)
            })
            .map_err(|err| {
                let error_event = perf_logger.create_event("saved_state_loader_error");
                error_event.string("error", format!("Failed to deserialize: {}", err));
                perf_logger.complete_event(error_event);
                perf_logger.flush();
                "failed to deserialize"
            })?;
        // For cases, where we want to debug saved state integration, that doesn't include
        // saved_state format changes we may need to disable this by adding this env variable
        if std::env::var("RELAY_COMPILER_IGNORE_SAVED_STATE_VERSION").is_err()
            && compiler_state.saved_state_version != saved_state_version
        {
            return Err("Saved state version doesn't match.");
        }
        compiler_state
            .pending_file_source_changes
            .write()
            .unwrap()
            .push(file_source_result);
        if let Err(parse_error) = perf_logger_event.time("merge_file_source_changes", || {
            compiler_state.merge_file_source_changes(
                &self.config,
                perf_logger_event,
                perf_logger,
                true,
            )
        }) {
            Ok(Err(parse_error))
        } else {
            Ok(Ok(compiler_state))
        }
    }
}

pub struct FileSourceSubscription {
    resolved_root: ResolvedRoot,
    subscription: WatchmanSubscription<WatchmanFile>,
}

impl FileSourceSubscription {
    /// Awaits changes from Watchman and provides the next set of changes
    /// if there were any changes to files
    pub async fn next_change(&mut self) -> Result<FileSourceSubscriptionNextChange> {
        match self.subscription.next().await? {
            SubscriptionData::FilesChanged(changes) => {
                if let Some(files) = changes.files {
                    debug!("number of files in this update: {}", files.len());
                    return Ok(FileSourceSubscriptionNextChange::Result(FileSourceResult {
                        files,
                        resolved_root: self.resolved_root.clone(),
                        clock: changes.clock,
                        saved_state_info: None,
                    }));
                }
            }
            SubscriptionData::StateEnter { state_name, .. } => {
                if state_name == "hg.update" {
                    debug!("hg.update started");
                    return Ok(FileSourceSubscriptionNextChange::SourceControlUpdateEnter);
                }
            }
            SubscriptionData::StateLeave { state_name, .. } => {
                if state_name == "hg.update" {
                    debug!("hg.update completed");
                    return Ok(FileSourceSubscriptionNextChange::SourceControlUpdateLeave);
                }
            }
            SubscriptionData::Canceled => {
                return Err(Error::WatchmanSubscriptionCanceled);
            }
        }
        Ok(FileSourceSubscriptionNextChange::None)
    }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Jordi Boggiano <j.boggiano@seld.be>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

/* last synced with: yes (GNU coreutils) 8.13 */

#[macro_use]
extern crate clap;
#[macro_use]
extern crate uucore;

use clap::Arg;
use std::borrow::Cow;
use std::io::{self, Write};
use uucore::zero_copy::ZeroCopyWriter;

// it's possible that using a smaller or larger buffer might provide better performance on some
// systems, but honestly this is good enough
const BUF_SIZE: usize = 16 * 1024;

pub fn uumain(args: impl uucore::Args) -> i32 {
    let app = app_from_crate!().arg(Arg::with_name("STRING").index(1).multiple(true));

    let matches = match app.get_matches_from_safe(args) {
        Ok(m) => m,
        Err(ref e)
            if e.kind == clap::ErrorKind::HelpDisplayed
                || e.kind == clap::ErrorKind::VersionDisplayed =>
        {
            println!("{}", e);
            return 0;
        }
        Err(f) => {
            show_error!("{}", f);
            return 1;
        }
    };

    let string = if let Some(values) = matches.values_of("STRING") {
        let mut result = values.fold(String::new(), |res, s| res + s + " ");
        result.pop();
        result.push('\n');
        Cow::from(result)
    } else {
        Cow::from("y\n")
    };

    let mut buffer = [0; BUF_SIZE];
    let bytes = prepare_buffer(&string, &mut buffer);

    exec(bytes);

    0
}

#[cfg(not(feature = "latency"))]
fn prepare_buffer<'a>(input: &'a str, buffer: &'a mut [u8; BUF_SIZE]) -> &'a [u8] {
    if input.len() < BUF_SIZE / 2 {
        let mut size = 0;
        while size < BUF_SIZE - input.len() {
            let (_, right) = buffer.split_at_mut(size);
            right[..input.len()].copy_from_slice(input.as_bytes());
            size += input.len();
        }
        &buffer[..size]
    } else {
        input.as_bytes()
    }
}

#[cfg(feature = "latency")]
fn prepare_buffer<'a>(input: &'a str, _buffer: &'a mut [u8; BUF_SIZE]) -> &'a [u8] {
    input.as_bytes()
}

pub fn exec(bytes: &[u8]) {
    let mut stdin_raw = io::stdout();
    let mut writer = ZeroCopyWriter::with_default(&mut stdin_raw, |stdin| stdin.lock());
    loop {
        // TODO: needs to check if pipe fails
        writer.write_all(bytes).unwrap();
    }
}
<commit_msg>yes: correct a typo (#1727)<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Jordi Boggiano <j.boggiano@seld.be>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

/* last synced with: yes (GNU coreutils) 8.13 */

#[macro_use]
extern crate clap;
#[macro_use]
extern crate uucore;

use clap::Arg;
use std::borrow::Cow;
use std::io::{self, Write};
use uucore::zero_copy::ZeroCopyWriter;

// it's possible that using a smaller or larger buffer might provide better performance on some
// systems, but honestly this is good enough
const BUF_SIZE: usize = 16 * 1024;

pub fn uumain(args: impl uucore::Args) -> i32 {
    let app = app_from_crate!().arg(Arg::with_name("STRING").index(1).multiple(true));

    let matches = match app.get_matches_from_safe(args) {
        Ok(m) => m,
        Err(ref e)
            if e.kind == clap::ErrorKind::HelpDisplayed
                || e.kind == clap::ErrorKind::VersionDisplayed =>
        {
            println!("{}", e);
            return 0;
        }
        Err(f) => {
            show_error!("{}", f);
            return 1;
        }
    };

    let string = if let Some(values) = matches.values_of("STRING") {
        let mut result = values.fold(String::new(), |res, s| res + s + " ");
        result.pop();
        result.push('\n');
        Cow::from(result)
    } else {
        Cow::from("y\n")
    };

    let mut buffer = [0; BUF_SIZE];
    let bytes = prepare_buffer(&string, &mut buffer);

    exec(bytes);

    0
}

#[cfg(not(feature = "latency"))]
fn prepare_buffer<'a>(input: &'a str, buffer: &'a mut [u8; BUF_SIZE]) -> &'a [u8] {
    if input.len() < BUF_SIZE / 2 {
        let mut size = 0;
        while size < BUF_SIZE - input.len() {
            let (_, right) = buffer.split_at_mut(size);
            right[..input.len()].copy_from_slice(input.as_bytes());
            size += input.len();
        }
        &buffer[..size]
    } else {
        input.as_bytes()
    }
}

#[cfg(feature = "latency")]
fn prepare_buffer<'a>(input: &'a str, _buffer: &'a mut [u8; BUF_SIZE]) -> &'a [u8] {
    input.as_bytes()
}

pub fn exec(bytes: &[u8]) {
    let mut stdout_raw = io::stdout();
    let mut writer = ZeroCopyWriter::with_default(&mut stdout_raw, |stdout| stdout.lock());
    loop {
        // TODO: needs to check if pipe fails
        writer.write_all(bytes).unwrap();
    }
}
<|endoftext|>


<commit_before>use ncurses;

use color;
use vec::Vec2;
use view::{View,SizeRequest};
use event::EventResult;
use printer::Printer;

/// Displays an editable text.
pub struct EditView {
    content: String,
    cursor: usize,
    multiline: bool,
    min_length: usize,
}

impl EditView {
    /// Creates a new, empty edit view.
    pub fn new() -> Self {
        EditView {
            content: String::new(),
            cursor: 0,
            multiline: false,
            min_length: 1,
        }
    }

    /// Replace the entire content of the view with the given one.
    pub fn set_content<'a>(&mut self, content: &'a str) {
        self.content = content.to_string();
    }

    /// Get the current text.
    pub fn get_content(&self) -> &str {
        &self.content
    }

    /// Sets the current content to the given value. Convenient chainable method.
    pub fn content<'a>(mut self, content: &'a str) -> Self {
        self.set_content(content);
        self
    }

    /// Sets the minimum length for this view.
    /// (This applies to the layout, not the content.)
    pub fn min_length(mut self, min_length: usize) -> Self {
        self.min_length = min_length;

        self
    }
}

fn read_char(ch: i32) -> Option<char> {
    // Printable ascii range: 32-126
    if ch >= ' ' as i32 && ch <= '~' as i32 {
        Some(ch as u8 as char)
    } else {
        None
    }
}

impl View for EditView {
    fn draw(&mut self, printer: &Printer, focused: bool) {
        let style = if focused { color::HIGHLIGHT } else { color::HIGHLIGHT_INACTIVE };
        printer.with_style(style, |printer| {
            printer.print((0,0), &self.content);
        });
    }

    fn get_min_size(&self, req: SizeRequest) -> Vec2 {
        Vec2::new(self.min_length, 1)
    }

    fn take_focus(&mut self) -> bool {
        true
    }

    fn on_key_event(&mut self, ch: i32) -> EventResult {

        if let Some(ch) = read_char(ch) {
            self.content.insert(self.cursor, ch);
            self.cursor += 1;
            return EventResult::Consumed(None);
        }

        match ch {
            ncurses::KEY_HOME => self.cursor = 0,
            ncurses::KEY_END => self.cursor = self.content.len(),
            ncurses::KEY_LEFT if self.cursor > 0 => self.cursor -= 1,
            ncurses::KEY_RIGHT if self.cursor < self.content.len() => self.cursor += 1,
            127 if self.cursor > 0 => { self.cursor -= 1; self.content.remove(self.cursor); },
            330 if self.cursor < self.content.len() => { self.content.remove(self.cursor); },
            _ => return EventResult::Ignored,
        }

        EventResult::Consumed(None)
    }
}
<commit_msg>Fix warnings<commit_after>use ncurses;

use color;
use vec::Vec2;
use view::{View,SizeRequest};
use event::EventResult;
use printer::Printer;

/// Displays an editable text.
pub struct EditView {
    content: String,
    cursor: usize,
    min_length: usize,
}

impl EditView {
    /// Creates a new, empty edit view.
    pub fn new() -> Self {
        EditView {
            content: String::new(),
            cursor: 0,
            min_length: 1,
        }
    }

    /// Replace the entire content of the view with the given one.
    pub fn set_content<'a>(&mut self, content: &'a str) {
        self.content = content.to_string();
    }

    /// Get the current text.
    pub fn get_content(&self) -> &str {
        &self.content
    }

    /// Sets the current content to the given value. Convenient chainable method.
    pub fn content<'a>(mut self, content: &'a str) -> Self {
        self.set_content(content);
        self
    }

    /// Sets the minimum length for this view.
    /// (This applies to the layout, not the content.)
    pub fn min_length(mut self, min_length: usize) -> Self {
        self.min_length = min_length;

        self
    }
}

fn read_char(ch: i32) -> Option<char> {
    // Printable ascii range: 32-126
    if ch >= ' ' as i32 && ch <= '~' as i32 {
        Some(ch as u8 as char)
    } else {
        None
    }
}

impl View for EditView {
    fn draw(&mut self, printer: &Printer, focused: bool) {
        let style = if focused { color::HIGHLIGHT } else { color::HIGHLIGHT_INACTIVE };
        printer.with_style(style, |printer| {
            printer.print((0,0), &self.content);
        });
    }

    fn get_min_size(&self, _: SizeRequest) -> Vec2 {
        Vec2::new(self.min_length, 1)
    }

    fn take_focus(&mut self) -> bool {
        true
    }

    fn on_key_event(&mut self, ch: i32) -> EventResult {

        if let Some(ch) = read_char(ch) {
            self.content.insert(self.cursor, ch);
            self.cursor += 1;
            return EventResult::Consumed(None);
        }

        match ch {
            ncurses::KEY_HOME => self.cursor = 0,
            ncurses::KEY_END => self.cursor = self.content.len(),
            ncurses::KEY_LEFT if self.cursor > 0 => self.cursor -= 1,
            ncurses::KEY_RIGHT if self.cursor < self.content.len() => self.cursor += 1,
            127 if self.cursor > 0 => { self.cursor -= 1; self.content.remove(self.cursor); },
            330 if self.cursor < self.content.len() => { self.content.remove(self.cursor); },
            _ => return EventResult::Ignored,
        }

        EventResult::Consumed(None)
    }
}
<|endoftext|>


<commit_before>use webcore::value::Reference;
use webapi::event_target::{IEventTarget, EventTarget};
use webapi::node::{INode, Node};
use webapi::token_list::TokenList;
use webapi::node_list::NodeList;

/// The `IElement` interface represents an object of a [Document](struct.Document.html).
/// This interface describes methods and properties common to all
/// kinds of elements.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element)
pub trait IElement: IEventTarget {
    /// The Element.classList is a read-only property which returns a live
    /// [TokenList](struct.TokenList.html) collection of the class attributes
    /// of the element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList)
    fn class_list( &self ) -> TokenList {
        unsafe {
            js!( return @{self.as_ref()}.classList; ).into_reference_unchecked().unwrap()
        }
    }

    /// Returns the first element that is a descendant of the element on which it is
    /// invoked that matches the specified group of selectors.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector)
    fn query_selector( &self, selector: &str ) -> Option< Element > {
        // TODO: This can throw an exception in case of an invalid selector;
        //       convert the return type to a Result.
        unsafe {
            js!( return @{self.as_ref()}.querySelector( @{selector} ); ).into_reference_unchecked()
        }
    }

    /// Returns a non-live [NodeList](struct.NodeList.html) of all elements descended
    /// from the element on which it is invoked that matches the specified group of CSS selectors.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll)
    fn query_selector_all( &self, selector: &str ) -> NodeList {
        unsafe {
            js!( return @{self.as_ref()}.querySelectorAll( @{selector} ); ).into_reference_unchecked().unwrap()
        }
    }
}

/// A reference to a JavaScript object which implements the [IElement](trait.IElement.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element)
pub struct Element( Reference );

impl IEventTarget for Element {}
impl INode for Element {}
impl IElement for Element {}

reference_boilerplate! {
    Element,
    instanceof Element
    convertible to EventTarget
    convertible to Node
}
<commit_msg>IElement should inherit from INode<commit_after>use webcore::value::Reference;
use webapi::event_target::{IEventTarget, EventTarget};
use webapi::node::{INode, Node};
use webapi::token_list::TokenList;
use webapi::node_list::NodeList;

/// The `IElement` interface represents an object of a [Document](struct.Document.html).
/// This interface describes methods and properties common to all
/// kinds of elements.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element)
pub trait IElement: INode {
    /// The Element.classList is a read-only property which returns a live
    /// [TokenList](struct.TokenList.html) collection of the class attributes
    /// of the element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList)
    fn class_list( &self ) -> TokenList {
        unsafe {
            js!( return @{self.as_ref()}.classList; ).into_reference_unchecked().unwrap()
        }
    }

    /// Returns the first element that is a descendant of the element on which it is
    /// invoked that matches the specified group of selectors.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector)
    fn query_selector( &self, selector: &str ) -> Option< Element > {
        // TODO: This can throw an exception in case of an invalid selector;
        //       convert the return type to a Result.
        unsafe {
            js!( return @{self.as_ref()}.querySelector( @{selector} ); ).into_reference_unchecked()
        }
    }

    /// Returns a non-live [NodeList](struct.NodeList.html) of all elements descended
    /// from the element on which it is invoked that matches the specified group of CSS selectors.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll)
    fn query_selector_all( &self, selector: &str ) -> NodeList {
        unsafe {
            js!( return @{self.as_ref()}.querySelectorAll( @{selector} ); ).into_reference_unchecked().unwrap()
        }
    }
}

/// A reference to a JavaScript object which implements the [IElement](trait.IElement.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element)
pub struct Element( Reference );

impl IEventTarget for Element {}
impl INode for Element {}
impl IElement for Element {}

reference_boilerplate! {
    Element,
    instanceof Element
    convertible to EventTarget
    convertible to Node
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use webcore::try_from::{TryFrom, TryInto};
use webcore::value::{Reference, Value, ConversionError};
use webcore::serialization::{JsSerialize, deserialize_object, deserialize_object_to_iter};

/// A type representing a JavaScript object.
#[derive(Clone, PartialEq, Eq, Debug, ReferenceType)]
#[reference(instance_of = "Object")]
pub struct Object( Reference );

impl Object {
    /// Returns the number of elements in this particular object.
    pub fn len( &self ) -> usize {
        js!(
            return Object.keys( @{self} ).length;
        ).try_into().unwrap()
    }

    /// Retrieves an iterator over this object's keys and values.
    ///
    /// When called, this method will pull all the objecy's keys and values
    /// from JavaScript, then return an iterator which accesses them in pairs.
    ///
    /// # Example:
    ///
    /// ```
    /// # fn main() -> Result< (), Box< dyn std::error::Error > > {
    /// # use std::collections::HashMap;
    /// use stdweb::{ js, unstable::TryInto, Object };
    ///
    /// let obj: Object = js!( return { [1]: 2 } ).try_into()?;
    ///
    /// let map: HashMap< i32, i32 > = obj
    ///     .to_iter()
    ///     .map( |(k, v)| Ok( ( k.parse()?, v.try_into()? ) ) )
    ///     .collect::< Result< _, Box< dyn std::error::Error > > >()?;
    ///
    /// assert_eq!( map[ &1 ], 2 );
    /// panic!("ahhh");
    /// # Ok( () )
    /// # }
    /// ```
    pub fn to_iter( &self ) -> impl ExactSizeIterator < Item = ( String, Value ) > {
        deserialize_object_to_iter( self.as_ref() )
    }
}

impl From< Object > for BTreeMap< String, Value > {
    fn from( object: Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< 'a > From< &'a Object > for BTreeMap< String, Value > {
    fn from( object: &'a Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< 'a > From< &'a mut Object > for BTreeMap< String, Value > {
    fn from( object: &'a mut Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl From< Object > for HashMap< String, Value > {
    fn from( object: Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< 'a > From< &'a Object > for HashMap< String, Value > {
    fn from( object: &'a Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< 'a > From< &'a mut Object > for HashMap< String, Value > {
    fn from( object: &'a mut Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< K: AsRef< str >, V: JsSerialize > From< BTreeMap< K, V > > for Object {
    #[inline]
    fn from( value: BTreeMap< K, V > ) -> Self {
        (&value).into()
    }
}

impl< 'a, K, V > From< &'a BTreeMap< K, V > > for Object where K: AsRef< str >, V: JsSerialize {
    #[inline]
    fn from( value: &'a BTreeMap< K, V > ) -> Self {
        // TODO: Do something more efficient here?
        let value = js! {
            return @{value};
        };

        match value {
            Value::Reference( reference ) => Object( reference ),
            _ => unreachable!()
        }
    }
}

impl< 'a, K, V > From< &'a mut BTreeMap< K, V > > for Object where K: AsRef< str >, V: JsSerialize {
    #[inline]
    fn from( value: &'a mut BTreeMap< K, V > ) -> Self {
        let value: &BTreeMap< K, V > = value;
        value.into()
    }
}

impl< K, V > From< HashMap< K, V > > for Object where K: AsRef< str > + Hash + Eq, V: JsSerialize {
    #[inline]
    fn from( value: HashMap< K, V > ) -> Self {
        (&value).into()
    }
}

impl< 'a, K, V > From< &'a HashMap< K, V > > for Object where K: AsRef< str > + Hash + Eq, V: JsSerialize {
    #[inline]
    fn from( value: &'a HashMap< K, V > ) -> Self {
        // TODO: Do something more efficient here?
        let value = js! {
            return @{value};
        };

        match value {
            Value::Reference( reference ) => Object( reference ),
            _ => unreachable!()
        }
    }
}

impl< 'a, K: Hash + Eq, V > From< &'a mut HashMap< K, V > > for Object where K: AsRef< str >, V: JsSerialize {
    #[inline]
    fn from( value: &'a mut HashMap< K, V > ) -> Self {
        let value: &HashMap< K, V > = value;
        value.into()
    }
}

impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E > > TryFrom< Object > for BTreeMap< String, V > {
    type Error = ConversionError;

    fn try_from( object: Object ) -> Result< Self, Self::Error > {
        deserialize_object( object.as_ref(), |deserializer| -> Result< BTreeMap< String, V >, E > {
            let mut output = BTreeMap::new();
            for (key, value) in deserializer {
                output.insert( key, value.try_into()? );
            }
            Ok( output )
        }).map_err( |err| err.into() )
    }
}

impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E > > TryFrom< Object > for HashMap< String, V > {
    type Error = ConversionError;

    fn try_from( object: Object ) -> Result< Self, Self::Error > {
        deserialize_object( object.as_ref(), |deserializer| -> Result< HashMap< String, V >, E > {
            let mut output = HashMap::with_capacity( deserializer.len() );
            for (key, value) in deserializer {
                output.insert( key, value.try_into()? );
            }

            Ok( output )
        }).map_err( |err| err.into() )
    }
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;

    use stdweb::{ js, unstable::TryInto, Object };

    /// This duplicates and tests the example in `Object::to_iter` documentation.
    #[test]
    fn test_object_to_iter() -> Result< (), Box< dyn std::error::Error > > {
        let obj: Object = js!( return { [1]: 2 } ).try_into()?;

        let map: HashMap< i32, i32 > = obj
            .to_iter()
            .map( |(k, v)| Ok( ( k.parse()?, v.try_into()? ) ) )
            .collect::< Result< _, Box< dyn std::error::Error > > >()?;

        assert_eq!( map[ &1 ], 2 );

        Ok( () )
    }
}
<commit_msg>Restore compatibility with `wasm-bindgen` test runner<commit_after>use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use webcore::try_from::{TryFrom, TryInto};
use webcore::value::{Reference, Value, ConversionError};
use webcore::serialization::{JsSerialize, deserialize_object, deserialize_object_to_iter};

/// A type representing a JavaScript object.
#[derive(Clone, PartialEq, Eq, Debug, ReferenceType)]
#[reference(instance_of = "Object")]
pub struct Object( Reference );

impl Object {
    /// Returns the number of elements in this particular object.
    pub fn len( &self ) -> usize {
        js!(
            return Object.keys( @{self} ).length;
        ).try_into().unwrap()
    }

    /// Retrieves an iterator over this object's keys and values.
    ///
    /// When called, this method will pull all the objecy's keys and values
    /// from JavaScript, then return an iterator which accesses them in pairs.
    ///
    /// # Example:
    ///
    /// ```
    /// # fn main() -> Result< (), Box< dyn std::error::Error > > {
    /// # use std::collections::HashMap;
    /// use stdweb::{ js, unstable::TryInto, Object };
    ///
    /// let obj: Object = js!( return { [1]: 2 } ).try_into()?;
    ///
    /// let map: HashMap< i32, i32 > = obj
    ///     .to_iter()
    ///     .map( |(k, v)| Ok( ( k.parse()?, v.try_into()? ) ) )
    ///     .collect::< Result< _, Box< dyn std::error::Error > > >()?;
    ///
    /// assert_eq!( map[ &1 ], 2 );
    /// panic!("ahhh");
    /// # Ok( () )
    /// # }
    /// ```
    pub fn to_iter( &self ) -> impl ExactSizeIterator < Item = ( String, Value ) > {
        deserialize_object_to_iter( self.as_ref() )
    }
}

impl From< Object > for BTreeMap< String, Value > {
    fn from( object: Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< 'a > From< &'a Object > for BTreeMap< String, Value > {
    fn from( object: &'a Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< 'a > From< &'a mut Object > for BTreeMap< String, Value > {
    fn from( object: &'a mut Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl From< Object > for HashMap< String, Value > {
    fn from( object: Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< 'a > From< &'a Object > for HashMap< String, Value > {
    fn from( object: &'a Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< 'a > From< &'a mut Object > for HashMap< String, Value > {
    fn from( object: &'a mut Object ) -> Self {
        deserialize_object( &object.0, |iter| iter.collect() )
    }
}

impl< K: AsRef< str >, V: JsSerialize > From< BTreeMap< K, V > > for Object {
    #[inline]
    fn from( value: BTreeMap< K, V > ) -> Self {
        (&value).into()
    }
}

impl< 'a, K, V > From< &'a BTreeMap< K, V > > for Object where K: AsRef< str >, V: JsSerialize {
    #[inline]
    fn from( value: &'a BTreeMap< K, V > ) -> Self {
        // TODO: Do something more efficient here?
        let value = js! {
            return @{value};
        };

        match value {
            Value::Reference( reference ) => Object( reference ),
            _ => unreachable!()
        }
    }
}

impl< 'a, K, V > From< &'a mut BTreeMap< K, V > > for Object where K: AsRef< str >, V: JsSerialize {
    #[inline]
    fn from( value: &'a mut BTreeMap< K, V > ) -> Self {
        let value: &BTreeMap< K, V > = value;
        value.into()
    }
}

impl< K, V > From< HashMap< K, V > > for Object where K: AsRef< str > + Hash + Eq, V: JsSerialize {
    #[inline]
    fn from( value: HashMap< K, V > ) -> Self {
        (&value).into()
    }
}

impl< 'a, K, V > From< &'a HashMap< K, V > > for Object where K: AsRef< str > + Hash + Eq, V: JsSerialize {
    #[inline]
    fn from( value: &'a HashMap< K, V > ) -> Self {
        // TODO: Do something more efficient here?
        let value = js! {
            return @{value};
        };

        match value {
            Value::Reference( reference ) => Object( reference ),
            _ => unreachable!()
        }
    }
}

impl< 'a, K: Hash + Eq, V > From< &'a mut HashMap< K, V > > for Object where K: AsRef< str >, V: JsSerialize {
    #[inline]
    fn from( value: &'a mut HashMap< K, V > ) -> Self {
        let value: &HashMap< K, V > = value;
        value.into()
    }
}

impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E > > TryFrom< Object > for BTreeMap< String, V > {
    type Error = ConversionError;

    fn try_from( object: Object ) -> Result< Self, Self::Error > {
        deserialize_object( object.as_ref(), |deserializer| -> Result< BTreeMap< String, V >, E > {
            let mut output = BTreeMap::new();
            for (key, value) in deserializer {
                output.insert( key, value.try_into()? );
            }
            Ok( output )
        }).map_err( |err| err.into() )
    }
}

impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E > > TryFrom< Object > for HashMap< String, V > {
    type Error = ConversionError;

    fn try_from( object: Object ) -> Result< Self, Self::Error > {
        deserialize_object( object.as_ref(), |deserializer| -> Result< HashMap< String, V >, E > {
            let mut output = HashMap::with_capacity( deserializer.len() );
            for (key, value) in deserializer {
                output.insert( key, value.try_into()? );
            }

            Ok( output )
        }).map_err( |err| err.into() )
    }
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;

    use stdweb::{ js, unstable::TryInto, Object };

    /// This duplicates and tests the example in `Object::to_iter` documentation.
    #[test]
    fn test_object_to_iter() {
        let obj: Object = js!( return { [1]: 2 } ).try_into().unwrap();

        let map: HashMap< i32, i32 > = obj
            .to_iter()
            .map( |(k, v)| Ok( ( k.parse()?, v.try_into()? ) ) )
            .collect::< Result< _, Box< dyn std::error::Error > > >().unwrap();

        assert_eq!( map[ &1 ], 2 );
    }
}
<|endoftext|>


<commit_before>use frappe::Sink;
use rand::Rng;
use std::thread;
use std::time::Duration;

fn main() {
    let sink = Sink::new();

    let result = sink
        .stream()
        // we'll do this part on another thread
        .map_n(move |arg, sender| {
            let n = *arg;
            let main_th = thread::current();
            // our expensive computation (sleep sort)
            thread::spawn(move || {
                thread::sleep(Duration::from_millis(n));
                sender.send(n);
                main_th.unpark(); // signal that there is data available
            });
        })
        // the rest of the chain continues on the main thread as normal
        .collect::<Vec<_>>();

    // now send some random values
    let mut rng = rand::thread_rng();
    sink.feed((0..10).map(|_| rng.gen_range(0, 100)));

    // receive the results on the main thread
    loop {
        thread::park();
        let res = result.sample();
        println!("{:?}", res);
        if res.len() >= 10 {
            break;
        }
    }
}
<commit_msg>improved the async example<commit_after>use frappe::Sink;
use rand::distributions::Uniform;
use rand::Rng;
use std::thread;
use std::time::Duration;

fn main() {
    let sink = Sink::new();

    // build the chain on the main thread
    let result = sink
        .stream()
        // we'll do this part on another thread
        .map_n(|arg, sender| {
            let n = *arg;
            // our expensive computation (sleep sort)
            thread::spawn(move || {
                thread::sleep(Duration::from_millis(n));
                sender.send(n); // return the computed value
            });
        })
        // the rest of the stream chain is executed on the thread that called `Sender::send`
        .fold(Vec::new(), |mut vec, n| {
            vec.push(*n);
            vec
        });

    // now send some random values
    let mut rng = rand::thread_rng();
    let input: Vec<_> = rng
        .sample_iter(&Uniform::new_inclusive(0, 100))
        .take(10)
        .collect();
    println!("input:  {:?}", input);
    sink.feed(input);

    // wait a bit for the threads to finish
    thread::sleep(Duration::from_millis(150));

    // receive the results on the main thread
    println!("result: {:?}", result.sample());
}
<|endoftext|>


<commit_before>//! Processor
//!
//! ## Terminololgy
//! * Evaluator - a code fragment to evaluate an expression
//! * Processor - A list of evaluators
//!
//! ## Phases for Generation
//!

use std::rc::Rc;

use common::err::{Error, Result, Void, void_ok};
use common::func::{
	NoArgFn,
	UnaryFn,
	BinaryFn,
	TrinityFn
};
use common::plugin::{
	FuncRegistry,
	TypeRegistry
};
use common::rows::{
	MiniPage,
	Page,
	PageBuilder,
	PageId
};
use common::session::Session;
use common::types::*;
use plan::expr::*;
use plan::expr::visitor::{accept_by_default, Visitor};

use driver::DriverContext;

pub trait Processor
{
  fn process(
    &self,
    input: &Page,
    builder: &mut PageBuilder) -> Void;
}

pub trait Evaluator
{
	fn evaluate<'p>(&self, input: &'p Page) -> Result<&'p MiniPage>;

	fn ty(&self) -> &Ty;
}

pub struct NoArgFnEvaluator
{
	f: NoArgFn,
	output_pid: PageId
}

pub struct UnaryFnEvaluator
{
	f: UnaryFn,
	input_pid: PageId,
	output_pid: PageId
}

pub struct BinaryFnEvaluator
{
	f: BinaryFn,
	lhs_pid: PageId,
	rhs_pid: PageId,
	output_pid: PageId
}

#[derive(Clone)]
pub struct FieldEvaluator
{
	idx: usize,
	ty:  Ty
}

impl Evaluator for FieldEvaluator
{
	fn evaluate<'p>(&self, input: &'p Page) -> Result<&'p MiniPage>
	{
		Ok(input.minipage(self.idx))
	}

	fn ty(&self) -> &Ty
	{
		&self.ty
	}
}

pub struct Interpreter<'a>
{
	types: &'a Vec<Ty>,
	names: &'a Vec<&'a str>,
	stack: Vec<Box<Evaluator>>,
	error: Option<Error>
}

impl<'a> Interpreter<'a>
{
	fn new(session: &Session,
		     types: &'a Vec<Ty>,
		     names: &'a Vec<&'a str>) -> Interpreter<'a> {
		Interpreter {
			types : types,
			names : names,
			stack : Vec::new(),
			error : None
		}
	}

	pub fn build(session:  &'a Session,
					  input_types: &'a Vec<Ty>,
					  input_names: &'a Vec<&'a str>,
					  expression : &Expr) -> Result<Box<Evaluator>>
	{
		let mut interpreter = Interpreter::new(session, input_types, input_names);
		interpreter.accept(expression);

		match interpreter.stack.len() {
			len if len == 1 => Ok(interpreter.stack.pop().unwrap()),
			len if len > 1  => panic!("more than one stack item still remains in interpreter"),
			_               => panic!("no more stack item in interpreter")
		}
  }

	pub fn Not(&self, c: &Expr)
	{
	}

	pub fn IsNull(&self, c: &Expr)
	{
	}

	pub fn IsNotNull(&self, c: &Expr)
	{
	}

	pub fn PlusSign(&self, c: &Expr)
	{
	}

	pub fn MinusSign(&self, c: &Expr)
	{
	}

	pub fn Cast(&self, c: &Expr, f: &Ty, t: &Ty)
	{
	}

	pub fn And(&self, lhs: &Expr, rhs: &Expr)
	{
	}

	pub fn Or(&self, lhs: &Expr, rhs: &Expr)
	{
	}

	pub fn Cmp(&self, op: &CmpOp, lhs: &Expr, rhs: &Expr)
	{
	}

	pub fn Arithm(&self, op: &ArithmOp, lhs: &Expr, rhs: &Expr)
	{
	}

	pub fn Func(&self, f: &FnDecl, args: &Vec<Box<Expr>>)
	{
	}

	pub fn Field(&mut self, ty: &Ty, name: &str)
	{
		let found: Option<(usize, &Ty, &&str)>;

		found = izip!(0 .. self.types.len(), self.types, self.names)
						.find(|&(i, t, n)| *n == name);

    let eval = match found {
    	Some(f) => FieldEvaluator {idx: f.0, ty: f.1.clone()},
    	None    => panic!("no such field for {}", name)
    };

		self.stack.push(Box::new(eval));
	}
}

impl<'a> visitor::Visitor for Interpreter<'a>
{
	fn accept(&mut self, e: &Expr)
	{
	  match *e.kind() {
	    ExprKind::Not      (ref c)               => self.Not(c),
	    ExprKind::IsNull   (ref c)               => self.IsNull(c),
	    ExprKind::IsNotNull(ref c)               => self.IsNotNull(c),
	    ExprKind::PlusSign (ref c)               => self.PlusSign(c),
	    ExprKind::MinusSign(ref c)               => self.MinusSign(c),
	    ExprKind::Cast     (ref c, ref f, ref t) => self.Cast(c, f, t),

	    ExprKind::And      (ref l, ref r)        => self.And(l, r),
	    ExprKind::Or       (ref l, ref r)        => self.And(l, r),
	    ExprKind::Cmp      (ref o, ref l, ref r) => self.Cmp(o, l, r),
	    ExprKind::Arithm   (ref o, ref l, ref r) => self.Arithm(o, l, r),

	    ExprKind::Fn     (ref f, ref args)  => self.Func(f, args),
			ExprKind::Field  (ref name)         => self.Field(e.ty(), name),
			/*
	    ExprKind::Const  (_)            => {}

	    ExprKind::Switch(ref cases, ref default) => {
	    	for c in cases.iter() {
	    		v.accept(c);
	   	  }

	    	v.accept(default);
	    },

	    ExprKind::Case   (ref l, ref r) => { v.accept(l); v.accept(r) },*/
	    _ => panic!("")
	  }
	}
}

pub type Schema<'a, 'b> = (&'a Vec<Ty>, &'a Vec<&'b str>);

pub struct InterpreterProcessor
{
	evals: Vec<Box<Evaluator>>
}

impl InterpreterProcessor
{
	pub fn new(session: &Session,
		         schema : &Schema,
		         exprs  : &Vec<Box<Expr>>) -> Result<InterpreterProcessor>
	{
		let evals = try!(
			exprs.iter()
		       .map(|e| Interpreter::build(session, schema.0, schema.1, e))
		       .collect::<Result<Vec<Box<Evaluator>>>>()
    );

		Ok(InterpreterProcessor { evals: evals })
	}
}

impl Processor for InterpreterProcessor
{
	fn process(
    &self,
    input: &Page,
    builder: &mut PageBuilder) -> Void
	{
  	for e in self.evals.iter() {
  		try!(e.evaluate(input));
  	}

  	void_ok
  }
}

#[cfg(test)]
mod tests {
	use common::rows::{
		Page,
		PageBuilder,
		PageId
	};
	use common::plugin::*;
	use common::session::Session;
	use common::storage::{RandomTable, MemTable};
	use common::types::*;

	use plan::expr::*;
	use driver::DriverContext;

	use super::*;

	#[test]
	pub fn tpch_q1() {
		let plugin_mgr = PluginManager::new();

		/*
			l_orderkey long,
			l_partkey long,
			l_suppkey long,
			l_linenumber int,
			l_quantity double,
			l_extendedprice double,
			l_discount double,
			l_tax double,
			l_returnflag string,
			l_linestatus string,
			l_shipdate string,
			l_commitdate string,
			l_receiptdate string,
			l_shipinstruct string,
			l_shipmode string,
			l_comment string
		*/
		let tb_types: Vec<Ty> = vec![
	    i64_ty(), // l_orderkey      bigint
	    i64_ty(), // l_partkey       bigint
	    i64_ty(), // l_suppkey       bigint
	    i32_ty(), // l_linenumber    int
	    f64_ty(), // l_quantity      double,
	    f64_ty(), // l_extendedprice double,
	    f64_ty(), // l_discount      double,
	    f64_ty(), // l_tax           double,
	    // string types are not implmeneted yet.
	  ];

	  let tb_field_names: Vec<&str> = vec![
	  	"l_orderkey",
	  	"l_partkey",
	  	"l_suppkey",
	  	"l_linenumber",
	  	"l_quantity",
	  	"l_extendedprice",
	  	"l_discount",
	  	"l_tax"
	  ];

		/*
	  let sum_disc_price =
	  	Mul(
	  		&f64_ty(), Field(&f64_ty(), "l_extendedprice"), Subtract(&f64_ty(), Const(1), Field(&f64_ty(), "l_discount")));

  	let sum_charge =
	  	Mul(&f64_ty(), sum_disc_price.clone(), Plus(&f64_ty(), Const(1), Field(&f64_ty(), "l_tax")));*/

		let l_quantity = Field(&f64_ty(), "l_quantity");

	  let exprs = vec![
//	  	Box::new(sum_disc_price),
//	  	Box::new(sum_charge)
				Box::new(l_quantity)
  	];

  	let schema = (&tb_types, &tb_field_names);
  	let session    = Session;

		let processor = InterpreterProcessor::new(&session, &schema, &exprs).ok().unwrap();
		let mut input  = RandomTable::new(&session, &tb_types, 1024);

		let output_tys = exprs.iter()
											.map(|e| e.ty().clone())
											.collect::<Vec<Ty>>();
		let mut output = MemTable::new(&session, &output_tys, &vec!["x","y"]);

		let mut builder = PageBuilder::new(&output_tys);

		loop {
		  let mut read_page = input.next().unwrap();

		  if read_page.value_count() == 0 {
		  	break;
		  }

		  processor.process(read_page, &mut builder);
		  output.write(builder.build(read_page.value_count()));
		  builder.reset();
		}

		assert_eq!(1, output.col_num());
		assert_eq!(1024, output.row_num());
	}
}<commit_msg>Improve tpch_q1 test in processor.rs.<commit_after>//! Processor
//!
//! ## Terminololgy
//! * Evaluator - a code fragment to evaluate an expression
//! * Processor - A list of evaluators
//!
//! ## Phases for Generation
//!

use std::rc::Rc;

use common::err::{Error, Result, Void, void_ok};
use common::func::{
	NoArgFn,
	UnaryFn,
	BinaryFn,
	TrinityFn
};
use common::plugin::{
	FuncRegistry,
	TypeRegistry
};
use common::rows::{
	MiniPage,
	Page,
	PageBuilder,
	PageId
};
use common::session::Session;
use common::types::*;
use plan::expr::*;
use plan::expr::visitor::{accept_by_default, Visitor};

use driver::DriverContext;

pub trait Processor
{
  fn process(
    &self,
    input: &Page,
    builder: &mut PageBuilder) -> Void;
}

pub trait Evaluator
{
	fn evaluate<'p>(&self, input: &'p Page) -> Result<&'p MiniPage>;

	fn ty(&self) -> &Ty;
}

pub struct NoArgFnEvaluator
{
	f: NoArgFn,
	output_pid: PageId
}

pub struct UnaryFnEvaluator
{
	f: UnaryFn,
	input_pid: PageId,
	output_pid: PageId
}

pub struct BinaryFnEvaluator
{
	f: BinaryFn,
	lhs_pid: PageId,
	rhs_pid: PageId,
	output_pid: PageId
}

#[derive(Clone)]
pub struct FieldEvaluator
{
	idx: usize,
	ty:  Ty
}

impl Evaluator for FieldEvaluator
{
	fn evaluate<'p>(&self, input: &'p Page) -> Result<&'p MiniPage>
	{
		Ok(input.minipage(self.idx))
	}

	fn ty(&self) -> &Ty
	{
		&self.ty
	}
}

pub struct Interpreter<'a>
{
	types: &'a Vec<Ty>,
	names: &'a Vec<&'a str>,
	stack: Vec<Box<Evaluator>>,
	error: Option<Error>
}

impl<'a> Interpreter<'a>
{
	fn new(session: &Session,
		     types: &'a Vec<Ty>,
		     names: &'a Vec<&'a str>) -> Interpreter<'a> {
		Interpreter {
			types : types,
			names : names,
			stack : Vec::new(),
			error : None
		}
	}

	pub fn build(session:  &'a Session,
					  input_types: &'a Vec<Ty>,
					  input_names: &'a Vec<&'a str>,
					  expression : &Expr) -> Result<Box<Evaluator>>
	{
		let mut interpreter = Interpreter::new(session, input_types, input_names);
		interpreter.accept(expression);

		match interpreter.stack.len() {
			len if len == 1 => Ok(interpreter.stack.pop().unwrap()),
			len if len > 1  => panic!("more than one stack item still remains in interpreter"),
			_               => panic!("no more stack item in interpreter")
		}
  }

	pub fn Not(&self, c: &Expr)
	{
	}

	pub fn IsNull(&self, c: &Expr)
	{
	}

	pub fn IsNotNull(&self, c: &Expr)
	{
	}

	pub fn PlusSign(&self, c: &Expr)
	{
	}

	pub fn MinusSign(&self, c: &Expr)
	{
	}

	pub fn Cast(&self, c: &Expr, f: &Ty, t: &Ty)
	{
	}

	pub fn And(&self, lhs: &Expr, rhs: &Expr)
	{
	}

	pub fn Or(&self, lhs: &Expr, rhs: &Expr)
	{
	}

	pub fn Cmp(&self, op: &CmpOp, lhs: &Expr, rhs: &Expr)
	{
	}

	pub fn Arithm(&self, op: &ArithmOp, lhs: &Expr, rhs: &Expr)
	{
	}

	pub fn Func(&self, f: &FnDecl, args: &Vec<Box<Expr>>)
	{
	}

	pub fn Field(&mut self, ty: &Ty, name: &str)
	{
		let found: Option<(usize, &Ty, &&str)>;

		found = izip!(0 .. self.types.len(), self.types, self.names)
						.find(|&(i, t, n)| *n == name);

    let eval = match found {
    	Some(f) => FieldEvaluator {idx: f.0, ty: f.1.clone()},
    	None    => panic!("no such field for {}", name)
    };

		self.stack.push(Box::new(eval));
	}
}

impl<'a> visitor::Visitor for Interpreter<'a>
{
	fn accept(&mut self, e: &Expr)
	{
	  match *e.kind() {
	    ExprKind::Not      (ref c)               => self.Not(c),
	    ExprKind::IsNull   (ref c)               => self.IsNull(c),
	    ExprKind::IsNotNull(ref c)               => self.IsNotNull(c),
	    ExprKind::PlusSign (ref c)               => self.PlusSign(c),
	    ExprKind::MinusSign(ref c)               => self.MinusSign(c),
	    ExprKind::Cast     (ref c, ref f, ref t) => self.Cast(c, f, t),

	    ExprKind::And      (ref l, ref r)        => self.And(l, r),
	    ExprKind::Or       (ref l, ref r)        => self.And(l, r),
	    ExprKind::Cmp      (ref o, ref l, ref r) => self.Cmp(o, l, r),
	    ExprKind::Arithm   (ref o, ref l, ref r) => self.Arithm(o, l, r),

	    ExprKind::Fn     (ref f, ref args)  => self.Func(f, args),
			ExprKind::Field  (ref name)         => self.Field(e.ty(), name),
			/*
	    ExprKind::Const  (_)            => {}

	    ExprKind::Switch(ref cases, ref default) => {
	    	for c in cases.iter() {
	    		v.accept(c);
	   	  }

	    	v.accept(default);
	    },

	    ExprKind::Case   (ref l, ref r) => { v.accept(l); v.accept(r) },*/
	    _ => panic!("")
	  }
	}
}

pub type Schema<'a, 'b> = (&'a Vec<Ty>, &'a Vec<&'b str>);

pub struct InterpreterProcessor
{
	evals: Vec<Box<Evaluator>>
}

impl InterpreterProcessor
{
	pub fn new(session: &Session,
		         schema : &Schema,
		         exprs  : &Vec<Box<Expr>>) -> Result<InterpreterProcessor>
	{
		let evals = try!(
			exprs.iter()
		       .map(|e| Interpreter::build(session, schema.0, schema.1, e))
		       .collect::<Result<Vec<Box<Evaluator>>>>()
    );

		Ok(InterpreterProcessor { evals: evals })
	}
}

impl Processor for InterpreterProcessor
{
	fn process(
    &self,
    input: &Page,
    builder: &mut PageBuilder) -> Void
	{
  	for e in self.evals.iter() {
  		try!(e.evaluate(input));
  	}

  	void_ok
  }
}

#[cfg(test)]
mod tests {
	use common::rows::{
		Page,
		PageBuilder,
		PageId
	};
	use common::plugin::*;
	use common::session::Session;
	use common::storage::{RandomTable, MemTable};
	use common::types::*;

	use plan::expr::*;
	use driver::DriverContext;

	use super::*;

	#[test]
	pub fn tpch_q1() {
		let plugin_mgr = PluginManager::new();

		/*
			l_orderkey long,
			l_partkey long,
			l_suppkey long,
			l_linenumber int,
			l_quantity double,
			l_extendedprice double,
			l_discount double,
			l_tax double,
			l_returnflag string,
			l_linestatus string,
			l_shipdate string,
			l_commitdate string,
			l_receiptdate string,
			l_shipinstruct string,
			l_shipmode string,
			l_comment string
		*/
		let tb_types: Vec<Ty> = vec![
	    i64_ty(), // l_orderkey      bigint
	    i64_ty(), // l_partkey       bigint
	    i64_ty(), // l_suppkey       bigint
	    i32_ty(), // l_linenumber    int
	    f64_ty(), // l_quantity      double,
	    f64_ty(), // l_extendedprice double,
	    f64_ty(), // l_discount      double,
	    f64_ty(), // l_tax           double,
	    // string types are not implmeneted yet.
	  ];

	  let tb_field_names: Vec<&str> = vec![
	  	"l_orderkey",
	  	"l_partkey",
	  	"l_suppkey",
	  	"l_linenumber",
	  	"l_quantity",
	  	"l_extendedprice",
	  	"l_discount",
	  	"l_tax"
	  ];

		/*
	  let sum_disc_price =
	  	Mul(
	  		&f64_ty(), Field(&f64_ty(), "l_extendedprice"), Subtract(&f64_ty(), Const(1), Field(&f64_ty(), "l_discount")));

  	let sum_charge =
	  	Mul(&f64_ty(), sum_disc_price.clone(), Plus(&f64_ty(), Const(1), Field(&f64_ty(), "l_tax")));*/

		let l_quantity = Field(&f64_ty(), "l_quantity");

	  let exprs = vec![
//	  	Box::new(sum_disc_price),
//	  	Box::new(sum_charge)
				Box::new(l_quantity)
  	];

  	let schema = (&tb_types, &tb_field_names);
  	let session    = Session;

		let processor = InterpreterProcessor::new(&session, &schema, &exprs).ok().unwrap();
		let mut input  = RandomTable::new(&session, &tb_types, 1024);

		let output_tys = exprs.iter()
											.map(|e| e.ty().clone())
											.collect::<Vec<Ty>>();
		let mut output = MemTable::new(&session, &output_tys, &vec!["x"]);

		let mut builder = PageBuilder::new(&output_tys);

		loop {
		  let mut read_page = input.next().unwrap();

		  if read_page.value_count() == 0 {
		  	break;
		  }

		  processor.process(read_page, &mut builder);
		  output.write(builder.build(read_page.value_count()));
		  builder.reset();
		}

		assert_eq!(1, output.col_num());
		assert_eq!(1024, output.row_num());

		for x in output.reader() {
			let r: (f64) = x.ok().unwrap();
			println!("{}", r);
		}
	}
}<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Targets on which your draw commands are executed.
//!
//! # Render passes and framebuffers
//!
//! There are two concepts in Vulkan:
//!
//! - A *render pass* describes the target which you are going to render to. It is a collection of
//!   of descriptions of one or more attachments (ie. image that are rendered to), and of one or
//!   multiples subpasses. The render pass contains the format and number of samples of each
//!   attachment, and the attachments that are attached to each subpass. They are represented
//!   in vulkano with the `RenderPass` object.
//! - A *framebuffer* contains the list of actual images that are attached. It is created from a
//!   render pass and has to match its characteristics. They are represented in vulkano with the
//!   `Framebuffer` object.
//!
//! Render passes are typically created at initialization only (for example during a loading
//! screen), while framebuffers can be created and destroyed during the frame.
//!
//! Consequently you can create graphics pipelines from a render pass object alone.
//! A `Framebuffer` object is only needed when you actually add draw commands to a command buffer.
//!
//! > **Note**: While it is fast enough to create or destroy a framebuffer during a frame, it
//! > doesn't mean that you *have to* create it during a frame. You can try to keep framebuffer
//! > objects alive for as long as possible instead. But don't bother trying too hard if you can't.
//!
//! # Render passes
//!
//! In vulkano, a render pass is represented by the `RenderPass` struct. The `RenderPassRef` trait
//! also exists and is implemented on objects that hold a render pass (eg. `Arc<RenderPass>`).
//!
//! The `RenderPass` struct has a template parameter that contains the description of the render
//! pass. This template parameter must implement the `RenderPassDesc` trait. In order to create
//! a render pass, you must first create an object that implements the `RenderPassDesc` trait, then
//! call the `build_render_pass` method of that trait.
//!
//! For example the `EmptySinglePassRenderPassDesc` struct implements that trait. You can create
//! a render pass like this:
//!
//! ```
//! use vulkano::framebuffer::EmptySinglePassRenderPassDesc;
//! use vulkano::framebuffer::RenderPassDesc;
//!
//! # let device: std::sync::Arc<vulkano::device::Device> = return;
//! let desc = EmptySinglePassRenderPassDesc;
//! let render_pass = desc.build_render_pass(device.clone()).unwrap();
//! // The type of `render_pass` is `RenderPass<EmptySinglePassRenderPassDesc>`.
//! ```
//!
//! This example creates a render pass with no attachment and one single subpass that doesn't draw
//! on anything. While it's sometimes useful, most of the time it's not what you want.
//!
//! The easiest way to create a "real" render pass is to use the `single_pass_renderpass!` macro.
//! See the documentation of the macro.
//!
//! # Framebuffers
//!
//! Creating a framebuffer is done by passing the render pass object, the dimensions of the
//! framebuffer, and the list of attachments to `Framebuffer::new()`.
//!
//! The slightly tricky part is that the type that contains the list of attachments depends on
//! the trait implementation of `RenderPassRef`. For example if you use an
//! `EmptySinglePassRenderPass`, you have to pass `()` for the list of attachments.
//!

pub use self::basic_render_pass::BasicRenderPassDesc;
pub use self::basic_render_pass::BasicRenderPassDescAttachment;
pub use self::empty::EmptySinglePassRenderPassDesc;
pub use self::framebuffer::Framebuffer;
pub use self::framebuffer::FramebufferCreationError;
pub use self::framebuffer::FramebufferSys;
pub use self::sys::RenderPass;
pub use self::sys::RenderPassSys;
pub use self::sys::RenderPassCreationError;
pub use self::traits::FramebufferRef;
pub use self::traits::RenderPassRef;
pub use self::traits::RenderPassDesc;
pub use self::traits::RenderPassAttachmentsList;
pub use self::traits::RenderPassClearValues;
pub use self::traits::RenderPassCompatible;
pub use self::traits::RenderPassSubpassInterface;
pub use self::traits::LayoutAttachmentDescription;
pub use self::traits::LayoutPassDescription;
pub use self::traits::LayoutPassDependencyDescription;
pub use self::traits::StoreOp;
pub use self::traits::LoadOp;
pub use self::traits::Subpass;

mod basic_render_pass;
#[macro_use]
mod macros;
mod empty;
#[doc(hidden)] pub mod framebuffer;
mod sys;
#[doc(hidden)] pub mod traits;      // TODO: pub-hidden because of that trait visibility bug
<commit_msg>More documentation<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Targets on which your draw commands are executed.
//!
//! # Render passes and framebuffers
//!
//! There are two concepts in Vulkan:
//!
//! - A *render pass* describes the target which you are going to render to. It is a collection of
//!   of descriptions of one or more attachments (ie. image that are rendered to), and of one or
//!   multiples subpasses. The render pass contains the format and number of samples of each
//!   attachment, and the attachments that are attached to each subpass. They are represented
//!   in vulkano with the `RenderPass` object.
//! - A *framebuffer* contains the list of actual images that are attached. It is created from a
//!   render pass and has to match its characteristics. They are represented in vulkano with the
//!   `Framebuffer` object.
//!
//! Render passes are typically created at initialization only (for example during a loading
//! screen), while framebuffers can be created and destroyed during the frame.
//!
//! Consequently you can create graphics pipelines from a render pass object alone.
//! A `Framebuffer` object is only needed when you actually add draw commands to a command buffer.
//!
//! > **Note**: While it is fast enough to create or destroy a framebuffer during a frame, it
//! > doesn't mean that you *have to* create it during a frame. You can try to keep framebuffer
//! > objects alive for as long as possible instead. But don't bother trying too hard if you can't.
//!
//! # Render passes
//!
//! In vulkano, a render pass is represented by the `RenderPass` struct. The `RenderPassRef` trait
//! also exists and is implemented on objects that hold a render pass (eg. `Arc<RenderPass>`).
//!
//! The `RenderPass` struct has a template parameter that contains the description of the render
//! pass. This template parameter must implement the `RenderPassDesc` trait. In order to create
//! a render pass, you must first create an object that implements the `RenderPassDesc` trait, then
//! call the `build_render_pass` method of that trait.
//!
//! For example the `EmptySinglePassRenderPassDesc` struct implements that trait. You can create
//! a render pass like this:
//!
//! ```
//! use vulkano::framebuffer::EmptySinglePassRenderPassDesc;
//! use vulkano::framebuffer::RenderPassDesc;
//!
//! # let device: std::sync::Arc<vulkano::device::Device> = return;
//! let desc = EmptySinglePassRenderPassDesc;
//! let render_pass = desc.build_render_pass(device.clone()).unwrap();
//! // The type of `render_pass` is `RenderPass<EmptySinglePassRenderPassDesc>`.
//! ```
//!
//! This example creates a render pass with no attachment and one single subpass that doesn't draw
//! on anything. While it's sometimes useful, most of the time it's not what you want.
//!
//! The easiest way to create a "real" render pass is to use the `single_pass_renderpass!` macro.
//! See the documentation of the macro.
//!
//! # Framebuffers
//!
//! Creating a framebuffer is done by passing the render pass object, the dimensions of the
//! framebuffer, and the list of attachments to `Framebuffer::new()`.
//!
//! The tricky part is that the type that contains the list of attachments depends on the
//! template parameter of the `RenderPass` object. For example if you use an
//! `EmptySinglePassRenderPass`, you have to pass `()` for the list of attachments.
//!
//! When it comes to `single_pass_renderpass!` and `ordered_passes_renderpass!` you can build a
//! list of attachments by TODO.
//!
//! ## Example
//!
//! TODO

pub use self::basic_render_pass::BasicRenderPassDesc;
pub use self::basic_render_pass::BasicRenderPassDescAttachment;
pub use self::empty::EmptySinglePassRenderPassDesc;
pub use self::framebuffer::Framebuffer;
pub use self::framebuffer::FramebufferCreationError;
pub use self::framebuffer::FramebufferSys;
pub use self::sys::RenderPass;
pub use self::sys::RenderPassSys;
pub use self::sys::RenderPassCreationError;
pub use self::traits::FramebufferRef;
pub use self::traits::RenderPassRef;
pub use self::traits::RenderPassDesc;
pub use self::traits::RenderPassAttachmentsList;
pub use self::traits::RenderPassClearValues;
pub use self::traits::RenderPassCompatible;
pub use self::traits::RenderPassSubpassInterface;
pub use self::traits::LayoutAttachmentDescription;
pub use self::traits::LayoutPassDescription;
pub use self::traits::LayoutPassDependencyDescription;
pub use self::traits::StoreOp;
pub use self::traits::LoadOp;
pub use self::traits::Subpass;

mod basic_render_pass;
#[macro_use]
mod macros;
mod empty;
#[doc(hidden)] pub mod framebuffer;
mod sys;
#[doc(hidden)] pub mod traits;      // TODO: pub-hidden because of that trait visibility bug
<|endoftext|>


<commit_before>#![feature(maybe_uninit, maybe_uninit_ref)]
use std::mem::MaybeUninit;
use std::cell::Cell;
use std::cell::RefCell;

fn main() {
    aliasing_mut_and_shr();
    aliasing_frz_and_shr();
    into_interior_mutability();
}

fn aliasing_mut_and_shr() {
    fn inner(rc: &RefCell<i32>, aliasing: &mut i32) {
        *aliasing += 4;
        let _escape_to_raw = rc as *const _;
        *aliasing += 4;
        let _shr = &*rc;
        *aliasing += 4;
        // also turning this into a frozen ref now must work
        let aliasing = &*aliasing;
        let _val = *aliasing;
        let _escape_to_raw = rc as *const _; // this must NOT unfreeze
        let _val = *aliasing;
        let _shr = &*rc; // this must NOT unfreeze
        let _val = *aliasing;
    }

    let rc = RefCell::new(23);
    let mut bmut = rc.borrow_mut();
    inner(&rc, &mut *bmut);
    drop(bmut);
    assert_eq!(*rc.borrow(), 23+12);
}

fn aliasing_frz_and_shr() {
    fn inner(rc: &RefCell<i32>, aliasing: &i32) {
        let _val = *aliasing;
        let _escape_to_raw = rc as *const _; // this must NOT unfreeze
        let _val = *aliasing;
        let _shr = &*rc; // this must NOT unfreeze
        let _val = *aliasing;
    }

    let rc = RefCell::new(23);
    let bshr = rc.borrow();
    inner(&rc, &*bshr);
    assert_eq!(*rc.borrow(), 23);
}

// Getting a pointer into a union with interior mutability used to be tricky
// business (https://github.com/rust-lang/miri/issues/615), but it should work
// now.
fn into_interior_mutability() {
    let mut x: MaybeUninit<(Cell<u32>, u32)> = MaybeUninit::uninit();
    x.as_ptr();
    x.write((Cell::new(0), 1));
    let ptr = unsafe { x.get_ref() };
    assert_eq!(ptr.1, 1);
}
<commit_msg>this also fixed our 2-phase woes<commit_after>#![feature(maybe_uninit, maybe_uninit_ref)]
use std::mem::MaybeUninit;
use std::cell::{Cell, RefCell, UnsafeCell};

fn main() {
    aliasing_mut_and_shr();
    aliasing_frz_and_shr();
    into_interior_mutability();
    unsafe_cell_2phase();
}

fn aliasing_mut_and_shr() {
    fn inner(rc: &RefCell<i32>, aliasing: &mut i32) {
        *aliasing += 4;
        let _escape_to_raw = rc as *const _;
        *aliasing += 4;
        let _shr = &*rc;
        *aliasing += 4;
        // also turning this into a frozen ref now must work
        let aliasing = &*aliasing;
        let _val = *aliasing;
        let _escape_to_raw = rc as *const _; // this must NOT unfreeze
        let _val = *aliasing;
        let _shr = &*rc; // this must NOT unfreeze
        let _val = *aliasing;
    }

    let rc = RefCell::new(23);
    let mut bmut = rc.borrow_mut();
    inner(&rc, &mut *bmut);
    drop(bmut);
    assert_eq!(*rc.borrow(), 23+12);
}

fn aliasing_frz_and_shr() {
    fn inner(rc: &RefCell<i32>, aliasing: &i32) {
        let _val = *aliasing;
        let _escape_to_raw = rc as *const _; // this must NOT unfreeze
        let _val = *aliasing;
        let _shr = &*rc; // this must NOT unfreeze
        let _val = *aliasing;
    }

    let rc = RefCell::new(23);
    let bshr = rc.borrow();
    inner(&rc, &*bshr);
    assert_eq!(*rc.borrow(), 23);
}

// Getting a pointer into a union with interior mutability used to be tricky
// business (https://github.com/rust-lang/miri/issues/615), but it should work
// now.
fn into_interior_mutability() {
    let mut x: MaybeUninit<(Cell<u32>, u32)> = MaybeUninit::uninit();
    x.as_ptr();
    x.write((Cell::new(0), 1));
    let ptr = unsafe { x.get_ref() };
    assert_eq!(ptr.1, 1);
}

// Two-phase borrows of the pointer returned by UnsafeCell::get() should not
// invalidate aliases.
fn unsafe_cell_2phase() { unsafe {
    let x = &UnsafeCell::new(vec![]);
    let x2 = &*x;
    (*x.get()).push(0);
    let _val = (*x2.get()).get(0);
} }
<|endoftext|>


<commit_before>use crate::utils::{fn_has_unsatisfiable_preds, match_panic_def_id, snippet_opt, span_lint_and_then};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for missing return statements at the end of a block.
    ///
    /// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers
    /// coming from other languages might prefer the expressiveness of `return`. It's possible to miss
    /// the last returning statement because the only difference is a missing `;`. Especially in bigger
    /// code with multiple return paths having a `return` keyword makes it easier to find the
    /// corresponding statements.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// fn foo(x: usize) -> usize {
    ///     x
    /// }
    /// ```
    /// add return
    /// ```rust
    /// fn foo(x: usize) -> usize {
    ///     return x;
    /// }
    /// ```
    pub IMPLICIT_RETURN,
    restriction,
    "use a return statement like `return expr` instead of an expression"
}

declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]);

static LINT_BREAK: &str = "change `break` to `return` as shown";
static LINT_RETURN: &str = "add `return` as shown";

fn lint(cx: &LateContext<'_>, outer_span: Span, inner_span: Span, msg: &str) {
    let outer_span = outer_span.source_callsite();
    let inner_span = inner_span.source_callsite();

    span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing `return` statement", |diag| {
        if let Some(snippet) = snippet_opt(cx, inner_span) {
            diag.span_suggestion(
                outer_span,
                msg,
                format!("return {}", snippet),
                Applicability::MachineApplicable,
            );
        }
    });
}

fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) {
    match expr.kind {
        // loops could be using `break` instead of `return`
        ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => {
            if let Some(expr) = &block.expr {
                expr_match(cx, expr);
            }
            // only needed in the case of `break` with `;` at the end
            else if let Some(stmt) = block.stmts.last() {
                if_chain! {
                    if let StmtKind::Semi(expr, ..) = &stmt.kind;
                    // make sure it's a break, otherwise we want to skip
                    if let ExprKind::Break(.., Some(break_expr)) = &expr.kind;
                    then {
                            lint(cx, expr.span, break_expr.span, LINT_BREAK);
                    }
                }
            }
        },
        // use `return` instead of `break`
        ExprKind::Break(.., break_expr) => {
            if let Some(break_expr) = break_expr {
                lint(cx, expr.span, break_expr.span, LINT_BREAK);
            }
        },
        ExprKind::If(.., if_expr, else_expr) => {
            expr_match(cx, if_expr);

            if let Some(else_expr) = else_expr {
                expr_match(cx, else_expr);
            }
        },
        ExprKind::Match(.., arms, source) => {
            let check_all_arms = match source {
                MatchSource::IfLetDesugar {
                    contains_else_clause: has_else,
                } => has_else,
                _ => true,
            };

            if check_all_arms {
                for arm in arms {
                    expr_match(cx, &arm.body);
                }
            } else {
                expr_match(cx, &arms.first().expect("`if let` doesn't have a single arm").body);
            }
        },
        // skip if it already has a return statement
        ExprKind::Ret(..) => (),
        // make sure it's not a call that panics
        ExprKind::Call(expr, ..) => {
            if_chain! {
                if let ExprKind::Path(qpath) = &expr.kind;
                if let Some(path_def_id) = cx.qpath_res(qpath, expr.hir_id).opt_def_id();
                if match_panic_def_id(cx, path_def_id);
                then { }
                else {
                    lint(cx, expr.span, expr.span, LINT_RETURN)
                }
            }
        },
        // everything else is missing `return`
        _ => lint(cx, expr.span, expr.span, LINT_RETURN),
    }
}

impl<'tcx> LateLintPass<'tcx> for ImplicitReturn {
    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx FnDecl<'_>,
        body: &'tcx Body<'_>,
        span: Span,
        _: HirId,
    ) {
        let def_id = cx.tcx.hir().body_owner_def_id(body.id());

        // Building MIR for `fn`s with unsatisfiable preds results in ICE.
        if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) {
            return;
        }

        let mir = cx.tcx.optimized_mir(def_id.to_def_id());

        // checking return type through MIR, HIR is not able to determine inferred closure return types
        // make sure it's not a macro
        if !mir.return_ty().is_unit() && !span.from_expansion() {
            expr_match(cx, &body.value);
        }
    }
}
<commit_msg>Avoid mir in implicit_return<commit_after>use crate::utils::{match_panic_def_id, snippet_opt, span_lint_and_then};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for missing return statements at the end of a block.
    ///
    /// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers
    /// coming from other languages might prefer the expressiveness of `return`. It's possible to miss
    /// the last returning statement because the only difference is a missing `;`. Especially in bigger
    /// code with multiple return paths having a `return` keyword makes it easier to find the
    /// corresponding statements.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// fn foo(x: usize) -> usize {
    ///     x
    /// }
    /// ```
    /// add return
    /// ```rust
    /// fn foo(x: usize) -> usize {
    ///     return x;
    /// }
    /// ```
    pub IMPLICIT_RETURN,
    restriction,
    "use a return statement like `return expr` instead of an expression"
}

declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]);

static LINT_BREAK: &str = "change `break` to `return` as shown";
static LINT_RETURN: &str = "add `return` as shown";

fn lint(cx: &LateContext<'_>, outer_span: Span, inner_span: Span, msg: &str) {
    let outer_span = outer_span.source_callsite();
    let inner_span = inner_span.source_callsite();

    span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing `return` statement", |diag| {
        if let Some(snippet) = snippet_opt(cx, inner_span) {
            diag.span_suggestion(
                outer_span,
                msg,
                format!("return {}", snippet),
                Applicability::MachineApplicable,
            );
        }
    });
}

fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) {
    match expr.kind {
        // loops could be using `break` instead of `return`
        ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => {
            if let Some(expr) = &block.expr {
                expr_match(cx, expr);
            }
            // only needed in the case of `break` with `;` at the end
            else if let Some(stmt) = block.stmts.last() {
                if_chain! {
                    if let StmtKind::Semi(expr, ..) = &stmt.kind;
                    // make sure it's a break, otherwise we want to skip
                    if let ExprKind::Break(.., Some(break_expr)) = &expr.kind;
                    then {
                            lint(cx, expr.span, break_expr.span, LINT_BREAK);
                    }
                }
            }
        },
        // use `return` instead of `break`
        ExprKind::Break(.., break_expr) => {
            if let Some(break_expr) = break_expr {
                lint(cx, expr.span, break_expr.span, LINT_BREAK);
            }
        },
        ExprKind::If(.., if_expr, else_expr) => {
            expr_match(cx, if_expr);

            if let Some(else_expr) = else_expr {
                expr_match(cx, else_expr);
            }
        },
        ExprKind::Match(.., arms, source) => {
            let check_all_arms = match source {
                MatchSource::IfLetDesugar {
                    contains_else_clause: has_else,
                } => has_else,
                _ => true,
            };

            if check_all_arms {
                for arm in arms {
                    expr_match(cx, &arm.body);
                }
            } else {
                expr_match(cx, &arms.first().expect("`if let` doesn't have a single arm").body);
            }
        },
        // skip if it already has a return statement
        ExprKind::Ret(..) => (),
        // make sure it's not a call that panics
        ExprKind::Call(expr, ..) => {
            if_chain! {
                if let ExprKind::Path(qpath) = &expr.kind;
                if let Some(path_def_id) = cx.qpath_res(qpath, expr.hir_id).opt_def_id();
                if match_panic_def_id(cx, path_def_id);
                then { }
                else {
                    lint(cx, expr.span, expr.span, LINT_RETURN)
                }
            }
        },
        // everything else is missing `return`
        _ => lint(cx, expr.span, expr.span, LINT_RETURN),
    }
}

impl<'tcx> LateLintPass<'tcx> for ImplicitReturn {
    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx FnDecl<'_>,
        body: &'tcx Body<'_>,
        span: Span,
        _: HirId,
    ) {
        if span.from_expansion() {
            return;
        }
        let body = cx.tcx.hir().body(body.id());
        if cx.typeck_results().expr_ty(&body.value).is_unit() {
            return;
        }
        expr_match(cx, &body.value);
    }
}
<|endoftext|>