<commit_before>use std::collections::BTreeMap;

/// top level document
#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Spec {
    /// version string
    pub swagger: String,
    pub info: Info,
    /// HTTP path to Operations mappings
    pub paths: BTreeMap<String, Operations>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub definitions: Option<BTreeMap<String, Schema>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub schemes: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub host: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="basePath")]
    pub base_path: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub consumes: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub produces: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub parameters: Option<BTreeMap<String, Parameter>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub responses: Option<BTreeMap<String, Response>>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="securityDefinitions")]
    pub security_definitions: Option<BTreeMap<String, Security>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub tags: Option<Vec<Tag>>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Tag {
    pub name: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="externalDocs")]
    pub external_docs: Option<Vec<ExternalDoc>>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct ExternalDoc {
    pub url: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub description: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Info {
    pub title: String,
    pub version: String,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="termsOfService")]
    pub terms_of_service: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Operations {
    #[serde(skip_serializing_if="Option::is_none")]
    pub get: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub post: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub put: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub patch: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub delete: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub options: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub head: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub parameters: Option<Vec<ParameterOrRef>>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Operation {
    #[serde(skip_serializing_if="Option::is_none")]
    pub summary: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub consumes: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub produces: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub schemes: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub tags: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="operationId")]
    pub operation_id: Option<String>,
    pub responses: BTreeMap<String, Response>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub parameters: Option<Vec<ParameterOrRef>>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Parameter {
    pub name: String,
    #[serde(rename="in")]
    pub location: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub required: Option<bool>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub schema: Option<Schema>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="uniqueItems")]
    pub unique_items: Option<bool>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="type")]
    pub param_type: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub format: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Response {
    pub description: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub schema: Option<Schema>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
pub enum ParameterOrRef {
    Parameter {
        name: String,
        #[serde(rename="in")]
        location: String,
        #[serde(skip_serializing_if="Option::is_none")]
        required: Option<bool>,
        #[serde(skip_serializing_if="Option::is_none")]
        schema: Option<Schema>,
        #[serde(skip_serializing_if="Option::is_none")]
        #[serde(rename="uniqueItems")]
        unique_items: Option<bool>,
        #[serde(skip_serializing_if="Option::is_none")]
        #[serde(rename="type")]
        param_type: Option<String>,
        #[serde(skip_serializing_if="Option::is_none")]
        format: Option<String>,
    },
    Ref {
        #[serde(rename="$ref")]
        location: String,
    },
}
#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(tag = "type")]
pub enum Security {
    #[serde(rename="apiKey")]
    ApiKey {
        name: String,
        #[serde(rename="in")]
        location: String,
    },
    #[serde(rename="oauth2")]
    Oauth2 {
        flow: String,
        #[serde(rename="authorizationUrl")]
        authorization_url: String,
        #[serde(rename="tokenUrl")]
        #[serde(skip_serializing_if="Option::is_none")]
        token_url: Option<String>,
        scopes: BTreeMap<String, String>,
    },
    #[serde(rename="basic")]
    Basic,
}

/// A [JSON schema](http://json-schema.org/) definition describing
/// the shape and properties of an object.
///
/// This may also contain a `$ref` to another definition
#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Schema {
    #[serde(skip_serializing_if="Option::is_none")]
    /// a [JSON reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03)
    /// path to another defintion
    #[serde(rename="$ref")]
    pub ref_path: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="type")]
    pub schema_type: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub format: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="enum")]
    pub enum_values: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub required: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub items: Option<Box<Schema>>,
    // implies object
    #[serde(skip_serializing_if="Option::is_none")]
    pub properties: Option<BTreeMap<String, Schema>>,
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json;
    use serde_yaml;
    use std::collections::BTreeMap;

    #[test]
    fn security_api_deserializes() {
        let json = r#"{"type":"apiKey", "name":"foo", "in": "query"}"#;
        assert_eq!(
            serde_yaml::from_str::<Security>(&json).unwrap(),
            Security::ApiKey {
                name: "foo".into(),
                location: "query".into(),
            }
        );
    }

    #[test]
    fn security_api_serializes() {
        let json = r#"{"type":"apiKey","name":"foo","in":"query"}"#;
        assert_eq!(
            serde_json::to_string(
                &Security::ApiKey {
                     name: "foo".into(),
                     location: "query".into(),
                 },
            )
                    .unwrap(),
            json
        );
    }

    #[test]
    fn security_basic_deserializes() {
        let json = r#"{"type":"basic"}"#;
        assert_eq!(
            serde_yaml::from_str::<Security>(&json).unwrap(),
            Security::Basic
        );
    }

    #[test]
    fn security_basic_serializes() {
        let json = r#"{"type":"basic"}"#;
        assert_eq!(json, serde_json::to_string(&Security::Basic).unwrap());
    }

    #[test]
    fn security_oauth_deserializes() {
        let json = r#"{"type":"oauth2","flow":"implicit","authorizationUrl":"foo/bar","scopes":{"foo":"bar"}}"#;
        let mut scopes = BTreeMap::new();
        scopes.insert("foo".into(), "bar".into());
        assert_eq!(
            serde_yaml::from_str::<Security>(&json).unwrap(),
            Security::Oauth2 {
                flow: "implicit".into(),
                authorization_url: "foo/bar".into(),
                token_url: None,
                scopes: scopes,
            }
        );
    }

    #[test]
    fn security_oauth_serializes() {
        let json = r#"{"type":"oauth2","flow":"implicit","authorizationUrl":"foo/bar","scopes":{"foo":"bar"}}"#;
        let mut scopes = BTreeMap::new();
        scopes.insert("foo".into(), "bar".into());
        assert_eq!(
            json,
            serde_json::to_string(
                &Security::Oauth2 {
                     flow: "implicit".into(),
                     authorization_url: "foo/bar".into(),
                     token_url: None,
                     scopes: scopes,
                 },
            )
                    .unwrap()
        );
    }

    #[test]
    fn parameter_or_ref_deserializes_ref() {
        let json = r#"{"$ref":"foo/bar"}"#;
        assert_eq!(
            serde_yaml::from_str::<ParameterOrRef>(&json).unwrap(),
            ParameterOrRef::Ref { location: "foo/bar".into() }
        );
    }

    #[test]
    fn parameter_or_ref_serializes_pref() {
        let json = r#"{"$ref":"foo/bar"}"#;
        assert_eq!(
            json,
            serde_json::to_string(&ParameterOrRef::Ref { location: "foo/bar".into() }).unwrap()
        );
    }
}
<commit_msg>more consistent name<commit_after>use std::collections::BTreeMap;

