<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 crate::build_project::{build_project, build_schema, commit_project};
use crate::compiler_state::{ArtifactMapKind, CompilerState, ProjectName};
use crate::config::Config;
use crate::errors::{BuildProjectError, Error, Result};
use crate::graphql_asts::GraphQLAsts;
use crate::{source_for_location, watchman::FileSource};
use common::{Diagnostic, PerfLogEvent, PerfLogger};
use futures::future::join_all;
use graphql_cli::DiagnosticPrinter;
use log::{error, info};
use rayon::prelude::*;
use schema::Schema;
use std::{collections::HashMap, sync::Arc};
use tokio::task;

pub struct Compiler<TPerfLogger>
where
    TPerfLogger: PerfLogger + 'static,
{
    config: Arc<Config>,
    perf_logger: Arc<TPerfLogger>,
}

impl<TPerfLogger: PerfLogger> Compiler<TPerfLogger> {
    pub fn new(config: Config, perf_logger: Arc<TPerfLogger>) -> Self {
        Self {
            config: Arc::new(config),
            perf_logger,
        }
    }

    pub async fn compile(self) -> Result<CompilerState> {
        let setup_event = self.perf_logger.create_event("compiler_setup");

        let file_source = FileSource::connect(&self.config, &setup_event).await?;
        let mut compiler_state = file_source
            .query(&setup_event, self.perf_logger.as_ref())
            .await?;
        self.build_projects(&mut compiler_state, &setup_event)
            .await?;

        self.perf_logger.complete_event(setup_event);
        Ok(compiler_state)
    }

    pub fn build_schemas(
        &self,
        compiler_state: &CompilerState,
        setup_event: &impl PerfLogEvent,
    ) -> HashMap<ProjectName, Arc<Schema>> {
        let timer = setup_event.start("build_schemas");
        let mut schemas = HashMap::new();
        for project_config in self.config.enabled_projects() {
            let schema = build_schema(compiler_state, project_config);
            schemas.insert(project_config.name, Arc::new(schema));
        }
        setup_event.stop(timer);
        schemas
    }

    pub async fn watch(&self) -> Result<()> {
        let setup_event = self.perf_logger.create_event("compiler_setup");

        let file_source = FileSource::connect(&self.config, &setup_event).await?;

        let (mut compiler_state, mut subscription) = file_source
            .subscribe(&setup_event, self.perf_logger.as_ref())
            .await?;

        if self
            .build_projects(&mut compiler_state, &setup_event)
            .await
            .is_err()
        {
            // noop, build_projects should have logged already
        } else {
            info!("Compilation completed.");
        }
        self.perf_logger.complete_event(setup_event);
        info!("Waiting for changes...");

        loop {
            if let Some(file_source_changes) = subscription.next_change().await? {
                let incremental_build_event =
                    self.perf_logger.create_event("incremental_build_event");
                let incremental_build_time =
                    incremental_build_event.start("incremental_build_time");

                // TODO Single change to file in VSCode sometimes produces
                // 2 watchman change events for the same file

                let had_new_changes = compiler_state.merge_file_source_changes(
                    &self.config,
                    &file_source_changes,
                    &incremental_build_event,
                    self.perf_logger.as_ref(),
                    false,
                )?;

                if had_new_changes {
                    info!("Change detected, start compiling...");
                    if self
                        .build_projects(&mut compiler_state, &incremental_build_event)
                        .await
                        .is_err()
                    {
                        // noop, build_projects should have logged already
                    } else {
                        info!("Compilation completed.");
                    }
                    incremental_build_event.stop(incremental_build_time);
                    info!("Waiting for changes...");
                } else {
                    incremental_build_event.stop(incremental_build_time);
                }
                self.perf_logger.complete_event(incremental_build_event);
                // We probably don't want the messages queue to grow indefinitely
                // and we need to flush then, as the check/build is completed
                self.perf_logger.flush();
            }
        }
    }

    async fn build_projects(
        &self,
        compiler_state: &mut CompilerState,
        setup_event: &impl PerfLogEvent,
    ) -> Result<()> {
        let result = build_projects(
            Arc::clone(&self.config),
            Arc::clone(&self.perf_logger),
            setup_event,
            compiler_state,
        )
        .await;
        match result {
            Ok(()) => {
                compiler_state.complete_compilation();
                self.config.artifact_writer.finalize()?;
                Ok(())
            }
            Err(error) => {
                match &error {
                    Error::DiagnosticsError { errors } => {
                        for diagnostic in errors {
                            self.print_diagnostic(diagnostic);
                        }
                    }
                    Error::BuildProjectsErrors { errors } => {
                        for error in errors {
                            self.print_project_error(error);
                        }
                    }
                    error => {
                        error!("{}", error);
                    }
                }
                error!("Compilation failed.");
                Err(error)
            }
        }
    }

    fn print_project_error(&self, error: &BuildProjectError) {
        match error {
            BuildProjectError::ValidationErrors { errors } => {
                for diagnostic in errors {
                    self.print_diagnostic(diagnostic);
                }
            }
            BuildProjectError::PersistErrors { errors } => {
                for error in errors {
                    error!("{}", error);
                }
            }
            _ => {
                error!("{}", error);
            }
        }
    }

    fn print_diagnostic(&self, diagnostic: &Diagnostic) {
        let printer = DiagnosticPrinter::new(|source_location| {
            source_for_location(&self.config.root_dir, source_location).map(|source| source.text)
        });
        error!("{}", printer.diagnostic_to_string(diagnostic));
    }
}

async fn build_projects<TPerfLogger: PerfLogger + 'static>(
    config: Arc<Config>,
    perf_logger: Arc<TPerfLogger>,
    setup_event: &impl PerfLogEvent,
    compiler_state: &mut CompilerState,
) -> Result<()> {
    let mut graphql_asts = setup_event.time("parse_sources_time", || {
        GraphQLAsts::from_graphql_sources_map(
            &compiler_state.graphql_sources,
            &compiler_state.get_dirty_defintions(&config),
        )
    })?;

    let build_results: Vec<_> = config
        .par_enabled_projects()
        .filter(|project_config| compiler_state.project_has_pending_changes(project_config.name))
        .map(|project_config| {
            build_project(
                &config,
                project_config,
                compiler_state,
                &graphql_asts,
                Arc::clone(&perf_logger),
            )
        })
        .collect();
    let mut results = Vec::new();
    let mut errors = Vec::new();
    for result in build_results {
        match result {
            Ok(result) => results.push(result),
            Err(error) => errors.push(error),
        }
    }

    if errors.is_empty() {
        let mut handles = Vec::new();
        for (project_name, schema, programs, artifacts) in results {
            let config = Arc::clone(&config);
            let perf_logger = Arc::clone(&perf_logger);
            let artifact_map = compiler_state
                .artifacts
                .get(&project_name)
                .cloned()
                .unwrap_or_else(|| Arc::new(ArtifactMapKind::Unconnected(Default::default())));
            let removed_definition_names = graphql_asts
                .remove(&project_name)
                .expect("Expect GraphQLAsts to exist.")
                .removed_definition_names;
            let dirty_artifact_paths = compiler_state
                .dirty_artifact_paths
                .get(&project_name)
                .cloned()
                .unwrap_or_default();
            handles.push(task::spawn(async move {
                let project_config = &config.projects[&project_name];
                Ok((
                    project_name,
                    commit_project(
                        &config,
                        project_config,
                        perf_logger,
                        &schema,
                        programs,
                        artifacts,
                        artifact_map,
                        removed_definition_names,
                        dirty_artifact_paths,
                    )
                    .await?,
                ))
            }));
        }
        for commit_result in join_all(handles).await {
            let commit_result: std::result::Result<std::result::Result<_, _>, _> = commit_result;
            let inner_result = commit_result.map_err(|e| Error::JoinError {
                error: e.to_string(),
            })?;
            match inner_result {
                Ok((project_name, next_artifact_map)) => {
                    let next_artifact_map = Arc::new(ArtifactMapKind::Mapping(next_artifact_map));
                    compiler_state
                        .artifacts
                        .insert(project_name, next_artifact_map);
                }
                Err(error) => {
                    errors.push(error);
                }
            }
        }
    };

    if errors.is_empty() {
        Ok(())
    } else {
        Err(Error::BuildProjectsErrors { errors })
    }
}
<commit_msg>we need to build a project if only changes to the base project happened<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 crate::build_project::{build_project, build_schema, commit_project};
use crate::compiler_state::{ArtifactMapKind, CompilerState, ProjectName};
use crate::config::Config;
use crate::errors::{BuildProjectError, Error, Result};
use crate::graphql_asts::GraphQLAsts;
use crate::{source_for_location, watchman::FileSource};
use common::{Diagnostic, PerfLogEvent, PerfLogger};
use futures::future::join_all;
use graphql_cli::DiagnosticPrinter;
use log::{error, info};
use rayon::prelude::*;
use schema::Schema;
use std::{collections::HashMap, sync::Arc};
use tokio::task;

pub struct Compiler<TPerfLogger>
where
    TPerfLogger: PerfLogger + 'static,
{
    config: Arc<Config>,
    perf_logger: Arc<TPerfLogger>,
}

impl<TPerfLogger: PerfLogger> Compiler<TPerfLogger> {
    pub fn new(config: Config, perf_logger: Arc<TPerfLogger>) -> Self {
        Self {
            config: Arc::new(config),
            perf_logger,
        }
    }

    pub async fn compile(self) -> Result<CompilerState> {
        let setup_event = self.perf_logger.create_event("compiler_setup");

        let file_source = FileSource::connect(&self.config, &setup_event).await?;
        let mut compiler_state = file_source
            .query(&setup_event, self.perf_logger.as_ref())
            .await?;
        self.build_projects(&mut compiler_state, &setup_event)
            .await?;

        self.perf_logger.complete_event(setup_event);
        Ok(compiler_state)
    }

    pub fn build_schemas(
        &self,
        compiler_state: &CompilerState,
        setup_event: &impl PerfLogEvent,
    ) -> HashMap<ProjectName, Arc<Schema>> {
        let timer = setup_event.start("build_schemas");
        let mut schemas = HashMap::new();
        for project_config in self.config.enabled_projects() {
            let schema = build_schema(compiler_state, project_config);
            schemas.insert(project_config.name, Arc::new(schema));
        }
        setup_event.stop(timer);
        schemas
    }

