<commit_before>use std::ptr::null;
use std::str::raw;
use libc::{c_int, c_char, c_double};
use sync::mutex::{StaticMutex, MUTEX_INIT};

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *c_char, bUpdate: c_int, pahDriverList: *()) -> *();
    fn OGR_DS_GetLayerCount(hDS: *()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *());
    fn OGR_DS_GetLayer(hDS: *(), iLayer: c_int) -> *();
    fn OGR_L_GetNextFeature(hLayer: *()) -> *();
    fn OGR_F_GetFieldIndex(hFeat: *(), pszName: *c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *(), i: c_int) -> *();
    fn OGR_F_GetFieldAsString(hFeat: *(), iField: c_int) -> *c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *(), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *()) -> *();
    fn OGR_F_Destroy(hFeat: *());
    fn OGR_G_ExportToWkt(hGeom: *(), ppszSrcText: **c_char) -> c_int;
    fn OGR_Fld_GetType(hDefn: *()) -> c_int;
    fn OGRFree(ptr: *());
}

static OFTInteger:        c_int = 0;
static OFTIntegerList:    c_int = 1;
static OFTReal:           c_int = 2;
static OFTRealList:       c_int = 3;
static OFTString:         c_int = 4;
static OFTStringList:     c_int = 5;
static OFTWideString:     c_int = 6;
static OFTWideStringList: c_int = 7;
static OFTBinary:         c_int = 8;
static OFTDate:           c_int = 9;
static OFTTime:           c_int = 10;
static OFTDateTime:       c_int = 11;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

pub enum FieldValue {
    StringValue(String),
    F64Value(f64),
}

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *(),
}

impl VectorDataset {
    pub fn get_layer_count(&self) -> int {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as int;
    }

    pub fn get_layer<'a>(&'a self, idx: int) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    vector_dataset: &'a VectorDataset,
    c_layer: *(),
}

impl<'a> Layer<'a> {
    pub fn features<'a>(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator<Feature<'a>> for FeatureIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    layer: &'a Layer<'a>,
    c_feature: *(),
}

impl<'a> Feature<'a> {
    pub fn get_field(&self, name: String) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFTString => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(StringValue(raw::from_c_str(rv)));
                },
                OFTReal => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(F64Value(rv as f64));
                },
                _ => fail!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn get_string_field(&self, name: String) -> String {
        return match self.get_field(name) {
            Some(StringValue(rv)) => rv,
            _ => fail!("not a string")
        }
    }

    pub fn get_f64_field(&self, name: String) -> f64 {
        return match self.get_field(name) {
            Some(F64Value(rv)) => rv,
            _ => fail!("not an f64")
        }
    }

    pub fn get_wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = raw::from_c_str(c_wkt);
            OGRFree(c_wkt as *());
            return wkt;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

#[cfg(test)]
mod test {
    use std::os::getenv;
    use std::path::Path;
    use super::{Feature, open};

    fn fixture_path(name: &str) -> Path {
        let envvar = "RUST_GDAL_TEST_FIXTURES";
        let fixtures = match getenv(envvar) {
            Some(p) => Path::new(p),
            None => fail!("Environment variable {} not set", envvar)
        };
        let rv = fixtures.join(name);
        return rv;
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        assert_eq!(ds.get_layer_count(), 1);
    }

    #[test]
    fn test_iterate_features() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let features: Vec<Feature> = layer.features().collect();
        assert_eq!(features.len(), 21);
    }

    #[test]
    fn test_get_string_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert_eq!(feature.get_string_field("highway".to_string()),
                   "footway".to_string());
        assert_eq!(
            layer.features()
                 .count(|f|
                    f.get_string_field("highway".to_string()) ==
                    "residential".to_string()),
            2);
    }

    #[test]
    fn test_get_float_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert_almost_eq(feature.get_f64_field("sort_key".to_string()), -9.0);
    }

    #[test]
    fn test_get_missing_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert!(feature.get_field("no such field".to_string()).is_none());
    }

    #[test]
    fn test_get_wkt() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        let wkt = feature.get_wkt();
        assert_eq!(wkt, "LINESTRING (26.1019276 44.4302748,26.1019382 44.4303191,26.1020002 44.4304202)".to_string());
    }
}
<commit_msg>as_string and as_f64 methods<commit_after>use std::ptr::null;
use std::str::raw;
use libc::{c_int, c_char, c_double};
use sync::mutex::{StaticMutex, MUTEX_INIT};

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *c_char, bUpdate: c_int, pahDriverList: *()) -> *();
    fn OGR_DS_GetLayerCount(hDS: *()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *());
    fn OGR_DS_GetLayer(hDS: *(), iLayer: c_int) -> *();
    fn OGR_L_GetNextFeature(hLayer: *()) -> *();
    fn OGR_F_GetFieldIndex(hFeat: *(), pszName: *c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *(), i: c_int) -> *();
    fn OGR_F_GetFieldAsString(hFeat: *(), iField: c_int) -> *c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *(), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *()) -> *();
    fn OGR_F_Destroy(hFeat: *());
    fn OGR_G_ExportToWkt(hGeom: *(), ppszSrcText: **c_char) -> c_int;
    fn OGR_Fld_GetType(hDefn: *()) -> c_int;
    fn OGRFree(ptr: *());
}

static OFTInteger:        c_int = 0;
static OFTIntegerList:    c_int = 1;
static OFTReal:           c_int = 2;
static OFTRealList:       c_int = 3;
static OFTString:         c_int = 4;
static OFTStringList:     c_int = 5;
static OFTWideString:     c_int = 6;
static OFTWideStringList: c_int = 7;
static OFTBinary:         c_int = 8;
static OFTDate:           c_int = 9;
static OFTTime:           c_int = 10;
static OFTDateTime:       c_int = 11;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

pub enum FieldValue {
    StringValue(String),
    F64Value(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self { StringValue(rv) => rv, _ => fail!("not a string") }
    }

    pub fn as_f64(self) -> f64 {
        match self { F64Value(rv) => rv, _ => fail!("not an f64") }
    }
}

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *(),
}

impl VectorDataset {
    pub fn get_layer_count(&self) -> int {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as int;
    }

    pub fn get_layer<'a>(&'a self, idx: int) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    vector_dataset: &'a VectorDataset,
    c_layer: *(),
}

impl<'a> Layer<'a> {
    pub fn features<'a>(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator<Feature<'a>> for FeatureIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    layer: &'a Layer<'a>,
    c_feature: *(),
}

impl<'a> Feature<'a> {
    pub fn get_field(&self, name: String) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFTString => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(StringValue(raw::from_c_str(rv)));
                },
                OFTReal => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(F64Value(rv as f64));
                },
                _ => fail!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn get_wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = raw::from_c_str(c_wkt);
            OGRFree(c_wkt as *());
            return wkt;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

#[cfg(test)]
mod test {
    use std::os::getenv;
    use std::path::Path;
    use super::{Feature, open};

    fn fixture_path(name: &str) -> Path {
        let envvar = "RUST_GDAL_TEST_FIXTURES";
        let fixtures = match getenv(envvar) {
            Some(p) => Path::new(p),
            None => fail!("Environment variable {} not set", envvar)
        };
        let rv = fixtures.join(name);
        return rv;
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        assert_eq!(ds.get_layer_count(), 1);
    }

    #[test]
    fn test_iterate_features() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let features: Vec<Feature> = layer.features().collect();
        assert_eq!(features.len(), 21);
    }

    #[test]
    fn test_get_string_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert_eq!(feature.get_field("highway".to_string()).unwrap().as_string(),
                   "footway".to_string());
        assert_eq!(
            layer.features()
                 .count(|f|
                    f.get_field("highway".to_string()).unwrap().as_string() ==
                    "residential".to_string()),
            2);
    }

    #[test]
    fn test_get_float_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert_almost_eq(feature.get_field("sort_key".to_string()).unwrap().as_f64(), -9.0);
    }

    #[test]
    fn test_get_missing_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert!(feature.get_field("no such field".to_string()).is_none());
    }

    #[test]
    fn test_get_wkt() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        let wkt = feature.get_wkt();
        assert_eq!(wkt, "LINESTRING (26.1019276 44.4302748,26.1019382 44.4303191,26.1020002 44.4304202)".to_string());
    }
}
<|endoftext|>


<commit_before>extern crate openssl;
extern crate openssl_verify;

use std::io;
use std::fmt;
use std::error;
use self::openssl::crypto::pkcs12;
use self::openssl::error::ErrorStack;
use self::openssl::ssl::{self, SslContext, SslMethod, SSL_VERIFY_PEER, IntoSsl,
                         MidHandshakeSslStream};
use self::openssl_verify::verify_callback;

pub struct Error(ssl::Error);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<ssl::Error> for Error {
    fn from(err: ssl::Error) -> Error {
        Error(err)
    }
}