/// top level document
#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Spec {
    /// version string
    pub swagger: String,
    pub info: Info,
    /// HTTP path to Operations mappings
    pub paths: BTreeMap<String, Operations>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub definitions: Option<BTreeMap<String, Schema>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub schemes: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub host: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="basePath")]
    pub base_path: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub consumes: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub produces: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub parameters: Option<BTreeMap<String, Parameter>>,
    /// mappings to http response codes or "default"
    #[serde(skip_serializing_if="Option::is_none")]
    pub responses: Option<BTreeMap<String, Response>>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="securityDefinitions")]
    pub security_definitions: Option<BTreeMap<String, Security>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub tags: Option<Vec<Tag>>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Tag {
    pub name: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="externalDocs")]
    pub external_docs: Option<Vec<ExternalDoc>>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct ExternalDoc {
    pub url: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub description: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Info {
    pub title: String,
    pub version: String,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="termsOfService")]
    pub terms_of_service: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Operations {
    #[serde(skip_serializing_if="Option::is_none")]
    pub get: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub post: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub put: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub patch: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub delete: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub options: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub head: Option<Operation>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub parameters: Option<Vec<ParameterOrRef>>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Operation {
    #[serde(skip_serializing_if="Option::is_none")]
    pub summary: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub consumes: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub produces: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub schemes: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub tags: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="operationId")]
    pub operation_id: Option<String>,
    pub responses: BTreeMap<String, Response>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub parameters: Option<Vec<ParameterOrRef>>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Parameter {
    pub name: String,
    #[serde(rename="in")]
    pub location: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub required: Option<bool>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub schema: Option<Schema>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="uniqueItems")]
    pub unique_items: Option<bool>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="type")]
    pub param_type: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub format: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Response {
    pub description: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub schema: Option<Schema>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
pub enum ParameterOrRef {
    Parameter {
        name: String,
        #[serde(rename="in")]
        location: String,
        #[serde(skip_serializing_if="Option::is_none")]
        required: Option<bool>,
        #[serde(skip_serializing_if="Option::is_none")]
        schema: Option<Schema>,
        #[serde(skip_serializing_if="Option::is_none")]
        #[serde(rename="uniqueItems")]
        unique_items: Option<bool>,
        #[serde(skip_serializing_if="Option::is_none")]
        #[serde(rename="type")]
        param_type: Option<String>,
        #[serde(skip_serializing_if="Option::is_none")]
        format: Option<String>,
    },
    Ref {
        #[serde(rename="$ref")]
        ref_path: String,
    },
}
#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(tag = "type")]
pub enum Security {
    #[serde(rename="apiKey")]
    ApiKey {
        name: String,
        #[serde(rename="in")]
        location: String,
    },
    #[serde(rename="oauth2")]
    Oauth2 {
        flow: String,
        #[serde(rename="authorizationUrl")]
        authorization_url: String,
        #[serde(rename="tokenUrl")]
        #[serde(skip_serializing_if="Option::is_none")]
        token_url: Option<String>,
        scopes: BTreeMap<String, String>,
    },
    #[serde(rename="basic")]
    Basic,
}

/// A [JSON schema](http://json-schema.org/) definition describing
/// the shape and properties of an object.
///
/// This may also contain a `$ref` to another definition
#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Schema {
    #[serde(skip_serializing_if="Option::is_none")]
    /// a [JSON reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03)
    /// path to another defintion
    #[serde(rename="$ref")]
    pub ref_path: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="type")]
    pub schema_type: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub format: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    #[serde(rename="enum")]
    pub enum_values: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub required: Option<Vec<String>>,
    #[serde(skip_serializing_if="Option::is_none")]
    pub items: Option<Box<Schema>>,
    // implies object
    #[serde(skip_serializing_if="Option::is_none")]
    pub properties: Option<BTreeMap<String, Schema>>,
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json;
    use serde_yaml;
    use std::collections::BTreeMap;

    #[test]
    fn security_api_deserializes() {
        let json = r#"{"type":"apiKey", "name":"foo", "in": "query"}"#;
        assert_eq!(
            serde_yaml::from_str::<Security>(&json).unwrap(),
            Security::ApiKey {
                name: "foo".into(),
                location: "query".into(),
            }
        );
    }

    #[test]
    fn security_api_serializes() {
        let json = r#"{"type":"apiKey","name":"foo","in":"query"}"#;
        assert_eq!(
            serde_json::to_string(
                &Security::ApiKey {
                     name: "foo".into(),
                     location: "query".into(),
                 },
            )
                    .unwrap(),
            json
        );
    }

    #[test]
    fn security_basic_deserializes() {
        let json = r#"{"type":"basic"}"#;
        assert_eq!(
            serde_yaml::from_str::<Security>(&json).unwrap(),
            Security::Basic
        );
    }

    #[test]
    fn security_basic_serializes() {
        let json = r#"{"type":"basic"}"#;
        assert_eq!(json, serde_json::to_string(&Security::Basic).unwrap());
    }

    #[test]
    fn security_oauth_deserializes() {
        let json = r#"{"type":"oauth2","flow":"implicit","authorizationUrl":"foo/bar","scopes":{"foo":"bar"}}"#;
        let mut scopes = BTreeMap::new();
        scopes.insert("foo".into(), "bar".into());
        assert_eq!(
            serde_yaml::from_str::<Security>(&json).unwrap(),
            Security::Oauth2 {
                flow: "implicit".into(),
                authorization_url: "foo/bar".into(),
                token_url: None,
                scopes: scopes,
            }
        );
    }

    #[test]
    fn security_oauth_serializes() {
        let json = r#"{"type":"oauth2","flow":"implicit","authorizationUrl":"foo/bar","scopes":{"foo":"bar"}}"#;
        let mut scopes = BTreeMap::new();
        scopes.insert("foo".into(), "bar".into());
        assert_eq!(
            json,
            serde_json::to_string(
                &Security::Oauth2 {
                     flow: "implicit".into(),
                     authorization_url: "foo/bar".into(),
                     token_url: None,
                     scopes: scopes,
                 },
            )
                    .unwrap()
        );
    }

    #[test]
    fn parameter_or_ref_deserializes_ref() {
        let json = r#"{"$ref":"foo/bar"}"#;
        assert_eq!(
            serde_yaml::from_str::<ParameterOrRef>(&json).unwrap(),
            ParameterOrRef::Ref { ref_path: "foo/bar".into() }
        );
    }

    #[test]
    fn parameter_or_ref_serializes_pref() {
        let json = r#"{"$ref":"foo/bar"}"#;
        assert_eq!(
            json,
            serde_json::to_string(&ParameterOrRef::Ref { ref_path: "foo/bar".into() }).unwrap()
        );
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::mem;
use std::rc::Rc;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::thread;

use {spawn_unsafe, FnBox};
use sync::AtomicOption;

pub struct Scope<'a> {
    dtors: RefCell<Option<DtorChain<'a>>>
}

struct DtorChain<'a> {
    dtor: Box<FnBox + 'a>,
    next: Option<Box<DtorChain<'a>>>
}

enum JoinState {
    Running(thread::JoinHandle<()>),
    Joined,
}

impl JoinState {
    fn join(&mut self) {
        let mut state = JoinState::Joined;
        mem::swap(self, &mut state);
        if let JoinState::Running(handle) = state {
            let res = handle.join();

            if !thread::panicking() { res.unwrap(); }
        }
    }
}

pub struct ScopedJoinHandle<T> {
    inner: Rc<RefCell<JoinState>>,
    packet: Arc<AtomicOption<T>>,
    thread: thread::Thread,
}

pub fn scope<'a, F, R>(f: F) -> R where F: FnOnce(&Scope<'a>) -> R {
    let mut scope = Scope { dtors: RefCell::new(None) };
    let ret = f(&scope);
    scope.drop_all();
    ret
}

impl<'a> Scope<'a> {
    // This method is carefully written in a transactional style, so
    // that it can be called directly and, if any dtor panics, can be
    // resumed in the unwinding this causes. By initially running the
    // method outside of any destructor, we avoid any leakage problems
    // due to #14875.
    fn drop_all(&mut self) {
        loop {
            // use a separate scope to ensure that the RefCell borrow
            // is relinquishe before running `dtor`
            let dtor = {
                let mut dtors = self.dtors.borrow_mut();
                if let Some(mut node) = dtors.take() {
                    *dtors = node.next.take().map(|b| *b);
                    node.dtor
                } else {
                    return
                }
            };
            dtor.call_box()
        }
    }

    pub fn defer<F>(&self, f: F) where F: FnOnce() + 'a {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new)
        });
    }

    pub fn spawn<F, T>(&self, f: F) -> ScopedJoinHandle<T> where
        F: FnOnce() -> T + Send + 'a, T: Send + 'a
    {
        let their_packet = Arc::new(AtomicOption::new());
        let my_packet = their_packet.clone();

        let join_handle = unsafe {
            spawn_unsafe(move || {
                their_packet.swap(f(), Ordering::Relaxed);
            })
        };

        let thread = join_handle.thread().clone();
        let deferred_handle = Rc::new(RefCell::new(JoinState::Running(join_handle)));
        let my_handle = deferred_handle.clone();

        self.defer(move || {
            let mut state = deferred_handle.borrow_mut();
            state.join();
        });

        ScopedJoinHandle {
            inner: my_handle,
            packet: my_packet,
            thread: thread,
        }
    }
}

impl<T> ScopedJoinHandle<T> {
    pub fn join(self) -> T {
        self.inner.borrow_mut().join();
        self.packet.take(Ordering::Relaxed).unwrap()
    }

    pub fn thread(&self) -> &thread::Thread {
        &self.thread
    }
}

impl<'a> Drop for Scope<'a> {
    fn drop(&mut self) {
        self.drop_all()
    }
}
<commit_msg>Add documentation for scoped threads<commit_after>use std::cell::RefCell;
use std::mem;
use std::rc::Rc;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::thread;

use {spawn_unsafe, FnBox};
use sync::AtomicOption;

pub struct Scope<'a> {
    dtors: RefCell<Option<DtorChain<'a>>>
}

struct DtorChain<'a> {
    dtor: Box<FnBox + 'a>,
    next: Option<Box<DtorChain<'a>>>
}

enum JoinState {
    Running(thread::JoinHandle<()>),
    Joined,
}

impl JoinState {
    fn join(&mut self) {
        let mut state = JoinState::Joined;
        mem::swap(self, &mut state);
        if let JoinState::Running(handle) = state {
            let res = handle.join();

            if !thread::panicking() { res.unwrap(); }
        }
    }
}

pub struct ScopedJoinHandle<T> {
    inner: Rc<RefCell<JoinState>>,
    packet: Arc<AtomicOption<T>>,
    thread: thread::Thread,
}

/// Create a new `scope`, for scoped concurrency operations.
///
/// Using crossbeam for concurrency involves creating a [`Scope`][scope]. That's the job of
/// `scope`.
///
/// [scope]: struct.Scope.html
///
/// # Examples
///
/// Creating a scope:
///
/// ```
/// crossbeam::scope(|scope| {
///     // do stuff with scope here
/// });
/// ```
pub fn scope<'a, F, R>(f: F) -> R where F: FnOnce(&Scope<'a>) -> R {
    let mut scope = Scope { dtors: RefCell::new(None) };
    let ret = f(&scope);
    scope.drop_all();
    ret
}

