<commit_before>use crate::{
    ast::{Directive, FromInputValue, InputValue, Selection},
    executor::{ExecutionResult, Executor},
    parser::Spanning,
    value::{Object, ScalarRefValue, ScalarValue, Value},
    BoxFuture,
};

use super::base::{Arguments, GraphQLType, is_excluded, merge_key_into};

#[async_trait::async_trait]
pub trait GraphQLTypeAsync<S>: GraphQLType<S> + Send + Sync
where
    Self::Context: Send + Sync,
    Self::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    async fn resolve_field_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        field_name: &'a str,
        arguments: &'a Arguments<'a, S>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        panic!("resolve_field must be implemented by object types");
    }

    async fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> Value<S> {
        if let Some(selection_set) = selection_set {
            resolve_selection_set_into_async(self, info, selection_set, executor).await
        } else {
            panic!("resolve() must be implemented by non-object output types");
        }
    }

    async fn resolve_into_type_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        type_name: &str,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        if Self::name(info).unwrap() == type_name {
            Ok(self.resolve_async(info, selection_set, executor).await)
        } else {
            panic!("resolve_into_type_async must be implemented by unions and interfaces");
        }
    }
}

// Wrapper function around resolve_selection_set_into_async_recursive.
// This wrapper is necessary because async fns can not be recursive.
#[cfg(feature = "async")]
pub(crate) fn resolve_selection_set_into_async<'a, 'e, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'e [Selection<'e, S>],
    executor: &'e Executor<'e, CtxT, S>,
) -> BoxFuture<'a, Value<S>>
where
    T: GraphQLTypeAsync<S, Context = CtxT>,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    'e: 'a,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    Box::pin(resolve_selection_set_into_async_recursive(
        instance,
        info,
        selection_set,
        executor,
    ))
}

struct AsyncField<S> {
    name: String,
    value: Option<Value<S>>,
}

enum AsyncValue<S> {
    Field(AsyncField<S>),
    Nested(Value<S>),
}

#[cfg(feature = "async")]
pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'a [Selection<'a, S>],
    executor: &'a Executor<'a, CtxT, S>,
) -> Value<S>
where
    T: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    use futures::stream::{FuturesOrdered, StreamExt};

    let mut object = Object::with_capacity(selection_set.len());

    let mut async_values = FuturesOrdered::<BoxFuture<'a, AsyncValue<S>>>::new();

    let meta_type = executor
        .schema()
        .concrete_type_by_name(
            T::name(info)
                .expect("Resolving named type's selection set")
                .as_ref(),
        )
        .expect("Type not found in schema");

    for selection in selection_set {
        match *selection {
            Selection::Field(Spanning {
                item: ref f,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&f.directives, executor.variables()) {
                    continue;
                }

                let response_name = f.alias.as_ref().unwrap_or(&f.name).item;

                if f.name.item == "__typename" {
                    object.add_field(
                        response_name,
                        Value::scalar(instance.concrete_type_name(executor.context(), info)),
                    );
                    continue;
                }

                let meta_field = meta_type.field_by_name(f.name.item).unwrap_or_else(|| {
                    panic!(format!(
                        "Field {} not found on type {:?}",
                        f.name.item,
                        meta_type.name()
                    ))
                });

                let exec_vars = executor.variables();

                let sub_exec = executor.field_sub_executor(
                    &response_name,
                    f.name.item,
                    start_pos.clone(),
                    f.selection_set.as_ref().map(|v| &v[..]),
                );
                let args = Arguments::new(
                    f.arguments.as_ref().map(|m| {
                        m.item
                            .iter()
                            .map(|&(ref k, ref v)| (k.item, v.item.clone().into_const(exec_vars)))
                            .collect()
                    }),
                    &meta_field.arguments,
                );

                let pos = start_pos.clone();
                let is_non_null = meta_field.field_type.is_non_null();

                let response_name = response_name.to_string();
                let field_future = async move {
                    // TODO: implement custom future type instead of
                    //       two-level boxing.
                    let res = instance
                        .resolve_field_async(info, f.name.item, &args, &sub_exec)
                        .await;

                    let value = match res {
                        Ok(Value::Null) if is_non_null => None,
                        Ok(v) => Some(v),
                        Err(e) => {
                            sub_exec.push_error_at(e, pos);

                            if is_non_null {
                                None
                            } else {
                                Some(Value::null())
                            }
                        }
                    };
                    AsyncValue::Field(AsyncField {
                        name: response_name,
                        value,
                    })
                };
                async_values.push(Box::pin(field_future));
            }
            Selection::FragmentSpread(Spanning {
                item: ref spread, ..
            }) => {
                if is_excluded(&spread.directives, executor.variables()) {
                    continue;
                }

                // TODO: prevent duplicate boxing.
                let f = async move {
                    let fragment = &executor
                        .fragment_by_name(spread.name.item)
                        .expect("Fragment could not be found");
                    let value = resolve_selection_set_into_async(
                        instance,
                        info,
                        &fragment.selection_set[..],
                        executor,
                    )
                    .await;
                    AsyncValue::Nested(value)
                };
                async_values.push(Box::pin(f));
            }
            Selection::InlineFragment(Spanning {
                item: ref fragment,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&fragment.directives, executor.variables()) {
                    continue;
                }

                let sub_exec = executor.type_sub_executor(
                    fragment.type_condition.as_ref().map(|c| c.item),
                    Some(&fragment.selection_set[..]),
                );

                if let Some(ref type_condition) = fragment.type_condition {
                    let sub_result = instance
                        .resolve_into_type_async(
                            info,
                            type_condition.item,
                            Some(&fragment.selection_set[..]),
                            &sub_exec,
                        )
                        .await;

                    if let Ok(Value::Object(obj)) = sub_result {
                        for (k, v) in obj {
                            merge_key_into(&mut object, &k, v);
                        }
                    } else if let Err(e) = sub_result {
                        sub_exec.push_error_at(e, start_pos.clone());
                    }
                } else {
                    let f = async move {
                        let value = resolve_selection_set_into_async(
                            instance,
                            info,
                            &fragment.selection_set[..],
                            &sub_exec,
                        )
                        .await;
                        AsyncValue::Nested(value)
                    };
                    async_values.push(Box::pin(f));
                }
            }
        }
    }

    while let Some(item) = async_values.next().await {
        match item {
            AsyncValue::Field(AsyncField { name, value }) => {
                if let Some(value) = value {
                    object.add_field(&name, value);
                } else {
                    return Value::null();
                }
            }
            AsyncValue::Nested(obj) => match obj {
                v @ Value::Null => {
                    return v;
                }
                Value::Object(obj) => {
                    for (k, v) in obj {
                        merge_key_into(&mut object, &k, v);
                    }
                }
                _ => unreachable!(),
            },
        }
    }

    Value::Object(object)
}
<commit_msg>Format<commit_after>use crate::{
    ast::{Directive, FromInputValue, InputValue, Selection},
    executor::{ExecutionResult, Executor},
    parser::Spanning,
    value::{Object, ScalarRefValue, ScalarValue, Value},
    BoxFuture,
};

use super::base::{is_excluded, merge_key_into, Arguments, GraphQLType};

#[async_trait::async_trait]
pub trait GraphQLTypeAsync<S>: GraphQLType<S> + Send + Sync
where
    Self::Context: Send + Sync,
    Self::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    async fn resolve_field_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        field_name: &'a str,
        arguments: &'a Arguments<'a, S>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        panic!("resolve_field must be implemented by object types");
    }

    async fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> Value<S> {
        if let Some(selection_set) = selection_set {
            resolve_selection_set_into_async(self, info, selection_set, executor).await
        } else {
            panic!("resolve() must be implemented by non-object output types");
        }
    }

    async fn resolve_into_type_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        type_name: &str,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        if Self::name(info).unwrap() == type_name {
            Ok(self.resolve_async(info, selection_set, executor).await)
        } else {
            panic!("resolve_into_type_async must be implemented by unions and interfaces");
        }
    }
}

// Wrapper function around resolve_selection_set_into_async_recursive.
// This wrapper is necessary because async fns can not be recursive.
#[cfg(feature = "async")]
pub(crate) fn resolve_selection_set_into_async<'a, 'e, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'e [Selection<'e, S>],
    executor: &'e Executor<'e, CtxT, S>,
) -> BoxFuture<'a, Value<S>>
where
    T: GraphQLTypeAsync<S, Context = CtxT>,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    'e: 'a,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    Box::pin(resolve_selection_set_into_async_recursive(
        instance,
        info,
        selection_set,
        executor,
    ))
}

struct AsyncField<S> {
    name: String,
    value: Option<Value<S>>,
}

enum AsyncValue<S> {
    Field(AsyncField<S>),
    Nested(Value<S>),
}