impl From<ErrorStack> for Error {
    fn from(err: ErrorStack) -> Error {
        ssl::Error::Ssl(err).into()
    }
}

pub struct Pkcs12(pkcs12::ParsedPkcs12);

impl Pkcs12 {
    pub fn from_der(buf: &[u8], pass: &str) -> Result<Pkcs12, Error> {
        let pkcs12 = try!(pkcs12::Pkcs12::from_der(buf));
        let parsed = try!(pkcs12.parse(pass));
        Ok(Pkcs12(parsed))
    }
}

pub struct MidHandshakeTlsStream<S>(MidHandshakeSslStream<S>);

impl<S> fmt::Debug for MidHandshakeTlsStream<S>
    where S: fmt::Debug
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S> MidHandshakeTlsStream<S> {
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }
}

impl<S> MidHandshakeTlsStream<S>
    where S: io::Read + io::Write
{
    pub fn handshake(self) -> Result<TlsStream<S>, HandshakeError<S>> {
        match self.0.handshake() {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub enum HandshakeError<S> {
    Failure(Error),
    Interrupted(MidHandshakeTlsStream<S>),
}

impl<S> From<ssl::HandshakeError<S>> for HandshakeError<S> {
    fn from(e: ssl::HandshakeError<S>) -> HandshakeError<S> {
        match e {
            ssl::HandshakeError::Failure(e) => HandshakeError::Failure(Error(e)),
            ssl::HandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream(s))
            }
        }
    }
}

impl<S> From<ErrorStack> for HandshakeError<S> {
    fn from(e: ErrorStack) -> HandshakeError<S> {
        HandshakeError::Failure(e.into())
    }
}

fn ctx() -> Result<SslContext, Error> {
    let mut ctx = try!(SslContext::new(SslMethod::Sslv23));
    try!(ctx.set_default_verify_paths());
    Ok(ctx)
}

pub struct ClientBuilder(SslContext);

impl ClientBuilder {
    pub fn new() -> Result<ClientBuilder, Error> {
        ctx().map(ClientBuilder)
    }

    pub fn identity(&mut self, pkcs12: Pkcs12) -> Result<(), Error> {
        // FIXME clear chain certs to clean up if called multiple times
        try!(self.0.set_certificate(&pkcs12.0.cert));
        try!(self.0.set_private_key(&pkcs12.0.pkey));
        try!(self.0.check_private_key());
        for cert in &pkcs12.0.chain {
            try!(self.0.add_extra_chain_cert(&cert));
        }
        Ok(())
    }

    pub fn handshake<S>(&self,
                        domain: &str,
                        stream: S)
                        -> Result<TlsStream<S>, HandshakeError<S>>
        where S: io::Read + io::Write
    {
        let mut ssl = try!(self.0.into_ssl());
        try!(ssl.set_hostname(domain));
        let domain = domain.to_owned();
        ssl.set_verify_callback(SSL_VERIFY_PEER, move |p, x| verify_callback(&domain, p, x));

        let s = try!(ssl::SslStream::connect(ssl, stream));
        Ok(TlsStream(s))
    }
}

/// OpenSSL-specific extensions to `ClientBuilder`.
pub trait ClientBuilderExt {
    /// Returns a shared reference to the inner `SslContext`.
    fn context(&self) -> &SslContext;

    /// Returns a mutable reference to the inner `SslContext`.
    fn context_mut(&mut self) -> &mut SslContext;
}

impl ClientBuilderExt for ::ClientBuilder {
    fn context(&self) -> &SslContext {
        &(self.0).0
    }

    fn context_mut(&mut self) -> &mut SslContext {
        &mut (self.0).0
    }
}

pub struct ServerBuilder(SslContext);

impl ServerBuilder {
    pub fn new(pkcs12: Pkcs12) -> Result<ServerBuilder, Error> {
        let mut ctx = try!(ctx());
        try!(ctx.set_certificate(&pkcs12.0.cert));
        try!(ctx.set_private_key(&pkcs12.0.pkey));
        try!(ctx.check_private_key());
        for cert in &pkcs12.0.chain {
            try!(ctx.add_extra_chain_cert(&cert));
        }
        Ok(ServerBuilder(ctx))
    }

    pub fn handshake<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
        where S: io::Read + io::Write
    {
        let s = try!(ssl::SslStream::accept(&self.0, stream));
        Ok(TlsStream(s))
    }
}

/// OpenSSL-specific extensions to `ServerBuilder`.
pub trait ServerBuilderExt {
    /// Returns a shared reference to the inner `SslContext`.
    fn context(&self) -> &SslContext;

    /// Returns a mutable reference to the inner `SslContext`.
    fn context_mut(&mut self) -> &mut SslContext;
}

impl ServerBuilderExt for ::ServerBuilder {
    fn context(&self) -> &SslContext {
        &(self.0).0
    }

    fn context_mut(&mut self) -> &mut SslContext {
        &mut (self.0).0
    }
}

pub struct TlsStream<S>(ssl::SslStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn buffered_read_size(&self) -> Result<usize, Error> {
        Ok(self.0.ssl().pending())
    }

    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

/// OpenSSL-specific extensions to `TlsStream`.
pub trait TlsStreamExt<S> {
    /// Returns a shared reference to the OpenSSL `SslStream`.
    fn raw_stream(&self) -> &ssl::SslStream<S>;

    /// Returns a mutable reference to the OpenSSL `SslStream`.
    fn raw_stream_mut(&mut self) -> &mut ssl::SslStream<S>;
}

impl<S> TlsStreamExt<S> for ::TlsStream<S> {
    fn raw_stream(&self) -> &ssl::SslStream<S> {
        &(self.0).0
    }

    fn raw_stream_mut(&mut self) -> &mut ssl::SslStream<S> {
        &mut (self.0).0
    }
}
<commit_msg>Set some defaults based on libcurl<commit_after>extern crate openssl;
extern crate openssl_verify;

use std::io;
use std::fmt;
use std::error;
use self::openssl::crypto::pkcs12;
use self::openssl::error::ErrorStack;
use self::openssl::ssl::{self, SslContext, SslMethod, SSL_VERIFY_PEER, IntoSsl,
                         MidHandshakeSslStream};
use self::openssl_verify::verify_callback;

pub struct Error(ssl::Error);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<ssl::Error> for Error {
    fn from(err: ssl::Error) -> Error {
        Error(err)
    }
}

impl From<ErrorStack> for Error {
    fn from(err: ErrorStack) -> Error {
        ssl::Error::Ssl(err).into()
    }
}

pub struct Pkcs12(pkcs12::ParsedPkcs12);

impl Pkcs12 {
    pub fn from_der(buf: &[u8], pass: &str) -> Result<Pkcs12, Error> {
        let pkcs12 = try!(pkcs12::Pkcs12::from_der(buf));
        let parsed = try!(pkcs12.parse(pass));
        Ok(Pkcs12(parsed))
    }
}

pub struct MidHandshakeTlsStream<S>(MidHandshakeSslStream<S>);

impl<S> fmt::Debug for MidHandshakeTlsStream<S>
    where S: fmt::Debug
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S> MidHandshakeTlsStream<S> {
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }
}

impl<S> MidHandshakeTlsStream<S>
    where S: io::Read + io::Write
{
    pub fn handshake(self) -> Result<TlsStream<S>, HandshakeError<S>> {
        match self.0.handshake() {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub enum HandshakeError<S> {
    Failure(Error),
    Interrupted(MidHandshakeTlsStream<S>),
}

impl<S> From<ssl::HandshakeError<S>> for HandshakeError<S> {
    fn from(e: ssl::HandshakeError<S>) -> HandshakeError<S> {
        match e {
            ssl::HandshakeError::Failure(e) => HandshakeError::Failure(Error(e)),
            ssl::HandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream(s))
            }
        }
    }
}

impl<S> From<ErrorStack> for HandshakeError<S> {
    fn from(e: ErrorStack) -> HandshakeError<S> {
        HandshakeError::Failure(e.into())
    }
}

fn ctx() -> Result<SslContext, Error> {
    let mut ctx = try!(SslContext::new(SslMethod::Sslv23));
    try!(ctx.set_default_verify_paths());

    // options to enable and cipher list lifted from libcurl
    let mut opts = ssl::SSL_OP_ALL;
    opts |= ssl::SSL_OP_NO_TICKET;
    opts |= ssl::SSL_OP_NO_COMPRESSION;
    opts &= !ssl::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
    opts &= !ssl::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
    opts |= ssl::SSL_OP_NO_SSLV2;
    opts |= ssl::SSL_OP_NO_SSLV3;
    ctx.set_options(opts);
    let ciphers = "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH";
    try!(ctx.set_cipher_list(ciphers));
    Ok(ctx)
}

pub struct ClientBuilder(SslContext);

impl ClientBuilder {
    pub fn new() -> Result<ClientBuilder, Error> {
        ctx().map(ClientBuilder)
    }

    pub fn identity(&mut self, pkcs12: Pkcs12) -> Result<(), Error> {
        // FIXME clear chain certs to clean up if called multiple times
        try!(self.0.set_certificate(&pkcs12.0.cert));
        try!(self.0.set_private_key(&pkcs12.0.pkey));
        try!(self.0.check_private_key());
        for cert in &pkcs12.0.chain {
            try!(self.0.add_extra_chain_cert(&cert));
        }
        Ok(())
    }

    pub fn handshake<S>(&self,
                        domain: &str,
                        stream: S)
                        -> Result<TlsStream<S>, HandshakeError<S>>
        where S: io::Read + io::Write
    {
        let mut ssl = try!(self.0.into_ssl());
        try!(ssl.set_hostname(domain));
        let domain = domain.to_owned();
        ssl.set_verify_callback(SSL_VERIFY_PEER, move |p, x| verify_callback(&domain, p, x));

        let s = try!(ssl::SslStream::connect(ssl, stream));
        Ok(TlsStream(s))
    }
}

/// OpenSSL-specific extensions to `ClientBuilder`.
pub trait ClientBuilderExt {
    /// Returns a shared reference to the inner `SslContext`.
    fn context(&self) -> &SslContext;

    /// Returns a mutable reference to the inner `SslContext`.
    fn context_mut(&mut self) -> &mut SslContext;
}

impl ClientBuilderExt for ::ClientBuilder {
    fn context(&self) -> &SslContext {
        &(self.0).0
    }

    fn context_mut(&mut self) -> &mut SslContext {
        &mut (self.0).0
    }
}

pub struct ServerBuilder(SslContext);

impl ServerBuilder {
    pub fn new(pkcs12: Pkcs12) -> Result<ServerBuilder, Error> {
        let mut ctx = try!(ctx());
        try!(ctx.set_certificate(&pkcs12.0.cert));
        try!(ctx.set_private_key(&pkcs12.0.pkey));
        try!(ctx.check_private_key());
        for cert in &pkcs12.0.chain {
            try!(ctx.add_extra_chain_cert(&cert));
        }
        Ok(ServerBuilder(ctx))
    }

    pub fn handshake<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
        where S: io::Read + io::Write
    {
        let s = try!(ssl::SslStream::accept(&self.0, stream));
        Ok(TlsStream(s))
    }
}

/// OpenSSL-specific extensions to `ServerBuilder`.
pub trait ServerBuilderExt {
    /// Returns a shared reference to the inner `SslContext`.
    fn context(&self) -> &SslContext;

    /// Returns a mutable reference to the inner `SslContext`.
    fn context_mut(&mut self) -> &mut SslContext;
}

impl ServerBuilderExt for ::ServerBuilder {
    fn context(&self) -> &SslContext {
        &(self.0).0
    }

    fn context_mut(&mut self) -> &mut SslContext {
        &mut (self.0).0
    }
}

pub struct TlsStream<S>(ssl::SslStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn buffered_read_size(&self) -> Result<usize, Error> {
        Ok(self.0.ssl().pending())
    }

    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

/// OpenSSL-specific extensions to `TlsStream`.
pub trait TlsStreamExt<S> {
    /// Returns a shared reference to the OpenSSL `SslStream`.
    fn raw_stream(&self) -> &ssl::SslStream<S>;

    /// Returns a mutable reference to the OpenSSL `SslStream`.
    fn raw_stream_mut(&mut self) -> &mut ssl::SslStream<S>;
}

impl<S> TlsStreamExt<S> for ::TlsStream<S> {
    fn raw_stream(&self) -> &ssl::SslStream<S> {
        &(self.0).0
    }

    fn raw_stream_mut(&mut self) -> &mut ssl::SslStream<S> {
        &mut (self.0).0
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

use ring::digest::Algorithm;

use hashutils::HashUtils;
use tree::Tree;

/// An inclusion proof represent the fact that a `value` is a member
/// of a `MerkleTree` with root hash `root_hash`, and hash function `algorithm`.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct Proof<T> {
    /// The hashing algorithm used in the original `MerkleTree`
    #[cfg_attr(feature = "serialization-serde", serde(with = "algorithm_serde"))]
    pub algorithm: &'static Algorithm,

    /// The hash of the root of the original `MerkleTree`
    pub root_hash: Vec<u8>,

    /// The first `Lemma` of the `Proof`
    pub lemma: Lemma,

    /// The value concerned by this `Proof`
    pub value: T,
}

#[cfg(feature = "serialization-serde")]
mod algorithm_serde {
    use ring::digest::{self, Algorithm};
    use serde::de::Error;
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub fn serialize<S: Serializer>(
        algorithm: &'static Algorithm,
        se: S,
    ) -> Result<S::Ok, S::Error> {
        // The `Debug` implementation of `Algorithm` prints its ID.
        format!("{:?}", algorithm).serialize(se)
    }

    pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<&'static Algorithm, D::Error> {
        let alg_str: String = Deserialize::deserialize(de)?;
        match &*alg_str {
            "SHA1" => Ok(&digest::SHA1_FOR_LEGACY_USE_ONLY),
            "SHA256" => Ok(&digest::SHA256),
            "SHA384" => Ok(&digest::SHA384),
            "SHA512" => Ok(&digest::SHA512),
            "SHA512_256" => Ok(&digest::SHA512_256),
            _ => Err(D::Error::custom("unknown hash algorithm")),
        }
    }

    #[cfg(test)]
    mod test {
        use super::*;
        use ring::digest::{
            SHA1_FOR_LEGACY_USE_ONLY as sha1, SHA256 as sha256, SHA384 as sha384, SHA512 as sha512,
            SHA512_256 as sha512_256,
        };

        static SHA1: &Algorithm = &sha1;
        static SHA256: &Algorithm = &sha256;
        static SHA384: &Algorithm = &sha384;
        static SHA512: &Algorithm = &sha512;
        static SHA512_256: &Algorithm = &sha512_256;

        #[test]
        fn test_serialize_known_algorithms() {
            extern crate serde_json;

            for alg in &[SHA1, SHA256, SHA384, SHA512, SHA512_256] {
                let mut serializer = serde_json::Serializer::with_formatter(
                    vec![],
                    serde_json::ser::PrettyFormatter::new(),
                );

                serialize(alg, &mut serializer).unwrap_or_else(|_| panic!("{:?}", alg));

                let alg_ = deserialize(&mut serde_json::Deserializer::from_slice(
                    &serializer.into_inner()[..],
                ))
                .unwrap_or_else(|_| panic!("{:?}", alg));

                assert_eq!(*alg, alg_);
            }
        }

        #[test]
        #[should_panic(expected = "unknown hash algorithm")]
        fn test_serialize_unknown_algorithm() {
            extern crate serde_json;
            {
                let alg_str = "\"BLAKE2b\"";
                let mut deserializer = serde_json::Deserializer::from_str(alg_str);
                let _ = deserialize(&mut deserializer).unwrap_or_else(|_| panic!("{:?}", alg_str));
            }
        }
    }
}

impl<T: PartialEq> PartialEq for Proof<T> {
    fn eq(&self, other: &Proof<T>) -> bool {
        self.root_hash == other.root_hash && self.lemma == other.lemma && self.value == other.value
    }
}

impl<T: Eq> Eq for Proof<T> {}

impl<T: Ord> PartialOrd for Proof<T> {
    fn partial_cmp(&self, other: &Proof<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: Ord> Ord for Proof<T> {
    fn cmp(&self, other: &Proof<T>) -> Ordering {
        self.root_hash
            .cmp(&other.root_hash)
            .then(self.value.cmp(&other.value))
            .then_with(|| self.lemma.cmp(&other.lemma))
    }
}

impl<T: Hash> Hash for Proof<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.root_hash.hash(state);
        self.lemma.hash(state);
        self.value.hash(state);
    }
}

impl<T> Proof<T> {
    /// Constructs a new `Proof`
    pub fn new(algorithm: &'static Algorithm, root_hash: Vec<u8>, lemma: Lemma, value: T) -> Self {
        Proof {
            algorithm,
            root_hash,
            lemma,
            value,
        }
    }

    /// Checks whether this inclusion proof is well-formed,
    /// and whether its root hash matches the given `root_hash`.
    pub fn validate(&self, root_hash: &[u8]) -> bool {
        if self.root_hash != root_hash || self.lemma.node_hash != root_hash {
            return false;
        }

        self.lemma.validate(self.algorithm)
    }

    /// Returns the index of this proof's value, given the total number of items in the tree.
    ///
    /// # Panics
    ///
    /// Panics if the proof is malformed. Call `validate` first.
    pub fn index(&self, count: usize) -> usize {
        self.lemma.index(count)
    }
}

/// A `Lemma` holds the hash of a node, the hash of its sibling node,
/// and a sub lemma, whose `node_hash`, when combined with this `sibling_hash`
/// must be equal to this `node_hash`.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Lemma {
    pub node_hash: Vec<u8>,
    pub sibling_hash: Option<Positioned<Vec<u8>>>,
    pub sub_lemma: Option<Box<Lemma>>,
}

impl Lemma {
    /// Attempts to generate a proof that the a value with hash `needle` is a
    /// member of the given `tree`.
    pub fn new<T>(tree: &Tree<T>, needle: &[u8]) -> Option<Lemma> {
        match *tree {
            Tree::Empty { .. } => None,

            Tree::Leaf { ref hash, .. } => Lemma::new_leaf_proof(hash, needle),

            Tree::Node {
                ref hash,
                ref left,
                ref right,
            } => Lemma::new_tree_proof(hash, needle, left, right),
        }
    }

    /// Attempts to generate a proof that the `idx`-th leaf is a member of
    /// the given tree. The `count` must equal the number of leaves in the
    /// `tree`. If `idx >= count`, `None` is returned. Otherwise it returns
    /// the new `Lemma` and the `idx`-th value.
    pub fn new_by_index<T>(tree: &Tree<T>, idx: usize, count: usize) -> Option<(Lemma, &T)> {
        if idx >= count {
            return None;
        }
        match *tree {
            Tree::Empty { .. } => None,

            Tree::Leaf {
                ref hash,
                ref value,
                ..
            } => {
                if count != 1 {
                    return None;
                }
                let lemma = Lemma {
                    node_hash: hash.clone(),
                    sibling_hash: None,
                    sub_lemma: None,
                };
                Some((lemma, value))
            }

            Tree::Node {
                ref hash,
                ref left,
                ref right,
            } => {
                let left_count = count.next_power_of_two() / 2;
                let (sub_lem_val, sibling_hash);
                if idx < left_count {
                    sub_lem_val = Lemma::new_by_index(left, idx, left_count);
                    sibling_hash = Positioned::Right(right.hash().clone());
                } else {
                    sub_lem_val = Lemma::new_by_index(right, idx - left_count, count - left_count);
                    sibling_hash = Positioned::Left(left.hash().clone());
                }
                sub_lem_val.map(|(sub_lemma, value)| {
                    let lemma = Lemma {
                        node_hash: hash.clone(),
                        sibling_hash: Some(sibling_hash),
                        sub_lemma: Some(Box::new(sub_lemma)),
                    };
                    (lemma, value)
                })
            }
        }
    }

    /// Returns the index of this lemma's value, given the total number of items in the tree.
    ///
    /// # Panics
    ///
    /// Panics if the lemma is malformed. Call `validate_lemma` first.
    pub fn index(&self, count: usize) -> usize {
        let left_count = count.next_power_of_two() / 2;
        match (self.sub_lemma.as_ref(), self.sibling_hash.as_ref()) {
            (None, None) => 0,
            (Some(l), Some(&Positioned::Left(_))) => left_count + l.index(count - left_count),
            (Some(l), Some(&Positioned::Right(_))) => l.index(left_count),
            (None, Some(_)) | (Some(_), None) => panic!("malformed lemma"),
        }
    }

    fn new_leaf_proof(hash: &[u8], needle: &[u8]) -> Option<Lemma> {
        if *hash == *needle {
            Some(Lemma {
                node_hash: hash.into(),
                sibling_hash: None,
                sub_lemma: None,
            })
        } else {
            None
        }
    }

    fn new_tree_proof<T>(
        hash: &[u8],
        needle: &[u8],
        left: &Tree<T>,
        right: &Tree<T>,
    ) -> Option<Lemma> {
        Lemma::new(left, needle)
            .map(|lemma| {
                let right_hash = right.hash().clone();
                let sub_lemma = Some(Positioned::Right(right_hash));
                (lemma, sub_lemma)
            })
            .or_else(|| {
                let sub_lemma = Lemma::new(right, needle);
                sub_lemma.map(|lemma| {
                    let left_hash = left.hash().clone();
                    let sub_lemma = Some(Positioned::Left(left_hash));
                    (lemma, sub_lemma)
                })
            })
            .map(|(sub_lemma, sibling_hash)| Lemma {
                node_hash: hash.into(),
                sibling_hash,
                sub_lemma: Some(Box::new(sub_lemma)),
            })
    }

    fn validate(&self, algorithm: &'static Algorithm) -> bool {
        match self.sub_lemma {
            None => self.sibling_hash.is_none(),

            Some(ref sub) => match self.sibling_hash {
                None => false,

                Some(Positioned::Left(ref hash)) => {
                    let combined = algorithm.hash_nodes(hash, &sub.node_hash);
                    let hashes_match = combined.as_ref() == self.node_hash.as_slice();
                    hashes_match && sub.validate(algorithm)
                }

                Some(Positioned::Right(ref hash)) => {
                    let combined = algorithm.hash_nodes(&sub.node_hash, hash);
                    let hashes_match = combined.as_ref() == self.node_hash.as_slice();
                    hashes_match && sub.validate(algorithm)
                }
            },
        }
    }
}

/// Tags a value so that we know from which branch of a `Tree` (if any) it was found.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Positioned<T> {
    /// The value was found in the left branch
    Left(T),

    /// The value was found in the right branch
    Right(T),
}
<commit_msg>Fix tests<commit_after>use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

use ring::digest::Algorithm;

use hashutils::HashUtils;
use tree::Tree;

/// An inclusion proof represent the fact that a `value` is a member
/// of a `MerkleTree` with root hash `root_hash`, and hash function `algorithm`.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct Proof<T> {
    /// The hashing algorithm used in the original `MerkleTree`
    #[cfg_attr(feature = "serialization-serde", serde(with = "algorithm_serde"))]
    pub algorithm: &'static Algorithm,

    /// The hash of the root of the original `MerkleTree`
    pub root_hash: Vec<u8>,

    /// The first `Lemma` of the `Proof`
    pub lemma: Lemma,

    /// The value concerned by this `Proof`
    pub value: T,
}