    pub async fn watch(&self) -> Result<()> {
        let setup_event = self.perf_logger.create_event("compiler_setup");

        let file_source = FileSource::connect(&self.config, &setup_event).await?;

        let (mut compiler_state, mut subscription) = file_source
            .subscribe(&setup_event, self.perf_logger.as_ref())
            .await?;

        if self
            .build_projects(&mut compiler_state, &setup_event)
            .await
            .is_err()
        {
            // noop, build_projects should have logged already
        } else {
            info!("Compilation completed.");
        }
        self.perf_logger.complete_event(setup_event);
        info!("Waiting for changes...");

        loop {
            if let Some(file_source_changes) = subscription.next_change().await? {
                let incremental_build_event =
                    self.perf_logger.create_event("incremental_build_event");
                let incremental_build_time =
                    incremental_build_event.start("incremental_build_time");

                // TODO Single change to file in VSCode sometimes produces
                // 2 watchman change events for the same file

                let had_new_changes = compiler_state.merge_file_source_changes(
                    &self.config,
                    &file_source_changes,
                    &incremental_build_event,
                    self.perf_logger.as_ref(),
                    false,
                )?;

                if had_new_changes {
                    info!("Change detected, start compiling...");
                    if self
                        .build_projects(&mut compiler_state, &incremental_build_event)
                        .await
                        .is_err()
                    {
                        // noop, build_projects should have logged already
                    } else {
                        info!("Compilation completed.");
                    }
                    incremental_build_event.stop(incremental_build_time);
                    info!("Waiting for changes...");
                } else {
                    incremental_build_event.stop(incremental_build_time);
                }
                self.perf_logger.complete_event(incremental_build_event);
                // We probably don't want the messages queue to grow indefinitely
                // and we need to flush then, as the check/build is completed
                self.perf_logger.flush();
            }
        }
    }

    async fn build_projects(
        &self,
        compiler_state: &mut CompilerState,
        setup_event: &impl PerfLogEvent,
    ) -> Result<()> {
        let result = build_projects(
            Arc::clone(&self.config),
            Arc::clone(&self.perf_logger),
            setup_event,
            compiler_state,
        )
        .await;
        match result {
            Ok(()) => {
                compiler_state.complete_compilation();
                self.config.artifact_writer.finalize()?;
                Ok(())
            }
            Err(error) => {
                match &error {
                    Error::DiagnosticsError { errors } => {
                        for diagnostic in errors {
                            self.print_diagnostic(diagnostic);
                        }
                    }
                    Error::BuildProjectsErrors { errors } => {
                        for error in errors {
                            self.print_project_error(error);
                        }
                    }
                    error => {
                        error!("{}", error);
                    }
                }
                error!("Compilation failed.");
                Err(error)
            }
        }
    }

    fn print_project_error(&self, error: &BuildProjectError) {
        match error {
            BuildProjectError::ValidationErrors { errors } => {
                for diagnostic in errors {
                    self.print_diagnostic(diagnostic);
                }
            }
            BuildProjectError::PersistErrors { errors } => {
                for error in errors {
                    error!("{}", error);
                }
            }
            _ => {
                error!("{}", error);
            }
        }
    }

    fn print_diagnostic(&self, diagnostic: &Diagnostic) {
        let printer = DiagnosticPrinter::new(|source_location| {
            source_for_location(&self.config.root_dir, source_location).map(|source| source.text)
        });
        error!("{}", printer.diagnostic_to_string(diagnostic));
    }
}

async fn build_projects<TPerfLogger: PerfLogger + 'static>(
    config: Arc<Config>,
    perf_logger: Arc<TPerfLogger>,
    setup_event: &impl PerfLogEvent,
    compiler_state: &mut CompilerState,
) -> Result<()> {
    let mut graphql_asts = setup_event.time("parse_sources_time", || {
        GraphQLAsts::from_graphql_sources_map(
            &compiler_state.graphql_sources,
            &compiler_state.get_dirty_defintions(&config),
        )
    })?;

    let build_results: Vec<_> = config
        .par_enabled_projects()
        .filter(|project_config| {
            if let Some(base) = project_config.base {
                if compiler_state.project_has_pending_changes(base) {
                    return true;
                }
            }
            compiler_state.project_has_pending_changes(project_config.name)
        })
        .map(|project_config| {
            build_project(
                &config,
                project_config,
                compiler_state,
                &graphql_asts,
                Arc::clone(&perf_logger),
            )
        })
        .collect();
    let mut results = Vec::new();
    let mut errors = Vec::new();
    for result in build_results {
        match result {
            Ok(result) => results.push(result),
            Err(error) => errors.push(error),
        }
    }

    if errors.is_empty() {
        let mut handles = Vec::new();
        for (project_name, schema, programs, artifacts) in results {
            let config = Arc::clone(&config);
            let perf_logger = Arc::clone(&perf_logger);
            let artifact_map = compiler_state
                .artifacts
                .get(&project_name)
                .cloned()
                .unwrap_or_else(|| Arc::new(ArtifactMapKind::Unconnected(Default::default())));
            let removed_definition_names = graphql_asts
                .remove(&project_name)
                .expect("Expect GraphQLAsts to exist.")
                .removed_definition_names;
            let dirty_artifact_paths = compiler_state
                .dirty_artifact_paths
                .get(&project_name)
                .cloned()
                .unwrap_or_default();
            handles.push(task::spawn(async move {
                let project_config = &config.projects[&project_name];
                Ok((
                    project_name,
                    commit_project(
                        &config,
                        project_config,
                        perf_logger,
                        &schema,
                        programs,
                        artifacts,
                        artifact_map,
                        removed_definition_names,
                        dirty_artifact_paths,
                    )
                    .await?,
                ))
            }));
        }
        for commit_result in join_all(handles).await {
            let commit_result: std::result::Result<std::result::Result<_, _>, _> = commit_result;
            let inner_result = commit_result.map_err(|e| Error::JoinError {
                error: e.to_string(),
            })?;
            match inner_result {
                Ok((project_name, next_artifact_map)) => {
                    let next_artifact_map = Arc::new(ArtifactMapKind::Mapping(next_artifact_map));
                    compiler_state
                        .artifacts
                        .insert(project_name, next_artifact_map);
                }
                Err(error) => {
                    errors.push(error);
                }
            }
        }
    };

    if errors.is_empty() {
        Ok(())
    } else {
        Err(Error::BuildProjectsErrors { errors })
    }
}
<|endoftext|>


<commit_before>use crate::builtins::WasmbinCountable;
use crate::io::{DecodeError, WasmbinDecode, WasmbinEncode};
use crate::visit::WasmbinVisit;
use arbitrary::Arbitrary;

#[cfg(feature = "lazy-blob")]
macro_rules! if_lazy {
    (if lazy { $($then:tt)* } $(else { $($otherwise:tt)* })?) => {
        $($then)*
    };
}

#[cfg(not(feature = "lazy-blob"))]
macro_rules! if_lazy {
    (if lazy { $($then:tt)* } $(else { $($otherwise:tt)* })?) => {
        $($($otherwise)*)?
    };
}

#[derive(Debug, Arbitrary, PartialEq, Eq, Hash, Clone, WasmbinVisit)]
pub struct RawBlob<T = Vec<u8>> {
    pub contents: T,
}

impl<T: AsRef<[u8]>> WasmbinEncode for RawBlob<T> {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        let bytes = self.contents.as_ref();
        bytes.len().encode(w)?;
        bytes.encode(w)
    }
}

impl<T: WasmbinDecode> WasmbinDecode for RawBlob<T> {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let size = u32::decode(r)?;
        let mut taken = std::io::Read::take(r, size.into());
        let contents = T::decode(&mut taken)?;
        if taken.limit() != 0 {
            return Err(DecodeError::UnrecognizedData);
        }
        Ok(RawBlob { contents })
    }
}

impl<T: AsRef<[u8]>> AsRef<[u8]> for RawBlob<T> {
    fn as_ref(&self) -> &[u8] {
        self.contents.as_ref()
    }
}

if_lazy!(if lazy {
    use crate::builtins::Lazy as BlobContents;

    impl<T: WasmbinDecode> Blob<T> {
        pub fn try_contents(&self) -> Result<&T, DecodeError> {
            self.contents.try_contents()
        }

        pub fn try_contents_mut(&mut self) -> Result<&mut T, DecodeError> {
            self.contents.try_contents_mut()
        }

        pub fn try_into_contents(self) -> Result<T, DecodeError> {
            self.contents.try_into_contents()
        }
    }
} else {
    type BlobContents<T> = T;

    impl<T: WasmbinDecode> Blob<T> {
        pub fn try_contents(&self) -> Result<&T, DecodeError> {
            Ok(&self.contents)
        }

        pub fn try_contents_mut(&mut self) -> Result<&mut T, DecodeError> {
            Ok(&mut self.contents)
        }

        pub fn try_into_contents(self) -> Result<T, DecodeError> {
            Ok(self.contents)
        }
    }
});

#[derive(Default, Arbitrary, PartialEq, Eq, Hash, Clone, WasmbinVisit)]
pub struct Blob<T: WasmbinDecode> {
    contents: BlobContents<T>,
}

impl<T: WasmbinDecode + std::fmt::Debug> std::fmt::Debug for Blob<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("Blob(")?;
        self.contents.fmt(f)?;
        f.write_str(")")
    }
}

impl<T: WasmbinDecode + WasmbinEncode> WasmbinEncode for Blob<T> {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        let value = if_lazy!(if lazy {
            match self.contents.try_as_raw() {
                Ok(raw) => return RawBlob { contents: raw }.encode(w),
                Err(value) => value,
            }
        } else {
            &self.contents
        });
        let mut buf;
        buf = Vec::new();
        value.encode(&mut buf)?;
        RawBlob { contents: buf }.encode(w)
    }
}

impl<T: WasmbinDecode> WasmbinDecode for Blob<T> {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        Ok(Blob {
            contents: RawBlob::decode(r)?.contents,
        })
    }
}

impl<T: WasmbinDecode + WasmbinCountable> WasmbinCountable for Blob<T> {}