#[cfg(feature = "async")]
pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'a [Selection<'a, S>],
    executor: &'a Executor<'a, CtxT, S>,
) -> Value<S>
where
    T: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    use futures::stream::{FuturesOrdered, StreamExt};

    let mut object = Object::with_capacity(selection_set.len());

    let mut async_values = FuturesOrdered::<BoxFuture<'a, AsyncValue<S>>>::new();

    let meta_type = executor
        .schema()
        .concrete_type_by_name(
            T::name(info)
                .expect("Resolving named type's selection set")
                .as_ref(),
        )
        .expect("Type not found in schema");

    for selection in selection_set {
        match *selection {
            Selection::Field(Spanning {
                item: ref f,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&f.directives, executor.variables()) {
                    continue;
                }

                let response_name = f.alias.as_ref().unwrap_or(&f.name).item;

                if f.name.item == "__typename" {
                    object.add_field(
                        response_name,
                        Value::scalar(instance.concrete_type_name(executor.context(), info)),
                    );
                    continue;
                }

                let meta_field = meta_type.field_by_name(f.name.item).unwrap_or_else(|| {
                    panic!(format!(
                        "Field {} not found on type {:?}",
                        f.name.item,
                        meta_type.name()
                    ))
                });

                let exec_vars = executor.variables();

                let sub_exec = executor.field_sub_executor(
                    &response_name,
                    f.name.item,
                    start_pos.clone(),
                    f.selection_set.as_ref().map(|v| &v[..]),
                );
                let args = Arguments::new(
                    f.arguments.as_ref().map(|m| {
                        m.item
                            .iter()
                            .map(|&(ref k, ref v)| (k.item, v.item.clone().into_const(exec_vars)))
                            .collect()
                    }),
                    &meta_field.arguments,
                );

                let pos = start_pos.clone();
                let is_non_null = meta_field.field_type.is_non_null();

                let response_name = response_name.to_string();
                let field_future = async move {
                    // TODO: implement custom future type instead of
                    //       two-level boxing.
                    let res = instance
                        .resolve_field_async(info, f.name.item, &args, &sub_exec)
                        .await;

                    let value = match res {
                        Ok(Value::Null) if is_non_null => None,
                        Ok(v) => Some(v),
                        Err(e) => {
                            sub_exec.push_error_at(e, pos);

                            if is_non_null {
                                None
                            } else {
                                Some(Value::null())
                            }
                        }
                    };
                    AsyncValue::Field(AsyncField {
                        name: response_name,
                        value,
                    })
                };
                async_values.push(Box::pin(field_future));
            }
            Selection::FragmentSpread(Spanning {
                item: ref spread, ..
            }) => {
                if is_excluded(&spread.directives, executor.variables()) {
                    continue;
                }

                // TODO: prevent duplicate boxing.
                let f = async move {
                    let fragment = &executor
                        .fragment_by_name(spread.name.item)
                        .expect("Fragment could not be found");
                    let value = resolve_selection_set_into_async(
                        instance,
                        info,
                        &fragment.selection_set[..],
                        executor,
                    )
                    .await;
                    AsyncValue::Nested(value)
                };
                async_values.push(Box::pin(f));
            }
            Selection::InlineFragment(Spanning {
                item: ref fragment,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&fragment.directives, executor.variables()) {
                    continue;
                }

                let sub_exec = executor.type_sub_executor(
                    fragment.type_condition.as_ref().map(|c| c.item),
                    Some(&fragment.selection_set[..]),
                );

                if let Some(ref type_condition) = fragment.type_condition {
                    let sub_result = instance
                        .resolve_into_type_async(
                            info,
                            type_condition.item,
                            Some(&fragment.selection_set[..]),
                            &sub_exec,
                        )
                        .await;

                    if let Ok(Value::Object(obj)) = sub_result {
                        for (k, v) in obj {
                            merge_key_into(&mut object, &k, v);
                        }
                    } else if let Err(e) = sub_result {
                        sub_exec.push_error_at(e, start_pos.clone());
                    }
                } else {
                    let f = async move {
                        let value = resolve_selection_set_into_async(
                            instance,
                            info,
                            &fragment.selection_set[..],
                            &sub_exec,
                        )
                        .await;
                        AsyncValue::Nested(value)
                    };
                    async_values.push(Box::pin(f));
                }
            }
        }
    }

    while let Some(item) = async_values.next().await {
        match item {
            AsyncValue::Field(AsyncField { name, value }) => {
                if let Some(value) = value {
                    object.add_field(&name, value);
                } else {
                    return Value::null();
                }
            }
            AsyncValue::Nested(obj) => match obj {
                v @ Value::Null => {
                    return v;
                }
                Value::Object(obj) => {
                    for (k, v) in obj {
                        merge_key_into(&mut object, &k, v);
                    }
                }
                _ => unreachable!(),
            },
        }
    }

    Value::Object(object)
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate clap;
extern crate toml;
extern crate toml_query;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagerror;
extern crate libimagentrylink;
extern crate libimagstore;

use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace;
use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::iter::get::*;
use libimagstore::error::StoreError as Error;
use libimagentrylink::internal::*;

use toml::Value;
use toml_query::read::TomlValueReadExt;

use std::collections::BTreeMap;

mod ui;

struct Diagnostic {
    pub id: StoreId,
    pub entry_store_version: String,
    pub header_sections: usize,
    pub bytecount_content: usize,
    pub overall_byte_size: usize,
    pub verified: bool,
    pub num_internal_links: usize,
}

impl<'a> From<FileLockEntry<'a>> for Diagnostic {

    fn from(entry: FileLockEntry<'a>) -> Diagnostic {
        Diagnostic {
            id: entry.get_location().clone(),
            entry_store_version: entry
                .get_header()
                .read("imag.version")
                .map(|opt| match opt {
                    Some(&Value::String(ref s)) => s.clone(),
                    Some(_) => "Non-String type in 'imag.version'".to_owned(),
                    None => "No version".to_owned(),
                })
                .unwrap_or("Error reading version".to_owned()),
            header_sections: match entry.get_header() {
                &Value::Table(ref map) => map.keys().count(),
                _ => 0
            },
            bytecount_content: entry.get_content().as_str().len(),
            overall_byte_size: entry.to_str().as_str().len(),
            verified: entry.verify().is_ok(),
            num_internal_links: entry.get_internal_links().map(Iterator::count).unwrap_or(0),
        }
    }
}

fn main() {
    let rt = generate_runtime_setup("imag-diagnostics",
                                    &version!()[..],
                                    "Print diagnostics about imag and the imag store",
                                    ui::build_ui);

    let diags = rt.store()
        .entries()
        .map_err_trace_exit(1)
        .unwrap()
        .into_get_iter(rt.store())
        .map(|e| {
            e.map_err_trace_exit_unwrap(1)
                .ok_or(Error::from("Unable to get entry".to_owned()))
                .map_err_trace_exit_unwrap(1)
        })
        .map(Diagnostic::from)
        .collect::<Vec<_>>();

    let mut version_counts        : BTreeMap<String, usize> = BTreeMap::new();
    let mut sum_header_sections   = 0;
    let mut sum_bytecount_content = 0;
    let mut sum_overall_byte_size = 0;
    let mut max_overall_byte_size : Option<(usize, StoreId)> = None;
    let mut verified_count        = 0;
    let mut unverified_count      = 0;
    let mut num_internal_links    = 0;
    let mut max_internal_links : Option<(usize, StoreId)> = None;

    for diag in diags.iter() {
        sum_header_sections     += diag.header_sections;
        sum_bytecount_content   += diag.bytecount_content;
        sum_overall_byte_size   += diag.overall_byte_size;
        match max_overall_byte_size {
            None => max_overall_byte_size = Some((diag.num_internal_links, diag.id.clone())),
            Some((num, _)) => if num < diag.overall_byte_size {
                max_overall_byte_size = Some((diag.overall_byte_size, diag.id.clone()));
            }
        }

        let n = version_counts.get(&diag.entry_store_version).map(Clone::clone).unwrap_or(0);
        version_counts.insert(diag.entry_store_version.clone(), n+1);

        if diag.verified {
            verified_count += 1;
        } else {
            unverified_count += 1;
        }

        num_internal_links += diag.num_internal_links;
        match max_internal_links {
            None => max_internal_links = Some((diag.num_internal_links, diag.id.clone())),
            Some((num, _)) => if num < diag.num_internal_links {
                max_internal_links = Some((diag.num_internal_links, diag.id.clone()));
            }
        }
    }

    let n = diags.len();

    println!("imag version {}", version!());
    println!("");
    println!("{} entries", n);
    for (k, v) in version_counts {
        println!("{} entries with store version '{}'", v, k);
    }
    if n != 0 {
        println!("{} header sections in the average entry", sum_header_sections / n);
        println!("{} average content bytecount", sum_bytecount_content / n);
        println!("{} average overall bytecount", sum_overall_byte_size / n);
        if let Some((num, path)) = max_overall_byte_size {
            println!("Largest Entry ({bytes} bytes): {path}",
                bytes = num,
                path = path
                    .into_pathbuf()
                    .map_err_trace_exit_unwrap(1)
                    .to_str()
                    .unwrap_or("Failed converting path to string")
            );
        }
        println!("{} average internal link count per entry", num_internal_links / n);
        if let Some((num, path)) = max_internal_links {
            println!("Entry with most internal links ({count}): {path}",
                     count = num,
                     path = path
                        .into_pathbuf()
                        .map_err_trace_exit_unwrap(1)
                        .to_str()
                        .unwrap_or("Failed converting path to string")
            );
        }
        println!("{} verified entries", verified_count);
        println!("{} unverified entries", unverified_count);
    }
}

<commit_msg>Fix: Explicitely import only relevant trait<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate clap;
extern crate toml;
extern crate toml_query;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagerror;
extern crate libimagentrylink;
extern crate libimagstore;

use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace;
use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::iter::get::StoreIdGetIteratorExtension;
use libimagstore::error::StoreError as Error;
use libimagentrylink::internal::*;

use toml::Value;
use toml_query::read::TomlValueReadExt;

use std::collections::BTreeMap;

mod ui;

struct Diagnostic {
    pub id: StoreId,
    pub entry_store_version: String,
    pub header_sections: usize,
    pub bytecount_content: usize,
    pub overall_byte_size: usize,
    pub verified: bool,
    pub num_internal_links: usize,
}

impl<'a> From<FileLockEntry<'a>> for Diagnostic {

    fn from(entry: FileLockEntry<'a>) -> Diagnostic {
        Diagnostic {
            id: entry.get_location().clone(),
            entry_store_version: entry
                .get_header()
                .read("imag.version")
                .map(|opt| match opt {
                    Some(&Value::String(ref s)) => s.clone(),
                    Some(_) => "Non-String type in 'imag.version'".to_owned(),
                    None => "No version".to_owned(),
                })
                .unwrap_or("Error reading version".to_owned()),
            header_sections: match entry.get_header() {
                &Value::Table(ref map) => map.keys().count(),
                _ => 0
            },
            bytecount_content: entry.get_content().as_str().len(),
            overall_byte_size: entry.to_str().as_str().len(),
            verified: entry.verify().is_ok(),
            num_internal_links: entry.get_internal_links().map(Iterator::count).unwrap_or(0),
        }
    }
}

