<commit_before>// Copyright 2014 Pierre Talbot (IRCAM)

// 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.

pub use compile_error::*;
pub use syntax::parse::token::InternedString;
pub use syntax::ast::*;

use syntax::codemap::DUMMY_SP;
use std::rc::Rc;

#[deriving(Clone)]
pub struct AttributeValue<T>
{
  pub value: Option<T>,
  pub span: Span,
  duplicate: DuplicateAttribute
}

impl<T: Clone> AttributeValue<T>
{
  pub fn new(duplicate: DuplicateAttribute) -> AttributeValue<T>
  {
    AttributeValue {
      value: None,
      duplicate: duplicate,
      span: DUMMY_SP
    }
  }

  pub fn simple() -> AttributeValue<T>
  {
    AttributeValue::new(DuplicateAttribute::simple(Warn))
  }

  pub fn update(self, cx: &ExtCtxt, value: T, span: Span) -> AttributeValue<T>
  {
    let mut this = self;
    if this.value.is_some() {
      this.duplicate.issue(cx, this.span, span);
    } else {
      this.value = Some(value);
      this.span = span;
    }
    this
  }

  pub fn has_value(&self) -> bool
  {
    self.value.is_some()
  }

  pub fn value_or(&self, default: T) -> T
  {
    match self.value {
      None => default,
      Some(ref value) => value.clone()
    }
  }

  pub fn span(&self) -> Span
  {
    self.span.clone()
  }
}

#[deriving(Clone)]
pub struct AttributeInfo
{
  pub name: InternedString,
  pub desc: &'static str,
  pub model: AttributeModel
}

impl AttributeInfo
{
  pub fn new(name: &'static str, desc: &'static str,
    model: AttributeModel) -> AttributeInfo
  {
    AttributeInfo {
      name: InternedString::new(name),
      desc: desc,
      model: model
    }
  }

  pub fn simple(name: &'static str, desc: &'static str) -> AttributeInfo
  {
    AttributeInfo::new(name, desc, UnitValue(AttributeValue::simple()))
  }

  pub fn update(self, model: AttributeModel) -> AttributeInfo
  {
    let mut this = self;
    this.model = model;
    this
  }

  pub fn plain_value<'a>(&'a self) -> &'a AttributeValue<()>
  {
    match self.model {
      UnitValue(ref v) => v,
      _ => fail!("No plain value for the current attribute.")
    }
  }

  pub fn sub_model<'a>(&'a self) -> &'a AttributeArray
  {
    match self.model {
      SubAttribute(ref array) => array,
      _ => fail!("No sub value for the attribute.")
    }
  }
}

#[deriving(Clone)]
pub enum AttributeModel
{
  UnitValue(AttributeValue<()>),
  KeyValue(AttributeLitModel),
  SubAttribute(AttributeArray)
}

#[deriving(Clone)]
pub enum AttributeLitModel
{
  MLitStr(AttributeValue<(InternedString, StrStyle)>),
  MLitBinary(AttributeValue<Rc<Vec<u8>>>),
  MLitByte(AttributeValue<u8>),
  MLitChar(AttributeValue<char>),
  MLitInt(AttributeValue<(u64, LitIntType)>),
  MLitFloat(AttributeValue<(InternedString, FloatTy)>),
  MLitFloatUnsuffixed(AttributeValue<InternedString>),
  MLitNil(AttributeValue<()>),
  MLitBool(AttributeValue<bool>)
}

pub type AttributeArray = Vec<AttributeInfo>;

pub mod access
{
  pub use super::*;
  pub fn by_name<'a>(array: &'a AttributeArray, name: &'static str) -> &'a AttributeInfo
  {
    let interned = InternedString::new(name);
    for info in array.iter() {
      if info.name == interned {
        return info;
      }
    }
    fail!("Try to get an attribute that doesn't exist.")
  }

  pub fn plain_value<'a>(array: &'a AttributeArray, name: &'static str) -> &'a AttributeValue<()>
  {
    by_name(array, name).plain_value()
  }

  pub fn sub_model<'a>(array: &'a AttributeArray, name: &'static str) -> &'a AttributeArray
  {
    by_name(array, name).sub_model()
  }

  pub fn plain_value_or(array: &AttributeArray, name: &'static str, def: bool) -> bool
  {
    if plain_value(array, name).has_value() {
      true
    } else {
      def
    }
  }
}
// fn attribute_doc(&self)
// {
//   let mut doc = format!("Attribute `#[{}(<attribute list>)]`: {}\n",
//       self.root_name.get(), self.root_desc);
//   for info in self.infos.iter() {
//     doc.add(format!("  * `#[{}({})]`: {}\n",
//       self.root_name.get(), info.name, info.desc));
//   }
//   self.cx.parse_sess.span_diagnostic.handler.note(doc.as_slice());
// }

pub struct AttributeMerger<'a>
{
  cx: &'a ExtCtxt<'a>,
  duplicate: DuplicateAttribute
}

impl<'a> AttributeMerger<'a>
{
  pub fn new(cx: &'a ExtCtxt, duplicate: DuplicateAttribute) -> AttributeMerger<'a>
  {
    AttributeMerger {
      cx: cx,
      duplicate: duplicate
    }
  }

  pub fn merge(&self, info: AttributeInfo, info2: AttributeInfo) -> AttributeInfo
  {
    assert!(info.name == info2.name);
    let mut info = info;
    info.model = match (info.model, info2.model) {
      (UnitValue(val), UnitValue(val2)) => UnitValue(self.merge_value(val, val2)),
      (KeyValue(lit), KeyValue(lit2)) => KeyValue(self.merge_lit(lit, lit2)),
      (SubAttribute(sub), SubAttribute(sub2)) => SubAttribute(self.merge_sub_attr(sub, sub2)),
      _ => fail!("Mismatch between attribute models during merging.")
    };
    info
  }

  fn merge_value<T>(&self, val: AttributeValue<T>, val2: AttributeValue<T>) -> AttributeValue<T>
  {
    match (&val.value, &val2.value) {
      (&None, _) => val2,
      (_, &None) => val,
      (&Some(_), &Some(_)) => {
        self.duplicate.issue(self.cx, val.span, val2.span);
        val
      }
    }
  }

  fn merge_lit(&self, lit: AttributeLitModel, lit2: AttributeLitModel) -> AttributeLitModel
  {
    match (lit, lit2) {
      (MLitStr(val), MLitStr(val2)) => MLitStr(self.merge_value(val, val2)),
      (MLitBinary(val), MLitBinary(val2)) => MLitBinary(self.merge_value(val, val2)),
      (MLitByte(val), MLitByte(val2)) => MLitByte(self.merge_value(val, val2)),
      (MLitChar(val), MLitChar(val2)) => MLitChar(self.merge_value(val, val2)),
      (MLitInt(val), MLitInt(val2)) => MLitInt(self.merge_value(val, val2)),
      (MLitFloat(val), MLitFloat(val2)) => MLitFloat(self.merge_value(val, val2)),
      (MLitFloatUnsuffixed(val), MLitFloatUnsuffixed(val2)) => MLitFloatUnsuffixed(self.merge_value(val, val2)),
      (MLitNil(val), MLitNil(val2)) => MLitNil(self.merge_value(val, val2)),
      (MLitBool(val), MLitBool(val2)) => MLitBool(self.merge_value(val, val2)),
      _ => fail!("Mismatch between attribute models during merging.")
    }
  }

  fn merge_sub_attr(&self, sub1: AttributeArray, sub2: AttributeArray) -> AttributeArray
  {
    assert!(sub1.len() == sub2.len());
    sub1.move_iter()
      .zip(sub2.move_iter())
      .map(|(info, info2)| self.merge(info, info2))
      .collect()
  }
}

impl AttributeLitModel
{
  pub fn to_lit_printer(&self) -> LitTypePrinter
  {
    match *self {
      MLitStr(_) => PLitStr,
      MLitBinary(_) => PLitBinary,
      MLitByte(_) => PLitByte,
      MLitChar(_) => PLitChar,
      MLitInt(_) => PLitInt,
      MLitFloat(_) => PLitFloat,
      MLitFloatUnsuffixed(_) => PLitFloatUnsuffixed,
      MLitNil(_) => PLitNil,
      MLitBool(_) => PLitBool
    }
  }
}

pub fn lit_to_lit_printer(lit: &Lit_) -> LitTypePrinter
{
  match *lit {
    LitStr(_, _) => PLitStr,
    LitBinary(_) => PLitBinary,
    LitByte(_) => PLitByte,
    LitChar(_) => PLitChar,
    LitInt(_, _) => PLitInt,
    LitFloat(_, _) => PLitFloat,
    LitFloatUnsuffixed(_) => PLitFloatUnsuffixed,
    LitNil => PLitNil,
    LitBool(_) => PLitBool
  }
}

pub enum LitTypePrinter
{
  PLitStr,
  PLitBinary,
  PLitByte,
  PLitChar,
  PLitInt,
  PLitFloat,
  PLitFloatUnsuffixed,
  PLitNil,
  PLitBool
}

impl LitTypePrinter
{
  pub fn type_to_str(&self) -> &'static str
  {
    match *self {
      PLitStr => "string",
      PLitBinary => "binary",
      PLitByte => "byte",
      PLitChar => "char",
      PLitInt => "int",
      PLitFloat => "float",
      PLitFloatUnsuffixed => "unsuffixed float",
      PLitNil => "nil",
      PLitBool => "boolean"
    }
  }

  pub fn type_example_to_str(&self) -> &'static str
  {
    match *self {
      PLitStr => "\"hello world\"",
      PLitBinary => "0b01010101",
      PLitByte => "b'9'",
      PLitChar => "'a'",
      PLitInt => "38",
      PLitFloat => "0.01f32",
      PLitFloatUnsuffixed => "0.1",
      PLitNil => "()",
      PLitBool => "true"
    }
  }
}
<commit_msg>[Access] Add access to the string literal.<commit_after>// Copyright 2014 Pierre Talbot (IRCAM)

// 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.

pub use compile_error::*;
pub use syntax::parse::token::InternedString;
pub use syntax::ast::*;

use syntax::codemap::DUMMY_SP;
use std::rc::Rc;

#[deriving(Clone)]
pub struct AttributeValue<T>
{
  pub value: Option<T>,
  pub span: Span,
  duplicate: DuplicateAttribute
}

impl<T: Clone> AttributeValue<T>
{
  pub fn new(duplicate: DuplicateAttribute) -> AttributeValue<T>
  {
    AttributeValue {
      value: None,
      duplicate: duplicate,
      span: DUMMY_SP
    }
  }

  pub fn simple() -> AttributeValue<T>
  {
    AttributeValue::new(DuplicateAttribute::simple(Warn))
  }

  pub fn update(self, cx: &ExtCtxt, value: T, span: Span) -> AttributeValue<T>
  {
    let mut this = self;
    if this.value.is_some() {
      this.duplicate.issue(cx, this.span, span);
    } else {
      this.value = Some(value);
      this.span = span;
    }
    this
  }

  pub fn has_value(&self) -> bool
  {
    self.value.is_some()
  }

  pub fn value_or(&self, default: T) -> T
  {
    match self.value {
      None => default,
      Some(ref value) => value.clone()
    }
  }

