<commit_before>pub mod book;
pub mod logger;

use bus::BusReader;
use std::thread::{self, JoinHandle};
use ::error::PoloError;

pub type ActorResult = Result<u32,PoloError>;

pub trait Actor: Send + Clone + 'static {
  fn process_message(&mut self, msg: String) -> Result<(),PoloError>;

  fn listen(&mut self, mut channel: BusReader<Option<String>>) -> ActorResult {
    let mut counter = 0;
    loop {
      // TODO: maybe send reference, not String?
      let msg = channel.recv().unwrap();
      counter = counter + 1;
      if let Some(text) = msg {
        self.process_message(text).unwrap();
      } else {
        break;
      }
    };
    Ok(counter)
  }

  fn subscribe(&mut self, channel: BusReader<Option<String>>) -> JoinHandle<ActorResult> {
    let mut actor = self.clone();
    thread::spawn(move || actor.listen(channel))
  }
}<commit_msg>add exports for Accountant and Logger<commit_after>pub mod book;
pub mod logger;

use bus::BusReader;
use std::thread::{self, JoinHandle};
use ::error::PoloError;

pub type Accountant = book::Accountant;
pub type Logger = logger::Logger;

pub type ActorResult = Result<u32,PoloError>;

pub trait Actor: Send + Clone + 'static {
  fn process_message(&mut self, msg: String) -> Result<(),PoloError>;

  fn listen(&mut self, mut channel: BusReader<Option<String>>) -> ActorResult {
    let mut counter = 0;
    loop {
      // TODO: maybe send reference, not String?
      let msg = channel.recv().unwrap();
      counter = counter + 1;
      if let Some(text) = msg {
        self.process_message(text).unwrap();
      } else {
        break;
      }
    };
    Ok(counter)
  }

  fn subscribe(&mut self, channel: BusReader<Option<String>>) -> JoinHandle<ActorResult> {
    let mut actor = self.clone();
    thread::spawn(move || actor.listen(channel))
  }
}<|endoftext|>


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

use std::iter::Range;

/// The `SharedVertex` trait is meant to be used with the `IndexedPolygon` trait.
/// This trait is meant as a way to calculate the shared vertices that are
/// required to build the implementors mesh.
pub trait SharedVertex<V> {
    /// return the shared vertex at offset `i`
    fn shared_vertex(&self, i: uint) -> V;

    /// return the number of shared vertices required to represent the mesh
    fn shared_vertex_count(&self) -> uint;

    /// create an iterator that returns each shared vertex that is required to
    /// build the mesh.
    fn shared_vertex_iter<'a>(&'a self) -> ShareVertexIterator<'a, Self, V> {
        ShareVertexIterator {
            base: self,
            idx: range(0, self.shared_vertex_count())
        }
    }
}

pub struct ShareVertexIterator<'a, T:'a, V> {
    base: &'a T,
    idx: Range<uint>
}

impl<'a, T: SharedVertex<V>, V> Iterator<V> for ShareVertexIterator<'a, T, V> {
    fn next(&mut self) -> Option<V> {
        self.idx.next().map(|idx| self.base.shared_vertex(idx))
    }
}

/// The `IndexedPolygon` trait is used with the `SharedVertex` trait in order to build
/// a mesh. `IndexedPolygon` calculates each polygon face required to build an implementors mesh.
/// each face is always returned in indexed form that points to the correct vertice supplied
/// by the `SharedVertex` trait.
pub trait IndexedPolygon<V> {
    /// return a polygon with indices to the shared vertex
    fn indexed_polygon(&self, i: uint) -> V;

    /// return the number of polygons that are needed to represent this mesh
    fn indexed_polygon_count(&self) -> uint;

    /// create a iterator that will return a polygon for each face in the source mesh
    fn indexed_polygon_iter<'a>(&'a self) -> IndexedPolygonIterator<'a, Self, V> {
        IndexedPolygonIterator {
            base: self,
            idx: range(0, self.indexed_polygon_count())
        }
    }
}

pub struct IndexedPolygonIterator<'a, T:'a, V> {
    base: &'a T,
    idx: Range<uint>
}

impl<'a, T: IndexedPolygon<V>, V> Iterator<V> for IndexedPolygonIterator<'a, T, V> {
    fn next(&mut self) -> Option<V> {
        self.idx.next().map(|idx| self.base.indexed_polygon(idx))
    }
}<commit_msg>Fix spelling<commit_after>//   Copyright Colin Sherratt 2014
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

use std::iter::Range;

/// The `SharedVertex` trait is meant to be used with the `IndexedPolygon` trait.
/// This trait is meant as a way to calculate the shared vertices that are
/// required to build the implementors mesh.
pub trait SharedVertex<V> {
    /// return the shared vertex at offset `i`
    fn shared_vertex(&self, i: uint) -> V;

    /// return the number of shared vertices required to represent the mesh
    fn shared_vertex_count(&self) -> uint;

    /// create an iterator that returns each shared vertex that is required to
    /// build the mesh.
    fn shared_vertex_iter<'a>(&'a self) -> SharedVertexIterator<'a, Self, V> {
        SharedVertexIterator {
            base: self,
            idx: range(0, self.shared_vertex_count())
        }
    }
}

pub struct SharedVertexIterator<'a, T:'a, V> {
    base: &'a T,
    idx: Range<uint>
}

impl<'a, T: SharedVertex<V>, V> Iterator<V> for SharedVertexIterator<'a, T, V> {
    fn next(&mut self) -> Option<V> {
        self.idx.next().map(|idx| self.base.shared_vertex(idx))
    }
}

/// The `IndexedPolygon` trait is used with the `SharedVertex` trait in order to build
/// a mesh. `IndexedPolygon` calculates each polygon face required to build an implementors mesh.
/// each face is always returned in indexed form that points to the correct vertice supplied
/// by the `SharedVertex` trait.
pub trait IndexedPolygon<V> {
    /// return a polygon with indices to the shared vertex
    fn indexed_polygon(&self, i: uint) -> V;

    /// return the number of polygons that are needed to represent this mesh
    fn indexed_polygon_count(&self) -> uint;

    /// create a iterator that will return a polygon for each face in the source mesh
    fn indexed_polygon_iter<'a>(&'a self) -> IndexedPolygonIterator<'a, Self, V> {
        IndexedPolygonIterator {
            base: self,
            idx: range(0, self.indexed_polygon_count())
        }
    }
}

pub struct IndexedPolygonIterator<'a, T:'a, V> {
    base: &'a T,
    idx: Range<uint>
}

impl<'a, T: IndexedPolygon<V>, V> Iterator<V> for IndexedPolygonIterator<'a, T, V> {
    fn next(&mut self) -> Option<V> {
        self.idx.next().map(|idx| self.base.indexed_polygon(idx))
    }
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::borrow::Cow;
use std::fmt;
use std::io::Write;
use std::mem;

use syn;

use bindgen::config::{Config, Language};
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::dependencies::Dependencies;
use bindgen::ir::{
    AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
    Struct, ToCondition, Type,
};
use bindgen::library::Library;
use bindgen::writer::{Source, SourceWriter};
use bindgen::Bindings;

#[derive(Debug, Clone)]
pub enum Literal {
    Expr(String),
    BinOp {
        left: Box<Literal>,
        op: &'static str,
        right: Box<Literal>,
    },
    Struct {
        path: Path,
        export_name: String,
        fields: Vec<(String, Literal)>,
    },
}

impl Literal {
    fn replace_self_with(&mut self, self_ty: &Path) {
        match *self {
            Literal::BinOp { .. } | Literal::Expr(..) => {}
            Literal::Struct {
                ref mut path,
                ref mut export_name,
                ref mut fields,
            } => {
                if path.replace_self_with(self_ty) {
                    *export_name = self_ty.name().to_owned();
                }
                for &mut (ref _name, ref mut expr) in fields {
                    expr.replace_self_with(self_ty);
                }
            }
        }
    }

    fn is_valid(&self, bindings: &Bindings) -> bool {
        match *self {
            Literal::Expr(..) => true,
            Literal::BinOp {
                ref left,
                ref right,
                ..
            } => left.is_valid(bindings) && right.is_valid(bindings),
            Literal::Struct { ref path, .. } => bindings.struct_exists(path),
        }
    }
}

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Literal::Expr(v) => write!(f, "{}", v),
            Literal::BinOp {
                ref left,
                op,
                ref right,
            } => write!(f, "{} {} {}", left, op, right),
            Literal::Struct {
                path: _,
                export_name,
                fields,
            } => write!(
                f,
                "({}){{ {} }}",
                export_name,
                fields
                    .iter()
                    .map(|(key, lit)| format!(".{} = {}", key, lit))
                    .collect::<Vec<String>>()
                    .join(", "),
            ),
        }
    }
}

impl Literal {
    pub fn rename_for_config(&mut self, config: &Config) {
        match self {
            Literal::Struct {
                path: _,
                ref mut export_name,
                fields,
            } => {
                config.export.rename(export_name);
                for (_, lit) in fields {
                    lit.rename_for_config(config);
                }
            }
            Literal::BinOp {
                ref mut left,
                ref mut right,
                ..
            } => {
                left.rename_for_config(config);
                right.rename_for_config(config);
            }
            Literal::Expr(_) => {}
        }
    }