fn main() {
    let rt = generate_runtime_setup("imag-diagnostics",
                                    &version!()[..],
                                    "Print diagnostics about imag and the imag store",
                                    ui::build_ui);

    let diags = rt.store()
        .entries()
        .map_err_trace_exit(1)
        .unwrap()
        .into_get_iter(rt.store())
        .map(|e| {
            e.map_err_trace_exit_unwrap(1)
                .ok_or(Error::from("Unable to get entry".to_owned()))
                .map_err_trace_exit_unwrap(1)
        })
        .map(Diagnostic::from)
        .collect::<Vec<_>>();

    let mut version_counts        : BTreeMap<String, usize> = BTreeMap::new();
    let mut sum_header_sections   = 0;
    let mut sum_bytecount_content = 0;
    let mut sum_overall_byte_size = 0;
    let mut max_overall_byte_size : Option<(usize, StoreId)> = None;
    let mut verified_count        = 0;
    let mut unverified_count      = 0;
    let mut num_internal_links    = 0;
    let mut max_internal_links : Option<(usize, StoreId)> = None;

    for diag in diags.iter() {
        sum_header_sections     += diag.header_sections;
        sum_bytecount_content   += diag.bytecount_content;
        sum_overall_byte_size   += diag.overall_byte_size;
        match max_overall_byte_size {
            None => max_overall_byte_size = Some((diag.num_internal_links, diag.id.clone())),
            Some((num, _)) => if num < diag.overall_byte_size {
                max_overall_byte_size = Some((diag.overall_byte_size, diag.id.clone()));
            }
        }

        let n = version_counts.get(&diag.entry_store_version).map(Clone::clone).unwrap_or(0);
        version_counts.insert(diag.entry_store_version.clone(), n+1);

        if diag.verified {
            verified_count += 1;
        } else {
            unverified_count += 1;
        }

        num_internal_links += diag.num_internal_links;
        match max_internal_links {
            None => max_internal_links = Some((diag.num_internal_links, diag.id.clone())),
            Some((num, _)) => if num < diag.num_internal_links {
                max_internal_links = Some((diag.num_internal_links, diag.id.clone()));
            }
        }
    }

    let n = diags.len();

    println!("imag version {}", version!());
    println!("");
    println!("{} entries", n);
    for (k, v) in version_counts {
        println!("{} entries with store version '{}'", v, k);
    }
    if n != 0 {
        println!("{} header sections in the average entry", sum_header_sections / n);
        println!("{} average content bytecount", sum_bytecount_content / n);
        println!("{} average overall bytecount", sum_overall_byte_size / n);
        if let Some((num, path)) = max_overall_byte_size {
            println!("Largest Entry ({bytes} bytes): {path}",
                bytes = num,
                path = path
                    .into_pathbuf()
                    .map_err_trace_exit_unwrap(1)
                    .to_str()
                    .unwrap_or("Failed converting path to string")
            );
        }
        println!("{} average internal link count per entry", num_internal_links / n);
        if let Some((num, path)) = max_internal_links {
            println!("Entry with most internal links ({count}): {path}",
                     count = num,
                     path = path
                        .into_pathbuf()
                        .map_err_trace_exit_unwrap(1)
                        .to_str()
                        .unwrap_or("Failed converting path to string")
            );
        }
        println!("{} verified entries", verified_count);
        println!("{} unverified entries", unverified_count);
    }
}

<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Implementation of the `RawLink` smart-ish pointer.
//!
//! A `RawLink` is a zero-cost abstraction that allows a raw pointer to be used
//! with an `Option`-esque API.
//!
//! TODO: implement all monadic operations over `Option`-esque types (i.e.
//! `map()`, `and_then()`, etc).

use core::ptr;
use core::fmt;
use core::mem;

/// A `RawLink` provides an `Option`-like interface to a raw pointer.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct RawLink<T>(*mut T);

unsafe impl<T> Send for RawLink<T>
where T: 'static
    , T: Send {}

unsafe impl<T> Sync for RawLink<T>
where T: Send
    , T: Sync {}

impl<T> Default for RawLink<T> {
    fn default() -> Self { Self::none() }
}

impl<T> fmt::Display for RawLink<T>
where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.0.is_null() {
            write!(f, "RawLink::none")
        } else {
            unsafe { write!(f, "RawLink::some({})", *self.0) }
        }

    }
}

impl<T> RawLink<T> {

    /// Equivalent of `Option::None` for a `RawLink`
    ///
    /// # Returns
    ///   - A `RawLink<T>` wrapping a null pointer
    #[inline]
    pub const fn none() -> RawLink<T> { RawLink(ptr::null_mut()) }

    /// Equivalent of `Option::Some` for a `RawLink`
    ///
    /// # Returns
    ///   - A `RawLink<T>` wrapping a pointer to the specified value
    #[inline]
    pub const fn some(thing: &mut T) -> RawLink<T> { RawLink(thing) }

    pub const fn from_raw(ptr: *mut T) -> RawLink<T> { RawLink(ptr) }

    /// Resolve the `RawLink` to an `Option`
    ///
    /// # Returns
    ///   - `Some<&'a T>` if the `RawLink` is not a null pointer
    ///   - `None` if the `RawLink` is a null pointer
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    #[inline]
    pub unsafe fn resolve<'a>(&self) -> Option<&'a T> {
        self.0.as_ref()
    }

    /// Resolve the `RawLink` to an `Option` on a mutable pointer
    ///
    /// # Returns
    ///   - `Some<&'a mut T>` if the `RawLink` is not a null pointer
    ///   - `None` if the `RawLink` is a null pointer
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    #[inline]
    pub unsafe fn resolve_mut<'a>(&self) -> Option<&'a mut T> {
        self.0.as_mut()
    }

    /// Please don't do this.
    ///
    /// # Returns
    ///   - The underlying raw pointer (`*mut T`) behind this `RawLink`
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    ///   - Please don't do this
    #[inline]
    pub unsafe fn as_raw(&self) -> *mut T { self.0 }

    #[inline]
    pub fn is_some(&self) -> bool { !self.is_none() }

    #[inline]
    pub fn is_none(&self) -> bool { self.0.is_null() }

    /// Returns the `RawLink` and replaces it with `RawLink::none()`.
    #[inline]
    pub fn take(&mut self) -> Self { mem::replace(self, Self::none()) }

    pub unsafe fn map<U, F: FnOnce(T) -> U>(self, f: F) -> RawLink<U> {
        unimplemented!()
    }
}
//
// impl<T> ops::Deref for RawLink<T> {
//     type Target = T;
//
//     fn deref(&self) -> &Self::Target { unsafe { self.resolve().unwrap() } }
// }
<commit_msg>[intrusive] fix issue with RawLink const fn changed in new Rust<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Implementation of the `RawLink` smart-ish pointer.
//!
//! A `RawLink` is a zero-cost abstraction that allows a raw pointer to be used
//! with an `Option`-esque API.
//!
//! TODO: implement all monadic operations over `Option`-esque types (i.e.
//! `map()`, `and_then()`, etc).

use core::ptr;
use core::fmt;
use core::mem;

/// A `RawLink` provides an `Option`-like interface to a raw pointer.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct RawLink<T>(*mut T);

unsafe impl<T> Send for RawLink<T>
where T: 'static
    , T: Send {}

unsafe impl<T> Sync for RawLink<T>
where T: Send
    , T: Sync {}

impl<T> Default for RawLink<T> {
    fn default() -> Self { Self::none() }
}

impl<T> fmt::Display for RawLink<T>
where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.0.is_null() {
            write!(f, "RawLink::none")
        } else {
            unsafe { write!(f, "RawLink::some({})", *self.0) }
        }

    }
}

impl<T> RawLink<T> {

    /// Equivalent of `Option::None` for a `RawLink`
    ///
    /// # Returns
    ///   - A `RawLink<T>` wrapping a null pointer
    #[inline]
    pub const fn none() -> RawLink<T> { RawLink(ptr::null_mut()) }

    /// Equivalent of `Option::Some` for a `RawLink`
    ///
    /// # Returns
    ///   - A `RawLink<T>` wrapping a pointer to the specified value
    #[inline]
    pub fn some(thing: &mut T) -> RawLink<T> { RawLink(thing) }

    pub const fn from_raw(ptr: *mut T) -> RawLink<T> { RawLink(ptr) }

    /// Resolve the `RawLink` to an `Option`
    ///
    /// # Returns
    ///   - `Some<&'a T>` if the `RawLink` is not a null pointer
    ///   - `None` if the `RawLink` is a null pointer
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    #[inline]
    pub unsafe fn resolve<'a>(&self) -> Option<&'a T> {
        self.0.as_ref()
    }

    /// Resolve the `RawLink` to an `Option` on a mutable pointer
    ///
    /// # Returns
    ///   - `Some<&'a mut T>` if the `RawLink` is not a null pointer
    ///   - `None` if the `RawLink` is a null pointer
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    #[inline]
    pub unsafe fn resolve_mut<'a>(&self) -> Option<&'a mut T> {
        self.0.as_mut()
    }

    /// Please don't do this.
    ///
    /// # Returns
    ///   - The underlying raw pointer (`*mut T`) behind this `RawLink`
    ///
    /// # Unsafe due to
    ///   - Returning a reference with an arbitrary lifetime
    ///   - Dereferencing a raw pointer
    ///   - Please don't do this
    #[inline]
    pub unsafe fn as_raw(&self) -> *mut T { self.0 }

    #[inline]
    pub fn is_some(&self) -> bool { !self.is_none() }

    #[inline]
    pub fn is_none(&self) -> bool { self.0.is_null() }

    /// Returns the `RawLink` and replaces it with `RawLink::none()`.
    #[inline]
    pub fn take(&mut self) -> Self { mem::replace(self, Self::none()) }

    pub unsafe fn map<U, F: FnOnce(T) -> U>(self, f: F) -> RawLink<U> {
        unimplemented!()
    }
}
//
// impl<T> ops::Deref for RawLink<T> {
//     type Target = T;
//
//     fn deref(&self) -> &Self::Target { unsafe { self.resolve().unwrap() } }
// }
<|endoftext|>


<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::{stdin, File};
use extra::getopts;
use std::run::{Process, ProcessOptions};
use std::io::signal::{Listener, Interrupt};

