<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

pub mod metadata;
pub mod startup;

use crate::session::{self, Session, Task};

/// Abstraction for action-specific requests.
///
/// Protocol Buffer messages received from the GRR server are not necessarily
/// easy to work with and are hardly idiomatic to Rust. For this reason, actions
/// should define more structured data types to represent their input and should
/// be able to parse raw messages into them.
pub trait Request: Sized {

    /// A type of the corresponding raw proto message.
    type Proto: prost::Message + Default;

    /// A method for converting raw proto messages into structured requests.
    fn from_proto(proto: Self::Proto) -> Result<Self, session::ParseError>;
}

/// Abstraction for action-specific responses.
///
/// Like with the [`Request`] type, Protocol Buffer messages sent to the GRR
/// server are very idiomatic to Rust. For this reason, actions should define
/// more structured data types to represent responses and provide a way to
/// convert them into the wire format.
///
/// Note that because of the design flaws in the protocol, actions also need to
/// specify a name of the wrapper RDF class from the Python implementation.
/// Hopefully, one day this issue would be fixed and class names will not leak
/// into the specification.
///
/// [`Request`]: trait.Request.html
pub trait Response: Sized {

    /// A name of the corresponding RDF class.
    const RDF_NAME: Option<&'static str>;

    /// A type of the corresponding raw proto message.
    type Proto: prost::Message + Default;

    /// A method for converting structured responses into raw proto messages.
    fn into_proto(self) -> Self::Proto;
}

impl Request for () {

    type Proto = ();

    fn from_proto(unit: ()) -> Result<(), session::ParseError> {
        Ok(unit)
    }
}

impl Response for () {

    const RDF_NAME: Option<&'static str> = None;

    type Proto = ();

    fn into_proto(self) {
    }
}

/// Dispatches `task` to a handler appropriate for the given `action`.
///
/// This method is a mapping between action names (as specified in the protocol)
/// and action handlers (implemented on the agent).
///
/// If the given action is unknown (or not yet implemented), this function will
/// return an error.
pub fn dispatch<'s, S>(action: &str, task: Task<'s, S>) -> session::Result<()>
where
    S: Session,
{
    match action {
        "SendStartupInfo" => task.execute(self::startup::handle),
        "GetClientInfo" => task.execute(self::metadata::handle),
        action => return Err(session::Error::Dispatch(String::from(action))),
    }
}
<commit_msg>Write documentation for the action module.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Handlers and types for agent's actions.
//!
//! The basic functionality that a GRR agent exposes is called an _action_.
//! Actions are invoked by the server (when running a _flow_), should gather
//! requested information and report back to the server.
//!
//! In RRG each action consists of three components: a request type, a response
//! type and an action handler. Request and response types wrap lower-level
//! Protocol Buffer messages sent by and to the GRR server. Handlers accept one
//! instance of the corresponding request type and send some (zero or more)
//! instances of the corresponding response type.

pub mod metadata;
pub mod startup;

use crate::session::{self, Session, Task};

/// Abstraction for action-specific requests.
///
/// Protocol Buffer messages received from the GRR server are not necessarily
/// easy to work with and are hardly idiomatic to Rust. For this reason, actions
/// should define more structured data types to represent their input and should
/// be able to parse raw messages into them.
pub trait Request: Sized {

    /// A type of the corresponding raw proto message.
    type Proto: prost::Message + Default;

    /// A method for converting raw proto messages into structured requests.
    fn from_proto(proto: Self::Proto) -> Result<Self, session::ParseError>;
}

/// Abstraction for action-specific responses.
///
/// Like with the [`Request`] type, Protocol Buffer messages sent to the GRR
/// server are very idiomatic to Rust. For this reason, actions should define
/// more structured data types to represent responses and provide a way to
/// convert them into the wire format.
///
/// Note that because of the design flaws in the protocol, actions also need to
/// specify a name of the wrapper RDF class from the Python implementation.
/// Hopefully, one day this issue would be fixed and class names will not leak
/// into the specification.
///
/// [`Request`]: trait.Request.html
pub trait Response: Sized {

    /// A name of the corresponding RDF class.
    const RDF_NAME: Option<&'static str>;

    /// A type of the corresponding raw proto message.
    type Proto: prost::Message + Default;

    /// A method for converting structured responses into raw proto messages.
    fn into_proto(self) -> Self::Proto;
}

impl Request for () {

    type Proto = ();

    fn from_proto(unit: ()) -> Result<(), session::ParseError> {
        Ok(unit)
    }
}

impl Response for () {

    const RDF_NAME: Option<&'static str> = None;

    type Proto = ();

    fn into_proto(self) {
    }
}

