<commit_before>mod object;
mod pointer;

pub use self::{
    object::{Builtin, Closure, Data, Int, Object, Struct, Symbol, Text},
    pointer::Pointer,
};
use crate::builtin_functions::BuiltinFunction;
use itertools::Itertools;
use num_bigint::BigInt;
use std::{cmp::Ordering, collections::HashMap};

#[derive(Clone)]
pub struct Heap {
    objects: HashMap<Pointer, Object>,
    next_address: Pointer,
}

impl std::fmt::Debug for Heap {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut objects = self.objects.clone().into_iter().collect_vec();
        objects.sort_by_key(|(address, _)| address.raw());

        writeln!(f, "{{")?;
        for (address, object) in objects {
            writeln!(
                f,
                "{address}: {} {}",
                object.reference_count,
                address.format(self),
            )?;
        }
        write!(f, "}}")
    }
}

impl Default for Heap {
    fn default() -> Self {
        Self {
            objects: HashMap::new(),
            next_address: Pointer::from_raw(1),
        }
    }
}
impl Heap {
    pub fn get(&self, address: Pointer) -> &Object {
        self.objects
            .get(&address)
            .unwrap_or_else(|| panic!("Couldn't get object {address}."))
    }
    pub fn get_mut(&mut self, address: Pointer) -> &mut Object {
        self.objects
            .get_mut(&address)
            .unwrap_or_else(|| panic!("Couldn't get object {address}."))
    }

    pub fn dup(&mut self, address: Pointer) {
        self.get_mut(address).reference_count += 1;
        log::trace!(
            "RefCount of {address} increased to {}. Value: {}",
            self.get(address).reference_count,
            address.format(self),
        );
    }
    pub fn drop(&mut self, address: Pointer) {
        let formatted_value = address.format(self);
        let object = self.get_mut(address);
        object.reference_count -= 1;
        log::trace!(
            "RefCount of {address} reduced to {}. Value: {formatted_value}",
            object.reference_count,
        );
        if object.reference_count == 0 {
            self.free(address);
        }
    }

    pub fn create(&mut self, object: Data) -> Pointer {
        let address = self.next_address;
        self.objects.insert(
            address,
            Object {
                reference_count: 1,
                data: object,
            },
        );
        log::trace!("Created object {} at {address}.", address.format(self));
        self.next_address = Pointer::from_raw(self.next_address.raw() + 1);
        address
    }
    pub fn free(&mut self, address: Pointer) {
        let object = self.objects.remove(&address).unwrap();
        log::trace!("Freeing object at {address}.");
        assert_eq!(object.reference_count, 0);
        for child in object.children() {
            self.drop(child);
        }
    }

    /// Clones all objects at the `root_addresses` into the `other` heap and
    /// returns a list of their addresses in the other heap.
    pub fn clone_multiple_to_other_heap(
        &self,
        other: &mut Heap,
        addresses: &[Pointer],
    ) -> Vec<Pointer> {
        let mut objects_to_refcounts = HashMap::new();
        for address in addresses {
            self.gather_objects_to_clone(&mut objects_to_refcounts, *address);
        }
        let mut mapped_addresses = vec![];
        for (address, refcount) in objects_to_refcounts {
            mapped_addresses.push(other.create(self.get(address).data.clone()));
            other.get_mut(address).reference_count = refcount;
        }
        mapped_addresses
    }
    fn gather_objects_to_clone(
        &self,
        objects_to_refcounts: &mut HashMap<Pointer, usize>,
        address: Pointer,
    ) {
        *objects_to_refcounts.entry(address).or_default() += 1;
        for child in self.get(address).children() {
            self.gather_objects_to_clone(objects_to_refcounts, child);
        }
    }
    pub fn clone_single_to_other_heap(&self, other: &mut Heap, address: Pointer) -> Pointer {
        self.clone_multiple_to_other_heap(other, &[address])
            .pop()
            .unwrap()
    }

    pub fn create_int(&mut self, int: BigInt) -> Pointer {
        self.create(Data::Int(Int { value: int }))
    }
    pub fn create_text(&mut self, text: String) -> Pointer {
        self.create(Data::Text(Text { value: text }))
    }
    pub fn create_symbol(&mut self, symbol: String) -> Pointer {
        self.create(Data::Symbol(Symbol { value: symbol }))
    }
    pub fn create_struct(&mut self, fields: HashMap<Pointer, Pointer>) -> Pointer {
        self.create(Data::Struct(Struct::from_fields(self, fields)))
    }
    pub fn create_closure(&mut self, closure: Closure) -> Pointer {
        self.create(Data::Closure(closure))
    }
    pub fn create_builtin(&mut self, builtin: BuiltinFunction) -> Pointer {
        self.create(Data::Builtin(Builtin { function: builtin }))
    }
    pub fn create_nothing(&mut self) -> Pointer {
        self.create_symbol("Nothing".to_string())
    }
    pub fn create_list(&mut self, items: Vec<Pointer>) -> Pointer {
        let mut fields = vec![];
        for (index, item) in items.into_iter().enumerate() {
            fields.push((self.create_int(index.into()), item));
        }
        self.create_struct(fields.into_iter().collect())
    }
    pub fn create_bool(&mut self, value: bool) -> Pointer {
        self.create_symbol(if value { "True" } else { "False" }.to_string())
    }
    pub fn create_result(&mut self, result: Result<Pointer, Pointer>) -> Pointer {
        let (type_, value) = match result {
            Ok(it) => ("Ok".to_string(), it),
            Err(it) => ("Error".to_string(), it),
        };
        let fields = vec![
            (
                self.create_symbol("Type".to_string()),
                self.create_symbol(type_),
            ),
            (self.create_symbol("Value".to_string()), value),
        ]
        .into_iter()
        .collect();
        self.create_struct(fields)
    }
    pub fn create_ordering(&mut self, ordering: Ordering) -> Pointer {
        self.create_symbol(
            match ordering {
                Ordering::Less => "Less",
                Ordering::Equal => "Equal",
                Ordering::Greater => "Greater",
            }
            .to_string(),
        )
    }
}
<commit_msg>Fix object transfers<commit_after>mod object;
mod pointer;

pub use self::{
    object::{Builtin, Closure, Data, Int, Object, Struct, Symbol, Text},
    pointer::Pointer,
};
use crate::builtin_functions::BuiltinFunction;
use itertools::Itertools;
use num_bigint::BigInt;
use std::{cmp::Ordering, collections::HashMap};

#[derive(Clone)]
pub struct Heap {
    objects: HashMap<Pointer, Object>,
    next_address: Pointer,
}

impl std::fmt::Debug for Heap {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut objects = self.objects.clone().into_iter().collect_vec();
        objects.sort_by_key(|(address, _)| address.raw());

        writeln!(f, "{{")?;
        for (address, object) in objects {
            writeln!(
                f,
                "{address}: {} {}",
                object.reference_count,
                address.format(self),
            )?;
        }
        write!(f, "}}")
    }
}

impl Default for Heap {
    fn default() -> Self {
        Self {
            objects: HashMap::new(),
            next_address: Pointer::from_raw(1),
        }
    }
}
impl Heap {
    pub fn get(&self, address: Pointer) -> &Object {
        self.objects
            .get(&address)
            .unwrap_or_else(|| panic!("Couldn't get object {address}."))
    }
    pub fn get_mut(&mut self, address: Pointer) -> &mut Object {
        self.objects
            .get_mut(&address)
            .unwrap_or_else(|| panic!("Couldn't get object {address}."))
    }

    pub fn dup(&mut self, address: Pointer) {
        self.get_mut(address).reference_count += 1;
        log::trace!(
            "RefCount of {address} increased to {}. Value: {}",
            self.get(address).reference_count,
            address.format(self),
        );
    }
    pub fn drop(&mut self, address: Pointer) {
        let formatted_value = address.format(self);
        let object = self.get_mut(address);
        object.reference_count -= 1;
        log::trace!(
            "RefCount of {address} reduced to {}. Value: {formatted_value}",
            object.reference_count,
        );
        if object.reference_count == 0 {
            self.free(address);
        }
    }

    pub fn create(&mut self, object: Data) -> Pointer {
        let address = self.next_address;
        self.objects.insert(
            address,
            Object {
                reference_count: 1,
                data: object,
            },
        );
        log::trace!("Created object {} at {address}.", address.format(self));
        self.next_address = Pointer::from_raw(self.next_address.raw() + 1);
        address
    }
    pub fn free(&mut self, address: Pointer) {
        let object = self.objects.remove(&address).unwrap();
        log::trace!("Freeing object at {address}.");
        assert_eq!(object.reference_count, 0);
        for child in object.children() {
            self.drop(child);
        }
    }

    /// Clones all objects at the `root_addresses` into the `other` heap and
    /// returns a list of their addresses in the other heap.
    pub fn clone_multiple_to_other_heap(
        &self,
        other: &mut Heap,
        addresses: &[Pointer],
    ) -> Vec<Pointer> {
        let mut objects_to_refcounts = HashMap::new();
        for address in addresses {
            self.gather_objects_to_clone(&mut objects_to_refcounts, *address);
        }
        let num_objects = objects_to_refcounts.len();

        let address_map: HashMap<Pointer, Pointer> = objects_to_refcounts
            .keys()
            .cloned()
            .zip(
                (other.next_address.raw()..other.next_address.raw() + num_objects)
                    .map(Pointer::from_raw),
            )
            .collect();

        for (address, refcount) in objects_to_refcounts {
            other.objects.insert(
                address_map[&address],
                Object {
                    reference_count: refcount,
                    data: Self::map_addresses_in_data(&address_map, &self.get(address).data),
                },
            );
        }
        other.next_address = Pointer::from_raw(other.next_address.raw() + num_objects);

        addresses
            .iter()
            .map(|address| address_map[address])
            .collect()
    }
    fn gather_objects_to_clone(
        &self,
        objects_to_refcounts: &mut HashMap<Pointer, usize>,
        address: Pointer,
    ) {
        *objects_to_refcounts.entry(address).or_default() += 1;
        for child in self.get(address).children() {
            self.gather_objects_to_clone(objects_to_refcounts, child);
        }
    }
    fn map_addresses_in_data(address_map: &HashMap<Pointer, Pointer>, data: &Data) -> Data {
        match data {
            Data::Int(int) => Data::Int(int.clone()),
            Data::Text(text) => Data::Text(text.clone()),
            Data::Symbol(symbol) => Data::Symbol(symbol.clone()),
            Data::Struct(struct_) => Data::Struct(Struct {
                fields: struct_
                    .fields
                    .iter()
                    .map(|(hash, key, value)| (*hash, address_map[key], address_map[value]))
                    .collect_vec(),
            }),
            Data::Closure(closure) => Data::Closure(Closure {
                captured: closure
                    .captured
                    .iter()
                    .map(|address| address_map[address])
                    .collect(),
                num_args: closure.num_args,
                body: closure.body.clone(),
            }),
            Data::Builtin(builtin) => Data::Builtin(builtin.clone()),
        }
    }
    pub fn clone_single_to_other_heap(&self, other: &mut Heap, address: Pointer) -> Pointer {
        self.clone_multiple_to_other_heap(other, &[address])
            .pop()
            .unwrap()
    }

