<commit_before>use object_id::ObjectId;
use object_header::ObjectHeader;
use meta::Meta;
use serialization::Serializable;
use serialization;

#[deriving(PartialEq, Show)]
pub struct Commit {
    pub meta: Meta,
    pub author_name: String,
    pub author_email: String,
    pub author_date: uint,
    pub committer_name: String,
    pub committer_email: String,
    pub commit_date: uint,
    pub message: String,
    pub tree_id: ObjectId,
    pub parent_ids: Vec<ObjectId>,
}

impl Serializable for Commit {
    fn encode(&self) -> Vec<u8> {
        let mut buff = Vec::new();
        let mut header = self.meta.header;

        let body_buff = self.encode_body();

        // Update header length if necessary.
        if header.length == 0 {
            header = ObjectHeader { length: body_buff.len(), ..header };
        }

        let header_buff = header.encode();

        buff.push_all(header_buff.as_slice());
        buff.push_all(body_buff.as_slice());

        buff
    }

    fn encode_body(&self) -> Vec<u8> {
        let mut buff = Vec::new();

        buff.push_all(format!("tree {}\n", self.tree_id.hash).into_bytes().as_slice());

        for id in self.parent_ids.iter() {
            buff.push_all(format!("parent {}\n", id.hash).into_bytes().as_slice());
        }

        buff.push_all(serialization::encode_author_info(self).as_slice());
        buff.push_all(serialization::encode_commit_info(self).as_slice());

        buff.push_all(format!("\n{}", self.message).into_bytes().as_slice());

        buff
    }
}
<commit_msg>Implement some rudimentary Commit decoding<commit_after>use object_id::ObjectId;
use object_header::ObjectHeader;
use object_header;
use object_type;
use meta::Meta;
use serialization::Serializable;
use serialization;
use reader::Reader;
use error::GitError;
use error::CorruptedCommit;

#[deriving(PartialEq, Show)]
pub struct Commit {
    pub meta: Meta,
    pub author_name: String,
    pub author_email: String,
    pub author_date: uint,
    pub committer_name: String,
    pub committer_email: String,
    pub commit_date: uint,
    pub message: String,
    pub tree_id: ObjectId,
    pub parent_ids: Vec<ObjectId>,
}

impl Serializable for Commit {
    fn encode(&self) -> Vec<u8> {
        let mut buff = Vec::new();
        let mut header = self.meta.header;

        let body_buff = self.encode_body();

        // Update header length if necessary.
        if header.length == 0 {
            header = ObjectHeader { length: body_buff.len(), ..header };
        }

        let header_buff = header.encode();

        buff.push_all(header_buff.as_slice());
        buff.push_all(body_buff.as_slice());

        buff
    }

    fn encode_body(&self) -> Vec<u8> {
        let mut buff = Vec::new();

        buff.push_all(format!("tree {}\n", self.tree_id.hash).into_bytes().as_slice());

        for id in self.parent_ids.iter() {
            buff.push_all(format!("parent {}\n", id.hash).into_bytes().as_slice());
        }

        buff.push_all(serialization::encode_author_info(self).as_slice());
        buff.push_all(serialization::encode_commit_info(self).as_slice());

        buff.push_all(format!("\n{}", self.message).into_bytes().as_slice());

        buff
    }
}

pub fn decode(bytes: &[u8]) -> Result<Commit, GitError> {
    let header = object_header::decode(bytes);

    decode_body(bytes.slice_from(bytes.len() - header.length), &header)
}

pub fn decode_body(bytes: &[u8], header: &ObjectHeader) -> Result<Commit, GitError> {
    let mut reader = Reader::from_data(bytes);

    if reader.take_string(5) != "tree " {
        return Err(CorruptedCommit("Expected 'tree '"))
    }

    let tree_id = reader.take_string_based_object_id();

    reader.skip(1);

    let mut parent_ids = Vec::new();

    while reader.take_string_while(|&c| c != 32) == "parent" {
        reader.skip(1);

        parent_ids.push(reader.take_string_based_object_id());

        reader.skip(1);
    }

    reader.back(6);

    if reader.take_string(7) != "author " {
        return Err(CorruptedCommit("Expected 'author '"))
    }

    let (author_name, author_email, author_date) = serialization::decode_user_info(&mut reader);

    if reader.take_string(10) != "committer " {
        return Err(CorruptedCommit("Expected 'committer '"))
    }

    let (committer_name, committer_email, commit_date) = serialization::decode_user_info(&mut reader);

    let message = reader.get_rest_as_string();

    Ok(Commit {
        meta: Meta {
            id: ObjectId::from_string("b744d5cddb5095249299d95ee531cbd990741140"),
            header: *header,
        },
        author_name: author_name,
        author_email: author_email,
        author_date: author_date,
        committer_name: committer_name,
        committer_email: committer_email,
        commit_date: commit_date,
        message: message.into_string(),
        tree_id: tree_id,
        parent_ids: parent_ids
    })
}<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::Read;
use std::net;
use std::path::Path;
use std::result;
use std::str::FromStr;

use toml;

use error::{Error, Result};

pub trait ConfigFile: Sized {
    type Error: std::error::Error + From<Error>;

    fn from_file<T: AsRef<Path>>(filepath: T) -> result::Result<Self, Self::Error> {
        let mut file = match File::open(filepath.as_ref()) {
            Ok(f) => f,
            Err(e) => return Err(Self::Error::from(Error::ConfigFileIO(e))),
        };
        let mut raw = String::new();
        match file.read_to_string(&mut raw) {
            Ok(_) => (),
            Err(e) => return Err(Self::Error::from(Error::ConfigFileIO(e))),
        }
        match raw.parse() {
            Ok(toml) => Self::from_toml(toml),
            Err(e) => {
                let msg = format_errors(&e);
                Err(Self::Error::from(Error::ConfigFileSyntax(msg)))
            }
        }
    }

    fn from_toml(toml: toml::Value) -> result::Result<Self, Self::Error>;
}

