<commit_before>//! Game loop.

// External crates.
use graphics::*;
use gl;
use gl::types::GLint;
use time;

// Local crate.
use Gl = gl_back_end::Gl;
use GlData = gl_back_end::GlData;
use GameWindow = game_window::GameWindow;
use AssetStore;
use keyboard;
use event;
use mouse;

/// Implemented by game applications.
pub trait Game {
    /// Render graphics.
    ///
    /// `context` is a Rust-Graphics context.
    /// `gl` is the Piston OpenGL back-end for Rust-Graphics.
    fn render(&self, _ext_dt: f64, _context: &Context, _gl: &mut Gl) {}

    /// Update the physical state of the game.
    ///
    /// `dt` is the delta time from last update in seconds.
    fn update(&mut self, _dt: f64, _asset_store: &mut AssetStore) {}

    /// Perform tasks for loading before showing anything.
    fn load(&mut self, _asset_store: &mut AssetStore) {}

    /// User pressed a key.
    ///
    /// This can be overridden to handle key pressed events.
    fn key_press(
        &mut self,
        _key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {}

    /// User released a key.
    ///
    /// This can be overridden to handle key released events.
    fn key_release(
        &mut self,
        _key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {}

    /// Pressed a mouse button.
    fn mouse_press(
        &mut self,
        _button: mouse::Button,
        _asset_store: &mut AssetStore
    ) {}

    /// Released a mouse button.
    fn mouse_release(
        &mut self,
        _button: mouse::Button,
        _asset_store: &mut AssetStore
    ) {}

    /// Moved mouse cursor.
    fn mouse_move(
        &mut self,
        _x: f64,
        _y: f64,
        _asset_store: &mut AssetStore
    ) {}

    /// Moved mouse relative, not bounded by cursor.
    fn mouse_relative_move(
        &mut self,
        _dx: f64,
        _dy: f64,
        _asset_store: &mut AssetStore
    ) {}

    /// Sets up viewport.
    ///
    /// A viewport is the region of the window where graphics is rendered.
    #[inline(always)]
    fn viewport<W: GameWindow>(&self, game_window: &W) {
        let (w, h) = game_window.get_size();
        gl::Viewport(0, 0, w as GLint, h as GLint);
    }

    /// Whether the window should be closed.
    ///
    /// When this is `true` the application shuts down.
    /// This can be overridden to emulate a user closing the window.
    /// One can also override this method to prevent window from closing.
    fn should_close<W: GameWindow>(&self, game_window: &W) -> bool {
        game_window.should_close()
    }

    /// Swaps the front buffer with the back buffer.
    ///
    /// When called, This shows the next frame.
    /// The graphics is rendered to the back buffer.
    /// The front buffer is displayed on the screen.
    fn swap_buffers<W: GameWindow>(&self, game_window: &W) {
        game_window.swap_buffers()
    }

    /// Handles events using current game window settings.
    ///
    /// This can be overriden to do custom event handling.
    fn handle_events<W: GameWindow>(
        &mut self,
        game_window: &mut W,
        asset_store: &mut AssetStore
    ) {
        loop {
            match game_window.poll_event() {
                event::KeyPressed(keycode) => {
                    self.key_press(keycode, asset_store)
                },
                event::KeyReleased(keycode) => {
                    self.key_release(keycode, asset_store)
                },
                event::MouseButtonPressed(mouse_button) => {
                    self.mouse_press(mouse_button, asset_store)
                },
                event::MouseButtonReleased(mouse_button) => {
                    self.mouse_release(mouse_button, asset_store)
                },
                event::MouseMoved(x, y, relative_move) => {
                    self.mouse_move(x, y, asset_store);
                    match relative_move {
                        Some((dx, dy)) =>
                            self.mouse_relative_move(dx, dy, asset_store),
                        None => {},
                    }
                },
                event::NoEvent => {
                    break
                },
            }
        }
    }

    /// Executes a game loop.
    ///
    /// The loop continues until `should_close` returns true.
    fn run<W: GameWindow>(
        &mut self,
        game_window: &mut W,
        asset_store: &mut AssetStore
    ) {
        use graphics::{Clear, AddColor};

        self.load(asset_store);
        let mut gl_data = GlData::new();
        let context = Context::new();
        let bg = game_window.get_settings().background_color;
        let bg = context.rgba(bg[0], bg[1], bg[2], bg[3]);
        let updates_per_second: f64 = 120.0;
        let max_frames_per_second: f64 = 60.0;

        let billion: u64 = 1_000_000_000;
        let dt: f64 = 1.0 / updates_per_second;
        let update_time_in_ns: u64 = billion / updates_per_second as u64;

        let start = time::precise_time_ns();
        let min_ns_per_frame = (billion as f64 / max_frames_per_second) as u64;
        let mut next_render = start;
        let mut last_update = start;
        // Set updated to 'true' to trigger rendering before first update.
        while !self.should_close(game_window) {
            let now = time::precise_time_ns();

            if now >= next_render {
                // Render.
                let (w, h) = game_window.get_size();
                if w != 0 && h != 0 {
                    self.viewport(game_window);
                    let mut gl = Gl::new(&mut gl_data, asset_store);
                    bg.clear(&mut gl);
                    // Extrapolate time forward to allow smooth motion.
                    // 'now' is always bigger than 'last_update'.
                    let ext_dt = (now - last_update) as f64 / billion as f64;
                    self.render(
                        ext_dt,
                        &context
                        .trans(-1.0, 1.0)
                        .scale(2.0 / w as f64, -2.0 / h as f64)
                        .store_view(),
                        &mut gl
                    );
                    self.swap_buffers(game_window);
                }

                // Set moment for next rendering.
                next_render = now + min_ns_per_frame;
            }

            // Perform updates by fixed time step until it catches up.
            while last_update < next_render &&
                  time::precise_time_ns() < next_render {
                // Handle user input.
                // This is handled every update to make it more responsive.
                self.handle_events(game_window, asset_store);

                // Update application state.
                self.update(dt, asset_store);
                last_update += update_time_in_ns;
            }
        }
    }
}

<commit_msg>Fix bug: never updating on long render<commit_after>//! Game loop.

// External crates.
use graphics::*;
use gl;
use gl::types::GLint;
use time;

// Local crate.
use Gl = gl_back_end::Gl;
use GlData = gl_back_end::GlData;
use GameWindow = game_window::GameWindow;
use AssetStore;
use keyboard;
use event;
use mouse;

/// Implemented by game applications.
pub trait Game {
    /// Render graphics.
    ///
    /// `context` is a Rust-Graphics context.
    /// `gl` is the Piston OpenGL back-end for Rust-Graphics.
    fn render(&self, _ext_dt: f64, _context: &Context, _gl: &mut Gl) {}

    /// Update the physical state of the game.
    ///
    /// `dt` is the delta time from last update in seconds.
    fn update(&mut self, _dt: f64, _asset_store: &mut AssetStore) {}

    /// Perform tasks for loading before showing anything.
    fn load(&mut self, _asset_store: &mut AssetStore) {}

    /// User pressed a key.
    ///
    /// This can be overridden to handle key pressed events.
    fn key_press(
        &mut self,
        _key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {}

    /// User released a key.
    ///
    /// This can be overridden to handle key released events.
    fn key_release(
        &mut self,
        _key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {}

    /// Pressed a mouse button.
    fn mouse_press(
        &mut self,
        _button: mouse::Button,
        _asset_store: &mut AssetStore
    ) {}

    /// Released a mouse button.
    fn mouse_release(
        &mut self,
        _button: mouse::Button,
        _asset_store: &mut AssetStore
    ) {}

    /// Moved mouse cursor.
    fn mouse_move(
        &mut self,
        _x: f64,
        _y: f64,
        _asset_store: &mut AssetStore
    ) {}

    /// Moved mouse relative, not bounded by cursor.
    fn mouse_relative_move(
        &mut self,
        _dx: f64,
        _dy: f64,
        _asset_store: &mut AssetStore
    ) {}

    /// Sets up viewport.
    ///
    /// A viewport is the region of the window where graphics is rendered.
    #[inline(always)]
    fn viewport<W: GameWindow>(&self, game_window: &W) {
        let (w, h) = game_window.get_size();
        gl::Viewport(0, 0, w as GLint, h as GLint);
    }

    /// Whether the window should be closed.
    ///
    /// When this is `true` the application shuts down.
    /// This can be overridden to emulate a user closing the window.
    /// One can also override this method to prevent window from closing.
    fn should_close<W: GameWindow>(&self, game_window: &W) -> bool {
        game_window.should_close()
    }

    /// Swaps the front buffer with the back buffer.
    ///
    /// When called, This shows the next frame.
    /// The graphics is rendered to the back buffer.
    /// The front buffer is displayed on the screen.
    fn swap_buffers<W: GameWindow>(&self, game_window: &W) {
        game_window.swap_buffers()
    }

    /// Handles events using current game window settings.
    ///
    /// This can be overriden to do custom event handling.
    fn handle_events<W: GameWindow>(
        &mut self,
        game_window: &mut W,
        asset_store: &mut AssetStore
    ) {
        loop {
            match game_window.poll_event() {
                event::KeyPressed(keycode) => {
                    self.key_press(keycode, asset_store)
                },
                event::KeyReleased(keycode) => {
                    self.key_release(keycode, asset_store)
                },
                event::MouseButtonPressed(mouse_button) => {
                    self.mouse_press(mouse_button, asset_store)
                },
                event::MouseButtonReleased(mouse_button) => {
                    self.mouse_release(mouse_button, asset_store)
                },
                event::MouseMoved(x, y, relative_move) => {
                    self.mouse_move(x, y, asset_store);
                    match relative_move {
                        Some((dx, dy)) =>
                            self.mouse_relative_move(dx, dy, asset_store),
                        None => {},
                    }
                },
                event::NoEvent => {
                    break
                },
            }
        }
    }

    /// Executes a game loop.
    ///
    /// The loop continues until `should_close` returns true.
    fn run<W: GameWindow>(
        &mut self,
        game_window: &mut W,
        asset_store: &mut AssetStore
    ) {
        use graphics::{Clear, AddColor};

        self.load(asset_store);
        let mut gl_data = GlData::new();
        let context = Context::new();
        let bg = game_window.get_settings().background_color;
        let bg = context.rgba(bg[0], bg[1], bg[2], bg[3]);
        let updates_per_second: u64 = 120;
        let max_frames_per_second: u64 = 60;

        // You can make this lower if needed
        let min_updates_per_frame: u64 = updates_per_second / max_frames_per_second;

        let billion: u64 = 1_000_000_000;
        let dt: f64 = 1.0 / updates_per_second as f64;
        let update_time_in_ns: u64 = billion / updates_per_second;

        let start = time::precise_time_ns();
        let min_ns_per_frame = billion / max_frames_per_second;
        let mut next_render = start;
        let mut last_update = start;
        let mut updated = min_updates_per_frame;

        while !self.should_close(game_window) {
            let now = time::precise_time_ns();

            if now >= next_render &&
               ( updated >= min_updates_per_frame ||
                 next_render >= last_update ) {
                let (w, h) = game_window.get_size();
                if w != 0 && h != 0 {
                    self.viewport(game_window);
                    let mut gl = Gl::new(&mut gl_data, asset_store);
                    bg.clear(&mut gl);
                    // Extrapolate time forward to allow smooth motion.
                    // 'now' is always bigger than 'last_update'.
                    let ext_dt = (now - last_update) as f64 / billion as f64;
                    self.render(
                        ext_dt,
                        &context
                        .trans(-1.0, 1.0)
                        .scale(2.0 / w as f64, -2.0 / h as f64)
                        .store_view(),
                        &mut gl
                    );
                    self.swap_buffers(game_window);
                }

                // Set moment for next rendering.
                next_render = now + min_ns_per_frame;
                updated = 0;
            }

            // Perform updates by fixed time step until it catches up.
            while last_update < next_render &&
                  ( updated < min_updates_per_frame ||
                    time::precise_time_ns() < next_render ) {
                // Handle user input.
                // This is handled every update to make it more responsive.
                self.handle_events(game_window, asset_store);

                // Update application state.
                self.update(dt, asset_store);
                last_update += update_time_in_ns;
                updated += 1
            }
        }
    }
}

<|endoftext|>


<commit_before>//! Module for creating HMAC digests.
use sha2::{HashFunction, MAX_DIGEST_SIZE, Sha224, Sha256, Sha384, Sha512};

const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5c;

/// A function for creating HMAC digests given a hash function `H`.
///
/// # Examples
///
/// ```
/// use crypto_pure::hmac::Hmac;
/// use crypto_pure::sha2::{HashFunction, Sha512};
/// # let key = b"This should be generated securely.";
/// let mut digest = [0; Sha512::DIGEST_SIZE];
/// let mut hmac = Hmac::<Sha512>::new(key);
/// hmac.update(b"part one");
/// hmac.update(b"part two");
/// hmac.write_digest(&mut digest);
/// ```
pub struct Hmac<H> {
    inner_hash_function: H,
    outer_hash_function: H,
}

macro_rules! impl_wrapper { ($function:ident, $key:expr, $message:expr) => {{
    let mut digest = [0; $function::DIGEST_SIZE];
    let mut hmac = Hmac::<$function>::new($key);
    hmac.update($message);
    hmac.write_digest(&mut digest);
    digest
}}}

/// Wrapper for obtaining the HMAC-SHA-512 digest for a complete message.
pub fn hmac_sha512(key: &[u8], message: &[u8]) -> [u8; Sha512::DIGEST_SIZE] {
    impl_wrapper!(Sha512, key, message)
}

/// Wrapper for obtaining the HMAC-SHA-384 digest for a complete message.
pub fn hmac_sha384(key: &[u8], message: &[u8]) -> [u8; Sha384::DIGEST_SIZE] {
    impl_wrapper!(Sha384, key, message)
}

/// Wrapper for obtaining the HMAC-SHA-256 digest for a complete message.
pub fn hmac_sha256(key: &[u8], message: &[u8]) -> [u8; Sha256::DIGEST_SIZE] {
    impl_wrapper!(Sha256, key, message)
}

/// Wrapper for obtaining the HMAC-SHA-224 digest for a complete message.
pub fn hmac_sha224(key: &[u8], message: &[u8]) -> [u8; Sha224::DIGEST_SIZE] {
    impl_wrapper!(Sha224, key, message)
}

impl<H: HashFunction> Hmac<H> {
    /// Initializes an HMAC function given a key.
    pub fn new(key: &[u8]) -> Self {
        let mut hashed_key;
        let new_key;
        if key.len() > H::BLOCK_SIZE {
            hashed_key = [0; MAX_DIGEST_SIZE];
            let mut hash_function = H::default();
            hash_function.update(key);
            hash_function.write_digest(&mut hashed_key[..H::DIGEST_SIZE]);
            new_key = &hashed_key[..H::DIGEST_SIZE];
        } else {
            new_key = key;
        }
        Self {
            inner_hash_function: Self::keyed_hash_function(new_key, IPAD),
            outer_hash_function: Self::keyed_hash_function(new_key, OPAD),
        }
    }

    /// Feeds input into the function to update its state.
    pub fn update(&mut self, input: &[u8]) {
        self.inner_hash_function.update(input);
    }

    /// Writes the digest into an output buffer.
    ///
    /// # Panics
    ///
    /// Panics if `output.len()` is not equal to the digest size.
    pub fn write_digest(mut self, output: &mut [u8]) {
        assert_eq!(H::DIGEST_SIZE, output.len());
        self.inner_hash_function.write_digest(output);
        self.outer_hash_function.update(output);
        self.outer_hash_function.write_digest(output);
    }

    fn keyed_hash_function(key: &[u8], pad: u8) -> H {
        let mut hash_function = H::default();
        for byte in key {
            hash_function.update(&[byte ^ pad]);
        }
        for _ in key.len()..H::BLOCK_SIZE {
            hash_function.update(&[pad]);
        }
        hash_function
    }
}

#[cfg(test)]
mod tests {
    use std::vec::Vec;
    use super::*;
    use test_helpers::*;

    fn check(exp512: &str, exp384: &str, exp256: &str, exp224: &str, key: &[u8], data: &[u8]) {
        macro_rules! check { ($function:ident, $wrapper:path, $expected:expr) => (
            let expected = h2b($expected);
            let actual = $wrapper(key, data);
            assert_eq!(expected, actual.to_vec());

            let actual = &mut vec![0; expected.len()];
            let mut hmac = Hmac::<$function>::new(key);
            for word in data.chunks(4) {
                hmac.update(word);
            }
            hmac.write_digest(actual);
            assert_eq!(expected, actual.to_vec());
        )}

        check!(Sha512, hmac_sha512, exp512);
        check!(Sha384, hmac_sha384, exp384);
        check!(Sha256, hmac_sha256, exp256);
        check!(Sha224, hmac_sha224, exp224);
    }

    #[test]
    fn test_digest() {
        let key = h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
        let data = b"Hi There";
        let exp512 = "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde\
                      daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854";
        let exp384 = "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c\
                      faea9ea9076ede7f4af152e8b2fa9cb6";
        let exp256 = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7";
        let exp224 = "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22";
        check(exp512, exp384, exp256, exp224, &key, data);

        let key = b"Jefe";
        let data = b"what do ya want for nothing?";
        let exp512 = "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554\
                      9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737";
        let exp384 = "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e\
                      8e2240ca5e69e2c78b3239ecfab21649";
        let exp256 = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843";
        let exp224 = "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44";
        check(exp512, exp384, exp256, exp224, key, data);

        let key = [0xaa; 20];
        let data = [0xdd; 50];
        let exp512 = "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39\
                      bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb";
        let exp384 = "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b\
                      2a5ab39dc13814b94e3ab6e101a34f27";
        let exp256 = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe";
        let exp224 = "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea";
        check(exp512, exp384, exp256, exp224, &key, &data);

        let key: Vec<_> = (0x01..0x1a).collect();
        let data = [0xcd; 50];
        let exp512 = "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db\
                      a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd";
        let exp384 = "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e\
                      6801dd23c4a7d679ccf8a386c674cffb";
        let exp256 = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b";
        let exp224 = "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a";
        check(exp512, exp384, exp256, exp224, &key, &data);

        let key = [0xaa; 131];
        let data = b"Test Using Larger Than Block-Size Key - Hash Key First";
        let exp512 = "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352\
                      6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598";
        let exp384 = "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6\
                      0c2ef6ab4030fe8296248df163f44952";
        let exp256 = "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54";
        let exp224 = "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e";
        check(exp512, exp384, exp256, exp224, &key, data);

        let data =
            b"This is a test using a larger than block-size key and a larger than block-\
              size data. The key needs to be hashed before being used by the HMAC algorithm.";
        let exp512 = "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944\
                      b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58";
        let exp384 = "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5\
                      a678cc31e799176d3860e6110c46523e";
        let exp256 = "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2";
        let exp224 = "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1";
        check(exp512, exp384, exp256, exp224, &key, data);
    }
}
<commit_msg>hmac: move some references in tests<commit_after>//! Module for creating HMAC digests.
use sha2::{HashFunction, MAX_DIGEST_SIZE, Sha224, Sha256, Sha384, Sha512};

const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5c;

/// A function for creating HMAC digests given a hash function `H`.
///
/// # Examples
///
/// ```
/// use crypto_pure::hmac::Hmac;
/// use crypto_pure::sha2::{HashFunction, Sha512};
/// # let key = b"This should be generated securely.";
/// let mut digest = [0; Sha512::DIGEST_SIZE];
/// let mut hmac = Hmac::<Sha512>::new(key);
/// hmac.update(b"part one");
/// hmac.update(b"part two");
/// hmac.write_digest(&mut digest);
/// ```
pub struct Hmac<H> {
    inner_hash_function: H,
    outer_hash_function: H,
}

macro_rules! impl_wrapper { ($function:ident, $key:expr, $message:expr) => {{
    let mut digest = [0; $function::DIGEST_SIZE];
    let mut hmac = Hmac::<$function>::new($key);
    hmac.update($message);
    hmac.write_digest(&mut digest);
    digest
}}}

/// Wrapper for obtaining the HMAC-SHA-512 digest for a complete message.
pub fn hmac_sha512(key: &[u8], message: &[u8]) -> [u8; Sha512::DIGEST_SIZE] {
    impl_wrapper!(Sha512, key, message)
}

/// Wrapper for obtaining the HMAC-SHA-384 digest for a complete message.
pub fn hmac_sha384(key: &[u8], message: &[u8]) -> [u8; Sha384::DIGEST_SIZE] {
    impl_wrapper!(Sha384, key, message)
}

/// Wrapper for obtaining the HMAC-SHA-256 digest for a complete message.
pub fn hmac_sha256(key: &[u8], message: &[u8]) -> [u8; Sha256::DIGEST_SIZE] {
    impl_wrapper!(Sha256, key, message)
}

/// Wrapper for obtaining the HMAC-SHA-224 digest for a complete message.
pub fn hmac_sha224(key: &[u8], message: &[u8]) -> [u8; Sha224::DIGEST_SIZE] {
    impl_wrapper!(Sha224, key, message)
}

impl<H: HashFunction> Hmac<H> {
    /// Initializes an HMAC function given a key.
    pub fn new(key: &[u8]) -> Self {
        let mut hashed_key;
        let new_key;
        if key.len() > H::BLOCK_SIZE {
            hashed_key = [0; MAX_DIGEST_SIZE];
            let mut hash_function = H::default();
            hash_function.update(key);
            hash_function.write_digest(&mut hashed_key[..H::DIGEST_SIZE]);
            new_key = &hashed_key[..H::DIGEST_SIZE];
        } else {
            new_key = key;
        }
        Self {
            inner_hash_function: Self::keyed_hash_function(new_key, IPAD),
            outer_hash_function: Self::keyed_hash_function(new_key, OPAD),
        }
    }

    /// Feeds input into the function to update its state.
    pub fn update(&mut self, input: &[u8]) {
        self.inner_hash_function.update(input);
    }

    /// Writes the digest into an output buffer.
    ///
    /// # Panics
    ///
    /// Panics if `output.len()` is not equal to the digest size.
    pub fn write_digest(mut self, output: &mut [u8]) {
        assert_eq!(H::DIGEST_SIZE, output.len());
        self.inner_hash_function.write_digest(output);
        self.outer_hash_function.update(output);
        self.outer_hash_function.write_digest(output);
    }

    fn keyed_hash_function(key: &[u8], pad: u8) -> H {
        let mut hash_function = H::default();
        for byte in key {
            hash_function.update(&[byte ^ pad]);
        }
        for _ in key.len()..H::BLOCK_SIZE {
            hash_function.update(&[pad]);
        }
        hash_function
    }
}

#[cfg(test)]
mod tests {
    use std::vec::Vec;
    use super::*;
    use test_helpers::*;

    fn check(exp512: &str, exp384: &str, exp256: &str, exp224: &str, key: &[u8], data: &[u8]) {
        macro_rules! check { ($function:ident, $wrapper:path, $expected:expr) => (
            let expected = h2b($expected);
            let actual = $wrapper(key, data);
            assert_eq!(expected, actual.to_vec());

            let actual = &mut vec![0; expected.len()];
            let mut hmac = Hmac::<$function>::new(key);
            for word in data.chunks(4) {
                hmac.update(word);
            }
            hmac.write_digest(actual);
            assert_eq!(expected, actual.to_vec());
        )}

        check!(Sha512, hmac_sha512, exp512);
        check!(Sha384, hmac_sha384, exp384);
        check!(Sha256, hmac_sha256, exp256);
        check!(Sha224, hmac_sha224, exp224);
    }

    #[test]
    fn test_digest() {
        let key = &h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
        let data = b"Hi There";
        let exp512 = "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde\
                      daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854";
        let exp384 = "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c\
                      faea9ea9076ede7f4af152e8b2fa9cb6";
        let exp256 = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7";
        let exp224 = "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22";
        check(exp512, exp384, exp256, exp224, key, data);

        let key = b"Jefe";
        let data = b"what do ya want for nothing?";
        let exp512 = "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554\
                      9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737";
        let exp384 = "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e\
                      8e2240ca5e69e2c78b3239ecfab21649";
        let exp256 = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843";
        let exp224 = "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44";
        check(exp512, exp384, exp256, exp224, key, data);

        let key = &[0xaa; 20];
        let data = &[0xdd; 50];
        let exp512 = "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39\
                      bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb";
        let exp384 = "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b\
                      2a5ab39dc13814b94e3ab6e101a34f27";
        let exp256 = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe";
        let exp224 = "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea";
        check(exp512, exp384, exp256, exp224, key, data);

        let key: &Vec<_> = &(0x01..0x1a).collect();
        let data = &[0xcd; 50];
        let exp512 = "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db\
                      a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd";
        let exp384 = "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e\
                      6801dd23c4a7d679ccf8a386c674cffb";
        let exp256 = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b";
        let exp224 = "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a";
        check(exp512, exp384, exp256, exp224, key, data);

        let key = &[0xaa; 131];
        let data = b"Test Using Larger Than Block-Size Key - Hash Key First";
        let exp512 = "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352\
                      6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598";
        let exp384 = "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6\
                      0c2ef6ab4030fe8296248df163f44952";
        let exp256 = "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54";
        let exp224 = "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e";
        check(exp512, exp384, exp256, exp224, key, data);

        let data =
            b"This is a test using a larger than block-size key and a larger than block-\
              size data. The key needs to be hashed before being used by the HMAC algorithm.";
        let exp512 = "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944\
                      b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58";
        let exp384 = "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5\
                      a678cc31e799176d3860e6110c46523e";
        let exp256 = "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2";
        let exp224 = "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1";
        check(exp512, exp384, exp256, exp224, key, data);
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("{}", check());
}

fn check() -> bool {
    std::mem::size_of::<usize>() == 8
}

#[test]
fn ok() {
    assert!(check());
}
<commit_msg>Use cfg<commit_after>fn main() {
    println!("{}", check());
}

#[cfg(target_arch = "x86_64")]
fn check() -> bool {
    std::mem::size_of::<usize>() == 8
}

#[cfg(target_arch = "i686")]
fn check() -> bool {
    std::mem::size_of::<usize>() == 4
}

#[test]
fn ok() {
    assert!(check());
}
<|endoftext|>


<commit_before>extern crate cargo;
extern crate rustc_serialize;

use cargo::core::Package;
use cargo::core::Workspace;
use cargo::ops;
use cargo::util::Config;

use std::env;
use std::fmt;
use std::path;
use std::io::Read;

#[derive(RustcDecodable)]
struct Options {
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_frozen: bool,
    flag_locked: bool,
}

#[derive(Debug)]
enum Licenses {
    Licenses(Vec<String>),
    File(String),
    Missing,
}

impl fmt::Display for Licenses {
    fn fmt(self: &Self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Licenses::File(_) => Ok(write!(f, "Specified in license file")?),
            Licenses::Missing => Ok(write!(f, "Missing")?),
            Licenses::Licenses(ref lic_names) => Ok(write!(f, "{}", lic_names.join(", "))?),
        }
    }
}

const USAGE_STR: &'static str = r#"
Produce Bill of Materials from Cargo project's depencies
Usage:
    cargo bom [options]
Options:
    -h, --help               Print this message
    -V, --version            Print version information
    -v, --verbose ...        Use verbose output
    --frozen                 Require Cargo.lock and cache are up to date
    --locked                 Require Cargo.lock is up to date
    --color WHEN             Coloring: auto, always, never
This cargo subcommand will produce Bill of Materials (BOM) from crates the
project depends on.
"#;

fn main() {
    let config = Config::default().expect("cargo config");
    let args: Vec<String> = env::args().collect();

    let res = cargo::call_main_without_stdin(real_main, &config, USAGE_STR, &args, false);
    if let Err(e) = res {
        cargo::exit_with_error(e, &mut *config.shell());
    }
}

fn real_main(options: Options, config: &Config) -> cargo::CliResult {
    config.configure(options.flag_verbose,
                     options.flag_quiet,
                     &options.flag_color,
                     options.flag_frozen,
                     options.flag_locked)?;

    let manifest = config.cwd().join("Cargo.toml");
    let ws = Workspace::new(&manifest, config)?;
    let (package_ids, resolve) = ops::resolve_ws(&ws)?;

    let mut packages: Vec<(String, String, String, Vec<path::PathBuf>)> = Vec::new();
    let mut longest_name = 0;
    for package_id in resolve.iter() {
        let package = package_ids.get(package_id)?;
        let name = package.name().to_owned();
        let version = format!("{}", package.version());
        let licenses = format!("{}", package_licenses(package));
        let license_files = package_license_files(package);
        longest_name = std::cmp::max(longest_name, name.len());
        packages.push((name, version, licenses, license_files));
    }

    packages.sort();

    right_pad_print(longest_name, "Name", "Version", "Licenses");
    println!("{:-<80}", "");

    for (name, version, licenses, _) in packages.clone() {
        right_pad_print(longest_name, &name, &version, &licenses);
    }

    println!("");

    for (name, version, _, license_files) in packages {
        if license_files.is_empty() {
            continue;
        }

        println!("-----BEGIN {} {} LICENSES-----", name, version);

        let mut buf = String::new();
        for file in license_files {
            let mut fs = std::fs::File::open(file).expect("File::open");
            fs.read_to_string(&mut buf).expect("read_to_string");
            println!("{}", buf);
            buf.clear();
        }

        println!("-----END {} {} LICENSES-----", name, version);
        println!("");
    }

    Ok(())
}

fn package_licenses(package: &Package) -> Licenses {
    let metadata = package.manifest().metadata();

    if let Some(ref license_str) = metadata.license {
        let mut licenses: Vec<String> = license_str
            .split('/')
            .map(|s| s.trim().to_owned())
            .collect();
        licenses.dedup();
        licenses.sort();
        return Licenses::Licenses(licenses);
    }

    if let Some(ref license_file) = metadata.license_file {
        return Licenses::File(license_file.to_owned());
    }

    Licenses::Missing
}

fn package_license_files(package: &Package) -> Vec<path::PathBuf> {
    let mut result = Vec::new();

    if let Some(path) = package.manifest_path().parent() {
        for entry in path.read_dir().expect("read_dir call failed") {
            if let Ok(entry) = entry {
                if let Ok(name) = entry.file_name().into_string() {
                    if name.starts_with("LICENSE") {
                        result.push(entry.path())
                    }
                }
            }
        }
    }

    result
}

fn right_pad_print(longest_name: usize, name: &str, version: &str, licenses: &str) {
    if longest_name <= 8 {
        println!("{:<8} | {:<8} | {}", name, version, licenses);
    } else if longest_name <= 16 {
        println!("{:<16} | {:<8} | {}", name, version, licenses);
    } else if longest_name <= 24 {
        println!("{:<24} | {:<8} | {}", name, version, licenses);
    } else {
        println!("{:<32} | {:<8} | {}", name, version, licenses);
    }
}
<commit_msg>First sort, then deduplicate.<commit_after>extern crate cargo;
extern crate rustc_serialize;

use cargo::core::Package;
use cargo::core::Workspace;
use cargo::ops;
use cargo::util::Config;

use std::env;
use std::fmt;
use std::path;
use std::io::Read;

#[derive(RustcDecodable)]
struct Options {
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_frozen: bool,
    flag_locked: bool,
}

#[derive(Debug)]
enum Licenses {
    Licenses(Vec<String>),
    File(String),
    Missing,
}

impl fmt::Display for Licenses {
    fn fmt(self: &Self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Licenses::File(_) => Ok(write!(f, "Specified in license file")?),
            Licenses::Missing => Ok(write!(f, "Missing")?),
            Licenses::Licenses(ref lic_names) => Ok(write!(f, "{}", lic_names.join(", "))?),
        }
    }
}

const USAGE_STR: &'static str = r#"
Produce Bill of Materials from Cargo project's depencies
Usage:
    cargo bom [options]
Options:
    -h, --help               Print this message
    -V, --version            Print version information
    -v, --verbose ...        Use verbose output
    --frozen                 Require Cargo.lock and cache are up to date
    --locked                 Require Cargo.lock is up to date
    --color WHEN             Coloring: auto, always, never
This cargo subcommand will produce Bill of Materials (BOM) from crates the
project depends on.
"#;

fn main() {
    let config = Config::default().expect("cargo config");
    let args: Vec<String> = env::args().collect();

    let res = cargo::call_main_without_stdin(real_main, &config, USAGE_STR, &args, false);
    if let Err(e) = res {
        cargo::exit_with_error(e, &mut *config.shell());
    }
}

fn real_main(options: Options, config: &Config) -> cargo::CliResult {
    config.configure(options.flag_verbose,
                     options.flag_quiet,
                     &options.flag_color,
                     options.flag_frozen,
                     options.flag_locked)?;

    let manifest = config.cwd().join("Cargo.toml");
    let ws = Workspace::new(&manifest, config)?;
    let (package_ids, resolve) = ops::resolve_ws(&ws)?;

    let mut packages: Vec<(String, String, String, Vec<path::PathBuf>)> = Vec::new();
    let mut longest_name = 0;
    for package_id in resolve.iter() {
        let package = package_ids.get(package_id)?;
        let name = package.name().to_owned();
        let version = format!("{}", package.version());
        let licenses = format!("{}", package_licenses(package));
        let license_files = package_license_files(package);
        longest_name = std::cmp::max(longest_name, name.len());
        packages.push((name, version, licenses, license_files));
    }

    packages.sort();

    right_pad_print(longest_name, "Name", "Version", "Licenses");
    println!("{:-<80}", "");

    for (name, version, licenses, _) in packages.clone() {
        right_pad_print(longest_name, &name, &version, &licenses);
    }

    println!("");

    for (name, version, _, license_files) in packages {
        if license_files.is_empty() {
            continue;
        }

        println!("-----BEGIN {} {} LICENSES-----", name, version);

        let mut buf = String::new();
        for file in license_files {
            let mut fs = std::fs::File::open(file).expect("File::open");
            fs.read_to_string(&mut buf).expect("read_to_string");
            println!("{}", buf);
            buf.clear();
        }

        println!("-----END {} {} LICENSES-----", name, version);
        println!("");
    }

    Ok(())
}

fn package_licenses(package: &Package) -> Licenses {
    let metadata = package.manifest().metadata();

    if let Some(ref license_str) = metadata.license {
        let mut licenses: Vec<String> = license_str
            .split('/')
            .map(|s| s.trim().to_owned())
            .collect();
        licenses.sort();
        licenses.dedup();
        return Licenses::Licenses(licenses);
    }

    if let Some(ref license_file) = metadata.license_file {
        return Licenses::File(license_file.to_owned());
    }

    Licenses::Missing
}

fn package_license_files(package: &Package) -> Vec<path::PathBuf> {
    let mut result = Vec::new();

    if let Some(path) = package.manifest_path().parent() {
        for entry in path.read_dir().expect("read_dir call failed") {
            if let Ok(entry) = entry {
                if let Ok(name) = entry.file_name().into_string() {
                    if name.starts_with("LICENSE") {
                        result.push(entry.path())
                    }
                }
            }
        }
    }

    result
}

fn right_pad_print(longest_name: usize, name: &str, version: &str, licenses: &str) {
    if longest_name <= 8 {
        println!("{:<8} | {:<8} | {}", name, version, licenses);
    } else if longest_name <= 16 {
        println!("{:<16} | {:<8} | {}", name, version, licenses);
    } else if longest_name <= 24 {
        println!("{:<24} | {:<8} | {}", name, version, licenses);
    } else {
        println!("{:<32} | {:<8} | {}", name, version, licenses);
    }
}
<|endoftext|>


<commit_before>extern crate z80e_core_rust;
extern crate goss;

mod mmu;
mod stdio_dev;
mod disk;
mod debug;

use mmu::{ Memory, MMU };
use stdio_dev::{ StdioDevice };

use disk::{ Disk, Protection };
use z80e_core_rust::Cpu;

use debug::DebugDevice;

use std::io::{ Read, Write };
use std::str::FromStr;
use std::env;
use std::fs::File;
use std::sync::{ Arc };
use std::sync::atomic::{ AtomicBool, Ordering };
use std::time::Duration;
use std::thread;

struct BankImage {
    name: String,
    bank: usize,
    file: File,
}

const NUM_BANKS: u8 = 1;
const DIE_TIMEOUT_SECS: u64 = 1;
const DIE_TIMEOUT_NANOS: u32 = 0;

pub trait ConcurrentDevice {
    fn run(&mut self, die: Arc<AtomicBool>, timeout: Duration);
}

fn main() {
    let mut num_banks = NUM_BANKS;
    let mut stderr = std::io::stderr();
    let memory;
    let mut mmu;
    {
        let mut images: Vec<BankImage> = Vec::new();
        match goss::getopt(env::args(), "l:n:") {
            Ok(mut got_opt) => {
                for opt in got_opt.opts {
                    match opt.switch {
                        'n' => {
                            let arg = opt.argument.unwrap();
                            num_banks = match usize::from_str(&arg[..]) {
                                Ok(x) => {
                                    if x > u8::max_value() as usize {
                                        let _ = writeln!(stderr, "-n: Bad argument: {}", arg);
                                        panic!("Bank too big. (max: {})", u8::max_value() as usize);
                                    }
                                    x as u8
                                },
                                Err(err) => {
                                    let _ = writeln!(stderr, "-n: Bad argument: {} ← {}", arg, err);
                                    panic!("Unable to comprehend number.")
                                }
                            }
                        },
                        'l' => {
                            let mut bank = 0;
                            let arg = opt.argument.unwrap();
                            let subopts: Vec<&str> = arg.split('=').collect();
                            let file_name;
                            if subopts.len() > 1 {
                                match usize::from_str(&(subopts[0])[..]) {
                                    Ok(x) => bank = x,
                                    Err(err) => {
                                        let _ = writeln!(stderr, "-l: Bad argument: {} → {} ← {}", arg, subopts[0], err);
                                        panic!("Unable to comprehend number.");
                                    },
                                }
                                file_name = subopts[1].clone();
                            } else {
                                file_name = subopts[0].clone();
                            }
                            let mut file = match File::open(file_name) {
                                Ok(file) => file,
                                Err(err) => {
                                    let _ = writeln!(stderr, "-l: Unable to open image: {} → {}", file_name, err);
                                    panic!("I/O error.");
                                },
                            };
                            images.push(BankImage {
                                name: file_name.to_string(),
                                bank: bank,
                                file: file,
                            });
                        },
                        switch @ _ => { let _ = writeln!(stderr, "Unhandled switch: -{}", switch); },
                    }
                }
                match got_opt.rest.next() {
                    Some(x) => {
                        let _ = writeln!(stderr, "Excess argument: {}", x);
                        panic!("You specified an argument no switch was expecting.");
                    },
                    None => (),
                }
            },
            Err(err) => {
                match err {
                    goss::Error::BadOptionString => {
                        let _ = writeln!(stderr, "GOSS is broken.");
                        panic!("The option parsing library claims we're using it wrong.'");
                    },
                    goss::Error::UnknownSwitch(switch) => {
                        let _ = writeln!(stderr, "Unknown switch: {}", switch);
                        panic!("You have specified an unrecognized switch.");
                    },
                    goss::Error::MissingArgument(switch) => {
                        let _ = writeln!(stderr, "Missing argument to -{}.", switch);
                        panic!("You didn't specify a required optarg or you messed up your switch order.");
                    },
                }
            },
        }
        memory = Memory::new(num_banks);
        mmu = MMU::new(memory.clone());
        let mut bank_0_initialized = false;
        for image in images.iter_mut() {
            if image.bank >= num_banks as usize {
                let _ = writeln!(stderr, "Invalid bank: {} for image {}", image.bank, image.name);
                panic!("Total number of banks too low for index. (Number of banks: {})", num_banks);
            }
            let mut image_temp: Vec<u8> = Vec::new();
            match image.file.read_to_end(&mut image_temp) {
                Ok(_) => {
                    if image_temp.len() > mmu::BANK_SIZE {
                        let _ = writeln!(stderr, "Invalid image: {}", image.name);
                        panic!("The file is too large for the bank size ({} bytes).", mmu::BANK_SIZE);
                    }
                },
                Err(err) => {
                    let _ = writeln!(stderr, "-l: Read error: {}", err);
                    panic!("Unable to read bank image.");
                }
            }
            let mut bank = match memory.banks[image.bank].lock() {
                Ok(x) => x,
                Err(err) => {
                    let _ = writeln!(stderr, "-l: Mutex error: {}", err);
                    panic!("Unable to acquire mutex for bank {}.", image.bank);
                }
            };
            for i in 0..image_temp.len() {
                bank[i] = image_temp[i];
            }
            if image.bank == 0 { bank_0_initialized = true; };
        }
        if !bank_0_initialized {
            let _ = writeln!(stderr, "Memory not ready.");
            panic!("You must load an image for bank 0. (-l)")
        }
    }
    let mut cpu = Cpu::new(&mut mmu);
    cpu.install_device(0, &mut mmu.bank_registers[0]);
    cpu.install_device(1, &mut mmu.bank_registers[1]);
    cpu.install_device(2, &mut mmu.bank_registers[2]);
    cpu.install_device(3, &mut mmu.bank_registers[3]);

    let device = StdioDevice::new();
    cpu.install_device(4, &mut device.get_control_port());
    cpu.install_device(5, &mut device.get_data_port());

    cpu.install_device(6, &mut DebugDevice::new());

    let disk_controller = disk::DiskController::new();
    cpu.install_device(7, &mut disk_controller.status_port());
    cpu.install_device(8, &mut disk_controller.data_port());

    let die = Arc::new(AtomicBool::new(false));
    let timeout = Duration::new(DIE_TIMEOUT_SECS, DIE_TIMEOUT_NANOS);
    let mut device_threads = Vec::new();
    {
        let mut reader = device.get_reader();
        let die = die.clone();
        let timeout = timeout.clone();
        device_threads.push(thread::spawn(move || reader.run(die, timeout)));
    }
    {
        let mut writer = device.get_writer();
        let die = die.clone();
        let timeout = timeout.clone();
        device_threads.push(thread::spawn(move || writer.run(die, timeout)));
    }
    {
        let mut device = disk_controller.clone();
        let die = die.clone();
        let timeout = timeout.clone();
        device_threads.push(thread::spawn(move || device.run(die, timeout)));
    }

    let cpu = Arc::new(&cpu);
    let _ = cpu.execute(0);
    die.store(true, Ordering::Release);
    println!("Waiting for all threads to quit… (Press Enter if they don't. [StdioReader is broken.])");
    for thread in device_threads {
        let _ = thread.join().unwrap();
    }
    println!("Exiting successfully.")
}
<commit_msg>Don't wait for StdioReader to die. It won't.<commit_after>extern crate z80e_core_rust;
extern crate goss;

mod mmu;
mod stdio_dev;
mod disk;
mod debug;

use mmu::{ Memory, MMU };
use stdio_dev::{ StdioDevice };

use disk::{ Disk, Protection };
use z80e_core_rust::Cpu;

use debug::DebugDevice;

use std::io::{ Read, Write };
use std::str::FromStr;
use std::env;
use std::fs::File;
use std::sync::{ Arc };
use std::sync::atomic::{ AtomicBool, Ordering };
use std::time::Duration;
use std::thread;

struct BankImage {
    name: String,
    bank: usize,
    file: File,
}

const NUM_BANKS: u8 = 1;
const DIE_TIMEOUT_SECS: u64 = 1;
const DIE_TIMEOUT_NANOS: u32 = 0;

pub trait ConcurrentDevice {
    fn run(&mut self, die: Arc<AtomicBool>, timeout: Duration);
}

fn main() {
    let mut num_banks = NUM_BANKS;
    let mut stderr = std::io::stderr();
    let memory;
    let mut mmu;
    {
        let mut images: Vec<BankImage> = Vec::new();
        match goss::getopt(env::args(), "l:n:") {
            Ok(mut got_opt) => {
                for opt in got_opt.opts {
                    match opt.switch {
                        'n' => {
                            let arg = opt.argument.unwrap();
                            num_banks = match usize::from_str(&arg[..]) {
                                Ok(x) => {
                                    if x > u8::max_value() as usize {
                                        let _ = writeln!(stderr, "-n: Bad argument: {}", arg);
                                        panic!("Bank too big. (max: {})", u8::max_value() as usize);
                                    }
                                    x as u8
                                },
                                Err(err) => {
                                    let _ = writeln!(stderr, "-n: Bad argument: {} ← {}", arg, err);
                                    panic!("Unable to comprehend number.")
                                }
                            }
                        },
                        'l' => {
                            let mut bank = 0;
                            let arg = opt.argument.unwrap();
                            let subopts: Vec<&str> = arg.split('=').collect();
                            let file_name;
                            if subopts.len() > 1 {
                                match usize::from_str(&(subopts[0])[..]) {
                                    Ok(x) => bank = x,
                                    Err(err) => {
                                        let _ = writeln!(stderr, "-l: Bad argument: {} → {} ← {}", arg, subopts[0], err);
                                        panic!("Unable to comprehend number.");
                                    },
                                }
                                file_name = subopts[1].clone();
                            } else {
                                file_name = subopts[0].clone();
                            }
                            let mut file = match File::open(file_name) {
                                Ok(file) => file,
                                Err(err) => {
                                    let _ = writeln!(stderr, "-l: Unable to open image: {} → {}", file_name, err);
                                    panic!("I/O error.");
                                },
                            };
                            images.push(BankImage {
                                name: file_name.to_string(),
                                bank: bank,
                                file: file,
                            });
                        },
                        switch @ _ => { let _ = writeln!(stderr, "Unhandled switch: -{}", switch); },
                    }
                }
                match got_opt.rest.next() {
                    Some(x) => {
                        let _ = writeln!(stderr, "Excess argument: {}", x);
                        panic!("You specified an argument no switch was expecting.");
                    },
                    None => (),
                }
            },
            Err(err) => {
                match err {
                    goss::Error::BadOptionString => {
                        let _ = writeln!(stderr, "GOSS is broken.");
                        panic!("The option parsing library claims we're using it wrong.'");
                    },
                    goss::Error::UnknownSwitch(switch) => {
                        let _ = writeln!(stderr, "Unknown switch: {}", switch);
                        panic!("You have specified an unrecognized switch.");
                    },
                    goss::Error::MissingArgument(switch) => {
                        let _ = writeln!(stderr, "Missing argument to -{}.", switch);
                        panic!("You didn't specify a required optarg or you messed up your switch order.");
                    },
                }
            },
        }
        memory = Memory::new(num_banks);
        mmu = MMU::new(memory.clone());
        let mut bank_0_initialized = false;
        for image in images.iter_mut() {
            if image.bank >= num_banks as usize {
                let _ = writeln!(stderr, "Invalid bank: {} for image {}", image.bank, image.name);
                panic!("Total number of banks too low for index. (Number of banks: {})", num_banks);
            }
            let mut image_temp: Vec<u8> = Vec::new();
            match image.file.read_to_end(&mut image_temp) {
                Ok(_) => {
                    if image_temp.len() > mmu::BANK_SIZE {
                        let _ = writeln!(stderr, "Invalid image: {}", image.name);
                        panic!("The file is too large for the bank size ({} bytes).", mmu::BANK_SIZE);
                    }
                },
                Err(err) => {
                    let _ = writeln!(stderr, "-l: Read error: {}", err);
                    panic!("Unable to read bank image.");
                }
            }
            let mut bank = match memory.banks[image.bank].lock() {
                Ok(x) => x,
                Err(err) => {
                    let _ = writeln!(stderr, "-l: Mutex error: {}", err);
                    panic!("Unable to acquire mutex for bank {}.", image.bank);
                }
            };
            for i in 0..image_temp.len() {
                bank[i] = image_temp[i];
            }
            if image.bank == 0 { bank_0_initialized = true; };
        }
        if !bank_0_initialized {
            let _ = writeln!(stderr, "Memory not ready.");
            panic!("You must load an image for bank 0. (-l)")
        }
    }
    let mut cpu = Cpu::new(&mut mmu);
    cpu.install_device(0, &mut mmu.bank_registers[0]);
    cpu.install_device(1, &mut mmu.bank_registers[1]);
    cpu.install_device(2, &mut mmu.bank_registers[2]);
    cpu.install_device(3, &mut mmu.bank_registers[3]);

    let device = StdioDevice::new();
    cpu.install_device(4, &mut device.get_control_port());
    cpu.install_device(5, &mut device.get_data_port());

    cpu.install_device(6, &mut DebugDevice::new());

    let disk_controller = disk::DiskController::new();
    cpu.install_device(7, &mut disk_controller.status_port());
    cpu.install_device(8, &mut disk_controller.data_port());

    let die = Arc::new(AtomicBool::new(false));
    let timeout = Duration::new(DIE_TIMEOUT_SECS, DIE_TIMEOUT_NANOS);
    let mut device_threads = Vec::new();
    {
        let mut reader = device.get_reader();
        let die = die.clone();
        let timeout = timeout.clone();
        thread::spawn(move || reader.run(die, timeout));
    }
    {
        let mut writer = device.get_writer();
        let die = die.clone();
        let timeout = timeout.clone();
        device_threads.push(thread::spawn(move || writer.run(die, timeout)));
    }
    {
        let mut device = disk_controller.clone();
        let die = die.clone();
        let timeout = timeout.clone();
        device_threads.push(thread::spawn(move || device.run(die, timeout)));
    }

    let cpu = Arc::new(&cpu);
    let _ = cpu.execute(0);
    die.store(true, Ordering::Release);
    println!("Waiting for all threads to quit…");
    for thread in device_threads {
        let _ = thread.join().unwrap();
    }
    println!("Exiting successfully.")
}
<|endoftext|>


<commit_before>extern crate regex;

use regex::{Regex,Captures};

/// Calculates the result of the given calculation.
///
/// The calculation may only contain one type of arithmetic operations, either
/// `[+-]` or `[*/]` and may not contain braces.
/// The result will be calculated by replacing the first arithmetic operator and
/// the first two numbers with the result of this calculation.
fn calc(equation:String)->String
{
	let mut equ=equation;
	let split=Regex::new(
		r"(?P<n1>(\d*\.)?\d+)(?P<char>[-+*/])(?P<n2>(\d*\.)?\d+)").unwrap();

	while split.is_match(equ.as_ref())
	{
		equ=split.replace(equ.as_ref(),|cap:&Captures|
		{
			let n1=cap.name("n1").unwrap().parse::<f64>().unwrap();
			let n2=cap.name("n2").unwrap().parse::<f64>().unwrap();
			//TODO: write back different for more accuracy
			format!("{}",match cap.name("char").unwrap()
			{
				"+" => n1+n2,
				"-" => n1-n2,
				"*" => n1*n2,
				"/" => n1/n2,
				_ => unreachable!(),
			})
		});
	}
	equ
}

/// Parses a calculation including the four basic arithmetic operations and
/// braces.
///
/// This function is responsible for dealing with the order of the operations.
/// It firstly recursively disassembles the passed string  based on the braces
/// contained.
/// These parts are being calculated and merged into the former string, which
/// then will not contain braces anymore.
/// Secondly it passes the multiplications and divisions to `calc` and lastly
/// resolves additions and subtractions using, again, `calc`.
fn parse(equation:String)->String
{
	let mut equ=equation;
	let braces=Regex::new(r"\((?P<res>([^()]*|(.*?\(.*?\))+.*?))\)").unwrap();
	let dot=Regex::new(r"((\d*\.)?\d+)([*/]((\d*\.)?\d+))+").unwrap();
	let line=Regex::new(r"((\d*\.)?\d+)([+-]((\d*\.)?\d+))+").unwrap();

	equ=braces.replace_all(equ.as_ref(),
		|cap:&Captures|parse(cap.name("res").unwrap().to_string()));
	equ=dot.replace_all(equ.as_ref(),
		|cap:&Captures|calc(cap.at(0).unwrap().to_string()));
	equ=line.replace_all(equ.as_ref(),
		|cap:&Captures|calc(cap.at(0).unwrap().to_string()));
	equ
}

/// Prepares the commandline arguments for usage with `parse` which then will be
/// called.
///
/// The format of `parse`s argument is the following:
///
/// - no spaces
fn main()
{
	let args:Vec<String>=std::env::args().skip(1).collect();
	let s=args.connect("").replace(" ","");
	println!("{}",parse(s));
}

<commit_msg>minor purrformance improvements<commit_after>extern crate regex;

use regex::{Regex,Captures};

/// Calculates the result of the given calculation.
///
/// The calculation may only contain one type of arithmetic operations, either
/// `[+-]` or `[*/]` and may not contain braces.
/// The result will be calculated by replacing the first arithmetic operator and
/// the first two numbers with the result of this calculation.
fn calc(equation:&str)->String
{
	let mut equ=equation.to_string();
	let split=Regex::new(
		r"(?P<n1>(\d*\.)?\d+)(?P<char>[-+*/])(?P<n2>(\d*\.)?\d+)").unwrap();

	while split.is_match(equ.as_ref())
	{
		equ=split.replace(equ.as_ref(),|cap:&Captures|
		{
			let n1=cap.name("n1").unwrap().parse::<f64>().unwrap();
			let n2=cap.name("n2").unwrap().parse::<f64>().unwrap();
			//TODO: write back different for more accuracy
			match cap.name("char").unwrap()
			{
				"+" => n1+n2,
				"-" => n1-n2,
				"*" => n1*n2,
				"/" => n1/n2,
				_ => unreachable!(),
			}.to_string()
		});
	}
	equ
}

/// Parses a calculation including the four basic arithmetic operations and
/// braces.
///
/// This function is responsible for dealing with the order of the operations.
/// It firstly recursively disassembles the passed string  based on the braces
/// contained.
/// These parts are being calculated and merged into the former string, which
/// then will not contain braces anymore.
/// Secondly it passes the multiplications and divisions to `calc` and lastly
/// resolves additions and subtractions using, again, `calc`.
fn parse(equation:String)->String
{
	let mut equ=equation;
	let braces=Regex::new(r"\((?P<res>([^()]*|(.*?\(.*?\))+.*?))\)").unwrap();
	let dot=Regex::new(r"((\d*\.)?\d+)([*/]((\d*\.)?\d+))+").unwrap();
	let line=Regex::new(r"((\d*\.)?\d+)([+-]((\d*\.)?\d+))+").unwrap();

	equ=braces.replace_all(equ.as_ref(),
		|cap:&Captures|parse(cap.name("res").unwrap().to_string()));
	equ=dot.replace_all(equ.as_ref(),
		|cap:&Captures|calc(cap.at(0).unwrap()));
	equ=line.replace_all(equ.as_ref(),
		|cap:&Captures|calc(cap.at(0).unwrap()));
	equ
}

/// Prepares the commandline arguments for usage with `parse` which then will be
/// called.
///
/// The format of `parse`s argument is the following:
///
/// - no spaces
fn main()
{
	let args:Vec<String>=std::env::args().skip(1).collect();
	let s=args.connect("").replace(" ","");
	println!("{}",parse(s));
}

<|endoftext|>


<commit_before>extern crate regex;
use regex::Regex;

use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Comma,
}

#[derive(Debug, PartialEq, Clone)]
pub enum Function {
	Abs,
    Sqrt,
    Ln,
    Log,
    Sin,
    Csc,
    Cos,
    Sec,
    Tan,
    Cot,
    Asin,
    Acsc,
    Acos,
    Asec,
    Atan,
    Acot,
    Sinh,
    Csch,
    Cosh,
    Sech,
    Tanh,
    Coth,
    Asinh,
    Acsch,
    Acosh,
    Asech,
    Atanh,
    Acoth,
    Max,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Operator {
    Add=0,
    Sub=1,
    Div=2,
    Mul=3,
    Pow=4, // Right
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
}

struct ExpressionIter<'a> {
	expr: &'a Expression,
	count: usize,
}

impl<'a> Iterator for ExpressionIter<'a> {
	type Item = &'a Token;
    fn next(&mut self) -> Option<&'a Token> {
    	let token = self.expr.get_tokens().get(self.count);
    	self.count += 1;
    	token
    }
}

#[allow(dead_code)]
impl Expression {
	fn new(tokens: Vec<Token>) -> Self {
		Expression {tokens: tokens}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn get_token(&self, index: usize) -> &Token {
		self.tokens.get(index).unwrap()
	}

	fn get_mut_token(&mut self, index: usize) -> &mut Token {
		self.tokens.get_mut(index).unwrap()
	}

	fn replace_token(&mut self, index: usize, new_token: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, new_token);
	}