    pub fn create_int(&mut self, int: BigInt) -> Pointer {
        self.create(Data::Int(Int { value: int }))
    }
    pub fn create_text(&mut self, text: String) -> Pointer {
        self.create(Data::Text(Text { value: text }))
    }
    pub fn create_symbol(&mut self, symbol: String) -> Pointer {
        self.create(Data::Symbol(Symbol { value: symbol }))
    }
    pub fn create_struct(&mut self, fields: HashMap<Pointer, Pointer>) -> Pointer {
        self.create(Data::Struct(Struct::from_fields(self, fields)))
    }
    pub fn create_closure(&mut self, closure: Closure) -> Pointer {
        self.create(Data::Closure(closure))
    }
    pub fn create_builtin(&mut self, builtin: BuiltinFunction) -> Pointer {
        self.create(Data::Builtin(Builtin { function: builtin }))
    }
    pub fn create_nothing(&mut self) -> Pointer {
        self.create_symbol("Nothing".to_string())
    }
    pub fn create_list(&mut self, items: Vec<Pointer>) -> Pointer {
        let mut fields = vec![];
        for (index, item) in items.into_iter().enumerate() {
            fields.push((self.create_int(index.into()), item));
        }
        self.create_struct(fields.into_iter().collect())
    }
    pub fn create_bool(&mut self, value: bool) -> Pointer {
        self.create_symbol(if value { "True" } else { "False" }.to_string())
    }
    pub fn create_result(&mut self, result: Result<Pointer, Pointer>) -> Pointer {
        let (type_, value) = match result {
            Ok(it) => ("Ok".to_string(), it),
            Err(it) => ("Error".to_string(), it),
        };
        let fields = vec![
            (
                self.create_symbol("Type".to_string()),
                self.create_symbol(type_),
            ),
            (self.create_symbol("Value".to_string()), value),
        ]
        .into_iter()
        .collect();
        self.create_struct(fields)
    }
    pub fn create_ordering(&mut self, ordering: Ordering) -> Pointer {
        self.create_symbol(
            match ordering {
                Ordering::Less => "Less",
                Ordering::Equal => "Equal",
                Ordering::Greater => "Greater",
            }
            .to_string(),
        )
    }
}
<|endoftext|>


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

//! Starts a service from an installed Habitat package.
//!
//! Services run by the Supervisor support one or more *topologies*, which are state machines that
//! handle the lifecycle of a service; they are members of a *group*, which is a namespace for
//! their configuration and state.
//!
//! # Examples
//!
//! ```bash
//! $ hab-sup start acme/redis
//! ```
//!
//! Will start the `redis` service in the `default` group, using the `standalone` topology.
//!
//! ```bash
//! $ hab-sup start acme/redis -g production
//! ```
//!
//! Will do the same, but in the `production` group.
//!
//! ```bash
//! $ hab-sup start acme/redis -t leader
//! ```
//!
//! Will start the `redis` service using the `leader` topology.
//!
//! ```bash
//! $ hab-sup start acme/redis -t leader -g production
//! ```
//!
//! Will start the `redis` service using the `leader` topology in the `production` group.
//!
//! See the [documentation on topologies](../topology) for a deeper discussion of how they function.
//!

use std;
use std::path::Path;

use ansi_term::Colour::Yellow;
use common;
use common::ui::UI;
use hcore::fs::{self, FS_ROOT_PATH};

use {PRODUCT, VERSION};
use error::{Error, Result};
use feat;
use manager::{Manager, ManagerConfig};
use manager::ServiceSpec;

static LOGKEY: &'static str = "CS";

pub fn package(cfg: ManagerConfig,
               service_spec: Option<ServiceSpec>,
               local_artifact: Option<&str>)
               -> Result<()> {
    let mut ui = UI::default();
    if !fs::am_i_root() {
        ui.warn("Running the Habitat Supervisor requires root or administrator privileges. \
                   Please retry this command as a super user or use a privilege-granting \
                   facility such as sudo.")?;
        ui.br()?;
        return Err(sup_error!(Error::RootRequired));
    }

    // TODO fn: once we remove the `Multi` feature flag a refactoring of this function will clean
    // things up substantially. If it looks slightly awkward, this was done with an eye to the end
    // state, not this intermediate state. Cheers!

    if let Some(spec) = service_spec.as_ref() {
        if let Some(artifact) = local_artifact {
            outputln!("Installing local artifact {}",
                      Yellow.bold().paint(artifact));
            common::command::package::install::start(&mut ui,
                                                     &spec.depot_url,
                                                     artifact,
                                                     PRODUCT,
                                                     VERSION,
                                                     Path::new(&*FS_ROOT_PATH),
                                                     &fs::cache_artifact_path(None),
                                                     false)?;
        }
    }

    if feat::is_enabled(feat::Multi) {
        if let Some(spec) = service_spec {
            // If we're starting with a package, then we assume that any prior specs are out of
            // date.  TODO fn: there are some assumptions to be tested here...
            let specs_path = Manager::specs_path_for(&cfg);
            if specs_path.exists() && specs_path.is_dir() {
                std::fs::remove_dir_all(specs_path)?;
            }
            Manager::save_spec_for(&cfg, spec)?;
        }

        let mut manager = Manager::load(cfg)?;
        manager.run()
    } else {
        let mut manager = Manager::load(cfg)?;
        if let Some(spec) = service_spec {
            manager.add_service(spec)?;
        }
        manager.run()
    }
}
<commit_msg>removes root requirement for running hab start, now only warns rather than fails<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Starts a service from an installed Habitat package.
//!
//! Services run by the Supervisor support one or more *topologies*, which are state machines that
//! handle the lifecycle of a service; they are members of a *group*, which is a namespace for
//! their configuration and state.
//!
//! # Examples
//!
//! ```bash
//! $ hab-sup start acme/redis
//! ```
//!
//! Will start the `redis` service in the `default` group, using the `standalone` topology.
//!
//! ```bash
//! $ hab-sup start acme/redis -g production
//! ```
//!
//! Will do the same, but in the `production` group.
//!
//! ```bash
//! $ hab-sup start acme/redis -t leader
//! ```
//!
//! Will start the `redis` service using the `leader` topology.
//!
//! ```bash
//! $ hab-sup start acme/redis -t leader -g production
//! ```
//!
//! Will start the `redis` service using the `leader` topology in the `production` group.
//!
//! See the [documentation on topologies](../topology) for a deeper discussion of how they function.
//!

use std;
use std::path::Path;

use ansi_term::Colour::Yellow;
use common;
use common::ui::UI;
use hcore::fs::{self, FS_ROOT_PATH};

use {PRODUCT, VERSION};
use error::{Error, Result};
use feat;
use manager::{Manager, ManagerConfig};
use manager::ServiceSpec;

static LOGKEY: &'static str = "CS";

pub fn package(cfg: ManagerConfig,
               service_spec: Option<ServiceSpec>,
               local_artifact: Option<&str>)
               -> Result<()> {
    let mut ui = UI::default();
    if !fs::am_i_root() {
        ui.warn("Running the Habitat Supervisor with root or superuser privileges is recommended")?;
        ui.br()?;
    }

    // TODO fn: once we remove the `Multi` feature flag a refactoring of this function will clean
    // things up substantially. If it looks slightly awkward, this was done with an eye to the end
    // state, not this intermediate state. Cheers!

    if let Some(spec) = service_spec.as_ref() {
        if let Some(artifact) = local_artifact {
            outputln!("Installing local artifact {}",
                      Yellow.bold().paint(artifact));
            common::command::package::install::start(&mut ui,
                                                     &spec.depot_url,
                                                     artifact,
                                                     PRODUCT,
                                                     VERSION,
                                                     Path::new(&*FS_ROOT_PATH),
                                                     &fs::cache_artifact_path(None),
                                                     false)?;
        }
    }

    if feat::is_enabled(feat::Multi) {
        if let Some(spec) = service_spec {
            // If we're starting with a package, then we assume that any prior specs are out of
            // date.  TODO fn: there are some assumptions to be tested here...
            let specs_path = Manager::specs_path_for(&cfg);
            if specs_path.exists() && specs_path.is_dir() {
                std::fs::remove_dir_all(specs_path)?;
            }
            Manager::save_spec_for(&cfg, spec)?;
        }

        let mut manager = Manager::load(cfg)?;
        manager.run()
    } else {
        let mut manager = Manager::load(cfg)?;
        if let Some(spec) = service_spec {
            manager.add_service(spec)?;
        }
        manager.run()
    }
}
<|endoftext|>


<commit_before>use std::f64;
use std::cmp::min;
use std::num::Float;
use std::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use elem;
use elem::Molecule;
use error::{CTResult, CTError};
use error::CTErrorKind::InputError;

macro_rules! impl_matrix_index {
    ($idx:ty, $out:ty) => {
        impl Index<$idx> for Matrix {
            type Output = $out;

            fn index(&self, index: &$idx) -> &$out {
                &self.buf[*index]
            }
        }
    }
}

macro_rules! impl_matrix_index_mut {
    ($idx:ty, $out:ty) => {
        impl IndexMut<$idx> for Matrix {
            fn index_mut(&mut self, index: &$idx) -> &mut $out {
                &mut self.buf[*index]
            }
        }
    }
}

pub fn pretty_print_balanced(reaction: &(Vec<Molecule>, Vec<Molecule>), coefs: &Vec<u32>) {
    let &(ref lhs, ref rhs) = reaction;
    print!("{} {}", coefs[0], lhs[0]);
    for (coef, molecule) in coefs.iter().zip(lhs.iter()).skip(1) {
        print!(" + {} {}", coef, molecule);
    }
    print!(" -> ");
    print!("{} {}", coefs[lhs.len()], rhs[0]);
    for (coef, molecule) in coefs.iter().skip(lhs.len()).zip(rhs.iter()).skip(1) {
        print!(" + {} {}", coef, molecule);
    }
    println!("");
}

/// Balances a chemical reaction using Gaussian elimination
pub fn balance_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> CTResult<Vec<u32>> {
    let reac_mat = Matrix::from_reaction(reaction);
    let reduced_mat = try!(forward_elim(reac_mat));
    let coefs = back_substitute(&reduced_mat);

    // if any of the coefs are 0, then an element in that molecule is missing on the other side
    // of the reaction
    if let Some(pos) = coefs.iter().position(|&c| c == 0.0) {
        let &(ref lhs, ref rhs) = reaction;
        let molecule = lhs.iter().chain(rhs.iter()).nth(pos).unwrap();
        let begin = molecule.first().unwrap().pos;
        let len = molecule.last().unwrap().pos + molecule.last().unwrap().len - begin;
        return Err(CTError {
            kind: InputError,
            desc: format!("An element in {} is missing on the other side of the reaction",
                          molecule),
            pos: Some((begin, len)),
        })
    }

    // we find the minimum element with fold, since f64 does not implement Ord...
    let min = coefs.iter().fold(f64::INFINITY, |crnt, &num| {
        if num < crnt {
            num
        } else {
            crnt
        }
    });
    // now we divide all elements by the minimum to (hopefully) convert them all to intergers
    // after which we do the actual conversion
    // we also reverse the Vec so the coefs are in the right order
    Ok(coefs.iter().rev().map(|n| (n / min) as u32).collect())
}