  pub fn span(&self) -> Span
  {
    self.span.clone()
  }
}

#[deriving(Clone)]
pub struct AttributeInfo
{
  pub name: InternedString,
  pub desc: &'static str,
  pub model: AttributeModel
}

impl AttributeInfo
{
  pub fn new(name: &'static str, desc: &'static str,
    model: AttributeModel) -> AttributeInfo
  {
    AttributeInfo {
      name: InternedString::new(name),
      desc: desc,
      model: model
    }
  }

  pub fn simple(name: &'static str, desc: &'static str) -> AttributeInfo
  {
    AttributeInfo::new(name, desc, UnitValue(AttributeValue::simple()))
  }

  pub fn update(self, model: AttributeModel) -> AttributeInfo
  {
    let mut this = self;
    this.model = model;
    this
  }

  pub fn plain_value<'a>(&'a self) -> &'a AttributeValue<()>
  {
    match self.model {
      UnitValue(ref v) => v,
      _ => fail!("No plain value for the current attribute.")
    }
  }

  pub fn sub_model<'a>(&'a self) -> &'a AttributeArray
  {
    match self.model {
      SubAttribute(ref array) => array,
      _ => fail!("No sub value for the current attribute.")
    }
  }

  pub fn key_value<'a>(&'a self) -> &'a AttributeLitModel
  {
    match self.model {
      KeyValue(ref lit) => lit,
      _ => fail!("No key value for the current attribute.")
    }
  }
}

#[deriving(Clone)]
pub enum AttributeModel
{
  UnitValue(AttributeValue<()>),
  KeyValue(AttributeLitModel),
  SubAttribute(AttributeArray)
}

#[deriving(Clone)]
pub enum AttributeLitModel
{
  MLitStr(AttributeValue<(InternedString, StrStyle)>),
  MLitBinary(AttributeValue<Rc<Vec<u8>>>),
  MLitByte(AttributeValue<u8>),
  MLitChar(AttributeValue<char>),
  MLitInt(AttributeValue<(u64, LitIntType)>),
  MLitFloat(AttributeValue<(InternedString, FloatTy)>),
  MLitFloatUnsuffixed(AttributeValue<InternedString>),
  MLitNil(AttributeValue<()>),
  MLitBool(AttributeValue<bool>)
}

pub type AttributeArray = Vec<AttributeInfo>;

pub mod access
{
  pub use super::*;
  pub fn by_name<'a>(array: &'a AttributeArray, name: &'static str) -> &'a AttributeInfo
  {
    let interned = InternedString::new(name);
    for info in array.iter() {
      if info.name == interned {
        return info;
      }
    }
    fail!("Try to get an attribute that doesn't exist.")
  }

  pub fn plain_value<'a>(array: &'a AttributeArray, name: &'static str) -> &'a AttributeValue<()>
  {
    by_name(array, name).plain_value()
  }

  pub fn sub_model<'a>(array: &'a AttributeArray, name: &'static str) -> &'a AttributeArray
  {
    by_name(array, name).sub_model()
  }

  pub fn lit_str<'a>(array: &'a AttributeArray, name: &'static str) -> Option<&'a AttributeValue<(InternedString, StrStyle)>>
  {
    match by_name(array, name).key_value() {
      &MLitStr(ref val) => Some(val),
      _ => None
    }
  }

  pub fn plain_value_or(array: &AttributeArray, name: &'static str, def: bool) -> bool
  {
    if plain_value(array, name).has_value() {
      true
    } else {
      def
    }
  }
}
// fn attribute_doc(&self)
// {
//   let mut doc = format!("Attribute `#[{}(<attribute list>)]`: {}\n",
//       self.root_name.get(), self.root_desc);
//   for info in self.infos.iter() {
//     doc.add(format!("  * `#[{}({})]`: {}\n",
//       self.root_name.get(), info.name, info.desc));
//   }
//   self.cx.parse_sess.span_diagnostic.handler.note(doc.as_slice());
// }

pub struct AttributeMerger<'a>
{
  cx: &'a ExtCtxt<'a>,
  duplicate: DuplicateAttribute
}

impl<'a> AttributeMerger<'a>
{
  pub fn new(cx: &'a ExtCtxt, duplicate: DuplicateAttribute) -> AttributeMerger<'a>
  {
    AttributeMerger {
      cx: cx,
      duplicate: duplicate
    }
  }

  pub fn merge(&self, info: AttributeInfo, info2: AttributeInfo) -> AttributeInfo
  {
    assert!(info.name == info2.name);
    let mut info = info;
    info.model = match (info.model, info2.model) {
      (UnitValue(val), UnitValue(val2)) => UnitValue(self.merge_value(val, val2)),
      (KeyValue(lit), KeyValue(lit2)) => KeyValue(self.merge_lit(lit, lit2)),
      (SubAttribute(sub), SubAttribute(sub2)) => SubAttribute(self.merge_sub_attr(sub, sub2)),
      _ => fail!("Mismatch between attribute models during merging.")
    };
    info
  }

  fn merge_value<T>(&self, val: AttributeValue<T>, val2: AttributeValue<T>) -> AttributeValue<T>
  {
    match (&val.value, &val2.value) {
      (&None, _) => val2,
      (_, &None) => val,
      (&Some(_), &Some(_)) => {
        self.duplicate.issue(self.cx, val.span, val2.span);
        val
      }
    }
  }

  fn merge_lit(&self, lit: AttributeLitModel, lit2: AttributeLitModel) -> AttributeLitModel
  {
    match (lit, lit2) {
      (MLitStr(val), MLitStr(val2)) => MLitStr(self.merge_value(val, val2)),
      (MLitBinary(val), MLitBinary(val2)) => MLitBinary(self.merge_value(val, val2)),
      (MLitByte(val), MLitByte(val2)) => MLitByte(self.merge_value(val, val2)),
      (MLitChar(val), MLitChar(val2)) => MLitChar(self.merge_value(val, val2)),
      (MLitInt(val), MLitInt(val2)) => MLitInt(self.merge_value(val, val2)),
      (MLitFloat(val), MLitFloat(val2)) => MLitFloat(self.merge_value(val, val2)),
      (MLitFloatUnsuffixed(val), MLitFloatUnsuffixed(val2)) => MLitFloatUnsuffixed(self.merge_value(val, val2)),
      (MLitNil(val), MLitNil(val2)) => MLitNil(self.merge_value(val, val2)),
      (MLitBool(val), MLitBool(val2)) => MLitBool(self.merge_value(val, val2)),
      _ => fail!("Mismatch between attribute models during merging.")
    }
  }

  fn merge_sub_attr(&self, sub1: AttributeArray, sub2: AttributeArray) -> AttributeArray
  {
    assert!(sub1.len() == sub2.len());
    sub1.move_iter()
      .zip(sub2.move_iter())
      .map(|(info, info2)| self.merge(info, info2))
      .collect()
  }
}

impl AttributeLitModel
{
  pub fn to_lit_printer(&self) -> LitTypePrinter
  {
    match *self {
      MLitStr(_) => PLitStr,
      MLitBinary(_) => PLitBinary,
      MLitByte(_) => PLitByte,
      MLitChar(_) => PLitChar,
      MLitInt(_) => PLitInt,
      MLitFloat(_) => PLitFloat,
      MLitFloatUnsuffixed(_) => PLitFloatUnsuffixed,
      MLitNil(_) => PLitNil,
      MLitBool(_) => PLitBool
    }
  }
}

pub fn lit_to_lit_printer(lit: &Lit_) -> LitTypePrinter
{
  match *lit {
    LitStr(_, _) => PLitStr,
    LitBinary(_) => PLitBinary,
    LitByte(_) => PLitByte,
    LitChar(_) => PLitChar,
    LitInt(_, _) => PLitInt,
    LitFloat(_, _) => PLitFloat,
    LitFloatUnsuffixed(_) => PLitFloatUnsuffixed,
    LitNil => PLitNil,
    LitBool(_) => PLitBool
  }
}

pub enum LitTypePrinter
{
  PLitStr,
  PLitBinary,
  PLitByte,
  PLitChar,
  PLitInt,
  PLitFloat,
  PLitFloatUnsuffixed,
  PLitNil,
  PLitBool
}

impl LitTypePrinter
{
  pub fn type_to_str(&self) -> &'static str
  {
    match *self {
      PLitStr => "string",
      PLitBinary => "binary",
      PLitByte => "byte",
      PLitChar => "char",
      PLitInt => "int",
      PLitFloat => "float",
      PLitFloatUnsuffixed => "unsuffixed float",
      PLitNil => "nil",
      PLitBool => "boolean"
    }
  }

  pub fn type_example_to_str(&self) -> &'static str
  {
    match *self {
      PLitStr => "\"hello world\"",
      PLitBinary => "0b01010101",
      PLitByte => "b'9'",
      PLitChar => "'a'",
      PLitInt => "38",
      PLitFloat => "0.01f32",
      PLitFloatUnsuffixed => "0.1",
      PLitNil => "()",
      PLitBool => "true"
    }
  }
}
<|endoftext|>


<commit_before>// Helianto -- static website generator
// Copyright © 2015-2016 Mickaël RAYBAUD-ROIG
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::rc::Rc;
use std::collections::HashMap;
use std::path::PathBuf;
use super::super::{Result, Document, DocumentMetadata, DocumentContent};

pub struct IndexGenerator;

impl super::Generator for IndexGenerator {
    fn new() -> IndexGenerator { IndexGenerator }

    fn generate(&self, docs: &[Rc<DocumentMetadata>]) -> Result<Vec<Rc<Document>>> {
        let mut indexes: HashMap<String, Vec<Rc<DocumentMetadata>>> = HashMap::new();

        for doc in docs.iter() {
            let mut path: PathBuf = PathBuf::from(&doc.url);

            while let Some(parent) = path.clone().parent() {

                let index_url = match parent.to_str() {
                    Some(string) => string.into(),
                    None => continue,
                };

                let documents = indexes.entry(index_url).or_insert_with(Vec::new);
                documents.push(doc.clone());

                path = parent.into();
            }
        }

        Ok(indexes.into_iter()
                  .map(|(url, mut docs)| {

                      let meta = DocumentMetadata {
                          url: format!("{}/index.html", url),
                          title: format!("Index of {}", url),
                          ..DocumentMetadata::default()
                      };

                      docs.sort_by(|b, a| a.created.cmp(&b.created));
                      let content = DocumentContent::Index(docs);

                      Rc::new(Document::new(meta, content))
                  })
                  .collect())
    }
}
<commit_msg>Fix index titles<commit_after>// Helianto -- static website generator
// Copyright © 2015-2016 Mickaël RAYBAUD-ROIG
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::rc::Rc;
use std::collections::HashMap;
use std::path::PathBuf;
use super::super::{Result, Document, DocumentMetadata, DocumentContent};

pub struct IndexGenerator;

impl super::Generator for IndexGenerator {
    fn new() -> IndexGenerator { IndexGenerator }