impl<'a> Scope<'a> {
    // This method is carefully written in a transactional style, so
    // that it can be called directly and, if any dtor panics, can be
    // resumed in the unwinding this causes. By initially running the
    // method outside of any destructor, we avoid any leakage problems
    // due to @rust-lang/rust#14875.
    fn drop_all(&mut self) {
        loop {
            // use a separate scope to ensure that the RefCell borrow
            // is relinquishe before running `dtor`
            let dtor = {
                let mut dtors = self.dtors.borrow_mut();
                if let Some(mut node) = dtors.take() {
                    *dtors = node.next.take().map(|b| *b);
                    node.dtor
                } else {
                    return
                }
            };
            dtor.call_box()
        }
    }

    pub fn defer<F>(&self, f: F) where F: FnOnce() + 'a {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new)
        });
    }

    /// Create a scoped thread.
    ///
    /// `spawn` is similar to the [`spawn`][spawn] function in Rust's standard library. The
    /// difference is that this thread is scoped, meaning that it's guaranteed to terminate
    /// before the current stack frame goes away, allowing you to reference the parent stack frame
    /// directly. This is ensured by having the parent thread join on the child thread before the
    /// scope exits.
    ///
    /// [spawn]: http://doc.rust-lang.org/std/thread/fn.spawn.html
    ///
    /// # Examples
    ///
    /// A basic scoped thread:
    ///
    /// ```
    /// crossbeam::scope(|scope| {
    ///     scope.spawn(|| {
    ///         println!("Hello from a scoped thread!");
    ///     });
    /// });
    /// ```
    ///
    /// When writing concurrent Rust programs, you'll sometimes see a pattern like this, using
    /// [`std::thread::spawn`][spawn]:
    ///
    /// ```ignore
    /// let array = [1, 2, 3];
    /// let mut guards = vec![];
    ///
    /// for i in &array {
    ///     let guard = std::thread::spawn(move || {
    ///         println!("element: {}", i);
    ///     });
    ///
    ///     guards.push(guard);
    /// }
    ///
    /// for guard in guards {
    ///     guard.join().unwrap();
    /// }
    /// ```
    ///
    /// The basic pattern is:
    ///
    /// 1. Iterate over some collection.
    /// 2. Spin up a thread to operate on each part of the collection.
    /// 3. Join all the threads.
    ///
    /// However, this code actually gives an error:
    ///
    /// ```text
    /// error: `array` does not live long enough
    /// for i in &array {
    ///           ^~~~~
    /// in expansion of for loop expansion
    /// note: expansion site
    /// note: reference must be valid for the static lifetime...
    /// note: ...but borrowed value is only valid for the block suffix following statement 0 at ...
    ///     let array = [1, 2, 3];
    ///     let mut guards = vec![];
    ///
    ///     for i in &array {
    ///         let guard = std::thread::spawn(move || {
    ///             println!("element: {}", i);
    /// ...
    /// error: aborting due to previous error
    /// ```
    ///
    /// Because [`std::thread::spawn`][spawn] doesn't know about this scope, it requires a
    /// `'static` lifetime. One way of giving it a proper lifetime is to [`Box`][box] it up:
    ///
    /// [box]: http://doc.rust-lang.org/std/boxed/struct.Box.html
    ///
    /// ```
    /// let array = Box::new([1, 2, 3]);
    /// let mut guards = vec![];
    ///
    /// for i in (0..array.len()) {
    ///     let i = array[i];
    ///     let guard = std::thread::spawn(move || {
    ///         println!("element: {}", i);
    ///     });
    ///
    ///     guards.push(guard);
    /// }
    ///
    /// for guard in guards {
    ///     guard.join().unwrap();
    /// }
    /// ```
    ///
    /// But this introduces unnecessary allocation: we know that we're joining the threads before
    /// our function returns, so just taking a reference _should_ be safe. Rust can't know that,
    /// though.
    ///
    /// Enter scoped threads. Here's our original example, using `spawn` from crossbeam rather
    /// than from `std::thread`:
    ///
    /// ```
    /// let array = [1, 2, 3];
    ///
    /// crossbeam::scope(|scope| {
    ///     for i in &array {
    ///         scope.spawn(move || {
    ///             println!("element: {}", i);
    ///         });
    ///     }
    /// });
    /// ```
    ///
    /// Much more straightforward.
    pub fn spawn<F, T>(&self, f: F) -> ScopedJoinHandle<T> where
        F: FnOnce() -> T + Send + 'a, T: Send + 'a
    {
        let their_packet = Arc::new(AtomicOption::new());
        let my_packet = their_packet.clone();

        let join_handle = unsafe {
            spawn_unsafe(move || {
                their_packet.swap(f(), Ordering::Relaxed);
            })
        };

        let thread = join_handle.thread().clone();
        let deferred_handle = Rc::new(RefCell::new(JoinState::Running(join_handle)));
        let my_handle = deferred_handle.clone();

        self.defer(move || {
            let mut state = deferred_handle.borrow_mut();
            state.join();
        });

        ScopedJoinHandle {
            inner: my_handle,
            packet: my_packet,
            thread: thread,
        }
    }
}

impl<T> ScopedJoinHandle<T> {
    pub fn join(self) -> T {
        self.inner.borrow_mut().join();
        self.packet.take(Ordering::Relaxed).unwrap()
    }

    pub fn thread(&self) -> &thread::Thread {
        &self.thread
    }
}

impl<'a> Drop for Scope<'a> {
    fn drop(&mut self) {
        self.drop_all()
    }
}
<|endoftext|>


<commit_before>use std::cmp::min;
use std::mem;

use runtime::Messageable;
use id::{class, Id, IdVector};
use super::{INSCopying, INSObject};

pub trait INSDictionary<K: Messageable, V> : INSObject {
	fn count(&self) -> uint {
		let result = unsafe {
			msg_send![self.as_ptr() count]
		};
		result as uint
	}

	fn object_for<'a>(&'a self, key: &K) -> Option<&'a V> {
		unsafe {
			let obj = msg_send![self.as_ptr() objectForKey:key.as_ptr()];
			if obj.is_null() {
				None
			} else {
				Some(mem::transmute(obj))
			}
		}
	}

	unsafe fn from_refs<T: INSCopying<K>>(keys: &[&T], vals: &[&V]) -> Id<Self> {
		let cls = class::<Self>();
		let count = min(keys.len(), vals.len());
		let obj = msg_send![cls.as_ptr() alloc];
		let obj = msg_send![obj initWithObjects:vals.as_ptr()
		                                forKeys:keys.as_ptr()
		                                  count:count];
		Id::from_retained_ptr(obj as *Self)
	}

	fn from_keys_and_objects<T: INSCopying<K>>(keys: &[&T], vals: Vec<Id<V>>) -> Id<Self> {
		let vals_refs = vals.as_refs_slice();
		unsafe {
			INSDictionary::from_refs(keys, vals_refs)
		}
	}
}

object_struct!(NSDictionary<K, V>)

impl<K: Messageable, V> INSDictionary<K, V> for NSDictionary<K, V> { }

impl<K: Messageable, V> Collection for NSDictionary<K, V> {
	fn len(&self) -> uint {
		self.count()
	}
}
<commit_msg>Implemented Map for NSDictionary.<commit_after>use std::cmp::min;
use std::mem;

use runtime::Messageable;
use id::{class, Id, IdVector};
use super::{INSCopying, INSObject};

pub trait INSDictionary<K: Messageable, V> : INSObject {
	fn count(&self) -> uint {
		let result = unsafe {
			msg_send![self.as_ptr() count]
		};
		result as uint
	}

	fn object_for<'a>(&'a self, key: &K) -> Option<&'a V> {
		unsafe {
			let obj = msg_send![self.as_ptr() objectForKey:key.as_ptr()];
			if obj.is_null() {
				None
			} else {
				Some(mem::transmute(obj))
			}
		}
	}

	unsafe fn from_refs<T: INSCopying<K>>(keys: &[&T], vals: &[&V]) -> Id<Self> {
		let cls = class::<Self>();
		let count = min(keys.len(), vals.len());
		let obj = msg_send![cls.as_ptr() alloc];
		let obj = msg_send![obj initWithObjects:vals.as_ptr()
		                                forKeys:keys.as_ptr()
		                                  count:count];
		Id::from_retained_ptr(obj as *Self)
	}

	fn from_keys_and_objects<T: INSCopying<K>>(keys: &[&T], vals: Vec<Id<V>>) -> Id<Self> {
		let vals_refs = vals.as_refs_slice();
		unsafe {
			INSDictionary::from_refs(keys, vals_refs)
		}
	}
}

object_struct!(NSDictionary<K, V>)

impl<K: Messageable, V> INSDictionary<K, V> for NSDictionary<K, V> { }

impl<K: Messageable, V> Collection for NSDictionary<K, V> {
	fn len(&self) -> uint {
		self.count()
	}
}

impl<K: Messageable, V> Map<K, V> for NSDictionary<K, V> {
	fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
		self.object_for(key)
	}
}
<|endoftext|>