struct Shell {
    cmd_prompt: ~str,
    cwd: Path
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            cwd:        os::getcwd()
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());
        let mut history: ~[~str] = ~[];

        loop {
            print!("[{}] {}", self.cwd.filename_display() ,self.cmd_prompt);
            io::stdio::flush();

            // Catches interrupt signal to prevent closing gash,
            // placing the listener outside of the loop broke the external command functionality
            let mut listener = Listener::new();
            listener.register(Interrupt);

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

            match program {
                ""      =>  { continue; }
                "history"   =>  { for i in range(0, history.len()) {
                                     println! ("{}: {}", i+1, history[i]);
                                    }
                                }
                "exit"  =>  { return; }
                "help"      =>  { println!("Why you askin' me?");}
                "cd"        =>  { self.run_cd(cmd_line)}
                _       =>  { self.run_cmdline(cmd_line); }
            }

            history.push(cmd_line.to_owned());
        }
    }

    fn run_cd(&mut self, cmd_line: &str){
        let argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 1 {
            let path_str: ~str = argv[1];
            let path = Path::new(path_str);
            if os::change_dir(&path) {
                self.cwd.push(path);
            }
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
        let program: ~str = argv.remove(0);
                self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            if argv.contains(&~"&") {
                let background = true;
                let argv_bkgd = argv.slice(0, argv.len()-1);
                if argv_bkgd.contains(&~">"){
                    for i in range(0, argv_bkgd.len()){
                        if argv_bkgd[i] == ~">" {
                            self.redirect_right(program, argv_bkgd.slice(0, i), argv_bkgd[i+1], background);
                            break;
                        }
                    }
                }
                else if argv_bkgd.contains(&~"<"){
                    for i in range(0, argv_bkgd.len()){
                        if argv_bkgd[i] == ~"<" {
                            self.redirect_left(program, argv_bkgd.slice(0, i), argv_bkgd[i+1], background);
                            break;
                        }
                    }
                }
                else {
                    let process = Process::new(program, argv_bkgd, ProcessOptions{
                        env: None,
                        dir: None,
                        in_fd: Some(0),
                        out_fd: Some(1),
                        err_fd: Some(2)
                    });
                    spawn(proc () {
                        match process {
                            Some(mut process) => {
                                process.finish();
                            },
                            None       => { }
                        }
                    });
                }

            } else {
                let background = false;
                if argv.contains(&~">"){
                    for i in range(0, argv.len()){
                        if argv[i] == ~">" {
                            self.redirect_right(program, argv.slice(0, i), argv[i+1], background);
                            break;
                        }
                    }
                }
                else if argv.contains(&~"<"){
                    for i in range(0, argv.len()){
                        if argv[i] == ~"<" {
                            self.redirect_left(program, argv.slice(0, i), argv[i+1], background);
                            break;
                        }
                    }
                }
                else if argv.contains(&~"|"){
                    let mut args = argv.to_owned();
                    args.insert(0, program.to_owned());
                    self.check_for_pipes(args);
                }
                else {
                    // No pipe or redirect
                    run::process_status(program, argv);
                }

            }

        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    fn check_for_pipes(&mut self, cmd_argv: &[~str]){
        for i in range(0, cmd_argv.len()){
            if cmd_argv[i] == ~"|" {
                self.pipe(cmd_argv[0], cmd_argv.slice(1, i), cmd_argv[i+1], cmd_argv.slice(i+2, cmd_argv.len()));
            }
        }
    }

    // Functional, but not correctly
    fn redirect_right(&mut self, program: &str, argv: &[~str], write_to_file: &str, background: bool){

        if background {
            let path = &Path::new(write_to_file.clone());
            let mut output_file = File::create(path).unwrap();
            println!("Created output file {}", write_to_file);
            let process = Process::new(program, argv, ProcessOptions::new());

            let (port, chan): (Port<~str>, Chan<~str>) = Chan::new();
            spawn(proc() {
                match process {
                    Some(mut p)     => {
                        {
                            let process = &mut p;
                            let reader = process.output();
                            let output = reader.read_to_str();  //~str

                            // Write to output file
                            chan.send(output);
                        }
                        p.close_input();
                        p.close_outputs();
                        p.finish();
                    },
                    None            => {println!("Redirect error!");}
                }
            });
            let output = port.recv();
            output_file.write_str(output);
        } else {
            let path = &Path::new(write_to_file.clone());
            let mut output_file = File::create(path).unwrap();
            println!("Created output file {}", write_to_file);

            // Works now, but requires interrupt signal to
            // be sent twice to return to gash
            match Process::new(program, argv, ProcessOptions::new()) {
                Some(mut p) => {
                    {
                        let process = &mut p;
                        let rdr = process.output();
                        let out = rdr.read_to_str();

                        // Write to output file
                        output_file.write_str(out);
                    }
                    p.close_input();
                    p.close_outputs();
                    p.finish();
                },
                None => {println!("Redirect error!");}
            }
        }
    }

    fn redirect_left(&mut self, program: &str, argv: &[~str], read_from_file: &str, background: bool){
        if background {

        }
        else {
            let path = &Path::new(read_from_file.clone());

            println!("Prog1: {}", program );
            for i in range(0, argv.len()){
                print!("\t{}", argv[i]);
            }

            if !path.is_file() {
                println!("There doesn't seem to be any file called {}", read_from_file);
            }
            else {
                let mut input_file = File::open(path);
                let input = input_file.read_to_end();
                println!("Starting process");
                match Process::new(program, argv, ProcessOptions{
                    env: None,
                    dir: None,
                    in_fd: None,
                    out_fd: Some(1),
                    err_fd: Some(2)
                }) {
                    Some(mut p) => {
                        {
                            let process = &mut p;
                            let wtr = process.input();

                            // Read input file
                            wtr.write(input);
                        }
                        p.close_input();
                        p.close_outputs();
                        p.finish();
                    },
                    None => {println!("Redirect error!");}
                }
            }
        }

    }

    fn pipe(&mut self, prog1: &str, prog1_args: &[~str], prog2: &str, prog2_args: &[~str]){

        let process1 = Process::new(prog1, prog1_args, ProcessOptions{
            env: None,
            dir: None,
            in_fd: Some(0),
            out_fd: None,
            err_fd: Some(2)
        });
        let (port1, chan1): (Port<~str>, Chan<~str>) = Chan::new();
        spawn(proc() {
            match process1 {
                Some(mut p1)    => {
                    {
                        let process1 = &mut p1;
                        let output = process1.output().read_to_str();
                        chan1.send(output);
                    }
                    p1.close_input();
                    p1.close_outputs();
                    p1.finish();
                },
                None            => { println!("Pipe Error!");}
            }
        });

        let process2 = Process::new(prog2, prog2_args, ProcessOptions{
            env: None,
            dir: None,
            in_fd: None,
            out_fd: Some(1),
            err_fd: Some(2)
        });

        let (port2, chan2): (Port<~str>, Chan<~str>) = Chan::new();
        spawn(proc() {
            match process2 {
                Some(mut p2)    => {
                    {
                        let process2 = &mut p2;
                        let writer = process2.input();
                        let input = port1.recv();
                        writer.write_str(input);
                    }
                    p2.close_input();
                    p2.close_outputs();
                    p2.finish();
                },
                None            => { println!("Pipe Error!");}
            }
        });
    }

}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>Update gash.rs<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::{stdin, File};
use extra::getopts;
use std::run::{Process, ProcessOptions};
use std::io::signal::{Listener, Interrupt};

struct Shell {
    cmd_prompt: ~str,
    cwd: Path
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            cwd:        os::getcwd()
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());
        let mut history: ~[~str] = ~[];

        loop {
            print!("[{}] {}", self.cwd.filename_display() ,self.cmd_prompt);
            io::stdio::flush();

            // Catches interrupt signal to prevent closing gash,
            // placing the listener outside of the loop broke the external command functionality
            let mut listener = Listener::new();
            listener.register(Interrupt);

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

            match program {
                ""      =>  { continue; }
                "history"   =>  { for i in range(0, history.len()) {
                                     println! ("{}: {}", i+1, history[i]);
                                    }
                                }
                "exit"  =>  { return; }
                "help"      =>  { println!("Why you askin' me?");}
                "cd"        =>  { self.run_cd(cmd_line)}
                _       =>  { self.run_cmdline(cmd_line); }
            }

            history.push(cmd_line.to_owned());
        }
    }

    fn run_cd(&mut self, cmd_line: &str){
        let argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 1 {
            let path_str: ~str = argv[1];
            let path = Path::new(path_str);
            if os::change_dir(&path) {
                self.cwd.push(path);
            }
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
        let program: ~str = argv.remove(0);
                self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            if argv.contains(&~"&") {
                let background = true;
                let argv_bkgd = argv.slice(0, argv.len()-1);
                if argv_bkgd.contains(&~">"){
                    for i in range(0, argv_bkgd.len()){
                        if argv_bkgd[i] == ~">" {
                            self.redirect_right(program, argv_bkgd.slice(0, i), argv_bkgd[i+1], background);
                            break;
                        }
                    }
                }
                else if argv_bkgd.contains(&~"<"){
                    for i in range(0, argv_bkgd.len()){
                        if argv_bkgd[i] == ~"<" {
                            self.redirect_left(program, argv_bkgd.slice(0, i), argv_bkgd[i+1], background);
                            break;
                        }
                    }
                }
                else {
                    let process = Process::new(program, argv_bkgd, ProcessOptions{
                        env: None,
                        dir: None,
                        in_fd: Some(0),
                        out_fd: Some(1),
                        err_fd: Some(2)
                    });
                    spawn(proc () {
                        match process {
                            Some(mut process) => {
                                process.finish();
                            },
                            None       => { }
                        }
                    });
                }

            } else {
                let background = false;
                if argv.contains(&~">"){
                    for i in range(0, argv.len()){
                        if argv[i] == ~">" {
                            self.redirect_right(program, argv.slice(0, i), argv[i+1], background);
                            break;
                        }
                    }
                }
                else if argv.contains(&~"<"){
                    for i in range(0, argv.len()){
                        if argv[i] == ~"<" {
                            self.redirect_left(program, argv.slice(0, i), argv[i+1], background);
                            break;
                        }
                    }
                }
                else if argv.contains(&~"|"){
                    let mut args = argv.to_owned();
                    args.insert(0, program.to_owned());
                    self.check_for_pipes(args);
                }
                else {
                    // No pipe or redirect
                    run::process_status(program, argv);
                }

            }

        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    fn check_for_pipes(&mut self, cmd_argv: &[~str]){
        for i in range(0, cmd_argv.len()){
            if cmd_argv[i] == ~"|" {
                self.pipe(cmd_argv[0], cmd_argv.slice(1, i), cmd_argv[i+1], cmd_argv.slice(i+2, cmd_argv.len()));
            }
        }
    }

    // Functional, but not correctly
    fn redirect_right(&mut self, program: &str, argv: &[~str], write_to_file: &str, background: bool){

        if background {
            let path = &Path::new(write_to_file.clone());
            let mut output_file = File::create(path).unwrap();
            println!("Created output file {}", write_to_file);
            let process = Process::new(program, argv, ProcessOptions::new());

            let (port, chan): (Port<~str>, Chan<~str>) = Chan::new();
            spawn(proc() {
                match process {
                    Some(mut p)     => {
                        {
                            let process = &mut p;
                            let reader = process.output();
                            let output = reader.read_to_str();  //~str

                            // Write to output file
                            chan.send(output);
                        }
                        p.close_input();
                        p.close_outputs();
                        p.finish();
                    },
                    None            => {println!("Redirect error!");}
                }
            });
            let output = port.recv();
            output_file.write_str(output);
        } else {
            let path = &Path::new(write_to_file.clone());
            let mut output_file = File::create(path).unwrap();
            println!("Created output file {}", write_to_file);

            // Works now, but requires interrupt signal to
            // be sent twice to return to gash
            match Process::new(program, argv, ProcessOptions::new()) {
                Some(mut p) => {
                    {
                        let process = &mut p;
                        let rdr = process.output();
                        let out = rdr.read_to_str();

                        // Write to output file
                        output_file.write_str(out);
                    }
                    p.close_input();
                    p.close_outputs();
                    p.finish();
                },
                None => {println!("Redirect error!");}
            }
        }
    }

    fn redirect_left(&mut self, program: &str, argv: &[~str], read_from_file: &str, background: bool){
        if background {

        }
        else {
            let path = &Path::new(read_from_file.clone());

            if !path.is_file() {
                println!("There doesn't seem to be any file called {}", read_from_file);
            }
            else {
                let mut input_file = File::open(path);
                let input = input_file.read_to_end();
                println!("Starting process");
                match Process::new(program, argv, ProcessOptions{
                    env: None,
                    dir: None,
                    in_fd: None,
                    out_fd: Some(1),
                    err_fd: Some(2)
                }) {
                    Some(mut p) => {
                        {
                            let process = &mut p;
                            let wtr = process.input();

                            // Read input file
                            wtr.write(input);
                        }
                        p.close_input();
                        p.close_outputs();
                        p.finish();
                    },
                    None => {println!("Redirect error!");}
                }
            }
        }

    }

    fn pipe(&mut self, prog1: &str, prog1_args: &[~str], prog2: &str, prog2_args: &[~str]){

        let process1 = Process::new(prog1, prog1_args, ProcessOptions{
            env: None,
            dir: None,
            in_fd: Some(0),
            out_fd: None,
            err_fd: Some(2)
        });
        let (port1, chan1): (Port<~str>, Chan<~str>) = Chan::new();
        spawn(proc() {
            match process1 {
                Some(mut p1)    => {
                    {
                        let process1 = &mut p1;
                        let output = process1.output().read_to_str();
                        chan1.send(output);
                    }
                    p1.close_input();
                    p1.close_outputs();
                    p1.finish();
                },
                None            => { println!("Pipe Error!");}
            }
        });

        let process2 = Process::new(prog2, prog2_args, ProcessOptions{
            env: None,
            dir: None,
            in_fd: None,
            out_fd: Some(1),
            err_fd: Some(2)
        });

        let (port2, chan2): (Port<~str>, Chan<~str>) = Chan::new();
        spawn(proc() {
            match process2 {
                Some(mut p2)    => {
                    {
                        let process2 = &mut p2;
                        let writer = process2.input();
                        let input = port1.recv();
                        writer.write_str(input);
                    }
                    p2.close_input();
                    p2.close_outputs();
                    p2.finish();
                },
                None            => { println!("Pipe Error!");}
            }
        });
    }

}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<|endoftext|>


<commit_before>extern crate gl_generator;

use gl_generator::{Registry, Api, Profile, Fallbacks, GlobalGenerator};
use std::env;
use std::path::Path;
use std::process::Command;
use std::fs::File;

fn main() {
    let profile = env::var("PROFILE").unwrap_or("Debug".to_string());
    let current_dir = std::env::current_dir().unwrap();
    let target;
    let target_os = env::var("TARGET").unwrap();

    if profile == "Release" {
        target = Path::new(&current_dir).join("target/release");
    } else {
        target = Path::new(&current_dir).join("target/debug");
    }

    let dest = env::var("OUT_DIR").unwrap();
    let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap();

    Registry::new(Api::Gles2, (2, 0), Profile::Core, Fallbacks::All, [])
        .write_bindings(GlobalGenerator, &mut file)
        .unwrap();

    Command::new("rustc")
        .arg("src/test_shared.rs")
        .arg("--crate-name")
        .arg("test_shared")
        .arg("--crate-type")
        .arg("dylib")
        .arg("--out-dir")
        .arg(target)
        .output()
        .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

    if target_os.contains("android") {
        println!("cargo:rustc-flags=-L android/Minigame/sdl/build/intermediates/cmake/debug/obj/armeabi",);
        println!("cargo:rustc-flags=-L android/Minigame/sdl/build/intermediates/cmake/debug/obj/armeabi-v7a",);
        println!("cargo:rustc-flags=-L android/Minigame/sdl/build/intermediates/cmake/debug/obj/x86",);

        // We should also add the following instead of defining our toolchain in .cargo/config
        // -C link-arg=--sysroot=$NDK_ROOT/platforms/android-<api level you are targeting>/arch-arm

        let abi = if target_os.contains("armv7") {
            "armeabi-v7a"
        } else if target_os.contains("aarch64") {
            "arm64-v8a"
        } else if target_os.contains("arm") {
            "armeabi"
        } else if target_os.contains("x86") {
            "x86"
        } else if target_os.contains("i686") {
            "x86"
        } else {
            panic!("Invalid target architecture {}", target_os);
        };

        let src = Path::new(&current_dir).join("target").join(target_os).join("debug").join("libminigame.so");
        let dst = Path::new(&current_dir).join("android/Minigame/app/src/main/jniLibs").join(abi).join("libminigame.so");
        //panic!("{:?}", dst);
        //std::fs::remove_file(Path::new(&dst)).unwrap();
        // This won't work as it's being executed before the actual library has finished building :(
        std::fs::copy(src, dst).unwrap();
    }
}<commit_msg>Added a missing reference for arm64 Android libraries<commit_after>extern crate gl_generator;

use gl_generator::{Registry, Api, Profile, Fallbacks, GlobalGenerator};
use std::env;
use std::path::Path;
use std::process::Command;
use std::fs::File;

fn main() {
    let profile = env::var("PROFILE").unwrap_or("Debug".to_string());
    let current_dir = std::env::current_dir().unwrap();
    let target;
    let target_os = env::var("TARGET").unwrap();

    if profile == "Release" {
        target = Path::new(&current_dir).join("target/release");
    } else {
        target = Path::new(&current_dir).join("target/debug");
    }

    let dest = env::var("OUT_DIR").unwrap();
    let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap();

    Registry::new(Api::Gles2, (2, 0), Profile::Core, Fallbacks::All, [])
        .write_bindings(GlobalGenerator, &mut file)
        .unwrap();

    Command::new("rustc")
        .arg("src/test_shared.rs")
        .arg("--crate-name")
        .arg("test_shared")
        .arg("--crate-type")
        .arg("dylib")
        .arg("--out-dir")
        .arg(target)
        .output()
        .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

    if target_os.contains("android") {
        println!("cargo:rustc-flags=-L android/Minigame/sdl/build/intermediates/cmake/debug/obj/armeabi",);
        println!("cargo:rustc-flags=-L android/Minigame/sdl/build/intermediates/cmake/debug/obj/armeabi-v7a",);
        println!("cargo:rustc-flags=-L android/Minigame/sdl/build/intermediates/cmake/debug/obj/x86",);
        println!("cargo:rustc-flags=-L android/Minigame/sdl/build/intermediates/cmake/debug/obj/arm64-v8a",);

        // We should also add the following instead of defining our toolchain in .cargo/config
        // -C link-arg=--sysroot=$NDK_ROOT/platforms/android-<api level you are targeting>/arch-arm

        let abi = if target_os.contains("armv7") {
            "armeabi-v7a"
        } else if target_os.contains("aarch64") {
            "arm64-v8a"
        } else if target_os.contains("arm") {
            "armeabi"
        } else if target_os.contains("x86") {
            "x86"
        } else if target_os.contains("i686") {
            "x86"
        } else {
            panic!("Invalid target architecture {}", target_os);
        };

        let src = Path::new(&current_dir).join("target").join(target_os).join("debug").join("libminigame.so");
        let dst = Path::new(&current_dir).join("android/Minigame/app/src/main/jniLibs").join(abi).join("libminigame.so");
        //panic!("{:?}", dst);
        //std::fs::remove_file(Path::new(&dst)).unwrap();
        // This won't work as it's being executed before the actual library has finished building :(
        std::fs::copy(src, dst).unwrap();
    }
}<|endoftext|>


<commit_before>use std::process::Command;
use std::env;

#[cfg(target_os="macos")]
fn print_lib_dir() {
    println!("cargo:rustc-flags=-L /usr/local/opt/gettext/lib/");
}

#[cfg(not(target_os="macos"))]
fn print_lib_dir() {
}

fn main() {
    let curr_dir = env::current_dir().unwrap();
    Command::new("git").arg("submodule").arg("update").arg("--init")
        .current_dir(&curr_dir).status().unwrap();

    let nvim_dir = curr_dir.join("neovim");
    Command::new("make").arg("deps").current_dir(&nvim_dir).status().unwrap();
    Command::new("make").arg("libnvim").current_dir(&nvim_dir).status().unwrap();

    let nvim_lib_dir = nvim_dir.join("build").join("lib");
    let deps_lib_dir = nvim_dir.join(".deps").join("usr").join("lib");
    println!("cargo:rustc-flags=-L {} -L {} -l nvim",
        nvim_lib_dir.to_str().unwrap(),
        deps_lib_dir.to_str().unwrap());

    print_lib_dir();
}
<commit_msg>Link to all libs<commit_after>use std::process::Command;
use std::env;

#[cfg(target_os="macos")]
fn print_lib_dir() {
    println!("cargo:rustc-flags=-L /usr/local/opt/gettext/lib/");
}

#[cfg(not(target_os="macos"))]
fn print_lib_dir() {
}

fn main() {
    let curr_dir = env::current_dir().unwrap();
    Command::new("git").arg("submodule").arg("update").arg("--init")
        .current_dir(&curr_dir).status().unwrap();

    let nvim_dir = curr_dir.join("neovim");
    Command::new("make").arg("deps").current_dir(&nvim_dir).status().unwrap();
    Command::new("make").arg("libnvim").current_dir(&nvim_dir).status().unwrap();

    let nvim_lib_dir = nvim_dir.join("build").join("lib");
    let deps_lib_dir = nvim_dir.join(".deps").join("usr").join("lib");
    println!("cargo:rustc-flags=-L {} -L {} -l nvim -l uv -l msgpack -l termkey -l unibilium -l vterm",
        nvim_lib_dir.to_str().unwrap(),
        deps_lib_dir.to_str().unwrap());

    print_lib_dir();
}
<|endoftext|>


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

extern crate cc;

use std::env;
use std::path::PathBuf;

fn main() {
    let mut build = cc::Build::new();
    let outdir = env::var("DEP_MOZJS_OUTDIR").unwrap();
    let include_path: PathBuf = [&outdir, "dist", "include"].iter().collect();

    build.cpp(true)
        .file("src/jsglue.cpp")
        .flag("-DSTATIC_JS_API")
        .include(include_path);
    if env::var("CARGO_FEATURE_DEBUGMOZJS").is_ok() {
        build.define("DEBUG", "");

        if cfg!(target_os = "windows") {
            build.flag("-Od");
        } else {
            build.flag("-g");
            build.flag("-O0");
        }
    }

    if env::var("CARGO_FEATURE_PROFILEMOZJS").is_ok() {
        build.flag_if_supported("-fno-omit-frame-pointer");
    }

    build.flag_if_supported("-Wno-c++0x-extensions");
    build.flag_if_supported("-Wno-return-type-c-linkage");
    build.flag_if_supported("-Wno-invalid-offsetof");
    build.flag_if_supported("-Wno-unused-parameter");

    let confdefs_path: PathBuf = [&outdir, "js", "src", "js-confdefs.h"].iter().collect();
    if cfg!(target_os = "windows") {
        build.flag(&format!("-FI{}", confdefs_path.to_string_lossy()));
        build.define("WIN32", "");
        build.flag("-Zi");
        build.flag("-GR-");
        build.flag("-std:c++17");
    } else {
        build.flag("-fPIC");
        build.flag("-fno-rtti");
        build.flag("-std=c++17");
        build.define("JS_NO_JSVAL_JSID_STRUCT_TYPES", "");
        build.flag("-include");
        build.flag(&confdefs_path.to_string_lossy());
    }

    build.compile("jsglue");
    println!("cargo:rerun-if-changed=src/jsglue.cpp");
}
<commit_msg>Use MSVC-like flags on MSVC-like compilers<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate cc;

use std::env;
use std::path::PathBuf;

fn main() {
    let mut build = cc::Build::new();
    let outdir = env::var("DEP_MOZJS_OUTDIR").unwrap();
    let include_path: PathBuf = [&outdir, "dist", "include"].iter().collect();

    build.cpp(true)
        .file("src/jsglue.cpp")
        .flag("-DSTATIC_JS_API")
        .include(include_path);
    if env::var("CARGO_FEATURE_DEBUGMOZJS").is_ok() {
        build.define("DEBUG", "");

        if cfg!(target_os = "windows") {
            build.flag("-Od");
        } else {
            build.flag("-g");
            build.flag("-O0");
        }
    }

    if env::var("CARGO_FEATURE_PROFILEMOZJS").is_ok() {
        build.flag_if_supported("-fno-omit-frame-pointer");
    }

    build.flag_if_supported("-Wno-c++0x-extensions");
    build.flag_if_supported("-Wno-return-type-c-linkage");
    build.flag_if_supported("-Wno-invalid-offsetof");
    build.flag_if_supported("-Wno-unused-parameter");

    let confdefs_path: PathBuf = [&outdir, "js", "src", "js-confdefs.h"].iter().collect();
    if build.get_compiler().is_like_msvc() {
        build.flag(&format!("-FI{}", confdefs_path.to_string_lossy()));
        build.define("WIN32", "");
        build.flag("-Zi");
        build.flag("-GR-");
        build.flag("-std:c++17");
    } else {
        build.flag("-fPIC");
        build.flag("-fno-rtti");
        build.flag("-std=c++17");
        build.define("JS_NO_JSVAL_JSID_STRUCT_TYPES", "");
        build.flag("-include");
        build.flag(&confdefs_path.to_string_lossy());
    }

    build.compile("jsglue");
    println!("cargo:rerun-if-changed=src/jsglue.cpp");
}
<|endoftext|>


<commit_before>#![no_std]
#![no_main]
#![feature(globs)]
#![feature(lang_items)]
#![feature(asm)]

#![allow(uppercase_variables)]
#![allow(non_camel_case_types)]

extern crate core;

use core::prelude::*;

use core::mem;
use core::raw::Slice;
use core::intrinsics::{volatile_load, volatile_store};
use core::ty::Unsafe;

#[lang = "begin_unwind"]
extern fn begin_unwind(args: &core::fmt::Arguments,
                       file: &str,
                       line: uint) -> ! {
    loop {}
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[no_mangle]
pub unsafe extern "C" fn _kill() { loop{} }

#[no_mangle]
pub unsafe extern "C" fn _getpid() { loop{} }

static SCS_BASE: uint = 0xE000E000; // System Control Space Base Address
static SysTick_BASE: uint = SCS_BASE +  0x0010; // SysTick Base Address
static NVIC_BASE: uint = SCS_BASE +  0x0100;    //NVIC Base Address
static SCB_BASE: uint = SCS_BASE +  0x0D00;

#[repr(C)]
struct SysTick {
  CTRL: Reg<u32>, // Offset: 0x000 (R/W)  SysTick Control and Status Register
  LOAD: Reg<u32>, // Offset: 0x004 (R/W)  SysTick Reload Value Register
  VAL: Reg<u32>,  // Offset: 0x008 (R/W)  SysTick Current Value Register
  CALIB: Reg<u32>,
}

static SysTick_CTRL_COUNTFLAG_Pos: uint = 16;                                    // SysTick CTRL: COUNTFLAG Position
static SysTick_CTRL_COUNTFLAG_Msk: u32 = (1 << SysTick_CTRL_COUNTFLAG_Pos);   // SysTick CTRL: COUNTFLAG Mask

static SysTick_CTRL_CLKSOURCE_Pos: uint =  2;                                    // SysTick CTRL: CLKSOURCE Position
static SysTick_CTRL_CLKSOURCE_Msk: u32 = (1 << SysTick_CTRL_CLKSOURCE_Pos);   // SysTick CTRL: CLKSOURCE Mask

static SysTick_CTRL_TICKINT_Pos: uint =    1;                                    // SysTick CTRL: TICKINT Position
static SysTick_CTRL_TICKINT_Msk: u32 =   (1 << SysTick_CTRL_TICKINT_Pos);    //  SysTick CTRL: TICKINT Mask

static SysTick_CTRL_ENABLE_Pos: uint =     0;                                  // SysTick CTRL: ENABLE Position
static SysTick_CTRL_ENABLE_Msk: u32 =    (1 << SysTick_CTRL_ENABLE_Pos);    // SysTick CTRL: ENABLE Mask

#[repr(C)]
struct Reg<T> {
  value: Unsafe<T>,
}

impl<T:Copy> Reg<T> {
  #[inline]
  fn get(&self) -> T {
    unsafe {
      volatile_load(self.value.get() as *const T)
    }
  }

  #[inline]
  fn set(&self, value: T) {
    unsafe {
      volatile_store(self.value.get(), value)
    }
  }
}

impl Reg<u32> {
  fn write_bit(&self, b: u8) {
    self.set(1 << (b as uint));
  }

  fn set_bit(&self, b: u8) {
    let old = self.get();
    self.set(old | (1 << (b as uint)));
  }

  fn clear_bit(&self, b: u8) {
    let old = self.get();
    self.set(old & !(1 << (b as uint)));
  }
}

impl SysTick {
  fn get() -> &'static SysTick {
    unsafe { &*(SysTick_BASE as *const SysTick) }
  }

  fn init(&self, ticks: u32) {
    self.LOAD.set(ticks - 1);
    self.VAL.set(0);
    self.CTRL.set(SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
  }
}

static SCU_BASE: u32 = 0x40086000;

#[repr(C)]
struct SCU {
  SFSP: [[Reg<u32>, ..32], ..16],
  RSVD1: [u32, ..256],
  SFSCLK: [Reg<u32>, ..4],
  RSVD2: [u32, ..28],
  SFSUSB: Reg<u32>,
  SFSI2C0: Reg<u32>,
  SFSENAIO: [Reg<u32>, ..3],
  RSVD3: [u32, ..27],
  EMCDELAYCLK: Reg<u32>,
  RSVD4: [u32, ..63],
  PINTSEL: [Reg<u32>, ..2],
}

static PDN_ENABLE: u32 =        (1 << 3);	// Pull-down enable
static PDN_DISABLE: u32 =       (0 << 3);      // Pull-down disable
static PUP_ENABLE: u32 =        (0 << 4);      // Pull-up enable
static PUP_DISABLE: u32 =       (1 << 4);	// Pull-up disable
static SLEWRATE_SLOW: u32 =	  (0 << 5);	// Slew rate for low noise with medium speed
static SLEWRATE_FAST: u32 =	  (1 << 5);	// Slew rate for medium noise with fast speed
static INBUF_ENABLE: u32 =	  (1 << 6);	// Input buffer
static INBUF_DISABLE: u32 =	  (0 << 6);	// Input buffer
static FILTER_ENABLE: u32 =	  (0 << 7);	// Glitch filter (for signals below 30MHz)
static FILTER_DISABLE: u32 =	  (1 << 7);	// No glitch filter (for signals above 30MHz)
static DRIVE_8MA: u32 =         (1 << 8);	// Drive strength of 8mA
static DRIVE_14MA: u32 =        (1 << 9);	// Drive strength of 14mA
static DRIVE_20MA: u32 =        (3 << 8);	// Drive strength of 20mA

impl SCU {
  fn get() -> &'static SCU {
    unsafe { &*(SCU_BASE as *const SCU) }
  }

  fn pinmux(&self, (port, pin): (u8, u8), mode: u32, func: u32) {
    self.SFSP[port as uint][pin as uint].set(mode | func);
  }
}

static LED1: (u8, u8) = (11, 2);
static LED2: (u8, u8) = (7, 3);

static GPIO_PORT_BASE: u32 = 0x400F4000;

#[repr(C)]
struct GPIO {
  B: [Reg<u8>, ..256],
  RESERVED0: [u32, ..960],
  W: [Reg<u32>, ..256],
  RESERVED1: [u32, ..768],
  DIR: [Reg<u32>, ..8],
  RESERVED2: [u32, ..24],
  MASK: [Reg<u32>, ..8],
  RESERVED3: [u32, ..24],
  PIN: [Reg<u32>, ..8],
  RESERVED4: [u32, ..24],
  MPIN: [Reg<u32>, ..8],
  RESERVED5: [u32, ..24],
  SET: [Reg<u32>, ..8],
  RESERVED6: [u32, ..24],
  CLR: [Reg<u32>, ..8],
  RESERVED7: [u32, ..24],
  NOT: [Reg<u32>, ..8],
  RESERVED8: [u32, ..24],
}

impl GPIO {
  fn get() -> &'static GPIO {
    unsafe { &*(GPIO_PORT_BASE as *const GPIO) }
  }

  fn dir(&self, (port, pin): (u8, u8), output: bool) {
    if output {
      self.DIR[port as uint].set_bit(pin);
    } else {
      self.DIR[port as uint].clear_bit(pin);
    }
  }

  fn write(&self, (port, pin): (u8, u8), value: bool) {
    if value {
      self.SET[port as uint].write_bit(pin);
    } else {
      self.CLR[port as uint].write_bit(pin);
    }
  }

  fn toggle(&self, (port, pin): (u8, u8)) {
    self.NOT[port as uint].write_bit(pin);
  }
}