    fn generate(&self, docs: &[Rc<DocumentMetadata>]) -> Result<Vec<Rc<Document>>> {
        let mut indexes: HashMap<String, Vec<Rc<DocumentMetadata>>> = HashMap::new();

        for doc in docs.iter() {
            let mut path: PathBuf = PathBuf::from(&doc.url);

            while let Some(parent) = path.clone().parent() {

                let index_url = match parent.to_str() {
                    Some(string) => string.into(),
                    None => continue,
                };

                let documents = indexes.entry(index_url).or_insert_with(Vec::new);
                documents.push(doc.clone());

                path = parent.into();
            }
        }

        Ok(indexes.into_iter()
                  .map(|(url, mut docs)| {

                      let meta = DocumentMetadata {
                          url: format!("{}/index.html", url),
                          title: format!("Index of {}", if url != "" { url } else { "/".into() }),
                          ..DocumentMetadata::default()
                      };

                      docs.sort_by(|b, a| a.created.cmp(&b.created));
                      let content = DocumentContent::Index(docs);

                      Rc::new(Document::new(meta, content))
                  })
                  .collect())
    }
}
<|endoftext|>


<commit_before>
use cretonne;
<commit_msg>Parser for .cton files.<commit_after>
// ====--------------------------------------------------------------------------------------====//
//
// Parser for .cton files.
//
// ====--------------------------------------------------------------------------------------====//

use std::result;
use lexer::{self, Lexer, Token};
use cretonne::{types, repr};

pub use lexer::Location;

/// A parse error is returned when the parse failed.
pub struct Error {
    pub location: Location,
    pub message: String,
}

pub type Result<T> = result::Result<T, Error>;

pub struct Parser<'a> {
    lex: Lexer<'a>,

    lex_error: Option<lexer::Error>,

    // Current lookahead token.
    lookahead: Option<Token<'a>>,

    // Location of lookahead.
    location: Location,
}

impl<'a> Parser<'a> {
    // Consume the current lookahead token and return it.
    fn consume(&mut self) -> Token<'a> {
        self.lookahead.take().expect("No token to consume")
    }

    // Get the current lookahead token, after making sure there is one.
    fn token(&mut self) -> Option<Token<'a>> {
        if self.lookahead == None {
            match self.lex.next() {
                Some(Ok(lexer::LocatedToken { token, location })) => {
                    self.lookahead = Some(token);
                    self.location = location;
                }
                Some(Err(lexer::LocatedError { error, location })) => {
                    self.lex_error = Some(error);
                    self.location = location;
                }
                None => {}
            }
        }
        return self.lookahead;
    }

    // Generate an error.
    fn error(&self, message: &str) -> Error {
        Error {
            location: self.location,
            message:
                // If we have a lexer error latched, report that.
                match self.lex_error {
                    Some(lexer::Error::InvalidChar) => "Invalid character".to_string(),
                    None => message.to_string(),
                }
        }
    }

    // Match and consume a token without payload.
    fn match_token(&mut self, want: Token<'a>, err_msg: &str) -> Result<Token<'a>> {
        match self.token() {
            Some(ref t) if *t == want => Ok(self.consume()),
            _ => Err(self.error(err_msg)),
        }
    }

    // if the next token is a `want`, consume it, otherwise do nothing.
    fn optional(&mut self, want: Token<'a>) -> bool {
        match self.token() {
            Some(t) if t == want => {
                self.consume();
                true
            }
            _ => false,
        }
    }

    // Parse a whole function definition.
    //
    // function ::= * "function" name signature { ... }
    //
    fn parse_function(&mut self) -> Result<repr::Function> {
        try!(self.match_token(Token::Function, "Expected 'function' keyword"));

        // function ::= "function" * name signature { ... }
        let name = try!(self.parse_function_name());

        // function ::= "function" name * signature { ... }
        let sig = try!(self.parse_signature());

        let mut func = repr::Function::new();

        try!(self.match_token(Token::LBrace, "Expected '{' before function body"));
        try!(self.match_token(Token::RBrace, "Expected '}' after function body"));

        Ok(func)
    }

    // Parse a function name.
    //
    // function ::= "function" * name signature { ... }
    //
    fn parse_function_name(&mut self) -> Result<String> {
        match self.token() {
            Some(Token::Identifier(s)) => {
                self.consume();
                Ok(s.to_string())
            }
            _ => Err(self.error("Expected function name")),
        }
    }

    // Parse a function signature.
    //
    // signature ::=  * "(" arglist ")" ["->" retlist] [call_conv]
    // callconv  ::=  string
    //
    // function ::= "function" * name signature { ... }
    //
    fn parse_signature(&mut self) -> Result<types::Signature> {
        let mut sig = types::Signature::new();

        try!(self.match_token(Token::LPar, "Expected function signature: '(' args... ')'"));
        // signature ::=  "(" * arglist ")" ["->" retlist] [call_conv]
        sig.argument_types = try!(self.parse_argument_list());
        try!(self.match_token(Token::RPar, "Expected ')' after function arguments"));
        if self.optional(Token::Arrow) {
            sig.return_types = try!(self.parse_argument_list());
            if sig.return_types.is_empty() {
                return Err(self.error("Missing return type after '->'"));
            }
        }

        // TBD: calling convention.

        Ok(sig)
    }

    // Parse (possibly empty) list of function argument / return value types.
    //
    // arglist ::= * <empty>
    //             * arg
    //             * arglist "," arg
    fn parse_argument_list(&mut self) -> Result<Vec<types::ArgumentType>> {
        let mut list = Vec::new();
        // arglist   ::= * <empty>
        //               * arg
        match self.token() {
            Some(Token::Type(_)) => list.push(try!(self.parse_argument_type())),
            _ => return Ok(list),
        }

        // arglist ::= arg *
        //             arglist * "," arg
        while self.token() == Some(Token::Comma) {
            // arglist ::= arglist * "," arg
            self.consume();
            // arglist ::= arglist "," * arg
            list.push(try!(self.parse_argument_type()));
        }

        Ok(list)
    }

    // Parse a single argument type with flags.
    fn parse_argument_type(&mut self) -> Result<types::ArgumentType> {
        // arg ::= * type
        //         * arg flag
        let mut arg = match self.token() {
            Some(Token::Type(t)) => types::ArgumentType::new(t),
            _ => return Err(self.error("Expected argument type")),
        };
        loop {
            self.consume();
            // arg ::= arg * flag
            match self.token() {
                Some(Token::Identifier(s)) => {
                    match s {
                        "uext" => arg.extension = types::ArgumentExtension::Uext,
                        "sext" => arg.extension = types::ArgumentExtension::Sext,
                        "inreg" => arg.inreg = true,
                        _ => break,
                    }
                }
                _ => break,
            }
        }
        Ok(arg)
    }
}
<|endoftext|>


<commit_before>
//! Implements the gerrit structure

use call::Call;
use entities::*;
use entities;
use error::GGRError;
use error::GGRResult;
use rustc_serialize;
use std::error::Error;

/// `Gerrit` structure for management of several gerrit endpoints
pub struct Gerrit {
    call: Call,
}

impl Gerrit {
    /// Creates a new `Gerrit` object
    ///
    /// The url points to the http endpoint of an gerrit server like
    /// `http://localhost:8080/gerrit`. All other function append to this url there endpoint pathes
    /// and query parameters.
    pub fn new<S>(url: S) -> Gerrit
    where S: Into<String> {
        Gerrit {
            call: Call::new(url.into()),
        }
    }

    /// pull changes from gerrit server
    ///
    /// `querylist` and `additional_info` are used as filter in the call to gerrit.
    pub fn changes(&self, querylist: Option<&[&str]>, additional_infos: Option<&[&str]>)
        -> GGRResult<Vec<entities::ChangeInfo>>
    {
        let mut querystring = "pp=0&q=".to_string();
        match querylist {
            None => { /* nothing to do, we call without filter */ },
            Some(x) => {
                let urlfragment = Changes::build_url(x);
                querystring = format!("{}{}", querystring, urlfragment);
            },
        };

        if let Ok(cr) = self.call.get("/changes/".into(), querystring) {
            // TODO: too much unwrap's here
            let data2 = String::from_utf8(cr.body.unwrap()).unwrap();

            let data4: Vec<ChangeInfo> = match rustc_serialize::json::decode(&data2) {
                Ok(d) => {
                    d
                },
                Err(err) => {
                    return Err(GGRError::General(format!("{}: {}", err.description(), data2)));
                },
            };
            return Ok(data4);
        } else {
            println!("call problem");
        }
        Ok(Vec::new())
    }
}

// helper structures
struct Changes;
impl Changes {
    pub fn build_url(querylist: &[&str]) -> String {
        let mut out = String::new();
        for el in querylist.iter() {
            out.push_str(el.clone());
            out.push_str("+");
        }
        if let Some(x) = out.chars().last() {
            if x == '+' {
                out = out.trim_right_matches(x).to_string();
            }
        };

        out
    }
}

#[test]
fn test_changes_build_url() {
    assert_eq!(Changes::build_url(&vec!()), "");
    assert_eq!(Changes::build_url(&vec!("a:1", "b:2")), "a:1+b:2");
    assert_eq!(Changes::build_url(&vec!("a:1")), "a:1");
}
<commit_msg>gerrit: remove useless clone of a copy object<commit_after>
//! Implements the gerrit structure

use call::Call;
use entities::*;
use entities;
use error::GGRError;
use error::GGRResult;
use rustc_serialize;
use std::error::Error;

/// `Gerrit` structure for management of several gerrit endpoints
pub struct Gerrit {
    call: Call,
}

impl Gerrit {
    /// Creates a new `Gerrit` object
    ///
    /// The url points to the http endpoint of an gerrit server like
    /// `http://localhost:8080/gerrit`. All other function append to this url there endpoint pathes
    /// and query parameters.
    pub fn new<S>(url: S) -> Gerrit
    where S: Into<String> {
        Gerrit {
            call: Call::new(url.into()),
        }
    }

    /// pull changes from gerrit server
    ///
    /// `querylist` and `additional_info` are used as filter in the call to gerrit.
    pub fn changes(&self, querylist: Option<&[&str]>, additional_infos: Option<&[&str]>)
        -> GGRResult<Vec<entities::ChangeInfo>>
    {
        let mut querystring = "pp=0&q=".to_string();
        match querylist {
            None => { /* nothing to do, we call without filter */ },
            Some(x) => {
                let urlfragment = Changes::build_url(x);
                querystring = format!("{}{}", querystring, urlfragment);
            },
        };

        if let Ok(cr) = self.call.get("/changes/".into(), querystring) {
            // TODO: too much unwrap's here
            let data2 = String::from_utf8(cr.body.unwrap()).unwrap();

            let data4: Vec<ChangeInfo> = match rustc_serialize::json::decode(&data2) {
                Ok(d) => {
                    d
                },
                Err(err) => {
                    return Err(GGRError::General(format!("{}: {}", err.description(), data2)));
                },
            };
            return Ok(data4);
        } else {
            println!("call problem");
        }
        Ok(Vec::new())
    }
}

// helper structures
struct Changes;
impl Changes {
    pub fn build_url(querylist: &[&str]) -> String {
        let mut out = String::new();
        for el in querylist.iter() {
            out.push_str(el);
            out.push_str("+");
        }
        if let Some(x) = out.chars().last() {
            if x == '+' {
                out = out.trim_right_matches(x).to_string();
            }
        };

        out
    }
}