pub trait ParseInto<T> {
    fn parse_into(&self, field: &'static str, out: &mut T) -> Result<bool>;
}

impl ParseInto<Vec<net::SocketAddrV4>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<net::SocketAddrV4>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(slice) = val.as_slice() {
                let mut buf = vec![];
                for entry in slice.iter() {
                    if let Some(v) = entry.as_str() {
                        match net::SocketAddrV4::from_str(v) {
                            Ok(addr) => buf.push(addr),
                            Err(_) => return Err(Error::ConfigInvalidSocketAddrV4(field)),
                        }
                    } else {
                        return Err(Error::ConfigInvalidSocketAddrV4(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                // error, expected array
                Ok(false)
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<net::SocketAddrV4> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut net::SocketAddrV4) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                match net::SocketAddrV4::from_str(v) {
                    Ok(addr) => {
                        *out = addr;
                        Ok(true)
                    }
                    Err(_) => Err(Error::ConfigInvalidSocketAddrV4(field)),
                }
            } else {
                Err(Error::ConfigInvalidSocketAddrV4(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<net::Ipv4Addr> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut net::Ipv4Addr) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                match net::Ipv4Addr::from_str(v) {
                    Ok(addr) => {
                        *out = addr;
                        Ok(true)
                    }
                    Err(_) => Err(Error::ConfigInvalidIpv4Addr(field)),
                }
            } else {
                Err(Error::ConfigInvalidIpv4Addr(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<String> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut String) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                *out = v.to_string();
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Option<String>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Option<String>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                *out = Some(v.to_string());
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            *out = None;
            Ok(true)
        }
    }
}

impl ParseInto<usize> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut usize) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as usize;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u16> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u16) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u16;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u32> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u32) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u32;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u64> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u64) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u64;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u16>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u16>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u16);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u32>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u32>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u32);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u64>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u64>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u64);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<BTreeMap<String, String>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut BTreeMap<String, String>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            let buf: BTreeMap<String, String> = val.as_table()
                .unwrap()
                .iter()
                .map(|(k, v)| (k.to_string(), v.as_str().unwrap().to_string()))
                .collect();
            *out = buf;
            Ok(true)
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<BTreeMap<String, String>>> for toml::Value {
    fn parse_into(&self,
                  field: &'static str,
                  out: &mut Vec<BTreeMap<String, String>>)
                  -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for m in v.iter() {
                    let map: BTreeMap<String, String> = m.as_table()
                        .unwrap()
                        .iter()
                        .map(|(k, v)| (k.to_string(), v.as_str().unwrap().to_string()))
                        .collect();
                    buf.push(map);
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

fn format_errors(errors: &Vec<toml::ParserError>) -> String {
    let mut msg = String::new();
    for err in errors {
        msg.push_str(&format!("\terror: {}\n", err.desc));
    }
    msg
}
<commit_msg>Add post-processing infra to builder-worker<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::Read;
use std::net;
use std::path::Path;
use std::result;
use std::str::FromStr;

use toml;

use error::{Error, Result};

pub trait ConfigFile: Sized {
    type Error: std::error::Error + From<Error>;

    fn from_file<T: AsRef<Path>>(filepath: T) -> result::Result<Self, Self::Error> {
        let mut file = match File::open(filepath.as_ref()) {
            Ok(f) => f,
            Err(e) => return Err(Self::Error::from(Error::ConfigFileIO(e))),
        };
        let mut raw = String::new();
        match file.read_to_string(&mut raw) {
            Ok(_) => (),
            Err(e) => return Err(Self::Error::from(Error::ConfigFileIO(e))),
        }
        match raw.parse() {
            Ok(toml) => Self::from_toml(toml),
            Err(e) => {
                let msg = format_errors(&e);
                Err(Self::Error::from(Error::ConfigFileSyntax(msg)))
            }
        }
    }

    fn from_toml(toml: toml::Value) -> result::Result<Self, Self::Error>;
}

pub trait ParseInto<T> {
    fn parse_into(&self, field: &'static str, out: &mut T) -> Result<bool>;
}

impl ParseInto<Vec<net::SocketAddrV4>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<net::SocketAddrV4>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(slice) = val.as_slice() {
                let mut buf = vec![];
                for entry in slice.iter() {
                    if let Some(v) = entry.as_str() {
                        match net::SocketAddrV4::from_str(v) {
                            Ok(addr) => buf.push(addr),
                            Err(_) => return Err(Error::ConfigInvalidSocketAddrV4(field)),
                        }
                    } else {
                        return Err(Error::ConfigInvalidSocketAddrV4(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                // error, expected array
                Ok(false)
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<net::SocketAddrV4> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut net::SocketAddrV4) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                match net::SocketAddrV4::from_str(v) {
                    Ok(addr) => {
                        *out = addr;
                        Ok(true)
                    }
                    Err(_) => Err(Error::ConfigInvalidSocketAddrV4(field)),
                }
            } else {
                Err(Error::ConfigInvalidSocketAddrV4(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<net::Ipv4Addr> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut net::Ipv4Addr) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                match net::Ipv4Addr::from_str(v) {
                    Ok(addr) => {
                        *out = addr;
                        Ok(true)
                    }
                    Err(_) => Err(Error::ConfigInvalidIpv4Addr(field)),
                }
            } else {
                Err(Error::ConfigInvalidIpv4Addr(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<String> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut String) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                *out = v.to_string();
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Option<String>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Option<String>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                *out = Some(v.to_string());
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            *out = None;
            Ok(true)
        }
    }
}

impl ParseInto<bool> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut bool) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_bool() {
                *out = v as bool;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<usize> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut usize) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as usize;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u16> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u16) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u16;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u32> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u32) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u32;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u64> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u64) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u64;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u16>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u16>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u16);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u32>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u32>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u32);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u64>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u64>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u64);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<BTreeMap<String, String>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut BTreeMap<String, String>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            let buf: BTreeMap<String, String> = val.as_table()
                .unwrap()
                .iter()
                .map(|(k, v)| (k.to_string(), v.as_str().unwrap().to_string()))
                .collect();
            *out = buf;
            Ok(true)
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<BTreeMap<String, String>>> for toml::Value {
    fn parse_into(&self,
                  field: &'static str,
                  out: &mut Vec<BTreeMap<String, String>>)
                  -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for m in v.iter() {
                    let map: BTreeMap<String, String> = m.as_table()
                        .unwrap()
                        .iter()
                        .map(|(k, v)| (k.to_string(), v.as_str().unwrap().to_string()))
                        .collect();
                    buf.push(map);
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

fn format_errors(errors: &Vec<toml::ParserError>) -> String {
    let mut msg = String::new();
    for err in errors {
        msg.push_str(&format!("\terror: {}\n", err.desc));
    }
    msg
}
<|endoftext|>


<commit_before>use scheduled_thread_pool::ScheduledThreadPool;
use std::fmt;
use std::time::Duration;
use std::marker::PhantomData;
use std::sync::Arc;

use {CustomizeConnection, Error, HandleError, LoggingErrorHandler, ManageConnection,
     NopConnectionCustomizer, Pool};

/// A builder for a connection pool.
pub struct Builder<M>
where
    M: ManageConnection,
{
    max_size: u32,
    min_idle: Option<u32>,
    test_on_check_out: bool,
    max_lifetime: Option<Duration>,
    idle_timeout: Option<Duration>,
    connection_timeout: Duration,
    error_handler: Box<HandleError<M::Error>>,
    connection_customizer: Box<CustomizeConnection<M::Connection, M::Error>>,
    thread_pool: Option<Arc<ScheduledThreadPool>>,
    reaper_rate: Duration,
    _p: PhantomData<M>,
}

impl<M> fmt::Debug for Builder<M>
where
    M: ManageConnection,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Builder")
            .field("max_size", &self.max_size)
            .field("min_idle", &self.min_idle)
            .field("test_on_check_out", &self.test_on_check_out)
            .field("max_lifetime", &self.max_lifetime)
            .field("idle_timeout", &self.idle_timeout)
            .field("connection_timeout", &self.connection_timeout)
            .field("error_handler", &self.error_handler)
            .field("connection_customizer", &self.connection_customizer)
            .finish()
    }
}

impl<M> Default for Builder<M>
where
    M: ManageConnection,
{
    fn default() -> Builder<M> {
        Builder {
            max_size: 10,
            min_idle: None,
            test_on_check_out: true,
            idle_timeout: Some(Duration::from_secs(10 * 60)),
            max_lifetime: Some(Duration::from_secs(30 * 60)),
            connection_timeout: Duration::from_secs(30),
            error_handler: Box::new(LoggingErrorHandler),
            connection_customizer: Box::new(NopConnectionCustomizer),
            thread_pool: None,
            reaper_rate: Duration::from_secs(30),
            _p: PhantomData,
        }
    }
}