    pub fn load(expr: &syn::Expr) -> Result<Literal, String> {
        match *expr {
            syn::Expr::Binary(ref bin_expr) => {
                let l = Self::load(&bin_expr.left)?;
                let r = Self::load(&bin_expr.right)?;
                let op = match bin_expr.op {
                    syn::BinOp::Add(..) => "+",
                    syn::BinOp::Sub(..) => "-",
                    syn::BinOp::Mul(..) => "*",
                    syn::BinOp::Div(..) => "/",
                    syn::BinOp::Rem(..) => "%",
                    syn::BinOp::Shl(..) => "<<",
                    syn::BinOp::Shr(..) => ">>",
                    _ => return Err(format!("Unsupported binary op {:?}", bin_expr.op)),
                };
                Ok(Literal::BinOp {
                    left: Box::new(l),
                    op,
                    right: Box::new(r),
                })
            }
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Str(ref value),
                ..
            }) => Ok(Literal::Expr(format!("u8\"{}\"", value.value()))),
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Byte(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Char(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Int(ref value),
                ..
            }) => match value.suffix() {
                syn::IntSuffix::Usize
                | syn::IntSuffix::U8
                | syn::IntSuffix::U16
                | syn::IntSuffix::U32
                | syn::IntSuffix::U64
                | syn::IntSuffix::U128
                | syn::IntSuffix::None => Ok(Literal::Expr(format!("{}", value.value()))),
                syn::IntSuffix::Isize
                | syn::IntSuffix::I8
                | syn::IntSuffix::I16
                | syn::IntSuffix::I32
                | syn::IntSuffix::I64
                | syn::IntSuffix::I128 => unsafe {
                    Ok(Literal::Expr(format!(
                        "{}",
                        mem::transmute::<u64, i64>(value.value())
                    )))
                },
            },
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Float(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Bool(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value))),

            syn::Expr::Struct(syn::ExprStruct {
                ref path,
                ref fields,
                ..
            }) => {
                let struct_name = path.segments[0].ident.to_string();
                let mut field_pairs: Vec<(String, Literal)> = Vec::new();
                for field in fields {
                    let ident = match field.member {
                        syn::Member::Named(ref name) => name.to_string(),
                        syn::Member::Unnamed(ref index) => format!("_{}", index.index),
                    };
                    let key = ident.to_string();
                    let value = Literal::load(&field.expr)?;
                    field_pairs.push((key, value));
                }
                Ok(Literal::Struct {
                    path: Path::new(struct_name.clone()),
                    export_name: struct_name,
                    fields: field_pairs,
                })
            }
            _ => Err("Unsupported literal expression.".to_owned()),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Constant {
    pub path: Path,
    pub export_name: String,
    pub ty: Type,
    pub value: Literal,
    pub cfg: Option<Cfg>,
    pub annotations: AnnotationSet,
    pub documentation: Documentation,
    pub associated_to: Option<Path>,
}

fn can_handle(ty: &Type, expr: &syn::Expr) -> bool {
    if ty.is_primitive_or_ptr_primitive() {
        return true;
    }
    match *expr {
        syn::Expr::Struct(_) => true,
        _ => false,
    }
}

impl Constant {
    pub fn load(
        path: Path,
        mod_cfg: Option<&Cfg>,
        ty: &syn::Type,
        expr: &syn::Expr,
        attrs: &[syn::Attribute],
        associated_to: Option<Path>,
    ) -> Result<Constant, String> {
        let ty = Type::load(ty)?;
        let mut ty = match ty {
            Some(ty) => ty,
            None => {
                return Err("Cannot have a zero sized const definition.".to_owned());
            }
        };

        if !can_handle(&ty, expr) {
            return Err("Unhanded const definition".to_owned());
        }

        let mut lit = Literal::load(&expr)?;

        if let Some(ref associated_to) = associated_to {
            ty.replace_self_with(associated_to);
            lit.replace_self_with(associated_to);
        }

        Ok(Constant::new(
            path,
            ty,
            lit,
            Cfg::append(mod_cfg, Cfg::load(attrs)),
            AnnotationSet::load(attrs)?,
            Documentation::load(attrs),
            associated_to,
        ))
    }

    pub fn new(
        path: Path,
        ty: Type,
        value: Literal,
        cfg: Option<Cfg>,
        annotations: AnnotationSet,
        documentation: Documentation,
        associated_to: Option<Path>,
    ) -> Self {
        let export_name = path.name().to_owned();
        Self {
            path,
            export_name,
            ty,
            value,
            cfg,
            annotations,
            documentation,
            associated_to,
        }
    }
}

impl Item for Constant {
    fn path(&self) -> &Path {
        &self.path
    }

    fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
        self.ty.add_dependencies(library, out);
    }

    fn export_name(&self) -> &str {
        &self.export_name
    }

    fn cfg(&self) -> Option<&Cfg> {
        self.cfg.as_ref()
    }

    fn annotations(&self) -> &AnnotationSet {
        &self.annotations
    }

    fn annotations_mut(&mut self) -> &mut AnnotationSet {
        &mut self.annotations
    }

    fn container(&self) -> ItemContainer {
        ItemContainer::Constant(self.clone())
    }

    fn rename_for_config(&mut self, config: &Config) {
        if self.associated_to.is_none() {
            config.export.rename(&mut self.export_name);
        }
        self.value.rename_for_config(config);
        self.ty.rename_for_config(config, &GenericParams::default()); // FIXME: should probably propagate something here
    }

    fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
        self.ty.resolve_declaration_types(resolver);
    }
}

impl Constant {
    pub fn write_declaration<F: Write>(
        &self,
        config: &Config,
        out: &mut SourceWriter<F>,
        associated_to_struct: &Struct,
    ) {
        debug_assert!(self.associated_to.is_some());
        debug_assert!(config.language == Language::Cxx);
        debug_assert!(!associated_to_struct.is_transparent);
        debug_assert!(config.structure.associated_constants_in_body);
        debug_assert!(config.constant.allow_static_const);

        if let Type::ConstPtr(..) = self.ty {
            out.write("static ");
        } else {
            out.write("static const ");
        }
        self.ty.write(config, out);
        write!(out, " {};", self.export_name())
    }

    pub fn write<F: Write>(
        &self,
        config: &Config,
        out: &mut SourceWriter<F>,
        associated_to_struct: Option<&Struct>,
    ) {
        if let Some(assoc) = associated_to_struct {
            if assoc.is_generic() {
                return; // Not tested / implemented yet, so bail out.
            }
        }

        if !self.value.is_valid(out.bindings()) {
            return;
        }

        let associated_to_transparent = associated_to_struct.map_or(false, |s| s.is_transparent);

        let in_body = associated_to_struct.is_some()
            && config.language == Language::Cxx
            && config.structure.associated_constants_in_body
            && config.constant.allow_static_const
            && !associated_to_transparent;

        let condition = (&self.cfg).to_condition(config);
        condition.write_before(config, out);

        let name = if in_body {
            Cow::Owned(format!(
                "{}::{}",
                associated_to_struct.unwrap().export_name(),
                self.export_name(),
            ))
        } else if self.associated_to.is_none() {
            Cow::Borrowed(self.export_name())
        } else {
            let associated_name = match associated_to_struct {
                Some(s) => Cow::Borrowed(s.export_name()),
                None => {
                    let mut name = self.associated_to.as_ref().unwrap().name().to_owned();
                    config.export.rename(&mut name);
                    Cow::Owned(name)
                }
            };

            Cow::Owned(format!("{}_{}", associated_name, self.export_name()))
        };

        let value = match self.value {
            Literal::Struct {
                ref fields,
                ref path,
                ..
            } if out.bindings().struct_is_transparent(path) => &fields[0].1,
            _ => &self.value,
        };

        if config.constant.allow_static_const && config.language == Language::Cxx {
            out.write(if in_body { "inline " } else { "static " });
            if let Type::ConstPtr(..) = self.ty {
                // Nothing.
            } else {
                out.write("const ");
            }
            self.ty.write(config, out);
            write!(out, " {} = {};", name, value)
        } else {
            write!(out, "#define {} {}", name, value)
        }
        condition.write_after(config, out);
    }
}
<commit_msg>typo (#311)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::borrow::Cow;
use std::fmt;
use std::io::Write;
use std::mem;

use syn;

use bindgen::config::{Config, Language};
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::dependencies::Dependencies;
use bindgen::ir::{
    AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
    Struct, ToCondition, Type,
};
use bindgen::library::Library;
use bindgen::writer::{Source, SourceWriter};
use bindgen::Bindings;

#[derive(Debug, Clone)]
pub enum Literal {
    Expr(String),
    BinOp {
        left: Box<Literal>,
        op: &'static str,
        right: Box<Literal>,
    },
    Struct {
        path: Path,
        export_name: String,
        fields: Vec<(String, Literal)>,
    },
}

impl Literal {
    fn replace_self_with(&mut self, self_ty: &Path) {
        match *self {
            Literal::BinOp { .. } | Literal::Expr(..) => {}
            Literal::Struct {
                ref mut path,
                ref mut export_name,
                ref mut fields,
            } => {
                if path.replace_self_with(self_ty) {
                    *export_name = self_ty.name().to_owned();
                }
                for &mut (ref _name, ref mut expr) in fields {
                    expr.replace_self_with(self_ty);
                }
            }
        }
    }

    fn is_valid(&self, bindings: &Bindings) -> bool {
        match *self {
            Literal::Expr(..) => true,
            Literal::BinOp {
                ref left,
                ref right,
                ..
            } => left.is_valid(bindings) && right.is_valid(bindings),
            Literal::Struct { ref path, .. } => bindings.struct_exists(path),
        }
    }
}

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Literal::Expr(v) => write!(f, "{}", v),
            Literal::BinOp {
                ref left,
                op,
                ref right,
            } => write!(f, "{} {} {}", left, op, right),
            Literal::Struct {
                path: _,
                export_name,
                fields,
            } => write!(
                f,
                "({}){{ {} }}",
                export_name,
                fields
                    .iter()
                    .map(|(key, lit)| format!(".{} = {}", key, lit))
                    .collect::<Vec<String>>()
                    .join(", "),
            ),
        }
    }
}