#[test]
fn test_changes_build_url() {
    assert_eq!(Changes::build_url(&vec!()), "");
    assert_eq!(Changes::build_url(&vec!("a:1", "b:2")), "a:1+b:2");
    assert_eq!(Changes::build_url(&vec!("a:1")), "a:1");
}
<|endoftext|>


<commit_before>extern crate cargotest;
extern crate hamcrest;

use cargotest::is_nightly;
use cargotest::support::{execs, project};
use hamcrest::assert_that;

#[test]
fn check_success() {
    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    let expected = if is_nightly() { 0 } else { 101 };
    assert_that(foo.cargo_process("check"),
                execs().with_status(expected));
}

#[test]
fn check_fail() {
    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() {
                ::bar::baz(42);
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(101));
}

#[test]
fn custom_derive() {
    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
#![feature(proc_macro)]

#[macro_use]
extern crate bar;

trait B {
    fn b(&self);
}

#[derive(B)]
struct A;

fn main() {
    let a = A;
    a.b();
}
"#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
            [lib]
            proc-macro = true
        "#)
        .file("src/lib.rs", r#"
#![feature(proc_macro, proc_macro_lib)]
#![crate_type = "proc-macro"]

extern crate proc_macro;

use proc_macro::TokenStream;

#[proc_macro_derive(B)]
pub fn derive(_input: TokenStream) -> TokenStream {
    format!("impl B for A {{ fn b(&self) {{}} }}").parse().unwrap()
}
"#);
    bar.build();

    let expected = if is_nightly() { 0 } else { 101 };
    assert_that(foo.cargo_process("check"),
                execs().with_status(expected));
}

#[test]
fn check_build() {
    if !is_nightly() {
        return;
    }

    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
    assert_that(foo.cargo_process("build"),
                execs().with_status(0));
}

#[test]
fn build_check() {
    if !is_nightly() {
        return;
    }

    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("build"),
                execs().with_status(0));
    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
}
<commit_msg>Only run check tests on nightly<commit_after>extern crate cargotest;
extern crate hamcrest;

use cargotest::is_nightly;
use cargotest::support::{execs, project};
use hamcrest::assert_that;

#[test]
fn check_success() {
    if !is_nightly() {
        return
    }
    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
}

#[test]
fn check_fail() {
    if !is_nightly() {
        return
    }
    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() {
                ::bar::baz(42);
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(101));
}

#[test]
fn custom_derive() {
    if !is_nightly() {
        return
    }
    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
#![feature(proc_macro)]

#[macro_use]
extern crate bar;

trait B {
    fn b(&self);
}

#[derive(B)]
struct A;

fn main() {
    let a = A;
    a.b();
}
"#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
            [lib]
            proc-macro = true
        "#)
        .file("src/lib.rs", r#"
#![feature(proc_macro, proc_macro_lib)]
#![crate_type = "proc-macro"]

extern crate proc_macro;

use proc_macro::TokenStream;

#[proc_macro_derive(B)]
pub fn derive(_input: TokenStream) -> TokenStream {
    format!("impl B for A {{ fn b(&self) {{}} }}").parse().unwrap()
}
"#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
}

#[test]
fn check_build() {
    if !is_nightly() {
        return;
    }

    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
    assert_that(foo.cargo_process("build"),
                execs().with_status(0));
}

#[test]
fn build_check() {
    if !is_nightly() {
        return;
    }

    let foo = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "../bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            fn main() {
                ::bar::baz();
            }
        "#);
    let bar = project("bar")
        .file("Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.1.0"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn baz() {}
        "#);
    bar.build();

    assert_that(foo.cargo_process("build"),
                execs().with_status(0));
    assert_that(foo.cargo_process("check"),
                execs().with_status(0));
}
<|endoftext|>


<commit_before>extern crate glib;

use std::cell::RefCell;
use std::panic;
use std::rc::Rc;
use std::sync::{Arc, Mutex};

use glib::clone;

struct State {
    count: i32,
    started: bool,
}

impl State {
    fn new() -> Self {
        Self {
            count: 0,
            started: false,
        }
    }
}

#[test]
fn clone_and_references() {
    let state = Rc::new(RefCell::new(State::new()));
    let ref_state = &state;
    assert_eq!(ref_state.borrow().started, false);

    let closure = {
        clone!(@weak ref_state => move || {
            ref_state.borrow_mut().started = true;
        })
    };

    assert_eq!(closure(), ());
}

#[test]
fn subfields_renaming() {
    struct Foo {
        v: Rc<usize>,
    }

    impl Foo {
        fn foo(&self) {
            let state = Rc::new(RefCell::new(State::new()));

            let closure = clone!(@strong self.v as v, @weak state as hello => move |_| {
                println!("v: {}", v);
                hello.borrow_mut().started = true;
            });
            closure(2);
        }
    }

    Foo { v: Rc::new(0) }.foo();
}

#[test]
fn renaming() {
    let state = Rc::new(RefCell::new(State::new()));
    assert_eq!(state.borrow().started, false);

    let closure = {
        clone!(@weak state as hello => move || {
            hello.borrow_mut().started = true;
        })
    };

    assert_eq!(closure(), ());
}

#[test]
fn clone_closure() {
    let state = Rc::new(RefCell::new(State::new()));
    assert_eq!(state.borrow().started, false);

    let closure = {
        clone!(@weak state => move || {
            state.borrow_mut().started = true;
        })
    };

    assert_eq!(closure(), ());

    assert_eq!(state.borrow().started, true);
    assert_eq!(state.borrow().count, 0);

    let closure = {
        let state2 = Rc::new(RefCell::new(State::new()));
        assert_eq!(state.borrow().started, true);

        clone!(@weak state, @strong state2 => move || {
            state.borrow_mut().count += 1;
            state.borrow_mut().started = true;
            state2.borrow_mut().started = true;
        })
    };

    assert_eq!(closure(), ());

    assert_eq!(state.borrow().count, 1);
    assert_eq!(state.borrow().started, true);
}

#[test]
fn clone_default_value() {
    let closure = {
        let state = Rc::new(RefCell::new(State::new()));
        clone!(@weak state => @default-return 42, move |_| {
            state.borrow_mut().started = true;
            10
        })
    };

    assert_eq!(42, closure(50));
}

#[test]
fn clone_panic() {
    let state = Arc::new(Mutex::new(State::new()));
    state.lock().expect("Failed to lock state mutex").count = 20;

    let closure = {
        let state2 = Arc::new(Mutex::new(State::new()));
        clone!(@weak state2, @strong state => @default-return panic!(), move |_| {
            state.lock().expect("Failed to lock state mutex").count = 21;
            state2.lock().expect("Failed to lock state2 mutex").started = true;
            10
        })
    };

    let result = panic::catch_unwind(|| {
        closure(50);
    });

    if result.is_ok() {
        assert!(false, "should panic");
    }

    assert_eq!(state.lock().expect("Failed to lock state mutex").count, 20);
}
<commit_msg>clippy: Clean up various issues in clone tests<commit_after>extern crate glib;

use std::cell::RefCell;
use std::panic;
use std::rc::Rc;
use std::sync::{Arc, Mutex};

use glib::clone;

struct State {
    count: i32,
    started: bool,
}

impl State {
    fn new() -> Self {
        Self {
            count: 0,
            started: false,
        }
    }
}

#[test]
fn clone_and_references() {
    let state = Rc::new(RefCell::new(State::new()));
    let ref_state = &state;
    assert_eq!(ref_state.borrow().started, false);

    let closure = {
        clone!(@weak ref_state => move || {
            ref_state.borrow_mut().started = true;
        })
    };

    closure();
    assert_eq!(ref_state.borrow().started, true);
}

#[test]
fn subfields_renaming() {
    struct Foo {
        v: Rc<usize>,
    }

    impl Foo {
        fn foo(&self) {
            let state = Rc::new(RefCell::new(State::new()));

            let closure = clone!(@strong self.v as v, @weak state as hello => move |_| {
                println!("v: {}", v);
                hello.borrow_mut().started = true;
            });
            closure(2);
        }
    }

    Foo { v: Rc::new(0) }.foo();
}

#[test]
fn renaming() {
    let state = Rc::new(RefCell::new(State::new()));
    assert_eq!(state.borrow().started, false);

    let closure = {
        clone!(@weak state as hello => move || {
            hello.borrow_mut().started = true;
        })
    };

    closure();
    assert_eq!(state.borrow().started, true);
}

#[test]
fn clone_closure() {
    let state = Rc::new(RefCell::new(State::new()));
    assert_eq!(state.borrow().started, false);

    let closure = {
        clone!(@weak state => move || {
            state.borrow_mut().started = true;
        })
    };

    closure();

    assert_eq!(state.borrow().started, true);
    assert_eq!(state.borrow().count, 0);

    let closure = {
        let state2 = Rc::new(RefCell::new(State::new()));
        assert_eq!(state.borrow().started, true);

        clone!(@weak state, @strong state2 => move || {
            state.borrow_mut().count += 1;
            state.borrow_mut().started = true;
            state2.borrow_mut().started = true;
        })
    };

    closure();

    assert_eq!(state.borrow().count, 1);
    assert_eq!(state.borrow().started, true);
}

#[test]
fn clone_default_value() {
    let closure = {
        let state = Rc::new(RefCell::new(State::new()));
        clone!(@weak state => @default-return 42, move |_| {
            state.borrow_mut().started = true;
            10
        })
    };

    assert_eq!(42, closure(50));
}

#[test]
fn clone_panic() {
    let state = Arc::new(Mutex::new(State::new()));
    state.lock().expect("Failed to lock state mutex").count = 20;

    let closure = {
        let state2 = Arc::new(Mutex::new(State::new()));
        clone!(@weak state2, @strong state => @default-return panic!(), move |_| {
            state.lock().expect("Failed to lock state mutex").count = 21;
            state2.lock().expect("Failed to lock state2 mutex").started = true;
            10
        })
    };

    let result = panic::catch_unwind(|| {
        closure(50);
    });

    assert!(result.is_err());

    assert_eq!(state.lock().expect("Failed to lock state mutex").count, 20);
}
<|endoftext|>


<commit_before>use snafu::Snafu;

use tests::{bano, cosmogony, download, ntfs, osm};

#[derive(Debug, Snafu)]
#[snafu(visibility = "pub(crate)")]
pub enum Error {
    #[snafu(display("Download Error: {}", source))]
    Download { source: download::Error },

    #[snafu(display("Generate Cosmogony Error: {}", source))]
    GenerateCosmogony { source: cosmogony::Error },

    #[snafu(display("Index Cosmogony Error: {}", source))]
    IndexCosmogony { source: cosmogony::Error },

    #[snafu(display("Index Bano Error: {}", source))]
    IndexBano { source: bano::Error },

    #[snafu(display("Index Osm Error: {}", source))]
    IndexOsm { source: osm::Error },

    #[snafu(display("Index NTFS Error: {}", source))]
    IndexNtfs { source: ntfs::Error },
}
<commit_msg>Fix case on indexntfs<commit_after>use snafu::Snafu;

use tests::{bano, cosmogony, download, ntfs, osm};

#[derive(Debug, Snafu)]
#[snafu(visibility = "pub(crate)")]
pub enum Error {
    #[snafu(display("Download Error: {}", source))]
    Download { source: download::Error },

    #[snafu(display("Generate Cosmogony Error: {}", source))]
    GenerateCosmogony { source: cosmogony::Error },

    #[snafu(display("Index Cosmogony Error: {}", source))]
    IndexCosmogony { source: cosmogony::Error },

    #[snafu(display("Index Bano Error: {}", source))]
    IndexBano { source: bano::Error },

    #[snafu(display("Index Osm Error: {}", source))]
    IndexOsm { source: osm::Error },

    #[snafu(display("Index NTFS Error: {}", source))]
    IndexNTFS { source: ntfs::Error },
}
<|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/.
*
*  Copyright (C) 2017  Juhamatti Kuusisaari / Mles developers
* */
extern crate tokio_core;
extern crate tokio_io;
extern crate futures;

use std::io::{Error, ErrorKind};

use tokio_core::net::TcpStream;
use tokio_io::io;

use super::*;

pub fn process_hdr_dummy_key(reader: io::ReadHalf<TcpStream>, hdr_key: Vec<u8>) -> Result<(io::ReadHalf<TcpStream>, Vec<u8>, usize), Error> {
    process_hdr(reader, hdr_key)
}

pub fn process_hdr(reader: io::ReadHalf<TcpStream>, hdr: Vec<u8>) -> Result<(io::ReadHalf<TcpStream>, Vec<u8>, usize), Error> {
    if hdr.is_empty() {
        return Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"));
    }
    if read_hdr_type(&hdr) != 'M' as u32 {
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
    }
    let hdr_len = read_hdr_len(&hdr);
    if 0 == hdr_len {
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
    }
    Ok((reader, hdr, hdr_len))
}

pub fn process_msg(reader: io::ReadHalf<TcpStream>, hdr_key: Vec<u8>, message: Vec<u8>) -> Result<(io::ReadHalf<TcpStream>, Vec<u8>, Vec<u8>), Error> {
    if message.is_empty() {
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
    }
    Ok((reader, hdr_key, message))
}

pub fn process_key(reader: io::ReadHalf<TcpStream>, hdr_key: Vec<u8>, message: Vec<u8>, mut keys: Vec<String>) -> Result<(io::ReadHalf<TcpStream>, Vec<Vec<u8>>, Msg), Error> {

    //decode message(s)
    let messages = message_decode(message, hdr_key);
    if messages.is_empty() {
        println!("Incorrect msg");
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect msg"));
    }
    let mut hdrkey = messages[0].clone();
    let message = hdrkey.split_off(HDRKEYL);
    //read key from header
    let key = read_key_from_hdr(&hdrkey);

    let decoded_message = Msg::decode(message.as_slice());
    keys.push(decoded_message.get_uid().to_string());
    keys.push(decoded_message.get_channel().to_string());

    let hkey = do_hash(&keys);
    if hkey != key {
        println!("Incorrect key {:x} != {:x}", hkey, key);
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect remote key"));
    }
    Ok((reader, messages, decoded_message))
}

fn message_decode(message: Vec<u8>, mut hdr_key: Vec<u8>) -> Vec<Vec<u8>> {
    //try first decoding as a resync
    let mut msgs = Vec::new();
    let decoded_resync_message: ResyncMsg = ResyncMsg::decode(message.as_slice());
    if 0 != decoded_resync_message.len() {
        println!("Got resync of size {}", decoded_resync_message.len());
        for msg in decoded_resync_message.get_messages() {
            msgs.push(msg);
        }
    }
    else {
        hdr_key.extend(message);
        msgs.push(hdr_key);
    }
    msgs
}

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

    #[test]
    fn test_message_decode() {
        let uid = "User".to_string();
        let channel = "Channel".to_string();
        let mut keys = Vec::new();
        keys.push(uid.clone());
        keys.push(channel.clone());
        let key = do_hash(&keys);
        let mut hdr: Vec<u8> = write_hdr(122, select_cid(key));
        let keyhdr: Vec<u8> = write_key(key);
        hdr.extend(keyhdr);
        let hdrkey = hdr.clone();
        let msg =  "a test msg".to_string().into_bytes();
        let orig_msg = Msg::new(uid, channel, msg);
        let encoded_msg = orig_msg.encode();
        let messages = message_decode(encoded_msg, hdrkey);
        assert_eq!(1, messages.len());
        let mut message = messages[0].clone();
        let msg = message.split_off(HDRKEYL);
        let decoded_msg = Msg::decode(msg.as_slice());
        assert_eq!(decoded_msg.uid, orig_msg.uid);
        assert_eq!(decoded_msg.channel, orig_msg.channel);
        assert_eq!(decoded_msg.message, orig_msg.message);
    }

    #[test]
    fn test_message_resync_decode() {
        let uid = "User".to_string();
        let channel = "Channel".to_string();
        let mut keys = Vec::new();
        keys.push(uid.clone());
        keys.push(channel.clone());
        let key = do_hash(&keys);
        let mut hdr: Vec<u8> = write_hdr(122, select_cid(key));
        let keyhdr: Vec<u8> = write_key(key);
        hdr.extend(keyhdr);
        let hdrkey = hdr.clone();
        let msg =  "a test msg".to_string().into_bytes();
        let orig_msg = Msg::new(uid, channel, msg);
        let encoded_msg = orig_msg.encode();
        hdr.extend(encoded_msg);
        let vec = vec![hdr.clone()];
        let rmsg = ResyncMsg::new(&vec);
        let encoded_resync_msg: Vec<u8> = rmsg.encode();
        let messages = message_decode(encoded_resync_msg, hdrkey);
        assert_eq!(1, messages.len());
        let mut message = messages[0].clone();
        let msg = message.split_off(HDRKEYL);
        let decoded_msg = Msg::decode(msg.as_slice());
        assert_eq!(decoded_msg.uid, orig_msg.uid);
        assert_eq!(decoded_msg.channel, orig_msg.channel);
        assert_eq!(decoded_msg.message, orig_msg.message);
    }

    #[test]
    fn test_message_resync_multi_decode() {
        let uid = "User".to_string();
        let channel = "Channel".to_string();
        let mut keys = Vec::new();
        keys.push(uid.clone());
        keys.push(channel.clone());
        let key = do_hash(&keys);
        let mut hdr: Vec<u8> = write_hdr(122, select_cid(key));
        let keyhdr: Vec<u8> = write_key(key);
        hdr.extend(keyhdr);
        let hdrkey = hdr.clone();
        let msg =  "a test msg".to_string().into_bytes();
        let orig_msg = Msg::new(uid, channel, msg);
        let encoded_msg = orig_msg.encode();
        hdr.extend(encoded_msg);
        let vec = vec![hdr.clone(), hdr.clone()];
        let rmsg = ResyncMsg::new(&vec);
        let encoded_resync_msg: Vec<u8> = rmsg.encode();
        let messages = message_decode(encoded_resync_msg, hdrkey);
        assert_eq!(2, messages.len());
        let mut message = messages[0].clone();
        let msg = message.split_off(HDRKEYL);
        let decoded_msg = Msg::decode(msg.as_slice());
        assert_eq!(decoded_msg.uid, orig_msg.uid);
        assert_eq!(decoded_msg.channel, orig_msg.channel);
        assert_eq!(decoded_msg.message, orig_msg.message);
        let mut message = messages[1].clone();
        let msg = message.split_off(HDRKEYL);
        let decoded_msg = Msg::decode(msg.as_slice());
        assert_eq!(decoded_msg.uid, orig_msg.uid);
        assert_eq!(decoded_msg.channel, orig_msg.channel);
        assert_eq!(decoded_msg.message, orig_msg.message);
    }
}