	fn replace_all_tokens(&mut self, new_token: Vec<Token>) {
		self.tokens = new_token
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

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

	fn iter(&self) -> ExpressionIter {
		ExpressionIter {expr: &self, count: 0}
	}
}

fn main() {
	let numeric_regex: Regex = Regex::new(r"\d+\.\d+|\d+").unwrap();
	let function_regex: Regex = Regex::new(r"\w{2,}").unwrap();
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        if let Err(x) = stdin.read_line(&mut input) {
        	println!("There was a problem reading stdin: {:?}", x);
        	print!("Exiting...");;
        	break;
        }
        input = strip_white_space(&input).to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let expr = parse_input(&input, &numeric_regex, &function_regex);
        if expr.is_ok() {
        	println!("{:?}", &expr.unwrap());
        } else {
        	println!("Encountered an error while parsing: {:?}", expr.unwrap_err());
        	println!("Try Again...(type 'quit' to exit)");
        	continue;
        }
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String, numeric_regex: &Regex, function_regex: &Regex) -> Result<Expression, String> {
	// 1. Replace everthing except letters/numbers with their enums
	// 2. Then go through and replace things with Literals or functions
	let mut expr: Expression = Expression::new(Vec::new());
	let mut builder: String = String::new();
	for c in input.chars() {
		match c {
		    '(' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Open);
		    },
		    ')' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Close);
		    },
		    '+' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Add));
		    },
		    '-' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Sub));
		    },
		    '*' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Mul));
		    },
		    '/' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Div));
		    },
		    '^' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Pow));
		    },
		    ',' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Comma);
		    },
		    _ => {
		    	builder.push(c);
		    }
		}
	}
	if builder.len() > 0 {
		if numeric_regex.is_match(&builder[..]) {
			expr.push(Token::Literal(builder.clone()));
		} else if function_regex.is_match(&builder[..]) {
			expr.push(map_string_to_func(&builder));
		}
		builder = String::new();
	}
	let mut op_stack: Vec<Token> = Vec::with_capacity(input.len());
	let mut out_queue: Vec<Token> = Vec::with_capacity(input.len());
	//println!("EXPR {:?}", &expr);
	for i in 0..expr.len() {
		let current_token = expr.get_token(i);
		//println!("BEFORE current_token: {:?}, OPSTACK {:?}, out_queue {:?}", &current_token, &op_stack, &out_queue);
		match current_token {
		    &Token::Literal(ref x) => out_queue.push(Token::Literal(x.clone())),
		    &Token::Func(ref x) => op_stack.push(Token::Func(x.clone())),
		    &Token::Comma => {
		    	let mut found_open = false;
		    	loop {
			    	let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
			    	match stack_token {
			    	    Token::Open => {op_stack.push(stack_token); found_open=true; break;},
			    	    _ => out_queue.push(stack_token),
			    	}
		    	}
		    	if !found_open {return Err(String::from("Mismatch Parenthesis"))}
			},
		    &Token::Op(ref o1) =>  {
		    	loop {
			    	if op_stack.len() < 1 {
						break;
					}
			    	let o2 = try!{op_stack.pop().ok_or("Malformed Expression")}; // top of stack
			    	match o1 {
			    	    &Operator::Pow => match o2 {
			    	    	_ => { op_stack.push(o2); break; },
			    	    },
			    	    &Operator::Mul | &Operator::Div => match o2 {
			    	    	Token::Op(Operator::Pow) | Token::Op(Operator::Mul) | Token::Op(Operator::Div) => out_queue.push(o2),
			    	    	_ => { op_stack.push(o2); break; },
			    	    },
			    	    &Operator::Add | &Operator::Sub => match o2 {
			    	    	Token::Op(Operator::Add) | Token::Op(Operator::Sub) => out_queue.push(o2),
			    	    	_ => { op_stack.push(o2); break; },
			    	    }
			    	}
		    	};
		    	op_stack.push(Token::Op(o1.clone()));
			},
			&Token::Open => op_stack.push(Token::Open),
			&Token::Close => {
				let mut found_open = false;
				loop {
					let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
					match stack_token {
						Token::Open => {op_stack.push(stack_token); found_open=true; break;},
						_ => out_queue.push(stack_token),
					}
				};
				if !found_open {return Err(String::from("Mismatch Parenthesis"))}
				let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
				let next_stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
				match next_stack_token {
					Token::Func(ref x) => out_queue.push(Token::Func(x.clone())),
					_ => op_stack.push(next_stack_token),
				}
			},
			&Token::Unknown(ref x) => {
				let mut message: String = "You either misspelled a function, or it is not yet implemented. The unknown string was: ".to_owned();
				message.push_str(x);
				return Err(message);
			},
		    _ => break,
		}
		//println!("AFTER current_token: {:?}, OPSTACK {:?}, out_queue {:?}\n\n\n", &current_token, &op_stack, &out_queue);
	}
	//println!("OPSTACK {:?}", &op_stack);
	while op_stack.len() > 0 {
	    out_queue.push(try!{op_stack.pop().ok_or("Malformed Expression")});
	}
	Ok(Expression::new(out_queue))
}