#[cfg(feature = "serialization-serde")]
mod algorithm_serde {
    use ring::digest::{self, Algorithm};
    use serde::de::Error;
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub fn serialize<S: Serializer>(
        algorithm: &'static Algorithm,
        se: S,
    ) -> Result<S::Ok, S::Error> {
        // The `Debug` implementation of `Algorithm` prints its ID.
        format!("{:?}", algorithm).serialize(se)
    }

    pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<&'static Algorithm, D::Error> {
        let alg_str: String = Deserialize::deserialize(de)?;
        match &*alg_str {
            "SHA1" => Ok(&digest::SHA1_FOR_LEGACY_USE_ONLY),
            "SHA256" => Ok(&digest::SHA256),
            "SHA384" => Ok(&digest::SHA384),
            "SHA512" => Ok(&digest::SHA512),
            "SHA512_256" => Ok(&digest::SHA512_256),
            _ => Err(D::Error::custom("unknown hash algorithm")),
        }
    }

    #[cfg(test)]
    mod test {
        use super::*;
        use ring::digest::{
            SHA1_FOR_LEGACY_USE_ONLY as sha1, SHA256 as sha256, SHA384 as sha384, SHA512 as sha512,
            SHA512_256 as sha512_256,
        };

        static SHA1: &Algorithm = &sha1;
        static SHA256: &Algorithm = &sha256;
        static SHA384: &Algorithm = &sha384;
        static SHA512: &Algorithm = &sha512;
        static SHA512_256: &Algorithm = &sha512_256;

        #[test]
        fn test_serialize_known_algorithms() {
            extern crate serde_json;

            for alg in &[SHA1, SHA256, SHA384, SHA512, SHA512_256] {
                let mut serializer = serde_json::Serializer::with_formatter(
                    vec![],
                    serde_json::ser::PrettyFormatter::new(),
                );

                serialize(alg, &mut serializer).unwrap_or_else(|_| panic!("{:?}", alg));

                let alg_ = deserialize(&mut serde_json::Deserializer::from_slice(
                    &serializer.into_inner()[..],
                ))
                .unwrap_or_else(|_| panic!("{:?}", alg));

                assert_eq!(*alg, alg_);
            }
        }

        #[test]
        #[should_panic(expected = "unknown hash algorithm")]
        fn test_serialize_unknown_algorithm() {
            extern crate serde_json;
            {
                let alg_str = "\"BLAKE2b\"";
                let mut deserializer = serde_json::Deserializer::from_str(alg_str);
                let _ = deserialize(&mut deserializer)
                    .unwrap_or_else(|_| panic!("unknown hash algorithm {:?}", alg_str));
            }
        }
    }
}