fn column_abs_max_index(columns: &[Vec<f64>], column: usize) -> usize {
    let mut max = 0;
    for i in 1..columns.len() {
        if columns[i][column].abs() > columns[max][column].abs() {
            max = i;
        }
    }
    max
}

fn forward_elim(mut mat: Matrix) -> CTResult<Matrix> {
    for k in 0..min(mat.width(), mat.height()) {
        // locate the pivot
        let pivot = column_abs_max_index(&mat[k..], k) + k;
        if mat[pivot][k] == 0_f64 {
            return Err(CTError {
                kind: InputError,
                desc: "Could not balance reaction".to_string(),
                pos: None,
            })
        }
        // move the pivot to its new position
        mat.switch_rows(k, pivot);

        // zero out the rest of the column
        for i in k + 1..mat.height() {
            let mult = -(mat[i][k] / mat[k][k]);
            mat.add_row_to_row(i, k, mult);
        }
    }
    Ok(mat)
}

fn back_substitute(mat: &Matrix) -> Vec<f64> {
    let mut vars = Vec::with_capacity(mat.width());
    for k in (0..mat.width()).rev() {
        if k >= mat.height() {
            // if this coef does not have a corresponding row in the matrix, then treat is as a
            // free variable and set it to 1
            vars.push(1_f64);
        } else {
            let mut var = 0f64;
            for i in k + 1..mat.width() {
                var -= mat[k][i] * vars[mat.width() - 1 - i];
            }
            vars.push(var / mat[k][k]);
        }
    }
    vars
}

#[derive(Debug, PartialEq)]
struct Matrix {
    buf: Vec<Vec<f64>>,
    height: usize,
    width: usize,
}

impl Matrix {
    fn from_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> Matrix {
        let &(ref lhs, ref rhs) = reaction;
        let lhs: Vec<Molecule> = lhs.clone().into_iter().map(|m| elem::group_elems(m)).collect();
        let rhs: Vec<Molecule> = rhs.clone().into_iter().map(|m| elem::group_elems(m)).collect();
        let mut names = Vec::<&str>::new();
        for molecule in lhs.iter().chain(rhs.iter()) {
            for elem in molecule.iter() {
                if names.iter().find(|e| **e == elem.name).is_none() {
                    names.push(elem.name.as_slice());
                }
            }
        }
        let mut buf = Vec::with_capacity(names.len());
        for name in names.iter() {
            let mut row = Vec::with_capacity(lhs.len() + rhs.len());
            for molecule in lhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(e.coef as f64))
                                 .unwrap_or(0_f64));
            }
            // we loop over rhs seperately, since we need to multiply the coefs with -1
            for molecule in rhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(-1.0*(e.coef as f64)))
                                 .unwrap_or(0_f64));
            }
            buf.push(row);
        }
        let height = names.len();
        let width = lhs.len() + rhs.len();
        Matrix {
            buf: buf,
            height: height,
            width: width,
        }
    }

    fn add_row_to_row(&mut self, dest: usize, row: usize, mult: f64) {
        for i in 0..self.width {
            let incr = self.buf[row][i] * mult;
            self.buf[dest][i] += incr;
        }
    }

    fn switch_rows(&mut self, row1: usize, row2: usize)  {
        self.buf.swap(row1, row2);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn height(&self) -> usize {
        self.height
    }
}

impl_matrix_index!(usize, Vec<f64>);
impl_matrix_index!(Range<usize>, [Vec<f64>]);
impl_matrix_index!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFull, [Vec<f64>]);

impl_matrix_index_mut!(usize, Vec<f64>);
impl_matrix_index_mut!(Range<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFull, [Vec<f64>]);

#[cfg(test)]
mod test {
    use super::*;
    use elem::PerElem;
    use error::CTErrorKind::InputError;

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn balance() {
        // attempt to balance C3H8 + O2 -> CO2 + H2O
        let reaction = (vec!(vec!(dummy_elem!("C", 3), dummy_elem!("H", 8)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn balance_non_grouped() {
        let reaction = (vec!(vec!(dummy_elem!("C"), dummy_elem!("H", 3), dummy_elem!("C"),
                                  dummy_elem!("H", 2), dummy_elem!("C"), dummy_elem!("H", 3)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn no_balance_needed() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 1, 1, 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn missing_elem() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1))));
        let result = balance_reaction(&reaction);
        println!("{:?}", result);
        assert!(result.is_err());
        assert_eq!(result.err().unwrap().kind, InputError);
    }
}<commit_msg>Add some doc comments to the balancer<commit_after>use std::f64;
use std::cmp::min;
use std::num::Float;
use std::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use elem;
use elem::Molecule;
use error::{CTResult, CTError};
use error::CTErrorKind::InputError;

macro_rules! impl_matrix_index {
    ($idx:ty, $out:ty) => {
        impl Index<$idx> for Matrix {
            type Output = $out;

            fn index(&self, index: &$idx) -> &$out {
                &self.buf[*index]
            }
        }
    }
}

macro_rules! impl_matrix_index_mut {
    ($idx:ty, $out:ty) => {
        impl IndexMut<$idx> for Matrix {
            fn index_mut(&mut self, index: &$idx) -> &mut $out {
                &mut self.buf[*index]
            }
        }
    }
}

/// Takes a parsed reaction and pretty prints it to the console
///
/// The reaction is printed as follows:
/// <coef> <molecule> + <coef> <molecule> + ... -> <coef> <molecule> + <coef> <molecule> + ...
pub fn pretty_print_balanced(reaction: &(Vec<Molecule>, Vec<Molecule>), coefs: &Vec<u32>) {
    let &(ref lhs, ref rhs) = reaction;
    print!("{} {}", coefs[0], lhs[0]);
    for (coef, molecule) in coefs.iter().zip(lhs.iter()).skip(1) {
        print!(" + {} {}", coef, molecule);
    }
    print!(" -> ");
    print!("{} {}", coefs[lhs.len()], rhs[0]);
    for (coef, molecule) in coefs.iter().skip(lhs.len()).zip(rhs.iter()).skip(1) {
        print!(" + {} {}", coef, molecule);
    }
    println!("");
}

/// Balances a chemical reaction using Gaussian elimination and returns the coefficients
///
/// The balancer finds the coefficients needed to balance the reaction by treating the reaction as
/// a system of linear equations and then solving the system with Gaussian elimination.
/// The transformation to an equation system (represented as a matrix `R`) is as follows:
/// * Each column corresponds to a molecule
/// * Each row corresponds to a periodic element.
/// * The number at `R[i,j]` is the amount of periocic element `i` in molecule `j`.
/// * Numbers from molecules on the right hand side of the equation will be negative.
/// Thus we can now solve the system to find a linear combination of the columns which will result
/// in a zero-vector, and then read the coefficients from the solution.
pub fn balance_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> CTResult<Vec<u32>> {
    let reac_mat = Matrix::from_reaction(reaction);
    let reduced_mat = try!(forward_elim(reac_mat));
    let coefs = back_substitute(&reduced_mat);

    // if any of the coefs are 0, then an element in that molecule is missing on the other side
    // of the reaction
    if let Some(pos) = coefs.iter().position(|&c| c == 0.0) {
        let &(ref lhs, ref rhs) = reaction;
        let molecule = lhs.iter().chain(rhs.iter()).nth(pos).unwrap();
        let begin = molecule.first().unwrap().pos;
        let len = molecule.last().unwrap().pos + molecule.last().unwrap().len - begin;
        return Err(CTError {
            kind: InputError,
            desc: format!("An element in {} is missing on the other side of the reaction",
                          molecule),
            pos: Some((begin, len)),
        })
    }

    // we find the minimum element with fold, since f64 does not implement Ord...
    let min = coefs.iter().fold(f64::INFINITY, |crnt, &num| {
        if num < crnt {
            num
        } else {
            crnt
        }
    });
    // now we divide all elements by the minimum to (hopefully) convert them all to intergers
    // after which we do the actual conversion
    // we also reverse the Vec so the coefs are in the right order
    Ok(coefs.iter().rev().map(|n| (n / min) as u32).collect())
}

fn column_abs_max_index(columns: &[Vec<f64>], column: usize) -> usize {
    let mut max = 0;
    for i in 1..columns.len() {
        if columns[i][column].abs() > columns[max][column].abs() {
            max = i;
        }
    }
    max
}

fn forward_elim(mut mat: Matrix) -> CTResult<Matrix> {
    for k in 0..min(mat.width(), mat.height()) {
        // locate the pivot
        let pivot = column_abs_max_index(&mat[k..], k) + k;
        if mat[pivot][k] == 0_f64 {
            return Err(CTError {
                kind: InputError,
                desc: "Could not balance reaction".to_string(),
                pos: None,
            })
        }
        // move the pivot to its new position
        mat.switch_rows(k, pivot);

        // zero out the rest of the column
        for i in k + 1..mat.height() {
            let mult = -(mat[i][k] / mat[k][k]);
            mat.add_row_to_row(i, k, mult);
        }
    }
    Ok(mat)
}

fn back_substitute(mat: &Matrix) -> Vec<f64> {
    let mut vars = Vec::with_capacity(mat.width());
    for k in (0..mat.width()).rev() {
        if k >= mat.height() {
            // if this coef does not have a corresponding row in the matrix, then treat is as a
            // free variable and set it to 1
            vars.push(1_f64);
        } else {
            let mut var = 0f64;
            for i in k + 1..mat.width() {
                var -= mat[k][i] * vars[mat.width() - 1 - i];
            }
            vars.push(var / mat[k][k]);
        }
    }
    vars
}

#[derive(Debug, PartialEq)]
struct Matrix {
    buf: Vec<Vec<f64>>,
    height: usize,
    width: usize,
}

impl Matrix {
    fn from_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> Matrix {
        let &(ref lhs, ref rhs) = reaction;
        let lhs: Vec<Molecule> = lhs.clone().into_iter().map(|m| elem::group_elems(m)).collect();
        let rhs: Vec<Molecule> = rhs.clone().into_iter().map(|m| elem::group_elems(m)).collect();
        let mut names = Vec::<&str>::new();
        // gather up all the element names in the reaction so we now how many rows will be needed
        for molecule in lhs.iter().chain(rhs.iter()) {
            for elem in molecule.iter() {
                if names.iter().find(|e| **e == elem.name).is_none() {
                    names.push(elem.name.as_slice());
                }
            }
        }
        let mut buf = Vec::with_capacity(names.len());
        for name in names.iter() {
            let mut row = Vec::with_capacity(lhs.len() + rhs.len());
            for molecule in lhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(e.coef as f64))
                                 .unwrap_or(0_f64));
            }
            // we loop over rhs seperately, since we need to multiply the coefs with -1
            for molecule in rhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(-1.0*(e.coef as f64)))
                                 .unwrap_or(0_f64));
            }
            buf.push(row);
        }
        let height = names.len();
        let width = lhs.len() + rhs.len();
        Matrix {
            buf: buf,
            height: height,
            width: width,
        }
    }

    fn add_row_to_row(&mut self, dest: usize, row: usize, mult: f64) {
        for i in 0..self.width {
            let incr = self.buf[row][i] * mult;
            self.buf[dest][i] += incr;
        }
    }

    fn switch_rows(&mut self, row1: usize, row2: usize)  {
        self.buf.swap(row1, row2);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn height(&self) -> usize {
        self.height
    }
}