fn map_string_to_func(input: &String) -> Token {
	match &(input.to_lowercase())[..] {
		"abs" => Token::Func(Function::Abs),
	    "sqrt" => Token::Func(Function::Sqrt),
	    "ln" => Token::Func(Function::Ln),
	    "log" => Token::Func(Function::Log),
	    "sin" => Token::Func(Function::Sin),
	    "csc" => Token::Func(Function::Csc),
	    "cos" => Token::Func(Function::Cos),
	    "sec" => Token::Func(Function::Sec),
	    "tan" => Token::Func(Function::Tan),
	    "cot" => Token::Func(Function::Cot),
	    "asin" => Token::Func(Function::Asin),
	    "acsc" => Token::Func(Function::Acsc),
	    "acos" => Token::Func(Function::Acos),
	    "asec" => Token::Func(Function::Asec),
	    "atan" => Token::Func(Function::Atan),
	    "acot" => Token::Func(Function::Acot),
	    "sinh" => Token::Func(Function::Sinh),
	    "csch" => Token::Func(Function::Csch),
	    "cosh" => Token::Func(Function::Cosh),
	    "sech" => Token::Func(Function::Sech),
	    "tanh" => Token::Func(Function::Tanh),
	    "coth" => Token::Func(Function::Coth),
	    "asinh" => Token::Func(Function::Asinh),
	    "acsch" => Token::Func(Function::Acsch),
	    "acosh" => Token::Func(Function::Acosh),
	    "asech" => Token::Func(Function::Asech),
	    "atanh" => Token::Func(Function::Atanh),
	    "acoth" => Token::Func(Function::Acoth),
	    "max" => Token::Func(Function::Max),
	    _ => Token::Unknown(input.clone()),
	}
}<commit_msg>Allow dead code everywhere, only for now<commit_after>#![allow(dead_code)]