impl<T: PartialEq> PartialEq for Proof<T> {
    fn eq(&self, other: &Proof<T>) -> bool {
        self.root_hash == other.root_hash && self.lemma == other.lemma && self.value == other.value
    }
}

impl<T: Eq> Eq for Proof<T> {}

impl<T: Ord> PartialOrd for Proof<T> {
    fn partial_cmp(&self, other: &Proof<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: Ord> Ord for Proof<T> {
    fn cmp(&self, other: &Proof<T>) -> Ordering {
        self.root_hash
            .cmp(&other.root_hash)
            .then(self.value.cmp(&other.value))
            .then_with(|| self.lemma.cmp(&other.lemma))
    }
}

impl<T: Hash> Hash for Proof<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.root_hash.hash(state);
        self.lemma.hash(state);
        self.value.hash(state);
    }
}

impl<T> Proof<T> {
    /// Constructs a new `Proof`
    pub fn new(algorithm: &'static Algorithm, root_hash: Vec<u8>, lemma: Lemma, value: T) -> Self {
        Proof {
            algorithm,
            root_hash,
            lemma,
            value,
        }
    }

    /// Checks whether this inclusion proof is well-formed,
    /// and whether its root hash matches the given `root_hash`.
    pub fn validate(&self, root_hash: &[u8]) -> bool {
        if self.root_hash != root_hash || self.lemma.node_hash != root_hash {
            return false;
        }

        self.lemma.validate(self.algorithm)
    }