impl_matrix_index!(usize, Vec<f64>);
impl_matrix_index!(Range<usize>, [Vec<f64>]);
impl_matrix_index!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFull, [Vec<f64>]);

impl_matrix_index_mut!(usize, Vec<f64>);
impl_matrix_index_mut!(Range<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFull, [Vec<f64>]);

#[cfg(test)]
mod test {
    use super::*;
    use elem::PerElem;
    use error::CTErrorKind::InputError;

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn balance() {
        // attempt to balance C3H8 + O2 -> CO2 + H2O
        let reaction = (vec!(vec!(dummy_elem!("C", 3), dummy_elem!("H", 8)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn balance_non_grouped() {
        let reaction = (vec!(vec!(dummy_elem!("C"), dummy_elem!("H", 3), dummy_elem!("C"),
                                  dummy_elem!("H", 2), dummy_elem!("C"), dummy_elem!("H", 3)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn no_balance_needed() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 1, 1, 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn missing_elem() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1))));
        let result = balance_reaction(&reaction);
        println!("{:?}", result);
        assert!(result.is_err());
        assert_eq!(result.err().unwrap().kind, InputError);
    }
}<|endoftext|>


<commit_before>/// A TOML [1] configuration file parser
///
/// [1]: https://github.com/mojombo/toml

use std::io::mem::MemReader;
use std::io::File;
use std::hashmap::HashMap;

fn read_char(rd: &mut MemReader) -> char {
  match rd.read_byte() {
    Some(b) => b as char,
    None => fail!()
  }
}

fn read_char_opt(rd: &mut MemReader) -> Option<char> {
  match rd.read_byte() {
    Some(b) => Some(b as char),
    None => None
  }
}

#[deriving(ToStr)]
enum Value {
    True,
    False,
    Unsigned(u64),
    Integer(i64),
    Float(f64),
    String(~str),
    Array(~[Value]),
    Datetime, // XXX
    Map(HashMap<~str, Value>) // XXX: This is no value
}

// parse values recursivly
fn parse_value(rd: &mut MemReader) -> Value {
    enum State {
        st_value,
        st_number,
        st_got_number
    }

    let mut state: State = st_value;
    let mut val: ~str = ~"";

    loop {
        match state {
            st_value => {
                if rd.eof() { fail!() }
                let ch = read_char(rd);
                match ch {
                    '\r' | '\n' | ' ' | '\t' => { }
                    '0' .. '9' => {
                        val.push_char(ch);
                        state = st_number;
                    }
                    't' => {
                        assert!(read_char(rd) == 'r');
                        assert!(read_char(rd) == 'u');
                        assert!(read_char(rd) == 'e');
                        return True
                    }
                    'f' => {
                        assert!(read_char(rd) == 'a');
                        assert!(read_char(rd) == 'l');
                        assert!(read_char(rd) == 's');
                        assert!(read_char(rd) == 'e');
                        return False
                    }
                    '"' => {
                        loop {
                            let ch = read_char(rd);
                            if ch == '"' {
                                break;
                            }
                            val.push_char(ch);
                        }
                        return String(val)
                    }
                    _ => { fail!() }
                }
            }
            st_got_number => {
                return Unsigned(from_str(val).unwrap())
            }
            st_number => {
                if rd.eof() {
                    state = st_got_number;
                } else {
                    let ch = read_char(rd);
                    match ch {
                        '\r' | '\n' | ' ' | '\t' => { state = st_got_number }
                        '#' => { skip_comment(rd); state = st_got_number }
                        '0' .. '9' => {
                            val.push_char(ch);
                        }
                        _ => { fail!() }
                    }
                }
            }
        }
    }
}

// We must be already within the '#"
fn skip_comment(rd: &mut MemReader) {
    loop {
        if rd.eof() { return }
        match read_char(rd) {
            '\n' => { return }
            _ => { }
        }
    }
}

trait Visitor {
    fn section(&mut self, name: ~str, is_array: bool) -> bool;
    fn pair(&mut self, key: ~str, val: Value) -> bool;
}

struct TOMLVisitor {
    root: HashMap<~str, Value>,
    current_path: ~str,
    is_array: bool
}

impl TOMLVisitor {
    fn new() -> TOMLVisitor {
        TOMLVisitor { root: HashMap::new(), current_path: ~"", is_array: false }
    }
    fn get_root<'a>(&'a self) -> &'a HashMap<~str, Value> {
        return &self.root;
    }
}

impl Visitor for TOMLVisitor {
    fn section(&mut self, name: ~str, is_array: bool) -> bool {
        debug!("Section: {} (is_array={})", name, is_array);
        self.is_array = is_array;
        self.current_path = name;
        return true
    }
    fn pair(&mut self, key: ~str, val: Value) -> bool {
        debug!("Pair: {} {:s}", key, val.to_str());
        let mut m = self.root.find_or_insert(self.current_path.clone(), Map(HashMap::new())); // XXX: remove clone
        match *m {
            Map(ref mut map) => {
                let ok = map.insert(key, val);
                return ok
            }
            _ => { return false }
        }
    }
}

fn read_token(rd: &mut MemReader, current_char: Option<char>, f: |char| -> bool) -> (~str, Option<char>) {
    let mut current_char = current_char;
    let mut token = ~"";
    loop {
        match current_char {
            Some(ch) => {
                if f(ch) { token.push_char(ch) }
                else { break }
            }
            None => { break }
        }
        current_char = read_char_opt(rd); // advance
    }

    return (token, current_char);
}

fn parse_section_identifier(rd: &mut MemReader, current_char: Option<char>) -> (~str, Option<char>) {
    read_token(rd, current_char, |ch| {
        match ch {
            'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '.' | '_' => true,
            _ => false
        }
    })
}

fn skip_whitespaces(rd: &mut MemReader, current_char: Option<char>) -> Option<char> {
    let mut current_char = current_char;
    loop {
        match current_char {
            Some(' ') | Some('\t') | Some('\r') | Some('\n') => {
                current_char = read_char_opt(rd); // advance
            }
            _ => { break }
        }
    }
    return current_char;
}

fn parse<V: Visitor>(rd: &mut MemReader, visitor: &mut V) -> bool {
    let mut current_char: Option<char> = read_char_opt(rd);

    loop {
        if current_char.is_none() { return true }
        let ch = current_char.unwrap();
        match ch {
            // ignore whitespace
            '\r' | '\n' | ' ' | '\t' => { }

            // comment
            '#' => {
                // skip to end of line
                loop {
                    current_char = read_char_opt(rd);
                    match current_char {
                        Some('\n') => { break }
                        None => { return true }
                        _ => { /* skip */ }
                    }
                }
            }

            // section
            '[' => {
                current_char = read_char_opt(rd); // advance
                let mut double_section = false;
                match current_char {
                    Some('[') => {
                        double_section = true;
                        current_char = read_char_opt(rd); // advance
                    }
                    _ => {}
                }

                let (section_name, ch) = parse_section_identifier(rd, current_char);
                current_char = ch;

                match current_char {
                    Some(']') => { /* ok */ }
                    _ => { return false }
                }

                if double_section {
                    current_char = read_char_opt(rd); // advance
                    if current_char != Some(']') { return false }
                }

                visitor.section(section_name, double_section);
            }

            // identifier
            'a' .. 'z' | 'A' .. 'Z' | '_' => {

                let (ident, ch) = read_token(rd, current_char, |ch| {
                    match ch {
                        'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' => true,
                        _ => false
                    }
                });

                current_char = ch;
                current_char = skip_whitespaces(rd, current_char);

                // assign wanted
                if current_char != Some('=') { return false }

                // XXX: current_char = read_char_opt(rd); // advance
                visitor.pair(ident, parse_value(rd)); // XXX: parse_value is not using peeking yet
            }

            _ => { return false }
        } /* end match */
        current_char = read_char_opt(rd); // advance
    }

    assert!(false);
}

fn main() {
  let contents = File::open(&Path::new(std::os::args()[1])).read_to_end();
  let mut rd = MemReader::new(contents);
  let mut visitor = TOMLVisitor::new();
  parse(&mut rd, &mut visitor);
  println!("{:s}", visitor.get_root().to_str());
}
<commit_msg>Rename a few variables<commit_after>/// A TOML [1] configuration file parser
///
/// [1]: https://github.com/mojombo/toml

use std::io::mem::MemReader;
use std::io::File;
use std::hashmap::HashMap;

fn read_char(rd: &mut MemReader) -> char {
  match rd.read_byte() {
    Some(b) => b as char,
    None => fail!()
  }
}

fn read_char_opt(rd: &mut MemReader) -> Option<char> {
  match rd.read_byte() {
    Some(b) => Some(b as char),
    None => None
  }
}

#[deriving(ToStr)]
enum Value {
    True,
    False,
    Unsigned(u64),
    Integer(i64),
    Float(f64),
    String(~str),
    Array(~[Value]),
    Datetime, // XXX
    Map(HashMap<~str, Value>) // XXX: This is no value
}

// parse values recursivly
fn parse_value(rd: &mut MemReader) -> Value {
    enum State {
        st_value,
        st_number,
        st_got_number
    }

    let mut state: State = st_value;
    let mut val: ~str = ~"";

    loop {
        match state {
            st_value => {
                if rd.eof() { fail!() }
                let ch = read_char(rd);
                match ch {
                    '\r' | '\n' | ' ' | '\t' => { }
                    '0' .. '9' => {
                        val.push_char(ch);
                        state = st_number;
                    }
                    't' => {
                        assert!(read_char(rd) == 'r');
                        assert!(read_char(rd) == 'u');
                        assert!(read_char(rd) == 'e');
                        return True
                    }
                    'f' => {
                        assert!(read_char(rd) == 'a');
                        assert!(read_char(rd) == 'l');
                        assert!(read_char(rd) == 's');
                        assert!(read_char(rd) == 'e');
                        return False
                    }
                    '"' => {
                        loop {
                            let ch = read_char(rd);
                            if ch == '"' {
                                break;
                            }
                            val.push_char(ch);
                        }
                        return String(val)
                    }
                    _ => { fail!() }
                }
            }
            st_got_number => {
                return Unsigned(from_str(val).unwrap())
            }
            st_number => {
                if rd.eof() {
                    state = st_got_number;
                } else {
                    let ch = read_char(rd);
                    match ch {
                        '\r' | '\n' | ' ' | '\t' => { state = st_got_number }
                        '#' => { skip_comment(rd); state = st_got_number }
                        '0' .. '9' => {
                            val.push_char(ch);
                        }
                        _ => { fail!() }
                    }
                }
            }
        }
    }
}

// We must be already within the '#"
fn skip_comment(rd: &mut MemReader) {
    loop {
        if rd.eof() { return }
        match read_char(rd) {
            '\n' => { return }
            _ => { }
        }
    }
}

trait Visitor {
    fn section(&mut self, name: ~str, is_array: bool) -> bool;
    fn pair(&mut self, key: ~str, val: Value) -> bool;
}

struct TOMLVisitor {
    root: HashMap<~str, Value>,
    current_section: ~str,
    section_is_array: bool
}

impl TOMLVisitor {
    fn new() -> TOMLVisitor {
        TOMLVisitor { root: HashMap::new(), current_section: ~"", section_is_array: false }
    }
    fn get_root<'a>(&'a self) -> &'a HashMap<~str, Value> {
        return &self.root;
    }
}