extern crate regex;
use regex::Regex;

use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Comma,
}

#[derive(Debug, PartialEq, Clone)]
pub enum Function {
	Abs,
    Sqrt,
    Ln,
    Log,
    Sin,
    Csc,
    Cos,
    Sec,
    Tan,
    Cot,
    Asin,
    Acsc,
    Acos,
    Asec,
    Atan,
    Acot,
    Sinh,
    Csch,
    Cosh,
    Sech,
    Tanh,
    Coth,
    Asinh,
    Acsch,
    Acosh,
    Asech,
    Atanh,
    Acoth,
    Max,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Operator {
    Add=0,
    Sub=1,
    Div=2,
    Mul=3,
    Pow=4, // Right
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
}

struct ExpressionIter<'a> {
	expr: &'a Expression,
	count: usize,
}

impl<'a> Iterator for ExpressionIter<'a> {
	type Item = &'a Token;
    fn next(&mut self) -> Option<&'a Token> {
    	let token = self.expr.get_tokens().get(self.count);
    	self.count += 1;
    	token
    }
}

impl Expression {
	fn new(tokens: Vec<Token>) -> Self {
		Expression {tokens: tokens}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn get_token(&self, index: usize) -> &Token {
		self.tokens.get(index).unwrap()
	}

	fn get_mut_token(&mut self, index: usize) -> &mut Token {
		self.tokens.get_mut(index).unwrap()
	}

	fn replace_token(&mut self, index: usize, new_token: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, new_token);
	}