impl<T: WasmbinDecode> From<T> for Blob<T> {
    fn from(value: T) -> Self {
        Blob {
            contents: value.into(),
        }
    }
}
<commit_msg>Use Lazy in Blob even when lazy-blob is disabled<commit_after>use crate::builtins::{Lazy, WasmbinCountable};
use crate::io::{DecodeError, WasmbinDecode, WasmbinEncode};
use crate::visit::WasmbinVisit;
use arbitrary::Arbitrary;

#[derive(Debug, Arbitrary, PartialEq, Eq, Hash, Clone, WasmbinVisit)]
pub struct RawBlob<T = Vec<u8>> {
    pub contents: T,
}

impl<T: AsRef<[u8]>> WasmbinEncode for RawBlob<T> {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        let bytes = self.contents.as_ref();
        bytes.len().encode(w)?;
        bytes.encode(w)
    }
}

impl<T: WasmbinDecode> WasmbinDecode for RawBlob<T> {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let size = u32::decode(r)?;
        let mut taken = std::io::Read::take(r, size.into());
        let contents = T::decode(&mut taken)?;
        if taken.limit() != 0 {
            return Err(DecodeError::UnrecognizedData);
        }
        Ok(RawBlob { contents })
    }
}

impl<T: AsRef<[u8]>> AsRef<[u8]> for RawBlob<T> {
    fn as_ref(&self) -> &[u8] {
        self.contents.as_ref()
    }
}

#[derive(Default, Arbitrary, PartialEq, Eq, Hash, Clone, WasmbinVisit)]
pub struct Blob<T: WasmbinDecode> {
    contents: Lazy<T>,
}

impl<T: WasmbinDecode> Blob<T> {
    pub fn try_contents(&self) -> Result<&T, DecodeError> {
        self.contents.try_contents()
    }

    pub fn try_contents_mut(&mut self) -> Result<&mut T, DecodeError> {
        self.contents.try_contents_mut()
    }

    pub fn try_into_contents(self) -> Result<T, DecodeError> {
        self.contents.try_into_contents()
    }
}

#[cfg(not(feature = "lazy-blob"))]
impl<T: WasmbinDecode> Blob<T> {
    pub fn contents(&self) -> &T {
        self.try_contents()
            .unwrap_or_else(|_| unsafe { std::hint::unreachable_unchecked() })
    }

    pub fn contents_mut(&mut self) -> &mut T {
        self.try_contents_mut()
            .unwrap_or_else(|_| unsafe { std::hint::unreachable_unchecked() })
    }

    pub fn into_contents(self) -> T {
        self.try_into_contents()
            .unwrap_or_else(|_| unsafe { std::hint::unreachable_unchecked() })
    }
}

impl<T: WasmbinDecode + std::fmt::Debug> std::fmt::Debug for Blob<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("Blob(")?;
        self.contents.fmt(f)?;
        f.write_str(")")
    }
}

impl<T: WasmbinDecode + WasmbinEncode> WasmbinEncode for Blob<T> {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        let value = match self.contents.try_as_raw() {
            Ok(raw) => return RawBlob { contents: raw }.encode(w),
            Err(value) => value,
        };
        let mut buf;
        buf = Vec::new();
        value.encode(&mut buf)?;
        RawBlob { contents: buf }.encode(w)
    }
}

impl<T: WasmbinDecode> WasmbinDecode for Blob<T> {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let contents: Lazy<T> = RawBlob::decode(r)?.contents;
        #[cfg(not(feature = "lazy-blob"))]
        {
            contents.try_contents()?;
        }
        Ok(Self { contents })
    }
}

impl<T: WasmbinDecode + WasmbinCountable> WasmbinCountable for Blob<T> {}

impl<T: WasmbinDecode> From<T> for Blob<T> {
    fn from(value: T) -> Self {
        Blob {
            contents: value.into(),
        }
    }
}
<|endoftext|>


<commit_before>use glium::backend::Facade;
use glium::{self, BackfaceCullingMode, DepthTest, DrawParameters, IndexBuffer, VertexBuffer};
use glium::index::PrimitiveType;
use Camera;
use util::ToArr;
use base::math::*;
use base::gen::seeded_rng;
use base::prop::plant::{Plant, Tree};
use std::rc::Rc;
use super::PlantRenderer;
use base::prop::plant::ControlPoint;

/// Graphical representation of a 'base::Plant'
pub struct PlantView {
    vertices: VertexBuffer<Vertex>,
    indices: IndexBuffer<u32>,
    renderer: Rc<PlantRenderer>,
    pos: Point3f,
}

impl PlantView {
    pub fn from_plant<F: Facade>(pos: Point3f,
                                 plant: &Plant,
                                 renderer: Rc<PlantRenderer>,
                                 facade: &F)
                                 -> Self {
        let mut indices = Vec::new();
        let mut vertices = Vec::new();
        let branches = match *plant {
            Plant::Tree(Tree { ref branches, branch_color }) => {
                for branch in branches {
                    for i in 1..branch.points.len() {
                        get_vertices_for_branch(&branch.points[i - 1],
                                                &branch.points[i],
                                                &mut vertices,
                                                &mut indices,
                                                branch_color);
                    }
                }
            }
        };

        PlantView {
            vertices: VertexBuffer::new(facade, &vertices).unwrap(),
            indices: IndexBuffer::new(facade, PrimitiveType::TrianglesList, &indices).unwrap(),
            renderer: renderer,
            pos: pos,
        }
    }

    pub fn draw<S: glium::Surface>(&self, surface: &mut S, camera: &Camera) {
        let uniforms = uniform! {
            offset: self.pos.to_arr(),
            proj_matrix: camera.proj_matrix().to_arr(),
            view_matrix: camera.view_matrix().to_arr(),
        };

        let params = DrawParameters {
            depth: glium::Depth {
                write: true,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            backface_culling: BackfaceCullingMode::CullCounterClockwise,
            ..Default::default()
        };

        surface.draw(&self.vertices,
                  &self.indices,
                  &self.renderer.program(),
                  &uniforms,
                  &params)
            .unwrap();
    }
}

/// Vertex type used to render plants/trees.
#[derive(Debug, Copy, Clone)]
pub struct Vertex {
    pub position: [f32; 3],
    pub color: [f32; 3],
    pub normal: [f32; 3],
}

implement_vertex!(Vertex, position, color, normal);

/// generates Vertexbuffer and indexbuffer for a branch
fn get_vertices_for_branch(start: &ControlPoint,
                           end: &ControlPoint,
                           vertices: &mut Vec<Vertex>,
                           indices: &mut Vec<u32>,
                           color: Vector3f) {

    let to_end = end.point - start.point;
    let ortho = get_points_from_vector(to_end);

    let mut cur_len = vertices.len() as u32;

    // Bottom
    for vec in ortho.iter() {
        vertices.push(Vertex {
            position: (start.point + vec * start.diameter).to_arr(),
            normal: (-to_end).normalize().to_arr(),
            color: color.to_arr(),
        });
    }
    indices.extend_from_slice(&[cur_len + 2, cur_len + 0, cur_len + 1]);

    // Top
    cur_len = vertices.len() as u32;

    for vec in ortho.iter() {
        vertices.push(Vertex {
            position: (end.point + vec * end.diameter).to_arr(),
            normal: to_end.normalize().to_arr(),
            color: color.to_arr(),
        });
    }
    indices.extend_from_slice(&[cur_len + 1, cur_len + 0, cur_len + 2]);

    side(vertices, indices, color, start, end, ortho[0], ortho[1]);
    side(vertices, indices, color, start, end, ortho[1], ortho[2]);
    side(vertices, indices, color, start, end, ortho[2], ortho[0]);
}

/// Creates Vertexbuffer and IndexBuffer for a Side of the plants
fn side(vertices: &mut Vec<Vertex>,
        indices: &mut Vec<u32>,
        color: Vector3f,
        start: &ControlPoint,
        end: &ControlPoint,
        first_normal: Vector3f,
        second_normal: Vector3f) {
    let cur_len = vertices.len() as u32;

    vertices.extend_from_slice(&[Vertex {
                                     position: (end.point + first_normal * end.diameter).to_arr(),
                                     normal: (first_normal + second_normal).normalize().to_arr(),
                                     color: color.to_arr(),
                                 },
                                 Vertex {
                                     position: (end.point + second_normal * end.diameter).to_arr(),
                                     normal: (first_normal + second_normal).normalize().to_arr(),
                                     color: color.to_arr(),
                                 },
                                 Vertex {
                                     position: (start.point + first_normal * start.diameter)
                                         .to_arr(),
                                     normal: (first_normal + second_normal).normalize().to_arr(),
                                     color: color.to_arr(),
                                 },
                                 Vertex {
                                     position: (start.point + second_normal * start.diameter)
                                         .to_arr(),
                                     normal: (first_normal + second_normal).normalize().to_arr(),
                                     color: color.to_arr(),
                                 }]);

    indices.extend_from_slice(&[cur_len + 2,
                                cur_len + 0,
                                cur_len + 1,
                                cur_len + 2,
                                cur_len + 1,
                                cur_len + 3]);
}

/// generates 3 normalized vectors perpendicular to the given vector
fn get_points_from_vector(vector: Vector3f) -> [Vector3f; 3] {
    let ortho = random_vec_with_angle(&mut seeded_rng(0x2651aa465abded, (), ()), vector, 90.0);
    let rot = Basis3::from_axis_angle(vector, Deg::new(120.0).into());
    let v0 = rot.rotate_vector(ortho);
    let v1 = rot.rotate_vector(v0);

    [ortho.normalize(), v0.normalize(), v1.normalize()]
}
<commit_msg>Remove unused variable<commit_after>use glium::backend::Facade;
use glium::{self, BackfaceCullingMode, DepthTest, DrawParameters, IndexBuffer, VertexBuffer};
use glium::index::PrimitiveType;
use Camera;
use util::ToArr;
use base::math::*;
use base::gen::seeded_rng;
use base::prop::plant::{Plant, Tree};
use std::rc::Rc;
use super::PlantRenderer;
use base::prop::plant::ControlPoint;

/// Graphical representation of a 'base::Plant'
pub struct PlantView {
    vertices: VertexBuffer<Vertex>,
    indices: IndexBuffer<u32>,
    renderer: Rc<PlantRenderer>,
    pos: Point3f,
}

impl PlantView {
    pub fn from_plant<F: Facade>(pos: Point3f,
                                 plant: &Plant,
                                 renderer: Rc<PlantRenderer>,
                                 facade: &F)
                                 -> Self {
        let mut indices = Vec::new();
        let mut vertices = Vec::new();
        match *plant {
            Plant::Tree(Tree { ref branches, branch_color }) => {
                for branch in branches {
                    for i in 1..branch.points.len() {
                        get_vertices_for_branch(&branch.points[i - 1],
                                                &branch.points[i],
                                                &mut vertices,
                                                &mut indices,
                                                branch_color);
                    }
                }
            }
        };

        PlantView {
            vertices: VertexBuffer::new(facade, &vertices).unwrap(),
            indices: IndexBuffer::new(facade, PrimitiveType::TrianglesList, &indices).unwrap(),
            renderer: renderer,
            pos: pos,
        }
    }