static LED1_GPIO: (u8, u8) = (5, 22);
static LED2_GPIO: (u8, u8) = (3, 11);

#[no_mangle]
#[no_split_stack]
pub unsafe extern "C" fn _reset_handler() {
  let systick = SysTick::get();
  let scu = SCU::get();
  systick.init(180_000_000 / 1000);

  scu.pinmux(LED1, PUP_DISABLE, 4);
  scu.pinmux(LED2, PUP_DISABLE, 0);

  let gpio = GPIO::get();
  gpio.write(LED1_GPIO, true);
  gpio.dir(LED1_GPIO, true);
  gpio.write(LED2_GPIO, false);
  gpio.dir(LED2_GPIO, true);

  asm!("CPSIE i");
  loop{}
}

static mut count: u32 = 0;

#[no_mangle]
pub unsafe extern "C" fn SysTick_Handler() {
  let gpio = GPIO::get();
  count += 1;
  if count % 100 == 0 {
    gpio.toggle(LED1_GPIO);
    gpio.toggle(LED2_GPIO);
  }
}
<commit_msg>rust: duplicate imports are now forbidden<commit_after>#![no_std]
#![no_main]
#![feature(globs)]
#![feature(lang_items)]
#![feature(asm)]

#![allow(uppercase_variables)]
#![allow(non_camel_case_types)]