<commit_msg>Remove additional debug. (#110)<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/.
*
*  Copyright (C) 2017  Juhamatti Kuusisaari / Mles developers
* */
extern crate tokio_core;
extern crate tokio_io;
extern crate futures;

use std::io::{Error, ErrorKind};

use tokio_core::net::TcpStream;
use tokio_io::io;

use super::*;

pub fn process_hdr_dummy_key(reader: io::ReadHalf<TcpStream>, hdr_key: Vec<u8>) -> Result<(io::ReadHalf<TcpStream>, Vec<u8>, usize), Error> {
    process_hdr(reader, hdr_key)
}

pub fn process_hdr(reader: io::ReadHalf<TcpStream>, hdr: Vec<u8>) -> Result<(io::ReadHalf<TcpStream>, Vec<u8>, usize), Error> {
    if hdr.is_empty() {
        return Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"));
    }
    if read_hdr_type(&hdr) != 'M' as u32 {
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
    }
    let hdr_len = read_hdr_len(&hdr);
    if 0 == hdr_len {
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
    }
    Ok((reader, hdr, hdr_len))
}

pub fn process_msg(reader: io::ReadHalf<TcpStream>, hdr_key: Vec<u8>, message: Vec<u8>) -> Result<(io::ReadHalf<TcpStream>, Vec<u8>, Vec<u8>), Error> {
    if message.is_empty() {
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
    }
    Ok((reader, hdr_key, message))
}

pub fn process_key(reader: io::ReadHalf<TcpStream>, hdr_key: Vec<u8>, message: Vec<u8>, mut keys: Vec<String>) -> Result<(io::ReadHalf<TcpStream>, Vec<Vec<u8>>, Msg), Error> {

    //decode message(s)
    let messages = message_decode(message, hdr_key);
    if messages.is_empty() {
        println!("Incorrect msg");
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect msg"));
    }
    let mut hdrkey = messages[0].clone();
    let message = hdrkey.split_off(HDRKEYL);
    //read key from header
    let key = read_key_from_hdr(&hdrkey);

    let decoded_message = Msg::decode(message.as_slice());
    keys.push(decoded_message.get_uid().to_string());
    keys.push(decoded_message.get_channel().to_string());

    let hkey = do_hash(&keys);
    if hkey != key {
        println!("Incorrect key {:x} != {:x}", hkey, key);
        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect remote key"));
    }
    Ok((reader, messages, decoded_message))
}

fn message_decode(message: Vec<u8>, mut hdr_key: Vec<u8>) -> Vec<Vec<u8>> {
    //try first decoding as a resync
    let mut msgs = Vec::new();
    let decoded_resync_message: ResyncMsg = ResyncMsg::decode(message.as_slice());
    if 0 != decoded_resync_message.len() {
        for msg in decoded_resync_message.get_messages() {
            msgs.push(msg);
        }
    }
    else {
        hdr_key.extend(message);
        msgs.push(hdr_key);
    }
    msgs
}

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

    #[test]
    fn test_message_decode() {
        let uid = "User".to_string();
        let channel = "Channel".to_string();
        let mut keys = Vec::new();
        keys.push(uid.clone());
        keys.push(channel.clone());
        let key = do_hash(&keys);
        let mut hdr: Vec<u8> = write_hdr(122, select_cid(key));
        let keyhdr: Vec<u8> = write_key(key);
        hdr.extend(keyhdr);
        let hdrkey = hdr.clone();
        let msg =  "a test msg".to_string().into_bytes();
        let orig_msg = Msg::new(uid, channel, msg);
        let encoded_msg = orig_msg.encode();
        let messages = message_decode(encoded_msg, hdrkey);
        assert_eq!(1, messages.len());
        let mut message = messages[0].clone();
        let msg = message.split_off(HDRKEYL);
        let decoded_msg = Msg::decode(msg.as_slice());
        assert_eq!(decoded_msg.uid, orig_msg.uid);
        assert_eq!(decoded_msg.channel, orig_msg.channel);
        assert_eq!(decoded_msg.message, orig_msg.message);
    }

    #[test]
    fn test_message_resync_decode() {
        let uid = "User".to_string();
        let channel = "Channel".to_string();
        let mut keys = Vec::new();
        keys.push(uid.clone());
        keys.push(channel.clone());
        let key = do_hash(&keys);
        let mut hdr: Vec<u8> = write_hdr(122, select_cid(key));
        let keyhdr: Vec<u8> = write_key(key);
        hdr.extend(keyhdr);
        let hdrkey = hdr.clone();
        let msg =  "a test msg".to_string().into_bytes();
        let orig_msg = Msg::new(uid, channel, msg);
        let encoded_msg = orig_msg.encode();
        hdr.extend(encoded_msg);
        let vec = vec![hdr.clone()];
        let rmsg = ResyncMsg::new(&vec);
        let encoded_resync_msg: Vec<u8> = rmsg.encode();
        let messages = message_decode(encoded_resync_msg, hdrkey);
        assert_eq!(1, messages.len());
        let mut message = messages[0].clone();
        let msg = message.split_off(HDRKEYL);
        let decoded_msg = Msg::decode(msg.as_slice());
        assert_eq!(decoded_msg.uid, orig_msg.uid);
        assert_eq!(decoded_msg.channel, orig_msg.channel);
        assert_eq!(decoded_msg.message, orig_msg.message);
    }

    #[test]
    fn test_message_resync_multi_decode() {
        let uid = "User".to_string();
        let channel = "Channel".to_string();
        let mut keys = Vec::new();
        keys.push(uid.clone());
        keys.push(channel.clone());
        let key = do_hash(&keys);
        let mut hdr: Vec<u8> = write_hdr(122, select_cid(key));
        let keyhdr: Vec<u8> = write_key(key);
        hdr.extend(keyhdr);
        let hdrkey = hdr.clone();
        let msg =  "a test msg".to_string().into_bytes();
        let orig_msg = Msg::new(uid, channel, msg);
        let encoded_msg = orig_msg.encode();
        hdr.extend(encoded_msg);
        let vec = vec![hdr.clone(), hdr.clone()];
        let rmsg = ResyncMsg::new(&vec);
        let encoded_resync_msg: Vec<u8> = rmsg.encode();
        let messages = message_decode(encoded_resync_msg, hdrkey);
        assert_eq!(2, messages.len());
        let mut message = messages[0].clone();
        let msg = message.split_off(HDRKEYL);
        let decoded_msg = Msg::decode(msg.as_slice());
        assert_eq!(decoded_msg.uid, orig_msg.uid);
        assert_eq!(decoded_msg.channel, orig_msg.channel);
        assert_eq!(decoded_msg.message, orig_msg.message);
        let mut message = messages[1].clone();
        let msg = message.split_off(HDRKEYL);
        let decoded_msg = Msg::decode(msg.as_slice());
        assert_eq!(decoded_msg.uid, orig_msg.uid);
        assert_eq!(decoded_msg.channel, orig_msg.channel);
        assert_eq!(decoded_msg.message, orig_msg.message);
    }
}