	fn replace_all_tokens(&mut self, new_token: Vec<Token>) {
		self.tokens = new_token
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

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

	fn iter(&self) -> ExpressionIter {
		ExpressionIter {expr: &self, count: 0}
	}
}

fn main() {
	let numeric_regex: Regex = Regex::new(r"\d+\.\d+|\d+").unwrap();
	let function_regex: Regex = Regex::new(r"\w{2,}").unwrap();
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        if let Err(x) = stdin.read_line(&mut input) {
        	println!("There was a problem reading stdin: {:?}", x);
        	print!("Exiting...");;
        	break;
        }
        input = strip_white_space(&input).to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let expr = parse_input(&input, &numeric_regex, &function_regex);
        if expr.is_ok() {
        	println!("{:?}", &expr.unwrap());
        } else {
        	println!("Encountered an error while parsing: {:?}", expr.unwrap_err());
        	println!("Try Again...(type 'quit' to exit)");
        	continue;
        }
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String, numeric_regex: &Regex, function_regex: &Regex) -> Result<Expression, String> {
	// 1. Replace everthing except letters/numbers with their enums
	// 2. Then go through and replace things with Literals or functions
	let mut expr: Expression = Expression::new(Vec::new());
	let mut builder: String = String::new();
	for c in input.chars() {
		match c {
		    '(' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Open);
		    },
		    ')' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Close);
		    },
		    '+' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Add));
		    },
		    '-' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Sub));
		    },
		    '*' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Mul));
		    },
		    '/' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Div));
		    },
		    '^' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Pow));
		    },
		    ',' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Comma);
		    },
		    _ => {
		    	builder.push(c);
		    }
		}
	}
	if builder.len() > 0 {
		if numeric_regex.is_match(&builder[..]) {
			expr.push(Token::Literal(builder.clone()));
		} else if function_regex.is_match(&builder[..]) {
			expr.push(map_string_to_func(&builder));
		}
		builder = String::new();
	}
	let mut op_stack: Vec<Token> = Vec::with_capacity(input.len());
	let mut out_queue: Vec<Token> = Vec::with_capacity(input.len());
	//println!("EXPR {:?}", &expr);
	for i in 0..expr.len() {
		let current_token = expr.get_token(i);
		//println!("BEFORE current_token: {:?}, OPSTACK {:?}, out_queue {:?}", &current_token, &op_stack, &out_queue);
		match current_token {
		    &Token::Literal(ref x) => out_queue.push(Token::Literal(x.clone())),
		    &Token::Func(ref x) => op_stack.push(Token::Func(x.clone())),
		    &Token::Comma => {
		    	let mut found_open = false;
		    	loop {
			    	let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
			    	match stack_token {
			    	    Token::Open => {op_stack.push(stack_token); found_open=true; break;},
			    	    _ => out_queue.push(stack_token),
			    	}
		    	}
		    	if !found_open {return Err(String::from("Mismatch Parenthesis"))}
			},
		    &Token::Op(ref o1) =>  {
		    	loop {
			    	if op_stack.len() < 1 {
						break;
					}
			    	let o2 = try!{op_stack.pop().ok_or("Malformed Expression")}; // top of stack
			    	match o1 {
			    	    &Operator::Pow => match o2 {
			    	    	_ => { op_stack.push(o2); break; },
			    	    },
			    	    &Operator::Mul | &Operator::Div => match o2 {
			    	    	Token::Op(Operator::Pow) | Token::Op(Operator::Mul) | Token::Op(Operator::Div) => out_queue.push(o2),
			    	    	_ => { op_stack.push(o2); break; },
			    	    },
			    	    &Operator::Add | &Operator::Sub => match o2 {
			    	    	Token::Op(Operator::Add) | Token::Op(Operator::Sub) => out_queue.push(o2),
			    	    	_ => { op_stack.push(o2); break; },
			    	    }
			    	}
		    	};
		    	op_stack.push(Token::Op(o1.clone()));
			},
			&Token::Open => op_stack.push(Token::Open),
			&Token::Close => {
				let mut found_open = false;
				loop {
					let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
					match stack_token {
						Token::Open => {op_stack.push(stack_token); found_open=true; break;},
						_ => out_queue.push(stack_token),
					}
				};
				if !found_open {return Err(String::from("Mismatch Parenthesis"))}
				let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
				let next_stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
				match next_stack_token {
					Token::Func(ref x) => out_queue.push(Token::Func(x.clone())),
					_ => op_stack.push(next_stack_token),
				}
			},
			&Token::Unknown(ref x) => {
				let mut message: String = "You either misspelled a function, or it is not yet implemented. The unknown string was: ".to_owned();
				message.push_str(x);
				return Err(message);
			},
		    _ => break,
		}
		//println!("AFTER current_token: {:?}, OPSTACK {:?}, out_queue {:?}\n\n\n", &current_token, &op_stack, &out_queue);
	}
	//println!("OPSTACK {:?}", &op_stack);
	while op_stack.len() > 0 {
	    out_queue.push(try!{op_stack.pop().ok_or("Malformed Expression")});
	}
	Ok(Expression::new(out_queue))
}

