<commit_before>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use datasource::DatasourceInput;
use gdal;
use gdal::vector::{Dataset, Geometry, WkbType, FieldValue};
use gdal::spatial_ref::{SpatialRef, CoordTransform};
use core::feature::{Feature, FeatureAttr, FeatureAttrValType};
use core::geom::{self, GeometryType};
use core::grid::Extent;
use core::grid::Grid;
use core::layer::Layer;
use core::Config;
use core::config::DatasourceCfg;
use std::path::Path;

pub struct GdalDatasource {
    pub path: String,
    // We don't store the Dataset, because we need mut access for getting layers
}

impl GdalDatasource {
    pub fn new(path: &str) -> GdalDatasource {
        GdalDatasource { path: path.to_string() }
    }
}

trait ToGeo {
    fn to_geo(&self, srid: Option<i32>) -> GeometryType;
}

impl ToGeo for Geometry {
    /// Convert OGR geomtry to t-rex EWKB geometry type (XY only)
    fn to_geo(&self, srid: Option<i32>) -> GeometryType {
        let geometry_type = self.geometry_type();

        let ring = |n: usize| {
            let ring = unsafe { self._get_geometry(n) };
            return match ring.to_geo(srid) {
                       GeometryType::LineString(r) => r,
                       _ => panic!("Expected to get a LineString"),
                   };
        };

        match geometry_type {
            WkbType::WkbPoint => {
                let (x, y, _) = self.get_point(0);
                GeometryType::Point(geom::Point {
                                        x: x,
                                        y: y,
                                        srid: srid,
                                    })
            }
            WkbType::WkbMultipoint => {
                let point_count = self.geometry_count();
                let coords = (0..point_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::Point(p) => p,
                             _ => panic!("Expected to get a Point"),
                         })
                    .collect();
                GeometryType::MultiPoint(geom::MultiPoint {
                                             points: coords,
                                             srid: srid,
                                         })
            }
            WkbType::WkbLinestring => {
                let coords = self.get_point_vec()
                    .iter()
                    .map(|&(x, y, _)| {
                             geom::Point {
                                 x: x,
                                 y: y,
                                 srid: srid,
                             }
                         })
                    .collect();
                GeometryType::LineString(geom::LineString {
                                             points: coords,
                                             srid: srid,
                                         })
            }
            WkbType::WkbMultilinestring => {
                let string_count = self.geometry_count();
                let strings = (0..string_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::LineString(s) => s,
                             _ => panic!("Expected to get a LineString"),
                         })
                    .collect();
                GeometryType::MultiLineString(geom::MultiLineString {
                                                  lines: strings,
                                                  srid: srid,
                                              })
            }
            WkbType::WkbPolygon => {
                let ring_count = self.geometry_count();
                let rings = (0..ring_count).map(|n| ring(n)).collect();
                GeometryType::Polygon(geom::Polygon {
                                          rings: rings,
                                          srid: srid,
                                      })
            }
            WkbType::WkbMultipolygon => {
                let string_count = self.geometry_count();
                let strings = (0..string_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::Polygon(s) => s,
                             _ => panic!("Expected to get a Polygon"),
                         })
                    .collect();
                GeometryType::MultiPolygon(geom::MultiPolygon {
                                               polygons: strings,
                                               srid: srid,
                                           })
            }
            /* TODO:
            WkbType::WkbGeometrycollection => {
                let item_count = self.geometry_count();
                let geometry_list = (0..item_count)
                    .map(|n| unsafe { self._get_geometry(n) }.to_geo(srid))
                    .collect();
                GeometryType::GeometryCollection(geom::GeometryCollection {
                                                     geometries: geometry_list,
                                                 })
            }
            */
            _ => panic!("Unknown geometry type"),
        }
    }
}

fn new_transform(src_srid: i32, dest_srid: i32) -> Result<CoordTransform, gdal::errors::Error> {
    let sref_in = SpatialRef::from_epsg(src_srid as u32)?;
    let sref_out = SpatialRef::from_epsg(dest_srid as u32)?;
    CoordTransform::new(&sref_in, &sref_out)
}

/// Projected extent
fn transform_extent(extent: &Extent,
                    src_srid: i32,
                    dest_srid: i32)
                    -> Result<Extent, gdal::errors::Error> {
    let transform = new_transform(src_srid, dest_srid)?;
    let xs = &mut [extent.minx, extent.maxx];
    let ys = &mut [extent.miny, extent.maxy];
    transform.transform_coords(xs, ys, &mut [0.0, 0.0])?;
    Ok(Extent {
           minx: *xs.get(0).unwrap(),
           miny: *ys.get(0).unwrap(),
           maxx: *xs.get(1).unwrap(),
           maxy: *ys.get(1).unwrap(),
       })
}

pub fn ogr_layer_name(path: &str, id: isize) -> Result<String, gdal::errors::Error> {
    let mut dataset = Dataset::open(Path::new(path))?;
    let layer = dataset.layer(id)?;
    Ok(layer.name())
}

struct VectorFeature<'a> {
    layer: &'a Layer,
    fields_defn: &'a Vec<gdal::vector::Field<'a>>,
    grid_srid: i32,
    transform: Option<&'a CoordTransform>,
    feature: &'a gdal::vector::Feature<'a>,
}

impl<'a> Feature for VectorFeature<'a> {
    fn fid(&self) -> Option<u64> {
        self.layer
            .fid_field
            .as_ref()
            .and_then(|fid| {
                          let field_value = self.feature.field(&fid);
                          match field_value {
                              Ok(FieldValue::IntegerValue(v)) => Some(v as u64),
                              _ => None,
                          }
                      })
    }
    fn attributes(&self) -> Vec<FeatureAttr> {
        let mut attrs = Vec::new();
        for (_i, field) in self.fields_defn.into_iter().enumerate() {
            let field_value = self.feature.field(&field.name()); //TODO: get by index
            let val = match field_value {
                Ok(FieldValue::StringValue(v)) => Some(FeatureAttrValType::String(v)),
                Ok(FieldValue::IntegerValue(v)) => Some(FeatureAttrValType::Int(v as i64)),
                Ok(FieldValue::RealValue(v)) => Some(FeatureAttrValType::Double(v)),
                Err(err) => {
                    warn!("Layer '{}' - skipping field '{}': {}",
                          self.layer.name,
                          field.name(),
                          err);
                    None
                }
            };
            // match field.field_type {
            //    OGRFieldType::OFTString => {
            if let Some(val) = val {
                let fattr = FeatureAttr {
                    key: field.name(),
                    value: val,
                };
                attrs.push(fattr);
            };
        }
        attrs
    }
    fn geometry(&self) -> Result<GeometryType, String> {
        let ogrgeom = if let Some(ref field) = self.layer.geometry_field {
            self.feature.geometry_by_name(field).unwrap()
        } else {
            self.feature.geometry()
        };
        if let Some(ref transform) = self.transform {
            ogrgeom.transform_inplace(transform).unwrap();
        };
        Ok(ogrgeom.to_geo(Some(self.grid_srid)))
    }
}

impl DatasourceInput for GdalDatasource {
    /// New instance with connected pool
    fn connected(&self) -> GdalDatasource {
        GdalDatasource { path: self.path.clone() }
    }
    fn detect_layers(&self, _detect_geometry_types: bool) -> Vec<Layer> {
        let mut layers: Vec<Layer> = Vec::new();
        let mut dataset = Dataset::open(Path::new(&self.path)).unwrap();
        for idx in 0..dataset.count() {
            let gdal_layer = dataset.layer(idx).unwrap();
            let name = gdal_layer.name();
            for (n, field) in gdal_layer.defn().geom_fields().enumerate() {
                let mut layer = Layer::new(&name);
                layer.table_name = if n == 0 {
                    Some(name.clone())
                } else {
                    Some(format!("{}_{}", &name, n))
                };
                layer.geometry_field = Some(field.name());
                //layer.geometry_type = Some("POINT".to_string()); //TODO
                let srs = field.spatial_ref().unwrap();
                if let Ok(epsg) = srs.auth_code() {
                    layer.srid = Some(epsg)
                }
                layers.push(layer)
            }
        }
        layers
    }
    /// Return column field names and Rust compatible type conversion - without geometry column
    fn detect_data_columns(&self, _layer: &Layer, _sql: Option<&String>) -> Vec<(String, String)> {
        Vec::new() //TODO
    }
    /// Projected extent
    fn extent_from_wgs84(&self, extent: &Extent, dest_srid: i32) -> Option<Extent> {
        transform_extent(extent, 4326, dest_srid).ok()
    }
    fn layer_extent(&self, _layer: &Layer) -> Option<Extent> {
        None // TODO
    }
    fn prepare_queries(&mut self, layer: &Layer, grid_srid: i32) {
        // TODO: Prepare gdal::vector::Layer, CoordTransform
        match layer.srid {
            None => {
                warn!("Layer '{}': Unknown SRS - assuming SRID {}",
                      layer.name,
                      grid_srid);
            }
            Some(srid) => {
                if srid != grid_srid {
                    info!("Layer '{}': Reprojecting geometry from SRID {} to {}",
                          layer.name,
                          srid,
                          grid_srid);
                }
            }
        }
    }
    fn retrieve_features<F>(&self,
                            layer: &Layer,
                            extent: &Extent,
                            zoom: u8,
                            grid: &Grid,
                            mut read: F)
        where F: FnMut(&Feature)
    {
        let mut dataset = Dataset::open(Path::new(&self.path)).unwrap();
        let layer_name = layer.table_name.as_ref().unwrap();
        debug!("retrieve_features layer: {}", layer_name);
        let ogr_layer = dataset.layer_by_name(layer_name).unwrap();

        let transform = match layer.srid {
            Some(srid) if srid != grid.srid => new_transform(srid, grid.srid).ok(),
            _ => None,
        };

        let mut bbox_extent = if let Some(pixels) = layer.buffer_size {
            let pixel_width = grid.pixel_width(zoom);
            let buf = f64::from(pixels) * pixel_width;
            Extent {
                minx: extent.minx - buf,
                miny: extent.miny - buf,
                maxx: extent.maxx + buf,
                maxy: extent.maxy + buf,
            }
        } else {
            extent.clone()
        };

        // Spatial filter must be in layer SRS
        let layer_srid = layer.srid.unwrap_or(grid.srid);
        if layer_srid != grid.srid {
            bbox_extent = transform_extent(&bbox_extent, grid.srid, layer_srid).unwrap()
        };
        let bbox = Geometry::bbox(bbox_extent.minx,
                                  bbox_extent.miny,
                                  bbox_extent.maxx,
                                  bbox_extent.maxy)
                .unwrap();
        ogr_layer.set_spatial_filter(&bbox);

        let fields_defn = ogr_layer.defn().fields().collect::<Vec<_>>();
        let mut cnt = 0;
        let query_limit = layer.query_limit.unwrap_or(0);
        for feature in ogr_layer.features() {
            let feat = VectorFeature {
                layer: layer,
                fields_defn: &fields_defn,
                grid_srid: grid.srid,
                transform: transform.as_ref(),
                feature: &feature,
            };
            read(&feat);
            cnt += 1;
            if cnt == query_limit {
                info!("Feature count limited (query_limit={})", cnt);
                break;
            }
        }
        debug!("Feature count: {}", cnt);
    }
}