    pub fn draw<S: glium::Surface>(&self, surface: &mut S, camera: &Camera) {
        let uniforms = uniform! {
            offset: self.pos.to_arr(),
            proj_matrix: camera.proj_matrix().to_arr(),
            view_matrix: camera.view_matrix().to_arr(),
        };

        let params = DrawParameters {
            depth: glium::Depth {
                write: true,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            backface_culling: BackfaceCullingMode::CullCounterClockwise,
            ..Default::default()
        };

        surface.draw(&self.vertices,
                  &self.indices,
                  &self.renderer.program(),
                  &uniforms,
                  &params)
            .unwrap();
    }
}

/// Vertex type used to render plants/trees.
#[derive(Debug, Copy, Clone)]
pub struct Vertex {
    pub position: [f32; 3],
    pub color: [f32; 3],
    pub normal: [f32; 3],
}

implement_vertex!(Vertex, position, color, normal);

/// generates Vertexbuffer and indexbuffer for a branch
fn get_vertices_for_branch(start: &ControlPoint,
                           end: &ControlPoint,
                           vertices: &mut Vec<Vertex>,
                           indices: &mut Vec<u32>,
                           color: Vector3f) {

    let to_end = end.point - start.point;
    let ortho = get_points_from_vector(to_end);

    let mut cur_len = vertices.len() as u32;

    // Bottom
    for vec in ortho.iter() {
        vertices.push(Vertex {
            position: (start.point + vec * start.diameter).to_arr(),
            normal: (-to_end).normalize().to_arr(),
            color: color.to_arr(),
        });
    }
    indices.extend_from_slice(&[cur_len + 2, cur_len + 0, cur_len + 1]);

    // Top
    cur_len = vertices.len() as u32;

    for vec in ortho.iter() {
        vertices.push(Vertex {
            position: (end.point + vec * end.diameter).to_arr(),
            normal: to_end.normalize().to_arr(),
            color: color.to_arr(),
        });
    }
    indices.extend_from_slice(&[cur_len + 1, cur_len + 0, cur_len + 2]);

    side(vertices, indices, color, start, end, ortho[0], ortho[1]);
    side(vertices, indices, color, start, end, ortho[1], ortho[2]);
    side(vertices, indices, color, start, end, ortho[2], ortho[0]);
}

/// Creates Vertexbuffer and IndexBuffer for a Side of the plants
fn side(vertices: &mut Vec<Vertex>,
        indices: &mut Vec<u32>,
        color: Vector3f,
        start: &ControlPoint,
        end: &ControlPoint,
        first_normal: Vector3f,
        second_normal: Vector3f) {
    let cur_len = vertices.len() as u32;

    vertices.extend_from_slice(&[Vertex {
                                     position: (end.point + first_normal * end.diameter).to_arr(),
                                     normal: (first_normal + second_normal).normalize().to_arr(),
                                     color: color.to_arr(),
                                 },
                                 Vertex {
                                     position: (end.point + second_normal * end.diameter).to_arr(),
                                     normal: (first_normal + second_normal).normalize().to_arr(),
                                     color: color.to_arr(),
                                 },
                                 Vertex {
                                     position: (start.point + first_normal * start.diameter)
                                         .to_arr(),
                                     normal: (first_normal + second_normal).normalize().to_arr(),
                                     color: color.to_arr(),
                                 },
                                 Vertex {
                                     position: (start.point + second_normal * start.diameter)
                                         .to_arr(),
                                     normal: (first_normal + second_normal).normalize().to_arr(),
                                     color: color.to_arr(),
                                 }]);

    indices.extend_from_slice(&[cur_len + 2,
                                cur_len + 0,
                                cur_len + 1,
                                cur_len + 2,
                                cur_len + 1,
                                cur_len + 3]);
}

/// generates 3 normalized vectors perpendicular to the given vector
fn get_points_from_vector(vector: Vector3f) -> [Vector3f; 3] {
    let ortho = random_vec_with_angle(&mut seeded_rng(0x2651aa465abded, (), ()), vector, 90.0);
    let rot = Basis3::from_axis_angle(vector, Deg::new(120.0).into());
    let v0 = rot.rotate_vector(ortho);
    let v1 = rot.rotate_vector(v0);

    [ortho.normalize(), v0.normalize(), v1.normalize()]
}
<|endoftext|>


<commit_before>//! The module contains an implementation of a simple HTTP/2 client.

use http::{StreamId, HttpResult, HttpError, Response, Header};
use http::transport::TransportStream;
use http::connection::{HttpConnection, SendStatus};
use http::session::{SessionState, DefaultSessionState, DefaultStream, Stream};
use http::client::{ClientConnection, HttpConnect, RequestStream};

/// A struct implementing a simple HTTP/2 client.
///
/// This client works as an HTTP/1.1 client with a Keep-Alive connection and
/// pipelining might work.
///
/// Multiple requests can be queued up (and sent to the server) by calling
/// `request` multiple times, before any `get_response`.
///
/// Once a `get_response` is issued, the client blocks until it receives the
/// response for the particular request that was referenced in the `get_response`
/// call.
///
/// Therefore, by doing `request` -> `get_response` we can use the HTTP/2
/// connection as a `Keep-Alive` HTTP/1.1 connection and a pipelined flow by
/// queuing up a sequence of requests and then "joining" over them by calling
/// `get_response` for each of them.
///
/// The responses that are returned by the client are very raw representations
/// of the response.
///
/// # Notes
///
/// - For now (temporarily) no requests with bodies are supported.
/// - A direct HTTP/2 connection is used (not an upgrade of an HTTP/1.1
///   connection)
///
/// # Examples
///
/// Issue a simple GET request using the helper `get` method. Premade connection
/// passed to the client.
///
/// ```no_run
/// use std::net::TcpStream;
/// use solicit::http::HttpScheme;
/// use solicit::http::connection::HttpConnection;
/// use solicit::http::client::write_preface;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Prepare a stream manually... We must write the preface ourselves in this case.
/// // This is a more advanced way to use the client and the `HttpConnect` implementations
/// // should usually be preferred for their convenience.
/// let mut stream = TcpStream::connect(&("http2bin.org", 80)).unwrap();
/// write_preface(&mut stream);
/// // Connect to an HTTP/2 aware server
/// let conn = HttpConnection::<TcpStream, TcpStream>::with_stream(
///                                stream,
///                                HttpScheme::Http);
/// let mut client = SimpleClient::with_connection(conn, "http2bin.org".into()).unwrap();
/// let response = client.get(b"/", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
///
/// Issue a simple GET request using the helper `get` method. Pass a connector
/// to establish a new connection.
///
/// ```no_run
/// use solicit::http::client::CleartextConnector;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Connect to an HTTP/2 aware server
/// let connector = CleartextConnector::new("http2bin.org");
/// let mut client = SimpleClient::with_connector(connector).unwrap();
/// let response = client.get(b"/", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
pub struct SimpleClient<S> where S: TransportStream {
    /// The underlying `ClientConnection` that the client uses
    conn: ClientConnection<S, S>,
    /// Holds the ID that can be assigned to the next stream to be opened by the
    /// client.
    next_stream_id: u32,
    /// The name of the host to which the client is connected to.
    host: Vec<u8>,
}

impl<S> SimpleClient<S> where S: TransportStream {
    /// Create a new `SimpleClient` instance that will use the given `HttpConnection`
    /// to communicate to the server.
    ///
    /// It assumes that the connection stream is initialized and will *not* automatically write the
    /// client preface.
    pub fn with_connection(conn: HttpConnection<S, S>, host: String)
            -> HttpResult<SimpleClient<S>> {
        let mut client = SimpleClient {
            conn: ClientConnection::with_connection(conn, DefaultSessionState::new()),
            next_stream_id: 1,
            host: host.as_bytes().to_vec(),
        };

        try!(client.init());

        Ok(client)
    }

    /// A convenience constructor that first tries to establish an HTTP/2
    /// connection by using the given connector instance (an implementation of
    /// the `HttpConnect` trait).
    ///
    /// # Panics
    ///
    /// Currently, it panics if the connector returns an error.
    pub fn with_connector<C>(connector: C) -> HttpResult<SimpleClient<S>>
            where C: HttpConnect<Stream=S> {
        let stream = try!(connector.connect());
        let conn = HttpConnection::<S, S>::with_stream(stream.0, stream.1);
        SimpleClient::with_connection(conn, stream.2)
    }

    /// Internal helper method that performs the initialization of the client's
    /// connection.
    #[inline]
    fn init(&mut self) -> HttpResult<()> {
        self.conn.init()
    }