impl<M> Builder<M>
where
    M: ManageConnection,
{
    /// Constructs a new `Builder`.
    ///
    /// Parameters are initialized with their default values.
    pub fn new() -> Builder<M> {
        Builder::default()
    }

    /// Sets the maximum number of connections managed by the pool.
    ///
    /// Defaults to 10.
    ///
    /// # Panics
    ///
    /// Panics if `max_size` is 0.
    pub fn max_size(mut self, max_size: u32) -> Builder<M> {
        assert!(max_size > 0, "max_size must be positive");
        self.max_size = max_size;
        self
    }

    /// Sets the minimum idle connection count maintained by the pool.
    ///
    /// If set, the pool will try to maintain at least this many idle
    /// connections at all times, while respecting the value of `max_size`.
    ///
    /// Defaults to `None` (equivalent to the value of `max_size`).
    pub fn min_idle(mut self, min_idle: Option<u32>) -> Builder<M> {
        self.min_idle = min_idle;
        self
    }

    /// Sets the thread pool used for asynchronous operations such as connection
    /// creation.
    ///
    /// Defaults to a new pool with 3 threads.
    pub fn thread_pool(mut self, thread_pool: Arc<ScheduledThreadPool>) -> Builder<M> {
        self.thread_pool = Some(thread_pool);
        self
    }

    /// If true, the health of a connection will be verified via a call to
    /// `ConnectionManager::is_valid` before it is checked out of the pool.
    ///
    /// Defaults to true.
    pub fn test_on_check_out(mut self, test_on_check_out: bool) -> Builder<M> {
        self.test_on_check_out = test_on_check_out;
        self
    }

    /// Sets the maximum lifetime of connections in the pool.
    ///
    /// If set, connections will be closed after existing for at most 30 seconds
    /// beyond this duration.
    ///
    /// If a connection reaches its maximum lifetime while checked out it will
    /// be closed when it is returned to the pool.
    ///
    /// Defaults to 30 minutes.
    ///
    /// # Panics
    ///
    /// Panics if `max_lifetime` is the zero `Duration`.
    pub fn max_lifetime(mut self, max_lifetime: Option<Duration>) -> Builder<M> {
        assert!(
            max_lifetime != Some(Duration::from_secs(0)),
            "max_lifetime must be positive"
        );
        self.max_lifetime = max_lifetime;
        self
    }

    /// Sets the idle timeout used by the pool.
    ///
    /// If set, connections will be closed after sitting idle for at most 30
    /// seconds beyond this duration.
    ///
    /// Defaults to 10 minutes.
    ///
    /// # Panics
    ///
    /// Panics if `idle_timeout` is the zero `Duration`.
    pub fn idle_timeout(mut self, idle_timeout: Option<Duration>) -> Builder<M> {
        assert!(
            idle_timeout != Some(Duration::from_secs(0)),
            "idle_timeout must be positive"
        );
        self.idle_timeout = idle_timeout;
        self
    }

    /// Sets the connection timeout used by the pool.
    ///
    /// Calls to `Pool::get` will wait this long for a connection to become
    /// available before returning an error.
    ///
    /// Defaults to 30 seconds.
    ///
    /// # Panics
    ///
    /// Panics if `connection_timeout` is the zero duration
    pub fn connection_timeout(mut self, connection_timeout: Duration) -> Builder<M> {
        assert!(
            connection_timeout > Duration::from_secs(0),
            "connection_timeout must be positive"
        );
        self.connection_timeout = connection_timeout;
        self
    }

    /// Sets the handler for errors reported in the pool.
    ///
    /// Defaults to the `LoggingErrorHandler`.
    pub fn error_handler(mut self, error_handler: Box<HandleError<M::Error>>) -> Builder<M> {
        self.error_handler = error_handler;
        self
    }

    /// Sets the connection customizer used by the pool.
    ///
    /// Defaults to the `NopConnectionCustomizer`.
    pub fn connection_customizer(
        mut self,
        connection_customizer: Box<CustomizeConnection<M::Connection, M::Error>>,
    ) -> Builder<M> {
        self.connection_customizer = connection_customizer;
        self
    }

    #[allow(dead_code)]
    pub(crate) fn reaper_rate(mut self, reaper_rate: Duration) -> Builder<M> {
        self.reaper_rate = reaper_rate;
        self
    }

    /// Consumes the builder, returning a new, initialized pool.
    ///
    /// # Failure
    ///
    /// Returns an error if the pool is unable to open its minimum number of
    /// connections.
    ///
    /// # Panics
    ///
    /// Panics if `min_idle` is greater than `max_size`.
    pub fn build(self, manager: M) -> Result<Pool<M>, Error> {
        let pool = self.build_unchecked(manager);
        pool.wait_for_initialization()?;
        Ok(pool)
    }

    /// Consumes the buffer, returning a new pool.
    ///
    /// Unlike `build`, this method does not wait for any connections to be
    /// established before returning.
    ///
    /// # Panics
    ///
    /// Panics if `min_idle` is greater than `max_size`.
    pub fn build_unchecked(self, manager: M) -> Pool<M> {
        if let Some(min_idle) = self.min_idle {
            assert!(
                self.max_size >= min_idle,
                "min_idle must be no larger than max_size"
            );
        }

        let thread_pool = match self.thread_pool {
            Some(thread_pool) => thread_pool,
            None => Arc::new(ScheduledThreadPool::with_name("r2d2-worker-{}", 3)),
        };

        let config = Config {
            max_size: self.max_size,
            min_idle: self.min_idle,
            test_on_check_out: self.test_on_check_out,
            max_lifetime: self.max_lifetime,
            idle_timeout: self.idle_timeout,
            connection_timeout: self.connection_timeout,
            error_handler: self.error_handler,
            connection_customizer: self.connection_customizer,
            thread_pool: thread_pool,
        };

        Pool::new_inner(config, manager, self.reaper_rate)
    }
}

pub struct Config<C, E> {
    pub max_size: u32,
    pub min_idle: Option<u32>,
    pub test_on_check_out: bool,
    pub max_lifetime: Option<Duration>,
    pub idle_timeout: Option<Duration>,
    pub connection_timeout: Duration,
    pub error_handler: Box<HandleError<E>>,
    pub connection_customizer: Box<CustomizeConnection<C, E>>,
    pub thread_pool: Arc<ScheduledThreadPool>,
}

// manual to avoid bounds on C and E
impl<C, E> fmt::Debug for Config<C, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Config")
            .field("max_size", &self.max_size)
            .field("min_idle", &self.min_idle)
            .field("test_on_check_out", &self.test_on_check_out)
            .field("max_lifetime", &self.max_lifetime)
            .field("idle_timeout", &self.idle_timeout)
            .field("connection_timeout", &self.connection_timeout)
            .field("error_handler", &self.error_handler)
            .field("connection_customizer", &self.connection_customizer)
            .finish()
    }
}
<commit_msg>Doc tweaks<commit_after>use scheduled_thread_pool::ScheduledThreadPool;
use std::fmt;
use std::time::Duration;
use std::marker::PhantomData;
use std::sync::Arc;

use {CustomizeConnection, Error, HandleError, LoggingErrorHandler, ManageConnection,
     NopConnectionCustomizer, Pool};

/// A builder for a connection pool.
pub struct Builder<M>
where
    M: ManageConnection,
{
    max_size: u32,
    min_idle: Option<u32>,
    test_on_check_out: bool,
    max_lifetime: Option<Duration>,
    idle_timeout: Option<Duration>,
    connection_timeout: Duration,
    error_handler: Box<HandleError<M::Error>>,
    connection_customizer: Box<CustomizeConnection<M::Connection, M::Error>>,
    thread_pool: Option<Arc<ScheduledThreadPool>>,
    reaper_rate: Duration,
    _p: PhantomData<M>,
}

impl<M> fmt::Debug for Builder<M>
where
    M: ManageConnection,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Builder")
            .field("max_size", &self.max_size)
            .field("min_idle", &self.min_idle)
            .field("test_on_check_out", &self.test_on_check_out)
            .field("max_lifetime", &self.max_lifetime)
            .field("idle_timeout", &self.idle_timeout)
            .field("connection_timeout", &self.connection_timeout)
            .field("error_handler", &self.error_handler)
            .field("connection_customizer", &self.connection_customizer)
            .finish()
    }
}

impl<M> Default for Builder<M>
where
    M: ManageConnection,
{
    fn default() -> Builder<M> {
        Builder {
            max_size: 10,
            min_idle: None,
            test_on_check_out: true,
            idle_timeout: Some(Duration::from_secs(10 * 60)),
            max_lifetime: Some(Duration::from_secs(30 * 60)),
            connection_timeout: Duration::from_secs(30),
            error_handler: Box::new(LoggingErrorHandler),
            connection_customizer: Box::new(NopConnectionCustomizer),
            thread_pool: None,
            reaper_rate: Duration::from_secs(30),
            _p: PhantomData,
        }
    }
}