impl Literal {
    pub fn rename_for_config(&mut self, config: &Config) {
        match self {
            Literal::Struct {
                path: _,
                ref mut export_name,
                fields,
            } => {
                config.export.rename(export_name);
                for (_, lit) in fields {
                    lit.rename_for_config(config);
                }
            }
            Literal::BinOp {
                ref mut left,
                ref mut right,
                ..
            } => {
                left.rename_for_config(config);
                right.rename_for_config(config);
            }
            Literal::Expr(_) => {}
        }
    }

    pub fn load(expr: &syn::Expr) -> Result<Literal, String> {
        match *expr {
            syn::Expr::Binary(ref bin_expr) => {
                let l = Self::load(&bin_expr.left)?;
                let r = Self::load(&bin_expr.right)?;
                let op = match bin_expr.op {
                    syn::BinOp::Add(..) => "+",
                    syn::BinOp::Sub(..) => "-",
                    syn::BinOp::Mul(..) => "*",
                    syn::BinOp::Div(..) => "/",
                    syn::BinOp::Rem(..) => "%",
                    syn::BinOp::Shl(..) => "<<",
                    syn::BinOp::Shr(..) => ">>",
                    _ => return Err(format!("Unsupported binary op {:?}", bin_expr.op)),
                };
                Ok(Literal::BinOp {
                    left: Box::new(l),
                    op,
                    right: Box::new(r),
                })
            }
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Str(ref value),
                ..
            }) => Ok(Literal::Expr(format!("u8\"{}\"", value.value()))),
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Byte(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Char(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Int(ref value),
                ..
            }) => match value.suffix() {
                syn::IntSuffix::Usize
                | syn::IntSuffix::U8
                | syn::IntSuffix::U16
                | syn::IntSuffix::U32
                | syn::IntSuffix::U64
                | syn::IntSuffix::U128
                | syn::IntSuffix::None => Ok(Literal::Expr(format!("{}", value.value()))),
                syn::IntSuffix::Isize
                | syn::IntSuffix::I8
                | syn::IntSuffix::I16
                | syn::IntSuffix::I32
                | syn::IntSuffix::I64
                | syn::IntSuffix::I128 => unsafe {
                    Ok(Literal::Expr(format!(
                        "{}",
                        mem::transmute::<u64, i64>(value.value())
                    )))
                },
            },
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Float(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Bool(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value))),

            syn::Expr::Struct(syn::ExprStruct {
                ref path,
                ref fields,
                ..
            }) => {
                let struct_name = path.segments[0].ident.to_string();
                let mut field_pairs: Vec<(String, Literal)> = Vec::new();
                for field in fields {
                    let ident = match field.member {
                        syn::Member::Named(ref name) => name.to_string(),
                        syn::Member::Unnamed(ref index) => format!("_{}", index.index),
                    };
                    let key = ident.to_string();
                    let value = Literal::load(&field.expr)?;
                    field_pairs.push((key, value));
                }
                Ok(Literal::Struct {
                    path: Path::new(struct_name.clone()),
                    export_name: struct_name,
                    fields: field_pairs,
                })
            }
            _ => Err("Unsupported literal expression.".to_owned()),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Constant {
    pub path: Path,
    pub export_name: String,
    pub ty: Type,
    pub value: Literal,
    pub cfg: Option<Cfg>,
    pub annotations: AnnotationSet,
    pub documentation: Documentation,
    pub associated_to: Option<Path>,
}

fn can_handle(ty: &Type, expr: &syn::Expr) -> bool {
    if ty.is_primitive_or_ptr_primitive() {
        return true;
    }
    match *expr {
        syn::Expr::Struct(_) => true,
        _ => false,
    }
}

impl Constant {
    pub fn load(
        path: Path,
        mod_cfg: Option<&Cfg>,
        ty: &syn::Type,
        expr: &syn::Expr,
        attrs: &[syn::Attribute],
        associated_to: Option<Path>,
    ) -> Result<Constant, String> {
        let ty = Type::load(ty)?;
        let mut ty = match ty {
            Some(ty) => ty,
            None => {
                return Err("Cannot have a zero sized const definition.".to_owned());
            }
        };

        if !can_handle(&ty, expr) {
            return Err("Unhandled const definition".to_owned());
        }

        let mut lit = Literal::load(&expr)?;

        if let Some(ref associated_to) = associated_to {
            ty.replace_self_with(associated_to);
            lit.replace_self_with(associated_to);
        }

        Ok(Constant::new(
            path,
            ty,
            lit,
            Cfg::append(mod_cfg, Cfg::load(attrs)),
            AnnotationSet::load(attrs)?,
            Documentation::load(attrs),
            associated_to,
        ))
    }

    pub fn new(
        path: Path,
        ty: Type,
        value: Literal,
        cfg: Option<Cfg>,
        annotations: AnnotationSet,
        documentation: Documentation,
        associated_to: Option<Path>,
    ) -> Self {
        let export_name = path.name().to_owned();
        Self {
            path,
            export_name,
            ty,
            value,
            cfg,
            annotations,
            documentation,
            associated_to,
        }
    }
}

impl Item for Constant {
    fn path(&self) -> &Path {
        &self.path
    }

    fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
        self.ty.add_dependencies(library, out);
    }

    fn export_name(&self) -> &str {
        &self.export_name
    }

    fn cfg(&self) -> Option<&Cfg> {
        self.cfg.as_ref()
    }

    fn annotations(&self) -> &AnnotationSet {
        &self.annotations
    }

    fn annotations_mut(&mut self) -> &mut AnnotationSet {
        &mut self.annotations
    }

    fn container(&self) -> ItemContainer {
        ItemContainer::Constant(self.clone())
    }

    fn rename_for_config(&mut self, config: &Config) {
        if self.associated_to.is_none() {
            config.export.rename(&mut self.export_name);
        }
        self.value.rename_for_config(config);
        self.ty.rename_for_config(config, &GenericParams::default()); // FIXME: should probably propagate something here
    }

    fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
        self.ty.resolve_declaration_types(resolver);
    }
}

impl Constant {
    pub fn write_declaration<F: Write>(
        &self,
        config: &Config,
        out: &mut SourceWriter<F>,
        associated_to_struct: &Struct,
    ) {
        debug_assert!(self.associated_to.is_some());
        debug_assert!(config.language == Language::Cxx);
        debug_assert!(!associated_to_struct.is_transparent);
        debug_assert!(config.structure.associated_constants_in_body);
        debug_assert!(config.constant.allow_static_const);

        if let Type::ConstPtr(..) = self.ty {
            out.write("static ");
        } else {
            out.write("static const ");
        }
        self.ty.write(config, out);
        write!(out, " {};", self.export_name())
    }