    /// Returns the index of this proof's value, given the total number of items in the tree.
    ///
    /// # Panics
    ///
    /// Panics if the proof is malformed. Call `validate` first.
    pub fn index(&self, count: usize) -> usize {
        self.lemma.index(count)
    }
}

/// A `Lemma` holds the hash of a node, the hash of its sibling node,
/// and a sub lemma, whose `node_hash`, when combined with this `sibling_hash`
/// must be equal to this `node_hash`.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Lemma {
    pub node_hash: Vec<u8>,
    pub sibling_hash: Option<Positioned<Vec<u8>>>,
    pub sub_lemma: Option<Box<Lemma>>,
}

impl Lemma {
    /// Attempts to generate a proof that the a value with hash `needle` is a
    /// member of the given `tree`.
    pub fn new<T>(tree: &Tree<T>, needle: &[u8]) -> Option<Lemma> {
        match *tree {
            Tree::Empty { .. } => None,

            Tree::Leaf { ref hash, .. } => Lemma::new_leaf_proof(hash, needle),

            Tree::Node {
                ref hash,
                ref left,
                ref right,
            } => Lemma::new_tree_proof(hash, needle, left, right),
        }
    }

    /// Attempts to generate a proof that the `idx`-th leaf is a member of
    /// the given tree. The `count` must equal the number of leaves in the
    /// `tree`. If `idx >= count`, `None` is returned. Otherwise it returns
    /// the new `Lemma` and the `idx`-th value.
    pub fn new_by_index<T>(tree: &Tree<T>, idx: usize, count: usize) -> Option<(Lemma, &T)> {
        if idx >= count {
            return None;
        }
        match *tree {
            Tree::Empty { .. } => None,

            Tree::Leaf {
                ref hash,
                ref value,
                ..
            } => {
                if count != 1 {
                    return None;
                }
                let lemma = Lemma {
                    node_hash: hash.clone(),
                    sibling_hash: None,
                    sub_lemma: None,
                };
                Some((lemma, value))
            }

            Tree::Node {
                ref hash,
                ref left,
                ref right,
            } => {
                let left_count = count.next_power_of_two() / 2;
                let (sub_lem_val, sibling_hash);
                if idx < left_count {
                    sub_lem_val = Lemma::new_by_index(left, idx, left_count);
                    sibling_hash = Positioned::Right(right.hash().clone());
                } else {
                    sub_lem_val = Lemma::new_by_index(right, idx - left_count, count - left_count);
                    sibling_hash = Positioned::Left(left.hash().clone());
                }
                sub_lem_val.map(|(sub_lemma, value)| {
                    let lemma = Lemma {
                        node_hash: hash.clone(),
                        sibling_hash: Some(sibling_hash),
                        sub_lemma: Some(Box::new(sub_lemma)),
                    };
                    (lemma, value)
                })
            }
        }
    }

    /// Returns the index of this lemma's value, given the total number of items in the tree.
    ///
    /// # Panics
    ///
    /// Panics if the lemma is malformed. Call `validate_lemma` first.
    pub fn index(&self, count: usize) -> usize {
        let left_count = count.next_power_of_two() / 2;
        match (self.sub_lemma.as_ref(), self.sibling_hash.as_ref()) {
            (None, None) => 0,
            (Some(l), Some(&Positioned::Left(_))) => left_count + l.index(count - left_count),
            (Some(l), Some(&Positioned::Right(_))) => l.index(left_count),
            (None, Some(_)) | (Some(_), None) => panic!("malformed lemma"),
        }
    }

    fn new_leaf_proof(hash: &[u8], needle: &[u8]) -> Option<Lemma> {
        if *hash == *needle {
            Some(Lemma {
                node_hash: hash.into(),
                sibling_hash: None,
                sub_lemma: None,
            })
        } else {
            None
        }
    }

    fn new_tree_proof<T>(
        hash: &[u8],
        needle: &[u8],
        left: &Tree<T>,
        right: &Tree<T>,
    ) -> Option<Lemma> {
        Lemma::new(left, needle)
            .map(|lemma| {
                let right_hash = right.hash().clone();
                let sub_lemma = Some(Positioned::Right(right_hash));
                (lemma, sub_lemma)
            })
            .or_else(|| {
                let sub_lemma = Lemma::new(right, needle);
                sub_lemma.map(|lemma| {
                    let left_hash = left.hash().clone();
                    let sub_lemma = Some(Positioned::Left(left_hash));
                    (lemma, sub_lemma)
                })
            })
            .map(|(sub_lemma, sibling_hash)| Lemma {
                node_hash: hash.into(),
                sibling_hash,
                sub_lemma: Some(Box::new(sub_lemma)),
            })
    }

    fn validate(&self, algorithm: &'static Algorithm) -> bool {
        match self.sub_lemma {
            None => self.sibling_hash.is_none(),

            Some(ref sub) => match self.sibling_hash {
                None => false,

                Some(Positioned::Left(ref hash)) => {
                    let combined = algorithm.hash_nodes(hash, &sub.node_hash);
                    let hashes_match = combined.as_ref() == self.node_hash.as_slice();
                    hashes_match && sub.validate(algorithm)
                }

                Some(Positioned::Right(ref hash)) => {
                    let combined = algorithm.hash_nodes(&sub.node_hash, hash);
                    let hashes_match = combined.as_ref() == self.node_hash.as_slice();
                    hashes_match && sub.validate(algorithm)
                }
            },
        }
    }
}

/// Tags a value so that we know from which branch of a `Tree` (if any) it was found.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Positioned<T> {
    /// The value was found in the left branch
    Left(T),

    /// The value was found in the right branch
    Right(T),
}
<|endoftext|>


<commit_before>use select::SelectType;
use join::Join;
use order_by::OrderBy;
use where_cl::{ToSQL, WhereType};

pub struct Query<'a> {
    pub select: SelectType<'a>,
    pub from: &'a str,
    pub joins: &'a [Join<'a>],
    pub group_by: &'a [&'a str],
    pub order_by: &'a [OrderBy<'a>],
    pub where_cl: WhereType<'a>,
    pub having: WhereType<'a>
}

impl<'a> Query<'a> {
    fn to_sql(&self) -> String {
        let mut rv = String::new();
        rv.push_str("SELECT");
        rv.push(' ');
        rv.push_str(&self.select.to_sql());
        rv.push(' ');
        rv.push_str("FROM");
        rv.push(' ');
        rv.push_str(self.from);

        for join in self.joins {
            rv.push(' ');
            rv.push_str(&join.to_sql());
        }

        let where_string = " WHERE ";
        match self.where_cl {
            WhereType::Empty => {},
            WhereType::Simple(clause) => {
                rv.push_str(where_string);
                rv.push_str(&clause.to_sql());
            },
            WhereType::Extended(clause) => {
                rv.push_str(where_string);
                rv.push_str(&clause.to_sql());
            }
        }

        if !self.group_by.is_empty() {
            rv.push(' ');
            rv.push_str("GROUP BY");
            rv.push(' ');
            rv.push_str(&self.group_by.join(", "));
        }

        let having_string = " HAVING ";
        match self.having {
            WhereType::Empty => {},
            WhereType::Simple(clause) => {
                rv.push_str(having_string);
                rv.push_str(&clause.to_sql());
            },
            WhereType::Extended(clause) => {
                rv.push_str(having_string);
                rv.push_str(&clause.to_sql());
            }
        }

        if !self.order_by.is_empty() {
            rv.push(' ');
            rv.push_str("ORDER BY");
            rv.push(' ');
            rv.push_str(&self.order_by
                        .into_iter()
                        .map(|x| x.to_sql())
                        .collect::<Vec<String>>()
                        .join(", "));
        }

        rv.push(';');
        rv
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use self::test::Bencher;

    use super::Query;
    use select::SelectType;
    use join::{JoinType, Join};
    use order_by::{Ordering, OrderBy};
    use where_cl::{Operator, ToSQL, WhereType, Where};

    #[test]
    fn select_all() {
        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };
        assert_eq!(query.to_sql(), "SELECT * FROM test_table;".to_string());
    }