impl<M> Builder<M>
where
    M: ManageConnection,
{
    /// Constructs a new `Builder`.
    ///
    /// Parameters are initialized with their default values.
    pub fn new() -> Builder<M> {
        Builder::default()
    }

    /// Sets the maximum number of connections managed by the pool.
    ///
    /// Defaults to 10.
    ///
    /// # Panics
    ///
    /// Panics if `max_size` is 0.
    pub fn max_size(mut self, max_size: u32) -> Builder<M> {
        assert!(max_size > 0, "max_size must be positive");
        self.max_size = max_size;
        self
    }

    /// Sets the minimum idle connection count maintained by the pool.
    ///
    /// If set, the pool will try to maintain at least this many idle
    /// connections at all times, while respecting the value of `max_size`.
    ///
    /// Defaults to `None` (equivalent to the value of `max_size`).
    pub fn min_idle(mut self, min_idle: Option<u32>) -> Builder<M> {
        self.min_idle = min_idle;
        self
    }

    /// Sets the thread pool used for asynchronous operations such as connection
    /// creation.
    ///
    /// Defaults to a new pool with 3 threads.
    pub fn thread_pool(mut self, thread_pool: Arc<ScheduledThreadPool>) -> Builder<M> {
        self.thread_pool = Some(thread_pool);
        self
    }

    /// If true, the health of a connection will be verified via a call to
    /// `ConnectionManager::is_valid` before it is checked out of the pool.
    ///
    /// Defaults to true.
    pub fn test_on_check_out(mut self, test_on_check_out: bool) -> Builder<M> {
        self.test_on_check_out = test_on_check_out;
        self
    }

    /// Sets the maximum lifetime of connections in the pool.
    ///
    /// If set, connections will be closed after existing for at most 30 seconds
    /// beyond this duration.
    ///
    /// If a connection reaches its maximum lifetime while checked out it will
    /// be closed when it is returned to the pool.
    ///
    /// Defaults to 30 minutes.
    ///
    /// # Panics
    ///
    /// Panics if `max_lifetime` is the zero `Duration`.
    pub fn max_lifetime(mut self, max_lifetime: Option<Duration>) -> Builder<M> {
        assert!(
            max_lifetime != Some(Duration::from_secs(0)),
            "max_lifetime must be positive"
        );
        self.max_lifetime = max_lifetime;
        self
    }

    /// Sets the idle timeout used by the pool.
    ///
    /// If set, connections will be closed after sitting idle for at most 30
    /// seconds beyond this duration.
    ///
    /// Defaults to 10 minutes.
    ///
    /// # Panics
    ///
    /// Panics if `idle_timeout` is the zero `Duration`.
    pub fn idle_timeout(mut self, idle_timeout: Option<Duration>) -> Builder<M> {
        assert!(
            idle_timeout != Some(Duration::from_secs(0)),
            "idle_timeout must be positive"
        );
        self.idle_timeout = idle_timeout;
        self
    }

    /// Sets the connection timeout used by the pool.
    ///
    /// Calls to `Pool::get` will wait this long for a connection to become
    /// available before returning an error.
    ///
    /// Defaults to 30 seconds.
    ///
    /// # Panics
    ///
    /// Panics if `connection_timeout` is the zero duration
    pub fn connection_timeout(mut self, connection_timeout: Duration) -> Builder<M> {
        assert!(
            connection_timeout > Duration::from_secs(0),
            "connection_timeout must be positive"
        );
        self.connection_timeout = connection_timeout;
        self
    }

    /// Sets the handler for errors reported in the pool.
    ///
    /// Defaults to the `LoggingErrorHandler`.
    pub fn error_handler(mut self, error_handler: Box<HandleError<M::Error>>) -> Builder<M> {
        self.error_handler = error_handler;
        self
    }

    /// Sets the connection customizer used by the pool.
    ///
    /// Defaults to the `NopConnectionCustomizer`.
    pub fn connection_customizer(
        mut self,
        connection_customizer: Box<CustomizeConnection<M::Connection, M::Error>>,
    ) -> Builder<M> {
        self.connection_customizer = connection_customizer;
        self
    }

    // used by tests
    #[allow(dead_code)]
    pub(crate) fn reaper_rate(mut self, reaper_rate: Duration) -> Builder<M> {
        self.reaper_rate = reaper_rate;
        self
    }

    /// Consumes the builder, returning a new, initialized pool.
    ///
    /// It will block until the pool has established its configured minimum
    /// number of connections, or it times out.
    ///
    /// # Errors
    ///
    /// Returns an error if the pool is unable to open its minimum number of
    /// connections.
    ///
    /// # Panics
    ///
    /// Panics if `min_idle` is greater than `max_size`.
    pub fn build(self, manager: M) -> Result<Pool<M>, Error> {
        let pool = self.build_unchecked(manager);
        pool.wait_for_initialization()?;
        Ok(pool)
    }

    /// Consumes the builder, returning a new pool.
    ///
    /// Unlike `build`, this method does not wait for any connections to be
    /// established before returning.
    ///
    /// # Panics
    ///
    /// Panics if `min_idle` is greater than `max_size`.
    pub fn build_unchecked(self, manager: M) -> Pool<M> {
        if let Some(min_idle) = self.min_idle {
            assert!(
                self.max_size >= min_idle,
                "min_idle must be no larger than max_size"
            );
        }

        let thread_pool = match self.thread_pool {
            Some(thread_pool) => thread_pool,
            None => Arc::new(ScheduledThreadPool::with_name("r2d2-worker-{}", 3)),
        };

        let config = Config {
            max_size: self.max_size,
            min_idle: self.min_idle,
            test_on_check_out: self.test_on_check_out,
            max_lifetime: self.max_lifetime,
            idle_timeout: self.idle_timeout,
            connection_timeout: self.connection_timeout,
            error_handler: self.error_handler,
            connection_customizer: self.connection_customizer,
            thread_pool: thread_pool,
        };

        Pool::new_inner(config, manager, self.reaper_rate)
    }
}

pub struct Config<C, E> {
    pub max_size: u32,
    pub min_idle: Option<u32>,
    pub test_on_check_out: bool,
    pub max_lifetime: Option<Duration>,
    pub idle_timeout: Option<Duration>,
    pub connection_timeout: Duration,
    pub error_handler: Box<HandleError<E>>,
    pub connection_customizer: Box<CustomizeConnection<C, E>>,
    pub thread_pool: Arc<ScheduledThreadPool>,
}

// manual to avoid bounds on C and E
impl<C, E> fmt::Debug for Config<C, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Config")
            .field("max_size", &self.max_size)
            .field("min_idle", &self.min_idle)
            .field("test_on_check_out", &self.test_on_check_out)
            .field("max_lifetime", &self.max_lifetime)
            .field("idle_timeout", &self.idle_timeout)
            .field("connection_timeout", &self.connection_timeout)
            .field("error_handler", &self.error_handler)
            .field("connection_customizer", &self.connection_customizer)
            .finish()
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use errors::Result;
use cpp_method::CppMethod;
use cpp_data::CppData;

pub type CppFfiGeneratorFilterFn = Fn(&CppMethod) -> Result<bool>;

#[derive(Default)]
struct CppFfiGeneratorFilter(Option<Box<CppFfiGeneratorFilterFn>>);

impl ::std::fmt::Debug for CppFfiGeneratorFilter {
  fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
    write!(f, "{}", if self.0.is_some() { "Some(fn)" } else { "None" })
  }
}

pub type CppDataFilterFn = Fn(&mut CppData) -> Result<()>;

#[derive(Default)]
struct CppDataFilter(Option<Box<CppDataFilterFn>>);

impl ::std::fmt::Debug for CppDataFilter {
  fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
    write!(f, "{}", if self.0.is_some() { "Some(fn)" } else { "None" })
  }
}

#[derive(Default, Debug)]
pub struct Config {
  /// Extra libraries to be linked.
  /// Used as "-l" option to linker.
  linked_libs: Vec<String>,
  /// Paths to library directories supplied to the linker
  /// via '-L' option or environment variables.
  lib_paths: Vec<PathBuf>,

  /// Extra frameworks to be linked (MacOS specific).
  /// Used as "-f" option to linker.
  linked_frameworks: Vec<String>,

  /// Paths to framework directories supplied to the linker
  /// via '-F' option or environment variables.
  framework_paths: Vec<PathBuf>,

  /// Paths to include directories supplied to the C++ parser
  /// and compiler of the C++ wrapper via '-I' option.
  /// This is detected automatically for Qt libraries using qmake.
  /// Paths can be relative to lib spec file's directory.
  include_paths: Vec<PathBuf>,

  /// Paths to include directories of the library.
  /// Only types and methods declared within these directories
  /// will be parsed.
  /// This is detected automatically for Qt libraries using qmake.
  /// Paths can be relative to lib spec file's directory.
  target_include_paths: Vec<PathBuf>,
  // TODO: allow both dirs and files in target_include_paths
  /// Name of the library's include file
  include_directives: Vec<PathBuf>,

  /// List of C++ identifiers which should be skipped
  /// by C++ parser. Identifier can contain namespaces
  /// and nested classes, with "::" separator (like in
  /// C++ identifiers). Identifier may refer to a method,
  /// a class, a enum or a namespace. All entities inside blacklisted
  /// entity (e.g. the methods of a blocked class or
  /// the contents of a blocked namespace)
  /// will also be skipped.
  cpp_parser_blocked_names: Vec<String>,

  /// Custom function that decides whether a C++ method should be
  /// added to FFI library wrapper. Err indicates an unexpected failure
  /// and terminates processing. Ok(true) allows the method, and
  /// Ok(false) blocks the method.
  cpp_ffi_generator_filter: CppFfiGeneratorFilter,
  cpp_data_filter: CppDataFilter,
}

impl Config {
  /// Creates empty Config
  pub fn new() -> Config {
    Config::default()
  }

  pub fn add_linked_lib<P: Into<String>>(&mut self, lib: P) {
    self.linked_libs.push(lib.into());
  }

  pub fn add_linked_framework<P: Into<String>>(&mut self, lib: P) {
    self.linked_frameworks.push(lib.into());
  }

  pub fn add_cpp_parser_blocked_name<P: Into<String>>(&mut self, lib: P) {
    self.cpp_parser_blocked_names.push(lib.into());
  }

  pub fn add_cpp_parser_blocked_names<Item, Iter>(&mut self, items: Iter)
    where Item: Into<String>,
          Iter: IntoIterator<Item = Item>
  {
    for item in items {
      self.cpp_parser_blocked_names.push(item.into());
    }
  }

  pub fn add_include_path<P: Into<PathBuf>>(&mut self, path: P) {
    self.include_paths.push(path.into());
  }

  pub fn add_lib_path<P: Into<PathBuf>>(&mut self, path: P) {
    self.lib_paths.push(path.into());
  }

  pub fn add_framework_path<P: Into<PathBuf>>(&mut self, path: P) {
    self.framework_paths.push(path.into());
  }

  pub fn add_target_include_path<P: Into<PathBuf>>(&mut self, path: P) {
    self.target_include_paths.push(path.into());
  }