extern crate core;

use core::prelude::*;

use core::mem;
use core::intrinsics::{volatile_load, volatile_store};
use core::ty::Unsafe;

#[lang = "begin_unwind"]
extern fn begin_unwind(args: &core::fmt::Arguments,
                       file: &str,
                       line: uint) -> ! {
    loop {}
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[no_mangle]
pub unsafe extern "C" fn _kill() { loop{} }

#[no_mangle]
pub unsafe extern "C" fn _getpid() { loop{} }

static SCS_BASE: uint = 0xE000E000; // System Control Space Base Address
static SysTick_BASE: uint = SCS_BASE +  0x0010; // SysTick Base Address
static NVIC_BASE: uint = SCS_BASE +  0x0100;    //NVIC Base Address
static SCB_BASE: uint = SCS_BASE +  0x0D00;

#[repr(C)]
struct SysTick {
  CTRL: Reg<u32>, // Offset: 0x000 (R/W)  SysTick Control and Status Register
  LOAD: Reg<u32>, // Offset: 0x004 (R/W)  SysTick Reload Value Register
  VAL: Reg<u32>,  // Offset: 0x008 (R/W)  SysTick Current Value Register
  CALIB: Reg<u32>,
}

static SysTick_CTRL_COUNTFLAG_Pos: uint = 16;                                    // SysTick CTRL: COUNTFLAG Position
static SysTick_CTRL_COUNTFLAG_Msk: u32 = (1 << SysTick_CTRL_COUNTFLAG_Pos);   // SysTick CTRL: COUNTFLAG Mask

static SysTick_CTRL_CLKSOURCE_Pos: uint =  2;                                    // SysTick CTRL: CLKSOURCE Position
static SysTick_CTRL_CLKSOURCE_Msk: u32 = (1 << SysTick_CTRL_CLKSOURCE_Pos);   // SysTick CTRL: CLKSOURCE Mask

static SysTick_CTRL_TICKINT_Pos: uint =    1;                                    // SysTick CTRL: TICKINT Position
static SysTick_CTRL_TICKINT_Msk: u32 =   (1 << SysTick_CTRL_TICKINT_Pos);    //  SysTick CTRL: TICKINT Mask

static SysTick_CTRL_ENABLE_Pos: uint =     0;                                  // SysTick CTRL: ENABLE Position
static SysTick_CTRL_ENABLE_Msk: u32 =    (1 << SysTick_CTRL_ENABLE_Pos);    // SysTick CTRL: ENABLE Mask

#[repr(C)]
struct Reg<T> {
  value: Unsafe<T>,
}

impl<T:Copy> Reg<T> {
  #[inline]
  fn get(&self) -> T {
    unsafe {
      volatile_load(self.value.get() as *const T)
    }
  }

  #[inline]
  fn set(&self, value: T) {
    unsafe {
      volatile_store(self.value.get(), value)
    }
  }
}

impl Reg<u32> {
  fn write_bit(&self, b: u8) {
    self.set(1 << (b as uint));
  }

  fn set_bit(&self, b: u8) {
    let old = self.get();
    self.set(old | (1 << (b as uint)));
  }

  fn clear_bit(&self, b: u8) {
    let old = self.get();
    self.set(old & !(1 << (b as uint)));
  }
}

impl SysTick {
  fn get() -> &'static SysTick {
    unsafe { &*(SysTick_BASE as *const SysTick) }
  }

  fn init(&self, ticks: u32) {
    self.LOAD.set(ticks - 1);
    self.VAL.set(0);
    self.CTRL.set(SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
  }
}

static SCU_BASE: u32 = 0x40086000;

#[repr(C)]
struct SCU {
  SFSP: [[Reg<u32>, ..32], ..16],
  RSVD1: [u32, ..256],
  SFSCLK: [Reg<u32>, ..4],
  RSVD2: [u32, ..28],
  SFSUSB: Reg<u32>,
  SFSI2C0: Reg<u32>,
  SFSENAIO: [Reg<u32>, ..3],
  RSVD3: [u32, ..27],
  EMCDELAYCLK: Reg<u32>,
  RSVD4: [u32, ..63],
  PINTSEL: [Reg<u32>, ..2],
}

static PDN_ENABLE: u32 =        (1 << 3);	// Pull-down enable
static PDN_DISABLE: u32 =       (0 << 3);      // Pull-down disable
static PUP_ENABLE: u32 =        (0 << 4);      // Pull-up enable
static PUP_DISABLE: u32 =       (1 << 4);	// Pull-up disable
static SLEWRATE_SLOW: u32 =	  (0 << 5);	// Slew rate for low noise with medium speed
static SLEWRATE_FAST: u32 =	  (1 << 5);	// Slew rate for medium noise with fast speed
static INBUF_ENABLE: u32 =	  (1 << 6);	// Input buffer
static INBUF_DISABLE: u32 =	  (0 << 6);	// Input buffer
static FILTER_ENABLE: u32 =	  (0 << 7);	// Glitch filter (for signals below 30MHz)
static FILTER_DISABLE: u32 =	  (1 << 7);	// No glitch filter (for signals above 30MHz)
static DRIVE_8MA: u32 =         (1 << 8);	// Drive strength of 8mA
static DRIVE_14MA: u32 =        (1 << 9);	// Drive strength of 14mA
static DRIVE_20MA: u32 =        (3 << 8);	// Drive strength of 20mA

impl SCU {
  fn get() -> &'static SCU {
    unsafe { &*(SCU_BASE as *const SCU) }
  }

  fn pinmux(&self, (port, pin): (u8, u8), mode: u32, func: u32) {
    self.SFSP[port as uint][pin as uint].set(mode | func);
  }
}