impl<'a> Config<'a, DatasourceCfg> for GdalDatasource {
    fn from_config(ds_cfg: &DatasourceCfg) -> Result<Self, String> {
        Ok(GdalDatasource::new(ds_cfg.path.as_ref().unwrap()))
    }

    fn gen_config() -> String {
        let toml = r#"
[[datasource]]
name = "ds"
# Dataset specification (http://gdal.org/ogr_formats.html)
path = "<filename-or-connection-spec>"
"#;
        toml.to_string()
    }
    fn gen_runtime_config(&self) -> String {
        format!(r#"
[[datasource]]
path = "{}"
"#,
                self.path)
    }
}
<commit_msg>Fix panic when bounding box cannot be reprojected<commit_after>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use datasource::DatasourceInput;
use gdal;
use gdal::vector::{Dataset, Geometry, WkbType, FieldValue};
use gdal::spatial_ref::{SpatialRef, CoordTransform};
use core::feature::{Feature, FeatureAttr, FeatureAttrValType};
use core::geom::{self, GeometryType};
use core::grid::Extent;
use core::grid::Grid;
use core::layer::Layer;
use core::Config;
use core::config::DatasourceCfg;
use std::path::Path;

pub struct GdalDatasource {
    pub path: String,
    // We don't store the Dataset, because we need mut access for getting layers
}

impl GdalDatasource {
    pub fn new(path: &str) -> GdalDatasource {
        GdalDatasource { path: path.to_string() }
    }
}

trait ToGeo {
    fn to_geo(&self, srid: Option<i32>) -> GeometryType;
}

impl ToGeo for Geometry {
    /// Convert OGR geomtry to t-rex EWKB geometry type (XY only)
    fn to_geo(&self, srid: Option<i32>) -> GeometryType {
        let geometry_type = self.geometry_type();

        let ring = |n: usize| {
            let ring = unsafe { self._get_geometry(n) };
            return match ring.to_geo(srid) {
                       GeometryType::LineString(r) => r,
                       _ => panic!("Expected to get a LineString"),
                   };
        };

        match geometry_type {
            WkbType::WkbPoint => {
                let (x, y, _) = self.get_point(0);
                GeometryType::Point(geom::Point {
                                        x: x,
                                        y: y,
                                        srid: srid,
                                    })
            }
            WkbType::WkbMultipoint => {
                let point_count = self.geometry_count();
                let coords = (0..point_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::Point(p) => p,
                             _ => panic!("Expected to get a Point"),
                         })
                    .collect();
                GeometryType::MultiPoint(geom::MultiPoint {
                                             points: coords,
                                             srid: srid,
                                         })
            }
            WkbType::WkbLinestring => {
                let coords = self.get_point_vec()
                    .iter()
                    .map(|&(x, y, _)| {
                             geom::Point {
                                 x: x,
                                 y: y,
                                 srid: srid,
                             }
                         })
                    .collect();
                GeometryType::LineString(geom::LineString {
                                             points: coords,
                                             srid: srid,
                                         })
            }
            WkbType::WkbMultilinestring => {
                let string_count = self.geometry_count();
                let strings = (0..string_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::LineString(s) => s,
                             _ => panic!("Expected to get a LineString"),
                         })
                    .collect();
                GeometryType::MultiLineString(geom::MultiLineString {
                                                  lines: strings,
                                                  srid: srid,
                                              })
            }
            WkbType::WkbPolygon => {
                let ring_count = self.geometry_count();
                let rings = (0..ring_count).map(|n| ring(n)).collect();
                GeometryType::Polygon(geom::Polygon {
                                          rings: rings,
                                          srid: srid,
                                      })
            }
            WkbType::WkbMultipolygon => {
                let string_count = self.geometry_count();
                let strings = (0..string_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::Polygon(s) => s,
                             _ => panic!("Expected to get a Polygon"),
                         })
                    .collect();
                GeometryType::MultiPolygon(geom::MultiPolygon {
                                               polygons: strings,
                                               srid: srid,
                                           })
            }
            /* TODO:
            WkbType::WkbGeometrycollection => {
                let item_count = self.geometry_count();
                let geometry_list = (0..item_count)
                    .map(|n| unsafe { self._get_geometry(n) }.to_geo(srid))
                    .collect();
                GeometryType::GeometryCollection(geom::GeometryCollection {
                                                     geometries: geometry_list,
                                                 })
            }
            */
            _ => panic!("Unknown geometry type"),
        }
    }
}

fn new_transform(src_srid: i32, dest_srid: i32) -> Result<CoordTransform, gdal::errors::Error> {
    let sref_in = SpatialRef::from_epsg(src_srid as u32)?;
    let sref_out = SpatialRef::from_epsg(dest_srid as u32)?;
    CoordTransform::new(&sref_in, &sref_out)
}

/// Projected extent
fn transform_extent(extent: &Extent,
                    src_srid: i32,
                    dest_srid: i32)
                    -> Result<Extent, gdal::errors::Error> {
    let transform = new_transform(src_srid, dest_srid)?;
    let xs = &mut [extent.minx, extent.maxx];
    let ys = &mut [extent.miny, extent.maxy];
    transform.transform_coords(xs, ys, &mut [0.0, 0.0])?;
    Ok(Extent {
           minx: *xs.get(0).unwrap(),
           miny: *ys.get(0).unwrap(),
           maxx: *xs.get(1).unwrap(),
           maxy: *ys.get(1).unwrap(),
       })
}

pub fn ogr_layer_name(path: &str, id: isize) -> Result<String, gdal::errors::Error> {
    let mut dataset = Dataset::open(Path::new(path))?;
    let layer = dataset.layer(id)?;
    Ok(layer.name())
}

struct VectorFeature<'a> {
    layer: &'a Layer,
    fields_defn: &'a Vec<gdal::vector::Field<'a>>,
    grid_srid: i32,
    transform: Option<&'a CoordTransform>,
    feature: &'a gdal::vector::Feature<'a>,
}

impl<'a> Feature for VectorFeature<'a> {
    fn fid(&self) -> Option<u64> {
        self.layer
            .fid_field
            .as_ref()
            .and_then(|fid| {
                          let field_value = self.feature.field(&fid);
                          match field_value {
                              Ok(FieldValue::IntegerValue(v)) => Some(v as u64),
                              _ => None,
                          }
                      })
    }
    fn attributes(&self) -> Vec<FeatureAttr> {
        let mut attrs = Vec::new();
        for (_i, field) in self.fields_defn.into_iter().enumerate() {
            let field_value = self.feature.field(&field.name()); //TODO: get by index
            let val = match field_value {
                Ok(FieldValue::StringValue(v)) => Some(FeatureAttrValType::String(v)),
                Ok(FieldValue::IntegerValue(v)) => Some(FeatureAttrValType::Int(v as i64)),
                Ok(FieldValue::RealValue(v)) => Some(FeatureAttrValType::Double(v)),
                Err(err) => {
                    warn!("Layer '{}' - skipping field '{}': {}",
                          self.layer.name,
                          field.name(),
                          err);
                    None
                }
            };
            // match field.field_type {
            //    OGRFieldType::OFTString => {
            if let Some(val) = val {
                let fattr = FeatureAttr {
                    key: field.name(),
                    value: val,
                };
                attrs.push(fattr);
            };
        }
        attrs
    }
    fn geometry(&self) -> Result<GeometryType, String> {
        let ogrgeom = if let Some(ref field) = self.layer.geometry_field {
            self.feature.geometry_by_name(field).unwrap()
        } else {
            self.feature.geometry()
        };
        if let Some(ref transform) = self.transform {
            ogrgeom.transform_inplace(transform).unwrap();
        };
        Ok(ogrgeom.to_geo(Some(self.grid_srid)))
    }
}