  pub fn add_include_directive<P: Into<PathBuf>>(&mut self, path: P) {
    self.include_directives.push(path.into());
  }

  pub fn set_cpp_ffi_generator_filter(&mut self, f: Box<CppFfiGeneratorFilterFn>) {
    self.cpp_ffi_generator_filter.0 = Some(f);
  }

  pub fn set_cpp_data_filter(&mut self, f: Box<CppDataFilterFn>) {
    self.cpp_data_filter.0 = Some(f);
  }

  pub fn exec(self) -> Result<()> {
    ::launcher::run_from_build_script(self)
  }

  pub fn linked_libs(&self) -> &[String] {
    &self.linked_libs
  }

  pub fn linked_frameworks(&self) -> &[String] {
    &self.linked_frameworks
  }

  pub fn cpp_parser_blocked_names(&self) -> &[String] {
    &self.cpp_parser_blocked_names
  }

  pub fn include_paths(&self) -> &[PathBuf] {
    &self.include_paths
  }

  pub fn lib_paths(&self) -> &[PathBuf] {
    &self.lib_paths
  }

  pub fn framework_paths(&self) -> &[PathBuf] {
    &self.framework_paths
  }

  pub fn target_include_paths(&self) -> &[PathBuf] {
    &self.target_include_paths
  }

  pub fn include_directives(&self) -> &[PathBuf] {
    &self.include_directives
  }

  pub fn cpp_ffi_generator_filter(&self) -> Option<&Box<CppFfiGeneratorFilterFn>> {
    self.cpp_ffi_generator_filter.0.as_ref()
  }

  pub fn cpp_data_filter(&self) -> Option<&Box<CppDataFilterFn>> {
    self.cpp_data_filter.0.as_ref()
  }
}
<commit_msg>multiple filters in config<commit_after>use std::path::PathBuf;
use errors::Result;
use cpp_method::CppMethod;
use cpp_data::CppData;

pub type CppFfiGeneratorFilterFn = Fn(&CppMethod) -> Result<bool>;

struct CppFfiGeneratorFilter(Box<CppFfiGeneratorFilterFn>);

impl ::std::fmt::Debug for CppFfiGeneratorFilter {
  fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
    write!(f, "CppFfiGeneratorFilter")
  }
}

pub type CppDataFilterFn = Fn(&mut CppData) -> Result<()>;

struct CppDataFilter(Box<CppDataFilterFn>);

impl ::std::fmt::Debug for CppDataFilter {
  fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
    write!(f, "CppDataFilter")
  }
}

#[derive(Default, Debug)]
pub struct Config {
  /// Extra libraries to be linked.
  /// Used as "-l" option to linker.
  linked_libs: Vec<String>,
  /// Paths to library directories supplied to the linker
  /// via '-L' option or environment variables.
  lib_paths: Vec<PathBuf>,

  /// Extra frameworks to be linked (MacOS specific).
  /// Used as "-f" option to linker.
  linked_frameworks: Vec<String>,

  /// Paths to framework directories supplied to the linker
  /// via '-F' option or environment variables.
  framework_paths: Vec<PathBuf>,

  /// Paths to include directories supplied to the C++ parser
  /// and compiler of the C++ wrapper via '-I' option.
  /// This is detected automatically for Qt libraries using qmake.
  /// Paths can be relative to lib spec file's directory.
  include_paths: Vec<PathBuf>,

  /// Paths to include directories of the library.
  /// Only types and methods declared within these directories
  /// will be parsed.
  /// This is detected automatically for Qt libraries using qmake.
  /// Paths can be relative to lib spec file's directory.
  target_include_paths: Vec<PathBuf>,
  // TODO: allow both dirs and files in target_include_paths
  /// Name of the library's include file
  include_directives: Vec<PathBuf>,

  /// List of C++ identifiers which should be skipped
  /// by C++ parser. Identifier can contain namespaces
  /// and nested classes, with "::" separator (like in
  /// C++ identifiers). Identifier may refer to a method,
  /// a class, a enum or a namespace. All entities inside blacklisted
  /// entity (e.g. the methods of a blocked class or
  /// the contents of a blocked namespace)
  /// will also be skipped.
  cpp_parser_blocked_names: Vec<String>,

  /// Custom function that decides whether a C++ method should be
  /// added to FFI library wrapper. Err indicates an unexpected failure
  /// and terminates processing. Ok(true) allows the method, and
  /// Ok(false) blocks the method.
  cpp_ffi_generator_filters: Vec<CppFfiGeneratorFilter>,
  cpp_data_filters: Vec<CppDataFilter>,
}

impl Config {
  /// Creates empty Config
  pub fn new() -> Config {
    Config::default()
  }

  pub fn add_linked_lib<P: Into<String>>(&mut self, lib: P) {
    self.linked_libs.push(lib.into());
  }

  pub fn add_linked_framework<P: Into<String>>(&mut self, lib: P) {
    self.linked_frameworks.push(lib.into());
  }

  pub fn add_cpp_parser_blocked_name<P: Into<String>>(&mut self, lib: P) {
    self.cpp_parser_blocked_names.push(lib.into());
  }

  pub fn add_cpp_parser_blocked_names<Item, Iter>(&mut self, items: Iter)
    where Item: Into<String>,
          Iter: IntoIterator<Item = Item>
  {
    for item in items {
      self.cpp_parser_blocked_names.push(item.into());
    }
  }

  pub fn add_include_path<P: Into<PathBuf>>(&mut self, path: P) {
    self.include_paths.push(path.into());
  }

  pub fn add_lib_path<P: Into<PathBuf>>(&mut self, path: P) {
    self.lib_paths.push(path.into());
  }

  pub fn add_framework_path<P: Into<PathBuf>>(&mut self, path: P) {
    self.framework_paths.push(path.into());
  }

  pub fn add_target_include_path<P: Into<PathBuf>>(&mut self, path: P) {
    self.target_include_paths.push(path.into());
  }

  pub fn add_include_directive<P: Into<PathBuf>>(&mut self, path: P) {
    self.include_directives.push(path.into());
  }

  pub fn add_cpp_ffi_generator_filter(&mut self, f: Box<CppFfiGeneratorFilterFn>) {
    self.cpp_ffi_generator_filters.push(CppFfiGeneratorFilter(f));
  }

  pub fn add_cpp_data_filter(&mut self, f: Box<CppDataFilterFn>) {
    self.cpp_data_filters.push(CppDataFilter(f));
  }

  pub fn exec(self) -> Result<()> {
    ::launcher::run_from_build_script(self)
  }

  pub fn linked_libs(&self) -> &[String] {
    &self.linked_libs
  }

  pub fn linked_frameworks(&self) -> &[String] {
    &self.linked_frameworks
  }

  pub fn cpp_parser_blocked_names(&self) -> &[String] {
    &self.cpp_parser_blocked_names
  }

  pub fn include_paths(&self) -> &[PathBuf] {
    &self.include_paths
  }

  pub fn lib_paths(&self) -> &[PathBuf] {
    &self.lib_paths
  }

  pub fn framework_paths(&self) -> &[PathBuf] {
    &self.framework_paths
  }

  pub fn target_include_paths(&self) -> &[PathBuf] {
    &self.target_include_paths
  }

  pub fn include_directives(&self) -> &[PathBuf] {
    &self.include_directives
  }

  pub fn cpp_ffi_generator_filters(&self) -> Vec<&Box<CppFfiGeneratorFilterFn>> {
    self.cpp_ffi_generator_filters.iter().map(|x| &x.0).collect()
  }

  pub fn cpp_data_filters(&self) -> Vec<&Box<CppDataFilterFn>> {
    self.cpp_data_filters.iter().map(|x| &x.0).collect()
  }
}
<|endoftext|>


<commit_before>use std::convert::AsRef;
use std::io;

use asnom::structures::{Tag, OctetString};
use asnom::common::TagClass;

use futures::Future;
use tokio_service::Service;

use controls::Control;
use ldap::{Ldap, LdapOp, next_req_controls};
use protocol::LdapResult;

impl Ldap {
    pub fn delete<S: AsRef<str>>(&self, dn: S) ->
            Box<Future<Item=(LdapResult, Vec<Control>), Error=io::Error>> {
        let req = Tag::OctetString(OctetString {
            id: 10,
            class: TagClass::Application,
            inner: Vec::from(dn.as_ref())
        });

        let fut = self.call(LdapOp::Single(req, next_req_controls(self)))
            .and_then(|(result, controls)| Ok((result.into(), controls)));

        Box::new(fut)
    }
}
<commit_msg>Fix signature for Delete<commit_after>use std::io;

use asnom::structures::{Tag, OctetString};
use asnom::common::TagClass;

use futures::Future;
use tokio_service::Service;