    /// Send a request to the server. Blocks until the entire request has been
    /// sent.
    ///
    /// The request is described by the method, the path on which it should be
    /// invoked and the "real" headers that should be included. Clients should
    /// never put pseudo-headers in the `headers` parameter, as those are
    /// automatically included based on metadata.
    ///
    /// # Returns
    ///
    /// If the full request is successfully sent, returns the ID of the stream
    /// on which the request was sent. Clients can use this ID to refer to the
    /// response.
    ///
    /// Any IO errors are propagated.
    pub fn request(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
            -> HttpResult<StreamId> {
        // Prepares the request stream
        let stream = self.new_stream(method, path, extras, body);
        // Remember the stream's ID before passing on the ownership to the connection
        let stream_id = stream.stream.id();
        // Starts the request (i.e. sends out the headers)
        try!(self.conn.start_request(stream));

        // And now makes sure the data is sent out...
        // Note: Since for now there is no flow control, sending data will always continue
        //       progressing, but it might violate flow control windows, causing the peer to shut
        //       down the connection.
        debug!("Trying to send the body");
        while let SendStatus::Sent = try!(self.conn.send_next_data()) {
            // We iterate until the data is sent, as the contract of this call is that it blocks
            // until such a time.
        }

        Ok(stream_id)
    }

    /// Gets the response for the stream with the given ID. If a valid stream ID
    /// is given, it blocks until a response is received.
    ///
    /// # Returns
    ///
    /// A `Response` if the response can be successfully read.
    ///
    /// Any underlying IO errors are propagated. Errors in the HTTP/2 protocol
    /// also stop processing and are returned to the client.
    pub fn get_response(&mut self, stream_id: StreamId) -> HttpResult<Response> {
        match self.conn.state.get_stream_ref(stream_id) {
            None => return Err(HttpError::UnknownStreamId),
            Some(_) => {},
        };
        loop {
            if let Some(stream) = self.conn.state.get_stream_ref(stream_id) {
                if stream.is_closed() {
                    return Ok(Response {
                        stream_id: stream.id(),
                        headers: stream.headers.clone().unwrap(),
                        body: stream.body.clone(),
                    });
                }
            }
            try!(self.handle_next_frame());
        }
    }

    /// Performs a GET request on the given path. This is a shortcut method for
    /// calling `request` followed by `get_response` for the returned stream ID.
    pub fn get(&mut self, path: &[u8], extra_headers: &[Header])
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"GET", path, extra_headers, None));
        self.get_response(stream_id)
    }

    /// Performs a POST request on the given path.
    pub fn post(&mut self, path: &[u8], extra_headers: &[Header], body: Vec<u8>)
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"POST", path, extra_headers, Some(body)));
        self.get_response(stream_id)
    }

    /// Internal helper method that prepares a new `RequestStream` instance based on the given
    /// request parameters.
    ///
    /// The `RequestStream` is then ready to be passed on to the connection instance in order to
    /// start the request.
    fn new_stream(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
            -> RequestStream<DefaultStream> {
        let stream_id = self.get_next_stream_id();
        let mut stream = DefaultStream::new(stream_id);
        match body {
            Some(body) => stream.set_full_data(body),
            None => stream.close_local(),
        };

        let mut headers: Vec<Header> = vec![
            (b":method".to_vec(), method.to_vec()),
            (b":path".to_vec(), path.to_vec()),
            (b":authority".to_vec(), self.host.clone()),
            (b":scheme".to_vec(), self.conn.scheme().as_bytes().to_vec()),
        ];
        headers.extend(extras.to_vec().into_iter());

        RequestStream {
            headers: headers,
            stream: stream,
        }
    }

    /// Internal helper method that gets the next valid stream ID number.
    fn get_next_stream_id(&mut self) -> StreamId {
        let ret = self.next_stream_id;
        self.next_stream_id += 2;

        ret
    }

    /// Internal helper method that triggers the client to handle the next
    /// frame off the HTTP/2 connection.
    #[inline]
    fn handle_next_frame(&mut self) -> HttpResult<()> {
        self.conn.handle_next_frame()
    }
}
<commit_msg>docs: Remove some obsolete comments<commit_after>//! The module contains an implementation of a simple HTTP/2 client.

use http::{StreamId, HttpResult, HttpError, Response, Header};
use http::transport::TransportStream;
use http::connection::{HttpConnection, SendStatus};
use http::session::{SessionState, DefaultSessionState, DefaultStream, Stream};
use http::client::{ClientConnection, HttpConnect, RequestStream};

/// A struct implementing a simple HTTP/2 client.
///
/// This client works as an HTTP/1.1 client with a Keep-Alive connection and
/// pipelining might work.
///
/// Multiple requests can be queued up (and sent to the server) by calling
/// `request` multiple times, before any `get_response`.
///
/// Once a `get_response` is issued, the client blocks until it receives the
/// response for the particular request that was referenced in the `get_response`
/// call.
///
/// Therefore, by doing `request` -> `get_response` we can use the HTTP/2
/// connection as a `Keep-Alive` HTTP/1.1 connection and a pipelined flow by
/// queuing up a sequence of requests and then "joining" over them by calling
/// `get_response` for each of them.
///
/// The responses that are returned by the client are very raw representations
/// of the response.
///
/// # Examples
///
/// Issue a simple GET request using the helper `get` method. Premade connection
/// passed to the client.
///
/// ```no_run
/// use std::net::TcpStream;
/// use solicit::http::HttpScheme;
/// use solicit::http::connection::HttpConnection;
/// use solicit::http::client::write_preface;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Prepare a stream manually... We must write the preface ourselves in this case.
/// // This is a more advanced way to use the client and the `HttpConnect` implementations
/// // should usually be preferred for their convenience.
/// let mut stream = TcpStream::connect(&("http2bin.org", 80)).unwrap();
/// write_preface(&mut stream);
/// // Connect to an HTTP/2 aware server
/// let conn = HttpConnection::<TcpStream, TcpStream>::with_stream(
///                                stream,
///                                HttpScheme::Http);
/// let mut client = SimpleClient::with_connection(conn, "http2bin.org".into()).unwrap();
/// let response = client.get(b"/", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
///
/// Issue a simple GET request using the helper `get` method. Pass a connector
/// to establish a new connection.
///
/// ```no_run
/// use solicit::http::client::CleartextConnector;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Connect to an HTTP/2 aware server
/// let connector = CleartextConnector::new("http2bin.org");
/// let mut client = SimpleClient::with_connector(connector).unwrap();
/// let response = client.get(b"/", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
pub struct SimpleClient<S> where S: TransportStream {
    /// The underlying `ClientConnection` that the client uses
    conn: ClientConnection<S, S>,
    /// Holds the ID that can be assigned to the next stream to be opened by the
    /// client.
    next_stream_id: u32,
    /// The name of the host to which the client is connected to.
    host: Vec<u8>,
}

impl<S> SimpleClient<S> where S: TransportStream {
    /// Create a new `SimpleClient` instance that will use the given `HttpConnection`
    /// to communicate to the server.
    ///
    /// It assumes that the connection stream is initialized and will *not* automatically write the
    /// client preface.
    pub fn with_connection(conn: HttpConnection<S, S>, host: String)
            -> HttpResult<SimpleClient<S>> {
        let mut client = SimpleClient {
            conn: ClientConnection::with_connection(conn, DefaultSessionState::new()),
            next_stream_id: 1,
            host: host.as_bytes().to_vec(),
        };

        try!(client.init());

        Ok(client)
    }

    /// A convenience constructor that first tries to establish an HTTP/2
    /// connection by using the given connector instance (an implementation of
    /// the `HttpConnect` trait).
    ///
    /// # Panics
    ///
    /// Currently, it panics if the connector returns an error.
    pub fn with_connector<C>(connector: C) -> HttpResult<SimpleClient<S>>
            where C: HttpConnect<Stream=S> {
        let stream = try!(connector.connect());
        let conn = HttpConnection::<S, S>::with_stream(stream.0, stream.1);
        SimpleClient::with_connection(conn, stream.2)
    }

    /// Internal helper method that performs the initialization of the client's
    /// connection.
    #[inline]
    fn init(&mut self) -> HttpResult<()> {
        self.conn.init()
    }

    /// Send a request to the server. Blocks until the entire request has been
    /// sent.
    ///
    /// The request is described by the method, the path on which it should be
    /// invoked and the "real" headers that should be included. Clients should
    /// never put pseudo-headers in the `headers` parameter, as those are
    /// automatically included based on metadata.
    ///
    /// # Returns
    ///
    /// If the full request is successfully sent, returns the ID of the stream
    /// on which the request was sent. Clients can use this ID to refer to the
    /// response.
    ///
    /// Any IO errors are propagated.
    pub fn request(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
            -> HttpResult<StreamId> {
        // Prepares the request stream
        let stream = self.new_stream(method, path, extras, body);
        // Remember the stream's ID before passing on the ownership to the connection
        let stream_id = stream.stream.id();
        // Starts the request (i.e. sends out the headers)
        try!(self.conn.start_request(stream));

        // And now makes sure the data is sent out...
        // Note: Since for now there is no flow control, sending data will always continue
        //       progressing, but it might violate flow control windows, causing the peer to shut
        //       down the connection.
        debug!("Trying to send the body");
        while let SendStatus::Sent = try!(self.conn.send_next_data()) {
            // We iterate until the data is sent, as the contract of this call is that it blocks
            // until such a time.
        }

        Ok(stream_id)
    }

    /// Gets the response for the stream with the given ID. If a valid stream ID
    /// is given, it blocks until a response is received.
    ///
    /// # Returns
    ///
    /// A `Response` if the response can be successfully read.
    ///
    /// Any underlying IO errors are propagated. Errors in the HTTP/2 protocol
    /// also stop processing and are returned to the client.
    pub fn get_response(&mut self, stream_id: StreamId) -> HttpResult<Response> {
        match self.conn.state.get_stream_ref(stream_id) {
            None => return Err(HttpError::UnknownStreamId),
            Some(_) => {},
        };
        loop {
            if let Some(stream) = self.conn.state.get_stream_ref(stream_id) {
                if stream.is_closed() {
                    return Ok(Response {
                        stream_id: stream.id(),
                        headers: stream.headers.clone().unwrap(),
                        body: stream.body.clone(),
                    });
                }
            }
            try!(self.handle_next_frame());
        }
    }

    /// Performs a GET request on the given path. This is a shortcut method for
    /// calling `request` followed by `get_response` for the returned stream ID.
    pub fn get(&mut self, path: &[u8], extra_headers: &[Header])
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"GET", path, extra_headers, None));
        self.get_response(stream_id)
    }

    /// Performs a POST request on the given path.
    pub fn post(&mut self, path: &[u8], extra_headers: &[Header], body: Vec<u8>)
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"POST", path, extra_headers, Some(body)));
        self.get_response(stream_id)
    }

    /// Internal helper method that prepares a new `RequestStream` instance based on the given
    /// request parameters.
    ///
    /// The `RequestStream` is then ready to be passed on to the connection instance in order to
    /// start the request.
    fn new_stream(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
            -> RequestStream<DefaultStream> {
        let stream_id = self.get_next_stream_id();
        let mut stream = DefaultStream::new(stream_id);
        match body {
            Some(body) => stream.set_full_data(body),
            None => stream.close_local(),
        };

        let mut headers: Vec<Header> = vec![
            (b":method".to_vec(), method.to_vec()),
            (b":path".to_vec(), path.to_vec()),
            (b":authority".to_vec(), self.host.clone()),
            (b":scheme".to_vec(), self.conn.scheme().as_bytes().to_vec()),
        ];
        headers.extend(extras.to_vec().into_iter());

        RequestStream {
            headers: headers,
            stream: stream,
        }
    }

    /// Internal helper method that gets the next valid stream ID number.
    fn get_next_stream_id(&mut self) -> StreamId {
        let ret = self.next_stream_id;
        self.next_stream_id += 2;

        ret
    }

    /// Internal helper method that triggers the client to handle the next
    /// frame off the HTTP/2 connection.
    #[inline]
    fn handle_next_frame(&mut self) -> HttpResult<()> {
        self.conn.handle_next_frame()
    }
}
<|endoftext|>