<|endoftext|>


<commit_before>use lazycell::LazyCell;
use syntect::highlighting::ThemeSet;
use syntect::parsing::SyntaxSet;
use syntect;

pub static DEFAULT_SYNTAX_THEME: &str = "base16-mexico.light";

pub struct SyntaxHighlighter {
    syntax_set: LazyCell<SyntaxSet>,
    theme_set: LazyCell<ThemeSet>,
    theme: String,
}

impl SyntaxHighlighter {
    pub fn new(theme: &str) -> Self {
        SyntaxHighlighter {
            syntax_set: LazyCell::new(),
            theme_set: LazyCell::new(),
            theme: theme.to_owned(),
        }
    }

    pub fn highlight(&self, language: &str, code: &str) -> Result<String, ()> {
        let syntax_set = self.syntax_set.borrow_with(|| SyntaxSet::load_defaults_newlines());
        let theme_set = self.theme_set.borrow_with(|| ThemeSet::load_defaults());

        let syntax = syntax_set.find_syntax_by_extension(language).ok_or(())?;
        let theme = &theme_set.themes[&self.theme];

        Ok(syntect::html::highlighted_snippet_for_string(&code, &syntax, theme))
    }
}
<commit_msg>Fix default syntax theme<commit_after>use lazycell::LazyCell;
use syntect::highlighting::ThemeSet;
use syntect::parsing::SyntaxSet;
use syntect;

pub static DEFAULT_SYNTAX_THEME: &str = "base16-ocean.light";

pub struct SyntaxHighlighter {
    syntax_set: LazyCell<SyntaxSet>,
    theme_set: LazyCell<ThemeSet>,
    theme: String,
}

impl SyntaxHighlighter {
    pub fn new(theme: &str) -> Self {
        SyntaxHighlighter {
            syntax_set: LazyCell::new(),
            theme_set: LazyCell::new(),
            theme: theme.to_owned(),
        }
    }

    pub fn highlight(&self, language: &str, code: &str) -> Result<String, ()> {
        let syntax_set = self.syntax_set.borrow_with(|| SyntaxSet::load_defaults_newlines());
        let theme_set = self.theme_set.borrow_with(|| ThemeSet::load_defaults());

        let syntax = syntax_set.find_syntax_by_extension(language).ok_or(())?;
        let theme = &theme_set.themes[&self.theme];

        Ok(syntect::html::highlighted_snippet_for_string(&code, &syntax, theme))
    }
}
<|endoftext|>


<commit_before>extern crate winapi;
extern crate ws2_32;

use std::io;
use std::os::windows::io::{AsRawSocket, RawSocket};

use winapi::{c_int, LPWSABUF};

use ws2_32::{WSASend, WSARecv};

use ::{Rawv, Writev, Readv};

struct WinSock(RawSocket);

impl<T: AsRawSocket> Rawv for T {
    fn readv(&mut self, buffers: &[&mut [u8]]) -> io::Result<usize> {
        WinSock(self.as_raw_socket()).readv(buffers)
    }

    fn writev(&mut self, buffers: &[&[u8]]) -> io::Result<usize> {
        WinSock(self.as_raw_socket()).writev(buffers)
    }
}

impl Writev for WinSock {
    fn writev(&mut self, buffers: &[&[u8]]) -> io::Result<usize> {
        unsafe {
            let mut bytes = 0;
            let ret = WSASend(
                self.0,
                buffers.as_ptr() as LPWSABUF,
                buffers.len() as c_int,
                &mut bytes,
                0,
                0,
                0
            );
            if ret != 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(bytes as usize)
            }
        }
    }
}

impl Readv for WinSock {
    fn readv(&mut self, buffers: &[&mut [u8]]) -> io::Result<usize> {
        unsafe {
            let mut bytes = 0;
            let ret = WSARecv(
                self.0,
                buffers.as_ptr() as LPWSABUF,
                buffers.len() as c_int,
                &mut bytes,
                0,
                0,
                0
            );
            if ret != 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(ret as usize)
            }
        }
    }
}
<commit_msg>access windows crates using self::<commit_after>extern crate winapi;
extern crate ws2_32;

use std::io;
use std::os::windows::io::{AsRawSocket, RawSocket};

use self::winapi::{c_int, LPWSABUF};

use self::ws2_32::{WSASend, WSARecv};

use ::{Rawv, Writev, Readv};

struct WinSock(RawSocket);

impl<T: AsRawSocket> Rawv for T {
    fn readv(&mut self, buffers: &[&mut [u8]]) -> io::Result<usize> {
        WinSock(self.as_raw_socket()).readv(buffers)
    }

    fn writev(&mut self, buffers: &[&[u8]]) -> io::Result<usize> {
        WinSock(self.as_raw_socket()).writev(buffers)
    }
}

impl Writev for WinSock {
    fn writev(&mut self, buffers: &[&[u8]]) -> io::Result<usize> {
        unsafe {
            let mut bytes = 0;
            let ret = WSASend(
                self.0,
                buffers.as_ptr() as LPWSABUF,
                buffers.len() as c_int,
                &mut bytes,
                0,
                0,
                0
            );
            if ret != 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(bytes as usize)
            }
        }
    }
}

impl Readv for WinSock {
    fn readv(&mut self, buffers: &[&mut [u8]]) -> io::Result<usize> {
        unsafe {
            let mut bytes = 0;
            let ret = WSARecv(
                self.0,
                buffers.as_ptr() as LPWSABUF,
                buffers.len() as c_int,
                &mut bytes,
                0,
                0,
                0
            );
            if ret != 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(ret as usize)
            }
        }
    }
}
<|endoftext|>


<commit_before>use cgmath;
use cgmath::{Matrix4, Point3, Vector3};
use gfx_app::{ColorFormat, DepthFormat};
use gfx;
use physics::Dimensions;
use specs;
use genmesh::{Vertices, Triangulate};
use genmesh::generators::{Plane, SharedVertex, IndexedPolygon};
use terrain::gfx_macros::{TileMapData, VertexData, Projection, pipe, TilemapSettings};
use terrain::controls::InputState;
use game::constants::{TILEMAP_BUF_LENGTH, ASPECT_RATIO};
use gfx_app::graphics::{load_texture};

#[macro_use]
pub mod gfx_macros;
pub mod terrain;
pub mod controls;

fn cartesian_to_isometric(point_x: f32, point_y: f32) -> (f32, f32) {
  ((point_x - point_y), (point_x + point_y) / 2.0)
}

impl TileMapData {
  pub fn new_empty() -> TileMapData {
    TileMapData { data: [32.0, 32.0, 0.0, 0.0] }
  }

  pub fn new(data: [f32; 4]) -> TileMapData {
    TileMapData { data: data }
  }
}

#[derive(Debug)]
pub struct Drawable {
  projection: Projection,
}

impl Drawable {
  pub fn new() -> Drawable {
    let view: Matrix4<f32> = Matrix4::look_at(
      Point3::new(0.0, 0.0, 1000.0),
      Point3::new(0.0, 0.0, 0.0),
      Vector3::unit_y(),
    );

    let aspect_ratio: f32 = ASPECT_RATIO;

    Drawable {
      projection: Projection {
        model: Matrix4::from(view).into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), aspect_ratio, 0.1, 4000.0).into(),
      }
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection) {
    self.projection = *world_to_clip;
  }
}

impl specs::Component for Drawable {
  type Storage = specs::HashMapStorage<Drawable>;
}

const SHADER_VERT: &'static [u8] = include_bytes!("tilemap.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("tilemap.f.glsl");

pub struct DrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<TileMapData>,
}