use controls::Control;
use ldap::{Ldap, LdapOp, next_req_controls};
use protocol::LdapResult;

impl Ldap {
    pub fn delete(&self, dn: &str) ->
            Box<Future<Item=(LdapResult, Vec<Control>), Error=io::Error>> {
        let req = Tag::OctetString(OctetString {
            id: 10,
            class: TagClass::Application,
            inner: Vec::from(dn.as_bytes())
        });

        let fut = self.call(LdapOp::Single(req, next_req_controls(self)))
            .and_then(|(result, controls)| Ok((result.into(), controls)));

        Box::new(fut)
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::result;

use definitions::*;

// We limit how far copy back-references can go, the same as the C++ code.
const maxOffset: u16 = 1 << 15;

// emitLiteral writes a literal chunk and returns the number of bytes written.
fn emit_literal(dst: &mut [u8], lit: &mut [u8]) -> Result<usize, &'static str> {

	let mut i: usize;
	let n : u64 = (lit.len() -1) as u64;

	if n < 60 {
		dst[0] = (n as u8) << 2 | TAG_LITERAL;
		i = 1;
	} else if n < 1<<8 {
		dst[0] = 60<<2 | TAG_LITERAL;
		dst[1] = n as u8;
		i = 2;
	} else if n < 1<<16 {
		dst[0] = 61<<2 | TAG_LITERAL;
		dst[1] = n as u8;
		dst[2] = (n >> 8) as u8;
		i = 3;
	} else if n < 1<<32 {
		dst[0] = 63<<2 | TAG_LITERAL;
		dst[1] = n as u8;
		dst[2] = (n >> 8) as u8;
		dst[3] = (n >> 16) as u8;
		dst[4] = (n >> 24) as u8;
		i = 5;
	} else {
		return Err("snappy: source buffer is too long")
	}

	let mut s = 0;
	for (d, l) in dst.split_at_mut(i).1.iter_mut().zip(lit.iter()) {
        *d = *l;
        s += 1;
    }

    if(s == lit.len()){
		Ok(i + lit.len())
    } else {
    	Err("snappy: destination buffer is too short")
    }
}

// emitCopy writes a copy chunk and returns the number of bytes written.
fn emit_copy(dst: &mut [u8], offset: u8, length: usize) -> Result<usize, &'static str> {

	let mut i: usize = 0;

}

// MaxEncodedLen returns the maximum length of a snappy block, given its
// uncompressed length.
pub fn MaxEncodedLen(srcLen : u64) ->  u64 {
	32 + srcLen + srcLen/6
}

// Encode returns the encoded form of src. The returned slice may be a sub-
// slice of dst if dst was large enough to hold the entire encoded block.
// Otherwise, a newly allocated slice will be returned.
// It is valid to pass a nil dst.
pub fn Encode(dst: &'a mut [u8], src: &mut [u8]) -> Result<&'a mut [u8], &'static str> {

	unimplemented!()
	Ok(dst.split_at_mut(i).1)
}

<commit_msg>Port EmitCopy<commit_after>use std::io;
use std::result;

use definitions::*;

// We limit how far copy back-references can go, the same as the C++ code.
const maxOffset: u16 = 1 << 15;

// emitLiteral writes a literal chunk and returns the number of bytes written.
fn emit_literal(dst: &mut [u8], lit: &mut [u8]) -> Result<usize, &'static str> {

	let mut i: usize;
	let n : u64 = (lit.len() -1) as u64;

	if n < 60 {
		dst[0] = (n as u8) << 2 | TAG_LITERAL;
		i = 1;
	} else if n < 1<<8 {
		dst[0] = 60<<2 | TAG_LITERAL;
		dst[1] = n as u8;
		i = 2;
	} else if n < 1<<16 {
		dst[0] = 61<<2 | TAG_LITERAL;
		dst[1] = n as u8;
		dst[2] = (n >> 8) as u8;
		i = 3;
	} else if n < 1<<32 {
		dst[0] = 63<<2 | TAG_LITERAL;
		dst[1] = n as u8;
		dst[2] = (n >> 8) as u8;
		dst[3] = (n >> 16) as u8;
		dst[4] = (n >> 24) as u8;
		i = 5;
	} else {
		return Err("snappy: source buffer is too long")
	}

	let mut s = 0;
	for (d, l) in dst.split_at_mut(i).1.iter_mut().zip(lit.iter()) {
        *d = *l;
        s += 1;
    }

    if(s == lit.len()){
		Ok(i + lit.len())
    } else {
    	Err("snappy: destination buffer is too short")
    }
}

// emitCopy writes a copy chunk and returns the number of bytes written.
fn emit_copy(dst: &mut [u8], offset: u8, length: usize) -> Result<usize, &'static str> {

	let mut i: usize = 0;

	while length > 0 {
		let mut x = length - 4;
		if 0 <=x && x < 1<<3 && offset < 1<<11 {
			dst[i] = (offset>>8 as u8)&0x07<<5 | (x as u8)<<2 | TAG_COPY_1;
			dst[i+1] = offset as u8;
			i += 2;
			break;
		}
		x = length;
		if x > 1<<6 {
			x = 1 << 6;
		}
		dst[i] = (x-1 as u8)<<2 | TAG_COPY_2;
		dst[i+1] = offset as u8;
		dst[i+2] = (offset >> 8) as u8;
		i += 3;
		length -= x;
	}
	i
}

// MaxEncodedLen returns the maximum length of a snappy block, given its
// uncompressed length.
pub fn MaxEncodedLen(srcLen : u64) ->  u64 {
	32 + srcLen + srcLen/6
}

// Encode returns the encoded form of src. The returned slice may be a sub-
// slice of dst if dst was large enough to hold the entire encoded block.
// Otherwise, a newly allocated slice will be returned.
// It is valid to pass a nil dst.
pub fn Encode(dst: &'a mut [u8], src: &mut [u8]) -> Result<&'a mut [u8], &'static str> {

	unimplemented!();
	// Ok(dst.split_at_mut(i).1)
}

<|endoftext|>


<commit_before>
use std::io::Read;  // Trait providing read_to_string()

use hyper;
use rustc_serialize;

use projects;
use groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Debug)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
            client: hyper::Client::new(),
            pagination: Pagination {page: 1, per_page: 20},
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}&page={}&per_page={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token,
                                self.pagination.page,
                                self.pagination.per_page)
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        // self.get("version")
        let url = self.build_url("version");
        // Close connections after each GET.
        let res = self.client.get(&url).header(hyper::header::Connection::close()).send();

        res
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn get<T>(&self, command: &str) -> Result<T, rustc_serialize::json::DecoderError>
            where T: rustc_serialize::Decodable {

        let url = self.build_url(command);
        let mut res: hyper::client::Response =
                        self.client
                        .get(&url)
                        .header(hyper::header::Connection::close())
                        .send()
                        .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        rustc_serialize::json::decode(body.as_str())
    }

    pub fn version(&self) -> Result<Version, rustc_serialize::json::DecoderError> {
        self.get("version")
    }

    pub fn groups(&self) -> Result<Vec<groups::Group>, rustc_serialize::json::DecoderError> {
        self.get("groups")
    }

    pub fn projects(&self) {
        // let mut res: hyper::client::Response = self.get("projects").unwrap();
        let url = self.build_url("projects");
        let mut res: hyper::client::Response =
                        self.client
                        .get(&url)
                        .header(hyper::header::Connection::close())
                        .send()
                        .unwrap();
        println!("####################################################################");
        println!("res: {:?}", res);
        println!("####################################################################");
        println!("Response: {}", res.status);
        println!("####################################################################");
        println!("Headers:\n{}", res.headers);
        println!("####################################################################");

        // let fresh_request = Request::get(url);
        // let streaming_request = fresh_request.start();
        // let mut response = streaming_request.send();
        // Ok(response.read_to_string())

        // let mut body = Vec::new::<u8>();
        // body.resize(, 0);
        // let result = res.read_exact(&body);

        // println!("####################################################################");
        println!("----------------------------");
        let mut body = String::new();
        println!("----------------------------");
        res.read_to_string(&mut body).unwrap();
        // println!("####################################################################");
        // let result = res.read_to_string(&mut body);
        // println!("####################################################################");
        // println!("body:\n{}", body);

        let projects: projects::Projects = rustc_serialize::json::decode(body.as_str()).unwrap();
        println!("{}", projects.p[0].description);

    }

    // pub fn projects(&self) -> ProjectManager {
    //     ProjectManager()
    // }
}

#[cfg(test)]
mod tests {
    use std::env;
    use gitlab::GitLab;