    pub fn write<F: Write>(
        &self,
        config: &Config,
        out: &mut SourceWriter<F>,
        associated_to_struct: Option<&Struct>,
    ) {
        if let Some(assoc) = associated_to_struct {
            if assoc.is_generic() {
                return; // Not tested / implemented yet, so bail out.
            }
        }

        if !self.value.is_valid(out.bindings()) {
            return;
        }

        let associated_to_transparent = associated_to_struct.map_or(false, |s| s.is_transparent);

        let in_body = associated_to_struct.is_some()
            && config.language == Language::Cxx
            && config.structure.associated_constants_in_body
            && config.constant.allow_static_const
            && !associated_to_transparent;

        let condition = (&self.cfg).to_condition(config);
        condition.write_before(config, out);

        let name = if in_body {
            Cow::Owned(format!(
                "{}::{}",
                associated_to_struct.unwrap().export_name(),
                self.export_name(),
            ))
        } else if self.associated_to.is_none() {
            Cow::Borrowed(self.export_name())
        } else {
            let associated_name = match associated_to_struct {
                Some(s) => Cow::Borrowed(s.export_name()),
                None => {
                    let mut name = self.associated_to.as_ref().unwrap().name().to_owned();
                    config.export.rename(&mut name);
                    Cow::Owned(name)
                }
            };

            Cow::Owned(format!("{}_{}", associated_name, self.export_name()))
        };

        let value = match self.value {
            Literal::Struct {
                ref fields,
                ref path,
                ..
            } if out.bindings().struct_is_transparent(path) => &fields[0].1,
            _ => &self.value,
        };

        if config.constant.allow_static_const && config.language == Language::Cxx {
            out.write(if in_body { "inline " } else { "static " });
            if let Type::ConstPtr(..) = self.ty {
                // Nothing.
            } else {
                out.write("const ");
            }
            self.ty.write(config, out);
            write!(out, " {} = {};", name, value)
        } else {
            write!(out, "#define {} {}", name, value)
        }
        condition.write_after(config, out);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Exonum Team
//
// 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.

//! An implementation of base index with most common features.
//!
//! The `BaseIndex` structure is not intended for direct use, rather it is the
//! basis for building other types of indices. The given section contains methods
//! related to `BaseIndex` and the iterator over the items of this index.

// spell-checker:ignore subprefix

use std::{borrow::Cow, marker::PhantomData};

use super::{BinaryKey, BinaryValue, Fork, Iter, Snapshot};
use crate::indexes_metadata::{self, IndexType, INDEXES_METADATA_TABLE_NAME};

/// Basic struct for all indices that implements common features.
///
/// This structure is not intended for direct use, rather it is the basis for building other types
/// of indices.
///
/// `BaseIndex` requires that keys should implement the [`BinaryKey`] trait and
/// values should implement the [`BinaryValue`] trait. However, this structure
/// is not bound to specific types and allows the use of *any* types as keys or values.
///
/// [`BinaryKey`]: ../trait.BinaryKey.html
/// [`BinaryValue`]: ../trait.BinaryValue.html
#[derive(Debug)]
pub struct BaseIndex<T> {
    name: String,
    is_family: bool,
    index_id: Option<Vec<u8>>,
    is_mutable: bool,
    index_type: IndexType,
    view: T,
}

/// An iterator over the entries of a `BaseIndex`.
///
/// This struct is created by the [`iter`] or
/// [`iter_from`] method on [`BaseIndex`]. See its documentation for details.
///
/// [`iter`]: struct.BaseIndex.html#method.iter
/// [`iter_from`]: struct.BaseIndex.html#method.iter_from
/// [`BaseIndex`]: struct.BaseIndex.html
pub struct BaseIndexIter<'a, K, V> {
    base_iter: Iter<'a>,
    base_prefix_len: usize,
    index_id: Vec<u8>,
    ended: bool,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
}

impl<T> BaseIndex<T>
where
    T: AsRef<dyn Snapshot>,
{
    /// Creates a new index representation based on the name and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case, only
    /// immutable methods are available. In the second case, both immutable and mutable methods are
    /// available.
    ///
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new<S: AsRef<str>>(index_name: S, index_type: IndexType, view: T) -> Self {
        assert_valid_name(&index_name);

        let is_family = false;
        indexes_metadata::assert_index_type(
            index_name.as_ref(),
            index_type,
            is_family,
            view.as_ref(),
        );

        Self {
            name: index_name.as_ref().to_string(),
            is_family,
            index_id: None,
            is_mutable: false,
            index_type,
            view,
        }
    }

    /// Creates a new index representation based on the family name, index ID inside family
    /// and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case, only
    /// immutable methods are available. In the second case, both immutable and mutable methods are
    /// available.
    ///
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new_in_family<S, P>(family_name: S, index_id: &P, index_type: IndexType, view: T) -> Self
    where
        P: BinaryKey,
        P: ?Sized,
        S: AsRef<str>,
    {
        assert_valid_name(&family_name);

        let is_family = true;
        indexes_metadata::assert_index_type(
            family_name.as_ref(),
            index_type,
            is_family,
            view.as_ref(),
        );

        Self {
            name: family_name.as_ref().to_string(),
            is_family,
            index_id: {
                let mut buf = vec![0; index_id.size()];
                index_id.write(&mut buf);
                Some(buf)
            },
            is_mutable: false,
            index_type,
            view,
        }
    }

    pub(crate) fn indexes_metadata(view: T) -> Self {
        Self {
            name: INDEXES_METADATA_TABLE_NAME.to_string(),
            is_family: false,
            index_id: None,
            is_mutable: true,
            index_type: IndexType::Map,
            view,
        }
    }

    fn prefixed_key<K: BinaryKey + ?Sized>(&self, key: &K) -> Vec<u8> {
        if let Some(ref prefix) = self.index_id {
            let mut v = vec![0; prefix.size() + key.size()];
            let pos = prefix.write(&mut v);
            key.write(&mut v[pos..]);
            v
        } else {
            let mut v = vec![0; key.size()];
            key.write(&mut v);
            v
        }
    }

    /// Returns a value of *any* type corresponding to the key of *any* type.
    pub fn get<K, V>(&self, key: &K) -> Option<V>
    where
        K: BinaryKey + ?Sized,
        V: BinaryValue,
    {
        self.view
            .as_ref()
            .get(&self.name, &self.prefixed_key(key))
            .map(get_value)
    }

    /// Returns `true` if the index contains a value of *any* type for the specified key of
    /// *any* type.
    pub fn contains<K>(&self, key: &K) -> bool
    where
        K: BinaryKey + ?Sized,
    {
        self.view
            .as_ref()
            .contains(&self.name, &self.prefixed_key(key))
    }

    /// Returns an iterator over the entries of the index in ascending order. The iterator element
    /// type is *any* key-value pair. An argument `subprefix` allows specifying a subset of keys
    /// for iteration.
    pub fn iter<P, K, V>(&self, subprefix: &P) -> BaseIndexIter<K, V>
    where
        P: BinaryKey,
        K: BinaryKey,
        V: BinaryValue,
    {
        let iter_prefix = self.prefixed_key(subprefix);
        BaseIndexIter {
            base_iter: self.view.as_ref().iter(&self.name, &iter_prefix),
            base_prefix_len: self.index_id.as_ref().map_or(0, |p| p.len()),
            index_id: iter_prefix,
            ended: false,
            _k: PhantomData,
            _v: PhantomData,
        }
    }

    /// Returns an iterator over the entries of the index in ascending order starting from the
    /// specified key. The iterator element type is *any* key-value pair. An argument `subprefix`
    /// allows specifying a subset of iteration.
    pub fn iter_from<P, F, K, V>(&self, subprefix: &P, from: &F) -> BaseIndexIter<K, V>
    where
        P: BinaryKey,
        F: BinaryKey + ?Sized,
        K: BinaryKey,
        V: BinaryValue,
    {
        let iter_prefix = self.prefixed_key(subprefix);
        let iter_from = self.prefixed_key(from);
        BaseIndexIter {
            base_iter: self.view.as_ref().iter(&self.name, &iter_from),
            base_prefix_len: self.index_id.as_ref().map_or(0, |p| p.len()),
            index_id: iter_prefix,
            ended: false,
            _k: PhantomData,
            _v: PhantomData,
        }
    }
}

impl<'a> BaseIndex<&'a mut Fork> {
    fn set_index_type(&mut self) {
        if !self.is_mutable {
            indexes_metadata::set_index_type(
                &self.name,
                self.index_type,
                self.is_family,
                &mut self.view,
            );
            self.is_mutable = true;
        }
    }

    /// Inserts the key-value pair into the index. Both key and value may be of *any* types.
    pub fn put<K, V>(&mut self, key: &K, value: V)
    where
        K: BinaryKey,
        V: BinaryValue,
    {
        self.set_index_type();
        let key = self.prefixed_key(key);
        self.view.put(&self.name, key, value.into_bytes());
    }

    /// Removes the key of *any* type from the index.
    pub fn remove<K>(&mut self, key: &K)
    where
        K: BinaryKey + ?Sized,
    {
        self.set_index_type();
        let key = self.prefixed_key(key);
        self.view.remove(&self.name, key);
    }

    /// Clears the index, removing entries with keys that start with a prefix or all entries
    /// if `prefix` is `None`.
    ///
    /// # Notes
    ///
    /// Currently this method is not optimized to delete a large set of data. During the execution of
    /// this method the amount of allocated memory is linearly dependent on the number of elements
    /// in the index.
    pub fn clear(&mut self) {
        self.set_index_type();
        let prefix = self.index_id.as_ref().map(Vec::as_slice);
        self.view.remove_by_prefix(&self.name, prefix);
    }
}

impl<'a, K, V> Iterator for BaseIndexIter<'a, K, V>
where
    K: BinaryKey,
    V: BinaryValue,
{
    type Item = (K::Owned, V);

    fn next(&mut self) -> Option<Self::Item> {
        if self.ended {
            return None;
        }
        if let Some((k, v)) = self.base_iter.next() {
            if k.starts_with(&self.index_id) {
                return Some((K::read(&k[self.base_prefix_len..]), get_value(v)));
            }
        }
        self.ended = true;
        None
    }
}

impl<'a, K, V> ::std::fmt::Debug for BaseIndexIter<'a, K, V> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "BaseIndexIter(..)")
    }
}

fn get_value<'a, B, V>(bytes: B) -> V
where
    B: Into<Cow<'a, [u8]>>,
    V: BinaryValue,
{
    let bytes = bytes.into();
    V::from_bytes(bytes).expect("Unable to decode value from bytes, an error occured")
}

/// A function that validates an index name. Allowable characters in name: ASCII characters, digits
/// and underscores.
fn is_valid_name<S: AsRef<str>>(name: S) -> bool {
    name.as_ref().as_bytes().iter().all(|c| match *c {
        48...57 | 65...90 | 97...122 | 95 | 46 => true,
        _ => false,
    })
}