fn map_string_to_func(input: &String) -> Token {
	match &(input.to_lowercase())[..] {
		"abs" => Token::Func(Function::Abs),
	    "sqrt" => Token::Func(Function::Sqrt),
	    "ln" => Token::Func(Function::Ln),
	    "log" => Token::Func(Function::Log),
	    "sin" => Token::Func(Function::Sin),
	    "csc" => Token::Func(Function::Csc),
	    "cos" => Token::Func(Function::Cos),
	    "sec" => Token::Func(Function::Sec),
	    "tan" => Token::Func(Function::Tan),
	    "cot" => Token::Func(Function::Cot),
	    "asin" => Token::Func(Function::Asin),
	    "acsc" => Token::Func(Function::Acsc),
	    "acos" => Token::Func(Function::Acos),
	    "asec" => Token::Func(Function::Asec),
	    "atan" => Token::Func(Function::Atan),
	    "acot" => Token::Func(Function::Acot),
	    "sinh" => Token::Func(Function::Sinh),
	    "csch" => Token::Func(Function::Csch),
	    "cosh" => Token::Func(Function::Cosh),
	    "sech" => Token::Func(Function::Sech),
	    "tanh" => Token::Func(Function::Tanh),
	    "coth" => Token::Func(Function::Coth),
	    "asinh" => Token::Func(Function::Asinh),
	    "acsch" => Token::Func(Function::Acsch),
	    "acosh" => Token::Func(Function::Acosh),
	    "asech" => Token::Func(Function::Asech),
	    "atanh" => Token::Func(Function::Atanh),
	    "acoth" => Token::Func(Function::Acoth),
	    "max" => Token::Func(Function::Max),
	    _ => Token::Unknown(input.clone()),
	}
}<|endoftext|>