impl Visitor for TOMLVisitor {
    fn section(&mut self, name: ~str, is_array: bool) -> bool {
        debug!("Section: {} (is_array={})", name, is_array);
        self.section_is_array = is_array;
        self.current_section = name;
        return true
    }
    fn pair(&mut self, key: ~str, val: Value) -> bool {
        debug!("Pair: {} {:s}", key, val.to_str());
        let mut m = self.root.find_or_insert(self.current_section.clone(), Map(HashMap::new())); // XXX: remove clone
        match *m {
            Map(ref mut map) => {
                let ok = map.insert(key, val);
                return ok
            }
            _ => { return false }
        }
    }
}

fn read_token(rd: &mut MemReader, current_char: Option<char>, f: |char| -> bool) -> (~str, Option<char>) {
    let mut current_char = current_char;
    let mut token = ~"";
    loop {
        match current_char {
            Some(ch) => {
                if f(ch) { token.push_char(ch) }
                else { break }
            }
            None => { break }
        }
        current_char = read_char_opt(rd); // advance
    }

    return (token, current_char);
}

fn parse_section_identifier(rd: &mut MemReader, current_char: Option<char>) -> (~str, Option<char>) {
    read_token(rd, current_char, |ch| {
        match ch {
            'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '.' | '_' => true,
            _ => false
        }
    })
}

fn skip_whitespaces(rd: &mut MemReader, current_char: Option<char>) -> Option<char> {
    let mut current_char = current_char;
    loop {
        match current_char {
            Some(' ') | Some('\t') | Some('\r') | Some('\n') => {
                current_char = read_char_opt(rd); // advance
            }
            _ => { break }
        }
    }
    return current_char;
}

fn parse<V: Visitor>(rd: &mut MemReader, visitor: &mut V) -> bool {
    let mut current_char: Option<char> = read_char_opt(rd);

    loop {
        if current_char.is_none() { return true }
        let ch = current_char.unwrap();
        match ch {
            // ignore whitespace
            '\r' | '\n' | ' ' | '\t' => { }

            // comment
            '#' => {
                // skip to end of line
                loop {
                    current_char = read_char_opt(rd);
                    match current_char {
                        Some('\n') => { break }
                        None => { return true }
                        _ => { /* skip */ }
                    }
                }
            }

            // section
            '[' => {
                current_char = read_char_opt(rd); // advance
                let mut double_section = false;
                match current_char {
                    Some('[') => {
                        double_section = true;
                        current_char = read_char_opt(rd); // advance
                    }
                    _ => {}
                }

                let (section_name, ch) = parse_section_identifier(rd, current_char);
                current_char = ch;

                match current_char {
                    Some(']') => { /* ok */ }
                    _ => { return false }
                }

                if double_section {
                    current_char = read_char_opt(rd); // advance
                    if current_char != Some(']') { return false }
                }

                visitor.section(section_name, double_section);
            }

            // identifier
            'a' .. 'z' | 'A' .. 'Z' | '_' => {

                let (ident, ch) = read_token(rd, current_char, |ch| {
                    match ch {
                        'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' => true,
                        _ => false
                    }
                });

                current_char = ch;
                current_char = skip_whitespaces(rd, current_char);

                // assign wanted
                if current_char != Some('=') { return false }

                // XXX: current_char = read_char_opt(rd); // advance
                visitor.pair(ident, parse_value(rd)); // XXX: parse_value is not using peeking yet
            }

            _ => { return false }
        } /* end match */
        current_char = read_char_opt(rd); // advance
    }

    assert!(false);
}

fn main() {
  let contents = File::open(&Path::new(std::os::args()[1])).read_to_end();
  let mut rd = MemReader::new(contents);
  let mut visitor = TOMLVisitor::new();
  parse(&mut rd, &mut visitor);
  println!("{:s}", visitor.get_root().to_str());
}
<|endoftext|>


<commit_before>use crate::term2;
use std::fmt;
use std::io::Write;
use term2::Terminal;

macro_rules! warn {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::warn_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}
macro_rules! err {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::err_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}
macro_rules! info {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::info_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}

macro_rules! verbose {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::verbose_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}

macro_rules! debug {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::debug_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}

pub fn warn_fmt(args: fmt::Arguments<'_>) {
    let mut t = term2::stderr();
    let _ = t.fg(term2::color::YELLOW);
    let _ = t.attr(term2::Attr::Bold);
    let _ = write!(t, "warning: ");
    let _ = t.reset();
    let _ = t.write_fmt(args);
    let _ = writeln!(t);
}

pub fn err_fmt(args: fmt::Arguments<'_>) {
    let mut t = term2::stderr();
    let _ = t.fg(term2::color::RED);
    let _ = t.attr(term2::Attr::Bold);
    let _ = write!(t, "error: ");
    let _ = t.reset();
    let _ = t.write_fmt(args);
    let _ = writeln!(t);
}

pub fn info_fmt(args: fmt::Arguments<'_>) {
    let mut t = term2::stderr();
    let _ = t.attr(term2::Attr::Bold);
    let _ = write!(t, "info: ");
    let _ = t.reset();
    let _ = t.write_fmt(args);
    let _ = writeln!(t);
}

pub fn verbose_fmt(args: fmt::Arguments<'_>) {
    let mut t = term2::stderr();
    let _ = t.fg(term2::color::MAGENTA);
    let _ = t.attr(term2::Attr::Bold);
    let _ = write!(t, "verbose: ");
    let _ = t.reset();
    let _ = t.write_fmt(args);
    let _ = writeln!(t);
}

pub fn debug_fmt(args: fmt::Arguments<'_>) {
    if std::env::var("RUSTUP_DEBUG").is_ok() {
        let mut t = term2::stderr();
        let _ = t.fg(term2::color::BLUE);
        let _ = t.attr(term2::Attr::Bold);
        let _ = write!(t, "verbose: ");
        let _ = t.reset();
        let _ = t.write_fmt(args);
        let _ = writeln!(t);
    }
}
<commit_msg>log: Debug should be prefixed 'debug:'<commit_after>use crate::term2;
use std::fmt;
use std::io::Write;
use term2::Terminal;

macro_rules! warn {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::warn_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}
macro_rules! err {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::err_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}
macro_rules! info {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::info_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}

macro_rules! verbose {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::verbose_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}

macro_rules! debug {
    ( $ ( $ arg : tt ) * ) => ( $crate::log::debug_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
}

pub fn warn_fmt(args: fmt::Arguments<'_>) {
    let mut t = term2::stderr();
    let _ = t.fg(term2::color::YELLOW);
    let _ = t.attr(term2::Attr::Bold);
    let _ = write!(t, "warning: ");
    let _ = t.reset();
    let _ = t.write_fmt(args);
    let _ = writeln!(t);
}

pub fn err_fmt(args: fmt::Arguments<'_>) {
    let mut t = term2::stderr();
    let _ = t.fg(term2::color::RED);
    let _ = t.attr(term2::Attr::Bold);
    let _ = write!(t, "error: ");
    let _ = t.reset();
    let _ = t.write_fmt(args);
    let _ = writeln!(t);
}

pub fn info_fmt(args: fmt::Arguments<'_>) {
    let mut t = term2::stderr();
    let _ = t.attr(term2::Attr::Bold);
    let _ = write!(t, "info: ");
    let _ = t.reset();
    let _ = t.write_fmt(args);
    let _ = writeln!(t);
}

pub fn verbose_fmt(args: fmt::Arguments<'_>) {
    let mut t = term2::stderr();
    let _ = t.fg(term2::color::MAGENTA);
    let _ = t.attr(term2::Attr::Bold);
    let _ = write!(t, "verbose: ");
    let _ = t.reset();
    let _ = t.write_fmt(args);
    let _ = writeln!(t);
}

pub fn debug_fmt(args: fmt::Arguments<'_>) {
    if std::env::var("RUSTUP_DEBUG").is_ok() {
        let mut t = term2::stderr();
        let _ = t.fg(term2::color::BLUE);
        let _ = t.attr(term2::Attr::Bold);
        let _ = write!(t, "debug: ");
        let _ = t.reset();
        let _ = t.write_fmt(args);
        let _ = writeln!(t);
    }
}
<|endoftext|>


<commit_before>use core::prelude::*;
use arch::Registers;
use stack;

pub struct Context<Stack: stack::Stack> {
  regs: Registers,
  _stack: Stack
}

impl<Stack> Context<Stack> where Stack: stack::Stack {
  #[inline]
  pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<Stack>
    where F: FnOnce() + Send + 'static {
    let regs = Registers::new(&mut stack, f);
    Context {
      regs: regs,
      _stack: stack
    }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    self.regs.swap()
  }
}
<commit_msg>add Context::destroy<commit_after>use core::prelude::*;
use arch::Registers;
use stack;

pub struct Context<Stack: stack::Stack> {
  regs: Registers,
  stack: Stack
}

impl<Stack> Context<Stack> where Stack: stack::Stack {
  #[inline]
  pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<Stack>
    where F: FnOnce() + Send + 'static {
    let regs = Registers::new(&mut stack, f);
    Context {
      regs: regs,
      stack: stack
    }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    self.regs.swap()
  }

  pub unsafe fn destroy(self) -> Stack {
    self.stack
  }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use arrayvec::ArrayVec;
use collect_slice::CollectSlice;
use thread_scoped;

use coefs::Coefficients;
use consts::SAMPLES_PER_FRAME;
use descramble::{descramble, Bootstrap};
use enhance::{self, EnhancedSpectrals, FrameEnergy};
use errors::Errors;
use gain::Gains;
use params::BaseParams;
use prev::PrevFrame;
use spectral::Spectrals;
use unvoiced::{UnvoicedDFT, Unvoiced};
use voiced::{Phase, PhaseBase, Voiced};

const THREADS: usize = 4;

pub struct CAIFrame {
    chunks: [u32; 8],
    errors: [usize; 7],
}

impl CAIFrame {
    pub fn new(chunks: [u32; 8], errors: [usize; 7]) -> CAIFrame {
        CAIFrame {
            chunks: chunks,
            errors: errors,
        }
    }
}

pub struct IMBEDecoder {
    prev: PrevFrame,
}

impl IMBEDecoder {
    pub fn new() -> IMBEDecoder {
        IMBEDecoder {
            prev: PrevFrame::default(),
        }
    }