/// Calls the `is_valid_name` function with the given name and panics if it returns `false`.
fn assert_valid_name<S: AsRef<str>>(name: S) {
    if !is_valid_name(name) {
        panic!("Wrong characters using in name. Use: a-zA-Z0-9 and _");
    }
}

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

    #[test]
    fn test_index_name_validator() {
        // spell-checker:disable
        assert!(is_valid_name("index_name"));
        assert!(is_valid_name("_index_name"));
        assert!(is_valid_name("AinDex_name_"));
        assert!(is_valid_name("core.index_name1Z"));
        assert!(is_valid_name("configuration.indeX_1namE"));
        assert!(is_valid_name("1index_Namez"));

        assert!(!is_valid_name("index-name"));
        assert!(!is_valid_name("_index-name"));
        assert!(!is_valid_name("индекс_name_"));
        assert!(!is_valid_name("core.index_имя3"));
        assert!(!is_valid_name("indeX_1namE-"));
        assert!(!is_valid_name("1in!dex_Namez"));
    }

    #[test]
    fn test_check_valid_name() {
        assert_valid_name("valid_name");
    }

    #[test]
    #[should_panic(expected = "Wrong characters using in name. Use: a-zA-Z0-9 and _")]
    fn test_check_invalid_name() {
        assert_valid_name("invalid-name");
    }

    #[test]
    #[should_panic(expected = "Unable to decode value from bytes")]
    fn test_get_value_panic() {
        let wrong_buf = vec![0_u8; 31];
        let _hash: exonum_crypto::Hash = get_value(wrong_buf);
    }
}
<commit_msg>Comment get_value method.<commit_after>// Copyright 2018 The Exonum Team
//
// 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.

//! An implementation of base index with most common features.
//!
//! The `BaseIndex` structure is not intended for direct use, rather it is the
//! basis for building other types of indices. The given section contains methods
//! related to `BaseIndex` and the iterator over the items of this index.

// spell-checker:ignore subprefix

use std::{borrow::Cow, marker::PhantomData};

use super::{BinaryKey, BinaryValue, Fork, Iter, Snapshot};
use crate::indexes_metadata::{self, IndexType, INDEXES_METADATA_TABLE_NAME};

/// Basic struct for all indices that implements common features.
///
/// This structure is not intended for direct use, rather it is the basis for building other types
/// of indices.
///
/// `BaseIndex` requires that keys should implement the [`BinaryKey`] trait and
/// values should implement the [`BinaryValue`] trait. However, this structure
/// is not bound to specific types and allows the use of *any* types as keys or values.
///
/// [`BinaryKey`]: ../trait.BinaryKey.html
/// [`BinaryValue`]: ../trait.BinaryValue.html
#[derive(Debug)]
pub struct BaseIndex<T> {
    name: String,
    is_family: bool,
    index_id: Option<Vec<u8>>,
    is_mutable: bool,
    index_type: IndexType,
    view: T,
}

/// An iterator over the entries of a `BaseIndex`.
///
/// This struct is created by the [`iter`] or
/// [`iter_from`] method on [`BaseIndex`]. See its documentation for details.
///
/// [`iter`]: struct.BaseIndex.html#method.iter
/// [`iter_from`]: struct.BaseIndex.html#method.iter_from
/// [`BaseIndex`]: struct.BaseIndex.html
pub struct BaseIndexIter<'a, K, V> {
    base_iter: Iter<'a>,
    base_prefix_len: usize,
    index_id: Vec<u8>,
    ended: bool,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
}

impl<T> BaseIndex<T>
where
    T: AsRef<dyn Snapshot>,
{
    /// Creates a new index representation based on the name and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case, only
    /// immutable methods are available. In the second case, both immutable and mutable methods are
    /// available.
    ///
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new<S: AsRef<str>>(index_name: S, index_type: IndexType, view: T) -> Self {
        assert_valid_name(&index_name);

        let is_family = false;
        indexes_metadata::assert_index_type(
            index_name.as_ref(),
            index_type,
            is_family,
            view.as_ref(),
        );

        Self {
            name: index_name.as_ref().to_string(),
            is_family,
            index_id: None,
            is_mutable: false,
            index_type,
            view,
        }
    }

    /// Creates a new index representation based on the family name, index ID inside family
    /// and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case, only
    /// immutable methods are available. In the second case, both immutable and mutable methods are
    /// available.
    ///
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new_in_family<S, P>(family_name: S, index_id: &P, index_type: IndexType, view: T) -> Self
    where
        P: BinaryKey,
        P: ?Sized,
        S: AsRef<str>,
    {
        assert_valid_name(&family_name);

        let is_family = true;
        indexes_metadata::assert_index_type(
            family_name.as_ref(),
            index_type,
            is_family,
            view.as_ref(),
        );

        Self {
            name: family_name.as_ref().to_string(),
            is_family,
            index_id: {
                let mut buf = vec![0; index_id.size()];
                index_id.write(&mut buf);
                Some(buf)
            },
            is_mutable: false,
            index_type,
            view,
        }
    }

    pub(crate) fn indexes_metadata(view: T) -> Self {
        Self {
            name: INDEXES_METADATA_TABLE_NAME.to_string(),
            is_family: false,
            index_id: None,
            is_mutable: true,
            index_type: IndexType::Map,
            view,
        }
    }

    fn prefixed_key<K: BinaryKey + ?Sized>(&self, key: &K) -> Vec<u8> {
        if let Some(ref prefix) = self.index_id {
            let mut v = vec![0; prefix.size() + key.size()];
            let pos = prefix.write(&mut v);
            key.write(&mut v[pos..]);
            v
        } else {
            let mut v = vec![0; key.size()];
            key.write(&mut v);
            v
        }
    }

    /// Returns a value of *any* type corresponding to the key of *any* type.
    pub fn get<K, V>(&self, key: &K) -> Option<V>
    where
        K: BinaryKey + ?Sized,
        V: BinaryValue,
    {
        self.view
            .as_ref()
            .get(&self.name, &self.prefixed_key(key))
            .map(get_value)
    }

    /// Returns `true` if the index contains a value of *any* type for the specified key of
    /// *any* type.
    pub fn contains<K>(&self, key: &K) -> bool
    where
        K: BinaryKey + ?Sized,
    {
        self.view
            .as_ref()
            .contains(&self.name, &self.prefixed_key(key))
    }

    /// Returns an iterator over the entries of the index in ascending order. The iterator element
    /// type is *any* key-value pair. An argument `subprefix` allows specifying a subset of keys
    /// for iteration.
    pub fn iter<P, K, V>(&self, subprefix: &P) -> BaseIndexIter<K, V>
    where
        P: BinaryKey,
        K: BinaryKey,
        V: BinaryValue,
    {
        let iter_prefix = self.prefixed_key(subprefix);
        BaseIndexIter {
            base_iter: self.view.as_ref().iter(&self.name, &iter_prefix),
            base_prefix_len: self.index_id.as_ref().map_or(0, |p| p.len()),
            index_id: iter_prefix,
            ended: false,
            _k: PhantomData,
            _v: PhantomData,
        }
    }

    /// Returns an iterator over the entries of the index in ascending order starting from the
    /// specified key. The iterator element type is *any* key-value pair. An argument `subprefix`
    /// allows specifying a subset of iteration.
    pub fn iter_from<P, F, K, V>(&self, subprefix: &P, from: &F) -> BaseIndexIter<K, V>
    where
        P: BinaryKey,
        F: BinaryKey + ?Sized,
        K: BinaryKey,
        V: BinaryValue,
    {
        let iter_prefix = self.prefixed_key(subprefix);
        let iter_from = self.prefixed_key(from);
        BaseIndexIter {
            base_iter: self.view.as_ref().iter(&self.name, &iter_from),
            base_prefix_len: self.index_id.as_ref().map_or(0, |p| p.len()),
            index_id: iter_prefix,
            ended: false,
            _k: PhantomData,
            _v: PhantomData,
        }
    }
}

impl<'a> BaseIndex<&'a mut Fork> {
    fn set_index_type(&mut self) {
        if !self.is_mutable {
            indexes_metadata::set_index_type(
                &self.name,
                self.index_type,
                self.is_family,
                &mut self.view,
            );
            self.is_mutable = true;
        }
    }

    /// Inserts the key-value pair into the index. Both key and value may be of *any* types.
    pub fn put<K, V>(&mut self, key: &K, value: V)
    where
        K: BinaryKey,
        V: BinaryValue,
    {
        self.set_index_type();
        let key = self.prefixed_key(key);
        self.view.put(&self.name, key, value.into_bytes());
    }

    /// Removes the key of *any* type from the index.
    pub fn remove<K>(&mut self, key: &K)
    where
        K: BinaryKey + ?Sized,
    {
        self.set_index_type();
        let key = self.prefixed_key(key);
        self.view.remove(&self.name, key);
    }

    /// Clears the index, removing entries with keys that start with a prefix or all entries
    /// if `prefix` is `None`.
    ///
    /// # Notes
    ///
    /// Currently this method is not optimized to delete a large set of data. During the execution of
    /// this method the amount of allocated memory is linearly dependent on the number of elements
    /// in the index.
    pub fn clear(&mut self) {
        self.set_index_type();
        let prefix = self.index_id.as_ref().map(Vec::as_slice);
        self.view.remove_by_prefix(&self.name, prefix);
    }
}