impl DatasourceInput for GdalDatasource {
    /// New instance with connected pool
    fn connected(&self) -> GdalDatasource {
        GdalDatasource { path: self.path.clone() }
    }
    fn detect_layers(&self, _detect_geometry_types: bool) -> Vec<Layer> {
        let mut layers: Vec<Layer> = Vec::new();
        let mut dataset = Dataset::open(Path::new(&self.path)).unwrap();
        for idx in 0..dataset.count() {
            let gdal_layer = dataset.layer(idx).unwrap();
            let name = gdal_layer.name();
            for (n, field) in gdal_layer.defn().geom_fields().enumerate() {
                let mut layer = Layer::new(&name);
                layer.table_name = if n == 0 {
                    Some(name.clone())
                } else {
                    Some(format!("{}_{}", &name, n))
                };
                layer.geometry_field = Some(field.name());
                //layer.geometry_type = Some("POINT".to_string()); //TODO
                let srs = field.spatial_ref().unwrap();
                if let Ok(epsg) = srs.auth_code() {
                    layer.srid = Some(epsg)
                }
                layers.push(layer)
            }
        }
        layers
    }
    /// Return column field names and Rust compatible type conversion - without geometry column
    fn detect_data_columns(&self, _layer: &Layer, _sql: Option<&String>) -> Vec<(String, String)> {
        Vec::new() //TODO
    }
    /// Projected extent
    fn extent_from_wgs84(&self, extent: &Extent, dest_srid: i32) -> Option<Extent> {
        transform_extent(extent, 4326, dest_srid).ok()
    }
    fn layer_extent(&self, _layer: &Layer) -> Option<Extent> {
        None // TODO
    }
    fn prepare_queries(&mut self, layer: &Layer, grid_srid: i32) {
        // TODO: Prepare gdal::vector::Layer, CoordTransform
        match layer.srid {
            None => {
                warn!("Layer '{}': Unknown SRS - assuming SRID {}",
                      layer.name,
                      grid_srid);
            }
            Some(srid) => {
                if srid != grid_srid {
                    info!("Layer '{}': Reprojecting geometry from SRID {} to {}",
                          layer.name,
                          srid,
                          grid_srid);
                }
            }
        }
    }
    fn retrieve_features<F>(&self,
                            layer: &Layer,
                            extent: &Extent,
                            zoom: u8,
                            grid: &Grid,
                            mut read: F)
        where F: FnMut(&Feature)
    {
        let mut dataset = Dataset::open(Path::new(&self.path)).unwrap();
        let layer_name = layer.table_name.as_ref().unwrap();
        debug!("retrieve_features layer: {}", layer_name);
        let ogr_layer = dataset.layer_by_name(layer_name).unwrap();

        let transform = match layer.srid {
            Some(srid) if srid != grid.srid => new_transform(srid, grid.srid).ok(),
            _ => None,
        };

        let mut bbox_extent = if let Some(pixels) = layer.buffer_size {
            let pixel_width = grid.pixel_width(zoom);
            let buf = f64::from(pixels) * pixel_width;
            Extent {
                minx: extent.minx - buf,
                miny: extent.miny - buf,
                maxx: extent.maxx + buf,
                maxy: extent.maxy + buf,
            }
        } else {
            extent.clone()
        };

        // Spatial filter must be in layer SRS
        let layer_srid = layer.srid.unwrap_or(grid.srid);
        if layer_srid != grid.srid {
            match transform_extent(&bbox_extent, grid.srid, layer_srid) {
                Ok(extent) => bbox_extent = extent,
                Err(e) => {
                    error!("Unable to transform {:?}: {}", bbox_extent, e);
                    return;
                }
            }
        };
        let bbox = Geometry::bbox(bbox_extent.minx,
                                  bbox_extent.miny,
                                  bbox_extent.maxx,
                                  bbox_extent.maxy)
                .unwrap();
        ogr_layer.set_spatial_filter(&bbox);

        let fields_defn = ogr_layer.defn().fields().collect::<Vec<_>>();
        let mut cnt = 0;
        let query_limit = layer.query_limit.unwrap_or(0);
        for feature in ogr_layer.features() {
            let feat = VectorFeature {
                layer: layer,
                fields_defn: &fields_defn,
                grid_srid: grid.srid,
                transform: transform.as_ref(),
                feature: &feature,
            };
            read(&feat);
            cnt += 1;
            if cnt == query_limit {
                info!("Feature count limited (query_limit={})", cnt);
                break;
            }
        }
        debug!("Feature count: {}", cnt);
    }
}

impl<'a> Config<'a, DatasourceCfg> for GdalDatasource {
    fn from_config(ds_cfg: &DatasourceCfg) -> Result<Self, String> {
        Ok(GdalDatasource::new(ds_cfg.path.as_ref().unwrap()))
    }

    fn gen_config() -> String {
        let toml = r#"
[[datasource]]
name = "ds"
# Dataset specification (http://gdal.org/ogr_formats.html)
path = "<filename-or-connection-spec>"
"#;
        toml.to_string()
    }
    fn gen_runtime_config(&self) -> String {
        format!(r#"
[[datasource]]
path = "{}"
"#,
                self.path)
    }
}
<|endoftext|>


<commit_before>use std::gc::{GC, Gc};
use syntax::ast;
use syntax::ext::base;
use syntax::codemap;
use syntax::parse;
use syntax::parse::attr::ParserAttr;

pub fn expand_hidden(cx: &mut base::ExtCtxt, _: codemap::Span,
                     _: Gc<ast::MetaItem>, input_item: Gc<ast::Item>)
    -> Gc<ast::Item>
{
    let dummy_cfg = "#[cfg(_a_cfg_that_you_should_never_pass_to_rustc_because_it_breaks_things_)]";
    let mut dummy_attr_generator = parse::new_parser_from_source_str(cx.parse_sess(), cx.cfg(),
                                                                     "dummy".to_string(),
                                                                     dummy_cfg.to_string());
    let attrs = dummy_attr_generator.parse_outer_attributes();

    let mut new_input_item = input_item.deref().clone();
    new_input_item.attrs.push_all_move(attrs);

    box(GC) new_input_item
}

pub fn expand_id(_: &mut base::ExtCtxt, _: codemap::Span,
                 _: Gc<ast::MetaItem>, input_item: Gc<ast::Item>)
                 -> Gc<ast::Item>
{
    input_item
}
<commit_msg>Use the correct filename of the method selectors.<commit_after>use std::gc::{GC, Gc};
use syntax::ast;
use syntax::ext::base;
use syntax::codemap;
use syntax::parse;
use syntax::parse::attr::ParserAttr;

pub fn expand_hidden(cx: &mut base::ExtCtxt, span: codemap::Span,
                     _: Gc<ast::MetaItem>, input_item: Gc<ast::Item>)
    -> Gc<ast::Item>
{
    let filename = cx.parse_sess.span_diagnostic.cm.span_to_filename(span);
    let dummy_cfg = "#[cfg(_a_cfg_that_you_should_never_pass_to_rustc_because_it_breaks_things_)]";
    let mut dummy_attr_generator = parse::new_parser_from_source_str(cx.parse_sess(), cx.cfg(),
                                                                     filename,
                                                                     dummy_cfg.to_string());
    let attrs = dummy_attr_generator.parse_outer_attributes();

    let mut new_input_item = input_item.deref().clone();
    new_input_item.attrs.push_all_move(attrs);

    box(GC) new_input_item
}

pub fn expand_id(_: &mut base::ExtCtxt, _: codemap::Span,
                 _: Gc<ast::MetaItem>, input_item: Gc<ast::Item>)
                 -> Gc<ast::Item>
{
    input_item
}
<|endoftext|>


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

//! A syntax highlighting plugin based on syntect.

extern crate syntect;
#[macro_use]
extern crate xi_plugin_lib;

mod stackmap;

use xi_plugin_lib::state_cache::{self, PluginCtx};
use xi_plugin_lib::plugin_base::ScopeSpan;
use syntect::parsing::{ParseState, ScopeStack, SyntaxSet, SCOPE_REPO};
use stackmap::{StackMap, LookupResult};

struct PluginState<'a> {
    syntax_set: &'a SyntaxSet,
    stack_idents: StackMap,
    line_num: usize,
    offset: usize,
    parse_state: Option<ParseState>,
    scope_state: ScopeStack,
    spans_start: usize,
    // unflushed spans
    spans: Vec<ScopeSpan>,
    new_scopes: Vec<Vec<String>>,
    syntax_name: String,
}

impl<'a> PluginState<'a> {
    pub fn new(syntax_set: &'a SyntaxSet) -> Self {
        PluginState {
            syntax_set: syntax_set,
            stack_idents: StackMap::default(),
            line_num: 0,
            offset: 0,
            parse_state: None,
            scope_state: ScopeStack::new(),
            spans_start: 0,
            spans: Vec::new(),
            new_scopes: Vec::new(),
            syntax_name: String::from("None"),
        }
    }

    // Return true if there's more to do.
    fn highlight_one_line(&mut self, ctx: &mut PluginCtx<State>) -> bool {
        let line = ctx.get_line(self.line_num);
        if let Err(err) = line {
            print_err!("Error: {:?}", err);
            return false;
        }
        let line = line.unwrap();
        if line.is_empty() {
            return false;
        }
        let ops = self.parse_state.as_mut().unwrap().parse_line(&line);

        let mut prev_cursor = 0;
        let repo = SCOPE_REPO.lock().unwrap();
        for (cursor, batch) in ops {
            if self.scope_state.len() > 0 {
                let scope_ident = self.stack_idents.get_value(self.scope_state.as_slice());
                let scope_ident = match scope_ident {
                    LookupResult::Existing(id) => id,
                    LookupResult::New(id) => {
                        let stack_strings = self.scope_state.as_slice().iter()
                            .map(|slice| repo.to_string(*slice))
                            .collect::<Vec<_>>();
                        self.new_scopes.push(stack_strings);
                        id
                    }
                };

                let start = self.offset - self.spans_start + prev_cursor;
                let end = start + (cursor - prev_cursor);
                let span = ScopeSpan::new(start, end, scope_ident);
                self.spans.push(span);
            }
            prev_cursor = cursor;
            self.scope_state.apply(&batch);
        }

        self.line_num += 1;
        self.offset += line.len();
        true
    }

    fn flush_spans(&mut self, ctx: &mut PluginCtx<State>) {
        if !self.new_scopes.is_empty() {
            ctx.add_scopes(&self.new_scopes);
            self.new_scopes.clear();
        }
        if !self.spans.is_empty() {
            ctx.update_spans(self.spans_start, self.offset - self.spans_start,
                             self.spans.as_slice());
            self.spans.clear();
        }
        self.spans_start = self.offset;
    }

    fn do_highlighting(&mut self, mut ctx: PluginCtx<State>) {
        let syntax = match ctx.get_path() {
            Some(ref path) => self.syntax_set.find_syntax_for_file(path).unwrap()
                .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text()),
            None => self.syntax_set.find_syntax_plain_text(),
        };

        if syntax.name != self.syntax_name {
            self.syntax_name = syntax.name.clone();
            print_err!("syntect using {}", syntax.name);
        }