<commit_before>//! The module contains an implementation of a simple HTTP/2 client.

use std::net::TcpStream;

use super::super::http::connection::ClientConnection;
use super::super::http::session::{DefaultSession, Stream};
use super::super::http::{StreamId, HttpResult, HttpError, Response, Header, Request};

/// A struct implementing a simple HTTP/2 client.
///
/// This client works as an HTTP/1.1 client with a Keep-Alive connection and
/// pipelining might work.
///
/// Multiple requests can be queued up (and sent to the server) by calling
/// `request` multiple times, before any `get_response`.
///
/// Once a `get_response` is issued, the client blocks until it receives the
/// response for the particular request that was referenced in the `get_response`
/// call.
///
/// Therefore, by doing `request` -> `get_response` we can use the HTTP/2
/// connection as a `Keep-Alive` HTTP/1.1 connection and a pipelined flow by
/// queuing up a sequence of requests and then "joining" over them by calling
/// `get_response` for each of them.
///
/// The responses that are returned by the client are very raw representations
/// of the response.
///
/// # Notes
///
/// - For now (temporarily) no requests with bodies are supported.
/// - For now, only HTTP/2 over a cleartext TCP connection is supported.
/// - A direct HTTP/2 connection is used (not an upgrade of an HTTP/1.1
///   connection)
///
/// # Examples
///
/// Issue a simple GET request using the helper `get` method.
///
/// ```no_run
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Connect to an HTTP/2 aware server
/// let mut client = SimpleClient::connect("nghttp2.org", 80).ok().unwrap();
/// let response = client.get(b"/", &[]).ok().unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().ok().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0[]).unwrap(),
///         str::from_utf8(&header.1[]).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
#[unstable = "This is unstable"]
pub struct SimpleClient {
    /// The underlying `ClientConnection` that the client uses
    conn: ClientConnection<TcpStream, DefaultSession>,
    /// Holds the ID that can be assigned to the next stream to be opened by the
    /// client.
    next_stream_id: u32,
    /// Holds the domain name of the host to which the client is connected to.
    host: Vec<u8>,
}

impl SimpleClient {
    /// Establishes an HTTP/2 connection to a server, given its host name and
    /// port number. If it is not possible to establish the connection, an error
    /// is returned.
    pub fn connect(host: &str, port: u16) -> HttpResult<SimpleClient> {
        let mut client = SimpleClient {
            conn: ClientConnection::new(
                TcpStream::connect(&(host, port)).unwrap(),
                DefaultSession::new()),
            next_stream_id: 1,
            host: host.as_bytes().to_vec(),
        };

        try!(client.init());

        Ok(client)
    }

    /// Internal helper method that performs the initialization of the client's
    /// connection.
    #[inline]
    fn init(&mut self) -> HttpResult<()> {
        self.conn.init()
    }

    /// Send a request to the server. Blocks until the entire request has been
    /// sent.
    ///
    /// The request is described by the method, the path on which it should be
    /// invoked and the "real" headers that should be included. Clients should
    /// never put pseudo-headers in the `headers` parameter, as those are
    /// automatically included based on metadata.
    ///
    /// # Returns
    ///
    /// If the full request is successfully sent, returns the ID of the stream
    /// on which the request was sent. Clients can use this ID to refer to the
    /// response.
    ///
    /// Any IO errors are propagated.
    pub fn request(&mut self, method: &[u8], path: &[u8], extras: &[Header])
            -> HttpResult<StreamId> {
        let stream_id = self.new_stream();
        // Only http supported for now...
        let scheme = b"http".to_vec();
        let host = self.host.clone();
        let mut headers: Vec<Header> = vec![
            (b":method".to_vec(), method.to_vec()),
            (b":path".to_vec(), path.to_vec()),
            (b":authority".to_vec(), host),
            (b":scheme".to_vec(), scheme),
        ];
        headers.extend(extras.to_vec().into_iter());

        try!(self.conn.send_request(Request {
            stream_id: stream_id,
            headers: headers,
            body: Vec::new(),
        }));

        Ok(stream_id)
    }

    /// Gets the response for the stream with the given ID. If a valid stream ID
    /// is given, it blocks until a response is received.
    ///
    /// # Returns
    ///
    /// A `Response` if the response can be successfully read.
    ///
    /// Any underlying IO errors are propagated. Errors in the HTTP/2 protocol
    /// also stop processing and are returned to the client.
    pub fn get_response(&mut self, stream_id: StreamId) -> HttpResult<Response> {
        match self.conn.session.get_stream(stream_id) {
            None => return Err(HttpError::UnknownStreamId),
            Some(_) => {},
        };
        loop {
            if let Some(stream) = self.conn.session.get_stream(stream_id) {
                if stream.is_closed() {
                    return Ok(Response {
                        stream_id: stream.id(),
                        headers: stream.headers.clone().unwrap(),
                        body: stream.body.clone(),
                    });
                }
            }
            try!(self.handle_next_frame());
        }
    }

    /// Performs a GET request on the given path. This is a shortcut method for
    /// calling `request` followed by `get_response` for the returned stream ID.
    pub fn get(&mut self, path: &[u8], extra_headers: &[Header])
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"GET", path, extra_headers));
        self.get_response(stream_id)
    }

    /// Internal helper method that initializes a new stream and returns its
    /// ID once done.
    fn new_stream(&mut self) -> StreamId {
        let stream_id = self.get_next_stream_id();
        self.conn.session.new_stream(stream_id);

        stream_id
    }

    /// Internal helper method that gets the next valid stream ID number.
    fn get_next_stream_id(&mut self) -> StreamId {
        let ret = self.next_stream_id;
        self.next_stream_id += 2;

        ret
    }

    /// Internal helper method that triggers the client to handle the next
    /// frame off the HTTP/2 connection.
    #[inline]
    fn handle_next_frame(&mut self) -> HttpResult<()> {
        self.conn.handle_next_frame()
    }
}
<commit_msg>Fix obsolete syntax in the documentation<commit_after>//! The module contains an implementation of a simple HTTP/2 client.

use std::net::TcpStream;

use super::super::http::connection::ClientConnection;
use super::super::http::session::{DefaultSession, Stream};
use super::super::http::{StreamId, HttpResult, HttpError, Response, Header, Request};

/// A struct implementing a simple HTTP/2 client.
///
/// This client works as an HTTP/1.1 client with a Keep-Alive connection and
/// pipelining might work.
///
/// Multiple requests can be queued up (and sent to the server) by calling
/// `request` multiple times, before any `get_response`.
///
/// Once a `get_response` is issued, the client blocks until it receives the
/// response for the particular request that was referenced in the `get_response`
/// call.
///
/// Therefore, by doing `request` -> `get_response` we can use the HTTP/2
/// connection as a `Keep-Alive` HTTP/1.1 connection and a pipelined flow by
/// queuing up a sequence of requests and then "joining" over them by calling
/// `get_response` for each of them.
///
/// The responses that are returned by the client are very raw representations
/// of the response.
///
/// # Notes
///
/// - For now (temporarily) no requests with bodies are supported.
/// - For now, only HTTP/2 over a cleartext TCP connection is supported.
/// - A direct HTTP/2 connection is used (not an upgrade of an HTTP/1.1
///   connection)
///
/// # Examples
///
/// Issue a simple GET request using the helper `get` method.
///
/// ```no_run
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Connect to an HTTP/2 aware server
/// let mut client = SimpleClient::connect("nghttp2.org", 80).ok().unwrap();
/// let response = client.get(b"/", &[]).ok().unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().ok().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
#[unstable = "This is unstable"]
pub struct SimpleClient {
    /// The underlying `ClientConnection` that the client uses
    conn: ClientConnection<TcpStream, DefaultSession>,
    /// Holds the ID that can be assigned to the next stream to be opened by the
    /// client.
    next_stream_id: u32,
    /// Holds the domain name of the host to which the client is connected to.
    host: Vec<u8>,
}

impl SimpleClient {
    /// Establishes an HTTP/2 connection to a server, given its host name and
    /// port number. If it is not possible to establish the connection, an error
    /// is returned.
    pub fn connect(host: &str, port: u16) -> HttpResult<SimpleClient> {
        let mut client = SimpleClient {
            conn: ClientConnection::new(
                TcpStream::connect(&(host, port)).unwrap(),
                DefaultSession::new()),
            next_stream_id: 1,
            host: host.as_bytes().to_vec(),
        };

        try!(client.init());

        Ok(client)
    }

    /// Internal helper method that performs the initialization of the client's
    /// connection.
    #[inline]
    fn init(&mut self) -> HttpResult<()> {
        self.conn.init()
    }

    /// Send a request to the server. Blocks until the entire request has been
    /// sent.
    ///
    /// The request is described by the method, the path on which it should be
    /// invoked and the "real" headers that should be included. Clients should
    /// never put pseudo-headers in the `headers` parameter, as those are
    /// automatically included based on metadata.
    ///
    /// # Returns
    ///
    /// If the full request is successfully sent, returns the ID of the stream
    /// on which the request was sent. Clients can use this ID to refer to the
    /// response.
    ///
    /// Any IO errors are propagated.
    pub fn request(&mut self, method: &[u8], path: &[u8], extras: &[Header])
            -> HttpResult<StreamId> {
        let stream_id = self.new_stream();
        // Only http supported for now...
        let scheme = b"http".to_vec();
        let host = self.host.clone();
        let mut headers: Vec<Header> = vec![
            (b":method".to_vec(), method.to_vec()),
            (b":path".to_vec(), path.to_vec()),
            (b":authority".to_vec(), host),
            (b":scheme".to_vec(), scheme),
        ];
        headers.extend(extras.to_vec().into_iter());

        try!(self.conn.send_request(Request {
            stream_id: stream_id,
            headers: headers,
            body: Vec::new(),
        }));

        Ok(stream_id)
    }