    #[test]
    fn list_projects() {
        let token = match env::var("GITLAB_TOKEN") {
            Ok(val) => val,
            Err(_)  => panic!("Please set environment variable 'GITLAB_TOKEN'"),
        };

        let gl = GitLab::new_https("gitlab.com", &token);
        println!("gl: {:?}", gl);

        gl.projects();
        // assert_eq!(gl.attempt_connection().unwrap().status, hyper::Ok);

    }
}
<commit_msg>Use the Groups<commit_after>
use std::io::Read;  // Trait providing read_to_string()

use hyper;
use rustc_serialize;

use projects;
use groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Debug)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
            client: hyper::Client::new(),
            pagination: Pagination {page: 1, per_page: 20},
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}&page={}&per_page={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token,
                                self.pagination.page,
                                self.pagination.per_page)
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        // self.get("version")
        let url = self.build_url("version");
        // Close connections after each GET.
        let res = self.client.get(&url).header(hyper::header::Connection::close()).send();

        res
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn get<T>(&self, command: &str) -> Result<T, rustc_serialize::json::DecoderError>
            where T: rustc_serialize::Decodable {

        let url = self.build_url(command);
        let mut res: hyper::client::Response =
                        self.client
                        .get(&url)
                        .header(hyper::header::Connection::close())
                        .send()
                        .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        rustc_serialize::json::decode(body.as_str())
    }

    pub fn version(&self) -> Result<Version, rustc_serialize::json::DecoderError> {
        self.get("version")
    }

    pub fn groups(&self) -> Result<groups::Groups, rustc_serialize::json::DecoderError> {
        self.get("groups")
    }

    pub fn projects(&self) {
        // let mut res: hyper::client::Response = self.get("projects").unwrap();
        let url = self.build_url("projects");
        let mut res: hyper::client::Response =
                        self.client
                        .get(&url)
                        .header(hyper::header::Connection::close())
                        .send()
                        .unwrap();
        println!("####################################################################");
        println!("res: {:?}", res);
        println!("####################################################################");
        println!("Response: {}", res.status);
        println!("####################################################################");
        println!("Headers:\n{}", res.headers);
        println!("####################################################################");

        // let fresh_request = Request::get(url);
        // let streaming_request = fresh_request.start();
        // let mut response = streaming_request.send();
        // Ok(response.read_to_string())

        // let mut body = Vec::new::<u8>();
        // body.resize(, 0);
        // let result = res.read_exact(&body);

        // println!("####################################################################");
        println!("----------------------------");
        let mut body = String::new();
        println!("----------------------------");
        res.read_to_string(&mut body).unwrap();
        // println!("####################################################################");
        // let result = res.read_to_string(&mut body);
        // println!("####################################################################");
        // println!("body:\n{}", body);

        let projects: projects::Projects = rustc_serialize::json::decode(body.as_str()).unwrap();
        println!("{}", projects.p[0].description);

    }

    // pub fn projects(&self) -> ProjectManager {
    //     ProjectManager()
    // }
}

#[cfg(test)]
mod tests {
    use std::env;
    use gitlab::GitLab;

    #[test]
    fn list_projects() {
        let token = match env::var("GITLAB_TOKEN") {
            Ok(val) => val,
            Err(_)  => panic!("Please set environment variable 'GITLAB_TOKEN'"),
        };

        let gl = GitLab::new_https("gitlab.com", &token);
        println!("gl: {:?}", gl);

        gl.projects();
        // assert_eq!(gl.attempt_connection().unwrap().status, hyper::Ok);

    }
}
<|endoftext|>


<commit_before>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Types that facilitate representing `GObject` descendants.

use translate::*;
use types::{self, StaticType};
use wrapper::{UnsafeFrom, Wrapper};
use gobject_ffi;

/// Declares the "is a" relationship.
///
/// `Self` is said to implement `T`. The trait can only be implemented if the appropriate
/// `ToGlibPtr` implementations exist.
///
/// `T` always implements `Upcast<T>`.
pub trait Upcast<T: StaticType + Wrapper>: StaticType + Wrapper +
    Into<ObjectRef> + UnsafeFrom<ObjectRef> +
    for<'a> ToGlibPtr<'a, *mut <T as Wrapper>::GlibType> { }

impl<T> Upcast<T> for T
where T: StaticType + Wrapper + Into<ObjectRef> + UnsafeFrom<ObjectRef> +
    for<'a> ToGlibPtr<'a, *mut <T as Wrapper>::GlibType> { }

/// Downcasts support.
pub trait Downcast<T> {
    /// Tries to downcast to `T`.
    ///
    /// Returns `Ok(T)` if the instance implements `T` and `Err(Self)` otherwise.
    fn downcast(self) -> Result<T, Self> where Self: Sized;
    /// Downcasts to `T` unconditionally.
    ///
    /// Panics if compiled with `debug_assertions` and the instance doesn't implement `T`.
    unsafe fn downcast_unchecked(self) -> T;
}

impl<Super: Upcast<Super>, Sub: Upcast<Super>> Downcast<Sub> for Super {
    #[inline]
    fn downcast(self) -> Result<Sub, Super> {
        unsafe {
            if !types::instance_of::<Sub>(self.to_glib_none().0 as *const _) {
                return Err(self);
            }
            Ok(Sub::from(self.into()))
        }
    }

    #[inline]
    unsafe fn downcast_unchecked(self) -> Sub {
        debug_assert!(types::instance_of::<Sub>(self.to_glib_none().0 as *const _));
        Sub::from(self.into())
    }
}

#[doc(hidden)]
pub use gobject_ffi::GObject;

glib_wrapper! {
    #[doc(hidden)]
    pub struct ObjectRef(Refcounted<GObject>);

    match fn {
        ref => |ptr| gobject_ffi::g_object_ref(ptr),
        unref => |ptr| gobject_ffi::g_object_unref(ptr),
    }
}

/// Wrapper implementations for Object types. See `glib_wrapper!`.
#[macro_export]
macro_rules! glib_object_wrapper {
    ([$($attr:meta)*] $name:ident, $ffi_name:path, @get_type $get_type_expr:expr) => {
        $(#[$attr])*
        #[derive(Clone, Debug, PartialEq, Eq, Hash)]
        pub struct $name($crate::object::ObjectRef, ::std::marker::PhantomData<$ffi_name>);

        impl Into<$crate::object::ObjectRef> for $name {
            fn into(self) -> $crate::object::ObjectRef {
                self.0
            }
        }

        impl $crate::wrapper::UnsafeFrom<$crate::object::ObjectRef> for $name {
            unsafe fn from(t: $crate::object::ObjectRef) -> Self {
                $name(t, ::std::marker::PhantomData)
            }
        }

        impl $crate::translate::GlibPtrDefault for $name {
            type GlibType = *mut $ffi_name;
        }

        impl $crate::wrapper::Wrapper for $name {
            type GlibType = $ffi_name;
        }

        impl<'a> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name {
            type Storage = <$crate::object::ObjectRef as
                $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;

            #[inline]
            fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> {
                let stash = self.0.to_glib_none();
                $crate::translate::Stash(stash.0 as *const _, stash.1)
            }

            #[inline]
            fn to_glib_full(&self) -> *const $ffi_name {
                self.0.to_glib_full() as *const _
            }
        }

        impl<'a> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name {
            type Storage = <$crate::object::ObjectRef as
                $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;

            #[inline]
            fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> {
                let stash = self.0.to_glib_none();
                $crate::translate::Stash(stash.0 as *mut _, stash.1)
            }

            #[inline]
            fn to_glib_full(&self) -> *mut $ffi_name {
                self.0.to_glib_full() as *mut _
            }
        }

        impl $crate::translate::FromGlibPtr<*mut $ffi_name> for $name {
            #[inline]
            unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
                $name($crate::translate::from_glib_none(ptr as *mut _), ::std::marker::PhantomData)
            }

            #[inline]
            unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
                $name($crate::translate::from_glib_full(ptr as *mut _), ::std::marker::PhantomData)
            }

            #[inline]
            unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> Self {
                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
                $name($crate::translate::from_glib_borrow(ptr as *mut _),
                      ::std::marker::PhantomData)
            }
        }

        impl $crate::types::StaticType for $name {
            fn static_type() -> $crate::types::Type {
                unsafe { $crate::translate::from_glib($get_type_expr) }
            }
        }
    };

    ([$($attr:meta)*] $name:ident, $ffi_name:path, @get_type $get_type_expr:expr,
     [$($implements:path),*]) => {
        glib_object_wrapper!([$($attr)*] $name, $ffi_name, @get_type $get_type_expr);

        impl<'a> $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject> for $name {
            type Storage = <$crate::object::ObjectRef as
                $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;

            #[inline]
            fn to_glib_none(&'a self)
                    -> $crate::translate::Stash<'a, *mut $crate::object::GObject, Self> {
                let stash = self.0.to_glib_none();
                $crate::translate::Stash(stash.0 as *mut _, stash.1)
            }

            #[inline]
            fn to_glib_full(&self) -> *mut $crate::object::GObject {
                (&self.0).to_glib_full() as *mut _
            }
        }

        impl $crate::object::Upcast<$crate::object::Object> for $name { }

        $(
            impl<'a> $crate::translate::ToGlibPtr<'a,
                    *mut <$implements as $crate::wrapper::Wrapper>::GlibType> for $name {
                type Storage = <$crate::object::ObjectRef as
                    $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;

                #[inline]
                fn to_glib_none(&'a self) -> $crate::translate::Stash<'a,
                        *mut <$implements as $crate::wrapper::Wrapper>::GlibType, Self> {
                    let stash = self.0.to_glib_none();
                    debug_assert!($crate::types::instance_of::<$implements>(stash.0 as *const _));
                    $crate::translate::Stash(stash.0 as *mut _, stash.1)
                }

                #[inline]
                fn to_glib_full(&self)
                        -> *mut <$implements as $crate::wrapper::Wrapper>::GlibType {
                    let ptr = self.0.to_glib_full();
                    debug_assert!($crate::types::instance_of::<$implements>(ptr as *const _));
                    ptr as *mut _
                }
            }

            impl $crate::object::Upcast<$implements> for $name { }
        )*
    }
}