<commit_before>use super::command::{Command, Query};
use super::command::Command::Select;
use std::collections::HashMap;
use util;
use command_query::CommandQuery;
use queryable::Queryable;
use commandable::Commandable;
use command_line::CommandLine;
use selectable::fragmentable::Fragmentable;
use selectable::fragmentable::{OrderedFragment, QueryFragment};
use selectable::drilldown::Drilldown;
use selectable::drilldownable::Drilldownable;
use selectable::drilldown_builder::DrilldownBuilder;
use selectable::labeled_drilldown::LabeledDrilldown;
use selectable::labeled_drilldownable::LabeledDrilldownable;
use selectable::labeled_drilldown_builder::LabeledDrilldownBuilder;
use std::ops::Add;
use extendable::Extendable;
use request_cancellable::RequestCancellable;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SelectCommand {
    command: Command,
    table: String,
    arguments: HashMap<String, String>,
}

impl Default for SelectCommand {
    fn default() -> SelectCommand {
        SelectCommand {
            command: Select,
            table: "".to_string(),
            arguments: HashMap::new(),
        }
    }
}

impl SelectCommand {
    pub fn new(table: String) -> SelectCommand {
        let default: SelectCommand = Default::default();
        SelectCommand {
            command: default.command,
            table: table,
            arguments: default.arguments,
        }
    }

    pub fn filter(mut self, filter: String) -> SelectCommand {
        let encoded = format!("'{}'", filter);
        self.arguments.insert("filter".to_string(), encoded.clone());
        self
    }

    pub fn query(mut self, query: String) -> SelectCommand {
        let encoded = format!("'{}'", query);
        self.arguments.insert("query".to_string(), encoded.clone());
        self
    }

    pub fn match_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = util::split_values_vec(columns);
        self.arguments.insert("match_columns".to_string(), string.clone());
        self
    }

    pub fn output_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = util::split_values_vec(columns);
        self.arguments.insert("output_columns".to_string(), string.clone());
        self
    }

    pub fn offset(mut self, offset: i64) -> SelectCommand {
        let offset = format!("{}", offset);
        self.arguments.insert("offset".to_string(), offset.clone());
        self
    }

    pub fn limit(mut self, limit: i64) -> SelectCommand {
        let limit = format!("{}", limit);
        self.arguments.insert("limit".to_string(), limit.clone());
        self
    }

    pub fn cache(mut self, cache: bool) -> SelectCommand {
        let flag = match cache {
            true => "yes",
            false => "no",
        };
        self.arguments.insert("cache".to_string(), flag.to_string());
        self
    }

    pub fn build(self) -> (Command, Query) {
        let mut query: Query = vec![("table".to_string(), self.table)];
        for (key, value) in self.arguments.iter() {
            query.push((key.to_owned(), value.to_owned()));
        }
        (Select, query)
    }
}

impl Queryable for SelectCommand {
    fn to_query(self) -> String {
        let (command, query) = self.build();
        let mut command = CommandQuery::new(command, query);
        command.encode()
    }
}

impl Commandable for SelectCommand {
    fn to_command(self) -> String {
        let (command, query) = self.build();
        let mut command = CommandLine::new(command, query);
        command.encode()
    }
}

impl Fragmentable for SelectCommand {
    fn to_fragment(self) -> (OrderedFragment, QueryFragment) {
        let mut select_fragment = HashMap::new();
        let ordered_fragment = vec![("table".to_string(), self.table)];
        for (key, value) in self.arguments.clone() {
            select_fragment.insert(key, value);
        }
        (ordered_fragment, select_fragment)
    }
}

impl Add<Drilldown> for SelectCommand {
    type Output = DrilldownBuilder;

    fn add(self, rhs: Drilldown) -> DrilldownBuilder {
        let drilldown_builder = DrilldownBuilder::new(self, rhs);
        drilldown_builder
    }
}

impl Add<LabeledDrilldown> for SelectCommand {
    type Output = LabeledDrilldownBuilder;

    fn add(self, rhs: LabeledDrilldown) -> LabeledDrilldownBuilder {
        let labeled_drilldown_builder = LabeledDrilldownBuilder::new(self, rhs);
        labeled_drilldown_builder
    }
}

impl Drilldownable for SelectCommand {
    fn with_drilldown(self, rhs: Drilldown) -> DrilldownBuilder {
        let drilldown_builder = DrilldownBuilder::new(self, rhs);
        drilldown_builder
    }
}

impl LabeledDrilldownable for SelectCommand {
    fn with_labeled_drilldown(self, rhs: LabeledDrilldown) -> LabeledDrilldownBuilder {
        let labeled_drilldown_builder = LabeledDrilldownBuilder::new(self, rhs);
        labeled_drilldown_builder
    }
}

extendable!(SelectCommand);
request_cancellable!(SelectCommand);

#[cfg(test)]
mod test {
    use super::*;
    use command::Query;
    use command::Command::Select;
    use std::collections::HashMap;
    use queryable::Queryable;
    use commandable::Commandable;
    use selectable::drilldown::Drilldown;
    use selectable::drilldownable::Drilldownable;
    use selectable::drilldown_builder::DrilldownBuilder;
    use selectable::labeled_drilldown::LabeledDrilldown;
    use selectable::labeled_drilldownable::LabeledDrilldownable;
    use selectable::labeled_drilldown_builder::LabeledDrilldownBuilder;
    use extendable::Extendable;

    #[test]
    fn test_new() {
        let vanilla_select = SelectCommand::new("test".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: HashMap::new(),
        };
        assert_eq!(expected, vanilla_select);
    }