        self.parse_state = Some(ParseState::new(syntax));
        self.scope_state = ScopeStack::new();
        self.spans = Vec::new();
        self.new_scopes = Vec::new();
        self.line_num = 0;
        self.offset = 0;
        self.spans_start = 0;
        ctx.schedule_idle(0);
    }
}

const LINES_PER_RPC: usize = 50;

type State = usize;

impl<'a> state_cache::Handler for PluginState<'a> {
    type State = State;

    fn initialize(&mut self, ctx: PluginCtx<State>, _buf_size: usize) {
        self.do_highlighting(ctx);
    }

    fn update(&mut self, ctx: PluginCtx<State>) {
        self.do_highlighting(ctx);
    }

    fn did_save(&mut self, ctx: PluginCtx<State>) {
        self.do_highlighting(ctx);
    }

    fn idle(&mut self, mut ctx: PluginCtx<State>, _token: usize) {
        //print_err!("idle task at line {}", self.line_num);
        for _ in 0..LINES_PER_RPC {
            if !self.highlight_one_line(&mut ctx) {
                self.flush_spans(&mut ctx);
                return;
            }
            if ctx.request_is_pending() {
                print_err!("request pending at line {}", self.line_num);
                break;
            }
        }
        self.flush_spans(&mut ctx);
        ctx.schedule_idle(0);
    }
}

fn main() {
    let syntax_set = SyntaxSet::load_defaults_newlines();
    let mut state = PluginState::new(&syntax_set);

    state_cache::mainloop(&mut state);
}
<commit_msg>Store syntect parse state in state cache<commit_after>// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A syntax highlighting plugin based on syntect.

extern crate syntect;
#[macro_use]
extern crate xi_plugin_lib;

mod stackmap;

use xi_plugin_lib::state_cache::{self, PluginCtx};
use xi_plugin_lib::plugin_base::ScopeSpan;
use syntect::parsing::{ParseState, ScopeStack, SyntaxSet, SCOPE_REPO};
use stackmap::{StackMap, LookupResult};

struct PluginState<'a> {
    syntax_set: &'a SyntaxSet,
    stack_idents: StackMap,
    line_num: usize,
    offset: usize,
    initial_state: Option<ParseState>,
    parse_state: Option<ParseState>,
    scope_state: ScopeStack,
    spans_start: usize,
    // unflushed spans
    spans: Vec<ScopeSpan>,
    new_scopes: Vec<Vec<String>>,
    syntax_name: String,
}

impl<'a> PluginState<'a> {
    pub fn new(syntax_set: &'a SyntaxSet) -> Self {
        PluginState {
            syntax_set: syntax_set,
            stack_idents: StackMap::default(),
            line_num: 0,
            offset: 0,
            initial_state: None,
            parse_state: None,
            scope_state: ScopeStack::new(),
            spans_start: 0,
            spans: Vec::new(),
            new_scopes: Vec::new(),
            syntax_name: String::from("None"),
        }
    }

    // compute syntax for one line, also accumulating the style spans
    fn compute_syntax(&mut self, line: &str, state: State) -> State {
        let mut parse_state = state.or_else(|| self.initial_state.clone()).unwrap();
        let ops = parse_state.parse_line(&line);

        let mut prev_cursor = 0;
        let repo = SCOPE_REPO.lock().unwrap();
        for (cursor, batch) in ops {
            if self.scope_state.len() > 0 {
                let scope_ident = self.stack_idents.get_value(self.scope_state.as_slice());
                let scope_ident = match scope_ident {
                    LookupResult::Existing(id) => id,
                    LookupResult::New(id) => {
                        let stack_strings = self.scope_state.as_slice().iter()
                            .map(|slice| repo.to_string(*slice))
                            .collect::<Vec<_>>();
                        self.new_scopes.push(stack_strings);
                        id
                    }
                };

                let start = self.offset - self.spans_start + prev_cursor;
                let end = start + (cursor - prev_cursor);
                let span = ScopeSpan::new(start, end, scope_ident);
                self.spans.push(span);
            }
            prev_cursor = cursor;
            self.scope_state.apply(&batch);
        }
        Some(parse_state)
    }

    #[allow(unused)]
    // Return true if there's any more work to be done.
    fn highlight_one_line(&mut self, ctx: &mut PluginCtx<State>) -> bool {
        if let Some(line_num) = ctx.get_frontier() {
            let (line_num, offset, state) = ctx.get_prev(line_num);
            if offset != self.offset {
                self.flush_spans(ctx);
                self.offset = offset;
                self.spans_start = offset;
            }
            let new_frontier = match ctx.get_line(line_num) {
                Ok("") => None,
                Ok(s) => {
                    let new_state = self.compute_syntax(s, state);
                    self.offset += s.len();
                    Some((new_state, line_num + 1))
                }
                Err(_) => None,
            };
            if let Some((new_state, new_frontier)) = new_frontier {
                ctx.set(new_frontier, new_state);
                ctx.update_frontier(new_frontier);
                return true;
            } else {
                ctx.close_frontier();
            }
        }
        false
    }

    fn flush_spans(&mut self, ctx: &mut PluginCtx<State>) {
        if !self.new_scopes.is_empty() {
            ctx.add_scopes(&self.new_scopes);
            self.new_scopes.clear();
        }
        if !self.spans.is_empty() {
            ctx.update_spans(self.spans_start, self.offset - self.spans_start,
                             self.spans.as_slice());
            self.spans.clear();
        }
        self.spans_start = self.offset;
    }

    fn do_highlighting(&mut self, mut ctx: PluginCtx<State>) {
        let syntax = match ctx.get_path() {
            Some(ref path) => self.syntax_set.find_syntax_for_file(path).unwrap()
                .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text()),
            None => self.syntax_set.find_syntax_plain_text(),
        };

        if syntax.name != self.syntax_name {
            self.syntax_name = syntax.name.clone();
            print_err!("syntect using {}", syntax.name);
        }

        self.initial_state = Some(ParseState::new(syntax));
        self.parse_state = self.initial_state.clone();
        self.scope_state = ScopeStack::new();
        self.spans = Vec::new();
        self.new_scopes = Vec::new();
        self.line_num = 0;
        self.offset = 0;
        self.spans_start = 0;
        ctx.schedule_idle(0);
    }
}

const LINES_PER_RPC: usize = 50;

// TODO: this needs to be option because the caching layer relies on Default.
// We can't implement that because the actual initial state depends on the
// syntax. There are other ways to handle this, but this will do for now.
type State = Option<ParseState>;

impl<'a> state_cache::Handler for PluginState<'a> {
    type State = State;

    fn initialize(&mut self, ctx: PluginCtx<State>, _buf_size: usize) {
        self.do_highlighting(ctx);
    }

    fn update(&mut self, ctx: PluginCtx<State>) {
        self.do_highlighting(ctx);
    }

    fn did_save(&mut self, ctx: PluginCtx<State>) {
        self.do_highlighting(ctx);
    }

    fn idle(&mut self, mut ctx: PluginCtx<State>, _token: usize) {
        //print_err!("idle task at line {}", self.line_num);
        for _ in 0..LINES_PER_RPC {
            if !self.highlight_one_line(&mut ctx) {
                self.flush_spans(&mut ctx);
                return;
            }
            if ctx.request_is_pending() {
                print_err!("request pending at line {}", self.line_num);
                break;
            }
        }
        self.flush_spans(&mut ctx);
        ctx.schedule_idle(0);
    }
}

fn main() {
    let syntax_set = SyntaxSet::load_defaults_newlines();
    let mut state = PluginState::new(&syntax_set);

    state_cache::mainloop(&mut state);
}
<|endoftext|>


<commit_before>use mio::*;
use std::cell::RefCell;
use std::fmt::Debug;
use std::io;
use std::rc::Rc;
use std::time::Duration;
use slab::Slab;

pub trait EventHandler {
    fn on_ready(&self, selector: &mut Selector, event: Event);
}

impl<F> EventHandler for F where F: Fn(&mut Selector, Event) {
    fn on_ready(&self, selector: &mut Selector, event: Event) {
        self(selector, event);
    }
}

// for convenience
impl EventHandler for Rc<RefCell<EventHandler>> {
    fn on_ready(&self, selector: &mut Selector, event: Event) {
        self.borrow().on_ready(selector, event);
    }
}

pub struct Selector {
    poll: Poll,
    handlers: Slab<Box<EventHandler>, Token>,
}

impl Selector {
    pub fn new() -> io::Result<Self> {
        Ok(Self {
            poll: Poll::new()?,
            handlers: Slab::with_capacity(1024),
        })
    }

    pub fn register<E>(&mut self, handle: &E, handler: Box<EventHandler>,
                   interest: Ready, opts: PollOpt) -> io::Result<Token>
            where E: Evented + ?Sized {
        let token = self.handlers.insert(handler)
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, "Cannot allocate slab slot"))?;
        self.poll.register(handle, token, interest, opts)?;
        Ok(token)
    }

    pub fn reregister<E>(&self, handle: &E, token: Token,
                   interest: Ready, opts: PollOpt) -> io::Result<()>
            where E: Evented + ?Sized {
        self.poll.reregister(handle, token, interest, opts)
    }

    pub fn deregister<E>(&mut self, handle: &E, token: Token) -> io::Result<()>
            where E: Evented + ?Sized {
        self.handlers.remove(token).expect("Unknown token removed");
        self.poll.deregister(handle)
    }

    pub fn poll(&mut self, events: &mut Events, timeout: Option<Duration>) -> io::Result<usize> {
        self.poll.poll(events, timeout)
    }

    pub fn run_handler(&mut self, event: Event) {
        let mut handler = self.handlers.remove(event.token()).expect("Token not found");
        handler.on_ready(self, event);
        if let Err(_) = self.handlers.insert(handler) {
            panic!("Cannot allocate slab slot");
        }
    }
}
<commit_msg>EventHandler as mutable<commit_after>use mio::*;
use std::cell::RefCell;
use std::fmt::Debug;
use std::io;
use std::rc::Rc;
use std::time::Duration;
use slab::Slab;

pub trait EventHandler {
    fn on_ready(&mut self, selector: &mut Selector, event: Event);
}