    pub fn decode(&mut self, frame: CAIFrame, buf: &mut [f32; SAMPLES_PER_FRAME]) {
        let period = match Bootstrap::new(&frame.chunks) {
            Bootstrap::Period(p) => p,
            Bootstrap::Invalid => {
                self.repeat(buf);
                return;
            },
            Bootstrap::Silence => {
                self.silence(buf);
                return;
            },
        };

        let errors = Errors::new(&frame.errors, self.prev.err_rate);

        if enhance::should_repeat(&errors) {
            self.repeat(buf);
            return;
        }

        if enhance::should_mute(&errors) {
            self.silence(buf);
            return;
        }

        let params = BaseParams::new(period);
        let (amps, mut voice, gain_idx) = descramble(&frame.chunks, &params);
        let gains = Gains::new(gain_idx, &amps, &params);
        let coefs = Coefficients::new(&gains, &amps, &params);
        let spectrals = Spectrals::new(&coefs, &params, &self.prev);
        let energy = FrameEnergy::new(&spectrals, &self.prev.energy, &params);

        let mut enhanced = EnhancedSpectrals::new(&spectrals, &energy, &params);
        let amp_thresh = enhance::amp_thresh(&errors, self.prev.amp_thresh);
        enhance::smooth(&mut enhanced, &mut voice, &errors, &energy, amp_thresh);

        let udft = UnvoicedDFT::new(&params, &voice, &enhanced);
        let vbase = PhaseBase::new(&params, &self.prev);
        let vphase = Phase::new(&params, &voice, &vbase);

        {
            let unvoiced = Arc::new(Unvoiced::new(&udft, &self.prev.unvoiced));
            let voiced = Arc::new(Voiced::new(&params, &self.prev, &vphase, &enhanced, &voice));

            let mut threads = buf.chunks_mut(SAMPLES_PER_FRAME / THREADS).enumerate().map(|(i, chunk)| {
                let u = unvoiced.clone();
                let v = voiced.clone();

                let start = i * SAMPLES_PER_FRAME / THREADS;
                let stop = start + SAMPLES_PER_FRAME / THREADS;

                unsafe {
                    thread_scoped::scoped(move || {
                        (start..stop)
                            .map(|n| u.get(n) + v.get(n))
                            .collect_slice(&mut chunk[..]);
                    })
                }
            }).collect::<ArrayVec<[thread_scoped::JoinGuard<()>; THREADS]>>();

            for thread in threads.drain(..) {
                thread.join();
            }
        }

        self.prev = PrevFrame {
            params: params,
            spectrals: spectrals,
            enhanced: enhanced,
            voice: voice,
            err_rate: errors.rate,
            energy: energy,
            amp_thresh: amp_thresh,
            unvoiced: udft,
            phase_base: vbase,
            phase: vphase,
        };
    }

    fn silence(&self, buf: &mut [f32; SAMPLES_PER_FRAME]) {
        (0..SAMPLES_PER_FRAME).map(|_| 0.0).collect_slice(&mut buf[..]);
    }

    fn repeat(&self, buf: &mut [f32; SAMPLES_PER_FRAME]) {
        let params = self.prev.params.clone();
        let voice = self.prev.voice.clone();
        let enhanced = self.prev.enhanced.clone();

        let udft = UnvoicedDFT::new(&params, &voice, &enhanced);
        let vbase = PhaseBase::new(&params, &self.prev);
        let vphase = Phase::new(&params, &voice, &vbase);

        let unvoiced = Unvoiced::new(&udft, &self.prev.unvoiced);
        let voiced = Voiced::new(&params, &self.prev, &vphase, &enhanced, &voice);

        (0..SAMPLES_PER_FRAME)
            .map(|n| unvoiced.get(n) + voiced.get(n))
            .collect_slice(&mut buf[..]);
    }
}
<commit_msg>Add SAMPLES_PER_THREAD constant<commit_after>use std::sync::Arc;

use arrayvec::ArrayVec;
use collect_slice::CollectSlice;
use thread_scoped;

use coefs::Coefficients;
use consts::SAMPLES_PER_FRAME;
use descramble::{descramble, Bootstrap};
use enhance::{self, EnhancedSpectrals, FrameEnergy};
use errors::Errors;
use gain::Gains;
use params::BaseParams;
use prev::PrevFrame;
use spectral::Spectrals;
use unvoiced::{UnvoicedDFT, Unvoiced};
use voiced::{Phase, PhaseBase, Voiced};

/// Number of threads to spin up per frame.
const THREADS: usize = 4;
/// Number of samples to process in each thread.
const SAMPLES_PER_THREAD: usize = SAMPLES_PER_FRAME / THREADS;

pub struct CAIFrame {
    chunks: [u32; 8],
    errors: [usize; 7],
}

impl CAIFrame {
    pub fn new(chunks: [u32; 8], errors: [usize; 7]) -> CAIFrame {
        CAIFrame {
            chunks: chunks,
            errors: errors,
        }
    }
}

pub struct IMBEDecoder {
    prev: PrevFrame,
}

impl IMBEDecoder {
    pub fn new() -> IMBEDecoder {
        IMBEDecoder {
            prev: PrevFrame::default(),
        }
    }

    pub fn decode(&mut self, frame: CAIFrame, buf: &mut [f32; SAMPLES_PER_FRAME]) {
        let period = match Bootstrap::new(&frame.chunks) {
            Bootstrap::Period(p) => p,
            Bootstrap::Invalid => {
                self.repeat(buf);
                return;
            },
            Bootstrap::Silence => {
                self.silence(buf);
                return;
            },
        };

        let errors = Errors::new(&frame.errors, self.prev.err_rate);

        if enhance::should_repeat(&errors) {
            self.repeat(buf);
            return;
        }

        if enhance::should_mute(&errors) {
            self.silence(buf);
            return;
        }

        let params = BaseParams::new(period);
        let (amps, mut voice, gain_idx) = descramble(&frame.chunks, &params);
        let gains = Gains::new(gain_idx, &amps, &params);
        let coefs = Coefficients::new(&gains, &amps, &params);
        let spectrals = Spectrals::new(&coefs, &params, &self.prev);
        let energy = FrameEnergy::new(&spectrals, &self.prev.energy, &params);

        let mut enhanced = EnhancedSpectrals::new(&spectrals, &energy, &params);
        let amp_thresh = enhance::amp_thresh(&errors, self.prev.amp_thresh);
        enhance::smooth(&mut enhanced, &mut voice, &errors, &energy, amp_thresh);

        let udft = UnvoicedDFT::new(&params, &voice, &enhanced);
        let vbase = PhaseBase::new(&params, &self.prev);
        let vphase = Phase::new(&params, &voice, &vbase);

        {
            let unvoiced = Arc::new(Unvoiced::new(&udft, &self.prev.unvoiced));
            let voiced = Arc::new(Voiced::new(&params, &self.prev, &vphase, &enhanced, &voice));

            let mut threads = buf.chunks_mut(SAMPLES_PER_THREAD).enumerate().map(|(i, chunk)| {
                let u = unvoiced.clone();
                let v = voiced.clone();

                let start = i * SAMPLES_PER_THREAD;
                let stop = start + SAMPLES_PER_THREAD;

                unsafe {
                    thread_scoped::scoped(move || {
                        (start..stop)
                            .map(|n| u.get(n) + v.get(n))
                            .collect_slice(&mut chunk[..]);
                    })
                }
            }).collect::<ArrayVec<[thread_scoped::JoinGuard<()>; THREADS]>>();

            for thread in threads.drain(..) {
                thread.join();
            }
        }

        self.prev = PrevFrame {
            params: params,
            spectrals: spectrals,
            enhanced: enhanced,
            voice: voice,
            err_rate: errors.rate,
            energy: energy,
            amp_thresh: amp_thresh,
            unvoiced: udft,
            phase_base: vbase,
            phase: vphase,
        };
    }

    fn silence(&self, buf: &mut [f32; SAMPLES_PER_FRAME]) {
        (0..SAMPLES_PER_FRAME).map(|_| 0.0).collect_slice(&mut buf[..]);
    }

    fn repeat(&self, buf: &mut [f32; SAMPLES_PER_FRAME]) {
        let params = self.prev.params.clone();
        let voice = self.prev.voice.clone();
        let enhanced = self.prev.enhanced.clone();

        let udft = UnvoicedDFT::new(&params, &voice, &enhanced);
        let vbase = PhaseBase::new(&params, &self.prev);
        let vphase = Phase::new(&params, &voice, &vbase);

        let unvoiced = Unvoiced::new(&udft, &self.prev.unvoiced);
        let voiced = Voiced::new(&params, &self.prev, &vphase, &enhanced, &voice);

        (0..SAMPLES_PER_FRAME)
            .map(|n| unvoiced.get(n) + voiced.get(n))
            .collect_slice(&mut buf[..]);
    }
}

#[cfg(test)]
mod test {
    use super::THREADS;
    use consts::SAMPLES_PER_FRAME;

    #[test]
    fn verify_threads() {
        assert!(SAMPLES_PER_FRAME % THREADS == 0);
    }
}
<|endoftext|>


<commit_before>use av_format::*;
use std::io::{Error,ErrorKind,SeekFrom};
use av_data::packet::Packet;
use av_format::buffer::Buffered;
use av_format::demuxer::demux::Demuxer;

use ebml::{ebml_header, EBMLHeader};
use nom::{IResult,Offset};

pub struct MkvDemuxer {
  pub header: Option<EBMLHeader>,

}

impl Demuxer for MkvDemuxer {
  fn open(&mut self) {}

  fn read_headers(&mut self, ctx: &Box<Buffered>) -> Result<SeekFrom, Error> {
    match ebml_header(ctx.data()) {
      IResult::Done(i, o) => {
        self.header = Some(o);
        Ok(SeekFrom::Current(ctx.data().offset(i) as i64))
      },
      _ => {
        Err(Error::new(ErrorKind::Other, "MKV header parsing error"))
      }
    }
  }

  fn read_packet(&mut self, ctx: &Box<Buffered>) -> Result<(SeekFrom,Packet), Error> {
    Err(Error::new(ErrorKind::Other, "MKV packet parsing error"))
  }
}
<commit_msg>start testing the Demuxer API<commit_after>use av_format::error::*;
use std::io::SeekFrom;
use av_data::packet::Packet;
use av_format::stream::Stream;
use av_format::buffer::Buffered;
use av_format::demuxer::demux::{Demuxer,Event};
use av_format::demuxer::context::GlobalInfo;
use std::collections::VecDeque;
use rational::Rational32;

use ebml::{ebml_header, EBMLHeader};
use elements::{ segment, segment_element, Cluster, SeekHead, Info, Tracks, TrackEntry, SegmentElement};
use nom::{self,IResult,Offset};

#[derive(Debug,Clone,PartialEq)]
pub struct MkvDemuxer {
  pub header:    Option<EBMLHeader>,
  pub seek_head: Option<SeekHead>,
  pub info:      Option<Info>,
  pub tracks:    Option<Tracks>,
  pub clusters:  Vec<Cluster>,
  pub queue:     VecDeque<Event>,
}

impl MkvDemuxer {
  pub fn new() -> MkvDemuxer {
    MkvDemuxer {
      header: None,
      seek_head: None,
      info: None,
      tracks: None,
      clusters: Vec::new(),
      queue:    VecDeque::new(),
    }
  }