/// Dispatches `task` to a handler appropriate for the given `action`.
///
/// This method is a mapping between action names (as specified in the protocol)
/// and action handlers (implemented on the agent).
///
/// If the given action is unknown (or not yet implemented), this function will
/// return an error.
pub fn dispatch<'s, S>(action: &str, task: Task<'s, S>) -> session::Result<()>
where
    S: Session,
{
    match action {
        "SendStartupInfo" => task.execute(self::startup::handle),
        "GetClientInfo" => task.execute(self::metadata::handle),
        action => return Err(session::Error::Dispatch(String::from(action))),
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use self::rand::Rng;
use std::collections::HashMap;
use std::hash::Hash;

#[derive(Debug)]
pub struct AliasDistribution<T: Hash + Eq> {
    values: Vec<T>,
    probability_table: Vec<f64>,
    alias_table: Vec<usize>,
    pub entropy: f64,
}

impl<T: Hash + Eq> AliasDistribution<T> {
    pub fn new(weights: HashMap<T, usize>) -> AliasDistribution<T> {
        let size = weights.len();
        let total = weights.values().fold(0, |sum, x| sum + x) as f64;
        let mut entropy = 0.0;

        let mut values = Vec::with_capacity(size);
        let mut probability_table = Vec::with_capacity(size);
        for (value, weight) in weights.into_iter() {
            let prob = (weight as f64) / total;
            entropy -= prob * prob.log(2.0);
            values.push(value);
            probability_table.push(prob * (size as f64));
        };

        let mut alias_table: Vec<usize> = (0..size).collect();
        let mut overfull: Vec<usize> = Vec::with_capacity(size);
        let mut underfull: Vec<usize> = Vec::with_capacity(size);
        for (i, prob) in probability_table.iter().enumerate() {
            if *prob < 1.0 { underfull.push(i); } else { overfull.push(i); }
        };
        loop {
            if overfull.is_empty() || underfull.is_empty() { break }
            let i = underfull.pop().unwrap();
            let j = overfull.pop().unwrap();
            alias_table[i] = j;
            probability_table[j] += probability_table[i] - 1.0;
            if probability_table[j] < 1.0 { underfull.push(j) } else { overfull.push(j) };
        };
        for i in underfull.iter().chain(overfull.iter()) {
            alias_table[*i] = 1;
        };

        AliasDistribution {
            values: values,
            probability_table: probability_table,
            alias_table: alias_table,
            entropy: entropy,
        }
    }

    pub fn choice(&self) -> Option<&T> {
        if self.values.len() == 0 { return None; };
        let mut rng = rand::OsRng::new().unwrap();
        let i = rng.gen_range(0, self.values.len());
        let y = rng.gen();
        let choice = if self.probability_table[i] >= y { i } else { self.alias_table[i] };

        Some(&self.values[choice])
    }
}
<commit_msg>Remove unecessary padding of alias_table<commit_after>extern crate rand;

use self::rand::Rng;
use std::collections::HashMap;
use std::hash::Hash;

#[derive(Debug)]
pub struct AliasDistribution<T: Hash + Eq> {
    values: Vec<T>,
    probability_table: Vec<f64>,
    alias_table: Vec<usize>,
    pub entropy: f64,
}

impl<T: Hash + Eq> AliasDistribution<T> {
    pub fn new(weights: HashMap<T, usize>) -> AliasDistribution<T> {
        let size = weights.len();
        let total = weights.values().fold(0, |sum, x| sum + x) as f64;
        let mut entropy = 0.0;

        let mut values = Vec::with_capacity(size);
        let mut probability_table = Vec::with_capacity(size);
        for (value, weight) in weights.into_iter() {
            let prob = (weight as f64) / total;
            entropy -= prob * prob.log(2.0);
            values.push(value);
            probability_table.push(prob * (size as f64));
        };

        let mut alias_table: Vec<usize> = (0..size).collect();
        let mut overfull: Vec<usize> = Vec::with_capacity(size);
        let mut underfull: Vec<usize> = Vec::with_capacity(size);
        for (i, prob) in probability_table.iter().enumerate() {
            if *prob < 1.0 { underfull.push(i); } else { overfull.push(i); }
        };
        loop {
            if overfull.is_empty() || underfull.is_empty() { break; };
            let i = underfull.pop().unwrap();
            let j = overfull.pop().unwrap();
            alias_table[i] = j;
            probability_table[j] += probability_table[i] - 1.0;
            if probability_table[j] < 1.0 { underfull.push(j) } else { overfull.push(j) };
        };

        AliasDistribution {
            values: values,
            probability_table: probability_table,
            alias_table: alias_table,
            entropy: entropy,
        }
    }

    pub fn choice(&self) -> Option<&T> {
        if self.values.len() == 0 { return None; };
        let mut rng = rand::OsRng::new().unwrap();
        let i = rng.gen_range(0, self.values.len());
        let y = rng.gen();
        let choice = if self.probability_table[i] >= y { i } else { self.alias_table[i] };

        Some(&self.values[choice])
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::filespec::SBFileSpec;
use super::stream::SBStream;
use super::typelist::SBTypeList;
use super::{LanguageType, TypeClass};
use std::fmt;
use sys;

/// A compilation unit or compiled source file.
pub struct SBCompileUnit {
    /// The underlying raw `SBCompileUnitRef`.
    pub raw: sys::SBCompileUnitRef,
}

impl SBCompileUnit {
    /// Construct a new `SBCompileUnit`.
    pub fn wrap(raw: sys::SBCompileUnitRef) -> SBCompileUnit {
        SBCompileUnit { raw }
    }

    /// Construct a new `Some(SBCompileUnit)` or `None`.
    pub fn maybe_wrap(raw: sys::SBCompileUnitRef) -> Option<SBCompileUnit> {
        if unsafe { sys::SBCompileUnitIsValid(raw) } {
            Some(SBCompileUnit { raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBCompileUnit` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBCompileUnitIsValid(self.raw) }
    }

    /// The source file for the compile unit.
    pub fn filespec(&self) -> SBFileSpec {
        SBFileSpec::from(unsafe { sys::SBCompileUnitGetFileSpec(self.raw) })
    }

    /// Get all types matching `type_mask` from the debug info in this
    /// compile unit.
    ///
    /// `type_mask` is a bitfield consisting of one or more type classes.
    /// This allows you to request only structure types, or only class,
    /// structure, and union types. Passing in [`TypeClass::ANY`] will
    /// return all types found in the debug information for this compile
    /// unit.
    pub fn types(&self, type_mask: TypeClass) -> SBTypeList {
        SBTypeList::from(unsafe { sys::SBCompileUnitGetTypes(self.raw, type_mask.bits()) })
    }

    /// The language for the compile unit.
    pub fn language(&self) -> LanguageType {
        unsafe { sys::SBCompileUnitGetLanguage(self.raw) }
    }
}

impl Clone for SBCompileUnit {
    fn clone(&self) -> SBCompileUnit {
        SBCompileUnit {
            raw: unsafe { sys::CloneSBCompileUnit(self.raw) },
        }
    }
}

impl fmt::Debug for SBCompileUnit {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBCompileUnitGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBCompileUnit {{ {} }}", stream.data())
    }
}

impl Drop for SBCompileUnit {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBCompileUnit(self.raw) };
    }
}

impl From<sys::SBCompileUnitRef> for SBCompileUnit {
    fn from(raw: sys::SBCompileUnitRef) -> SBCompileUnit {
        SBCompileUnit { raw }
    }
}

unsafe impl Send for SBCompileUnit {}
unsafe impl Sync for SBCompileUnit {}

#[cfg(feature = "graphql")]
graphql_object!(SBCompileUnit: super::debugger::SBDebugger | &self | {
    field is_valid() -> bool {
        self.is_valid()
    }

    field filespec() -> SBFileSpec {
        self.filespec()
    }
});
<commit_msg>Add `SBCompileUnit::line_entries()`.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::filespec::SBFileSpec;
use super::lineentry::SBLineEntry;
use super::stream::SBStream;
use super::typelist::SBTypeList;
use super::{LanguageType, TypeClass};
use std::fmt;
use sys;

/// A compilation unit or compiled source file.
pub struct SBCompileUnit {
    /// The underlying raw `SBCompileUnitRef`.
    pub raw: sys::SBCompileUnitRef,
}

impl SBCompileUnit {
    /// Construct a new `SBCompileUnit`.
    pub fn wrap(raw: sys::SBCompileUnitRef) -> SBCompileUnit {
        SBCompileUnit { raw }
    }

    /// Construct a new `Some(SBCompileUnit)` or `None`.
    pub fn maybe_wrap(raw: sys::SBCompileUnitRef) -> Option<SBCompileUnit> {
        if unsafe { sys::SBCompileUnitIsValid(raw) } {
            Some(SBCompileUnit { raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBCompileUnit` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBCompileUnitIsValid(self.raw) }
    }

    /// The source file for the compile unit.
    pub fn filespec(&self) -> SBFileSpec {
        SBFileSpec::from(unsafe { sys::SBCompileUnitGetFileSpec(self.raw) })
    }

    /// The [line entries][SBLineEntry] for the compilation unit.
    ///
    /// These come from the line table in the debug data.
    pub fn line_entries(&self) -> SBCompileUnitLineEntryIter {
        SBCompileUnitLineEntryIter {
            source: self,
            idx: 0,
        }
    }

    /// Get all types matching `type_mask` from the debug info in this
    /// compile unit.
    ///
    /// `type_mask` is a bitfield consisting of one or more type classes.
    /// This allows you to request only structure types, or only class,
    /// structure, and union types. Passing in [`TypeClass::ANY`] will
    /// return all types found in the debug information for this compile
    /// unit.
    pub fn types(&self, type_mask: TypeClass) -> SBTypeList {
        SBTypeList::from(unsafe { sys::SBCompileUnitGetTypes(self.raw, type_mask.bits()) })
    }

    /// The language for the compile unit.
    pub fn language(&self) -> LanguageType {
        unsafe { sys::SBCompileUnitGetLanguage(self.raw) }
    }
}

impl Clone for SBCompileUnit {
    fn clone(&self) -> SBCompileUnit {
        SBCompileUnit {
            raw: unsafe { sys::CloneSBCompileUnit(self.raw) },
        }
    }
}

impl fmt::Debug for SBCompileUnit {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBCompileUnitGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBCompileUnit {{ {} }}", stream.data())
    }
}

impl Drop for SBCompileUnit {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBCompileUnit(self.raw) };
    }
}

impl From<sys::SBCompileUnitRef> for SBCompileUnit {
    fn from(raw: sys::SBCompileUnitRef) -> SBCompileUnit {
        SBCompileUnit { raw }
    }
}

unsafe impl Send for SBCompileUnit {}
unsafe impl Sync for SBCompileUnit {}

/// Iterate over the [line entries] in a [compile unit].
///
/// [line entries]: struct.SBLineEntry.html
/// [compile unit]: struct.SBCompileUnit.html
pub struct SBCompileUnitLineEntryIter<'d> {
    source: &'d SBCompileUnit,
    idx: u32,
}

impl<'d> Iterator for SBCompileUnitLineEntryIter<'d> {
    type Item = SBLineEntry;

    fn next(&mut self) -> Option<SBLineEntry> {
        if self.idx < unsafe { sys::SBCompileUnitGetNumLineEntries(self.source.raw) } {
            let r = Some(SBLineEntry::from(unsafe {
                sys::SBCompileUnitGetLineEntryAtIndex(self.source.raw, self.idx)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBCompileUnitGetNumLineEntries(self.source.raw) } as usize;
        (sz - self.idx as usize, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBCompileUnitLineEntryIter<'d> {}

#[cfg(feature = "graphql")]
graphql_object!(SBCompileUnit: super::debugger::SBDebugger | &self | {
    field is_valid() -> bool {
        self.is_valid()
    }

    field filespec() -> SBFileSpec {
        self.filespec()
    }
});
<|endoftext|>


<commit_before>#[macro_export]
#[doc(hidden)]
macro_rules! dbg_println {
    ($($arg:tt)*) => {{
        use crate::core::DBG_PRINTLN_FLAG;
        use std::sync::atomic::Ordering;

        if DBG_PRINTLN_FLAG.load(Ordering::Relaxed) != 0 {
            eprintln!($($arg)*)
        }
    }};
}

#[macro_export]
#[doc(hidden)]
macro_rules! dbg_print {
    ($($arg:tt)*) => {{
        use crate::core::DBG_PRINTLN_FLAG;
        use std::sync::atomic::Ordering;

        if DBG_PRINTLN_FLAG.load(Ordering::Relaxed) != 0 {
            eprint!($($arg)*)
        }
    }};
}
<commit_msg>better dbg_print/dbg_println macors<commit_after>#[macro_export]
#[doc(hidden)]
macro_rules! dbg_println {
    ($($arg:tt)*) => {{
        use crate::core::DBG_PRINTLN_FLAG;
        use std::sync::atomic::Ordering;

        if DBG_PRINTLN_FLAG.load(Ordering::Relaxed) != 0 {
            eprint!("{}:{} ", file!(), line!());
            eprintln!($($arg)*)
        }
    }};
}

#[macro_export]
#[doc(hidden)]
macro_rules! dbg_print {
    ($($arg:tt)*) => {{
        use crate::core::DBG_PRINTLN_FLAG;
        use std::sync::atomic::Ordering;

        if DBG_PRINTLN_FLAG.load(Ordering::Relaxed) != 0 {
            eprint!("{}:{} ", file!(), line!());
            eprint!($($arg)*)
        }
    }};
}
<|endoftext|>


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

use command::*;
use datatypes::{EchoSettings, Key};
use datatypes::Key::*;
use datatypes::Area::*;
use datatypes::Movement::*;
use datatypes::Direction::*;

pub struct LineEcho {
    pub settings: EchoSettings,
    position: u32,
    len: u32,
}

impl LineEcho {
    pub fn new(settings: EchoSettings) -> LineEcho {
        LineEcho {
            settings: settings,
            position: 0,
            len: 0,
        }
    }

    pub fn echo(&mut self, key: Key) -> Option<Box<Command>> {
        match key {
            Char(c) if c == self.settings.lerase as char  => {
                self.len = 0;
                wrap(CommandSeries(vec![
                    Box::new(Move::new(To(Left, self.position, true))) as Box<Command>,
                    Box::new(Erase::new(CursorTo(To(Right, self.len, true)))) as Box<Command>,
                ]))
            }
            Char(c) if c == self.settings.lnext as char   => unimplemented!(),
            Char(c) if c == self.settings.werase as char  => unimplemented!(),
            Char(c) if c.width().is_some() => {
                self.len += 1;
                wrap(Put::new_char(c))
            }
            LeftArrow if self.position != 0 => {
                self.position -= 1;
                wrap(Move::new(To(Left, 1, false)))
            }
            RightArrow if self.position != self.len => {
                self.position += 1;
                wrap(Move::new(To(Right, 1, false)))
            }
            Enter       => wrap(Move::new(NextLine(1))),
            Backspace if self.position != 0 => {
                self.len -= 1;
                wrap(CommandSeries(vec![
                    Box::new(Move::new(To(Left, 1, false))) as Box<Command>,
                    Box::new(RemoveChars::new(1)) as Box<Command>,
                ]))
            }
            Delete if self.position != self.len => {
                self.len -= 1;
                wrap(RemoveChars::new(1))
            }
            Home        => {
                self.position = 0;
                wrap(Move::new(To(Left, self.position, true)))
            }
            _           => None
        }
    }
}

fn wrap<T: Command>(cmd: T) -> Option<Box<Command>> {
    Some(Box::new(cmd) as Box<Command>)
}
<commit_msg>Tests and bug fixes for line buffer.<commit_after>//  notty is a new kind of terminal emulator.
//  Copyright (C) 2015 without boats
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
use unicode_width::*;

use command::*;
use datatypes::{EchoSettings, Key};
use datatypes::Key::*;
use datatypes::Area::*;
use datatypes::Movement::*;
use datatypes::Direction::*;

pub struct LineEcho {
    pub settings: EchoSettings,
    position: u32,
    len: u32,
}

impl LineEcho {
    pub fn new(settings: EchoSettings) -> LineEcho {
        LineEcho {
            settings: settings,
            position: 0,
            len: 0,
        }
    }

    pub fn echo(&mut self, key: Key) -> Option<Box<Command>> {
        match key {
            Char(c) if c == self.settings.lerase as char  => {
                self.len = 0;
                wrap(CommandSeries(vec![
                    Box::new(Move::new(To(Left, self.position, true))) as Box<Command>,
                    Box::new(Erase::new(CursorTo(To(Right, self.len, true)))) as Box<Command>,
                ]))
            }
            Char(c) if c == self.settings.lnext as char   => unimplemented!(),
            Char(c) if c == self.settings.werase as char  => unimplemented!(),
            Char(c) if c.width().is_some() => {
                self.position += 1;
                self.len += 1;
                wrap(Put::new_char(c))
            }
            LeftArrow if self.position != 0 => {
                self.position -= 1;
                wrap(Move::new(To(Left, 1, true)))
            }
            RightArrow if self.position != self.len => {
                self.position += 1;
                wrap(Move::new(To(Right, 1, true)))
            }
            Enter       => {
                self.position = 0;
                self.len = 0;
                wrap(Move::new(NextLine(1)))
            }
            Backspace if self.position != 0 => {
                self.position -= 1;
                self.len -= 1;
                wrap(CommandSeries(vec![
                    Box::new(Move::new(To(Left, 1, false))) as Box<Command>,
                    Box::new(RemoveChars::new(1)) as Box<Command>,
                ]))
            }
            Delete if self.position != self.len => {
                self.len -= 1;
                wrap(RemoveChars::new(1))
            }
            Home if self.position != 0 => {
                self.position = 0;
                wrap(Move::new(To(Left, self.position, true)))
            }
            End if self.position != self.len => {
                let n = self.len - self.position;
                self.position = self.len;
                wrap(Move::new(To(Right, n, true)))
            }
            _           => None
        }
    }
}

fn wrap<T: Command>(cmd: T) -> Option<Box<Command>> {
    Some(Box::new(cmd) as Box<Command>)
}

#[cfg(test)]
mod tests {

    use command::*;
    use datatypes::EchoSettings;
    use datatypes::Key::*;
    use datatypes::Area::*;
    use datatypes::Movement::*;
    use datatypes::Direction::*;

    use super::*;

    static SETTINGS: EchoSettings = EchoSettings { lerase: 0, lnext: 1, werase: 2 };

    #[test]
    fn chars() {
        let mut echo = LineEcho::new(SETTINGS);
        assert_eq!(echo.echo(Char('A')).unwrap().repr(), Put::new_char('A').repr());
        assert_eq!(echo.len, 1);
        assert_eq!(echo.position, 1);
        assert!(echo.echo(Char('\x1b')).is_none());
        assert_eq!(echo.len, 1);
        assert_eq!(echo.position, 1);
    }

    #[test]
    fn left_arrow() {
        let mut echo = LineEcho { settings: SETTINGS, position: 0, len: 0 };
        assert!(echo.echo(LeftArrow).is_none());
        assert_eq!(echo.len, 0);
        assert_eq!(echo.position, 0);
        let mut echo = LineEcho { settings: SETTINGS, position: 1, len: 1 };
        assert_eq!(echo.echo(LeftArrow).unwrap().repr(), Move::new(To(Left, 1, true)).repr());
        assert_eq!(echo.len, 1);
        assert_eq!(echo.position, 0);
    }

    #[test]
    fn right_arrow() {
        let mut echo = LineEcho { settings: SETTINGS, position: 0, len: 0 };
        assert!(echo.echo(RightArrow).is_none());
        assert_eq!(echo.len, 0);
        assert_eq!(echo.position, 0);
        let mut echo = LineEcho { settings: SETTINGS, position: 0, len: 1 };
        assert_eq!(echo.echo(RightArrow).unwrap().repr(), Move::new(To(Right, 1, true)).repr());
        assert_eq!(echo.len, 1);
        assert_eq!(echo.position, 1);
    }

    #[test]
    fn enter() {
        let mut echo = LineEcho { settings: SETTINGS, position: 3, len: 3 };
        assert_eq!(echo.echo(Enter).unwrap().repr(), Move::new(NextLine(1)).repr());
        assert_eq!(echo.len, 0);
        assert_eq!(echo.position, 0);
    }

    #[test]
    fn backspace() {
        let mut echo = LineEcho { settings: SETTINGS, position: 0, len: 1 };
        assert!(echo.echo(Backspace).is_none());
        assert_eq!(echo.position, 0);
        assert_eq!(echo.len, 1);
        let mut echo = LineEcho { settings: SETTINGS, position: 1, len: 1 };
        assert!(echo.echo(Backspace).is_some());
        assert_eq!(echo.position, 0);
        assert_eq!(echo.len, 0);
    }

    #[test]
    fn delete() {
        let mut echo = LineEcho { settings: SETTINGS, position: 0, len: 1 };
        assert!(echo.echo(Delete).is_some());
        assert_eq!(echo.position, 0);
        assert_eq!(echo.len, 0);
        let mut echo = LineEcho { settings: SETTINGS, position: 1, len: 1 };
        assert!(echo.echo(Delete).is_none());
        assert_eq!(echo.position, 1);
        assert_eq!(echo.len, 1);
    }

    #[test]
    fn home() {
        let mut echo = LineEcho { settings: SETTINGS, position: 4, len: 5 };
        assert!(echo.echo(Home).is_some());
        assert_eq!(echo.position, 0);
        assert_eq!(echo.len, 5);
    }

    #[test]
    fn end() {
        let mut echo = LineEcho { settings: SETTINGS, position: 4, len: 5 };
        assert!(echo.echo(End).is_some());
        assert_eq!(echo.position, 5);
        assert_eq!(echo.len, 5);
    }

}
<|endoftext|>


<commit_before>extern crate chifir;
extern crate termion;

use termion::raw::IntoRawMode;
use termion::async_stdin;

use std::io::{self, Write};

fn main() {
    let stdout = io::stdout();
    let mut stdout = stdout.lock().into_raw_mode().unwrap();
    let mut stdin = async_stdin();

    write!(stdout,
           "{}{}",
           termion::clear::All,
           termion::cursor::Goto(1, 1))
        .unwrap();
    stdout.flush().unwrap();

    let mut compiler = chifir::compiler::Compiler::new();
    compiler.parse("
    f 2 0 3  ; 00 - Read key press and store it in $2
    8 2 2 3  ; 04 - $2 <- $2 - $3
    2 b 2 f  ; 08 - If $2 = 0, then PC <- 15
    1 f 0 0  ; 12 - Else PC <- 0
    ");

    let mut vm = chifir::computer::Computer::new();
    vm.input(&mut stdin);
    vm.output(&mut stdout);
    vm.load(compiler.bytecodes);

    while vm.next() != 0 {
        vm.step();
    }
}
<commit_msg>Displays 'A' when the 'a' key is pressed.<commit_after>extern crate chifir;
extern crate termion;

use termion::raw::IntoRawMode;
use termion::async_stdin;

use std::io::{self, Write};

fn main() {
    let stdout = io::stdout();
    let mut stdout = stdout.lock().into_raw_mode().unwrap();

    let mut compiler = chifir::compiler::Compiler::new();
    compiler.parse("
    ; Configure a 16x16 pixel display
    cfv display 10 10

    check-key:
      drw
      key x

      ; Exit if Ctrl+C is pressed
      sub y x ctrl-c
      beq /3 y exit

      ; Print 'A' if 'a' is pressed
      sub y x letter-a
      beq /3 y render-a

      ; Clear the display if anything else was pressed
      lpc /2 clear-display

    exit:
      brk

    ; Registers
    x:
      nop
    y:
      nop
    z:
      nop
    zz:
      nop
    k:
      nop
    kk:
      nop

    ; Constants
    ctrl-c:
      3
    letter-a:
      61
    one:
      1

    clear-display:
      lea k /3 100
      lea kk /3 display

    clear-display-loop:
      add x k kk
      sra /3 x 0
      beq /3 k check-key
      sub k k one
      lpc /2 clear-display-loop

    render-a:
      lea k /3 100
      lea kk /3 display
      lea zz /3 font-a

    render-a-loop:
      add x k kk
      add y k zz
      lra z y
      sra z x
      beq /3 k check-key
      sub k k one
      lpc /2 render-a-loop

    font-a:
      0 0 0 0
      0 1 1 1
      1 1 1 0
      0 0 0 0
      0 0 0 0
      0 1 1 1
      1 1 1 0
      0 0 0 0
      0 0 0 0
      0 1 1 1
      1 1 1 0
      0 0 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0
      0 0 1 1
      1 1 1 1
      1 1 1 1
      1 1 0 0
      0 0 1 1
      1 1 1 1
      1 1 1 1
      1 1 0 0
      0 0 1 1
      1 1 1 1
      1 1 1 1
      1 1 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0
      0 0 1 1
      1 0 0 0
      0 0 0 1
      1 1 0 0

    display:
      brk
    ");

    let mut stdin = async_stdin();

    write!(stdout,
           "{}{}",
           termion::clear::All,
           termion::cursor::Goto(1, 1))
        .unwrap();
    stdout.flush().unwrap();

    let mut vm = chifir::computer::Computer::new();
    vm.input(&mut stdin);
    vm.output(&mut stdout);
    vm.load(compiler.bytecodes);

    while vm.next() != 0 {
        vm.step();
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate opengl_graphics;
extern crate rand;
extern crate rpsrtsrs;
#[cfg(feature = "include_sdl2")] extern crate sdl2_window;
#[cfg(feature = "include_glfw")] extern crate glfw_window;
#[cfg(feature = "include_glutin")] extern crate glutin_window;

use piston::window::WindowSettings;
use opengl_graphics::{ GlGraphics, OpenGL };
use piston::input::*;
use piston::event_loop::*;
#[cfg(feature = "include_sdl2")] use sdl2_window::Sdl2Window as Window;
#[cfg(feature = "include_glfw")] use glfw_window::GlfwWindow as Window;
#[cfg(feature = "include_glutin")] use glutin_window::GlutinWindow as Window;
use rpsrtsrs::shapes::Unit;

pub struct App {
    gl: GlGraphics, // OpenGL drawing backend.
    units: Vec<Unit>,
}

impl App {
    fn select(&mut self, position: &[f64;2]) {
        for s in &mut self.units {
            s.selected = position[0]< s.position[0]+25.0 &&
                position[0]> s.position[0]-25.0 &&
                position[1]< s.position[1]+25.0 &&
                position[1]> s.position[1]-25.0;
        };
    }

    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const BLACK: [f32; 4] = [0.0, 0.0,  0.0, 1.0];
        const YELLOW:[f32; 4] = [1.0, 1.0,  0.22, 1.0];
        const ORANGE:[f32; 4] = [1.0, 0.61, 0.22, 1.0];

        let units = &self.units;

        self.gl.draw(args.viewport(), |c, gl| {
            // Clear the screen.
            clear(BLACK, gl);
            for s in units.iter() {
                let square = rectangle::square(0.0, 0.0, 50.0);
                let transform = c.transform.trans(s.position[0], s.position[1])
                    .rot_rad(s.rotation)
                    .trans(-25.0, -25.0);

                // Draw the box RED if selected
                if s.selected {
                    rectangle(ORANGE, square, transform, gl);
                } else {
                    rectangle(YELLOW, square, transform, gl);
                }
            }
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        for s in &mut self.units {
            let diff = [s.target[0]-s.position[0], s.target[1]-s.position[1]];
            s.position[0] += diff[0]/2.0*args.dt;
            s.position[1] += diff[1]/2.0*args.dt;
        }
    }

    fn move_selected(&mut self, position: [f64;2]) {
        for s in &mut self.units {
            if s.selected {
                s.target = position;
                let d0 = position[0]-s.position[0];
                let d1 = position[1]-s.position[1];
                s.rotation = (d1/d0).atan();
            }
        }
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    // Create an Glutin window.
    let window : Window = WindowSettings::new(
        "rpsrtsrs",
        [640, 480]
    ).exit_on_esc(true).into();

    // Create a new game and run it.
    let mut app = App {
        gl: GlGraphics::new(opengl),
        units: vec![],
    };
    for _ in 0..10 {
        let x = rand::random::<f64>() * 600.0 + 40.0;
        let y = rand::random::<f64>() * 440.0 + 40.0;
        app.units.push(Unit::new([x,y]));
    }

    let mut cursor = [0.0,0.0];

    for e in window.events() {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }
        if let Some(Button::Mouse(button)) = e.press_args() {
            match button {
                MouseButton::Left  => app.select(&cursor),
                MouseButton::Right => app.move_selected(cursor),
                _ => println!("Pressed mouse button '{:?}'", button),
            }
        }
        e.mouse_cursor(|x, y| {
            cursor = [x, y];
        });

        if let Some(u) = e.update_args() {
            app.update(&u);
        }
    }
}
<commit_msg>Draw triangles instead of squares<commit_after>extern crate piston;
extern crate graphics;
extern crate opengl_graphics;
extern crate rand;
extern crate rpsrtsrs;
#[cfg(feature = "include_sdl2")] extern crate sdl2_window;
#[cfg(feature = "include_glfw")] extern crate glfw_window;
#[cfg(feature = "include_glutin")] extern crate glutin_window;

use piston::window::WindowSettings;
use opengl_graphics::{ GlGraphics, OpenGL };
use piston::input::*;
use piston::event_loop::*;
#[cfg(feature = "include_sdl2")] use sdl2_window::Sdl2Window as Window;
#[cfg(feature = "include_glfw")] use glfw_window::GlfwWindow as Window;
#[cfg(feature = "include_glutin")] use glutin_window::GlutinWindow as Window;
use rpsrtsrs::shapes::Unit;

pub struct App {
    gl: GlGraphics, // OpenGL drawing backend.
    units: Vec<Unit>,
}

impl App {
    fn select(&mut self, position: &[f64;2]) {
        for s in &mut self.units {
            s.selected = position[0]< s.position[0]+25.0 &&
                position[0]> s.position[0]-25.0 &&
                position[1]< s.position[1]+25.0 &&
                position[1]> s.position[1]-25.0;
        };
    }

    fn render(&mut self, args: &RenderArgs) {
        use graphics::{polygon, clear, Transformed};
        use graphics::types::Polygon;

        const BLACK:  [f32; 4] = [0.0, 0.0,  0.0, 1.0];
        const YELLOW: [f32; 4] = [1.0, 1.0,  0.22, 1.0];
        const ORANGE: [f32; 4] = [1.0, 0.61, 0.22, 1.0];

        const UNIT_SIZE: f64 = 50.0;

        let units = &self.units;

        self.gl.draw(args.viewport(), |c, gl| {

            // Clear the screen.
            clear(BLACK, gl);

            for s in units.iter() {

                // Create a triangle polygon. The initial orientation is facing east.
                let triangle: Polygon = &[
                    [0.0, UNIT_SIZE / 2.0], // Left
                    [UNIT_SIZE, UNIT_SIZE], // Top right
                    [UNIT_SIZE, 0.0],       // Bottom right
                ];

                // Create the transoformation matrix
                let transform = c.transform.trans(s.position[0], s.position[1])
                    .rot_rad(s.rotation)
                    .trans(-25.0, -25.0);

                // Draw the unit ORANGE if selected
                if s.selected {
                    polygon(ORANGE, triangle, transform, gl);
                } else {
                    polygon(YELLOW, triangle, transform, gl);
                }

            }
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        for s in &mut self.units {
            let diff = [s.target[0]-s.position[0], s.target[1]-s.position[1]];
            s.position[0] += diff[0]/2.0*args.dt;
            s.position[1] += diff[1]/2.0*args.dt;
        }
    }

    fn move_selected(&mut self, position: [f64;2]) {
        for s in &mut self.units {
            if s.selected {
                s.target = position;
                let d0 = position[0]-s.position[0];
                let d1 = position[1]-s.position[1];
                s.rotation = (d1/d0).atan();
            }
        }
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    // Create an Glutin window.
    let window : Window = WindowSettings::new(
        "rpsrtsrs",
        [640, 480]
    ).exit_on_esc(true).into();

    // Create a new game and run it.
    let mut app = App {
        gl: GlGraphics::new(opengl),
        units: vec![],
    };
    for _ in 0..10 {
        let x = rand::random::<f64>() * 600.0 + 40.0;
        let y = rand::random::<f64>() * 440.0 + 40.0;
        app.units.push(Unit::new([x,y]));
    }

    let mut cursor = [0.0,0.0];

    for e in window.events() {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }
        if let Some(Button::Mouse(button)) = e.press_args() {
            match button {
                MouseButton::Left  => app.select(&cursor),
                MouseButton::Right => app.move_selected(cursor),
                _ => println!("Pressed mouse button '{:?}'", button),
            }
        }
        e.mouse_cursor(|x, y| {
            cursor = [x, y];
        });

        if let Some(u) = e.update_args() {
            app.update(&u);
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    collections::{hash_map, BTreeMap},
    fmt, mem,
    sync::Arc,
};

use gluon::{
    self,
    base::{
        ast::{Expr, SpannedExpr},
        filename_to_module, pos,
        symbol::Symbol,
    },
    import::Import,
    query::{Compilation, CompilationBase},
    Error as GluonError, Result as GluonResult, RootedThread, Thread, ThreadExt,
};

use futures::{
    future::{self, Either},
    prelude::*,
    stream,
    sync::mpsc,
};

use tokio;

use codespan;
use codespan_lsp;

use url::Url;

use jsonrpc_core::IoHandler;

use languageserver_types::*;

use crate::{
    cancelable,
    check_importer::{CheckImporter, Module},
    name::{
        codespan_name_to_file, module_name_to_file, strip_file_prefix,
        strip_file_prefix_with_thread,
    },
    rpc::{self, send_response, Entry, ServerError},
    server::{Handler, ShutdownReceiver},
    text_edit::TextChanges,
    BoxFuture,
};

fn create_diagnostics(
    diagnostics: &mut BTreeMap<Url, Vec<Diagnostic>>,
    code_map: &codespan::CodeMap,
    importer: &CheckImporter,
    filename: &Url,
    err: GluonError,
) -> Result<(), ServerError<()>> {
    use gluon::base::error::AsDiagnostic;
    fn into_diagnostic<T>(
        code_map: &codespan::CodeMap,
        err: pos::Spanned<T, pos::BytePos>,
    ) -> Result<Diagnostic, ServerError<()>>
    where
        T: fmt::Display + AsDiagnostic,
    {
        Ok(Diagnostic {
            source: Some("gluon".to_string()),
            ..codespan_lsp::make_lsp_diagnostic(code_map, err.as_diagnostic(), |filename| {
                codespan_name_to_file(filename).map_err(|err| {
                    error!("{}", err);
                })
            })?
        })
    }

    fn insert_in_file_error<T>(
        diagnostics: &mut BTreeMap<Url, Vec<Diagnostic>>,
        code_map: &codespan::CodeMap,
        importer: &CheckImporter,
        in_file_error: gluon::base::error::InFile<T>,
    ) -> Result<(), ServerError<()>>
    where
        T: fmt::Display + AsDiagnostic,
    {
        diagnostics
            .entry(module_name_to_file(importer, &in_file_error.source_name()))
            .or_insert(Vec::new())
            .extend(
                in_file_error
                    .errors()
                    .into_iter()
                    .map(|err| into_diagnostic(code_map, err))
                    .collect::<Result<Vec<_>, _>>()?,
            );
        Ok(())
    }

    match err {
        GluonError::Typecheck(err) => insert_in_file_error(diagnostics, code_map, importer, err)?,

        GluonError::Parse(err) => insert_in_file_error(diagnostics, code_map, importer, err)?,

        GluonError::Macro(err) => insert_in_file_error(diagnostics, code_map, importer, err)?,

        GluonError::Multiple(errors) => {
            for err in errors {
                create_diagnostics(diagnostics, code_map, importer, filename, err)?;
            }
        }

        err => diagnostics
            .entry(filename.clone())
            .or_insert(Vec::new())
            .push(Diagnostic {
                message: format!("{}", err),
                severity: Some(DiagnosticSeverity::Error),
                source: Some("gluon".to_string()),
                ..Diagnostic::default()
            }),
    }
    Ok(())
}

struct DiagnosticsWorker {
    thread: RootedThread,
    message_log: mpsc::Sender<String>,
}

impl DiagnosticsWorker {
    pub fn new(thread: RootedThread, message_log: mpsc::Sender<String>) -> Self {
        DiagnosticsWorker {
            thread,
            message_log,
        }
    }

    pub fn run_diagnostics(
        &mut self,
        uri_filename: &Url,
        version: Option<u64>,
        fileinput: &str,
    ) -> BoxFuture<(), ()> {
        info!("Running diagnostics on {}", uri_filename);

        let filename = strip_file_prefix_with_thread(&self.thread, uri_filename);
        let name = filename_to_module(&filename);

        self.thread.get_database().update_filemap(&name, fileinput);

        let diagnostics = match self.typecheck(uri_filename, &name, version, fileinput) {
            Ok(_) => Some((uri_filename.clone(), vec![])).into_iter().collect(),
            Err(err) => {
                debug!("Diagnostics result on `{}`: {}", uri_filename, err);
                let mut diagnostics = BTreeMap::new();

                let import = self
                    .thread
                    .get_macros()
                    .get("import")
                    .expect("Import macro");
                let import = import
                    .downcast_ref::<Import<CheckImporter>>()
                    .expect("Check importer");

                let result = create_diagnostics(
                    &mut diagnostics,
                    &self.thread.get_database().code_map(),
                    &import.importer,
                    uri_filename,
                    err,
                );
                if let Err(err) = result {
                    error!("Unable to create diagnostics: {}", err.message);
                    return Box::new(Err(()).into_future());
                }
                diagnostics
            }
        };

        let message_log = self.message_log.clone();
        Box::new(
            stream::futures_ordered(diagnostics.into_iter().map(|(source_name, diagnostic)| {
                send_response(
                    message_log.clone(),
                    notification!("textDocument/publishDiagnostics"),
                    PublishDiagnosticsParams {
                        uri: source_name,
                        diagnostics: diagnostic,
                    },
                )
            }))
            .for_each(|_| Ok(())),
        )
    }

    fn typecheck(
        &mut self,
        uri_filename: &Url,
        name: &str,
        version: Option<u64>,
        fileinput: &str,
    ) -> GluonResult<()> {
        let (expr_opt, error) = self.typecheck_(&name, fileinput);

        let import = self
            .thread
            .get_macros()
            .get("import")
            .expect("Import macro");
        let import = import
            .downcast_ref::<Import<CheckImporter>>()
            .expect("Check importer");
        let mut importer = import.importer.0.lock().unwrap();

        match importer.entry(name.into()) {
            hash_map::Entry::Occupied(mut entry) => {
                let module = entry.get_mut();

                if let Some(expr) = expr_opt {
                    module.expr = expr;
                }
                module.uri = uri_filename.clone();

                if version.is_some() {
                    module.version = version;
                }

                module.source = self
                    .thread
                    .get_database()
                    .get_filemap(&name)
                    .unwrap_or_else(|| panic!("FileMap for diagnostics is missing: {}", name))
                    .clone();

                module.dirty = false;

                let waiters = mem::replace(&mut module.waiters, Vec::new());
                tokio::spawn({
                    future::join_all(waiters.into_iter().map(|sender| sender.send(())))
                        .map(|_| ())
                        .map_err(|_| ())
                });
            }
            hash_map::Entry::Vacant(entry) => {
                entry.insert(self::Module {
                    expr: expr_opt.unwrap_or_else(|| {
                        Arc::new(pos::spanned2(0.into(), 0.into(), Expr::Error(None)))
                    }),
                    source: self
                        .thread
                        .get_database()
                        .get_filemap(&name)
                        .unwrap_or_else(|| panic!("FileMap for diagnostics is missing: {}", name))
                        .clone(),
                    uri: uri_filename.clone(),
                    dirty: false,
                    waiters: Vec::new(),
                    version: version,
                    text_changes: TextChanges::new(),
                });
            }
        }
        if let Some(error) = error {
            Err(error)
        } else {
            Ok(())
        }
    }

    fn typecheck_(
        &mut self,
        name: &str,
        fileinput: &str,
    ) -> (Option<Arc<SpannedExpr<Symbol>>>, Option<GluonError>) {
        debug!("Loading: `{}`", name);
        self.thread
            .get_database_mut()
            .add_module(name.into(), fileinput.into());
        match self
            .thread
            .get_database()
            .typechecked_module(name.into(), None)
        {
            Ok(value) => (Some(value.expr), None),
            Err((opt, err)) => (opt.map(|v| v.expr), Some(err)),
        }
    }
}

pub fn register(
    io: &mut IoHandler,
    thread: &RootedThread,
    message_log: &mpsc::Sender<String>,
    shutdown: ShutdownReceiver,
) {
    let work_queue = {
        let (diagnostic_sink, diagnostic_stream) = rpc::unique_queue();

        let mut diagnostics_runner = DiagnosticsWorker::new(thread.clone(), message_log.clone());

        tokio::spawn(cancelable(
            shutdown,
            future::lazy(move || {
                diagnostic_stream.for_each(move |entry: Entry<Url, Arc<codespan::FileMap>, _>| {
                    diagnostics_runner.run_diagnostics(
                        &entry.key,
                        Some(entry.version),
                        &entry.value.src(),
                    )
                })
            }),
        ));

        diagnostic_sink
    };

    {
        let work_queue = work_queue.clone();
        let thread = thread.clone();

        let f = move |change: DidOpenTextDocumentParams| {
            let work_queue = work_queue.clone();
            let thread = thread.clone();
            tokio::spawn({
                let filename = strip_file_prefix_with_thread(&thread, &change.text_document.uri);
                let module = filename_to_module(&filename);
                work_queue
                    .send(Entry {
                        key: change.text_document.uri,
                        value: Arc::new(codespan::FileMap::new(
                            module.into(),
                            change.text_document.text,
                        )),
                        version: change.text_document.version,
                    })
                    .map(|_| ())
                    .map_err(|_| ())
            });
        };
        io.add_notification(notification!("textDocument/didOpen"), f);
    }
    {
        let f = move |_: DidSaveTextDocumentParams| {};
        io.add_notification(notification!("textDocument/didSave"), f);
    }

    fn did_change<S>(
        thread: &Thread,
        message_log: mpsc::Sender<String>,
        work_queue: S,
        change: DidChangeTextDocumentParams,
    ) -> impl Future<Item = (), Error = ()> + Send + 'static
    where
        S: Sink<SinkItem = Entry<Url, Arc<codespan::FileMap>, u64>, SinkError = ()>
            + Send
            + 'static,
    {
        // If it does not exist in sources it should exist in the `import` macro
        let import = thread.get_macros().get("import").expect("Import macro");
        let import = import
            .downcast_ref::<Import<CheckImporter>>()
            .expect("Check importer");
        let mut modules = import.importer.0.lock().unwrap();
        let paths = import.paths.read().unwrap();
        let module_name = strip_file_prefix(&paths, &change.text_document.uri)
            .unwrap_or_else(|err| panic!("{}", err));
        let module_name = filename_to_module(&module_name);
        let module = modules
            .entry(module_name.clone())
            .or_insert_with(|| Module::empty(change.text_document.uri.clone()));

        module.text_changes.add(
            change.text_document.version.expect("version"),
            change.content_changes,
        );

        module.dirty = true;

        let uri = change.text_document.uri;
        // If the module was loaded via `import!` before we open it in the editor
        // `module.uri` has been set by looking at the current working directory which is
        // not necessarily correct (works in VS code but not with (neo)vim) so update the
        // uri to match the one supplied by the client to ensure errors show up.
        if module.uri != uri {
            module.uri.clone_from(&uri);
        }
        let result = {
            let mut source = module.source.src().to_string();
            debug!("Change source {}:\n{}", uri, source);

            match module.version {
                Some(current_version) => match module
                    .text_changes
                    .apply_changes(&mut source, current_version)
                {
                    Ok(version) if version == current_version => return Either::A(future::ok(())),
                    Ok(version) => {
                        module.source =
                            Arc::new(codespan::FileMap::new(module.source.name().clone(), source));
                        Ok(version)
                    }
                    Err(err) => Err(err),
                },
                None => return Either::A(future::ok(())),
            }
        };
        match result {
            Ok(new_version) => {
                module.version = Some(new_version);
                let arc_source = module.source.clone();
                debug!("Changed to\n{}", arc_source.src());
                Either::B(Either::A(
                    work_queue
                        .send(Entry {
                            key: uri,
                            value: arc_source,
                            version: new_version,
                        })
                        .map(|_| ()),
                ))
            }
            Err(err) => Either::B(Either::B(
                log_message!(message_log.clone(), "{}", err.message).then(|_| Err(())),
            )),
        }
    }
    {
        let thread = thread.clone();
        let message_log = message_log.clone();

        let f = move |change: DidChangeTextDocumentParams| {
            let work_queue = work_queue.clone();
            let thread = thread.clone();
            let message_log = message_log.clone();
            tokio::spawn({
                let work_queue = work_queue.clone();
                ::std::panic::AssertUnwindSafe(did_change(
                    &thread,
                    message_log.clone(),
                    work_queue.clone().sink_map_err(|_| ()),
                    change,
                ))
                .catch_unwind()
                .map_err(|err| {
                    error!("{:?}", err);
                })
                .and_then(|result| result)
            });
        };

        io.add_notification(notification!("textDocument/didChange"), f);
    }
}
<commit_msg>Avoid some unnecessary moves<commit_after>use std::{
    collections::{hash_map, BTreeMap},
    fmt, mem,
    sync::Arc,
};

use gluon::{
    self,
    base::{
        ast::{Expr, SpannedExpr},
        filename_to_module, pos,
        symbol::Symbol,
    },
    import::Import,
    query::{Compilation, CompilationBase},
    Error as GluonError, Result as GluonResult, RootedThread, Thread, ThreadExt,
};

use futures::{
    future::{self, Either},
    prelude::*,
    stream,
    sync::mpsc,
};

use tokio;

use codespan;
use codespan_lsp;

use url::Url;

use jsonrpc_core::IoHandler;

use languageserver_types::*;

use crate::{
    cancelable,
    check_importer::{CheckImporter, Module},
    name::{
        codespan_name_to_file, module_name_to_file, strip_file_prefix,
        strip_file_prefix_with_thread,
    },
    rpc::{self, send_response, Entry, ServerError},
    server::{Handler, ShutdownReceiver},
    text_edit::TextChanges,
    BoxFuture,
};

fn create_diagnostics(
    diagnostics: &mut BTreeMap<Url, Vec<Diagnostic>>,
    code_map: &codespan::CodeMap,
    importer: &CheckImporter,
    filename: &Url,
    err: &GluonError,
) -> Result<(), ServerError<()>> {
    use gluon::base::error::AsDiagnostic;
    fn into_diagnostic<T>(
        code_map: &codespan::CodeMap,
        err: &pos::Spanned<T, pos::BytePos>,
    ) -> Result<Diagnostic, ServerError<()>>
    where
        T: fmt::Display + AsDiagnostic,
    {
        Ok(Diagnostic {
            source: Some("gluon".to_string()),
            ..codespan_lsp::make_lsp_diagnostic(code_map, err.as_diagnostic(), |filename| {
                codespan_name_to_file(filename).map_err(|err| {
                    error!("{}", err);
                })
            })?
        })
    }

    fn insert_in_file_error<T>(
        diagnostics: &mut BTreeMap<Url, Vec<Diagnostic>>,
        code_map: &codespan::CodeMap,
        importer: &CheckImporter,
        in_file_error: &gluon::base::error::InFile<T>,
    ) -> Result<(), ServerError<()>>
    where
        T: fmt::Display + AsDiagnostic,
    {
        let errors = diagnostics
            .entry(module_name_to_file(importer, &in_file_error.source_name()))
            .or_default();
        for err in in_file_error.errors() {
            errors.push(into_diagnostic(code_map, &err)?);
        }
        Ok(())
    }

    match err {
        GluonError::Typecheck(err) => insert_in_file_error(diagnostics, code_map, importer, err)?,

        GluonError::Parse(err) => insert_in_file_error(diagnostics, code_map, importer, err)?,

        GluonError::Macro(err) => insert_in_file_error(diagnostics, code_map, importer, err)?,

        GluonError::Multiple(errors) => {
            for err in errors {
                create_diagnostics(diagnostics, code_map, importer, filename, err)?;
            }
        }

        err => diagnostics
            .entry(filename.clone())
            .or_default()
            .push(Diagnostic {
                message: format!("{}", err),
                severity: Some(DiagnosticSeverity::Error),
                source: Some("gluon".to_string()),
                ..Diagnostic::default()
            }),
    }
    Ok(())
}

struct DiagnosticsWorker {
    thread: RootedThread,
    message_log: mpsc::Sender<String>,
}

impl DiagnosticsWorker {
    pub fn new(thread: RootedThread, message_log: mpsc::Sender<String>) -> Self {
        DiagnosticsWorker {
            thread,
            message_log,
        }
    }

    pub fn run_diagnostics(
        &mut self,
        uri_filename: &Url,
        version: Option<u64>,
        fileinput: &str,
    ) -> BoxFuture<(), ()> {
        info!("Running diagnostics on {}", uri_filename);

        let filename = strip_file_prefix_with_thread(&self.thread, uri_filename);
        let name = filename_to_module(&filename);

        self.thread.get_database().update_filemap(&name, fileinput);

        let diagnostics = match self.typecheck(uri_filename, &name, version, fileinput) {
            Ok(_) => Some((uri_filename.clone(), vec![])).into_iter().collect(),
            Err(err) => {
                debug!("Diagnostics result on `{}`: {}", uri_filename, err);
                let mut diagnostics = BTreeMap::new();

                let import = self
                    .thread
                    .get_macros()
                    .get("import")
                    .expect("Import macro");
                let import = import
                    .downcast_ref::<Import<CheckImporter>>()
                    .expect("Check importer");

                let result = create_diagnostics(
                    &mut diagnostics,
                    &self.thread.get_database().code_map(),
                    &import.importer,
                    uri_filename,
                    &err,
                );
                if let Err(err) = result {
                    error!("Unable to create diagnostics: {}", err.message);
                    return Box::new(Err(()).into_future());
                }
                diagnostics
            }
        };

        let message_log = self.message_log.clone();
        Box::new(
            stream::futures_ordered(diagnostics.into_iter().map(|(source_name, diagnostic)| {
                send_response(
                    message_log.clone(),
                    notification!("textDocument/publishDiagnostics"),
                    PublishDiagnosticsParams {
                        uri: source_name,
                        diagnostics: diagnostic,
                    },
                )
            }))
            .for_each(|_| Ok(())),
        )
    }

    fn typecheck(
        &mut self,
        uri_filename: &Url,
        name: &str,
        version: Option<u64>,
        fileinput: &str,
    ) -> GluonResult<()> {
        let (expr_opt, error) = self.typecheck_(&name, fileinput);

        let import = self
            .thread
            .get_macros()
            .get("import")
            .expect("Import macro");
        let import = import
            .downcast_ref::<Import<CheckImporter>>()
            .expect("Check importer");
        let mut importer = import.importer.0.lock().unwrap();

        match importer.entry(name.into()) {
            hash_map::Entry::Occupied(mut entry) => {
                let module = entry.get_mut();

                if let Some(expr) = expr_opt {
                    module.expr = expr;
                }
                module.uri = uri_filename.clone();

                if version.is_some() {
                    module.version = version;
                }

                module.source = self
                    .thread
                    .get_database()
                    .get_filemap(&name)
                    .unwrap_or_else(|| panic!("FileMap for diagnostics is missing: {}", name))
                    .clone();

                module.dirty = false;

                let waiters = mem::replace(&mut module.waiters, Vec::new());
                tokio::spawn({
                    future::join_all(waiters.into_iter().map(|sender| sender.send(())))
                        .map(|_| ())
                        .map_err(|_| ())
                });
            }
            hash_map::Entry::Vacant(entry) => {
                entry.insert(self::Module {
                    expr: expr_opt.unwrap_or_else(|| {
                        Arc::new(pos::spanned2(0.into(), 0.into(), Expr::Error(None)))
                    }),
                    source: self
                        .thread
                        .get_database()
                        .get_filemap(&name)
                        .unwrap_or_else(|| panic!("FileMap for diagnostics is missing: {}", name))
                        .clone(),
                    uri: uri_filename.clone(),
                    dirty: false,
                    waiters: Vec::new(),
                    version: version,
                    text_changes: TextChanges::new(),
                });
            }
        }
        if let Some(error) = error {
            Err(error)
        } else {
            Ok(())
        }
    }

    fn typecheck_(
        &mut self,
        name: &str,
        fileinput: &str,
    ) -> (Option<Arc<SpannedExpr<Symbol>>>, Option<GluonError>) {
        debug!("Loading: `{}`", name);
        self.thread
            .get_database_mut()
            .add_module(name.into(), fileinput.into());
        match self
            .thread
            .get_database()
            .typechecked_module(name.into(), None)
        {
            Ok(value) => (Some(value.expr), None),
            Err((opt, err)) => (opt.map(|v| v.expr), Some(err)),
        }
    }
}

pub fn register(
    io: &mut IoHandler,
    thread: &RootedThread,
    message_log: &mpsc::Sender<String>,
    shutdown: ShutdownReceiver,
) {
    let work_queue = {
        let (diagnostic_sink, diagnostic_stream) = rpc::unique_queue();

        let mut diagnostics_runner = DiagnosticsWorker::new(thread.clone(), message_log.clone());

        tokio::spawn(cancelable(
            shutdown,
            future::lazy(move || {
                diagnostic_stream.for_each(move |entry: Entry<Url, Arc<codespan::FileMap>, _>| {
                    diagnostics_runner.run_diagnostics(
                        &entry.key,
                        Some(entry.version),
                        &entry.value.src(),
                    )
                })
            }),
        ));

        diagnostic_sink
    };

    {
        let work_queue = work_queue.clone();
        let thread = thread.clone();

        let f = move |change: DidOpenTextDocumentParams| {
            let work_queue = work_queue.clone();
            let thread = thread.clone();
            tokio::spawn({
                let filename = strip_file_prefix_with_thread(&thread, &change.text_document.uri);
                let module = filename_to_module(&filename);
                work_queue
                    .send(Entry {
                        key: change.text_document.uri,
                        value: Arc::new(codespan::FileMap::new(
                            module.into(),
                            change.text_document.text,
                        )),
                        version: change.text_document.version,
                    })
                    .map(|_| ())
                    .map_err(|_| ())
            });
        };
        io.add_notification(notification!("textDocument/didOpen"), f);
    }
    {
        let f = move |_: DidSaveTextDocumentParams| {};
        io.add_notification(notification!("textDocument/didSave"), f);
    }

    fn did_change<S>(
        thread: &Thread,
        message_log: mpsc::Sender<String>,
        work_queue: S,
        change: DidChangeTextDocumentParams,
    ) -> impl Future<Item = (), Error = ()> + Send + 'static
    where
        S: Sink<SinkItem = Entry<Url, Arc<codespan::FileMap>, u64>, SinkError = ()>
            + Send
            + 'static,
    {
        // If it does not exist in sources it should exist in the `import` macro
        let import = thread.get_macros().get("import").expect("Import macro");
        let import = import
            .downcast_ref::<Import<CheckImporter>>()
            .expect("Check importer");
        let mut modules = import.importer.0.lock().unwrap();
        let paths = import.paths.read().unwrap();
        let module_name = strip_file_prefix(&paths, &change.text_document.uri)
            .unwrap_or_else(|err| panic!("{}", err));
        let module_name = filename_to_module(&module_name);
        let module = modules
            .entry(module_name.clone())
            .or_insert_with(|| Module::empty(change.text_document.uri.clone()));

        module.text_changes.add(
            change.text_document.version.expect("version"),
            change.content_changes,
        );

        module.dirty = true;

        let uri = change.text_document.uri;
        // If the module was loaded via `import!` before we open it in the editor
        // `module.uri` has been set by looking at the current working directory which is
        // not necessarily correct (works in VS code but not with (neo)vim) so update the
        // uri to match the one supplied by the client to ensure errors show up.
        if module.uri != uri {
            module.uri.clone_from(&uri);
        }
        let result = {
            let mut source = module.source.src().to_string();
            debug!("Change source {}:\n{}", uri, source);

            match module.version {
                Some(current_version) => match module
                    .text_changes
                    .apply_changes(&mut source, current_version)
                {
                    Ok(version) if version == current_version => return Either::A(future::ok(())),
                    Ok(version) => {
                        module.source =
                            Arc::new(codespan::FileMap::new(module.source.name().clone(), source));
                        Ok(version)
                    }
                    Err(err) => Err(err),
                },
                None => return Either::A(future::ok(())),
            }
        };
        match result {
            Ok(new_version) => {
                module.version = Some(new_version);
                let arc_source = module.source.clone();
                debug!("Changed to\n{}", arc_source.src());
                Either::B(Either::A(
                    work_queue
                        .send(Entry {
                            key: uri,
                            value: arc_source,
                            version: new_version,
                        })
                        .map(|_| ()),
                ))
            }
            Err(err) => Either::B(Either::B(
                log_message!(message_log.clone(), "{}", err.message).then(|_| Err(())),
            )),
        }
    }
    {
        let thread = thread.clone();
        let message_log = message_log.clone();

        let f = move |change: DidChangeTextDocumentParams| {
            let work_queue = work_queue.clone();
            let thread = thread.clone();
            let message_log = message_log.clone();
            tokio::spawn({
                let work_queue = work_queue.clone();
                ::std::panic::AssertUnwindSafe(did_change(
                    &thread,
                    message_log.clone(),
                    work_queue.clone().sink_map_err(|_| ()),
                    change,
                ))
                .catch_unwind()
                .map_err(|err| {
                    error!("{:?}", err);
                })
                .and_then(|result| result)
            });
        };

        io.add_notification(notification!("textDocument/didChange"), f);
    }
}
<|endoftext|>


<commit_before>extern crate argparse;
extern crate num;
extern crate byteorder;

use std::fs::File;
use std::io::Read;
use std::io::Cursor;
use std::mem;
use byteorder::{ByteOrder, LittleEndian, BigEndian, NativeEndian};
use std::process::exit;
use argparse::{ArgumentParser, StoreTrue, Store};
use std::f64::consts::PI;

type c32 = num::Complex<f32>;

struct Arguments {
    verbose: bool,
    data_path: String,
    tol: f64,
    iter: usize,
    readonly: bool,
}

impl Arguments {
    // default values for arguments
    fn new() -> Arguments {
        Arguments {
            verbose: false,
            data_path: String::from(""),
            tol: 1e-5,
            iter: 1,
            readonly: false,
        }
    }
}

struct Header {
    endianness: u8,
    grid_size: (usize, usize),
    grid: Vec<Vec<c32>>,
}

impl Header {
    fn new(e: u8, x: usize, y: usize) -> Header {
        Header {
            endianness: e,
            grid_size: (x, y),
            grid: vec![vec![c32::new(0f32, 0f32); x]; y],
        }
    }
}

fn read_header(namein: &str, data_path: &String) -> Header {
    fn is_big_endian() -> bool {
        let probe = [43u8, 21];
        probe[0] == 21u8
    }

    let name = format!("{}/{}.bin", data_path, namein);
    let mut file = File::open(name).unwrap();
    let mut buf = [0u8; 8];
    file.read(&mut buf[0..1]).unwrap();
    unsafe {
        let endianness = mem::transmute::<[u8; 1], u8>([buf[0]]);
        let (xe, ye) = if endianness == 0 {
            file.read(&mut buf[0..4]).unwrap();
            let xe = LittleEndian::read_u32(&buf[0..4]);
            file.read(&mut buf[0..4]).unwrap();
            let ye = LittleEndian::read_u32(&buf[0..4]);

            (xe, ye)

        } else {
            file.read(&mut buf[0..4]).unwrap();
            let xe = BigEndian::read_u32(&buf[0..4]);
            file.read(&mut buf[0..4]).unwrap();
            let ye = BigEndian::read_u32(&buf[0..4]);

            (xe, ye)
        };

        let grid_sz = (xe * ye) as usize;
        let mut grid_buf = vec![0u8; grid_sz];
        let sz = file.read(&mut grid_buf[..]).unwrap();
        if sz != grid_sz {
            panic!("corrupted grid sz: {} xe*ye: {}", sz, xe * ye);
        }

        Header::new(endianness, xe as usize, ye as usize)
    }

}

fn main() {
    let mut args = Arguments::new();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("SOCS standalone test");
        ap.refer(&mut args.verbose)
          .add_option(&["-v", "--verbose"], StoreTrue, "be verbose");
        ap.refer(&mut args.data_path)
          .add_option(&["-d", "--data-path"], Store, "path to input data");
        ap.refer(&mut args.tol)
          .add_option(&["-t", "--tol"], Store, "set tolerance <eps fp value>");
        ap.refer(&mut args.iter)
          .add_option(&["-i", "--iter"], Store, "set # of iterations");
        ap.refer(&mut args.readonly)
          .add_option(&["-r", "--readonly"], StoreTrue, "set readonly");
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                exit(x);
            }
        }
    }

    if args.verbose {
        println!("data path : {} number of iterations : {} tolerance : {:e} readonly : {}",
                 args.data_path,
                 args.iter,
                 args.tol,
                 args.readonly);
    }

    let mut file = File::open("Cargo.toml").unwrap();
    let mut buf = [0u8; 12];
    file.read(&mut buf).unwrap();
    println!("{:?}", buf);
    // use file
}
<commit_msg>read grid.<commit_after>extern crate argparse;
extern crate num;
extern crate byteorder;

use std::fs::File;
use std::io::Read;
use std::io::Cursor;
use std::mem;
use byteorder::{ByteOrder, LittleEndian, BigEndian, NativeEndian};
use std::process::exit;
use argparse::{ArgumentParser, StoreTrue, Store};
use std::f64::consts::PI;
use std::iter::FromIterator;

type c32 = num::Complex<f32>;

struct Arguments {
    verbose: bool,
    data_path: String,
    tol: f64,
    iter: usize,
    readonly: bool,
}

impl Arguments {
    // default values for arguments
    fn new() -> Arguments {
        Arguments {
            verbose: false,
            data_path: String::from(""),
            tol: 1e-5,
            iter: 1,
            readonly: false,
        }
    }
}

struct Header {
    endianness: u8,
    grid_size: (usize, usize),
    grid: Vec<Vec<c32>>,
}

impl Header {
    fn new(e: u8, x: usize, y: usize, read_buf: &Vec<u8>) -> Header {
        let xsize = x;
        let ysize = y;
        Header {
            endianness: e,
            grid_size: (x, y),
            grid: Vec::from_iter((0..xsize)
                         .map (|i|
                  Vec::from_iter((0..ysize)
                         .map (|j| {
                             let start = (i*ysize+j) * 2 * mem::size_of::<f32>();
                             let (real, imag) = if e == 0 {
                                 (LittleEndian::read_f32(&read_buf[start + 0 .. start + 4]),
                                  LittleEndian::read_f32(&read_buf[start + 4 .. start + 8]) )
                                                } else {
                                 (BigEndian::read_f32(&read_buf[start + 0 .. start + 4]),
                                  BigEndian::read_f32(&read_buf[start + 4 .. start + 8]) )};
                             //println!("start: {} buf slice1: {:?} slice2: {:?} real: {} imag: {}",
                             //          start, &read_buf[start + 0 .. start + 4], &read_buf[start + 4 .. start + 8], real, imag);
                             c32::new(real, imag)
                          } ) ) ) ),

        }
    }
}

fn read_header(namein: &str, data_path: &String) -> Header {
    fn is_big_endian() -> bool {
        let probe = [43u8, 21];
        probe[0] == 21u8
    }

    let name = format!("{}/{}.bin", data_path, namein);
    let mut file = File::open(name).unwrap();
    let mut buf = [0u8; 8];
    file.read(&mut buf[0..1]).unwrap();
    unsafe {
        let endianness = mem::transmute::<[u8; 1], u8>([buf[0]]);
        let (xe, ye) = if endianness == 0 {
            file.read(&mut buf[0..4]).unwrap();
            let xe = LittleEndian::read_u32(&buf[0..4]);
            file.read(&mut buf[0..4]).unwrap();
            let ye = LittleEndian::read_u32(&buf[0..4]);

            (xe, ye)

        } else {
            file.read(&mut buf[0..4]).unwrap();
            let xe = BigEndian::read_u32(&buf[0..4]);
            file.read(&mut buf[0..4]).unwrap();
            let ye = BigEndian::read_u32(&buf[0..4]);

            (xe, ye)
        };

        let grid_sz = (xe * ye) as usize;
        let grid_elem_size = mem::size_of::<c32>();
        let mut read_buf = Vec::new();
        let sz = file.read(&mut read_buf).unwrap();
        if sz != (grid_sz * grid_elem_size) {
            panic!("corrupted grid sz: {} xe*ye: {}", sz, xe * ye);
        }

        Header::new(endianness, xe as usize, ye as usize, &read_buf)
    }

}

fn main() {
    let mut args = Arguments::new();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("SOCS standalone test");
        ap.refer(&mut args.verbose)
          .add_option(&["-v", "--verbose"], StoreTrue, "be verbose");
        ap.refer(&mut args.data_path)
          .add_option(&["-d", "--data-path"], Store, "path to input data");
        ap.refer(&mut args.tol)
          .add_option(&["-t", "--tol"], Store, "set tolerance <eps fp value>");
        ap.refer(&mut args.iter)
          .add_option(&["-i", "--iter"], Store, "set # of iterations");
        ap.refer(&mut args.readonly)
          .add_option(&["-r", "--readonly"], StoreTrue, "set readonly");
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                exit(x);
            }
        }
    }

    if args.verbose {
        println!("data path : {} number of iterations : {} tolerance : {:e} readonly : {}",
                 args.data_path,
                 args.iter,
                 args.tol,
                 args.readonly);
    }

    let mut file = File::open("Cargo.toml").unwrap();
    let mut buf = [0u8; 12];
    file.read(&mut buf).unwrap();
    println!("{:?}", buf);
    // use file
}
<|endoftext|>


<commit_before>use std::fs;
use std::fs::File;
use std::path::Path;

use std::io::{Error, ErrorKind, Read, Seek, SeekFrom};

use buffer::Buffer;
use reader::Reader;

#[derive(Debug)]
pub struct FileReader {
    pub filename: String,
    pub position: u64,
    pub file: Option<File>,
    pub buffer: Buffer,
}

pub fn exists(filename: &str) -> bool {
    Path::new(filename).exists()
}

impl Reader for FileReader {
    fn new() -> FileReader {
        FileReader {
            filename: "".to_string(),
            position: 0,
            file: None,
            buffer: Buffer {
                size: None,
                position: 0,
                max_end_position: None,
                buffer: vec![],
            },
        }
    }

    fn open(&mut self, filename: &str) -> Result<(), String> {
        self.filename = filename.to_string();

        match File::open(filename) {
            Err(msg) => Err(msg.to_string()),
            Ok(file) => {
                self.file = Some(file);
                Ok(())
            }
        }
    }

    fn get_position(&mut self) -> Result<u64, String> {
        Ok(self.position)
    }

    fn get_cache_size(&self) -> Option<usize> {
        self.buffer.size
    }

    fn set_cache_size(&mut self, cache_size: Option<usize>) {
        self.buffer.size = cache_size;
    }

    fn get_max_end_position(&self) -> Option<u64> {
        self.buffer.max_end_position
    }

    fn set_max_end_position(&mut self, max_end_position: Option<u64>) {
        self.buffer.max_end_position = max_end_position;
    }

    fn get_size(&mut self) -> Result<u64, String> {
        let metadata = try!(fs::metadata(self.filename.clone()).map_err(|e| e.to_string()));
        Ok(metadata.len())
    }
}

impl Read for FileReader {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        if let Some(ref mut file_reader) = self.file {
            let readed_size = file_reader.read(buf)?;
            self.position += readed_size as u64;
            Ok(readed_size)
        } else {
            Err(Error::new(ErrorKind::Other, "No file opened"))
        }
    }
}

impl Seek for FileReader {
    fn seek(&mut self, seek_from: SeekFrom) -> Result<u64, Error> {
        if let Some(ref mut file_reader) = self.file {
            file_reader.seek(seek_from)
        } else {
            Err(Error::new(ErrorKind::Other, "No file opened"))
        }
    }
}
<commit_msg>set position for file reader seek<commit_after>use std::fs;
use std::fs::File;
use std::path::Path;

use std::io::{Error, ErrorKind, Read, Seek, SeekFrom};

use buffer::Buffer;
use reader::Reader;

#[derive(Debug)]
pub struct FileReader {
    pub filename: String,
    pub position: u64,
    pub file: Option<File>,
    pub buffer: Buffer,
}

pub fn exists(filename: &str) -> bool {
    Path::new(filename).exists()
}

impl Reader for FileReader {
    fn new() -> FileReader {
        FileReader {
            filename: "".to_string(),
            position: 0,
            file: None,
            buffer: Buffer {
                size: None,
                position: 0,
                max_end_position: None,
                buffer: vec![],
            },
        }
    }

    fn open(&mut self, filename: &str) -> Result<(), String> {
        self.filename = filename.to_string();

        match File::open(filename) {
            Err(msg) => Err(msg.to_string()),
            Ok(file) => {
                self.file = Some(file);
                Ok(())
            }
        }
    }

    fn get_position(&mut self) -> Result<u64, String> {
        Ok(self.position)
    }

    fn get_cache_size(&self) -> Option<usize> {
        self.buffer.size
    }

    fn set_cache_size(&mut self, cache_size: Option<usize>) {
        self.buffer.size = cache_size;
    }

    fn get_max_end_position(&self) -> Option<u64> {
        self.buffer.max_end_position
    }

    fn set_max_end_position(&mut self, max_end_position: Option<u64>) {
        self.buffer.max_end_position = max_end_position;
    }

    fn get_size(&mut self) -> Result<u64, String> {
        let metadata = try!(fs::metadata(self.filename.clone()).map_err(|e| e.to_string()));
        Ok(metadata.len())
    }
}

impl Read for FileReader {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        if let Some(ref mut file_reader) = self.file {
            let readed_size = file_reader.read(buf)?;
            self.position += readed_size as u64;
            Ok(readed_size)
        } else {
            Err(Error::new(ErrorKind::Other, "No file opened"))
        }
    }
}

impl Seek for FileReader {
    fn seek(&mut self, seek_from: SeekFrom) -> Result<u64, Error> {
        if let Some(ref mut file_reader) = self.file {
            let seek_position = file_reader.seek(seek_from)?;
            self.position = seek_position;
            Ok(seek_position)
        } else {
            Err(Error::new(ErrorKind::Other, "No file opened"))
        }
    }
}
<|endoftext|>