impl<F> EventHandler for F where F: FnMut(&mut Selector, Event) {
    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        self(selector, event);
    }
}

// for convenience
impl EventHandler for Rc<RefCell<EventHandler>> {
    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        self.borrow_mut().on_ready(selector, event);
    }
}

pub struct Selector {
    poll: Poll,
    handlers: Slab<Box<EventHandler>, Token>,
}

impl Selector {
    pub fn new() -> io::Result<Self> {
        Ok(Self {
            poll: Poll::new()?,
            handlers: Slab::with_capacity(1024),
        })
    }

    pub fn register<E>(&mut self, handle: &E, handler: Box<EventHandler>,
                   interest: Ready, opts: PollOpt) -> io::Result<Token>
            where E: Evented + ?Sized {
        let token = self.handlers.insert(handler)
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, "Cannot allocate slab slot"))?;
        self.poll.register(handle, token, interest, opts)?;
        Ok(token)
    }

    pub fn reregister<E>(&self, handle: &E, token: Token,
                   interest: Ready, opts: PollOpt) -> io::Result<()>
            where E: Evented + ?Sized {
        self.poll.reregister(handle, token, interest, opts)
    }

    pub fn deregister<E>(&mut self, handle: &E, token: Token) -> io::Result<()>
            where E: Evented + ?Sized {
        self.handlers.remove(token).expect("Unknown token removed");
        self.poll.deregister(handle)
    }

    pub fn poll(&mut self, events: &mut Events, timeout: Option<Duration>) -> io::Result<usize> {
        self.poll.poll(events, timeout)
    }

    pub fn run_handler(&mut self, event: Event) {
        let mut handler = self.handlers.remove(event.token()).expect("Token not found");
        handler.on_ready(self, event);
        if let Err(_) = self.handlers.insert(handler) {
            panic!("Cannot allocate slab slot");
        }
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::result::Result as RResult;
use std::ops::Deref;

use toml::{Parser, Value};

/**
 * Errors which are related to configuration-file loading
 */
pub mod error {
    use std::error::Error;
    use std::fmt::{Display, Formatter};
    use std::fmt::Error as FmtError;

    /// The kind of an error
    #[derive(Clone, Debug, PartialEq)]
    pub enum ConfigErrorKind {
        NoConfigFileFound,
    }

    /// Configuration error type
    #[derive(Debug)]
    pub struct ConfigError {
        kind: ConfigErrorKind,
        cause: Option<Box<Error>>,
    }

    impl ConfigError {

        /// Instantiate a new `ConfigError`, optionally with cause
        pub fn new(kind: ConfigErrorKind, cause: Option<Box<Error>>) -> ConfigError {
            ConfigError {
                kind: kind,
                cause: cause,
            }
        }

        ///get the Kind of the Error
        pub fn err_type(&self) -> ConfigErrorKind {
            self.kind.clone()
        }

        /// Get the string, the `ConfigError` can be described with
        pub fn as_str(e: &ConfigError) -> &'static str {
            match e.err_type() {
                ConfigErrorKind::NoConfigFileFound   => "No config file found",
            }
        }

    }

    impl Display for ConfigError {

        fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
            try!(write!(fmt, "{}", ConfigError::as_str(self)));
            Ok(())
        }

    }

    impl Error for ConfigError {

        fn description(&self) -> &str {
            ConfigError::as_str(self)
        }

        fn cause(&self) -> Option<&Error> {
            self.cause.as_ref().map(|e| &**e)
        }

    }

}

use self::error::{ConfigError, ConfigErrorKind};

/**
 * Result type of this module. Either `T` or `ConfigError`
 */
pub type Result<T> = RResult<T, ConfigError>;

/// `Configuration` object
///
/// Holds all config variables which are globally available plus the configuration object from the
/// config parser, which can be accessed.
#[derive(Debug)]
pub struct Configuration {

    /// The plain configuration object for direct access if necessary
    config: Value,

    /// The verbosity the program should run with
    verbosity: bool,

    /// The editor which should be used
    editor: Option<String>,

    ///The options the editor should get when opening some file
    editor_opts: String,
}

impl Configuration {

    /// Get a new configuration object.
    ///
    /// The passed runtimepath is used for searching the configuration file, whereas several file
    /// names are tested. If that does not work, the home directory and the XDG basedir are tested
    /// with all variants.
    ///
    /// If that doesn't work either, an error is returned.
    pub fn new(rtp: &PathBuf) -> Result<Configuration> {
        fetch_config(&rtp).map(|cfg| {
            let verbosity   = get_verbosity(&cfg);
            let editor      = get_editor(&cfg);
            let editor_opts = get_editor_opts(&cfg);

            debug!("Building configuration");
            debug!("  - verbosity  : {:?}", verbosity);
            debug!("  - editor     : {:?}", editor);
            debug!("  - editor-opts: {}", editor_opts);

            Configuration {
                config: cfg,
                verbosity: verbosity,
                editor: editor,
                editor_opts: editor_opts,
            }
        })
    }

    pub fn editor(&self) -> Option<&String> {
        self.editor.as_ref()
    }

    #[allow(dead_code)] // Why do I actually need this annotation on a pub function?
    pub fn config(&self) -> &Value {
        &self.config
    }

    pub fn store_config(&self) -> Option<&Value> {
        match self.config {
            Value::Table(ref tabl) => tabl.get("store"),
            _ => None,
        }
    }

}

impl Deref for Configuration {
    type Target = Value;

    fn deref(&self) -> &Value {
        &self.config
    }

}

fn get_verbosity(v: &Value) -> bool {
    match *v {
        Value::Table(ref t) => t.get("verbose")
                .map_or(false, |v| match *v { Value::Boolean(b) => b, _ => false, }),
        _ => false,
    }
}

fn get_editor(v: &Value) -> Option<String> {
    match *v {
        Value::Table(ref t) => t.get("editor")
                .and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, }),
        _ => None,
    }
}

fn get_editor_opts(v: &Value) -> String {
    match *v {
        Value::Table(ref t) => t.get("editor-opts")
                .and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, })
                .unwrap_or_default(),
        _ => String::new(),
    }
}

/**
 * Helper to fetch the config file
 *
 * Tests several variants for the config file path and uses the first one which works.
 */
fn fetch_config(rtp: &PathBuf) -> Result<Value> {
    use std::env;
    use std::fs::File;
    use std::io::Read;
    use std::io::Write;
    use std::io::stderr;

    use xdg_basedir;
    use itertools::Itertools;

    use libimagutil::variants::generate_variants as gen_vars;

    let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
    let modifier = |base: &PathBuf, v: &'static str| {
        let mut base = base.clone();
        base.push(String::from(v));
        base
    };

    vec![
        gen_vars(rtp.clone(), variants.clone(), &modifier),

        env::var("HOME").map(|home| gen_vars(PathBuf::from(home), variants.clone(), &modifier))
                        .unwrap_or(vec![]),

        xdg_basedir::get_data_home().map(|data_dir| gen_vars(data_dir, variants.clone(), &modifier))
                                    .unwrap_or(vec![]),
    ].iter()
        .flatten()
        .filter(|path| path.exists() && path.is_file())
        .map(|path| {
            let content = {
                let mut s = String::new();
                let f = File::open(path);
                if f.is_err() {
                    return None
                }
                let mut f = f.unwrap();
                f.read_to_string(&mut s).ok();
                s
            };

            let mut parser = Parser::new(&content[..]);
            let res = parser.parse();

            if res.is_none() {
                write!(stderr(), "Config file parser error:").ok();
                for error in parser.errors {
                    write!(stderr(), "At [{}][{}] <> {}", error.lo, error.hi, error).ok();
                    write!(stderr(), "in: '{}'", &content[error.lo..error.hi]).ok();
                }
                None
            } else {
                res
            }
        })
        .filter(|loaded| loaded.is_some())
        .nth(0)
        .map(|inner| Value::Table(inner.unwrap()))
        .ok_or_else(|| ConfigError::new(ConfigErrorKind::NoConfigFileFound, None))
}

<commit_msg>Replace configuration error code with macro generator<commit_after>use std::path::PathBuf;
use std::result::Result as RResult;
use std::ops::Deref;

use toml::{Parser, Value};

generate_error_module!(
    generate_error_types!(ConfigError, ConfigErrorKind,
        NoConfigFileFound   => "No config file found"
    );
);

use self::error::{ConfigError, ConfigErrorKind};

/**
 * Result type of this module. Either `T` or `ConfigError`
 */
pub type Result<T> = RResult<T, ConfigError>;

/// `Configuration` object
///
/// Holds all config variables which are globally available plus the configuration object from the
/// config parser, which can be accessed.
#[derive(Debug)]
pub struct Configuration {

    /// The plain configuration object for direct access if necessary
    config: Value,

    /// The verbosity the program should run with
    verbosity: bool,

    /// The editor which should be used
    editor: Option<String>,

    ///The options the editor should get when opening some file
    editor_opts: String,
}

impl Configuration {

    /// Get a new configuration object.
    ///
    /// The passed runtimepath is used for searching the configuration file, whereas several file
    /// names are tested. If that does not work, the home directory and the XDG basedir are tested
    /// with all variants.
    ///
    /// If that doesn't work either, an error is returned.
    pub fn new(rtp: &PathBuf) -> Result<Configuration> {
        fetch_config(&rtp).map(|cfg| {
            let verbosity   = get_verbosity(&cfg);
            let editor      = get_editor(&cfg);
            let editor_opts = get_editor_opts(&cfg);

            debug!("Building configuration");
            debug!("  - verbosity  : {:?}", verbosity);
            debug!("  - editor     : {:?}", editor);
            debug!("  - editor-opts: {}", editor_opts);

            Configuration {
                config: cfg,
                verbosity: verbosity,
                editor: editor,
                editor_opts: editor_opts,
            }
        })
    }

    pub fn editor(&self) -> Option<&String> {
        self.editor.as_ref()
    }

    #[allow(dead_code)] // Why do I actually need this annotation on a pub function?
    pub fn config(&self) -> &Value {
        &self.config
    }