  pub fn parse_until_tracks<'a>(&mut self, original_input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let (i1, header) = try_parse!(original_input, ebml_header);

    self.header = Some(header);

    let (mut input, _) = try_parse!(i1, segment);

    loop {
      if self.seek_head.is_some() && self.info.is_some() && self.tracks.is_some() {
        return IResult::Done(input, ());
      }

      println!("offset: {}", original_input.offset(input));

      let (i3, element) = try_parse!(input, segment_element);

      match element {
        SegmentElement::SeekHead(s) => {
          println!("got seek head: {:#?}", s);
          if self.seek_head.is_some() {
            return IResult::Error(nom::ErrorKind::Custom(1));
          } else {
            self.seek_head = Some(s);
          }
        },
        SegmentElement::Info(i) => {
          println!("got info: {:#?}", i);
          if self.info.is_some() {
            return IResult::Error(nom::ErrorKind::Custom(1));
          } else {
            self.info = Some(i);
          }
        },
        SegmentElement::Tracks(t) => {
          println!("got tracks: {:#?}", t);
          if self.tracks.is_some() {
            return IResult::Error(nom::ErrorKind::Custom(1));
          } else {
            self.tracks = Some(t);
          }
        },
        SegmentElement::Cluster(c) => {
          println!("got a cluster: {:#?}", c);
          self.clusters.push(c);
        }
        el => {
          println!("got element: {:#?}", el);
        }
      }

      input = i3;
    }
  }

}

impl Demuxer for MkvDemuxer {
  fn open(&mut self) {}

  fn read_headers(&mut self, buf: &Box<Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom> {
    match self.parse_until_tracks(buf.data()) {
      IResult::Done(i, _) => {
        info.duration = self.info.as_ref().and_then(|info| info.duration).map(|d| d as u64);
        //self.tracks.as_ref().map(|t| t.tracks.
        Ok(SeekFrom::Current(buf.data().offset(i) as i64))
      },
      IResult::Incomplete(_) => Err(ErrorKind::MoreDataNeeded.into()),
      e => {
        Err(ErrorKind::InvalidData.into())
      }
    }
  }

  fn read_packet(&mut self, buf: &Box<Buffered>) -> Result<(SeekFrom, Event)> {
    match segment_element(buf.data()) {
      IResult::Done(i, element) => {
        let seek = SeekFrom::Current(buf.data().offset(i) as i64);
        match element {
          SegmentElement::Cluster(c) => {
            self.clusters.push(c);
          },
          el => {
            println!("got element: {:#?}", el);
          }
        }

        Ok((seek, Event::MoreDataNeeded))
      },
      IResult::Incomplete(_) => {
        Ok((SeekFrom::Current(0), Event::MoreDataNeeded))
      },
      e => {
        println!("parsing issue: {:?}", e);
        Err(ErrorKind::InvalidData.into())
      }
    }
  }
}

/*
pub fn track_stream(t: &TrackEntry) -> Stream {

  Stream {
    id: t.track_uid as usize,
    index: t.track_number as usize,
    start: None,
    duration: t.default_duration,
    timebase : Rational32::from_integer(1),
    params : CodecParams {
      extradata: Vec<u8>,
      tag: u32,
      bit_rate: usize,
      bits_per_coded_sample: usize,
      profile: usize,
      level: usize,
      codec_id: CodecID,
      kind: MediaKind::

    },
  }
}
*/

#[cfg(test)]
mod tests {
  use super::*;
  use std::io::Cursor;
  use nom::{IResult,Offset};
  use av_format::demuxer::context::DemuxerContext;

  const mkv: &'static [u8] = include_bytes!("../assets/single_stream.mkv");

  #[test]
  fn parse_headers() {
    let mut demuxer = MkvDemuxer::new();

    let res = demuxer.parse_until_tracks(mkv);
    println!("got parsing res: {:?}", res);
    match res {
      IResult::Done(i,_) => {
        println!("offset: {} bytes", mkv.offset(i));
      },
      e => {
        println!("could not parse: {:?}", e);
      }
    }

    println!("demuxer: {:#?}", demuxer);
    panic!();
  }

  #[test]
  fn context() {
    let mut context = DemuxerContext::new(Box::new(MkvDemuxer::new()), Box::new(Cursor::new(mkv)));
    println!("DEMUXER CONTEXT read headers: {:?}", context.read_headers());
    println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
    println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
    println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
    println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
    panic!();
  }
}
<|endoftext|>


<commit_before>use nalgebra::{Vector3, Cross, Dot};
use id::{Id, IdVec, Ids, IterMut, IdVecIter};
use point::Point;
use fnv::FnvHashMap;

fn remap_id<T>(id: Id<T>, remap: &FnvHashMap<Id<T>, Id<T>>) -> Id<T> {
    let mut result = id;
    while let Some(&mapped) = remap.get(&result) {
        result = mapped;
    }
    result
}

pub struct VertexData {
    point: Point,
    edges: Vec<Edge>,
    faces: Vec<Face>,
}
pub type Vertex = Id<VertexData>;

#[derive(Default)]
pub struct Vertices {
    vertices: IdVec<VertexData>,
}

impl Vertices {
    fn add(&mut self, data: VertexData) -> Vertex {
        self.vertices.add(data)
    }

    fn add_edge(&mut self, vertex: Vertex, edge: Edge) {
        self.vertices[vertex].edges.push(edge);
    }

    pub fn point(&self, vertex: Vertex) -> Point {
        self.vertices[vertex].point
    }

    pub fn position(&self, vertex: Vertex) -> Vector3<f64> {
        self.point(vertex).position
    }

    pub fn faces(&self, vertex: Vertex) -> &[Face] {
        &self.vertices[vertex].faces
    }

    pub fn edges(&self, vertex: Vertex) -> &[Edge] {
        &self.vertices[vertex].edges
    }

    pub fn retain<F: FnMut(&VertexData) -> bool>(&mut self, f: F) {
        self.vertices.retain(f);
    }

    pub fn ids(&self) -> IdVecIter<VertexData> {
        self.vertices.ids()
    }
}

pub struct EdgeData {
    vertices: (Vertex, Vertex),
    faces: (Face, Face),
}
pub type Edge = Id<EdgeData>;

#[derive(Default)]
pub struct Edges {
    edges: IdVec<EdgeData>,
}

impl Edges {
    fn add(&mut self, data: EdgeData) -> Edge {
        self.edges.add(data)
    }

    pub fn vertices(&self, edge: Edge) -> (Vertex, Vertex) {
        self.edges[edge].vertices
    }

    pub fn other_vertex(&self, edge: Edge, vertex: Vertex) -> Option<Vertex> {
        let (vertex0, vertex1) = self.vertices(edge);
        if vertex  == vertex0 {
            Some(vertex1)
        } else if vertex == vertex1 {
            Some(vertex0)
        } else {
            None
        }
    }

    pub fn set_faces(&mut self, edge: Edge, face1: Face, face2: Face) {
        self.edges[edge].faces = (face1, face2);
    }

    pub fn retain<F: FnMut(&EdgeData) -> bool>(&mut self, f: F) {
        self.edges.retain(f);
    }

    pub fn ids(&self) -> IdVecIter<EdgeData> {
        self.edges.ids()
    }
}

pub struct FaceData {
    point: Point,
    edges: Vec<Edge>,
    vertices: Vec<Vertex>,
}
pub type Face = Id<FaceData>;

#[derive(Default)]
pub struct Faces {
    faces: IdVec<FaceData>,
}

impl Faces {
    fn add(&mut self, data: FaceData) -> Face {
        self.faces.add(data)
    }

    pub fn point(&self, face: Face) -> Point {
        self.faces[face].point
    }

    pub fn position(&self, face: Face) -> Vector3<f64> {
        self.point(face).position
    }

    pub fn vertices(&self, face: Face) -> &[Vertex] {
        &self.faces[face].vertices
    }

    pub fn edges(&self, face: Face) -> &[Edge] {
        &self.faces[face].edges
    }

    pub fn add_edge(&mut self, face: Face, edge: Edge) {
        self.faces[face].edges.push(edge);
    }

    pub fn add_vertex(&mut self, face: Face, vertex: Vertex) {
        self.faces[face].vertices.push(vertex);
    }

    pub fn ids(&self) -> IdVecIter<FaceData> {
        self.faces.ids()
    }

    pub fn len(&self) -> usize {
        self.faces.len()
    }
}

fn is_bad_vertex(vertex_data: &VertexData) -> bool {
    vertex_data.faces.len() <= 2
}

fn is_bad_edge(edge_data: &EdgeData, vertices: &IdVec<VertexData>) -> bool {
    let (vertex0, vertex1) = edge_data.vertices;
    is_bad_vertex(&vertices[vertex0]) || is_bad_vertex(&vertices[vertex1])
}

#[derive(Default)]
pub struct Diagram {
    pub faces: Faces,
    pub edges: Edges,
    pub vertices: Vertices,
}

fn are_clockwise(n: Vector3<f64>, v1: Vector3<f64>, v2: Vector3<f64>) -> bool {
    (v1 - n).cross(&(v2 - n)).dot(&n) < 0.0
}

impl Diagram {
    pub fn new_edge(&mut self, vertex0: Vertex, vertex1: Vertex) -> Edge {
        let edge = self.edges.add(EdgeData {
            vertices: (vertex0, vertex1),
            faces: (Face::none(), Face::none()),
        });
        self.vertices.add_edge(vertex0, edge);
        self.vertices.add_edge(vertex1, edge);
        edge
    }

    pub fn new_vertex(&mut self, point: Point, faces: Vec<Face>) -> Vertex {
        self.vertices.add(VertexData {
            point: point,
            edges: Vec::new(),
            faces: faces
        })
    }

    pub fn new_face(&mut self, point: Point) -> Face {
        self.faces.add(FaceData {
            point: point,
            edges: Vec::new(),
            vertices: Vec::new(),
        })
    }

    pub fn center(&self, face: Face) -> Vector3<f64> {
        let mut center = Vector3::new(0.0, 0.0, 0.0);
        let mut count = 0.0f64;
        for vertex in self.faces.vertices(face) {
            center += self.vertices.point(*vertex).position;
            count += 1.0;
        }
        Vector3::new(center.x / count, center.y / count, center.z / count)
    }