    #[test]
    fn test_filter() {
        let select = SelectCommand::new("test".to_string())
                         .filter("output_column @ \"type_safe\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("filter".to_string(),
                   "'output_column @ \"type_safe\"'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_query() {
        let select = SelectCommand::new("test".to_string())
                         .query("_key:\"http://example.org/\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("query".to_string(),
                   "\'_key:\"http://example.org/\"\'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_match_columns() {
        let select = SelectCommand::new("test".to_string())
                         .match_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("match_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_output_columns() {
        let select = SelectCommand::new("test".to_string())
                         .output_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("output_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_offset() {
        let select = SelectCommand::new("test".to_string()).offset(100);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("offset".to_string(), "100".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_limit() {
        let select = SelectCommand::new("test".to_string()).limit(50);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("limit".to_string(), "50".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_cache() {
        let select_yes = SelectCommand::new("test".to_string()).cache(true);
        let mut arg_yes: HashMap<String, String> = HashMap::new();
        arg_yes.insert("cache".to_string(), "yes".to_string());
        let expected_yes = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_yes,
        };
        assert_eq!(expected_yes, select_yes);
        let select_no = SelectCommand::new("test".to_string()).cache(false);
        let mut arg_no: HashMap<String, String> = HashMap::new();
        arg_no.insert("cache".to_string(), "no".to_string());
        let expected_no = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_no,
        };
        assert_eq!(expected_no, select_no);
    }

    #[test]
    fn test_build() {
        let actual = SelectCommand::new("test".to_string())
                         .filter("output_column @ \"type_safe\"".to_string())
                         .build();
        let expected_query: Query = vec![("table".to_string(), "test".to_string()),
                                         ("filter".to_string(),
                                          "'output_column @ \"type_safe\"'".to_string())];
        let expected = (Select, expected_query);
        assert_eq!(expected, actual);
    }

    #[test]
    fn test_queryable() {
        let query = SelectCommand::new("Test".to_string())
                        .filter("output_column @ \"type_safe\"".to_string())
                        .to_query();
        let url_encoded = "/d/select?table=Test&filter=%27output_column+%40+%22type_safe%22%27";
        assert_eq!(url_encoded.to_string(), query);
    }

    #[test]
    fn test_commandable() {
        let query = SelectCommand::new("Test".to_string())
                        .filter("output_column @ \"type_safe\"".to_string())
                        .to_command();
        let cli_encoded = "select --table Test --filter \'output_column @ \"type_safe\"\'";
        assert_eq!(cli_encoded.to_string(), query);
    }

    #[test]
    fn test_add_ops_drilldown() {
        let select = SelectCommand::new("Entries".to_string())
                         .filter("content @ \"fast\"".to_string());
        let drilldown = Drilldown::new().drilldown(vec![("tag".to_string())]);
        let ops_builder = (select.clone() + drilldown.clone()).build();
        let drilldown_builder = DrilldownBuilder::new(select.clone(), drilldown.clone()).build();
        assert_eq!(ops_builder, drilldown_builder);
    }

    #[test]
    fn test_add_ops_labedled_drilldown() {
        let select = SelectCommand::new("Entries".to_string())
                         .filter("content @ \"fast\"".to_string());
        let drilldown = LabeledDrilldown::new("labeled".to_string())
                            .keys(vec![("tag".to_string())]);
        let ops_builder = (select.clone() + drilldown.clone()).build();
        let drilldown_builder = LabeledDrilldownBuilder::new(select.clone(), drilldown.clone())
                                    .build();
        assert_eq!(ops_builder, drilldown_builder);
    }

    #[test]
    fn test_with_drilldown() {
        let select = SelectCommand::new("Entries".to_string())
                         .filter("content @ \"fast\"".to_string());
        let drilldown = Drilldown::new().drilldown(vec![("tag".to_string())]);
        let drilldownable = select.clone().with_drilldown(drilldown.clone()).build();
        let drilldown_builder = DrilldownBuilder::new(select.clone(), drilldown.clone()).build();
        assert_eq!(drilldownable, drilldown_builder);
    }

    #[test]
    fn test_with_labeled_drilldown() {
        let select = SelectCommand::new("Entries".to_string())
                         .filter("content @ \"fast\"".to_string());
        let drilldown = LabeledDrilldown::new("label".to_string()).keys(vec![("tag".to_string())]);
        let drilldownable = select.clone().with_labeled_drilldown(drilldown.clone()).build();
        let drilldown_builder = LabeledDrilldownBuilder::new(select.clone(), drilldown.clone())
                                    .build();
        assert_eq!(drilldownable, drilldown_builder);
    }

    #[test]
    fn test_extendable() {
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("user".to_string(), "defined".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "Test".to_string(),
            arguments: arg.clone(),
        };
        let query = SelectCommand::new("Test".to_string());
        unsafe {
            let extended = query.set_arguments(arg.clone());
            assert_eq!(expected, extended);
        }
    }
}
<commit_msg>select: Support query_flags argument<commit_after>use super::command::{Command, Query};
use super::command::Command::Select;
use std::collections::HashMap;
use util;
use types::select_query_flags::QueryFlagsType;
use command_query::CommandQuery;
use queryable::Queryable;
use commandable::Commandable;
use command_line::CommandLine;
use selectable::fragmentable::Fragmentable;
use selectable::fragmentable::{OrderedFragment, QueryFragment};
use selectable::drilldown::Drilldown;
use selectable::drilldownable::Drilldownable;
use selectable::drilldown_builder::DrilldownBuilder;
use selectable::labeled_drilldown::LabeledDrilldown;
use selectable::labeled_drilldownable::LabeledDrilldownable;
use selectable::labeled_drilldown_builder::LabeledDrilldownBuilder;
use std::ops::Add;
use extendable::Extendable;
use request_cancellable::RequestCancellable;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SelectCommand {
    command: Command,
    table: String,
    arguments: HashMap<String, String>,
}

impl Default for SelectCommand {
    fn default() -> SelectCommand {
        SelectCommand {
            command: Select,
            table: "".to_string(),
            arguments: HashMap::new(),
        }
    }
}

impl SelectCommand {
    pub fn new(table: String) -> SelectCommand {
        let default: SelectCommand = Default::default();
        SelectCommand {
            command: default.command,
            table: table,
            arguments: default.arguments,
        }
    }

    pub fn filter(mut self, filter: String) -> SelectCommand {
        let encoded = format!("'{}'", filter);
        self.arguments.insert("filter".to_string(), encoded.clone());
        self
    }

    pub fn query(mut self, query: String) -> SelectCommand {
        let encoded = format!("'{}'", query);
        self.arguments.insert("query".to_string(), encoded.clone());
        self
    }

    pub fn match_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = util::split_values_vec(columns);
        self.arguments.insert("match_columns".to_string(), string.clone());
        self
    }

    pub fn output_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = util::split_values_vec(columns);
        self.arguments.insert("output_columns".to_string(), string.clone());
        self
    }

    pub fn offset(mut self, offset: i64) -> SelectCommand {
        let offset = format!("{}", offset);
        self.arguments.insert("offset".to_string(), offset.clone());
        self
    }

    pub fn limit(mut self, limit: i64) -> SelectCommand {
        let limit = format!("{}", limit);
        self.arguments.insert("limit".to_string(), limit.clone());
        self
    }

    pub fn cache(mut self, cache: bool) -> SelectCommand {
        let flag = match cache {
            true => "yes",
            false => "no",
        };
        self.arguments.insert("cache".to_string(), flag.to_string());
        self
    }

    pub fn query_flags(mut self, flags: Vec<QueryFlagsType>) -> SelectCommand {
        let string = util::split_flags_vec(flags);
        self.arguments.insert("query_flags".to_string(), string.clone());
        self
    }

    pub fn build(self) -> (Command, Query) {
        let mut query: Query = vec![("table".to_string(), self.table)];
        for (key, value) in self.arguments.iter() {
            query.push((key.to_owned(), value.to_owned()));
        }
        (Select, query)
    }
}

impl Queryable for SelectCommand {
    fn to_query(self) -> String {
        let (command, query) = self.build();
        let mut command = CommandQuery::new(command, query);
        command.encode()
    }
}

impl Commandable for SelectCommand {
    fn to_command(self) -> String {
        let (command, query) = self.build();
        let mut command = CommandLine::new(command, query);
        command.encode()
    }
}

impl Fragmentable for SelectCommand {
    fn to_fragment(self) -> (OrderedFragment, QueryFragment) {
        let mut select_fragment = HashMap::new();
        let ordered_fragment = vec![("table".to_string(), self.table)];
        for (key, value) in self.arguments.clone() {
            select_fragment.insert(key, value);
        }
        (ordered_fragment, select_fragment)
    }
}

impl Add<Drilldown> for SelectCommand {
    type Output = DrilldownBuilder;

    fn add(self, rhs: Drilldown) -> DrilldownBuilder {
        let drilldown_builder = DrilldownBuilder::new(self, rhs);
        drilldown_builder
    }
}

impl Add<LabeledDrilldown> for SelectCommand {
    type Output = LabeledDrilldownBuilder;

    fn add(self, rhs: LabeledDrilldown) -> LabeledDrilldownBuilder {
        let labeled_drilldown_builder = LabeledDrilldownBuilder::new(self, rhs);
        labeled_drilldown_builder
    }
}

impl Drilldownable for SelectCommand {
    fn with_drilldown(self, rhs: Drilldown) -> DrilldownBuilder {
        let drilldown_builder = DrilldownBuilder::new(self, rhs);
        drilldown_builder
    }
}

impl LabeledDrilldownable for SelectCommand {
    fn with_labeled_drilldown(self, rhs: LabeledDrilldown) -> LabeledDrilldownBuilder {
        let labeled_drilldown_builder = LabeledDrilldownBuilder::new(self, rhs);
        labeled_drilldown_builder
    }
}

extendable!(SelectCommand);
request_cancellable!(SelectCommand);

#[cfg(test)]
mod test {
    use super::*;
    use command::Query;
    use command::Command::Select;
    use std::collections::HashMap;
    use types::select_query_flags::QueryFlagsType;
    use queryable::Queryable;
    use commandable::Commandable;
    use selectable::drilldown::Drilldown;
    use selectable::drilldownable::Drilldownable;
    use selectable::drilldown_builder::DrilldownBuilder;
    use selectable::labeled_drilldown::LabeledDrilldown;
    use selectable::labeled_drilldownable::LabeledDrilldownable;
    use selectable::labeled_drilldown_builder::LabeledDrilldownBuilder;
    use extendable::Extendable;

    #[test]
    fn test_new() {
        let vanilla_select = SelectCommand::new("test".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: HashMap::new(),
        };
        assert_eq!(expected, vanilla_select);
    }

    #[test]
    fn test_filter() {
        let select = SelectCommand::new("test".to_string())
                         .filter("output_column @ \"type_safe\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("filter".to_string(),
                   "'output_column @ \"type_safe\"'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_query() {
        let select = SelectCommand::new("test".to_string())
                         .query("_key:\"http://example.org/\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("query".to_string(),
                   "\'_key:\"http://example.org/\"\'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_match_columns() {
        let select = SelectCommand::new("test".to_string())
                         .match_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("match_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_output_columns() {
        let select = SelectCommand::new("test".to_string())
                         .output_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("output_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_offset() {
        let select = SelectCommand::new("test".to_string()).offset(100);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("offset".to_string(), "100".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_limit() {
        let select = SelectCommand::new("test".to_string()).limit(50);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("limit".to_string(), "50".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_cache() {
        let select_yes = SelectCommand::new("test".to_string()).cache(true);
        let mut arg_yes: HashMap<String, String> = HashMap::new();
        arg_yes.insert("cache".to_string(), "yes".to_string());
        let expected_yes = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_yes,
        };
        assert_eq!(expected_yes, select_yes);
        let select_no = SelectCommand::new("test".to_string()).cache(false);
        let mut arg_no: HashMap<String, String> = HashMap::new();
        arg_no.insert("cache".to_string(), "no".to_string());
        let expected_no = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_no,
        };
        assert_eq!(expected_no, select_no);
    }

    #[test]
    fn test_query_flags() {
        let select = SelectCommand::new("test".to_string())
                         .query_flags(vec![(QueryFlagsType::AllowColumn),
                                           (QueryFlagsType::AllowUpdate)]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("query_flags".to_string(),
                   "ALLOW_COLUMN|ALLOW_UPDATE".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_build() {
        let actual = SelectCommand::new("test".to_string())
                         .filter("output_column @ \"type_safe\"".to_string())
                         .build();
        let expected_query: Query = vec![("table".to_string(), "test".to_string()),
                                         ("filter".to_string(),
                                          "'output_column @ \"type_safe\"'".to_string())];
        let expected = (Select, expected_query);
        assert_eq!(expected, actual);
    }

    #[test]
    fn test_queryable() {
        let query = SelectCommand::new("Test".to_string())
                        .filter("output_column @ \"type_safe\"".to_string())
                        .to_query();
        let url_encoded = "/d/select?table=Test&filter=%27output_column+%40+%22type_safe%22%27";
        assert_eq!(url_encoded.to_string(), query);
    }

    #[test]
    fn test_commandable() {
        let query = SelectCommand::new("Test".to_string())
                        .filter("output_column @ \"type_safe\"".to_string())
                        .to_command();
        let cli_encoded = "select --table Test --filter \'output_column @ \"type_safe\"\'";
        assert_eq!(cli_encoded.to_string(), query);
    }

    #[test]
    fn test_add_ops_drilldown() {
        let select = SelectCommand::new("Entries".to_string())
                         .filter("content @ \"fast\"".to_string());
        let drilldown = Drilldown::new().drilldown(vec![("tag".to_string())]);
        let ops_builder = (select.clone() + drilldown.clone()).build();
        let drilldown_builder = DrilldownBuilder::new(select.clone(), drilldown.clone()).build();
        assert_eq!(ops_builder, drilldown_builder);
    }

    #[test]
    fn test_add_ops_labedled_drilldown() {
        let select = SelectCommand::new("Entries".to_string())
                         .filter("content @ \"fast\"".to_string());
        let drilldown = LabeledDrilldown::new("labeled".to_string())
                            .keys(vec![("tag".to_string())]);
        let ops_builder = (select.clone() + drilldown.clone()).build();
        let drilldown_builder = LabeledDrilldownBuilder::new(select.clone(), drilldown.clone())
                                    .build();
        assert_eq!(ops_builder, drilldown_builder);
    }

    #[test]
    fn test_with_drilldown() {
        let select = SelectCommand::new("Entries".to_string())
                         .filter("content @ \"fast\"".to_string());
        let drilldown = Drilldown::new().drilldown(vec![("tag".to_string())]);
        let drilldownable = select.clone().with_drilldown(drilldown.clone()).build();
        let drilldown_builder = DrilldownBuilder::new(select.clone(), drilldown.clone()).build();
        assert_eq!(drilldownable, drilldown_builder);
    }

    #[test]
    fn test_with_labeled_drilldown() {
        let select = SelectCommand::new("Entries".to_string())
                         .filter("content @ \"fast\"".to_string());
        let drilldown = LabeledDrilldown::new("label".to_string()).keys(vec![("tag".to_string())]);
        let drilldownable = select.clone().with_labeled_drilldown(drilldown.clone()).build();
        let drilldown_builder = LabeledDrilldownBuilder::new(select.clone(), drilldown.clone())
                                    .build();
        assert_eq!(drilldownable, drilldown_builder);
    }

    #[test]
    fn test_extendable() {
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("user".to_string(), "defined".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "Test".to_string(),
            arguments: arg.clone(),
        };
        let query = SelectCommand::new("Test".to_string());
        unsafe {
            let extended = query.set_arguments(arg.clone());
            assert_eq!(expected, extended);
        }
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
use std::io;

use tokio_core::reactor;
use tokio_core::net::TcpListener;

use futures::future;
use futures::future::Future;
use futures::future::join_all;
use futures::stream;
use futures::stream::Stream;

use error::Error;

use solicit_async::*;

use futures_misc::*;

use net2;

use super::server_conn::*;
use super::common::*;

use service::Service;

use server_conf::*;

pub use server_tls::ServerTlsOption;

struct LoopToServer {
    shutdown: ShutdownSignal,
    local_addr: SocketAddr,
}

pub struct Server {
    state: Arc<Mutex<ServerState>>,
    loop_to_server: LoopToServer,
    alive_rx: mpsc::Receiver<()>,
    thread_join_handle: Option<thread::JoinHandle<()>>,
}

#[derive(Default)]
struct ServerState {
    last_conn_id: u64,
    conns: HashMap<u64, ServerConnection>,
}

impl ServerState {
    fn snapshot(&self) -> HttpFutureSend<ServerStateSnapshot> {
        let futures: Vec<_> = self.conns.iter()
            .map(|(&id, conn)| conn.dump_state().map(move |state| (id, state)))
            .collect();

        Box::new(join_all(futures)
            .map(|states| ServerStateSnapshot {
                conns: states.into_iter().collect(),
            }))
    }
}

pub struct ServerStateSnapshot {
    pub conns: HashMap<u64, ConnectionStateSnapshot>,
}

impl ServerStateSnapshot {
    pub fn single_conn(&self) -> (u64, &ConnectionStateSnapshot) {
        let mut iter = self.conns.iter();
        let (&id, conn) = iter.next().expect("no conns");
        assert!(iter.next().is_none(), "more than one conn");
        (id, conn)
    }
}

#[cfg(unix)]
fn configure_tcp(tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    use net2::unix::UnixTcpBuilderExt;
    if let Some(reuse_port) = conf.reuse_port {
        tcp.reuse_port(reuse_port)?;
    }
    Ok(())
}

#[cfg(windows)]
fn configure_tcp(_tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    Ok(())
}

fn listener(
    addr: &SocketAddr,
    handle: &reactor::Handle,
    conf: &ServerConf)
        -> io::Result<TcpListener>
{
    let listener = match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?,
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?,
    };
    configure_tcp(&listener, conf)?;
    listener.reuse_address(true)?;
    listener.bind(addr)?;
    let backlog = conf.backlog.unwrap_or(1024);
    let listener = listener.listen(backlog)?;
    TcpListener::from_listener(listener, addr, handle)
}

fn run_server_event_loop<S>(
    listen_addr: SocketAddr,
    state: Arc<Mutex<ServerState>>,
    tls: ServerTlsOption,
    conf: ServerConf,
    service: S,
    send_to_back: mpsc::Sender<LoopToServer>,
    _alive_tx: mpsc::Sender<()>)
        where S : Service,
{
    let service = Arc::new(service);

    let mut lp = reactor::Core::new().expect("http2server");

    let (shutdown_signal, shutdown_future) = shutdown_signal();

    let listen = listener(&listen_addr, &lp.handle(), &conf).unwrap();

    let stuff = stream::repeat((lp.handle(), service, state, tls, conf));

    let local_addr = listen.local_addr().unwrap();
    send_to_back
        .send(LoopToServer { shutdown: shutdown_signal, local_addr: local_addr })
        .expect("send back");

    let loop_run = listen.incoming().map_err(Error::from).zip(stuff)
        .for_each(move |((socket, peer_addr), (loop_handle, service, state, tls, conf))| {
            info!("accepted connection from {}", peer_addr);

            let no_delay = conf.no_delay.unwrap_or(true);
            socket.set_nodelay(no_delay).expect("failed to set TCP_NODELAY");

            let (conn, future) = ServerConnection::new(&loop_handle, socket, tls, conf, service);

            let conn_id = {
                let mut g = state.lock().expect("lock");
                g.last_conn_id += 1;
                let conn_id = g.last_conn_id;
                let prev = g.conns.insert(conn_id, conn);
                assert!(prev.is_none());
                conn_id
            };

            loop_handle.spawn(future
                .then(move |r| {
                    let mut g = state.lock().expect("lock");
                    let removed = g.conns.remove(&conn_id);
                    assert!(removed.is_some());
                    r
                })
                .map_err(|e| { warn!("connection end: {:?}", e); () }));
            Ok(())
        });

    let shutdown_future = shutdown_future
        .then(move |_| {
            // Must complete with error,
            // so `join` with this future cancels another future.
            future::failed::<(), _>(Error::Shutdown)
        });

    // Wait for either completion of connection (i. e. error)
    // or shutdown signal.
    let done = loop_run.join(shutdown_future);

    // TODO: do not ignore error
    lp.run(done).ok();
}

impl Server {
    pub fn new<A: ToSocketAddrs, S>(addr: A, tls: ServerTlsOption, conf: ServerConf, service: S) -> Server
        where S : Service
    {
        let listen_addr = addr.to_socket_addrs().unwrap().next().unwrap();

        let (get_from_loop_tx, get_from_loop_rx) = mpsc::channel();
        let (alive_tx, alive_rx) = mpsc::channel();

        let state: Arc<Mutex<ServerState>> = Default::default();

        let state_copy = state.clone();

        let join_handle = thread::Builder::new()
            .name(conf.thread_name.clone().unwrap_or_else(|| "http2-server-loop".to_owned()).to_string())
            .spawn(move || {
                run_server_event_loop(
                    listen_addr,
                    state_copy,
                    tls,
                    conf, service,
                    get_from_loop_tx,
                    alive_tx);
            })
            .expect("spawn");

        let loop_to_server = get_from_loop_rx.recv().unwrap();

        Server {
            state: state,
            loop_to_server: loop_to_server,
            thread_join_handle: Some(join_handle),
            alive_rx: alive_rx,
        }
    }

    pub fn local_addr(&self) -> &SocketAddr {
        &self.loop_to_server.local_addr
    }

    pub fn is_alive(&self) -> bool {
        self.alive_rx.try_recv() != Err(mpsc::TryRecvError::Disconnected)
    }

    // for tests
    pub fn dump_state(&self) -> HttpFutureSend<ServerStateSnapshot> {
        let g = self.state.lock().expect("lock");
        g.snapshot()
    }
}

// We shutdown the server in the destructor.
impl Drop for Server {
    fn drop(&mut self) {
        self.loop_to_server.shutdown.shutdown();

        // do not ignore errors of take
        // ignore errors of join, it means that server event loop crashed
        drop(self.thread_join_handle.take().unwrap().join());
    }
}

<commit_msg>TODO: Server::new should return Result<commit_after>use std::thread;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
use std::io;

use tokio_core::reactor;
use tokio_core::net::TcpListener;

use futures::future;
use futures::future::Future;
use futures::future::join_all;
use futures::stream;
use futures::stream::Stream;

use error::Error;

use solicit_async::*;

use futures_misc::*;

use net2;

use super::server_conn::*;
use super::common::*;

use service::Service;

use server_conf::*;

pub use server_tls::ServerTlsOption;

struct LoopToServer {
    shutdown: ShutdownSignal,
    local_addr: SocketAddr,
}

pub struct Server {
    state: Arc<Mutex<ServerState>>,
    loop_to_server: LoopToServer,
    alive_rx: mpsc::Receiver<()>,
    thread_join_handle: Option<thread::JoinHandle<()>>,
}

#[derive(Default)]
struct ServerState {
    last_conn_id: u64,
    conns: HashMap<u64, ServerConnection>,
}

impl ServerState {
    fn snapshot(&self) -> HttpFutureSend<ServerStateSnapshot> {
        let futures: Vec<_> = self.conns.iter()
            .map(|(&id, conn)| conn.dump_state().map(move |state| (id, state)))
            .collect();

        Box::new(join_all(futures)
            .map(|states| ServerStateSnapshot {
                conns: states.into_iter().collect(),
            }))
    }
}

pub struct ServerStateSnapshot {
    pub conns: HashMap<u64, ConnectionStateSnapshot>,
}

impl ServerStateSnapshot {
    pub fn single_conn(&self) -> (u64, &ConnectionStateSnapshot) {
        let mut iter = self.conns.iter();
        let (&id, conn) = iter.next().expect("no conns");
        assert!(iter.next().is_none(), "more than one conn");
        (id, conn)
    }
}

#[cfg(unix)]
fn configure_tcp(tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    use net2::unix::UnixTcpBuilderExt;
    if let Some(reuse_port) = conf.reuse_port {
        tcp.reuse_port(reuse_port)?;
    }
    Ok(())
}

#[cfg(windows)]
fn configure_tcp(_tcp: &net2::TcpBuilder, conf: &ServerConf) -> io::Result<()> {
    Ok(())
}

fn listener(
    addr: &SocketAddr,
    handle: &reactor::Handle,
    conf: &ServerConf)
        -> io::Result<TcpListener>
{
    let listener = match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?,
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?,
    };
    configure_tcp(&listener, conf)?;
    listener.reuse_address(true)?;
    listener.bind(addr)?;
    let backlog = conf.backlog.unwrap_or(1024);
    let listener = listener.listen(backlog)?;
    TcpListener::from_listener(listener, addr, handle)
}

fn run_server_event_loop<S>(
    listen_addr: SocketAddr,
    state: Arc<Mutex<ServerState>>,
    tls: ServerTlsOption,
    conf: ServerConf,
    service: S,
    send_to_back: mpsc::Sender<LoopToServer>,
    _alive_tx: mpsc::Sender<()>)
        where S : Service,
{
    let service = Arc::new(service);

    let mut lp = reactor::Core::new().expect("http2server");

    let (shutdown_signal, shutdown_future) = shutdown_signal();

    let listen = listener(&listen_addr, &lp.handle(), &conf).unwrap();

    let stuff = stream::repeat((lp.handle(), service, state, tls, conf));

    let local_addr = listen.local_addr().unwrap();
    send_to_back
        .send(LoopToServer { shutdown: shutdown_signal, local_addr: local_addr })
        .expect("send back");

    let loop_run = listen.incoming().map_err(Error::from).zip(stuff)
        .for_each(move |((socket, peer_addr), (loop_handle, service, state, tls, conf))| {
            info!("accepted connection from {}", peer_addr);

            let no_delay = conf.no_delay.unwrap_or(true);
            socket.set_nodelay(no_delay).expect("failed to set TCP_NODELAY");

            let (conn, future) = ServerConnection::new(&loop_handle, socket, tls, conf, service);

            let conn_id = {
                let mut g = state.lock().expect("lock");
                g.last_conn_id += 1;
                let conn_id = g.last_conn_id;
                let prev = g.conns.insert(conn_id, conn);
                assert!(prev.is_none());
                conn_id
            };

            loop_handle.spawn(future
                .then(move |r| {
                    let mut g = state.lock().expect("lock");
                    let removed = g.conns.remove(&conn_id);
                    assert!(removed.is_some());
                    r
                })
                .map_err(|e| { warn!("connection end: {:?}", e); () }));
            Ok(())
        });

    let shutdown_future = shutdown_future
        .then(move |_| {
            // Must complete with error,
            // so `join` with this future cancels another future.
            future::failed::<(), _>(Error::Shutdown)
        });

    // Wait for either completion of connection (i. e. error)
    // or shutdown signal.
    let done = loop_run.join(shutdown_future);

    // TODO: do not ignore error
    lp.run(done).ok();
}

impl Server {
    // TODO: result
    pub fn new<A: ToSocketAddrs, S>(addr: A, tls: ServerTlsOption, conf: ServerConf, service: S) -> Server
        where S : Service
    {
        let listen_addr = addr.to_socket_addrs().unwrap().next().unwrap();

        let (get_from_loop_tx, get_from_loop_rx) = mpsc::channel();
        let (alive_tx, alive_rx) = mpsc::channel();

        let state: Arc<Mutex<ServerState>> = Default::default();

        let state_copy = state.clone();

        let join_handle = thread::Builder::new()
            .name(conf.thread_name.clone().unwrap_or_else(|| "http2-server-loop".to_owned()).to_string())
            .spawn(move || {
                run_server_event_loop(
                    listen_addr,
                    state_copy,
                    tls,
                    conf, service,
                    get_from_loop_tx,
                    alive_tx);
            })
            .expect("spawn");

        let loop_to_server = get_from_loop_rx.recv().unwrap();

        Server {
            state: state,
            loop_to_server: loop_to_server,
            thread_join_handle: Some(join_handle),
            alive_rx: alive_rx,
        }
    }

    pub fn local_addr(&self) -> &SocketAddr {
        &self.loop_to_server.local_addr
    }

    pub fn is_alive(&self) -> bool {
        self.alive_rx.try_recv() != Err(mpsc::TryRecvError::Disconnected)
    }

    // for tests
    pub fn dump_state(&self) -> HttpFutureSend<ServerStateSnapshot> {
        let g = self.state.lock().expect("lock");
        g.snapshot()
    }
}

// We shutdown the server in the destructor.
impl Drop for Server {
    fn drop(&mut self) {
        self.loop_to_server.shutdown.shutdown();

        // do not ignore errors of take
        // ignore errors of join, it means that server event loop crashed
        drop(self.thread_join_handle.take().unwrap().join());
    }
}

<|endoftext|>


<commit_before>use device;
use device::draw::CommandBuffer;
use gfx;
use gfx::{ Device, DeviceHelper, ToSlice };
use gfx::render;
use vecmath::Matrix4;

static VERTEX: gfx::ShaderSource<'static> = shaders! {
glsl_120: b"
    #version 120
    uniform mat4 projection, view;

    attribute vec2 tex_coord;
    attribute vec3 color, position;

    varying vec2 v_tex_coord;
    varying vec3 v_color;

    void main() {
        v_tex_coord = tex_coord;
        v_color = color;
        gl_Position = projection * view * vec4(position, 1.0);
    }
",
glsl_150: b"
    #version 150 core
    uniform mat4 projection, view;

    in vec2 tex_coord;
    in vec3 color, position;

    out vec2 v_tex_coord;
    out vec3 v_color;

    void main() {
        v_tex_coord = tex_coord;
        v_color = color;
        gl_Position = projection * view * vec4(position, 1.0);
    }
"
};

static FRAGMENT: gfx::ShaderSource<'static> = shaders!{
glsl_120: b"
    #version 120

    uniform sampler2D s_texture;

    varying vec2 v_tex_coord;
    varying vec3 v_color;

    void main() {
        vec4 tex_color = texture2D(s_texture, v_tex_coord);
        if(tex_color.a == 0.0) // Discard transparent pixels.
            discard;
        gl_FragColor = tex_color * vec4(v_color, 1.0);
    }
",
glsl_150: b"
    #version 150 core
    out vec4 out_color;

    uniform sampler2D s_texture;

    in vec2 v_tex_coord;
    in vec3 v_color;

    void main() {
        vec4 tex_color = texture(s_texture, v_tex_coord);
        if(tex_color.a == 0.0) // Discard transparent pixels.
            discard;
        out_color = tex_color * vec4(v_color, 1.0);
    }
"
};

#[shader_param]
#[derive(Copy)]
pub struct ShaderParam {
    pub projection: [[f32; 4]; 4],
    pub view: [[f32; 4]; 4],
    pub s_texture: gfx::shade::TextureParam,
}

#[vertex_format]
#[derive(Copy)]
pub struct Vertex {
    #[name="position"]
    pub xyz: [f32; 3],
    #[name="tex_coord"]
    pub uv: [f32; 2],
    #[name="color"]
    pub rgb: [f32; 3],
}

impl Clone for Vertex {
    fn clone(&self) -> Vertex {
        *self
    }
}

pub struct Buffer {
    buf: gfx::BufferHandle<Vertex>,
    batch: gfx::batch::RefBatch<ShaderParam>,
}

pub struct Renderer<D: Device> {
    graphics: gfx::Graphics<D>,
    params: ShaderParam,
    frame: gfx::Frame,
    cd: gfx::ClearData,
    prog: device::Handle<u32, device::shade::ProgramInfo>,
    drawstate: gfx::DrawState
}

impl<D: Device> Renderer<D> {
    pub fn new(mut device: D, frame: gfx::Frame, tex: gfx::TextureHandle) -> Renderer<D> {
        let sampler = device.create_sampler(
                gfx::tex::SamplerInfo::new(
                    gfx::tex::FilterMethod::Scale,
                    gfx::tex::WrapMode::Tile
                )
            );
        let mut graphics = gfx::Graphics::new(device);

        let params = ShaderParam {
            projection: [[0.0; 4]; 4],
            view: [[0.0; 4]; 4],
            s_texture: (tex, Some(sampler))
        };
        let prog = graphics.device.link_program(VERTEX.clone(), FRAGMENT.clone()).ok().unwrap();
        let mut drawstate = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);
        drawstate.primitive.front_face = gfx::state::WindingOrder::Clockwise;

        Renderer {
            graphics: graphics,
            params: params,
            frame: frame,
            cd: gfx::ClearData {
                color: [0.81, 0.8, 1.0, 1.0],
                depth: 1.0,
                stencil: 0,
            },
            prog: prog,
            drawstate: drawstate,
        }
    }

    pub fn set_projection(&mut self, proj_mat: Matrix4<f32>) {
        self.params.projection = proj_mat;
    }

    pub fn set_view(&mut self, view_mat: Matrix4<f32>) {
        self.params.view = view_mat;
    }

    pub fn clear(&mut self) {
        self.graphics.clear(self.cd, gfx::COLOR | gfx::DEPTH, &self.frame);
    }

    pub fn create_buffer(&mut self, data: &[Vertex]) -> Buffer {
        let buf = self.graphics.device.create_buffer(data.len(), gfx::BufferUsage::Static);
        self.graphics.device.update_buffer(buf, data, 0);
        let mesh = gfx::Mesh::from_format(buf, data.len() as u32);
        Buffer {
            buf: buf,
            batch: self.graphics.make_batch(
                    &self.prog,
                    &mesh,
                    mesh.to_slice(gfx::PrimitiveType::TriangleList),
                    &self.drawstate
                ).ok().unwrap()
        }
    }

    pub fn delete_buffer(&mut self, buf: Buffer) {
        self.graphics.device.delete_buffer(buf.buf);
    }

    pub fn render(&mut self, buffer: Buffer) {
        self.graphics.draw(&buffer.batch, &self.params, &self.frame);
    }

    pub fn end_frame(&mut self) {
        self.graphics.end_frame();
    }
}
<commit_msg>Fix build errors.<commit_after>use device;
use device::draw::CommandBuffer;
use gfx;
use gfx::{ Device, DeviceHelper, ToSlice };
use gfx::render;
use vecmath::Matrix4;

static VERTEX: gfx::ShaderSource<'static> = shaders! {
glsl_120: b"
    #version 120
    uniform mat4 projection, view;

    attribute vec2 tex_coord;
    attribute vec3 color, position;

    varying vec2 v_tex_coord;
    varying vec3 v_color;

    void main() {
        v_tex_coord = tex_coord;
        v_color = color;
        gl_Position = projection * view * vec4(position, 1.0);
    }
",
glsl_150: b"
    #version 150 core
    uniform mat4 projection, view;

    in vec2 tex_coord;
    in vec3 color, position;

    out vec2 v_tex_coord;
    out vec3 v_color;

    void main() {
        v_tex_coord = tex_coord;
        v_color = color;
        gl_Position = projection * view * vec4(position, 1.0);
    }
"
};

static FRAGMENT: gfx::ShaderSource<'static> = shaders!{
glsl_120: b"
    #version 120

    uniform sampler2D s_texture;

    varying vec2 v_tex_coord;
    varying vec3 v_color;

    void main() {
        vec4 tex_color = texture2D(s_texture, v_tex_coord);
        if(tex_color.a == 0.0) // Discard transparent pixels.
            discard;
        gl_FragColor = tex_color * vec4(v_color, 1.0);
    }
",
glsl_150: b"
    #version 150 core
    out vec4 out_color;

    uniform sampler2D s_texture;

    in vec2 v_tex_coord;
    in vec3 v_color;

    void main() {
        vec4 tex_color = texture(s_texture, v_tex_coord);
        if(tex_color.a == 0.0) // Discard transparent pixels.
            discard;
        out_color = tex_color * vec4(v_color, 1.0);
    }
"
};

#[shader_param]
#[derive(Copy)]
pub struct ShaderParam {
    pub projection: [[f32; 4]; 4],
    pub view: [[f32; 4]; 4],
    pub s_texture: gfx::shade::TextureParam,
}

#[vertex_format]
#[derive(Copy)]
pub struct Vertex {
    #[name="position"]
    pub xyz: [f32; 3],
    #[name="tex_coord"]
    pub uv: [f32; 2],
    #[name="color"]
    pub rgb: [f32; 3],
}

impl Clone for Vertex {
    fn clone(&self) -> Vertex {
        *self
    }
}

#[derive(Copy)]
pub struct Buffer {
    buf: gfx::BufferHandle<Vertex>,
    batch: gfx::batch::RefBatch<ShaderParam>,
}

pub struct Renderer<D: Device> {
    graphics: gfx::Graphics<D>,
    params: ShaderParam,
    frame: gfx::Frame,
    cd: gfx::ClearData,
    prog: device::Handle<u32, device::shade::ProgramInfo>,
    drawstate: gfx::DrawState
}

impl<D: Device> Renderer<D> {
    pub fn new(mut device: D, frame: gfx::Frame, tex: gfx::TextureHandle) -> Renderer<D> {
        let sampler = device.create_sampler(
                gfx::tex::SamplerInfo::new(
                    gfx::tex::FilterMethod::Scale,
                    gfx::tex::WrapMode::Tile
                )
            );
        let mut graphics = gfx::Graphics::new(device);

        let params = ShaderParam {
            projection: [[0.0; 4]; 4],
            view: [[0.0; 4]; 4],
            s_texture: (tex, Some(sampler))
        };
        let prog = graphics.device.link_program(VERTEX.clone(), FRAGMENT.clone()).ok().unwrap();
        let mut drawstate = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);
        drawstate.primitive.front_face = gfx::state::WindingOrder::Clockwise;

        Renderer {
            graphics: graphics,
            params: params,
            frame: frame,
            cd: gfx::ClearData {
                color: [0.81, 0.8, 1.0, 1.0],
                depth: 1.0,
                stencil: 0,
            },
            prog: prog,
            drawstate: drawstate,
        }
    }

    pub fn set_projection(&mut self, proj_mat: Matrix4<f32>) {
        self.params.projection = proj_mat;
    }

    pub fn set_view(&mut self, view_mat: Matrix4<f32>) {
        self.params.view = view_mat;
    }

    pub fn clear(&mut self) {
        self.graphics.clear(self.cd, gfx::COLOR | gfx::DEPTH, &self.frame);
    }

    pub fn create_buffer(&mut self, data: &[Vertex]) -> Buffer {
        let buf = self.graphics.device.create_buffer(data.len(), gfx::BufferUsage::Static);
        self.graphics.device.update_buffer(buf, data, 0);
        let mesh = gfx::Mesh::from_format(buf, data.len() as u32);
        Buffer {
            buf: buf,
            batch: self.graphics.make_batch(
                    &self.prog,
                    &mesh,
                    mesh.to_slice(gfx::PrimitiveType::TriangleList),
                    &self.drawstate
                ).ok().unwrap()
        }
    }

    pub fn delete_buffer(&mut self, buf: Buffer) {
        self.graphics.device.delete_buffer(buf.buf);
    }

    pub fn render(&mut self, buffer: Buffer) {
        self.graphics.draw(&buffer.batch, &self.params, &self.frame);
    }

    pub fn end_frame(&mut self) {
        self.graphics.end_frame();
    }
}
<|endoftext|>