    /// Gets the response for the stream with the given ID. If a valid stream ID
    /// is given, it blocks until a response is received.
    ///
    /// # Returns
    ///
    /// A `Response` if the response can be successfully read.
    ///
    /// Any underlying IO errors are propagated. Errors in the HTTP/2 protocol
    /// also stop processing and are returned to the client.
    pub fn get_response(&mut self, stream_id: StreamId) -> HttpResult<Response> {
        match self.conn.session.get_stream(stream_id) {
            None => return Err(HttpError::UnknownStreamId),
            Some(_) => {},
        };
        loop {
            if let Some(stream) = self.conn.session.get_stream(stream_id) {
                if stream.is_closed() {
                    return Ok(Response {
                        stream_id: stream.id(),
                        headers: stream.headers.clone().unwrap(),
                        body: stream.body.clone(),
                    });
                }
            }
            try!(self.handle_next_frame());
        }
    }

    /// Performs a GET request on the given path. This is a shortcut method for
    /// calling `request` followed by `get_response` for the returned stream ID.
    pub fn get(&mut self, path: &[u8], extra_headers: &[Header])
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"GET", path, extra_headers));
        self.get_response(stream_id)
    }

    /// Internal helper method that initializes a new stream and returns its
    /// ID once done.
    fn new_stream(&mut self) -> StreamId {
        let stream_id = self.get_next_stream_id();
        self.conn.session.new_stream(stream_id);

        stream_id
    }

    /// Internal helper method that gets the next valid stream ID number.
    fn get_next_stream_id(&mut self) -> StreamId {
        let ret = self.next_stream_id;
        self.next_stream_id += 2;

        ret
    }

    /// Internal helper method that triggers the client to handle the next
    /// frame off the HTTP/2 connection.
    #[inline]
    fn handle_next_frame(&mut self) -> HttpResult<()> {
        self.conn.handle_next_frame()
    }
}
<|endoftext|>


<commit_before>use core::prelude::*;
use core::cell::UnsafeCell;

// Should T be `Sync`?
pub struct Shared<T> {
    value: UnsafeCell<T>
}

impl<T> Shared<T> {
    pub fn new(value: T) -> Shared<T> {
        Shared {
            value: UnsafeCell::new(value)
        }
    }

    pub fn borrow_mut<'a: 'b,'b>(&'a self) -> &'b mut T {
        unsafe {
            &mut *self.value.get()
        }
    }
}

impl<T> ::core::ops::Deref for Shared<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe {
            &*self.value.get()
        }
    }
}

impl<T> ::core::ops::DerefMut for Shared<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe {
            &mut *self.value.get()
        }
    }
}

<commit_msg>Oops revert shared.rs from master<commit_after>use core::prelude::*;
use core::cell::UnsafeCell;

// Should T be `Sync`?
pub struct Shared<T> {
    value: UnsafeCell<T>
}

impl<T> Shared<T> {
    pub fn new(value: T) -> Shared<T> {
        Shared {
            value: UnsafeCell::new(value)
        }
    }

    pub unsafe fn borrow_mut<'a: 'b,'b>(&'a self) -> &'b mut T {
        &mut *self.value.get()
    }
}

impl<T> ::core::ops::Deref for Shared<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe {
            &*self.value.get()
        }
    }
}

impl<T> ::core::ops::DerefMut for Shared<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe {
            &mut *self.value.get()
        }
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2014 by SiegeLord
//
// All rights reserved. Distributed under ZLib. For full terms see the file LICENSE.

macro_rules! if_ok
{
	($e: expr) =>
	{
		if ($e).is_err()
		{
			return Err(());
		}
	}
}

macro_rules! opaque
(
	($f: ident) =>
	{
		/* Mimicking c_void */
		#[allow(missing_copy_implementations)]
		pub enum $f
		{
		}
	}
)

macro_rules! flag_type
(
	($f: ident { $($n: ident = $v: expr),*}) =>
	{
		#[deriving(Copy)]
		pub struct $f
		{
			bits: u32
		}

		impl $f
		{
			#[inline]
			pub fn get(&self) -> u32
			{
				self.bits
			}
		}

		impl Flag for $f
		{
			fn zero() -> $f
			{
				$f{bits: 0}
			}
		}

		impl BitOr<$f, $f> for $f
		{
			fn bitor(&self, e: &$f) -> $f
			{
				$f{bits: self.bits | e.bits}
			}
		}

		impl BitAnd<$f, bool> for $f
		{
			fn bitand(&self, e: &$f) -> bool
			{
				self.bits & e.bits != 0
			}
		}

		$(
			pub const $n: $f = $f{bits: $v};
		)+
	}
)

macro_rules! cast_to_c
(
	($p:ident, f32) =>
	{
		$p as c_float
	};
	($p:ident, Color) =>
	{
		*$p
	}
)

macro_rules! wrap_bitmap_drawing
(
	($cf:ident -> $rf:ident ( $( $p:ident : $t:ident ),* )) =>
	{
		fn $rf<T: BitmapLike>(dummy:dummy, bitmap: &T, $( $p : $t ),* , flags: BitmapDrawingFlags)
		{
			target_bitmap_check(self.get_target_bitmap());
			unsafe
			{
				$cf(bitmap.get_bitmap(),
					$(
						cast_to_c!($p, $t)
					),*
				, (flags.get() << 1) as c_int);
			}
		}
	}
)

//~ wrap_bitmap_drawing!(al_draw_bitmap_region -> draw_bitmap_region(sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32))
//~ wrap_bitmap_drawing!(al_draw_bitmap_region -> draw_bitmap_region(sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32))
//~ wrap_bitmap_drawing!(al_draw_scaled_bitmap -> draw_scaled_bitmap(sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32, dw: f32, dh: f32))
//~ wrap_bitmap_drawing!(al_draw_rotated_bitmap -> draw_rotated_bitmap(cx: f32, cy: f32, dx: f32, dy: f32, angle: f32))
//~ wrap_bitmap_drawing!(al_draw_scaled_rotated_bitmap -> draw_scaled_rotated_bitmap(cx: f32, cy: f32, dx: f32, dy: f32, xscale: f32, yscale: f32, angle: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_bitmap -> draw_tinted_bitmap(tint: Color, dx: f32, dy: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_bitmap_region -> draw_tinted_bitmap_region(tint: Color, sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_scaled_bitmap -> draw_tinted_scaled_bitmap(tint: Color, sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32, dw: f32, dh: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_rotated_bitmap -> draw_tinted_rotated_bitmap(tint: Color, cx: f32, cy: f32, dx: f32, dy: f32, angle: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_scaled_rotated_bitmap -> draw_tinted_scaled_rotated_bitmap(tint: Color, cx: f32, cy: f32, dx: f32, dy: f32, xscale: f32, yscale: f32, angle: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_scaled_rotated_bitmap_region -> draw_tinted_scaled_rotated_bitmap_region(sx: f32, sy: f32, sw: f32, sh: f32, tint: Color, cx: f32, cy: f32, dx: f32, dy: f32, xscale: f32, yscale: f32, angle: f32))
<commit_msg>More fixes<commit_after>// Copyright (c) 2014 by SiegeLord
//
// All rights reserved. Distributed under ZLib. For full terms see the file LICENSE.

macro_rules! if_ok
{
	($e: expr) =>
	{
		if ($e).is_err()
		{
			return Err(());
		}
	}
}

macro_rules! opaque
(
	($f: ident) =>
	{
		/* Mimicking c_void */
		#[allow(missing_copy_implementations)]
		pub enum $f
		{
		}
	}
)

macro_rules! flag_type
(
	($f: ident { $($n: ident = $v: expr),*}) =>
	{
		#[deriving(Copy)]
		pub struct $f
		{
			bits: u32
		}

		impl $f
		{
			#[inline]
			pub fn get(&self) -> u32
			{
				self.bits
			}
		}

		impl Flag for $f
		{
			fn zero() -> $f
			{
				$f{bits: 0}
			}
		}

		impl BitOr<$f, $f> for $f
		{
			fn bitor(self, e: $f) -> $f
			{
				$f{bits: self.bits | e.bits}
			}
		}

		impl BitAnd<$f, bool> for $f
		{
			fn bitand(self, e: $f) -> bool
			{
				self.bits & e.bits != 0
			}
		}

		$(
			pub const $n: $f = $f{bits: $v};
		)+
	}
)

macro_rules! cast_to_c
(
	($p:ident, f32) =>
	{
		$p as c_float
	};
	($p:ident, Color) =>
	{
		*$p
	}
)

macro_rules! wrap_bitmap_drawing
(
	($cf:ident -> $rf:ident ( $( $p:ident : $t:ident ),* )) =>
	{
		fn $rf<T: BitmapLike>(dummy:dummy, bitmap: &T, $( $p : $t ),* , flags: BitmapDrawingFlags)
		{
			target_bitmap_check(self.get_target_bitmap());
			unsafe
			{
				$cf(bitmap.get_bitmap(),
					$(
						cast_to_c!($p, $t)
					),*
				, (flags.get() << 1) as c_int);
			}
		}
	}
)