glib_object_wrapper! {
    [doc = "The base class in the object hierarchy."]
    Object, GObject, @get_type gobject_ffi::g_object_get_type()
}

pub trait ObjectExt {
}

impl<T: Upcast<Object>> ObjectExt for T {
}
<commit_msg>Restore `Upcast::upcast`<commit_after>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Types that facilitate representing `GObject` descendants.

use translate::*;
use types::{self, StaticType};
use wrapper::{UnsafeFrom, Wrapper};
use gobject_ffi;

/// Declares the "is a" relationship.
///
/// `Self` is said to implement `T`. The trait can only be implemented if the appropriate
/// `ToGlibPtr` implementations exist.
///
/// `T` always implements `Upcast<T>`.
pub trait Upcast<T: StaticType + UnsafeFrom<ObjectRef> + Wrapper>: StaticType + Wrapper +
    Into<ObjectRef> + UnsafeFrom<ObjectRef> +
    for<'a> ToGlibPtr<'a, *mut <T as Wrapper>::GlibType> {
    fn upcast(self) -> T {
        unsafe { T::from(self.into()) }
    }
}

impl<T> Upcast<T> for T
where T: StaticType + Wrapper + Into<ObjectRef> + UnsafeFrom<ObjectRef> +
    for<'a> ToGlibPtr<'a, *mut <T as Wrapper>::GlibType> { }

/// Downcasts support.
pub trait Downcast<T> {
    /// Tries to downcast to `T`.
    ///
    /// Returns `Ok(T)` if the instance implements `T` and `Err(Self)` otherwise.
    fn downcast(self) -> Result<T, Self> where Self: Sized;
    /// Downcasts to `T` unconditionally.
    ///
    /// Panics if compiled with `debug_assertions` and the instance doesn't implement `T`.
    unsafe fn downcast_unchecked(self) -> T;
}

impl<Super: Upcast<Super>, Sub: Upcast<Super>> Downcast<Sub> for Super {
    #[inline]
    fn downcast(self) -> Result<Sub, Super> {
        unsafe {
            if !types::instance_of::<Sub>(self.to_glib_none().0 as *const _) {
                return Err(self);
            }
            Ok(Sub::from(self.into()))
        }
    }

    #[inline]
    unsafe fn downcast_unchecked(self) -> Sub {
        debug_assert!(types::instance_of::<Sub>(self.to_glib_none().0 as *const _));
        Sub::from(self.into())
    }
}

#[doc(hidden)]
pub use gobject_ffi::GObject;

glib_wrapper! {
    #[doc(hidden)]
    pub struct ObjectRef(Refcounted<GObject>);

    match fn {
        ref => |ptr| gobject_ffi::g_object_ref(ptr),
        unref => |ptr| gobject_ffi::g_object_unref(ptr),
    }
}

/// Wrapper implementations for Object types. See `glib_wrapper!`.
#[macro_export]
macro_rules! glib_object_wrapper {
    ([$($attr:meta)*] $name:ident, $ffi_name:path, @get_type $get_type_expr:expr) => {
        $(#[$attr])*
        #[derive(Clone, Debug, PartialEq, Eq, Hash)]
        pub struct $name($crate::object::ObjectRef, ::std::marker::PhantomData<$ffi_name>);

        impl Into<$crate::object::ObjectRef> for $name {
            fn into(self) -> $crate::object::ObjectRef {
                self.0
            }
        }

        impl $crate::wrapper::UnsafeFrom<$crate::object::ObjectRef> for $name {
            unsafe fn from(t: $crate::object::ObjectRef) -> Self {
                $name(t, ::std::marker::PhantomData)
            }
        }

        impl $crate::translate::GlibPtrDefault for $name {
            type GlibType = *mut $ffi_name;
        }

        impl $crate::wrapper::Wrapper for $name {
            type GlibType = $ffi_name;
        }

        impl<'a> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name {
            type Storage = <$crate::object::ObjectRef as
                $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;

            #[inline]
            fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> {
                let stash = self.0.to_glib_none();
                $crate::translate::Stash(stash.0 as *const _, stash.1)
            }

            #[inline]
            fn to_glib_full(&self) -> *const $ffi_name {
                self.0.to_glib_full() as *const _
            }
        }

        impl<'a> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name {
            type Storage = <$crate::object::ObjectRef as
                $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;

            #[inline]
            fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> {
                let stash = self.0.to_glib_none();
                $crate::translate::Stash(stash.0 as *mut _, stash.1)
            }

            #[inline]
            fn to_glib_full(&self) -> *mut $ffi_name {
                self.0.to_glib_full() as *mut _
            }
        }

        impl $crate::translate::FromGlibPtr<*mut $ffi_name> for $name {
            #[inline]
            unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
                $name($crate::translate::from_glib_none(ptr as *mut _), ::std::marker::PhantomData)
            }

            #[inline]
            unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
                $name($crate::translate::from_glib_full(ptr as *mut _), ::std::marker::PhantomData)
            }

            #[inline]
            unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> Self {
                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
                $name($crate::translate::from_glib_borrow(ptr as *mut _),
                      ::std::marker::PhantomData)
            }
        }

        impl $crate::types::StaticType for $name {
            fn static_type() -> $crate::types::Type {
                unsafe { $crate::translate::from_glib($get_type_expr) }
            }
        }
    };

    ([$($attr:meta)*] $name:ident, $ffi_name:path, @get_type $get_type_expr:expr,
     [$($implements:path),*]) => {
        glib_object_wrapper!([$($attr)*] $name, $ffi_name, @get_type $get_type_expr);

        impl<'a> $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject> for $name {
            type Storage = <$crate::object::ObjectRef as
                $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;

            #[inline]
            fn to_glib_none(&'a self)
                    -> $crate::translate::Stash<'a, *mut $crate::object::GObject, Self> {
                let stash = self.0.to_glib_none();
                $crate::translate::Stash(stash.0 as *mut _, stash.1)
            }

            #[inline]
            fn to_glib_full(&self) -> *mut $crate::object::GObject {
                (&self.0).to_glib_full() as *mut _
            }
        }

        impl $crate::object::Upcast<$crate::object::Object> for $name { }

        $(
            impl<'a> $crate::translate::ToGlibPtr<'a,
                    *mut <$implements as $crate::wrapper::Wrapper>::GlibType> for $name {
                type Storage = <$crate::object::ObjectRef as
                    $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;

                #[inline]
                fn to_glib_none(&'a self) -> $crate::translate::Stash<'a,
                        *mut <$implements as $crate::wrapper::Wrapper>::GlibType, Self> {
                    let stash = self.0.to_glib_none();
                    debug_assert!($crate::types::instance_of::<$implements>(stash.0 as *const _));
                    $crate::translate::Stash(stash.0 as *mut _, stash.1)
                }

                #[inline]
                fn to_glib_full(&self)
                        -> *mut <$implements as $crate::wrapper::Wrapper>::GlibType {
                    let ptr = self.0.to_glib_full();
                    debug_assert!($crate::types::instance_of::<$implements>(ptr as *const _));
                    ptr as *mut _
                }
            }

            impl $crate::object::Upcast<$implements> for $name { }
        )*
    }
}

glib_object_wrapper! {
    [doc = "The base class in the object hierarchy."]
    Object, GObject, @get_type gobject_ffi::g_object_get_type()
}

pub trait ObjectExt {
}

impl<T: Upcast<Object>> ObjectExt for T {
}
<|endoftext|>