impl<'a, K, V> Iterator for BaseIndexIter<'a, K, V>
where
    K: BinaryKey,
    V: BinaryValue,
{
    type Item = (K::Owned, V);

    fn next(&mut self) -> Option<Self::Item> {
        if self.ended {
            return None;
        }
        if let Some((k, v)) = self.base_iter.next() {
            if k.starts_with(&self.index_id) {
                return Some((K::read(&k[self.base_prefix_len..]), get_value(v)));
            }
        }
        self.ended = true;
        None
    }
}

impl<'a, K, V> ::std::fmt::Debug for BaseIndexIter<'a, K, V> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "BaseIndexIter(..)")
    }
}

/// Decodes given bytes into the given value.
/// This function panics if the given value can not be decoded from the given buffer.
fn get_value<'a, B, V>(bytes: B) -> V
where
    B: Into<Cow<'a, [u8]>>,
    V: BinaryValue,
{
    let bytes = bytes.into();
    V::from_bytes(bytes).expect("Unable to decode value from bytes, an error occured")
}

/// A function that validates an index name. Allowable characters in name: ASCII characters, digits
/// and underscores.
fn is_valid_name<S: AsRef<str>>(name: S) -> bool {
    name.as_ref().as_bytes().iter().all(|c| match *c {
        48...57 | 65...90 | 97...122 | 95 | 46 => true,
        _ => false,
    })
}

/// Calls the `is_valid_name` function with the given name and panics if it returns `false`.
fn assert_valid_name<S: AsRef<str>>(name: S) {
    if !is_valid_name(name) {
        panic!("Wrong characters using in name. Use: a-zA-Z0-9 and _");
    }
}

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

    #[test]
    fn test_index_name_validator() {
        // spell-checker:disable
        assert!(is_valid_name("index_name"));
        assert!(is_valid_name("_index_name"));
        assert!(is_valid_name("AinDex_name_"));
        assert!(is_valid_name("core.index_name1Z"));
        assert!(is_valid_name("configuration.indeX_1namE"));
        assert!(is_valid_name("1index_Namez"));

        assert!(!is_valid_name("index-name"));
        assert!(!is_valid_name("_index-name"));
        assert!(!is_valid_name("индекс_name_"));
        assert!(!is_valid_name("core.index_имя3"));
        assert!(!is_valid_name("indeX_1namE-"));
        assert!(!is_valid_name("1in!dex_Namez"));
    }

    #[test]
    fn test_check_valid_name() {
        assert_valid_name("valid_name");
    }

    #[test]
    #[should_panic(expected = "Wrong characters using in name. Use: a-zA-Z0-9 and _")]
    fn test_check_invalid_name() {
        assert_valid_name("invalid-name");
    }

    #[test]
    #[should_panic(expected = "Unable to decode value from bytes")]
    fn test_get_value_panic() {
        let wrong_buf = vec![0_u8; 31];
        let _hash: exonum_crypto::Hash = get_value(wrong_buf);
    }
}
<|endoftext|>


<commit_before>import std::vec;
import std::uint;
import std::str;
import std::term;
import std::io;
import std::option;
import std::option::some;
import std::option::none;

type filename = str;

type file_pos = {ch: uint, byte: uint};

/* A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 */
type filemap =
    @{name: filename, start_pos: file_pos, mutable lines: [file_pos]};

type codemap = @{mutable files: [filemap]};

type loc = {filename: filename, line: uint, col: uint};

fn new_codemap() -> codemap { ret @{mutable files: []}; }

fn new_filemap(filename: filename, start_pos_ch: uint, start_pos_byte: uint)
   -> filemap {
    ret @{name: filename,
          start_pos: {ch: start_pos_ch, byte: start_pos_byte},
          mutable lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
}

fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
    file.lines += [{ch: chpos, byte: byte_pos}];
}

type lookup_fn = fn(file_pos) -> uint;

fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
    let a = 0u;
    let b = vec::len(map.files);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
    }
    let f = map.files[a];
    a = 0u;
    b = vec::len(f.lines);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
    }
    ret {filename: f.name, line: a + 1u, col: pos - lookup(f.lines[a])};
}

fn lookup_char_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.byte; }
    ret lookup_pos(map, pos, lookup);
}

tag opt_span {
     //hack (as opposed to option::t), to make `span` compile
    os_none;
    os_some(@span);
}
type span = {lo: uint, hi: uint, expanded_from: opt_span};

fn span_to_str(sp: &span, cm: &codemap) -> str {
    let cur = sp;
    let res = "";
    let prev_file = none;
    while true {
        let lo = lookup_char_pos(cm, cur.lo);
        let hi = lookup_char_pos(cm, cur.hi);
        res +=
            #fmt["%s:%u:%u:%u:%u",
                 if some(lo.filename) == prev_file {
                     "-"
                 } else { lo.filename }, lo.line, lo.col, hi.line, hi.col];
        alt cur.expanded_from {
          os_none. { break; }
          os_some(new_sp) {
            cur = *new_sp;
            prev_file = some(lo.filename);
            res += "<<";
          }
        }
    }

    ret res;
}

fn emit_diagnostic(sp: &option::t<span>, msg: &str, kind: &str, color: u8,
                   cm: &codemap) {
    let ss = "<input>:0:0:0:0";
    let maybe_lines: option::t<@file_lines> = none;
    alt sp {
      some(ssp) {
        ss = span_to_str(ssp, cm);
        maybe_lines = some(span_to_lines(ssp, cm));
      }
      none. { }
    }
    io::stdout().write_str(ss + ": ");
    if term::color_supported() {
        term::fg(io::stdout().get_buf_writer(), color);
    }
    io::stdout().write_str(#fmt["%s:", kind]);
    if term::color_supported() { term::reset(io::stdout().get_buf_writer()); }
    io::stdout().write_str(#fmt[" %s\n", msg]);

    maybe_highlight_lines(sp, cm, maybe_lines);
}

fn maybe_highlight_lines(sp: &option::t<span>, cm: &codemap,
                         maybe_lines: option::t<@file_lines>) {

    alt maybe_lines {
      some(lines) {
        // If we're not looking at a real file then we can't re-open it to
        // pull out the lines
        if lines.name == "-" { ret; }

        // FIXME: reading in the entire file is the worst possible way to
        //        get access to the necessary lines.
        let file = io::read_whole_file_str(lines.name);
        let fm = get_filemap(cm, lines.name);

        // arbitrarily only print up to six lines of the error
        let max_lines = 6u;
        let elided = false;
        let display_lines = lines.lines;
        if vec::len(display_lines) > max_lines {
            display_lines = vec::slice(display_lines, 0u, max_lines);
            elided = true;
        }
        // Print the offending lines
        for line: uint in display_lines {
            io::stdout().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
            let s = get_line(fm, line as int, file);
            if !str::ends_with(s, "\n") { s += "\n"; }
            io::stdout().write_str(s);
        }
        if elided {
            let last_line = display_lines[vec::len(display_lines) - 1u];
            let s = #fmt["%s:%u ", fm.name, last_line + 1u];
            let indent = str::char_len(s);
            let out = "";
            while indent > 0u { out += " "; indent -= 1u; }
            out += "...\n";
            io::stdout().write_str(out);
        }

        // If there's one line at fault we can easily point to the problem
        if vec::len(lines.lines) == 1u {
            let lo = lookup_char_pos(cm, option::get(sp).lo);
            let digits = 0u;
            let num = lines.lines[0] / 10u;

            // how many digits must be indent past?
            while num > 0u { num /= 10u; digits += 1u; }

            // indent past |name:## | and the 0-offset column location
            let left = str::char_len(fm.name) + digits + lo.col + 3u;
            let s = "";
            while left > 0u { str::push_char(s, ' '); left -= 1u; }

            s += "^";
            let hi = lookup_char_pos(cm, option::get(sp).hi);
            if hi.col != lo.col {
                // the ^ already takes up one space
                let width = hi.col - lo.col - 1u;
                while width > 0u { str::push_char(s, '~'); width -= 1u; }
            }
            io::stdout().write_str(s + "\n");
        }
      }
      _ { }
    }
}

fn emit_warning(sp: &option::t<span>, msg: &str, cm: &codemap) {
    emit_diagnostic(sp, msg, "warning", 11u8, cm);
}
fn emit_error(sp: &option::t<span>, msg: &str, cm: &codemap) {
    emit_diagnostic(sp, msg, "error", 9u8, cm);
}
fn emit_note(sp: &option::t<span>, msg: &str, cm: &codemap) {
    emit_diagnostic(sp, msg, "note", 10u8, cm);
}

type file_lines = {name: str, lines: [uint]};

fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    let lines = [];
    for each i: uint in uint::range(lo.line - 1u, hi.line as uint) {
        lines += [i];
    }
    ret @{name: lo.filename, lines: lines};
}

fn get_line(fm: filemap, line: int, file: &str) -> str {
    let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
    let end: uint;
    if line as uint < vec::len(fm.lines) - 1u {
        end = fm.lines[line + 1].byte - fm.start_pos.byte;
    } else {
        // If we're not done parsing the file, we're at the limit of what's
        // parsed. If we just slice the rest of the string, we'll print out
        // the remainder of the file, which is undesirable.
        end = str::byte_len(file);
        let rest = str::slice(file, begin, end);
        let newline = str::index(rest, '\n' as u8);
        if newline != -1 { end = begin + (newline as uint); }
    }
    ret str::slice(file, begin, end);
}

fn get_filemap(cm: codemap, filename: str) -> filemap {
    for fm: filemap in cm.files { if fm.name == filename { ret fm; } }
    //XXjdm the following triggers a mismatched type bug
    //      (or expected function, found _|_)
    fail; // ("asking for " + filename + " which we don't know about");
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>Output error spans that don't confuse emacs compilation mode. Closes #845<commit_after>import std::vec;
import std::uint;
import std::str;
import std::term;
import std::io;
import std::option;
import std::option::some;
import std::option::none;

type filename = str;

type file_pos = {ch: uint, byte: uint};

/* A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 */
type filemap =
    @{name: filename, start_pos: file_pos, mutable lines: [file_pos]};

type codemap = @{mutable files: [filemap]};

type loc = {filename: filename, line: uint, col: uint};

fn new_codemap() -> codemap { ret @{mutable files: []}; }

fn new_filemap(filename: filename, start_pos_ch: uint, start_pos_byte: uint)
   -> filemap {
    ret @{name: filename,
          start_pos: {ch: start_pos_ch, byte: start_pos_byte},
          mutable lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
}

fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
    file.lines += [{ch: chpos, byte: byte_pos}];
}

type lookup_fn = fn(file_pos) -> uint;

fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
    let a = 0u;
    let b = vec::len(map.files);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
    }
    let f = map.files[a];
    a = 0u;
    b = vec::len(f.lines);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
    }
    ret {filename: f.name, line: a + 1u, col: pos - lookup(f.lines[a])};
}