    #[test]
    fn select_foo_and_bar() {
        let clauses = &["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(clauses),
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };
        assert_eq!(query.to_sql(), "SELECT foo, bar FROM test_table;".to_string());
    }

    #[test]
    fn select_foo_and_bar_with_vec_params() {
        let clauses = vec!["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };
        assert_eq!(query.to_sql(), "SELECT foo, bar FROM test_table;".to_string());
    }

    #[test]
    fn select_foo_and_bar_with_vec_params_and_strings() {
        let clauses = vec!["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };
        assert_eq!(query.to_sql(), "SELECT foo, bar FROM test_table;".to_string());
    }

    #[test]
    fn select_foo_and_join_bar() {
        let join = Join {
            join_type: JoinType::Inner,
            target: "target_table",
            clause: "2 == 2"
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[join],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            INNER JOIN target_table ON 2 == 2;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_foo_and_join_bar_and_bazz() {
        let bar_join = Join {
            join_type: JoinType::Inner,
            target: "bar_table",
            clause: "1 == 1"
        };

        let bazz_join = Join {
            join_type: JoinType::Left,
            target: "bazz_table",
            clause: "2 == 2"
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[bar_join, bazz_join],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            INNER JOIN bar_table ON 1 == 1 \
            LEFT JOIN bazz_table ON 2 == 2;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_and_group_by_foo() {
        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &["foo"],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            GROUP BY foo;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_and_group_by_foo_and_bar() {
        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &["foo", "bar"],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            GROUP BY foo, bar;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_and_order_by() {
        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[order_by_foo_asc],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            ORDER BY foo ASC;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_and_multi_order_by() {
        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let order_by_bar_desc = OrderBy {
            ordering: Ordering::Descending,
            order_by: "bar"
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[order_by_foo_asc, order_by_bar_desc],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            ORDER BY foo ASC, bar DESC;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_where_simple() {
        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Simple("foo == bar"),
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            WHERE foo == bar;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_where_extended() {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Extended(&where_cl),
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            WHERE (foo == bar AND lala == blah);".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_with_having() {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Simple("foo == bar")
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            HAVING foo == bar;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_with_extended_having() {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Extended(&where_cl),
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            HAVING (foo == bar AND lala == blah);".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn test_complex() {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let order_by_bar_desc = OrderBy {
            ordering: Ordering::Descending,
            order_by: "bar"
        };

        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let bar_join = Join {
            join_type: JoinType::Inner,
            target: "bar_table",
            clause: "1 == 1"
        };

        let bazz_join = Join {
            join_type: JoinType::Left,
            target: "bazz_table",
            clause: "2 == 2"
        };

        let clauses = ["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[bar_join, bazz_join],
            group_by: &["foo", "bar"],
            order_by: &[order_by_bar_desc, order_by_foo_asc],
            where_cl: WhereType::Extended(&where_cl),
            having: WhereType::Extended(&where_cl)
        };

        let test_sql_string = {
            "SELECT foo, bar \
            FROM test_table \
            INNER JOIN bar_table ON 1 == 1 \
            LEFT JOIN bazz_table ON 2 == 2 \
            WHERE (foo == bar AND lala == blah) \
            GROUP BY foo, bar \
            HAVING (foo == bar AND lala == blah) \
            ORDER BY bar DESC, foo ASC;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[bench]
    fn bench_query_with_extended_where(b: &mut Bencher) {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let order_by_bar_desc = OrderBy {
            ordering: Ordering::Descending,
            order_by: "bar"
        };

        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let bar_join = Join {
            join_type: JoinType::Inner,
            target: "bar_table",
            clause: "1 == 1"
        };

        let bazz_join = Join {
            join_type: JoinType::Left,
            target: "bazz_table",
            clause: "2 == 2"
        };

        let clauses = ["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[bar_join, bazz_join],
            group_by: &["foo", "bar"],
            order_by: &[order_by_bar_desc, order_by_foo_asc],
            where_cl: WhereType::Extended(&where_cl),
            having: WhereType::Empty,
        };

        b.iter(|| query.to_sql());
    }

    #[bench]
    fn bench_query_with_empty_where(b: &mut Bencher) {
        let order_by_bar_desc = OrderBy {
            ordering: Ordering::Descending,
            order_by: "bar"
        };

        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let bar_join = Join {
            join_type: JoinType::Inner,
            target: "bar_table",
            clause: "1 == 1"
        };

        let bazz_join = Join {
            join_type: JoinType::Left,
            target: "bazz_table",
            clause: "2 == 2"
        };

        let clauses = ["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[bar_join, bazz_join],
            group_by: &["foo", "bar"],
            order_by: &[order_by_bar_desc, order_by_foo_asc],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        b.iter(|| query.to_sql());
    }
}
<commit_msg>Changed type of `joins` and `order_by` fields in `Query`<commit_after>use select::SelectType;
use join::Join;
use order_by::OrderBy;
use where_cl::{ToSQL, WhereType};

pub struct Query<'a> {
    pub select: SelectType<'a>,
    pub from: &'a str,
    pub joins: &'a [&'a Join<'a>],
    pub group_by: &'a [&'a str],
    pub order_by: &'a [&'a OrderBy<'a>],
    pub where_cl: WhereType<'a>,
    pub having: WhereType<'a>
}

impl<'a> Query<'a> {
    fn to_sql(&self) -> String {
        let mut rv = String::new();
        rv.push_str("SELECT");
        rv.push(' ');
        rv.push_str(&self.select.to_sql());
        rv.push(' ');
        rv.push_str("FROM");
        rv.push(' ');
        rv.push_str(self.from);

        for join in self.joins {
            rv.push(' ');
            rv.push_str(&join.to_sql());
        }

        let where_string = " WHERE ";
        match self.where_cl {
            WhereType::Empty => {},
            WhereType::Simple(clause) => {
                rv.push_str(where_string);
                rv.push_str(&clause.to_sql());
            },
            WhereType::Extended(clause) => {
                rv.push_str(where_string);
                rv.push_str(&clause.to_sql());
            }
        }

        if !self.group_by.is_empty() {
            rv.push(' ');
            rv.push_str("GROUP BY");
            rv.push(' ');
            rv.push_str(&self.group_by.join(", "));
        }

        let having_string = " HAVING ";
        match self.having {
            WhereType::Empty => {},
            WhereType::Simple(clause) => {
                rv.push_str(having_string);
                rv.push_str(&clause.to_sql());
            },
            WhereType::Extended(clause) => {
                rv.push_str(having_string);
                rv.push_str(&clause.to_sql());
            }
        }

        if !self.order_by.is_empty() {
            rv.push(' ');
            rv.push_str("ORDER BY");
            rv.push(' ');
            rv.push_str(&self.order_by
                        .into_iter()
                        .map(|x| x.to_sql())
                        .collect::<Vec<String>>()
                        .join(", "));
        }

        rv.push(';');
        rv
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use self::test::Bencher;

    use super::Query;
    use select::SelectType;
    use join::{JoinType, Join};
    use order_by::{Ordering, OrderBy};
    use where_cl::{Operator, ToSQL, WhereType, Where};

    #[test]
    fn select_all() {
        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };
        assert_eq!(query.to_sql(), "SELECT * FROM test_table;".to_string());
    }

    #[test]
    fn select_foo_and_bar() {
        let clauses = &["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(clauses),
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };
        assert_eq!(query.to_sql(), "SELECT foo, bar FROM test_table;".to_string());
    }

    #[test]
    fn select_foo_and_bar_with_vec_params() {
        let clauses = vec!["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };
        assert_eq!(query.to_sql(), "SELECT foo, bar FROM test_table;".to_string());
    }

    #[test]
    fn select_foo_and_bar_with_vec_params_and_strings() {
        let clauses = vec!["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };
        assert_eq!(query.to_sql(), "SELECT foo, bar FROM test_table;".to_string());
    }

    #[test]
    fn select_foo_and_join_bar() {
        let join = Join {
            join_type: JoinType::Inner,
            target: "target_table",
            clause: "2 == 2"
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[&join],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            INNER JOIN target_table ON 2 == 2;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_foo_and_join_bar_and_bazz() {
        let bar_join = Join {
            join_type: JoinType::Inner,
            target: "bar_table",
            clause: "1 == 1"
        };

        let bazz_join = Join {
            join_type: JoinType::Left,
            target: "bazz_table",
            clause: "2 == 2"
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[&bar_join, &bazz_join],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            INNER JOIN bar_table ON 1 == 1 \
            LEFT JOIN bazz_table ON 2 == 2;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_and_group_by_foo() {
        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &["foo"],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            GROUP BY foo;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_and_group_by_foo_and_bar() {
        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &["foo", "bar"],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            GROUP BY foo, bar;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_and_order_by() {
        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[&order_by_foo_asc],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            ORDER BY foo ASC;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_and_multi_order_by() {
        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let order_by_bar_desc = OrderBy {
            ordering: Ordering::Descending,
            order_by: "bar"
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[&order_by_foo_asc, &order_by_bar_desc],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            ORDER BY foo ASC, bar DESC;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_where_simple() {
        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Simple("foo == bar"),
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            WHERE foo == bar;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_where_extended() {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Extended(&where_cl),
            having: WhereType::Empty,
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            WHERE (foo == bar AND lala == blah);".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_with_having() {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Simple("foo == bar")
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            HAVING foo == bar;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn select_all_with_extended_having() {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let query = Query {
            select: SelectType::All,
            from: "test_table",
            joins: &[],
            group_by: &[],
            order_by: &[],
            where_cl: WhereType::Empty,
            having: WhereType::Extended(&where_cl),
        };

        let test_sql_string = {
            "SELECT * \
            FROM test_table \
            HAVING (foo == bar AND lala == blah);".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[test]
    fn test_complex() {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let order_by_bar_desc = OrderBy {
            ordering: Ordering::Descending,
            order_by: "bar"
        };

        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let bar_join = Join {
            join_type: JoinType::Inner,
            target: "bar_table",
            clause: "1 == 1"
        };

        let bazz_join = Join {
            join_type: JoinType::Left,
            target: "bazz_table",
            clause: "2 == 2"
        };

        let clauses = ["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[&bar_join, &bazz_join],
            group_by: &["foo", "bar"],
            order_by: &[&order_by_bar_desc, &order_by_foo_asc],
            where_cl: WhereType::Extended(&where_cl),
            having: WhereType::Extended(&where_cl)
        };

        let test_sql_string = {
            "SELECT foo, bar \
            FROM test_table \
            INNER JOIN bar_table ON 1 == 1 \
            LEFT JOIN bazz_table ON 2 == 2 \
            WHERE (foo == bar AND lala == blah) \
            GROUP BY foo, bar \
            HAVING (foo == bar AND lala == blah) \
            ORDER BY bar DESC, foo ASC;".to_string()
        };
        assert_eq!(query.to_sql(), test_sql_string);
    }

    #[bench]
    fn bench_query_with_extended_where(b: &mut Bencher) {
        let where_cl = Where {
            operator: Operator::And,
            clause: &["foo == bar", "lala == blah"]
        };

        let order_by_bar_desc = OrderBy {
            ordering: Ordering::Descending,
            order_by: "bar"
        };

        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let bar_join = Join {
            join_type: JoinType::Inner,
            target: "bar_table",
            clause: "1 == 1"
        };

        let bazz_join = Join {
            join_type: JoinType::Left,
            target: "bazz_table",
            clause: "2 == 2"
        };

        let clauses = ["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[&bar_join, &bazz_join],
            group_by: &["foo", "bar"],
            order_by: &[&order_by_bar_desc, &order_by_foo_asc],
            where_cl: WhereType::Extended(&where_cl),
            having: WhereType::Empty,
        };

        b.iter(|| query.to_sql());
    }

    #[bench]
    fn bench_query_with_empty_where(b: &mut Bencher) {
        let order_by_bar_desc = OrderBy {
            ordering: Ordering::Descending,
            order_by: "bar"
        };

        let order_by_foo_asc = OrderBy {
            ordering: Ordering::Ascending,
            order_by: "foo"
        };

        let bar_join = Join {
            join_type: JoinType::Inner,
            target: "bar_table",
            clause: "1 == 1"
        };

        let bazz_join = Join {
            join_type: JoinType::Left,
            target: "bazz_table",
            clause: "2 == 2"
        };

        let clauses = ["foo", "bar"];
        let query = Query {
            select: SelectType::Specific(&clauses),
            from: "test_table",
            joins: &[&bar_join, &bazz_join],
            group_by: &["foo", "bar"],
            order_by: &[&order_by_bar_desc, &order_by_foo_asc],
            where_cl: WhereType::Empty,
            having: WhereType::Empty,
        };

        b.iter(|| query.to_sql());
    }
}
<|endoftext|>


<commit_before>
use error::MpdResult;
use connection::{FromConn, MpdConnection, mpd_connection};
use songs::{MpdSong, mpd_song};
use libc;

extern {
    fn mpd_run_get_queue_song_pos(connection: *mut mpd_connection, pos: libc::c_uint) -> *mut mpd_song;
    fn mpd_run_move_id(connection: *mut mpd_connection, from: libc::c_uint, to: libc::c_uint) -> bool;
    fn mpd_run_swap_id(connection: *mut mpd_connection, id1: libc::c_uint, id2: libc::c_uint) -> bool;
}

pub struct MpdQueue<'a> {
    conn: &'a MpdConnection
}

impl<'a> MpdQueue<'a> {
    pub fn from_conn(conn: &'a MpdConnection) -> MpdQueue<'a> {
        MpdQueue { conn: conn }
    }

    pub fn get(&self, index: uint) -> Option<MpdSong> {
        let song = unsafe { mpd_run_get_queue_song_pos(self.conn.conn, index as libc::c_uint) };
        if song.is_null() {
            None
        } else {
            Some(MpdSong { song: song })
        }
    }

    pub fn move_to(&mut self, song: &MpdSong, pos: uint) -> MpdResult<()> {
        if unsafe { mpd_run_move_id(self.conn.conn, song.id(), pos as libc::c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    pub fn swap(&mut self, song1: &MpdSong, song2: &MpdSong) -> MpdResult<()> {
        if unsafe { mpd_run_swap_id(self.conn.conn, song1.id(), song2.id()) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }
}
<commit_msg>trait for song swap<commit_after>
use error::MpdResult;
use connection::{FromConn, MpdConnection, mpd_connection};
use songs::{MpdSong, mpd_song};
use libc;

extern {
    fn mpd_run_get_queue_song_pos(connection: *mut mpd_connection, pos: libc::c_uint) -> *mut mpd_song;
    fn mpd_run_move_id(connection: *mut mpd_connection, from: libc::c_uint, to: libc::c_uint) -> bool;
    fn mpd_run_swap_id(connection: *mut mpd_connection, id1: libc::c_uint, id2: libc::c_uint) -> bool;
    fn mpd_run_swap(connection: *mut mpd_connection, pos1: libc::c_uint, pos2: libc::c_uint) -> bool;
}

pub struct MpdQueue<'a> {
    conn: &'a MpdConnection
}

impl<'a> MpdQueue<'a> {
    pub fn from_conn(conn: &'a MpdConnection) -> MpdQueue<'a> {
        MpdQueue { conn: conn }
    }

    pub fn get(&self, index: uint) -> Option<MpdSong> {
        let song = unsafe { mpd_run_get_queue_song_pos(self.conn.conn, index as libc::c_uint) };
        if song.is_null() {
            None
        } else {
            Some(MpdSong { song: song })
        }
    }

    pub fn move_to(&mut self, pos: uint, song: &MpdSong) -> MpdResult<()> {
        if unsafe { mpd_run_move_id(self.conn.conn, song.id(), pos as libc::c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    pub fn swap<T: ToSongPos>(&mut self, song1: T, song2: T) -> MpdResult<()> {
        if unsafe { mpd_run_swap(self.conn.conn, song1.song_pos(), song2.song_pos()) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }
}

trait ToSongPos {
    fn song_pos(&self) -> uint;
}

impl ToSongPos for uint {
    #[inline] fn song_pos(&self) -> uint { *self }
}

impl ToSongPos for MpdSong {
    #[inline] fn song_pos(&self) -> uint { self.pos() }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

extern crate libc;

use std::{ptr, mem};

use gc_object::GCObjectRef;

mod pthread {
    extern crate libc;

    extern {
        pub fn pthread_self() -> libc::pthread_t;
        pub fn pthread_getattr_np(native: libc::pthread_t,
                                  attr: *mut libc::pthread_attr_t) -> libc::c_int;
        pub fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
                                     stackaddr: *mut *mut libc::c_void,
                                     stacksize: *mut libc::size_t) -> libc::c_int;
        pub fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    }
}

pub struct Stack {
    /// The bottom of the stack.
    ///
    /// This will be the lowest addressable address of the current threads
    /// stack buffer minus the buffer size.
    stack_bottom: *mut u8,

    /// The static roots added via `set_static_root()`.
    static_roots: Vec<*const GCObjectRef>,
}

/// Abstractions over the stack to scan the stack and the registers for
/// garbage collection roots.
impl Stack {
    /// Create a new `Stack`.
    pub fn new() -> Stack {
        Stack {
            stack_bottom: Stack::get_stack_bottom()
                                .expect("Can not get the stack bottom."),
            static_roots: Vec::new(),
        }
    }

    /// Return the top of the stack.
    ///
    /// See the `llvm.frameaddress` intrinsic for details.
    #[inline(always)]
    fn get_stack_top() -> *mut u8 {
        extern {
            #[link_name = "llvm.frameaddress"]
            fn frameaddress(level: i32) -> *mut u8;
        }
        unsafe{ frameaddress(0) }
    }

    /// Return the bottom of the stack.
    ///
    /// This will be the lowest addressable address of the current threads stack
    /// buffer minus the buffer size.
    #[inline(always)]
    #[cfg(target_os = "linux")]
    fn get_stack_bottom() -> Option<*mut u8> {
        unsafe {
            let mut attr: libc::pthread_attr_t = mem::zeroed();
            if pthread::pthread_getattr_np(pthread::pthread_self(), &mut attr) != 0 {
                return None;
            }
            let mut stackaddr = ptr::null_mut();
            let mut stacksize = 0;
            if pthread::pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
                return None;
            }
            pthread::pthread_attr_destroy(&mut attr);
            Some(stackaddr.offset(stacksize as isize) as *mut u8)
        }
    }

    /// Get the contents of the registers
    #[inline(always)]
    #[allow(unused_assignments)]
    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    pub fn get_registers() -> Vec<GCObjectRef> {
        let mut rbx = ptr::null_mut(); unsafe{ asm!("movq %rbx, %rax": "=rax" (rbx));}
        let mut rsp = ptr::null_mut(); unsafe{ asm!("movq %rsp, %rax": "=rax" (rsp));}
        let mut rbp = ptr::null_mut(); unsafe{ asm!("movq %rbp, %rax": "=rax" (rbp));}
        let mut r12 = ptr::null_mut(); unsafe{ asm!("movq %r12, %rax": "=rax" (r12));}
        let mut r13 = ptr::null_mut(); unsafe{ asm!("movq %r13, %rax": "=rax" (r13));}
        let mut r14 = ptr::null_mut(); unsafe{ asm!("movq %r14, %rax": "=rax" (r14));}
        let mut r15 = ptr::null_mut(); unsafe{ asm!("movq %r15, %rax": "=rax" (r15));}
        let registers = vec![rbx, rsp, rbp, r12, r13, r14, r15];
        debug!("Register values: {:?}", registers);
        registers
    }

    /// Set an address of an object reference as static root.
    pub fn set_static_root(&mut self, address: *const GCObjectRef) {
        debug!("Set address {:p} as static root", address);
        self.static_roots.push(address);
    }

    /// Scan the stack for garbage collection roots.
    ///
    /// This will filter all non-null values on the stack and append the
    /// static roots added via `Stack::set_static_root()`. The registers must
    /// be stored on the stack beforehand using `Stack::get_registers().
    pub fn enumerate_roots(&self) -> Vec<GCObjectRef> {
        let top = Stack::get_stack_top();
        let stack_size = (self.stack_bottom as usize) - (top as usize) - 8;
        debug!("Scanning stack of size {} ({:p} - {:p})",
               stack_size, top, self.stack_bottom);
        debug!("There are {} possible static roots: {:?}",
               self.static_roots.len(),
               self.static_roots.iter().map(|o| unsafe{ **o }).collect::<Vec<GCObjectRef>>());
        (0..stack_size).map(|o| unsafe{ *(top.offset(o as isize) as *const GCObjectRef) })
                       .filter(|o| !o.is_null())
                       .chain(self.static_roots.iter().map(|o| unsafe{ **o }))
                       .collect()
    }
}
<commit_msg>clippy: Allow needed lint errors<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

extern crate libc;

use std::{ptr, mem};

use gc_object::GCObjectRef;

mod pthread {
    extern crate libc;

    #[allow(mut_mut)]
    extern {
        pub fn pthread_self() -> libc::pthread_t;
        pub fn pthread_getattr_np(native: libc::pthread_t,
                                  attr: *mut libc::pthread_attr_t) -> libc::c_int;
        pub fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
                                     stackaddr: *mut *mut libc::c_void,
                                     stacksize: *mut libc::size_t) -> libc::c_int;
        pub fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    }
}

pub struct Stack {
    /// The bottom of the stack.
    ///
    /// This will be the lowest addressable address of the current threads
    /// stack buffer minus the buffer size.
    stack_bottom: *mut u8,

    /// The static roots added via `set_static_root()`.
    static_roots: Vec<*const GCObjectRef>,
}

/// Abstractions over the stack to scan the stack and the registers for
/// garbage collection roots.
#[allow(inline_always)]
impl Stack {
    /// Create a new `Stack`.
    pub fn new() -> Stack {
        Stack {
            stack_bottom: Stack::get_stack_bottom()
                                .expect("Can not get the stack bottom."),
            static_roots: Vec::new(),
        }
    }

    /// Return the top of the stack.
    ///
    /// See the `llvm.frameaddress` intrinsic for details.
    #[inline(always)]
    fn get_stack_top() -> *mut u8 {
        extern {
            #[link_name = "llvm.frameaddress"]
            fn frameaddress(level: i32) -> *mut u8;
        }
        unsafe{ frameaddress(0) }
    }

    /// Return the bottom of the stack.
    ///
    /// This will be the lowest addressable address of the current threads stack
    /// buffer minus the buffer size.
    #[inline(always)]
    #[cfg(target_os = "linux")]
    fn get_stack_bottom() -> Option<*mut u8> {
        unsafe {
            let mut attr: libc::pthread_attr_t = mem::zeroed();
            if pthread::pthread_getattr_np(pthread::pthread_self(), &mut attr) != 0 {
                return None;
            }
            let mut stackaddr = ptr::null_mut();
            let mut stacksize = 0;
            if pthread::pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
                return None;
            }
            pthread::pthread_attr_destroy(&mut attr);
            Some(stackaddr.offset(stacksize as isize) as *mut u8)
        }
    }

    /// Get the contents of the registers
    #[inline(always)]
    #[allow(unused_assignments)]
    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    pub fn get_registers() -> Vec<GCObjectRef> {
        let mut rbx = ptr::null_mut(); unsafe{ asm!("movq %rbx, %rax": "=rax" (rbx));}
        let mut rsp = ptr::null_mut(); unsafe{ asm!("movq %rsp, %rax": "=rax" (rsp));}
        let mut rbp = ptr::null_mut(); unsafe{ asm!("movq %rbp, %rax": "=rax" (rbp));}
        let mut r12 = ptr::null_mut(); unsafe{ asm!("movq %r12, %rax": "=rax" (r12));}
        let mut r13 = ptr::null_mut(); unsafe{ asm!("movq %r13, %rax": "=rax" (r13));}
        let mut r14 = ptr::null_mut(); unsafe{ asm!("movq %r14, %rax": "=rax" (r14));}
        let mut r15 = ptr::null_mut(); unsafe{ asm!("movq %r15, %rax": "=rax" (r15));}
        let registers = vec![rbx, rsp, rbp, r12, r13, r14, r15];
        debug!("Register values: {:?}", registers);
        registers
    }

    /// Set an address of an object reference as static root.
    pub fn set_static_root(&mut self, address: *const GCObjectRef) {
        debug!("Set address {:p} as static root", address);
        self.static_roots.push(address);
    }

    /// Scan the stack for garbage collection roots.
    ///
    /// This will filter all non-null values on the stack and append the
    /// static roots added via `Stack::set_static_root()`. The registers must
    /// be stored on the stack beforehand using `Stack::get_registers().
    pub fn enumerate_roots(&self) -> Vec<GCObjectRef> {
        let top = Stack::get_stack_top();
        let stack_size = (self.stack_bottom as usize) - (top as usize) - 8;
        debug!("Scanning stack of size {} ({:p} - {:p})",
               stack_size, top, self.stack_bottom);
        debug!("There are {} possible static roots: {:?}",
               self.static_roots.len(),
               self.static_roots.iter().map(|o| unsafe{ **o }).collect::<Vec<GCObjectRef>>());
        (0..stack_size).map(|o| unsafe{ *(top.offset(o as isize) as *const GCObjectRef) })
                       .filter(|o| !o.is_null())
                       .chain(self.static_roots.iter().map(|o| unsafe{ **o }))
                       .collect()
    }
}
<|endoftext|>