impl<R: gfx::Resources> DrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>)
                -> DrawSystem<R>
    where F: gfx::Factory<R>
  {
    use gfx::traits::FactoryExt;

    let tile_size = 32;
    let width = 32;
    let height = 32;
    let half_width = (tile_size * width) / 2;
    let half_height = (tile_size * height) / 2;

    let tilesheet_bytes = &include_bytes!("../../assets/maps/terrain.png")[..];
    let plane = Plane::subdivide(width, width);
    let vertex_data: Vec<VertexData> = plane.shared_vertex_iter()
      .map(|vertex| {
        let x = vertex.pos[0];
        let y = vertex.pos[1];
        let (raw_x, raw_y) = cartesian_to_isometric(x, y);
        let vertex_x = half_width as f32 * raw_x;
        let vertex_y = half_height as f32 * raw_y;

        let (u_pos, v_pos) = ((raw_x / 4.0 - raw_y / 2.0) + 0.5, (raw_x / 4.0 + raw_y / 2.0) + 0.5);
        let tilemap_x = u_pos * width as f32;
        let tilemap_y = v_pos * height as f32;

        VertexData {
          pos: [vertex_x, vertex_y, 0.0],
          buf_pos: [tilemap_x as f32, tilemap_y as f32]
        }
      })
      .collect();

    let index_data: Vec<u32> = plane.indexed_polygon_iter()
      .triangulate()
      .vertices()
      .map(|i| i as u32)
      .collect();

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, &index_data[..]);

    let tile_texture = load_texture(factory, tilesheet_bytes).unwrap();

    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      tilemap: factory.create_constant_buffer(TILEMAP_BUF_LENGTH),
      tilemap_cb: factory.create_constant_buffer(1),
      tilesheet: (tile_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    DrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data: terrain::generate().tiles,
    }
  }

  pub fn draw<C>(&mut self,
                 drawable: &Drawable,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_buffer(&self.bundle.data.tilemap, self.data.as_slice(), 0).unwrap();  //tilemap
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.tilemap_cb, &TilemapSettings {
      world_size: [32.0, 32.0, 32.0, 0.0],
      tilesheet_size: [32.0, 32.0, 32.0, 32.0],
      offsets: [0.0, 0.0],
    });

    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<C> specs::System<C> for PreDrawSystem {
  fn run(&mut self, arg: specs::RunArg, _: C) {
    use specs::Join;
    let (mut terrain, dim, mut input) =
      arg.fetch(|w| (
        w.write::<Drawable>(),
        w.read_resource::<Dimensions>(),
        w.write::<InputState>()));

    for (t, i) in (&mut terrain, &mut input).join() {
      let world_to_clip = dim.world_to_clip(i);
      t.update(&world_to_clip);
    }
  }
}
<commit_msg>Use constants to define tilemap size<commit_after>use cgmath;
use cgmath::{Matrix4, Point3, Vector3};
use gfx_app::{ColorFormat, DepthFormat};
use gfx;
use physics::Dimensions;
use specs;
use genmesh::{Vertices, Triangulate};
use genmesh::generators::{Plane, SharedVertex, IndexedPolygon};
use terrain::gfx_macros::{TileMapData, VertexData, Projection, pipe, TilemapSettings};
use terrain::controls::InputState;
use game::constants::{TILEMAP_BUF_LENGTH, ASPECT_RATIO};
use gfx_app::graphics::load_texture;
use game::constants::{TILES_PCS_W, TILES_PCS_H};

#[macro_use]
pub mod gfx_macros;
pub mod terrain;
pub mod controls;

fn cartesian_to_isometric(point_x: f32, point_y: f32) -> (f32, f32) {
  ((point_x - point_y), (point_x + point_y) / 2.0)
}

impl TileMapData {
  pub fn new_empty() -> TileMapData {
    TileMapData { data: [32.0, 32.0, 0.0, 0.0] }
  }

  pub fn new(data: [f32; 4]) -> TileMapData {
    TileMapData { data: data }
  }
}

#[derive(Debug)]
pub struct Drawable {
  projection: Projection,
}

impl Drawable {
  pub fn new() -> Drawable {
    let view: Matrix4<f32> = Matrix4::look_at(
      Point3::new(0.0, 0.0, 1000.0),
      Point3::new(0.0, 0.0, 0.0),
      Vector3::unit_y(),
    );

    let aspect_ratio: f32 = ASPECT_RATIO;

    Drawable {
      projection: Projection {
        model: Matrix4::from(view).into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), aspect_ratio, 0.1, 4000.0).into(),
      }
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection) {
    self.projection = *world_to_clip;
  }
}

impl specs::Component for Drawable {
  type Storage = specs::HashMapStorage<Drawable>;
}

const SHADER_VERT: &'static [u8] = include_bytes!("tilemap.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("tilemap.f.glsl");

pub struct DrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<TileMapData>,
}