static LED1: (u8, u8) = (11, 2);
static LED2: (u8, u8) = (7, 3);

static GPIO_PORT_BASE: u32 = 0x400F4000;

#[repr(C)]
struct GPIO {
  B: [Reg<u8>, ..256],
  RESERVED0: [u32, ..960],
  W: [Reg<u32>, ..256],
  RESERVED1: [u32, ..768],
  DIR: [Reg<u32>, ..8],
  RESERVED2: [u32, ..24],
  MASK: [Reg<u32>, ..8],
  RESERVED3: [u32, ..24],
  PIN: [Reg<u32>, ..8],
  RESERVED4: [u32, ..24],
  MPIN: [Reg<u32>, ..8],
  RESERVED5: [u32, ..24],
  SET: [Reg<u32>, ..8],
  RESERVED6: [u32, ..24],
  CLR: [Reg<u32>, ..8],
  RESERVED7: [u32, ..24],
  NOT: [Reg<u32>, ..8],
  RESERVED8: [u32, ..24],
}

impl GPIO {
  fn get() -> &'static GPIO {
    unsafe { &*(GPIO_PORT_BASE as *const GPIO) }
  }

  fn dir(&self, (port, pin): (u8, u8), output: bool) {
    if output {
      self.DIR[port as uint].set_bit(pin);
    } else {
      self.DIR[port as uint].clear_bit(pin);
    }
  }

  fn write(&self, (port, pin): (u8, u8), value: bool) {
    if value {
      self.SET[port as uint].write_bit(pin);
    } else {
      self.CLR[port as uint].write_bit(pin);
    }
  }

  fn toggle(&self, (port, pin): (u8, u8)) {
    self.NOT[port as uint].write_bit(pin);
  }
}