    pub fn cleanup_vertices(&mut self) {
        let mut bad_vertices = Vec::new();
        let mut bad_edges = Vec::new();
        for vertex in self.vertices.ids() {
            if self.vertices.faces(vertex).len() == 2 {
                let (edge0, edge1) = {
                    let edges = &self.vertices.edges(vertex);
                    assert_eq!(edges.len(), 2);
                    (edges[0], edges[1])
                };
                let vertex0 = self.edges.other_vertex(edge0, vertex).unwrap();
                let vertex1 = self.edges.other_vertex(edge1, vertex).unwrap();
                self.new_edge(vertex0, vertex1);
                bad_vertices.push(vertex);
                bad_edges.push(edge0);
                bad_edges.push(edge1);
            }
        }
        bad_edges.sort();
        bad_edges.dedup();
        let mut vertices_remap = FnvHashMap::default();
        for vertex in bad_vertices {
            let new_vertex = remap_id(vertex, &vertices_remap);
            let prev_vertex = self.vertices.vertices.remove(new_vertex);
            vertices_remap.insert(prev_vertex, vertex);
        }
        let mut edges_remap = FnvHashMap::default();
        for edge in bad_edges {
            let new_edge = remap_id(edge, &edges_remap);
            let prev_edge = self.edges.edges.remove(new_edge);
            edges_remap.insert(prev_edge, edge);
        }
        for edge in self.edges.ids() {
            let (vertex0, vertex1) = self.edges.vertices(edge);
            self.edges.edges[edge].vertices = (remap_id(vertex0, &vertices_remap), remap_id(vertex1, &vertices_remap));
        }
        for face in self.faces.ids() {
            for vertex in self.faces.faces[face].vertices.iter_mut() {
                *vertex = remap_id(*vertex, &vertices_remap);
            }
            for edge in self.faces.faces[face].edges.iter_mut() {
                *edge = remap_id(*edge, &edges_remap);
            }
        }
    }

    pub fn finish_faces(&mut self) {
        for edge in self.edges.ids() {
            let mut common = Vec::new();
            let (vertex0, vertex1) = self.edges.vertices(edge);
            for face0 in self.vertices.faces(vertex0) {
                for face1 in self.vertices.faces(vertex1) {
                    if face0 == face1 {
                        common.push(*face0);
                    }
                }
            }
            assert_eq!(common.len(), 2);
            self.faces.add_edge(common[0], edge);
            self.faces.add_edge(common[1], edge);
            self.edges.set_faces(edge, common[0], common[1]);
        }
        for face in self.faces.ids() {
            let n = self.faces.position(face);
            let mut edge = self.faces.edges(face)[0];
            let (v0, v1) = self.edges.vertices(edge);
            let (prev, v) = if are_clockwise(n, self.vertices.position(v0), self.vertices.position(v1)) {
                (v0, v1)
            } else {
                (v1, v0)
            };
            self.faces.add_vertex(face, prev);
            let mut vertex = v;
            for _ in 0..self.faces.edges(face).len() - 1 {
                self.faces.add_vertex(face, vertex);
                for &e in self.faces.edges(face) {
                    if e != edge {
                        if let Some(v) = self.edges.other_vertex(e, vertex) {
                            vertex = v;
                            edge = e;
                            break;
                        }
                    }
                }
            }
        }
    }
}
<commit_msg>Remove unused imports and functions.<commit_after>use nalgebra::{Vector3, Cross, Dot};
use id::{Id, IdVec, IdVecIter};
use point::Point;
use fnv::FnvHashMap;

fn remap_id<T>(id: Id<T>, remap: &FnvHashMap<Id<T>, Id<T>>) -> Id<T> {
    let mut result = id;
    while let Some(&mapped) = remap.get(&result) {
        result = mapped;
    }
    result
}

pub struct VertexData {
    point: Point,
    edges: Vec<Edge>,
    faces: Vec<Face>,
}
pub type Vertex = Id<VertexData>;

#[derive(Default)]
pub struct Vertices {
    vertices: IdVec<VertexData>,
}

impl Vertices {
    fn add(&mut self, data: VertexData) -> Vertex {
        self.vertices.add(data)
    }

    fn add_edge(&mut self, vertex: Vertex, edge: Edge) {
        self.vertices[vertex].edges.push(edge);
    }

    pub fn point(&self, vertex: Vertex) -> Point {
        self.vertices[vertex].point
    }

    pub fn position(&self, vertex: Vertex) -> Vector3<f64> {
        self.point(vertex).position
    }

    pub fn faces(&self, vertex: Vertex) -> &[Face] {
        &self.vertices[vertex].faces
    }

    pub fn edges(&self, vertex: Vertex) -> &[Edge] {
        &self.vertices[vertex].edges
    }

    pub fn retain<F: FnMut(&VertexData) -> bool>(&mut self, f: F) {
        self.vertices.retain(f);
    }

    pub fn ids(&self) -> IdVecIter<VertexData> {
        self.vertices.ids()
    }
}

pub struct EdgeData {
    vertices: (Vertex, Vertex),
    faces: (Face, Face),
}
pub type Edge = Id<EdgeData>;

#[derive(Default)]
pub struct Edges {
    edges: IdVec<EdgeData>,
}

impl Edges {
    fn add(&mut self, data: EdgeData) -> Edge {
        self.edges.add(data)
    }

    pub fn vertices(&self, edge: Edge) -> (Vertex, Vertex) {
        self.edges[edge].vertices
    }

    pub fn other_vertex(&self, edge: Edge, vertex: Vertex) -> Option<Vertex> {
        let (vertex0, vertex1) = self.vertices(edge);
        if vertex  == vertex0 {
            Some(vertex1)
        } else if vertex == vertex1 {
            Some(vertex0)
        } else {
            None
        }
    }

    pub fn set_faces(&mut self, edge: Edge, face1: Face, face2: Face) {
        self.edges[edge].faces = (face1, face2);
    }

    pub fn retain<F: FnMut(&EdgeData) -> bool>(&mut self, f: F) {
        self.edges.retain(f);
    }

    pub fn ids(&self) -> IdVecIter<EdgeData> {
        self.edges.ids()
    }
}

pub struct FaceData {
    point: Point,
    edges: Vec<Edge>,
    vertices: Vec<Vertex>,
}
pub type Face = Id<FaceData>;

#[derive(Default)]
pub struct Faces {
    faces: IdVec<FaceData>,
}

impl Faces {
    fn add(&mut self, data: FaceData) -> Face {
        self.faces.add(data)
    }

    pub fn point(&self, face: Face) -> Point {
        self.faces[face].point
    }

    pub fn position(&self, face: Face) -> Vector3<f64> {
        self.point(face).position
    }

    pub fn vertices(&self, face: Face) -> &[Vertex] {
        &self.faces[face].vertices
    }

    pub fn edges(&self, face: Face) -> &[Edge] {
        &self.faces[face].edges
    }

    pub fn add_edge(&mut self, face: Face, edge: Edge) {
        self.faces[face].edges.push(edge);
    }

    pub fn add_vertex(&mut self, face: Face, vertex: Vertex) {
        self.faces[face].vertices.push(vertex);
    }

    pub fn ids(&self) -> IdVecIter<FaceData> {
        self.faces.ids()
    }

    pub fn len(&self) -> usize {
        self.faces.len()
    }
}

#[derive(Default)]
pub struct Diagram {
    pub faces: Faces,
    pub edges: Edges,
    pub vertices: Vertices,
}

fn are_clockwise(n: Vector3<f64>, v1: Vector3<f64>, v2: Vector3<f64>) -> bool {
    (v1 - n).cross(&(v2 - n)).dot(&n) < 0.0
}

impl Diagram {
    pub fn new_edge(&mut self, vertex0: Vertex, vertex1: Vertex) -> Edge {
        let edge = self.edges.add(EdgeData {
            vertices: (vertex0, vertex1),
            faces: (Face::none(), Face::none()),
        });
        self.vertices.add_edge(vertex0, edge);
        self.vertices.add_edge(vertex1, edge);
        edge
    }

    pub fn new_vertex(&mut self, point: Point, faces: Vec<Face>) -> Vertex {
        self.vertices.add(VertexData {
            point: point,
            edges: Vec::new(),
            faces: faces
        })
    }

    pub fn new_face(&mut self, point: Point) -> Face {
        self.faces.add(FaceData {
            point: point,
            edges: Vec::new(),
            vertices: Vec::new(),
        })
    }

    pub fn center(&self, face: Face) -> Vector3<f64> {
        let mut center = Vector3::new(0.0, 0.0, 0.0);
        let mut count = 0.0f64;
        for vertex in self.faces.vertices(face) {
            center += self.vertices.point(*vertex).position;
            count += 1.0;
        }
        Vector3::new(center.x / count, center.y / count, center.z / count)
    }

    pub fn cleanup_vertices(&mut self) {
        let mut bad_vertices = Vec::new();
        let mut bad_edges = Vec::new();
        for vertex in self.vertices.ids() {
            if self.vertices.faces(vertex).len() == 2 {
                let (edge0, edge1) = {
                    let edges = &self.vertices.edges(vertex);
                    assert_eq!(edges.len(), 2);
                    (edges[0], edges[1])
                };
                let vertex0 = self.edges.other_vertex(edge0, vertex).unwrap();
                let vertex1 = self.edges.other_vertex(edge1, vertex).unwrap();
                self.new_edge(vertex0, vertex1);
                bad_vertices.push(vertex);
                bad_edges.push(edge0);
                bad_edges.push(edge1);
            }
        }
        bad_edges.sort();
        bad_edges.dedup();
        let mut vertices_remap = FnvHashMap::default();
        for vertex in bad_vertices {
            let new_vertex = remap_id(vertex, &vertices_remap);
            let prev_vertex = self.vertices.vertices.remove(new_vertex);
            vertices_remap.insert(prev_vertex, vertex);
        }
        let mut edges_remap = FnvHashMap::default();
        for edge in bad_edges {
            let new_edge = remap_id(edge, &edges_remap);
            let prev_edge = self.edges.edges.remove(new_edge);
            edges_remap.insert(prev_edge, edge);
        }
        for edge in self.edges.ids() {
            let (vertex0, vertex1) = self.edges.vertices(edge);
            self.edges.edges[edge].vertices = (remap_id(vertex0, &vertices_remap), remap_id(vertex1, &vertices_remap));
        }
        for face in self.faces.ids() {
            for vertex in self.faces.faces[face].vertices.iter_mut() {
                *vertex = remap_id(*vertex, &vertices_remap);
            }
            for edge in self.faces.faces[face].edges.iter_mut() {
                *edge = remap_id(*edge, &edges_remap);
            }
        }
    }

    pub fn finish_faces(&mut self) {
        for edge in self.edges.ids() {
            let mut common = Vec::new();
            let (vertex0, vertex1) = self.edges.vertices(edge);
            for face0 in self.vertices.faces(vertex0) {
                for face1 in self.vertices.faces(vertex1) {
                    if face0 == face1 {
                        common.push(*face0);
                    }
                }
            }
            assert_eq!(common.len(), 2);
            self.faces.add_edge(common[0], edge);
            self.faces.add_edge(common[1], edge);
            self.edges.set_faces(edge, common[0], common[1]);
        }
        for face in self.faces.ids() {
            let n = self.faces.position(face);
            let mut edge = self.faces.edges(face)[0];
            let (v0, v1) = self.edges.vertices(edge);
            let (prev, v) = if are_clockwise(n, self.vertices.position(v0), self.vertices.position(v1)) {
                (v0, v1)
            } else {
                (v1, v0)
            };
            self.faces.add_vertex(face, prev);
            let mut vertex = v;
            for _ in 0..self.faces.edges(face).len() - 1 {
                self.faces.add_vertex(face, vertex);
                for &e in self.faces.edges(face) {
                    if e != edge {
                        if let Some(v) = self.edges.other_vertex(e, vertex) {
                            vertex = v;
                            edge = e;
                            break;
                        }
                    }
                }
            }
        }
    }
}
<|endoftext|>