impl<R: gfx::Resources> DrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>)
                -> DrawSystem<R>
    where F: gfx::Factory<R>
  {
    use gfx::traits::FactoryExt;

    let tile_size = 32;
    let width = TILES_PCS_W;
    let height = TILES_PCS_H;
    let half_width = (tile_size * width) / 2;
    let half_height = (tile_size * height) / 2;

    let tilesheet_bytes = &include_bytes!("../../assets/maps/terrain.png")[..];
    let plane = Plane::subdivide(width, width);
    let vertex_data: Vec<VertexData> = plane.shared_vertex_iter()
      .map(|vertex| {
        let x = vertex.pos[0];
        let y = vertex.pos[1];
        let (raw_x, raw_y) = cartesian_to_isometric(x, y);
        let vertex_x = half_width as f32 * raw_x;
        let vertex_y = half_height as f32 * raw_y;

        let (u_pos, v_pos) = ((raw_x / 4.0 - raw_y / 2.0) + 0.5, (raw_x / 4.0 + raw_y / 2.0) + 0.5);
        let tilemap_x = u_pos * width as f32;
        let tilemap_y = v_pos * height as f32;

        VertexData {
          pos: [vertex_x, vertex_y, 0.0],
          buf_pos: [tilemap_x as f32, tilemap_y as f32]
        }
      })
      .collect();

    let index_data: Vec<u32> = plane.indexed_polygon_iter()
      .triangulate()
      .vertices()
      .map(|i| i as u32)
      .collect();

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, &index_data[..]);

    let tile_texture = load_texture(factory, tilesheet_bytes).unwrap();

    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      tilemap: factory.create_constant_buffer(TILEMAP_BUF_LENGTH),
      tilemap_cb: factory.create_constant_buffer(1),
      tilesheet: (tile_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    DrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data: terrain::generate().tiles,
    }
  }

  pub fn draw<C>(&mut self,
                 drawable: &Drawable,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_buffer(&self.bundle.data.tilemap, self.data.as_slice(), 0).unwrap();  //tilemap
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.tilemap_cb, &TilemapSettings {
      world_size: [32.0, 32.0, 32.0, 0.0],
      tilesheet_size: [32.0, 32.0, 32.0, 32.0],
      offsets: [0.0, 0.0],
    });

    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<C> specs::System<C> for PreDrawSystem {
  fn run(&mut self, arg: specs::RunArg, _: C) {
    use specs::Join;
    let (mut terrain, dim, mut input) =
      arg.fetch(|w| (
        w.write::<Drawable>(),
        w.read_resource::<Dimensions>(),
        w.write::<InputState>()));

    for (t, i) in (&mut terrain, &mut input).join() {
      let world_to_clip = dim.world_to_clip(i);
      t.update(&world_to_clip);
    }
  }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate time;

use std::ffi::OsStr;
use std::io;
use std::ptr;

use std::os::windows::prelude::OsStrExt;

use self::libc::c_void;
use time::Duration;

use super::ffi::*;
use ::prelude::*;

/// A serial port implementation for Windows COM ports.
pub struct COMPort {
    handle: Handle,
    timeout: Duration
}

impl COMPort {
    /// Opens a COM port as a serial device.
    ///
    /// `port` should be the name of a COM port, e.g., `COM1`.
    ///
    /// ```no_run
    /// serial::windows::COMPort::open("COM1").unwrap();
    /// ```
    pub fn open<T: AsRef<OsStr> + ?Sized>(port: &T) -> io::Result<Self> {
        let mut name: Vec<u16> = port.as_ref().encode_wide().collect();
        name.push(0);

        let handle = unsafe {
            CreateFileW(name.as_ptr(), GENERIC_READ | GENERIC_WRITE, 0, ptr::null_mut(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 as Handle)
        };

        let timeout = Duration::milliseconds(100);

        if handle != INVALID_HANDLE_VALUE {
            let mut port = COMPort {
                handle: handle,
                timeout: timeout
            };

            try!(port.set_timeout(timeout));
            Ok(port)
        }
        else {
            Err(io::Error::last_os_error())
        }
    }
}

impl Drop for COMPort {
    fn drop(&mut self) {
        unsafe {
            CloseHandle(self.handle);
        }
    }
}

impl io::Read for COMPort {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { ReadFile(self.handle, buf.as_mut_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => {
                if len != 0 {
                    Ok(len as usize)
                }
                else {
                    Err(io::Error::new(io::ErrorKind::TimedOut, "operation timed out"))
                }
            }
        }
    }
}

impl io::Write for COMPort {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { WriteFile(self.handle, buf.as_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(len as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match unsafe { FlushFileBuffers(self.handle) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(())
        }
    }
}

impl SerialPort for COMPort {
    type Settings = COMSettings;

    fn read_settings(&self) -> ::Result<COMSettings> {
        let mut dcb = DCB::new();

        match unsafe { GetCommState(self.handle, &mut dcb) } {
            0 => Err(From::from(io::Error::last_os_error())),
            _ => Ok(COMSettings { inner: dcb })

        }
    }

    fn write_settings(&mut self, settings: &COMSettings) -> ::Result<()> {
        match unsafe { SetCommState(self.handle, &settings.inner) } {
            0 => Err(From::from(io::Error::last_os_error())),
            _ => Ok(())
        }
    }

    fn timeout(&self) -> Duration {
        self.timeout
    }

    fn set_timeout(&mut self, timeout: Duration) -> ::Result<()> {
        let timeouts = COMMTIMEOUTS {
            ReadIntervalTimeout: 0,
            ReadTotalTimeoutMultiplier: 0,
            ReadTotalTimeoutConstant: timeout.num_milliseconds() as DWORD,
            WriteTotalTimeoutMultiplier: 0,
            WriteTotalTimeoutConstant: 0
        };

        if unsafe { SetCommTimeouts(self.handle, &timeouts) } == 0 {
            return Err(From::from(io::Error::last_os_error()));
        }

        self.timeout = timeout;
        Ok(())
    }
}

/// Serial port settings for COM ports.
#[derive(Copy,Clone,Debug)]
pub struct COMSettings {
    inner: DCB
}

impl SerialPortSettings for COMSettings {
    fn baud_rate(&self) -> Option<::BaudRate> {
        match self.inner.BaudRate {
            CBR_110    => Some(::Baud110),
            CBR_300    => Some(::Baud300),
            CBR_600    => Some(::Baud600),
            CBR_1200   => Some(::Baud1200),
            CBR_2400   => Some(::Baud2400),
            CBR_4800   => Some(::Baud4800),
            CBR_9600   => Some(::Baud9600),
            CBR_14400  => Some(::BaudOther(14400)),
            CBR_19200  => Some(::Baud19200),
            CBR_38400  => Some(::Baud38400),
            CBR_56000  => Some(::BaudOther(56000)),
            CBR_57600  => Some(::Baud57600),
            CBR_115200 => Some(::Baud115200),
            CBR_128000 => Some(::BaudOther(128000)),
            CBR_256000 => Some(::BaudOther(256000)),
            n          => Some(::BaudOther(n as usize))
        }
    }

    fn char_size(&self) -> Option<::CharSize> {
        match self.inner.ByteSize {
            5 => Some(::Bits5),
            6 => Some(::Bits6),
            7 => Some(::Bits7),
            8 => Some(::Bits8),
            _ => None
        }
    }

    fn parity(&self) -> Option<::Parity> {
        match self.inner.Parity {
            ODDPARITY  => Some(::ParityOdd),
            EVENPARITY => Some(::ParityEven),
            NOPARITY   => Some(::ParityNone),
            _          => None
        }
    }

    fn stop_bits(&self) -> Option<::StopBits> {
        match self.inner.StopBits {
            TWOSTOPBITS => Some(::Stop2),
            ONESTOPBIT  => Some(::Stop1),
            _           => None
        }
    }

    fn flow_control(&self) -> Option<::FlowControl> {
        if self.inner.fBits & (fOutxCtsFlow | fRtsControl) != 0 {
            Some(::FlowHardware)
        }
        else if self.inner.fBits & (fOutX | fInX) != 0 {
            Some(::FlowSoftware)
        }
        else {
            Some(::FlowNone)
        }
    }

    fn set_baud_rate(&mut self, baud_rate: ::BaudRate) -> ::Result<()> {
        self.inner.BaudRate = match baud_rate {
            ::Baud110      => CBR_110,
            ::Baud300      => CBR_300,
            ::Baud600      => CBR_600,
            ::Baud1200     => CBR_1200,
            ::Baud2400     => CBR_2400,
            ::Baud4800     => CBR_4800,
            ::Baud9600     => CBR_9600,
            ::Baud19200    => CBR_19200,
            ::Baud38400    => CBR_38400,
            ::Baud57600    => CBR_57600,
            ::Baud115200   => CBR_115200,
            ::BaudOther(n) => n as DWORD
        };

        Ok(())
    }

    fn set_char_size(&mut self, char_size: ::CharSize) {
        self.inner.ByteSize = match char_size {
            ::Bits5 => 5,
            ::Bits6 => 6,
            ::Bits7 => 7,
            ::Bits8 => 8
        }
    }

    fn set_parity(&mut self, parity: ::Parity) {
        self.inner.Parity = match parity {
            ::ParityNone => NOPARITY,
            ::ParityOdd  => ODDPARITY,
            ::ParityEven => EVENPARITY
        }
    }

    fn set_stop_bits(&mut self, stop_bits: ::StopBits) {
        self.inner.StopBits = match stop_bits {
            ::Stop1 => ONESTOPBIT,
            ::Stop2 => TWOSTOPBITS
        }
    }

    fn set_flow_control(&mut self, flow_control: ::FlowControl) {
        match flow_control {
            ::FlowNone => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits &= !(fOutX | fInX);
            },
            ::FlowSoftware => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits |= fOutX | fInX;
            },
            ::FlowHardware => {
                self.inner.fBits |= fOutxCtsFlow | fRtsControl;
                self.inner.fBits &= !(fOutX | fInX);
            }
        }
    }
}
<commit_msg>implements AsRawHandle on COMPort<commit_after>extern crate libc;
extern crate time;

use std::ffi::OsStr;
use std::io;
use std::mem;
use std::ptr;

use std::os::windows::io::{RawHandle,AsRawHandle};
use std::os::windows::prelude::OsStrExt;

use self::libc::c_void;
use time::Duration;

use super::ffi::*;
use ::prelude::*;

/// A serial port implementation for Windows COM ports.
pub struct COMPort {
    handle: Handle,
    timeout: Duration
}

impl COMPort {
    /// Opens a COM port as a serial device.
    ///
    /// `port` should be the name of a COM port, e.g., `COM1`.
    ///
    /// ```no_run
    /// serial::windows::COMPort::open("COM1").unwrap();
    /// ```
    pub fn open<T: AsRef<OsStr> + ?Sized>(port: &T) -> io::Result<Self> {
        let mut name: Vec<u16> = port.as_ref().encode_wide().collect();
        name.push(0);

        let handle = unsafe {
            CreateFileW(name.as_ptr(), GENERIC_READ | GENERIC_WRITE, 0, ptr::null_mut(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 as Handle)
        };

        let timeout = Duration::milliseconds(100);

        if handle != INVALID_HANDLE_VALUE {
            let mut port = COMPort {
                handle: handle,
                timeout: timeout
            };

            try!(port.set_timeout(timeout));
            Ok(port)
        }
        else {
            Err(io::Error::last_os_error())
        }
    }
}

impl Drop for COMPort {
    fn drop(&mut self) {
        unsafe {
            CloseHandle(self.handle);
        }
    }
}

impl AsRawHandle for COMPort {
    fn as_raw_handle(&self) -> RawHandle {
        unsafe {
            mem::transmute(self.handle)
        }
    }
}

impl io::Read for COMPort {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { ReadFile(self.handle, buf.as_mut_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => {
                if len != 0 {
                    Ok(len as usize)
                }
                else {
                    Err(io::Error::new(io::ErrorKind::TimedOut, "operation timed out"))
                }
            }
        }
    }
}

impl io::Write for COMPort {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { WriteFile(self.handle, buf.as_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(len as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match unsafe { FlushFileBuffers(self.handle) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(())
        }
    }
}

impl SerialPort for COMPort {
    type Settings = COMSettings;

    fn read_settings(&self) -> ::Result<COMSettings> {
        let mut dcb = DCB::new();

        match unsafe { GetCommState(self.handle, &mut dcb) } {
            0 => Err(From::from(io::Error::last_os_error())),
            _ => Ok(COMSettings { inner: dcb })

        }
    }

    fn write_settings(&mut self, settings: &COMSettings) -> ::Result<()> {
        match unsafe { SetCommState(self.handle, &settings.inner) } {
            0 => Err(From::from(io::Error::last_os_error())),
            _ => Ok(())
        }
    }

    fn timeout(&self) -> Duration {
        self.timeout
    }

    fn set_timeout(&mut self, timeout: Duration) -> ::Result<()> {
        let timeouts = COMMTIMEOUTS {
            ReadIntervalTimeout: 0,
            ReadTotalTimeoutMultiplier: 0,
            ReadTotalTimeoutConstant: timeout.num_milliseconds() as DWORD,
            WriteTotalTimeoutMultiplier: 0,
            WriteTotalTimeoutConstant: 0
        };

        if unsafe { SetCommTimeouts(self.handle, &timeouts) } == 0 {
            return Err(From::from(io::Error::last_os_error()));
        }

        self.timeout = timeout;
        Ok(())
    }
}

/// Serial port settings for COM ports.
#[derive(Copy,Clone,Debug)]
pub struct COMSettings {
    inner: DCB
}

impl SerialPortSettings for COMSettings {
    fn baud_rate(&self) -> Option<::BaudRate> {
        match self.inner.BaudRate {
            CBR_110    => Some(::Baud110),
            CBR_300    => Some(::Baud300),
            CBR_600    => Some(::Baud600),
            CBR_1200   => Some(::Baud1200),
            CBR_2400   => Some(::Baud2400),
            CBR_4800   => Some(::Baud4800),
            CBR_9600   => Some(::Baud9600),
            CBR_14400  => Some(::BaudOther(14400)),
            CBR_19200  => Some(::Baud19200),
            CBR_38400  => Some(::Baud38400),
            CBR_56000  => Some(::BaudOther(56000)),
            CBR_57600  => Some(::Baud57600),
            CBR_115200 => Some(::Baud115200),
            CBR_128000 => Some(::BaudOther(128000)),
            CBR_256000 => Some(::BaudOther(256000)),
            n          => Some(::BaudOther(n as usize))
        }
    }

    fn char_size(&self) -> Option<::CharSize> {
        match self.inner.ByteSize {
            5 => Some(::Bits5),
            6 => Some(::Bits6),
            7 => Some(::Bits7),
            8 => Some(::Bits8),
            _ => None
        }
    }

    fn parity(&self) -> Option<::Parity> {
        match self.inner.Parity {
            ODDPARITY  => Some(::ParityOdd),
            EVENPARITY => Some(::ParityEven),
            NOPARITY   => Some(::ParityNone),
            _          => None
        }
    }

    fn stop_bits(&self) -> Option<::StopBits> {
        match self.inner.StopBits {
            TWOSTOPBITS => Some(::Stop2),
            ONESTOPBIT  => Some(::Stop1),
            _           => None
        }
    }

    fn flow_control(&self) -> Option<::FlowControl> {
        if self.inner.fBits & (fOutxCtsFlow | fRtsControl) != 0 {
            Some(::FlowHardware)
        }
        else if self.inner.fBits & (fOutX | fInX) != 0 {
            Some(::FlowSoftware)
        }
        else {
            Some(::FlowNone)
        }
    }

    fn set_baud_rate(&mut self, baud_rate: ::BaudRate) -> ::Result<()> {
        self.inner.BaudRate = match baud_rate {
            ::Baud110      => CBR_110,
            ::Baud300      => CBR_300,
            ::Baud600      => CBR_600,
            ::Baud1200     => CBR_1200,
            ::Baud2400     => CBR_2400,
            ::Baud4800     => CBR_4800,
            ::Baud9600     => CBR_9600,
            ::Baud19200    => CBR_19200,
            ::Baud38400    => CBR_38400,
            ::Baud57600    => CBR_57600,
            ::Baud115200   => CBR_115200,
            ::BaudOther(n) => n as DWORD
        };

        Ok(())
    }

    fn set_char_size(&mut self, char_size: ::CharSize) {
        self.inner.ByteSize = match char_size {
            ::Bits5 => 5,
            ::Bits6 => 6,
            ::Bits7 => 7,
            ::Bits8 => 8
        }
    }

    fn set_parity(&mut self, parity: ::Parity) {
        self.inner.Parity = match parity {
            ::ParityNone => NOPARITY,
            ::ParityOdd  => ODDPARITY,
            ::ParityEven => EVENPARITY
        }
    }

    fn set_stop_bits(&mut self, stop_bits: ::StopBits) {
        self.inner.StopBits = match stop_bits {
            ::Stop1 => ONESTOPBIT,
            ::Stop2 => TWOSTOPBITS
        }
    }

    fn set_flow_control(&mut self, flow_control: ::FlowControl) {
        match flow_control {
            ::FlowNone => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits &= !(fOutX | fInX);
            },
            ::FlowSoftware => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits |= fOutX | fInX;
            },
            ::FlowHardware => {
                self.inner.fBits |= fOutxCtsFlow | fRtsControl;
                self.inner.fBits &= !(fOutX | fInX);
            }
        }
    }
}
<|endoftext|>