<commit_before>extern crate ansi_term;
extern crate docopt;
extern crate rustc_serialize;

use ansi_term::Colour;
use docopt::Docopt;

use std::fs;
use std::path;

const USAGE: &'static str = "
srch, a command-line file search utility written in Rust.

Usage:
    srch [options] <pattern>
    srch --help
    srch --version

Options:
    -h, --help      Show this help screen
    -v, --version   Show this program's version
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_pattern: String,
}

fn main() {
    let args: Args = Docopt::new(USAGE).unwrap()
                            .help(true)
                            .version(Some(String::from("srch, version ") + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")))
                            .decode()
                            .unwrap_or_else(|e| e.exit());

    let curdir = path::PathBuf::from("./");
    explore(&curdir, &args.arg_pattern).unwrap();
}

fn ignore (path: &path::PathBuf) -> bool {
    let fname = path.file_name();
    if fname == None {
        return false
    }

    let fname = fname.unwrap().to_str().unwrap();
    if fname.chars().next().unwrap() == '.' {
        return true
    }

    false
}

trait Misc {
    fn is_dir(&self) -> bool;
    fn display_colour(&self) -> String;
    fn matches(&self, pattern: &String) -> bool;
}

impl Misc for path::PathBuf {
    fn is_dir(&self) -> bool {
        fs::metadata(self).unwrap().is_dir()
    }

    fn display_colour(&self) -> String {
        let s: &str = self.to_str().unwrap();

        if self.is_dir() {
            Colour::Yellow.bold().paint(s).to_string()
        } else {
            s.to_string()
        }
    }

    fn matches(&self, pattern: &String) -> bool {
        let fname = self.file_name();
        if fname == None {
            return false
        }

        let fname = fname.unwrap().to_str().unwrap().to_string();
        if fname == *pattern {
            return true
        }
        false
    }
}

fn explore(path: &path::PathBuf, pattern: &String) -> std::io::Result<()> {
    if !path.is_dir() || ignore(&path) {
        return Ok(())
    }

    let mut q: Vec<path::PathBuf> = Vec::new();
    for item in try!(fs::read_dir(path)) {
        let f = try!(item); // f is a DirEntry
        if f.path().is_dir() {
            q.push(f.path());
        };
        if f.path().matches(&pattern) {
            println!("{}", f.path().display_colour());
        }
    }

    for d in q {
        try!(explore(&d, &pattern));
    }
    Ok(())
}
<commit_msg>Improve error handling<commit_after>extern crate ansi_term;
extern crate docopt;
extern crate rustc_serialize;

use ansi_term::Colour;
use docopt::Docopt;

use std::fs;
use std::io;
use std::path;

const USAGE: &'static str = "
srch, a command-line file search utility written in Rust.

Usage:
    srch [options] <pattern>
    srch --help
    srch --version

Options:
    -h, --help      Show this help screen
    -v, --version   Show this program's version
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_pattern: String,
}

fn main() {
    let args: Args = Docopt::new(USAGE).unwrap()
                            .help(true)
                            .version(Some(String::from("srch, version ") + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")))
                            .decode()
                            .unwrap_or_else(|e| e.exit());

    let curdir = path::PathBuf::from("./");
    handle(&curdir, &args.arg_pattern);
}

fn ignore (path: &path::PathBuf) -> bool {
    let fname = path.file_name();
    if fname == None {
        return false
    }

    let fname = fname.unwrap().to_str().unwrap();
    if fname.chars().next().unwrap() == '.' {
        return true
    }

    false
}

trait Misc {
    fn is_dir(&self) -> io::Result<bool>;
    fn display_colour(&self) -> io::Result<String>;
    fn matches(&self, pattern: &String) -> bool;
}

impl Misc for path::PathBuf {
    fn is_dir(&self) -> io::Result<bool> {
        let m = try!(fs::metadata(self));
        Ok(m.is_dir())
    }

    fn display_colour(&self) -> io::Result<String> {
        let s: &str = self.to_str().unwrap();

        if try!(self.is_dir()) {
            Ok(Colour::Yellow.bold().paint(s).to_string())
        } else {
            Ok(s.to_string())
        }
    }

    fn matches(&self, pattern: &String) -> bool {
        let fname = self.file_name();
        if fname == None {
            return false
        }

        let fname = fname.unwrap().to_str().unwrap().to_string();
        if fname == *pattern {
            return true
        }
        false
    }
}

fn handle(path: &path::PathBuf, pattern: &String) -> () {
    match explore(path, pattern) {
        Ok(_) => (),
        Err(_) => (),
    }
}

fn explore(path: &path::PathBuf, pattern: &String) -> std::io::Result<()> {
    if !try!(path.is_dir()) || ignore(&path) {
        return Ok(())
    }

    let mut q: Vec<path::PathBuf> = Vec::new();
    for item in try!(fs::read_dir(path)) {
        let f = try!(item); // f is a DirEntry
        if try!(f.path().is_dir()) {
            q.push(f.path());
        };
        if f.path().matches(&pattern) {
            println!("{}", try!(f.path().display_colour()));
        }
    }

    for d in q {
        handle(&d, pattern);
    }
    Ok(())
}
<|endoftext|>


<commit_before>extern crate lancelot;
extern crate log;

use failure::{Error, Fail};
use log::{error, info, trace};
use std::env;
use std::process;

use lancelot::arch::*;
use lancelot::workspace::Workspace;

// TODO: removeme
use goblin::{Object};

#[derive(Debug, Fail)]
pub enum MainError {
    #[fail(display = "foo")]
    Foo,
}

pub struct Config {
    pub mode: u8,
    pub filename: String,
}

impl Config {
    pub fn from_args(args: env::Args) -> Result<Config, &'static str> {
        let args: Vec<String> = args.collect();

        if args.len() < 3 {
            return Err("not enough arguments: provide `lancelot.exe 32|64 /path/to/input`");
        }

        let mode = match args[1].as_ref() {
            "32" => 32,
            "64" => 64,
            _ => return Err("invalid mode, pick one of `32` or `64`"),
        };

        let filename = args[2].clone();
        trace!("config: parsed filename: {:?}", filename);

        Ok(Config { mode, filename })
    }
}

pub fn setup_logging(_args: &Config) {
    simplelog::TermLogger::init(simplelog::LevelFilter::Info, simplelog::Config::default())
        .expect("failed to setup logging");
}

pub fn run(args: &Config) -> Result<(), Error> {
    info!("filename: {:?}", args.filename);

    if args.mode == 32 {
        let mut ws = Workspace::<Arch32>::from_file(&args.filename)?.load()?;
    } else if args.mode == 64 {
        let mut ws = Workspace::<Arch64>::from_file(&args.filename)?.load()?;

        if ws.loader.get_name() == "Windows/64/PE" {
            if let Ok(Object::PE(pe)) = Object::parse(&ws.buf) {
                let entry = pe.entry;
                let exports: Vec<usize> = pe.exports.iter()
                    // re-exports are simply strings that point to a `DLL.export_name` ASCII string.
                    // therefore, they're not functions/code.
                    .filter(|exp| exp.reexport.is_none())
                    .map(|exp| exp.rva).collect();

                info!("PE entry: {:#x}", entry);
                ws.make_insn(entry as i64);
                ws.analyze();
                for export in exports.iter() {
                    info!("export: {:#x}", export);
                    ws.make_insn(*export as i64);
                    ws.analyze();
                }
            }
        }
    }

    Ok(())
}

fn main() {
    let args = Config::from_args(env::args()).unwrap_or_else(|err| {
        eprintln!("error parsing arguments: {}", err);
        process::exit(1);
    });

    setup_logging(&args);

    if let Err(e) = run(&args) {
        error!("{:?}", e)
    }
}
<commit_msg>main: consume analysis Result<commit_after>extern crate lancelot;
extern crate log;

use failure::{Error, Fail};
use log::{error, info, trace};
use std::env;
use std::process;

use lancelot::arch::*;
use lancelot::workspace::Workspace;

// TODO: removeme
use goblin::{Object};

#[derive(Debug, Fail)]
pub enum MainError {
    #[fail(display = "foo")]
    Foo,
}

pub struct Config {
    pub mode: u8,
    pub filename: String,
}

impl Config {
    pub fn from_args(args: env::Args) -> Result<Config, &'static str> {
        let args: Vec<String> = args.collect();

        if args.len() < 3 {
            return Err("not enough arguments: provide `lancelot.exe 32|64 /path/to/input`");
        }

        let mode = match args[1].as_ref() {
            "32" => 32,
            "64" => 64,
            _ => return Err("invalid mode, pick one of `32` or `64`"),
        };

        let filename = args[2].clone();
        trace!("config: parsed filename: {:?}", filename);

        Ok(Config { mode, filename })
    }
}

pub fn setup_logging(_args: &Config) {
    simplelog::TermLogger::init(simplelog::LevelFilter::Info, simplelog::Config::default())
        .expect("failed to setup logging");
}

pub fn run(args: &Config) -> Result<(), Error> {
    info!("filename: {:?}", args.filename);

    if args.mode == 32 {
        let mut ws = Workspace::<Arch32>::from_file(&args.filename)?.load()?;
    } else if args.mode == 64 {
        let mut ws = Workspace::<Arch64>::from_file(&args.filename)?.load()?;

        if ws.loader.get_name() == "Windows/64/PE" {
            if let Ok(Object::PE(pe)) = Object::parse(&ws.buf) {
                let entry = pe.entry;
                let exports: Vec<usize> = pe.exports.iter()
                    // re-exports are simply strings that point to a `DLL.export_name` ASCII string.
                    // therefore, they're not functions/code.
                    .filter(|exp| exp.reexport.is_none())
                    .map(|exp| exp.rva).collect();

                info!("PE entry: {:#x}", entry);
                ws.make_insn(entry as i64);
                ws.analyze()?;
                for export in exports.iter() {
                    info!("export: {:#x}", export);
                    ws.make_insn(*export as i64);
                    ws.analyze()?;
                }
            }
        }
    }

    Ok(())
}

fn main() {
    let args = Config::from_args(env::args()).unwrap_or_else(|err| {
        eprintln!("error parsing arguments: {}", err);
        process::exit(1);
    });

    setup_logging(&args);

    if let Err(e) = run(&args) {
        error!("{:?}", e)
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>feat(cli): Add basic CLI arg parsing features<commit_after>use structopt::StructOpt;

/// The CaSILE command line interface, publishing automation level wizard.
#[derive(StructOpt)]
struct Cli {
    /// Activate debug mode
    #[structopt(short, long)]
    debug: bool,

    /// Output verbose feedback where possible
    #[structopt(short, long)]
    verbose: bool,

    /// Primary CaSILE command (try make)
    command: String,
}

fn main() {
    let args = Cli::from_args();
    println!("Insert magic potion!");
}
<|endoftext|>