    pub fn store_config(&self) -> Option<&Value> {
        match self.config {
            Value::Table(ref tabl) => tabl.get("store"),
            _ => None,
        }
    }

}

impl Deref for Configuration {
    type Target = Value;

    fn deref(&self) -> &Value {
        &self.config
    }

}

fn get_verbosity(v: &Value) -> bool {
    match *v {
        Value::Table(ref t) => t.get("verbose")
                .map_or(false, |v| match *v { Value::Boolean(b) => b, _ => false, }),
        _ => false,
    }
}

fn get_editor(v: &Value) -> Option<String> {
    match *v {
        Value::Table(ref t) => t.get("editor")
                .and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, }),
        _ => None,
    }
}

fn get_editor_opts(v: &Value) -> String {
    match *v {
        Value::Table(ref t) => t.get("editor-opts")
                .and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, })
                .unwrap_or_default(),
        _ => String::new(),
    }
}

/**
 * Helper to fetch the config file
 *
 * Tests several variants for the config file path and uses the first one which works.
 */
fn fetch_config(rtp: &PathBuf) -> Result<Value> {
    use std::env;
    use std::fs::File;
    use std::io::Read;
    use std::io::Write;
    use std::io::stderr;

    use xdg_basedir;
    use itertools::Itertools;

    use libimagutil::variants::generate_variants as gen_vars;

    let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
    let modifier = |base: &PathBuf, v: &'static str| {
        let mut base = base.clone();
        base.push(String::from(v));
        base
    };

    vec![
        gen_vars(rtp.clone(), variants.clone(), &modifier),

        env::var("HOME").map(|home| gen_vars(PathBuf::from(home), variants.clone(), &modifier))
                        .unwrap_or(vec![]),

        xdg_basedir::get_data_home().map(|data_dir| gen_vars(data_dir, variants.clone(), &modifier))
                                    .unwrap_or(vec![]),
    ].iter()
        .flatten()
        .filter(|path| path.exists() && path.is_file())
        .map(|path| {
            let content = {
                let mut s = String::new();
                let f = File::open(path);
                if f.is_err() {
                    return None
                }
                let mut f = f.unwrap();
                f.read_to_string(&mut s).ok();
                s
            };

            let mut parser = Parser::new(&content[..]);
            let res = parser.parse();

            if res.is_none() {
                write!(stderr(), "Config file parser error:").ok();
                for error in parser.errors {
                    write!(stderr(), "At [{}][{}] <> {}", error.lo, error.hi, error).ok();
                    write!(stderr(), "in: '{}'", &content[error.lo..error.hi]).ok();
                }
                None
            } else {
                res
            }
        })
        .filter(|loaded| loaded.is_some())
        .nth(0)
        .map(|inner| Value::Table(inner.unwrap()))
        .ok_or_else(|| ConfigError::new(ConfigErrorKind::NoConfigFileFound, None))
}

<|endoftext|>


<commit_before>#![allow(unused_must_use)]

extern crate syntax;
extern crate rustc;
extern crate serialize;
extern crate getopts;

use getopts::{optflag,getopts};

use std::io;
use std::os;
use std::io::Reader;
use std::string::String;
use serialize::json;
use serialize::json::{Json, List, String, Object};
use syntax::diagnostics::registry;

use rustc::driver::{driver, session, config};

fn filter_json(j: &mut json::Json) {
    let mut replace = None;

    match *j {
        json::Object(ref mut ob) => {
            // remove
            ob.pop(&String::from_str("span"));
            ob.pop(&String::from_str("id"));
            let mut kv : Option<(String,Vec<Json>)> = None;
            match ob.find(&String::from_str("node")) {
                Some(&json::Object(ref ob2)) => {
                    match (ob2.find(&String::from_str("variant")),
                           ob2.find(&String::from_str("fields"))) {
                        (Some(&String(ref s)), Some(&List(ref ls))) => {
                            kv = Some((s.clone(), ls.clone()));
                        }
                        _ => ()
                    }
                }
                _ => ()
            }
            match kv {
                None => (),
                Some((k, v)) => {
                    ob.pop(&String::from_str("node"));
                    ob.insert(k, List(v));
                }
            }
            for (_, v) in ob.mut_iter() {
                filter_json(v);
            }
        }
        json::List(ref mut ls) => {
            for v in ls.mut_iter() {
                filter_json(v)
            }
            if ls.len() == 1 {
                replace = Some(ls.as_slice()[0].clone())
            }
        }
        _ => ()
    }
    match replace {
        None => (),
        Some(jj) => *j = jj
    }
}

static indent_step: int = 4;

fn print_indent(indent: int) {
    let mut out = io::stdout();
    for i in range(0, indent) {
        if i % indent_step == 0 {
            out.write_str("|");
        } else {
            out.write_str(" ");
        }
    }
}

fn print_sexp(indent: int, j: &json::Json) {
    let mut out = io::stdout();

    match *j {

        json::Object(ref ob) => {
            {
                for (k, v) in ob.iter() {
                    print_indent(indent);
                    out.write_str("(");
                    out.write_str(k.as_slice());
                    out.write_str("\n");
                    print_sexp(indent + indent_step, v);
                    print_indent(indent);
                    out.write_str(")\n");
                }
            }
        }
        json::List(ref ls) => {
            print_indent(indent);
            out.write_str("(\n");
            for v in ls.iter() {
                print_sexp(indent + indent_step, v);
            }
            print_indent(indent);
            out.write_str(")\n");
        }
        json::String(ref s) => {
            print_indent(indent);
            out.write_str(s.as_slice());
            out.write_str("\n");
        }
        json::Null => {
            print_indent(indent);
            out.write_str("<nil>\n");
        }
        json::Boolean(true) => {
            print_indent(indent);
            out.write_str("true\n");
        }
        json::Boolean(false) => {
            print_indent(indent);
            out.write_str("false\n");
        }
        json::Number(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
    }
}

fn main() {

    let args = os::args().move_iter().collect::<Vec<String>>();
    let opts = [ optflag("j", "", "dump output in JSON, not sexp") ];
    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f) }
    };
    let dump_json = matches.opt_present("j");

    match io::stdin().read_to_string() {
        Ok(text) => {
            let opt = config::basic_options();
            let sess = session::build_session(opt, None,
                                              registry::Registry::new(rustc::DIAGNOSTICS));
            let cfg = config::build_configuration(&sess);
            let input = driver::StrInput(text);
            let cr = driver::phase_1_parse_input(&sess, cfg, &input);

            // JSON-ify, meaning "encode then re-parse as just json", ugh.
            let ast_str = json::encode(&cr.module);
            let chars = ast_str.as_slice().chars().collect::<Vec<char>>();
            let mut b = json::Builder::new(chars.move_iter());
            let mut j = b.build().ok().unwrap();

            filter_json(&mut j);
            if dump_json {
                let mut writer = io::stdout();
                j.to_pretty_writer(&mut writer as &mut io::Writer);
            } else {
                print_sexp(0, &j);
            }
        },
        Err(ioerr) => {
            fail!("I/O Error: {}", ioerr.desc);
        }
    }
}
<commit_msg>Fix compile error with parse<commit_after>#![allow(unused_must_use)]

extern crate syntax;
extern crate rustc;
extern crate serialize;
extern crate getopts;

use getopts::{optflag,getopts};

use std::io;
use std::os;
use std::io::Reader;
use std::string::String;
use serialize::json;
use serialize::json::{Json, List, String, Object};
use syntax::diagnostics::registry;

use rustc::driver::{driver, session, config};

fn filter_json(j: &mut json::Json) {
    let mut replace = None;

    match *j {
        json::Object(ref mut ob) => {
            // remove
            ob.pop(&String::from_str("span"));
            ob.pop(&String::from_str("id"));
            let mut kv : Option<(String,Vec<Json>)> = None;
            match ob.find(&String::from_str("node")) {
                Some(&json::Object(ref ob2)) => {
                    match (ob2.find(&String::from_str("variant")),
                           ob2.find(&String::from_str("fields"))) {
                        (Some(&String(ref s)), Some(&List(ref ls))) => {
                            kv = Some((s.clone(), ls.clone()));
                        }
                        _ => ()
                    }
                }
                _ => ()
            }
            match kv {
                None => (),
                Some((k, v)) => {
                    ob.pop(&String::from_str("node"));
                    ob.insert(k, List(v));
                }
            }
            for (_, v) in ob.mut_iter() {
                filter_json(v);
            }
        }
        json::List(ref mut ls) => {
            for v in ls.mut_iter() {
                filter_json(v)
            }
            if ls.len() == 1 {
                replace = Some(ls.as_slice()[0].clone())
            }
        }
        _ => ()
    }
    match replace {
        None => (),
        Some(jj) => *j = jj
    }
}

static indent_step: int = 4;

fn print_indent(indent: int) {
    let mut out = io::stdout();
    for i in range(0, indent) {
        if i % indent_step == 0 {
            out.write_str("|");
        } else {
            out.write_str(" ");
        }
    }
}

fn print_sexp(indent: int, j: &json::Json) {
    let mut out = io::stdout();

    match *j {

        json::Object(ref ob) => {
            {
                for (k, v) in ob.iter() {
                    print_indent(indent);
                    out.write_str("(");
                    out.write_str(k.as_slice());
                    out.write_str("\n");
                    print_sexp(indent + indent_step, v);
                    print_indent(indent);
                    out.write_str(")\n");
                }
            }
        }
        json::List(ref ls) => {
            print_indent(indent);
            out.write_str("(\n");
            for v in ls.iter() {
                print_sexp(indent + indent_step, v);
            }
            print_indent(indent);
            out.write_str(")\n");
        }
        json::String(ref s) => {
            print_indent(indent);
            out.write_str(s.as_slice());
            out.write_str("\n");
        }
        json::Null => {
            print_indent(indent);
            out.write_str("<nil>\n");
        }
        json::Boolean(true) => {
            print_indent(indent);
            out.write_str("true\n");
        }
        json::Boolean(false) => {
            print_indent(indent);
            out.write_str("false\n");
        }
        json::I64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
        json::U64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
        json::F64(n) => {
            print_indent(indent);
            out.write_str(n.to_string().as_slice());
            out.write_str("\n");
        }
    }
}