static LED1_GPIO: (u8, u8) = (5, 22);
static LED2_GPIO: (u8, u8) = (3, 11);

#[no_mangle]
#[no_split_stack]
pub unsafe extern "C" fn _reset_handler() {
  let systick = SysTick::get();
  let scu = SCU::get();
  systick.init(180_000_000 / 1000);

  scu.pinmux(LED1, PUP_DISABLE, 4);
  scu.pinmux(LED2, PUP_DISABLE, 0);

  let gpio = GPIO::get();
  gpio.write(LED1_GPIO, true);
  gpio.dir(LED1_GPIO, true);
  gpio.write(LED2_GPIO, false);
  gpio.dir(LED2_GPIO, true);

  asm!("CPSIE i");
  loop{}
}

static mut count: u32 = 0;

#[no_mangle]
pub unsafe extern "C" fn SysTick_Handler() {
  let gpio = GPIO::get();
  count += 1;
  if count % 100 == 0 {
    gpio.toggle(LED1_GPIO);
    gpio.toggle(LED2_GPIO);
  }
}
<|endoftext|>


<commit_before>use std::io;
use std::fs::File;
use std::io::Write;
use api_parser::*;
use std::collections::HashMap;

static HEADER: &'static [u8] = b"use rust_ffi::*;\n\n";

/*
pub struct Ui {
    pu: *const PU
}

impl Ui {
    pub fn new(pu: *const PU) -> Ui { Ui { pu: pu } }
#\n";
*/

fn generate_struct(f: &mut File, structs: &Vec<Struct>) -> io::Result<()> {
    for sdef in structs {
        f.write_fmt(format_args!("pub struct {} {{\n", sdef.name))?;

        if sdef.is_pod() {
            for entry in &sdef.entries {
                match *entry {
                    StructEntry::Var(ref var) => f.write_fmt(format_args!("    pub {}: {},\n", var.name, var.vtype))?,
                    _ => (),
                }
            }
        } else {
            // Assume for non-pod that we only use the FFI interface to do stuff.
            f.write_fmt(format_args!("    obj: const* PU{},\n", sdef.name))?;
        }

        f.write_all(b"}\n\n")?;
    }

    Ok(())
}

fn generate_func_impl(f: &mut File, func: &Function) -> io::Result<()> {
    f.write_fmt(format_args!("    pub fn {}(", func.name))?;

    func.write_func_def(f, |_, arg| {
        if arg.vtype == "String" {
            (arg.name.clone(), "&str".to_owned())
        } else if arg.vtype == "self" {
            ("&self".to_owned(), "".to_owned())
        } else if arg.primitive {
            (arg.name.to_owned(), arg.vtype.clone())
        } else {
            (arg.name.clone(), format!("&{}", arg.vtype.to_owned()))
        }
    })?;

    f.write_all(b") {\n")?;

    // Handle strings (as they need to use CString before call down to the C code

    let mut str_in_count = 0;
    let mut name_remap = HashMap::with_capacity(func.function_args.len());

    for arg in &func.function_args {
        if arg.vtype == "String" {
            f.write_fmt(format_args!("        let str_in_{} = CString::new({}).unwrap();\n", str_in_count, arg.name))?;
            name_remap.insert(arg.name.to_owned(), format!("str_in_{}.get_ptr()", str_in_count));
            str_in_count += 1;
        } else {
            name_remap.insert(arg.name.to_owned(), arg.name.to_owned());
        }
    }

    f.write_all(b"        unsafe {\n")?;
    f.write_fmt(format_args!("            ((*self.obj).{})(", func.name))?;

    let arg_count = func.function_args.len();

    func.write_func_def(f, |_, arg| {
        if !arg.primitive {
            (format!("{}", name_remap.get(&arg.name.to_owned()).unwrap()), "".to_owned())
        } else {
            (arg.name.to_owned(), "".to_owned())
        }
    })?;

    if arg_count == 0 {
        f.write_all(b"(*self.obj).priv_data));\n")?;
    } else {
        f.write_all(b", (*self.obj).priv_data));\n")?;
    }

    f.write_all(b"        }\n")?;
    f.write_all(b"    }\n\n")?;

    //

    // f.write_all(b"    }\n\n")?;

    Ok(())
}

fn generate_impl(f: &mut File, api_def: &ApiDef) -> io::Result<()> {
    for sdef in api_def.entries.iter().filter(|s| !s.is_pod()) {
        f.write_fmt(format_args!("impl {} {{\n", sdef.name))?;

        let funcs = api_def.collect_functions(&sdef);

        for func in &funcs {
            if func.callback {
            } else {
                generate_func_impl(f, func)?;
            }
        }

        f.write_all(b"}\n\n")?;
    }

    Ok(())
}

pub fn generate_rust_bindigs(filename: &str, api_def: &ApiDef) -> io::Result<()> {
    let mut f = File::create(filename)?;

    f.write_all(HEADER)?;

    generate_struct(&mut f, &api_def.entries)?;
    generate_impl(&mut f, &api_def)?;

    Ok(())
}
<commit_msg>Fixed self argument in Rust generator<commit_after>use std::io;
use std::fs::File;
use std::io::Write;
use api_parser::*;
use std::collections::HashMap;

static HEADER: &'static [u8] = b"use rust_ffi::*;\n\n";

/*
pub struct Ui {
    pu: *const PU
}

impl Ui {
    pub fn new(pu: *const PU) -> Ui { Ui { pu: pu } }
#\n";
*/

fn generate_struct(f: &mut File, structs: &Vec<Struct>) -> io::Result<()> {
    for sdef in structs {
        f.write_fmt(format_args!("pub struct {} {{\n", sdef.name))?;

        if sdef.is_pod() {
            for entry in &sdef.entries {
                match *entry {
                    StructEntry::Var(ref var) => f.write_fmt(format_args!("    pub {}: {},\n", var.name, var.vtype))?,
                    _ => (),
                }
            }
        } else {
            // Assume for non-pod that we only use the FFI interface to do stuff.
            f.write_fmt(format_args!("    obj: const* PU{},\n", sdef.name))?;
        }

        f.write_all(b"}\n\n")?;
    }

    Ok(())
}

fn generate_func_impl(f: &mut File, func: &Function) -> io::Result<()> {
    f.write_fmt(format_args!("    pub fn {}(", func.name))?;

    func.write_func_def(f, |_, arg| {
        if arg.vtype == "String" {
            (arg.name.clone(), "&str".to_owned())
        } else if arg.vtype == "self" {
            ("&self".to_owned(), "".to_owned())
        } else if arg.primitive {
            (arg.name.to_owned(), arg.vtype.clone())
        } else {
            (arg.name.clone(), format!("&{}", arg.vtype.to_owned()))
        }
    })?;

    f.write_all(b") {\n")?;

    // Handle strings (as they need to use CString before call down to the C code

    let mut str_in_count = 0;
    let mut name_remap = HashMap::with_capacity(func.function_args.len());

    for arg in &func.function_args {
        if arg.vtype == "String" {
            f.write_fmt(format_args!("        let str_in_{} = CString::new({}).unwrap();\n", str_in_count, arg.name))?;
            name_remap.insert(arg.name.to_owned(), format!("str_in_{}.get_ptr()", str_in_count));
            str_in_count += 1;
        } else {
            name_remap.insert(arg.name.to_owned(), arg.name.to_owned());
        }
    }

    f.write_all(b"        unsafe {\n")?;
    f.write_fmt(format_args!("            ((*self.obj).{})(", func.name))?;

    func.write_func_def(f, |index, arg| {
        if index == 0 {
            ("(*self.obj).privd))".to_owned(), "".to_owned())
        } else if !arg.primitive {
            (format!("{}", name_remap.get(&arg.name.to_owned()).unwrap()), "".to_owned())
        } else {
            (arg.name.to_owned(), "".to_owned())
        }
    })?;

    f.write_all(b");\n")?;

    f.write_all(b"        }\n")?;
    f.write_all(b"    }\n\n")?;

    Ok(())
}

fn generate_impl(f: &mut File, api_def: &ApiDef) -> io::Result<()> {
    for sdef in api_def.entries.iter().filter(|s| !s.is_pod()) {
        f.write_fmt(format_args!("impl {} {{\n", sdef.name))?;

        let funcs = api_def.collect_functions(&sdef);

        for func in &funcs {
            if func.callback {
            } else {
                generate_func_impl(f, func)?;
            }
        }

        f.write_all(b"}\n\n")?;
    }

    Ok(())
}

pub fn generate_rust_bindigs(filename: &str, api_def: &ApiDef) -> io::Result<()> {
    let mut f = File::create(filename)?;

    f.write_all(HEADER)?;

    generate_struct(&mut f, &api_def.entries)?;
    generate_impl(&mut f, &api_def)?;

    Ok(())
}
<|endoftext|>


<commit_before>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
extern crate webrtc_sdp;

fn main() {
    let filename = match env::args().nth(1) {
        None => {
            println!("Missing file name argument!");
            return;
        }
        Some(x) => x,
    };
    let path = Path::new(filename.as_str());
    let display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!("Failed to open {}: {}", display, why.description()),
        Ok(file) => file,
    };

    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("couldn't read {}: {}", display, why.description()),
        Ok(s) => s,
    };

    let res = webrtc_sdp::parse_sdp(&s, true);
    if res.is_ok() {
        println!("successfully parsed SDP.");
    } else {
        println!("FAILURE: {}", res.err().unwrap());
    }
}
<commit_msg>several small improvements to file_parser sample code<commit_after>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
extern crate webrtc_sdp;

fn main() {
    let filename = match env::args().nth(1) {
        None => {
            eprintln!("Missing file name argument!");
            std::process::exit(1);
        }
        Some(x) => x,
    };
    let path = Path::new(filename.as_str());
    let display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!("Failed to open {}: {}", display, why.description()),
        Ok(file) => file,
    };

    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("Couldn't read {}: {}", display, why.description()),
        Ok(s) => s,
    };

    if let Err(why) = webrtc_sdp::parse_sdp(&s, true) {
        panic!("Failed to parse SDP with error: {}", why);
    }
    println!("Successfully parsed SDP");
}
<|endoftext|>