//~ wrap_bitmap_drawing!(al_draw_bitmap_region -> draw_bitmap_region(sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32))
//~ wrap_bitmap_drawing!(al_draw_bitmap_region -> draw_bitmap_region(sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32))
//~ wrap_bitmap_drawing!(al_draw_scaled_bitmap -> draw_scaled_bitmap(sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32, dw: f32, dh: f32))
//~ wrap_bitmap_drawing!(al_draw_rotated_bitmap -> draw_rotated_bitmap(cx: f32, cy: f32, dx: f32, dy: f32, angle: f32))
//~ wrap_bitmap_drawing!(al_draw_scaled_rotated_bitmap -> draw_scaled_rotated_bitmap(cx: f32, cy: f32, dx: f32, dy: f32, xscale: f32, yscale: f32, angle: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_bitmap -> draw_tinted_bitmap(tint: Color, dx: f32, dy: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_bitmap_region -> draw_tinted_bitmap_region(tint: Color, sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_scaled_bitmap -> draw_tinted_scaled_bitmap(tint: Color, sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32, dw: f32, dh: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_rotated_bitmap -> draw_tinted_rotated_bitmap(tint: Color, cx: f32, cy: f32, dx: f32, dy: f32, angle: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_scaled_rotated_bitmap -> draw_tinted_scaled_rotated_bitmap(tint: Color, cx: f32, cy: f32, dx: f32, dy: f32, xscale: f32, yscale: f32, angle: f32))
//~ wrap_bitmap_drawing!(al_draw_tinted_scaled_rotated_bitmap_region -> draw_tinted_scaled_rotated_bitmap_region(sx: f32, sy: f32, sw: f32, sh: f32, tint: Color, cx: f32, cy: f32, dx: f32, dy: f32, xscale: f32, yscale: f32, angle: f32))
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::convert::Into;

use mio;
use mio::Token;
use mio_extras::timer::Timeout;
use url;

use io::ALL;
use message;
use protocol::CloseCode;
use result::{Error, Result};
use std::cmp::PartialEq;
use std::hash::{Hash, Hasher};
use std::fmt;

#[derive(Debug, Clone)]
pub enum Signal {
    Message(message::Message),
    Close(CloseCode, Cow<'static, str>),
    Ping(Vec<u8>),
    Pong(Vec<u8>),
    Connect(url::Url),
    Shutdown,
    Timeout { delay: u64, token: Token },
    Cancel(Timeout),
}

#[derive(Debug, Clone)]
pub struct Command {
    token: Token,
    signal: Signal,
    connection_id: u32,
}

impl Command {
    pub fn token(&self) -> Token {
        self.token
    }

    pub fn into_signal(self) -> Signal {
        self.signal
    }

    pub fn connection_id(&self) -> u32 {
        self.connection_id
    }
}

/// A representation of the output of the WebSocket connection. Use this to send messages to the
/// other endpoint.
#[derive(Clone)]
pub struct Sender {
    token: Token,
    channel: mio::channel::SyncSender<Command>,
    connection_id: u32,
}

impl fmt::Debug for Sender {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            "Sender {{ token: {:?}, channel: mio::channel::SyncSender<Command>, connection_id: {:?} }}",
            self.token, self.connection_id)
    }
}

impl PartialEq for Sender {
    fn eq(&self, other: &Sender) -> bool {
        self.token == other.token && self.connection_id == other.connection_id
    }
}

// Fixes #255.
impl Eq for Sender { }

// Fixes #255.
impl Hash for Sender {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.connection_id.hash(state);
        self.token.hash(state);
    }
}

impl Sender {
    #[doc(hidden)]
    #[inline]
    pub fn new(
        token: Token,
        channel: mio::channel::SyncSender<Command>,
        connection_id: u32,
    ) -> Sender {
        Sender {
            token,
            channel,
            connection_id,
        }
    }

    /// A Token identifying this sender within the WebSocket.
    #[inline]
    pub fn token(&self) -> Token {
        self.token
    }

    /// A connection_id identifying this sender within the WebSocket.
    #[inline]
    pub fn connection_id(&self) -> u32 {
        self.connection_id
    }

    /// Send a message over the connection.
    #[inline]
    pub fn send<M>(&self, msg: M) -> Result<()>
    where
        M: Into<message::Message>,
    {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Message(msg.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a message to the endpoints of all connections.
    ///
    /// Be careful with this method. It does not discriminate between client and server connections.
    /// If your WebSocket is only functioning as a server, then usage is simple, this method will
    /// send a copy of the message to each connected client. However, if you have a WebSocket that
    /// is listening for connections and is also connected to another WebSocket, this method will
    /// broadcast a copy of the message to all the clients connected and to that WebSocket server.
    #[inline]
    pub fn broadcast<M>(&self, msg: M) -> Result<()>
    where
        M: Into<message::Message>,
    {
        self.channel
            .send(Command {
                token: ALL,
                signal: Signal::Message(msg.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a close code to the other endpoint.
    #[inline]
    pub fn close(&self, code: CloseCode) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Close(code, "".into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a close code and provide a descriptive reason for closing.
    #[inline]
    pub fn close_with_reason<S>(&self, code: CloseCode, reason: S) -> Result<()>
    where
        S: Into<Cow<'static, str>>,
    {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Close(code, reason.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a ping to the other endpoint with the given test data.
    #[inline]
    pub fn ping(&self, data: Vec<u8>) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Ping(data),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a pong to the other endpoint responding with the given test data.
    #[inline]
    pub fn pong(&self, data: Vec<u8>) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Pong(data),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Queue a new connection on this WebSocket to the specified URL.
    #[inline]
    pub fn connect(&self, url: url::Url) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Connect(url),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Request that all connections terminate and that the WebSocket stop running.
    #[inline]
    pub fn shutdown(&self) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Shutdown,
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Schedule a `token` to be sent to the WebSocket Handler's `on_timeout` method
    /// after `ms` milliseconds
    #[inline]
    pub fn timeout(&self, ms: u64, token: Token) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Timeout { delay: ms, token },
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Queue the cancellation of a previously scheduled timeout.
    ///
    /// This method is not guaranteed to prevent the timeout from occurring, because it is
    /// possible to call this method after a timeout has already occurred. It is still necessary to
    /// handle spurious timeouts.
    #[inline]
    pub fn cancel(&self, timeout: Timeout) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Cancel(timeout),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }
}
<commit_msg>Removed comments referencing issues.<commit_after>use std::borrow::Cow;
use std::convert::Into;

use mio;
use mio::Token;
use mio_extras::timer::Timeout;
use url;

use io::ALL;
use message;
use protocol::CloseCode;
use result::{Error, Result};
use std::cmp::PartialEq;
use std::hash::{Hash, Hasher};
use std::fmt;

#[derive(Debug, Clone)]
pub enum Signal {
    Message(message::Message),
    Close(CloseCode, Cow<'static, str>),
    Ping(Vec<u8>),
    Pong(Vec<u8>),
    Connect(url::Url),
    Shutdown,
    Timeout { delay: u64, token: Token },
    Cancel(Timeout),
}

#[derive(Debug, Clone)]
pub struct Command {
    token: Token,
    signal: Signal,
    connection_id: u32,
}

impl Command {
    pub fn token(&self) -> Token {
        self.token
    }

    pub fn into_signal(self) -> Signal {
        self.signal
    }

    pub fn connection_id(&self) -> u32 {
        self.connection_id
    }
}

/// A representation of the output of the WebSocket connection. Use this to send messages to the
/// other endpoint.
#[derive(Clone)]
pub struct Sender {
    token: Token,
    channel: mio::channel::SyncSender<Command>,
    connection_id: u32,
}

impl fmt::Debug for Sender {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            "Sender {{ token: {:?}, channel: mio::channel::SyncSender<Command>, connection_id: {:?} }}",
            self.token, self.connection_id)
    }
}

impl PartialEq for Sender {
    fn eq(&self, other: &Sender) -> bool {
        self.token == other.token && self.connection_id == other.connection_id
    }
}

impl Eq for Sender { }

impl Hash for Sender {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.connection_id.hash(state);
        self.token.hash(state);
    }
}

impl Sender {
    #[doc(hidden)]
    #[inline]
    pub fn new(
        token: Token,
        channel: mio::channel::SyncSender<Command>,
        connection_id: u32,
    ) -> Sender {
        Sender {
            token,
            channel,
            connection_id,
        }
    }

    /// A Token identifying this sender within the WebSocket.
    #[inline]
    pub fn token(&self) -> Token {
        self.token
    }

    /// A connection_id identifying this sender within the WebSocket.
    #[inline]
    pub fn connection_id(&self) -> u32 {
        self.connection_id
    }

    /// Send a message over the connection.
    #[inline]
    pub fn send<M>(&self, msg: M) -> Result<()>
    where
        M: Into<message::Message>,
    {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Message(msg.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a message to the endpoints of all connections.
    ///
    /// Be careful with this method. It does not discriminate between client and server connections.
    /// If your WebSocket is only functioning as a server, then usage is simple, this method will
    /// send a copy of the message to each connected client. However, if you have a WebSocket that
    /// is listening for connections and is also connected to another WebSocket, this method will
    /// broadcast a copy of the message to all the clients connected and to that WebSocket server.
    #[inline]
    pub fn broadcast<M>(&self, msg: M) -> Result<()>
    where
        M: Into<message::Message>,
    {
        self.channel
            .send(Command {
                token: ALL,
                signal: Signal::Message(msg.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a close code to the other endpoint.
    #[inline]
    pub fn close(&self, code: CloseCode) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Close(code, "".into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a close code and provide a descriptive reason for closing.
    #[inline]
    pub fn close_with_reason<S>(&self, code: CloseCode, reason: S) -> Result<()>
    where
        S: Into<Cow<'static, str>>,
    {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Close(code, reason.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a ping to the other endpoint with the given test data.
    #[inline]
    pub fn ping(&self, data: Vec<u8>) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Ping(data),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a pong to the other endpoint responding with the given test data.
    #[inline]
    pub fn pong(&self, data: Vec<u8>) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Pong(data),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Queue a new connection on this WebSocket to the specified URL.
    #[inline]
    pub fn connect(&self, url: url::Url) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Connect(url),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Request that all connections terminate and that the WebSocket stop running.
    #[inline]
    pub fn shutdown(&self) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Shutdown,
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Schedule a `token` to be sent to the WebSocket Handler's `on_timeout` method
    /// after `ms` milliseconds
    #[inline]
    pub fn timeout(&self, ms: u64, token: Token) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Timeout { delay: ms, token },
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Queue the cancellation of a previously scheduled timeout.
    ///
    /// This method is not guaranteed to prevent the timeout from occurring, because it is
    /// possible to call this method after a timeout has already occurred. It is still necessary to
    /// handle spurious timeouts.
    #[inline]
    pub fn cancel(&self, timeout: Timeout) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Cancel(timeout),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }
}
<|endoftext|>