fn main() {

    let args = os::args().move_iter().collect::<Vec<String>>();
    let opts = [ optflag("j", "", "dump output in JSON, not sexp") ];
    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f) }
    };
    let dump_json = matches.opt_present("j");

    match io::stdin().read_to_string() {
        Ok(text) => {
            let opt = config::basic_options();
            let sess = session::build_session(opt, None,
                                              registry::Registry::new(rustc::DIAGNOSTICS));
            let cfg = config::build_configuration(&sess);
            let input = driver::StrInput(text);
            let cr = driver::phase_1_parse_input(&sess, cfg, &input);

            // JSON-ify, meaning "encode then re-parse as just json", ugh.
            let ast_str = json::encode(&cr.module);
            let chars = ast_str.as_slice().chars().collect::<Vec<char>>();
            let mut b = json::Builder::new(chars.move_iter());
            let mut j = b.build().ok().unwrap();

            filter_json(&mut j);
            if dump_json {
                let mut writer = io::stdout();
                j.to_pretty_writer(&mut writer as &mut io::Writer);
            } else {
                print_sexp(0, &j);
            }
        },
        Err(ioerr) => {
            fail!("I/O Error: {}", ioerr.desc);
        }
    }
}
<|endoftext|>


<commit_before>//! Wallet.

use exonum::messages::Field;
use exonum::crypto::{PublicKey, Hash};

storage_value! {
/// Wallet information stored in the database.
    struct Wallet {
        const SIZE = 88;

        field pub_key:            &PublicKey  [00 => 32]
        field name:               &str        [32 => 40]
        field balance:            u64         [40 => 48]
        field history_len:        u64         [48 => 56]
        field history_hash:       &Hash       [56 => 88]
    }
}

impl Wallet {
    /// Overwrites balance.
    pub fn set_balance(&mut self, balance: u64) {
        Field::write(&balance, &mut self.raw, 40, 48);
    }

    /// Sets history hash.
    pub fn grow_length_set_history_hash(&mut self, hash: &Hash) {
        Field::write(&hash, &mut self.raw, 56, 88);
        Field::write(&(self.history_len() + 1), &mut self.raw, 48, 56);
    }

    /// Transfers currency from this wallet to `other`. Returns `false` if `self.balance()` is
    /// less then `amount`.
    pub fn transfer_to(&mut self, other: &mut Wallet, amount: u64) -> bool {
        if self.pub_key() == other.pub_key() {
            return false;
        }

        if self.balance() < amount {
            return false;
        }

        let self_amount = self.balance() - amount;
        let other_amount = other.balance() + amount;
        self.set_balance(self_amount);
        other.set_balance(other_amount);
        true
    }
}

#[cfg(test)]
pub fn assert_wallet(wallet: &Wallet,
                     pub_key: &PublicKey,
                     name: &str,
                     balance: u64,
                     history_len: u64,
                     history_hash: &Hash) {
    assert_eq!(wallet.pub_key(), pub_key);
    assert_eq!(wallet.name(), name);
    assert_eq!(wallet.balance(), balance);
    assert_eq!(wallet.history_hash(), history_hash);
    assert_eq!(wallet.history_len(), history_len);
}

#[cfg(test)]
mod tests {
    use exonum::storage::StorageValue;
    use super::*;

    #[test]
    fn test_wallet() {
        let hash = Hash::new([2; 32]);
        let name = "foobar abacaba Юникод всяуи";
        let pub_key = PublicKey::from_slice([1u8; 32].as_ref()).unwrap();
        let wallet = Wallet::new(&pub_key, name, 100500, 0, &hash);

        let wallet = wallet.clone();
        assert_wallet(&wallet, &pub_key, name, 100500, 0, &hash);
    }

    #[test]
    fn test_wallet_serde() {
        use serde_json;
        use rand::{thread_rng, Rng};
        use exonum::crypto::{HASH_SIZE, gen_keypair};

        let mut rng = thread_rng();
        let generator = move |_| {
            let string_len = rng.gen_range(20u8, 255u8);
            let mut hash_bytes = [0; HASH_SIZE];

            let (pub_key, _) = gen_keypair();
            let name: String = rng.gen_ascii_chars().take(string_len as usize).collect();
            let balance = rng.next_u64();
            let history_len = rng.next_u64();
            rng.fill_bytes(&mut hash_bytes);
            let hash = Hash::new(hash_bytes);
            Wallet::new(&pub_key, &name, balance, history_len, &hash)
        };
        let wallet_non_ascii = Wallet::new(&gen_keypair().0,
                                           "foobar abacaba Юникод всяуи",
                                           100500,
                                           0,
                                           &Hash::new([2; HASH_SIZE]));
        let mut wallets = (0..50).map(generator).collect::<Vec<_>>();
        wallets.push(wallet_non_ascii);
        for wallet in wallets {
            let json_str = serde_json::to_string(&wallet).unwrap();
            let wallet1: Wallet = serde_json::from_str(&json_str).unwrap();
            assert_eq!(wallet, wallet1);
            println!("wallet test data: {}",
                     serde_json::to_string(&WalletTestData::new(wallet)).unwrap());
        }
    }

    #[test]
    fn test_amount_transfer() {
        let hash = Hash::new([5; 32]);
        let pub_key_1 = PublicKey::from_slice([1u8; 32].as_ref()).unwrap();
        let pub_key_2 = PublicKey::from_slice([2u8; 32].as_ref()).unwrap();
        let mut a = Wallet::new(&pub_key_1, "a", 100, 12, &hash);
        let mut b = Wallet::new(&pub_key_2, "b", 0, 14, &hash);
        a.transfer_to(&mut b, 50);
        a.grow_length_set_history_hash(&hash);
        b.grow_length_set_history_hash(&hash);
        assert_eq!(a.balance(), 50);
        assert_eq!(a.history_len(), 13);
        assert_eq!(b.balance(), 50);
        assert_eq!(b.history_len(), 15);
    }

    #[derive(Serialize)]
    struct WalletTestData {
        wallet: Wallet,
        hash: Hash,
        raw: Vec<u8>,
    }

    impl WalletTestData {
        fn new(wallet: Wallet) -> WalletTestData {
            let wallet_hash = wallet.hash();
            let raw = StorageValue::serialize(wallet.clone());
            WalletTestData {
                wallet: wallet,
                hash: wallet_hash,
                raw: raw,
            }
        }
    }
}
<commit_msg>Add test for the same wallet transfer<commit_after>//! Wallet.

use exonum::messages::Field;
use exonum::crypto::{PublicKey, Hash};

storage_value! {
/// Wallet information stored in the database.
    struct Wallet {
        const SIZE = 88;

        field pub_key:            &PublicKey  [00 => 32]
        field name:               &str        [32 => 40]
        field balance:            u64         [40 => 48]
        field history_len:        u64         [48 => 56]
        field history_hash:       &Hash       [56 => 88]
    }
}

impl Wallet {
    /// Overwrites balance.
    pub fn set_balance(&mut self, balance: u64) {
        Field::write(&balance, &mut self.raw, 40, 48);
    }

    /// Sets history hash.
    pub fn grow_length_set_history_hash(&mut self, hash: &Hash) {
        Field::write(&hash, &mut self.raw, 56, 88);
        Field::write(&(self.history_len() + 1), &mut self.raw, 48, 56);
    }

    /// Transfers currency from this wallet to `other`. Returns `false` if `self.balance()` is
    /// less then `amount`.
    pub fn transfer_to(&mut self, other: &mut Wallet, amount: u64) -> bool {
        if self.pub_key() == other.pub_key() {
            return false;
        }

        if self.balance() < amount {
            return false;
        }

        let self_amount = self.balance() - amount;
        let other_amount = other.balance() + amount;
        self.set_balance(self_amount);
        other.set_balance(other_amount);
        true
    }
}

#[cfg(test)]
pub fn assert_wallet(wallet: &Wallet,
                     pub_key: &PublicKey,
                     name: &str,
                     balance: u64,
                     history_len: u64,
                     history_hash: &Hash) {
    assert_eq!(wallet.pub_key(), pub_key);
    assert_eq!(wallet.name(), name);
    assert_eq!(wallet.balance(), balance);
    assert_eq!(wallet.history_hash(), history_hash);
    assert_eq!(wallet.history_len(), history_len);
}

#[cfg(test)]
mod tests {
    use exonum::storage::StorageValue;
    use super::*;

    #[test]
    fn test_wallet() {
        let hash = Hash::new([2; 32]);
        let name = "foobar abacaba Юникод всяуи";
        let pub_key = PublicKey::from_slice([1u8; 32].as_ref()).unwrap();
        let wallet = Wallet::new(&pub_key, name, 100500, 0, &hash);

        let wallet = wallet.clone();
        assert_wallet(&wallet, &pub_key, name, 100500, 0, &hash);
    }

    #[test]
    fn test_wallet_serde() {
        use serde_json;
        use rand::{thread_rng, Rng};
        use exonum::crypto::{HASH_SIZE, gen_keypair};

        let mut rng = thread_rng();
        let generator = move |_| {
            let string_len = rng.gen_range(20u8, 255u8);
            let mut hash_bytes = [0; HASH_SIZE];

            let (pub_key, _) = gen_keypair();
            let name: String = rng.gen_ascii_chars().take(string_len as usize).collect();
            let balance = rng.next_u64();
            let history_len = rng.next_u64();
            rng.fill_bytes(&mut hash_bytes);
            let hash = Hash::new(hash_bytes);
            Wallet::new(&pub_key, &name, balance, history_len, &hash)
        };
        let wallet_non_ascii = Wallet::new(&gen_keypair().0,
                                           "foobar abacaba Юникод всяуи",
                                           100500,
                                           0,
                                           &Hash::new([2; HASH_SIZE]));
        let mut wallets = (0..50).map(generator).collect::<Vec<_>>();
        wallets.push(wallet_non_ascii);
        for wallet in wallets {
            let json_str = serde_json::to_string(&wallet).unwrap();
            let wallet1: Wallet = serde_json::from_str(&json_str).unwrap();
            assert_eq!(wallet, wallet1);
            println!("wallet test data: {}",
                     serde_json::to_string(&WalletTestData::new(wallet)).unwrap());
        }
    }