fn lookup_char_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.byte; }
    ret lookup_pos(map, pos, lookup);
}

tag opt_span {
     //hack (as opposed to option::t), to make `span` compile
    os_none;
    os_some(@span);
}
type span = {lo: uint, hi: uint, expanded_from: opt_span};

fn span_to_str(sp: &span, cm: &codemap) -> str {
    let cur = sp;
    let res = "";
    let prev_file = none;
    while true {
        let lo = lookup_char_pos(cm, cur.lo);
        let hi = lookup_char_pos(cm, cur.hi);
        res +=
            #fmt["%s:%u:%u: %u:%u",
                 if some(lo.filename) == prev_file {
                     "-"
                 } else { lo.filename }, lo.line, lo.col, hi.line, hi.col];
        alt cur.expanded_from {
          os_none. { break; }
          os_some(new_sp) {
            cur = *new_sp;
            prev_file = some(lo.filename);
            res += "<<";
          }
        }
    }

    ret res;
}

fn emit_diagnostic(sp: &option::t<span>, msg: &str, kind: &str, color: u8,
                   cm: &codemap) {
    let ss = "<input>:0:0:0:0";
    let maybe_lines: option::t<@file_lines> = none;
    alt sp {
      some(ssp) {
        ss = span_to_str(ssp, cm);
        maybe_lines = some(span_to_lines(ssp, cm));
      }
      none. { }
    }
    io::stdout().write_str(ss + " ");
    if term::color_supported() {
        term::fg(io::stdout().get_buf_writer(), color);
    }
    io::stdout().write_str(#fmt["%s:", kind]);
    if term::color_supported() { term::reset(io::stdout().get_buf_writer()); }
    io::stdout().write_str(#fmt[" %s\n", msg]);

    maybe_highlight_lines(sp, cm, maybe_lines);
}

fn maybe_highlight_lines(sp: &option::t<span>, cm: &codemap,
                         maybe_lines: option::t<@file_lines>) {

    alt maybe_lines {
      some(lines) {
        // If we're not looking at a real file then we can't re-open it to
        // pull out the lines
        if lines.name == "-" { ret; }

        // FIXME: reading in the entire file is the worst possible way to
        //        get access to the necessary lines.
        let file = io::read_whole_file_str(lines.name);
        let fm = get_filemap(cm, lines.name);

        // arbitrarily only print up to six lines of the error
        let max_lines = 6u;
        let elided = false;
        let display_lines = lines.lines;
        if vec::len(display_lines) > max_lines {
            display_lines = vec::slice(display_lines, 0u, max_lines);
            elided = true;
        }
        // Print the offending lines
        for line: uint in display_lines {
            io::stdout().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
            let s = get_line(fm, line as int, file);
            if !str::ends_with(s, "\n") { s += "\n"; }
            io::stdout().write_str(s);
        }
        if elided {
            let last_line = display_lines[vec::len(display_lines) - 1u];
            let s = #fmt["%s:%u ", fm.name, last_line + 1u];
            let indent = str::char_len(s);
            let out = "";
            while indent > 0u { out += " "; indent -= 1u; }
            out += "...\n";
            io::stdout().write_str(out);
        }

        // If there's one line at fault we can easily point to the problem
        if vec::len(lines.lines) == 1u {
            let lo = lookup_char_pos(cm, option::get(sp).lo);
            let digits = 0u;
            let num = lines.lines[0] / 10u;

            // how many digits must be indent past?
            while num > 0u { num /= 10u; digits += 1u; }

            // indent past |name:## | and the 0-offset column location
            let left = str::char_len(fm.name) + digits + lo.col + 3u;
            let s = "";
            while left > 0u { str::push_char(s, ' '); left -= 1u; }

            s += "^";
            let hi = lookup_char_pos(cm, option::get(sp).hi);
            if hi.col != lo.col {
                // the ^ already takes up one space
                let width = hi.col - lo.col - 1u;
                while width > 0u { str::push_char(s, '~'); width -= 1u; }
            }
            io::stdout().write_str(s + "\n");
        }
      }
      _ { }
    }
}

fn emit_warning(sp: &option::t<span>, msg: &str, cm: &codemap) {
    emit_diagnostic(sp, msg, "warning", 11u8, cm);
}
fn emit_error(sp: &option::t<span>, msg: &str, cm: &codemap) {
    emit_diagnostic(sp, msg, "error", 9u8, cm);
}
fn emit_note(sp: &option::t<span>, msg: &str, cm: &codemap) {
    emit_diagnostic(sp, msg, "note", 10u8, cm);
}

type file_lines = {name: str, lines: [uint]};

fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    let lines = [];
    for each i: uint in uint::range(lo.line - 1u, hi.line as uint) {
        lines += [i];
    }
    ret @{name: lo.filename, lines: lines};
}

fn get_line(fm: filemap, line: int, file: &str) -> str {
    let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
    let end: uint;
    if line as uint < vec::len(fm.lines) - 1u {
        end = fm.lines[line + 1].byte - fm.start_pos.byte;
    } else {
        // If we're not done parsing the file, we're at the limit of what's
        // parsed. If we just slice the rest of the string, we'll print out
        // the remainder of the file, which is undesirable.
        end = str::byte_len(file);
        let rest = str::slice(file, begin, end);
        let newline = str::index(rest, '\n' as u8);
        if newline != -1 { end = begin + (newline as uint); }
    }
    ret str::slice(file, begin, end);
}

fn get_filemap(cm: codemap, filename: str) -> filemap {
    for fm: filemap in cm.files { if fm.name == filename { ret fm; } }
    //XXjdm the following triggers a mismatched type bug
    //      (or expected function, found _|_)
    fail; // ("asking for " + filename + " which we don't know about");
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>pub use self::os::{iconv_t};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn iconv_open<T: ::NTStr, U: ::NTStr>(to: &T, from: &U) -> iconv_t {
    extern { fn iconv_open(to: *const ::char_t, from: *const ::char_t) -> iconv_t; }
    unsafe { iconv_open(to.as_ptr(), from.as_ptr()) }
}

pub fn iconv_close(cd: iconv_t) -> ::int_t {
    extern { fn iconv_close(cd: iconv_t) -> ::int_t; }
    unsafe { iconv_close(cd) }
}

extern "C" {
    pub fn iconv(cd: iconv_t, inbuf: *mut *mut ::char_t,
                 inbytesleft: *mut ::size_t, outbuf: *mut *mut ::char_t,
                 outbytesleft: *mut ::size_t) -> ::size_t;
}
<commit_msg>iconv.h<commit_after>pub use self::os::{iconv_t};

use {NTStr, char_t, int_t, size_t};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn iconv_open<T: NTStr, U: NTStr>(to: &T, from: &U) -> iconv_t {
    extern { fn iconv_open(to: *const char_t, from: *const char_t) -> iconv_t; }
    unsafe { iconv_open(to.as_ptr(), from.as_ptr()) }
}

pub fn iconv_close(cd: iconv_t) -> int_t {
    extern { fn iconv_close(cd: iconv_t) -> int_t; }
    unsafe { iconv_close(cd) }
}

extern "C" {
    pub fn iconv(cd: iconv_t, inbuf: *mut *mut char_t,
                 inbytesleft: *mut size_t, outbuf: *mut *mut char_t,
                 outbytesleft: *mut size_t) -> size_t;
}
<|endoftext|>


<commit_before>use game_state::{GameState, GameMode};
use command::{CommandProcessor, HelpInfo};
use items::Item;
use items::Item::*;

use self::InventoryCommand::*;

pub enum InventoryCommand {
  Buy(Item),
  Leave,
}

impl CommandProcessor<InventoryCommand> for InventoryCommand {
  fn prompt() -> &'static str { "What do you want to buy? " }

  fn get_help() -> Vec<HelpInfo> {
    let buy = |item: Item| format!("buy {} (${})", item, item.price());

    HelpInfo::list(vec![
      ('1', buy(Torch)),
      ('2', buy(Axe)),
      ('3', buy(Sword)),
      ('4', buy(Food)),
      ('5', buy(Amulet)),
      ('6', buy(Armor)),
      ('0', String::from("continue adventure")),
    ])
  }

  fn from_char(c: char) -> Option<InventoryCommand> {
    match c {
      '1' => Some(Buy(Torch)),
      '2' => Some(Buy(Axe)),
      '3' => Some(Buy(Sword)),
      '4' => Some(Buy(Food)),
      '5' => Some(Buy(Amulet)),
      '6' => Some(Buy(Armor)),
      _ => Some(Leave),
    }
  }
}

impl<'a> GameState<'a> {
  pub fn tick_inventory_mode(&mut self) {
    if self.show_desc {
      println!("Provisions & inventory\n");
      self.print_wealth();
      println!("");
      InventoryCommand::show_help();
      println!("");
      self.show_desc = false;
    }

    if let Some(cmd) = InventoryCommand::get() {
      match cmd {
        Buy(item) => {
          let price = item.price();
          if match item {
            Torch => self.light,
            Axe => self.axe,
            Sword => self.sword,
            Food => false,
            Amulet => self.amulet,
            Armor => self.suit,
          } {
            println!("You already own {}.", item);
          } else if self.wealth < price {
            self.accuse_player_of_cheating();
          } else {
            self.wealth -= price;
            println!("You bought {}.", item);
            self.print_wealth();
            match item {
              Torch => self.light = true,
              Axe => self.axe = true,
              Sword => self.sword = true,
              Food => self.food += 1,
              Amulet => self.amulet = true,
              Armor => self.suit = true,
            }
          }
          println!("");
        },
        Leave => { self.set_mode(GameMode::Primary) },
      }
    }
  }
}
<commit_msg>only leave inventory if user explicitly exits.<commit_after>use game_state::{GameState, GameMode};
use command::{CommandProcessor, HelpInfo};
use items::Item;
use items::Item::*;

use self::InventoryCommand::*;

pub enum InventoryCommand {
  Buy(Item),
  Leave,
}

impl CommandProcessor<InventoryCommand> for InventoryCommand {
  fn prompt() -> &'static str { "What do you want to buy? " }

  fn get_help() -> Vec<HelpInfo> {
    let buy = |item: Item| format!("buy {} (${})", item, item.price());

    HelpInfo::list(vec![
      ('1', buy(Torch)),
      ('2', buy(Axe)),
      ('3', buy(Sword)),
      ('4', buy(Food)),
      ('5', buy(Amulet)),
      ('6', buy(Armor)),
      ('0', String::from("continue adventure")),
    ])
  }

  fn from_char(c: char) -> Option<InventoryCommand> {
    match c {
      '1' => Some(Buy(Torch)),
      '2' => Some(Buy(Axe)),
      '3' => Some(Buy(Sword)),
      '4' => Some(Buy(Food)),
      '5' => Some(Buy(Amulet)),
      '6' => Some(Buy(Armor)),
      '0' | 'q' => Some(Leave),
      _ => None,
    }
  }
}

impl<'a> GameState<'a> {
  pub fn tick_inventory_mode(&mut self) {
    if self.show_desc {
      println!("Provisions & inventory\n");
      self.print_wealth();
      println!("");
      InventoryCommand::show_help();
      println!("");
      self.show_desc = false;
    }

    if let Some(cmd) = InventoryCommand::get() {
      match cmd {
        Buy(item) => {
          let price = item.price();
          if match item {
            Torch => self.light,
            Axe => self.axe,
            Sword => self.sword,
            Food => false,
            Amulet => self.amulet,
            Armor => self.suit,
          } {
            println!("You already own {}.", item);
          } else if self.wealth < price {
            self.accuse_player_of_cheating();
          } else {
            self.wealth -= price;
            println!("You bought {}.", item);
            self.print_wealth();
            match item {
              Torch => self.light = true,
              Axe => self.axe = true,
              Sword => self.sword = true,
              Food => self.food += 1,
              Amulet => self.amulet = true,
              Armor => self.suit = true,
            }
          }
          println!("");
        },
        Leave => { self.set_mode(GameMode::Primary) },
      }
    }
  }
}
<|endoftext|>


<commit_before>////////////////
// INTERFACES //
////////////////

use errors::*;

/// Address type/size.
/// Just a simple alias to usize for easier-to-read code. (In my opinion, obviously.)
/// Originally, I wanted to make it use generics,
/// but that got messy really quick.
pub type Addr = usize;

/// Byte.
/// Convenience alias.
pub type Byte = u8;

/// Simple trait for a finite memory block.
pub trait MemoryBlock {
    /// Get the block's accessible size.
    /// Simply the highest address,
    /// NOT the number of addresses.
    fn get_size(&self) -> Addr;

    /// Set a byte at address.
    fn set(&mut self, Addr, Byte) -> Result<(), Error>;

    /// Get a byte at address.
    /// Returns `Ok(X)` on success, where X will be the byte.
    fn get(&self, Addr) -> Result<Byte, Error>;

    /// Delete data at address.
    /// May allow the block to efficiently delete it, marking it as unused.
    /// This could allow the block to do wear leveling, for example.
    fn delete(&mut self, from: Addr, to: Addr) -> Result<(), Error> {
        if from == to {
            return self.set(from, 0);
        }
        for i in from..to {
            self.set(i, 0)?;
        }
        self.set(to, 0)
    }

    /// Flush writes out.
    /// In case it does any form of caching, calling this method
    /// ensures it has written all the data it needs to write.
    /// Or, well, it fails otherwise.
    fn flush(&mut self) -> Result<(), Error> {
        Ok(())
    }
}

/// Simple `new(size)` trait for backends.
// For convenience, mostly.
pub trait MemoryCreator<T> {
    /// Returns a `MemoryBlock` of size `size`.
    /// `size` being the highest address,
    /// NOT number of addresses.
    fn new(size: Addr) -> T;
}

/// Trait for a new function that wraps
/// another memory block, returning one itself.
///
/// Useful for invalid access checkers, debuggers, etc....
pub trait MemoryMiddlewareCreator<T> {
    fn new<M: MemoryBlock>(Box<M>) -> T;
}
<commit_msg>Better error information in default delete implementation.<commit_after>////////////////
// INTERFACES //
////////////////

use errors::*;

/// Address type/size.
/// Just a simple alias to usize for easier-to-read code. (In my opinion, obviously.)
/// Originally, I wanted to make it use generics,
/// but that got messy really quick.
pub type Addr = usize;

/// Byte.
/// Convenience alias.
pub type Byte = u8;

/// Simple trait for a finite memory block.
pub trait MemoryBlock {
    /// Get the block's accessible size.
    /// Simply the highest address,
    /// NOT the number of addresses.
    fn get_size(&self) -> Addr;

    /// Set a byte at address.
    fn set(&mut self, Addr, Byte) -> Result<(), Error>;

    /// Get a byte at address.
    /// Returns `Ok(X)` on success, where X will be the byte.
    fn get(&self, Addr) -> Result<Byte, Error>;

    /// Delete data at address.
    /// May allow the block to efficiently delete it, marking it as unused.
    /// This could allow the block to do wear leveling, for example.
    fn delete(&mut self, from: Addr, to: Addr) -> Result<(), Error> {
        if from == to {
            self.set(from, 0).chain_err(|| format!("failure to delete {:#X}", from))?;
        }
        for i in from..to {
            self.set(i, 0).chain_err(|| format!("failure to delete byte {} in {:#X}-{:#X}", i-from, from, to))?;
        }
        self.set(to, 0).chain_err(|| format!("failure to delete {:#X}", to))
    }

    /// Flush writes out.
    /// In case it does any form of caching, calling this method
    /// ensures it has written all the data it needs to write.
    /// Or, well, it fails otherwise.
    fn flush(&mut self) -> Result<(), Error> {
        Ok(())
    }
}

/// Simple `new(size)` trait for backends.
// For convenience, mostly.
pub trait MemoryCreator<T> {
    /// Returns a `MemoryBlock` of size `size`.
    /// `size` being the highest address,
    /// NOT number of addresses.
    fn new(size: Addr) -> T;
}

/// Trait for a new function that wraps
/// another memory block, returning one itself.
///
/// Useful for invalid access checkers, debuggers, etc....
pub trait MemoryMiddlewareCreator<T> {
    fn new<M: MemoryBlock>(Box<M>) -> T;
}
<|endoftext|>


<commit_before>use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    pub fn exists(&self) -> bool {
        let pb : PathBuf = self.clone().into();
        pb.exists()
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn is_dir(&self) -> bool {
        false
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        let mut base = self.base.unwrap_or(PathBuf::from("/"));
        base.push(self.id);
        base
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<commit_msg>Remove Into<PathBuf> for StoreId<commit_after>use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    pub fn exists(&self) -> bool {
        let pb : PathBuf = self.clone().into();
        pb.exists()
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn is_dir(&self) -> bool {
        false
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<|endoftext|>