    #[test]
    fn test_amount_transfer() {
        let hash = Hash::new([5; 32]);
        let pub_key_1 = PublicKey::from_slice([1u8; 32].as_ref()).unwrap();
        let pub_key_2 = PublicKey::from_slice([2u8; 32].as_ref()).unwrap();
        let mut a = Wallet::new(&pub_key_1, "a", 100, 12, &hash);
        let mut b = Wallet::new(&pub_key_2, "b", 0, 14, &hash);
        a.transfer_to(&mut b, 50);
        a.grow_length_set_history_hash(&hash);
        b.grow_length_set_history_hash(&hash);
        assert_eq!(a.balance(), 50);
        assert_eq!(a.history_len(), 13);
        assert_eq!(b.balance(), 50);
        assert_eq!(b.history_len(), 15);
    }

    #[test]
    fn test_same_wallet_transfer() {
        let hash = Hash::new([5; 32]);
        let pub_key = PublicKey::from_slice([1u8; 32].as_ref()).unwrap();
        let mut a1 = Wallet::new(&pub_key, "a", 100, 12, &hash);
        let mut a2 = Wallet::new(&pub_key, "a", 100, 12, &hash);
        assert_eq!(a1.transfer_to(&mut a2, 50), false);
        assert_eq!(a2.transfer_to(&mut a1, 50), false);
    }

    #[derive(Serialize)]
    struct WalletTestData {
        wallet: Wallet,
        hash: Hash,
        raw: Vec<u8>,
    }

    impl WalletTestData {
        fn new(wallet: Wallet) -> WalletTestData {
            let wallet_hash = wallet.hash();
            let raw = StorageValue::serialize(wallet.clone());
            WalletTestData {
                wallet: wallet,
                hash: wallet_hash,
                raw: raw,
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate base64;
extern crate test;
extern crate rand;

use base64::{decode, decode_mode_buf, encode, encode_mode_buf, Base64Mode};

use test::Bencher;
use rand::Rng;

#[bench]
fn encode_3b(b: &mut Bencher) {
    do_encode_bench(b, 3)
}

#[bench]
fn encode_3b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3)
}

#[bench]
fn encode_50b(b: &mut Bencher) {
    do_encode_bench(b, 50)
}

#[bench]
fn encode_50b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 50)
}

#[bench]
fn encode_100b(b: &mut Bencher) {
    do_encode_bench(b, 100)
}

#[bench]
fn encode_100b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 100)
}

#[bench]
fn encode_500b(b: &mut Bencher) {
    do_encode_bench(b, 500)
}

#[bench]
fn encode_500b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500)
}

#[bench]
fn encode_3kib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024)
}

#[bench]
fn encode_3kib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn encode_3mib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_10mib(b: &mut Bencher) {
    do_encode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_10mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_30mib(b: &mut Bencher) {
    do_encode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn encode_30mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_3b(b: &mut Bencher) {
    do_decode_bench(b, 3)
}

#[bench]
fn decode_3b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3)
}

#[bench]
fn decode_50b(b: &mut Bencher) {
    do_decode_bench(b, 50)
}

#[bench]
fn decode_50b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 50)
}

#[bench]
fn decode_100b(b: &mut Bencher) {
    do_decode_bench(b, 100)
}

#[bench]
fn decode_100b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 100)
}

#[bench]
fn decode_500b(b: &mut Bencher) {
    do_decode_bench(b, 500)
}

#[bench]
fn decode_500b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 500)
}

#[bench]
fn decode_3kib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024)
}

#[bench]
fn decode_3kib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn decode_3mib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_10mib(b: &mut Bencher) {
    do_decode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_10mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_30mib(b: &mut Bencher) {
    do_decode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

fn do_decode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);
    let encoded = encode(&v);

    b.iter(|| {
        let orig = decode(&encoded);
        test::black_box(&orig);
    });
}

fn do_decode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    b.iter(|| {
        decode_mode_buf(&encoded, Base64Mode::Standard, &mut buf).unwrap();
        test::black_box(&buf);
        buf.clear();
    });
}

fn do_encode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.iter(|| {
        let e = encode(&v);
        test::black_box(&e);
    });
}

fn do_encode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = String::new();

    b.iter(|| {
        let e = encode_mode_buf(&v, Base64Mode::Standard, &mut buf);
        test::black_box(&e);
        buf.clear();
    });
}

fn fill(v: &mut Vec<u8>) {
    let cap = v.capacity();
    // weak randomness is plenty; we just want to not be completely friendly to the branch predictor
    let mut r = rand::weak_rng();
    while v.len() < cap {
        v.push(r.gen::<u8>());
    }
}
<commit_msg>Let Bencher show us bytes/sec<commit_after>#![feature(test)]

extern crate base64;
extern crate test;
extern crate rand;

use base64::{decode, decode_mode_buf, encode, encode_mode_buf, Base64Mode};

use test::Bencher;
use rand::Rng;

#[bench]
fn encode_3b(b: &mut Bencher) {
    do_encode_bench(b, 3)
}

#[bench]
fn encode_3b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3)
}

#[bench]
fn encode_50b(b: &mut Bencher) {
    do_encode_bench(b, 50)
}

#[bench]
fn encode_50b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 50)
}

#[bench]
fn encode_100b(b: &mut Bencher) {
    do_encode_bench(b, 100)
}

#[bench]
fn encode_100b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 100)
}

#[bench]
fn encode_500b(b: &mut Bencher) {
    do_encode_bench(b, 500)
}

#[bench]
fn encode_500b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500)
}

#[bench]
fn encode_3kib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024)
}

#[bench]
fn encode_3kib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn encode_3mib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_10mib(b: &mut Bencher) {
    do_encode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_10mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_30mib(b: &mut Bencher) {
    do_encode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn encode_30mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_3b(b: &mut Bencher) {
    do_decode_bench(b, 3)
}

#[bench]
fn decode_3b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3)
}

#[bench]
fn decode_50b(b: &mut Bencher) {
    do_decode_bench(b, 50)
}

#[bench]
fn decode_50b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 50)
}

#[bench]
fn decode_100b(b: &mut Bencher) {
    do_decode_bench(b, 100)
}

#[bench]
fn decode_100b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 100)
}

#[bench]
fn decode_500b(b: &mut Bencher) {
    do_decode_bench(b, 500)
}

#[bench]
fn decode_500b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 500)
}

#[bench]
fn decode_3kib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024)
}

#[bench]
fn decode_3kib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn decode_3mib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_10mib(b: &mut Bencher) {
    do_decode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_10mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_30mib(b: &mut Bencher) {
    do_decode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

fn do_decode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);
    let encoded = encode(&v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let orig = decode(&encoded);
        test::black_box(&orig);
    });
}

fn do_decode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    b.bytes = v.len() as u64;
    b.iter(|| {
        decode_mode_buf(&encoded, Base64Mode::Standard, &mut buf).unwrap();
        test::black_box(&buf);
        buf.clear();
    });
}

fn do_encode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = encode(&v);
        test::black_box(&e);
    });
}

fn do_encode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = String::new();

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = encode_mode_buf(&v, Base64Mode::Standard, &mut buf);
        test::black_box(&e);
        buf.clear();
    });
}

fn fill(v: &mut Vec<u8>) {
    let cap = v.capacity();
    // weak randomness is plenty; we just want to not be completely friendly to the branch predictor
    let mut r = rand::weak_rng();
    while v.len() < cap {
        v.push(r.gen::<u8>());
    }
}
<|endoftext|>


<commit_before>#![feature(libc)]
#![feature(collections)]
#![feature(convert)]
#![feature(path_ext)]
extern crate ruroonga;
extern crate libc;
use ruroonga::*;
use std::ffi::CStr;
use std::ffi::CString;
use std::str;
use std::string::String;
use std::path::Path;
use std::fs::PathExt;

fn main() {
    unsafe {
        let ctx = groonga_init();
        let dbpath = "test.db";
        let db_ctx = groonga_db_use(ctx, dbpath);
        println!("Hello in Ruroonga with Groonga: {}", get_groonga_version());
        let _ = groonga_fin(ctx);
    }
}
<commit_msg>exec command with generated bindings in testing<commit_after>#![feature(libc)]
#![feature(collections)]
#![feature(convert)]
#![feature(path_ext)]
extern crate ruroonga;
extern crate libc;
use ruroonga::*;
use std::ffi::CStr;
use std::ffi::CString;
use std::str;
use std::string::String;
use std::path::Path;
use std::fs::PathExt;
use std::mem;

fn main() {
    unsafe {
        let ctx = groonga_init();
        let dbpath = "test.db";
        let db_ctx = groonga_db_use(ctx, dbpath);
        let command = "table_create Users TABLE_HASH_KEY ShortText";
        let command_length = command.len() as u32;
        println!("command length: {}", command.len());
        println!("command: {}", command);
        let c_command = convert_str_to_cstr(command);
        let flag = 0;
        let rc = groonga::grn_ctx_send(ctx, c_command, command_length, flag);
        let received_res: *mut *mut libc::c_char = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut *mut libc::c_char;
        let received_len: *mut libc::c_uint = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut libc::c_uint;
        let received_flag: *mut libc::c_int = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut libc::c_int;
        let _ = groonga::grn_ctx_recv(ctx, received_res, received_len, received_flag);
        /* for debug */
        let is_null_p = received_res.is_null();
        let is_null_p2 = received_len.is_null();
        let is_null_p3 = received_flag.is_null();
        println!("result str: {:?}", received_res);
        println!("result: {}", is_null_p);
        println!("result2: {}", is_null_p2);
        println!("result3: {}", is_null_p3);
        /* end */
        libc::free(received_res as *mut libc::c_void);
        libc::free(received_len as *mut libc::c_void);
        libc::free(received_flag as *mut libc::c_void);

        println!("Hello in Ruroonga with Groonga: {}", get_groonga_version());
        let _ = groonga_fin(ctx);
    }
}
<|endoftext|>