<commit_before>use crate::{Event, Image, ImageError, MsfIndex, TrackType};

use std::path::Path;

use chdr::{ChdError, ChdFile};
use chdr::metadata::CdTrackInfo;

use log::debug;

use thiserror::Error;

const BYTES_PER_SECTOR: u32 =  2352 + 96;

// TODO: Can we really assume that the first track's pregap is always
// two seconds long?
const FIRST_TRACK_PREGAP: u32 = 150;

#[derive(Debug)]
struct Track {
    start_lba: u32,
    track_type: TrackType,

    // Tracks are padded to multiples of 4 sectors in CHDs.
    // This is the number of padding sectors that has to be taken
    // into account when calculating the LBAs for a particular track.
    padding_offset: u32,
    track_info: CdTrackInfo,
}

#[derive(Debug, Error)]
pub enum ChdImageError {
    #[error(transparent)]
    ChdError(#[from] ChdError),
    #[error("CHD file does not seem like a CDROM image (wrong hunk size)")]
    WrongHunkSize,
    #[error("Wrong buffer size, needs to be 2352 bytes")]
    WrongBufferSize,
    #[error("Unsupported sector format: {0}")]
    UnsupportedSectorFormat(String)
}

pub struct ChdImage {
    chd: ChdFile,
    tracks: Vec<Track>,

    hunk: Vec<u8>,
    current_hunk_no: u32,
    current_lba: u32,
    // Starts counting from 0
    current_track: usize,

    sectors_per_hunk: u32,
}

impl ChdImage {
    pub fn open<P>(path: P) -> Result<ChdImage, ChdImageError>
        where P: AsRef<Path>
    {
        let mut chd = ChdFile::open(path)?;

        if chd.hunk_len() % BYTES_PER_SECTOR != 0 {
            return Err(ChdImageError::WrongHunkSize);
        }

        let mut hunk = vec![0; chd.hunk_len() as usize];
        chd.read_hunk(0, &mut hunk[..])?;

        let sectors_per_hunk = chd.hunk_len() / BYTES_PER_SECTOR;

        let mut tracks = Vec::new();
        if let Ok(chd_tracks) = chd.cd_tracks() {
            let mut current_lba = FIRST_TRACK_PREGAP;
            let mut total_padding = 0;
            for chd_track in chd_tracks {
                let track_type = match chd_track.track_type.as_str() {
                    "MODE1_RAW" => TrackType::Mode1,
                    "MODE2_RAW" => TrackType::Mode2,
                    "AUDIO" => TrackType::Audio,
                    _ => return Err(ChdImageError::UnsupportedSectorFormat(chd_track.track_type)),
                };
                let start_lba = current_lba;
                current_lba += chd_track.frames;
                let padding_offset = total_padding;
                total_padding += chd_track.frames % 4;
                tracks.push(Track {
                    start_lba,
                    track_type,
                    padding_offset,
                    track_info: chd_track
                });
            }
        }

        Ok(ChdImage {
            chd,
            hunk,
            current_hunk_no: 0,
            current_lba: 150,
            current_track: 0,

            sectors_per_hunk,

            tracks,
        })
    }

    fn update_current_track(&mut self, lba: u32) -> Result<(), ImageError> {
        let current_track = &self.tracks[self.current_track];
        let current_track_range_end = current_track.start_lba + current_track.track_info.frames;
        if !(current_track.start_lba..current_track_range_end).contains(&lba) {
            if let Some(index) = self.tracks.iter().position(
                |x| lba >= x.start_lba && lba < (x.start_lba + x.track_info.frames)
            ) {
                self.current_track = index;
                Ok(())
            } else {
                Err(ImageError::OutOfRange)
            }
        } else {
            Ok(())
        }
    }

    fn set_location_lba(&mut self, lba: u32) -> Result<(), ImageError> {
        self.current_lba = lba;
        // TODO: Can we really assume that the first track's pregap is always
        // two seconds long?
        if lba < FIRST_TRACK_PREGAP {
            self.current_track = 0;
            return Ok(());
        }

        self.update_current_track(lba)?;

        let current_track = &self.tracks[self.current_track];

        let lba = lba + current_track.padding_offset - FIRST_TRACK_PREGAP;
        debug!("set_location_lba {}", lba);
        let hunk_no = lba / self.sectors_per_hunk;
        if hunk_no > self.chd.num_hunks() {
            return Err(ImageError::OutOfRange);
        }
        if hunk_no != self.current_hunk_no {
            let res = self.chd.read_hunk(hunk_no, &mut self.hunk[..]);
            if let Err(e) = res {
                return Err(ChdImageError::from(e).into());
            }
            self.current_hunk_no = hunk_no;
        }
        Ok(())
    }
}

impl Image for ChdImage {
    fn num_tracks(&self) -> usize {
        self.tracks.len()
    }

    fn current_subchannel_q_valid(&self) -> bool {
        // TODO
        true
    }

    fn current_track(&self) -> Result<u8, ImageError> {
        Ok(self.current_track as u8 + 1)
    }

    fn current_index(&self) -> Result<u8, ImageError> {
        let current_track = &self.tracks[self.current_track];
        let track_local_lba = self.current_lba - current_track.start_lba;
        let index = if track_local_lba > current_track.track_info.pregap.unwrap_or(0) {
            1
        } else {
            0
        };
        Ok(index)
    }

    fn current_track_local_msf(&self) -> Result<MsfIndex, ImageError> {
        let current_track = &self.tracks[self.current_track];
        let index01_lba =
            current_track.start_lba + current_track.track_info.pregap.unwrap_or(150);

        if self.current_lba < index01_lba {
            // Negative MSFs are (100,0,0) - x
            let reference = 100 * 60 * 75;
            let offset = index01_lba - self.current_lba;
            Ok(MsfIndex::from_lba(reference - offset)?)
        } else {
            Ok(MsfIndex::from_lba(self.current_lba - index01_lba)?)
        }
    }

    fn current_global_msf(&self) -> Result<MsfIndex, ImageError> {
        Ok(MsfIndex::from_lba(self.current_lba)?)
    }

    fn current_track_type(&self) -> Result<TrackType, ImageError> {
        let current_track = &self.tracks[self.current_track];
        Ok(current_track.track_type)
    }

    fn first_track_type(&self) -> TrackType {
        self.tracks.first().unwrap().track_type
    }

    fn track_start(&self, track: u8) -> Result<MsfIndex, ImageError> {
        // Track 0: Special case for PlayStation, return length of whole disc
        // TODO: Make this less ugly?
        if track == 0 {
            let len = self.chd.num_hunks() * self.chd.hunk_len();
            let num_sectors = FIRST_TRACK_PREGAP + len / BYTES_PER_SECTOR;
            Ok(MsfIndex::from_lba(num_sectors)?)
        } else if track <= self.tracks.len() as u8 {
            let track = &self.tracks[track as usize - 1];
            let start_lba_index01 =
                track.start_lba + track.track_info.pregap.unwrap_or(150);
            debug!("track_start: {:?} {:?}", track, MsfIndex::from_lba(start_lba_index01));
            Ok(MsfIndex::from_lba(start_lba_index01)?)
        } else {
            Err(ImageError::OutOfRange)
        }
    }

    fn set_location(&mut self, target: MsfIndex) -> Result<(), ImageError> {
        self.set_location_lba(target.to_lba())
    }

    fn set_location_to_track(&mut self, track: u8) -> Result<(), ImageError> {
        debug!("set_location_to_track {}", track);
        let track_start = self.track_start(track)?;
        self.set_location(track_start)?;
        Ok(())
    }

    fn advance_position(&mut self) -> Result<Option<Event>, ImageError> {
        let res = self.set_location_lba(self.current_lba + 1);
        if let Err(e) = res {
            if let ImageError::OutOfRange = e {
                Ok(Some(Event::EndOfDisc))
            } else {
                Err(e)
            }
        } else {
            Ok(None)
        }
    }

    fn copy_current_sector(&self, buf: &mut[u8]) -> Result<(), ImageError> {
        if buf.len() != 2352 {
            return Err(ChdImageError::WrongBufferSize.into())
        }
        if self.current_lba < FIRST_TRACK_PREGAP {
            buf.fill(0);
            return Ok(());
        }
        let current_track = &self.tracks[self.current_track];
        let current_file_lba = self.current_lba + current_track.padding_offset - FIRST_TRACK_PREGAP;
        let sector_in_hunk = current_file_lba % self.sectors_per_hunk;
        let sector_start = (sector_in_hunk * BYTES_PER_SECTOR) as usize;
        let sector = &self.hunk[sector_start..sector_start + 2352];
        buf.clone_from_slice(sector);

        if self.current_track_type().unwrap() == TrackType::Audio {
            for x in buf.chunks_exact_mut(2) {
                x.swap(0, 1);
            }
        }

        Ok(())
    }
}<commit_msg>Remove handling of CHD track padding<commit_after>use crate::{Event, Image, ImageError, MsfIndex, TrackType};

use std::path::Path;

use chdr::{ChdError, ChdFile};
use chdr::metadata::CdTrackInfo;

use log::debug;

use thiserror::Error;

const BYTES_PER_SECTOR: u32 =  2352 + 96;

// TODO: Can we really assume that the first track's pregap is always
// two seconds long?
const FIRST_TRACK_PREGAP: u32 = 150;

#[derive(Debug)]
struct Track {
    start_lba: u32,
    track_type: TrackType,
    track_info: CdTrackInfo,
}

#[derive(Debug, Error)]
pub enum ChdImageError {
    #[error(transparent)]
    ChdError(#[from] ChdError),
    #[error("CHD file does not seem like a CDROM image (wrong hunk size)")]
    WrongHunkSize,
    #[error("Wrong buffer size, needs to be 2352 bytes")]
    WrongBufferSize,
    #[error("Unsupported sector format: {0}")]
    UnsupportedSectorFormat(String)
}

pub struct ChdImage {
    chd: ChdFile,
    tracks: Vec<Track>,

    hunk: Vec<u8>,
    current_hunk_no: u32,
    current_lba: u32,
    // Starts counting from 0
    current_track: usize,

    sectors_per_hunk: u32,
}

impl ChdImage {
    pub fn open<P>(path: P) -> Result<ChdImage, ChdImageError>
        where P: AsRef<Path>
    {
        let mut chd = ChdFile::open(path)?;

        if chd.hunk_len() % BYTES_PER_SECTOR != 0 {
            return Err(ChdImageError::WrongHunkSize);
        }

        let mut hunk = vec![0; chd.hunk_len() as usize];
        chd.read_hunk(0, &mut hunk[..])?;

        let sectors_per_hunk = chd.hunk_len() / BYTES_PER_SECTOR;

        let mut tracks = Vec::new();
        if let Ok(chd_tracks) = chd.cd_tracks() {
            let mut current_lba = FIRST_TRACK_PREGAP;
            for chd_track in chd_tracks {
                let track_type = match chd_track.track_type.as_str() {
                    "MODE1_RAW" => TrackType::Mode1,
                    "MODE2_RAW" => TrackType::Mode2,
                    "AUDIO" => TrackType::Audio,
                    _ => return Err(ChdImageError::UnsupportedSectorFormat(chd_track.track_type)),
                };
                let start_lba = current_lba;
                current_lba += chd_track.frames;
                tracks.push(Track {
                    start_lba,
                    track_type,
                    track_info: chd_track
                });
            }
        }

        Ok(ChdImage {
            chd,
            hunk,
            current_hunk_no: 0,
            current_lba: 150,
            current_track: 0,

            sectors_per_hunk,

            tracks,
        })
    }

    fn update_current_track(&mut self, lba: u32) -> Result<(), ImageError> {
        let current_track = &self.tracks[self.current_track];
        let current_track_range_end = current_track.start_lba + current_track.track_info.frames;
        if !(current_track.start_lba..current_track_range_end).contains(&lba) {
            if let Some(index) = self.tracks.iter().position(
                |x| lba >= x.start_lba && lba < (x.start_lba + x.track_info.frames)
            ) {
                self.current_track = index;
                Ok(())
            } else {
                Err(ImageError::OutOfRange)
            }
        } else {
            Ok(())
        }
    }

    fn set_location_lba(&mut self, lba: u32) -> Result<(), ImageError> {
        self.current_lba = lba;
        // TODO: Can we really assume that the first track's pregap is always
        // two seconds long?
        if lba < FIRST_TRACK_PREGAP {
            self.current_track = 0;
            return Ok(());
        }

        self.update_current_track(lba)?;

        let lba = lba - FIRST_TRACK_PREGAP;
        debug!("set_location_lba {}", lba);
        let hunk_no = lba / self.sectors_per_hunk;
        if hunk_no > self.chd.num_hunks() {
            return Err(ImageError::OutOfRange);
        }
        if hunk_no != self.current_hunk_no {
            let res = self.chd.read_hunk(hunk_no, &mut self.hunk[..]);
            if let Err(e) = res {
                return Err(ChdImageError::from(e).into());
            }
            self.current_hunk_no = hunk_no;
        }
        Ok(())
    }
}

impl Image for ChdImage {
    fn num_tracks(&self) -> usize {
        self.tracks.len()
    }

    fn current_subchannel_q_valid(&self) -> bool {
        // TODO
        true
    }

    fn current_track(&self) -> Result<u8, ImageError> {
        Ok(self.current_track as u8 + 1)
    }

    fn current_index(&self) -> Result<u8, ImageError> {
        let current_track = &self.tracks[self.current_track];
        let track_local_lba = self.current_lba - current_track.start_lba;
        let index = if track_local_lba > current_track.track_info.pregap.unwrap_or(0) {
            1
        } else {
            0
        };
        Ok(index)
    }

    fn current_track_local_msf(&self) -> Result<MsfIndex, ImageError> {
        let current_track = &self.tracks[self.current_track];
        let index01_lba =
            current_track.start_lba + current_track.track_info.pregap.unwrap_or(150);

        if self.current_lba < index01_lba {
            // Negative MSFs are (100,0,0) - x
            let reference = 100 * 60 * 75;
            let offset = index01_lba - self.current_lba;
            Ok(MsfIndex::from_lba(reference - offset)?)
        } else {
            Ok(MsfIndex::from_lba(self.current_lba - index01_lba)?)
        }
    }

    fn current_global_msf(&self) -> Result<MsfIndex, ImageError> {
        Ok(MsfIndex::from_lba(self.current_lba)?)
    }

    fn current_track_type(&self) -> Result<TrackType, ImageError> {
        let current_track = &self.tracks[self.current_track];
        Ok(current_track.track_type)
    }

    fn first_track_type(&self) -> TrackType {
        self.tracks.first().unwrap().track_type
    }

    fn track_start(&self, track: u8) -> Result<MsfIndex, ImageError> {
        // Track 0: Special case for PlayStation, return length of whole disc
        // TODO: Make this less ugly?
        if track == 0 {
            let len = self.chd.num_hunks() * self.chd.hunk_len();
            let num_sectors = FIRST_TRACK_PREGAP + len / BYTES_PER_SECTOR;
            Ok(MsfIndex::from_lba(num_sectors)?)
        } else if track <= self.tracks.len() as u8 {
            let track = &self.tracks[track as usize - 1];
            let start_lba_index01 =
                track.start_lba + track.track_info.pregap.unwrap_or(150);
            debug!("track_start: {:?} {:?}", track, MsfIndex::from_lba(start_lba_index01));
            Ok(MsfIndex::from_lba(start_lba_index01)?)
        } else {
            Err(ImageError::OutOfRange)
        }
    }

    fn set_location(&mut self, target: MsfIndex) -> Result<(), ImageError> {
        self.set_location_lba(target.to_lba())
    }

    fn set_location_to_track(&mut self, track: u8) -> Result<(), ImageError> {
        debug!("set_location_to_track {}", track);
        let track_start = self.track_start(track)?;
        self.set_location(track_start)?;
        Ok(())
    }

    fn advance_position(&mut self) -> Result<Option<Event>, ImageError> {
        let res = self.set_location_lba(self.current_lba + 1);
        if let Err(e) = res {
            if let ImageError::OutOfRange = e {
                Ok(Some(Event::EndOfDisc))
            } else {
                Err(e)
            }
        } else {
            Ok(None)
        }
    }

    fn copy_current_sector(&self, buf: &mut[u8]) -> Result<(), ImageError> {
        if buf.len() != 2352 {
            return Err(ChdImageError::WrongBufferSize.into())
        }
        if self.current_lba < FIRST_TRACK_PREGAP {
            buf.fill(0);
            return Ok(());
        }
        let current_file_lba = self.current_lba - FIRST_TRACK_PREGAP;
        let sector_in_hunk = current_file_lba % self.sectors_per_hunk;
        let sector_start = (sector_in_hunk * BYTES_PER_SECTOR) as usize;
        let sector = &self.hunk[sector_start..sector_start + 2352];
        buf.clone_from_slice(sector);

        if self.current_track_type().unwrap() == TrackType::Audio {
            for x in buf.chunks_exact_mut(2) {
                x.swap(0, 1);
            }
        }

        Ok(())
    }
}<|endoftext|>


<commit_before>//! CLI arguments and library Args struct
//!
//! Use `ArgsBuilder` preferentially as that will shield you from breaking changes resulting from
//! added fields and some field type changes.
//!
//! # Examples
//!
//! ```
//! # use watchexec::cli::ArgsBuilder;
//! ArgsBuilder::default()
//!     .cmd(vec!["echo hello world".into()])
//!     .paths(vec![".".into()])
//!     .build()
//!     .expect("mission failed");
//! ```

use crate::error;
use clap::{App, Arg, Error};
use std::{
    ffi::OsString,
    path::{PathBuf, MAIN_SEPARATOR},
    process::Command,
};

/// Arguments to the watcher
#[derive(Builder, Clone, Debug)]
#[builder(setter(into, strip_option))]
#[builder(build_fn(validate = "Self::validate"))]
pub struct Args {
    /// Command to execute in popen3 format (first program, rest arguments).
    pub cmd: Vec<String>,
    /// List of paths to watch for changes.
    pub paths: Vec<PathBuf>,
    /// Positive filters (trigger only on matching changes). Glob format.
    #[builder(default)]
    pub filters: Vec<String>,
    /// Negative filters (do not trigger on matching changes). Glob format.
    #[builder(default)]
    pub ignores: Vec<String>,
    /// Clear the screen before each run.
    #[builder(default)]
    pub clear_screen: bool,
    /// If Some, send that signal (e.g. SIGHUP) to the child on change.
    #[builder(default)]
    pub signal: Option<String>,
    /// If true, kill the child if it's still running when a change comes in.
    #[builder(default)]
    pub restart: bool,
    /// Interval to debounce the changes. (milliseconds)
    #[builder(default = "500")]
    pub debounce: u64,
    /// Enable debug/verbose logging.
    #[builder(default)]
    pub debug: bool,
    /// Run the commands right after starting.
    #[builder(default = "true")]
    pub run_initially: bool,
    /// Do not wrap the commands in a shell.
    #[builder(default)]
    pub no_shell: bool,
    /// Ignore metadata changes.
    #[builder(default)]
    pub no_meta: bool,
    /// Do not set WATCHEXEC_*_PATH environment variables for child process.
    #[builder(default)]
    pub no_environment: bool,
    /// Skip auto-loading .gitignore files
    #[builder(default)]
    pub no_vcs_ignore: bool,
    /// Skip auto-loading .ignore files
    #[builder(default)]
    pub no_ignore: bool,
    /// For testing only, always set to false.
    #[builder(setter(skip))]
    #[builder(default)]
    pub once: bool,
    /// Force using the polling backend.
    #[builder(default)]
    pub poll: bool,
    /// Interval for polling. (milliseconds)
    #[builder(default = "2")]
    pub poll_interval: u32,
    #[builder(default)]
    pub watch_when_idle: bool,
}

impl ArgsBuilder {
    fn validate(&self) -> Result<(), String> {
        if self.cmd.as_ref().map_or(true, Vec::is_empty) {
            return Err("cmd must not be empty".into());
        }

        if self.paths.as_ref().map_or(true, Vec::is_empty) {
            return Err("paths must not be empty".into());
        }

        Ok(())
    }
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cmd")
        .arg("/c")
        .arg("tput reset || cls")
        .status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("tput").arg("reset").status();
}

pub fn get_args() -> error::Result<Args> {
    get_args_impl(None::<&[&str]>)
}

pub fn get_args_from<I, T>(from: I) -> error::Result<Args>
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    get_args_impl(Some(from))
}

fn get_args_impl<I, T>(from: Option<I>) -> error::Result<Args>
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    let app = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("command")
                 .help("Command to execute")
                 .multiple(true)
                 .required(true))
        .arg(Arg::with_name("extensions")
                 .help("Comma-separated list of file extensions to watch (js,css,html)")
                 .short("e")
                 .long("exts")
                 .takes_value(true))
        .arg(Arg::with_name("path")
                 .help("Watch a specific directory")
                 .short("w")
                 .long("watch")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true))
        .arg(Arg::with_name("clear")
                 .help("Clear screen before executing command")
                 .short("c")
                 .long("clear"))
        .arg(Arg::with_name("restart")
                 .help("Restart the process if it's still running")
                 .short("r")
                 .long("restart"))
        .arg(Arg::with_name("signal")
                 .help("Send signal to process upon changes, e.g. SIGHUP")
                 .short("s")
                 .long("signal")
                 .takes_value(true)
                 .number_of_values(1)
                 .value_name("signal"))
        .arg(Arg::with_name("kill")
                 .help("Send SIGKILL to child processes (deprecated, use -s SIGKILL instead)")
                 .short("k")
                 .long("kill"))
        .arg(Arg::with_name("debounce")
                 .help("Set the timeout between detected change and command execution, defaults to 500ms")
                 .takes_value(true)
                 .value_name("milliseconds")
                 .short("d")
                 .long("debounce"))
        .arg(Arg::with_name("verbose")
                 .help("Print debugging messages to stderr")
                 .short("v")
                 .long("verbose"))
        .arg(Arg::with_name("filter")
                 .help("Ignore all modifications except those matching the pattern")
                 .short("f")
                 .long("filter")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("ignore")
                 .help("Ignore modifications to paths matching the pattern")
                 .short("i")
                 .long("ignore")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
                 .help("Skip auto-loading of .gitignore files for filtering")
                 .long("no-vcs-ignore"))
        .arg(Arg::with_name("no-ignore")
                 .help("Skip auto-loading of ignore files (.gitignore, .ignore, etc.) for filtering")
                 .long("no-ignore"))
        .arg(Arg::with_name("no-default-ignore")
                 .help("Skip auto-ignoring of commonly ignored globs")
                 .long("no-default-ignore"))
        .arg(Arg::with_name("postpone")
                 .help("Wait until first change to execute command")
                 .short("p")
                 .long("postpone"))
        .arg(Arg::with_name("poll")
                 .help("Force polling mode (interval in milliseconds)")
                 .long("force-poll")
                 .value_name("interval"))
        .arg(Arg::with_name("no-shell")
                 .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
                 .short("n")
                 .long("no-shell"))
        .arg(Arg::with_name("no-meta")
                 .help("Ignore metadata changes")
                 .long("no-meta"))
        .arg(Arg::with_name("no-environment")
                 .help("Do not set WATCHEXEC_*_PATH environment variables for child process")
                 .long("no-environment"))
        .arg(Arg::with_name("once").short("1").hidden(true))
        .arg(Arg::with_name("watch-when-idle")
                 .help("Ignore events while the process is still running")
                 .short("W")
                 .long("watch-when-idle"));

    let args = match from {
        None => app.get_matches(),
        Some(i) => app.get_matches_from(i),
    };

    let cmd: Vec<String> = values_t!(args.values_of("command"), String)?;
    let paths = values_t!(args.values_of("path"), String)
        .unwrap_or_else(|_| vec![".".into()])
        .iter()
        .map(|string_path| string_path.into())
        .collect();

    // Treat --kill as --signal SIGKILL (for compatibility with older syntax)
    let signal = if args.is_present("kill") {
        Some("SIGKILL".to_string())
    } else {
        // Convert Option<&str> to Option<String>
        args.value_of("signal").map(str::to_string)
    };

    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or_else(|_| Vec::new());

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',').filter_map(|ext| {
                if ext.is_empty() {
                    None
                } else {
                    Some(format!("*.{}", ext.replace(".", "")))
                }
            }));
        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![
        format!("**{}.DS_Store", MAIN_SEPARATOR),
        String::from("*.py[co]"),
        String::from("#*#"),
        String::from(".#*"),
        String::from(".*.kate-swp"),
        String::from(".*.sw?"),
        String::from(".*.sw?x"),
        format!("**{}.git{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("**{}.hg{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("**{}.svn{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
    ];

    if args.occurrences_of("no-default-ignore") == 0 {
        ignores.extend(default_ignores)
    };
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or_else(|_| Vec::new()));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    let debounce = if args.occurrences_of("debounce") > 0 {
        value_t!(args.value_of("debounce"), u64).unwrap_or_else(|e| e.exit())
    } else {
        500
    };

    if signal.is_some() && args.is_present("postpone") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--postpone and --signal are mutually exclusive".to_string())
            .exit();
    }

    if signal.is_some() && args.is_present("kill") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--kill and --signal is ambiguous.\n       Hint: Use only '--signal SIGKILL' without --kill".to_string())
            .exit();
    }

    Ok(Args {
        cmd,
        paths,
        filters,
        ignores,
        signal,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debounce,
        debug: args.is_present("verbose"),
        run_initially: !args.is_present("postpone"),
        no_shell: args.is_present("no-shell"),
        no_meta: args.is_present("no-meta"),
        no_environment: args.is_present("no-environment"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        no_ignore: args.is_present("no-ignore"),
        once: args.is_present("once"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval,
        watch_when_idle: args.is_present("watch-when-idle"),
    })
}
<commit_msg>Add soft deprecation on Args.debug<commit_after>//! CLI arguments and library Args struct
//!
//! Use `ArgsBuilder` preferentially as that will shield you from breaking changes resulting from
//! added fields and some field type changes.
//!
//! # Examples
//!
//! ```
//! # use watchexec::cli::ArgsBuilder;
//! ArgsBuilder::default()
//!     .cmd(vec!["echo hello world".into()])
//!     .paths(vec![".".into()])
//!     .build()
//!     .expect("mission failed");
//! ```

use crate::error;
use clap::{App, Arg, Error};
use std::{
    ffi::OsString,
    path::{PathBuf, MAIN_SEPARATOR},
    process::Command,
};

/// Arguments to the watcher
#[derive(Builder, Clone, Debug)]
#[builder(setter(into, strip_option))]
#[builder(build_fn(validate = "Self::validate"))]
pub struct Args {
    /// Command to execute in popen3 format (first program, rest arguments).
    pub cmd: Vec<String>,
    /// List of paths to watch for changes.
    pub paths: Vec<PathBuf>,
    /// Positive filters (trigger only on matching changes). Glob format.
    #[builder(default)]
    pub filters: Vec<String>,
    /// Negative filters (do not trigger on matching changes). Glob format.
    #[builder(default)]
    pub ignores: Vec<String>,
    /// Clear the screen before each run.
    #[builder(default)]
    pub clear_screen: bool,
    /// If Some, send that signal (e.g. SIGHUP) to the child on change.
    #[builder(default)]
    pub signal: Option<String>,
    /// If true, kill the child if it's still running when a change comes in.
    #[builder(default)]
    pub restart: bool,
    /// Interval to debounce the changes. (milliseconds)
    #[builder(default = "500")]
    pub debounce: u64,
    /// Enable debug/verbose logging. No longer used as of 1.14.0 (soft-deprecated).
    ///
    /// Debug messages are printed via debug! so configure your logger appropriately instead.
    #[builder(default)]
    pub debug: bool,
    /// Run the commands right after starting.
    #[builder(default = "true")]
    pub run_initially: bool,
    /// Do not wrap the commands in a shell.
    #[builder(default)]
    pub no_shell: bool,
    /// Ignore metadata changes.
    #[builder(default)]
    pub no_meta: bool,
    /// Do not set WATCHEXEC_*_PATH environment variables for child process.
    #[builder(default)]
    pub no_environment: bool,
    /// Skip auto-loading .gitignore files
    #[builder(default)]
    pub no_vcs_ignore: bool,
    /// Skip auto-loading .ignore files
    #[builder(default)]
    pub no_ignore: bool,
    /// For testing only, always set to false.
    #[builder(setter(skip))]
    #[builder(default)]
    pub once: bool,
    /// Force using the polling backend.
    #[builder(default)]
    pub poll: bool,
    /// Interval for polling. (milliseconds)
    #[builder(default = "2")]
    pub poll_interval: u32,
    #[builder(default)]
    pub watch_when_idle: bool,
}

impl ArgsBuilder {
    fn validate(&self) -> Result<(), String> {
        if self.cmd.as_ref().map_or(true, Vec::is_empty) {
            return Err("cmd must not be empty".into());
        }

        if self.paths.as_ref().map_or(true, Vec::is_empty) {
            return Err("paths must not be empty".into());
        }

        Ok(())
    }
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cmd")
        .arg("/c")
        .arg("tput reset || cls")
        .status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("tput").arg("reset").status();
}

pub fn get_args() -> error::Result<Args> {
    get_args_impl(None::<&[&str]>)
}

pub fn get_args_from<I, T>(from: I) -> error::Result<Args>
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    get_args_impl(Some(from))
}

fn get_args_impl<I, T>(from: Option<I>) -> error::Result<Args>
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    let app = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("command")
                 .help("Command to execute")
                 .multiple(true)
                 .required(true))
        .arg(Arg::with_name("extensions")
                 .help("Comma-separated list of file extensions to watch (js,css,html)")
                 .short("e")
                 .long("exts")
                 .takes_value(true))
        .arg(Arg::with_name("path")
                 .help("Watch a specific directory")
                 .short("w")
                 .long("watch")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true))
        .arg(Arg::with_name("clear")
                 .help("Clear screen before executing command")
                 .short("c")
                 .long("clear"))
        .arg(Arg::with_name("restart")
                 .help("Restart the process if it's still running")
                 .short("r")
                 .long("restart"))
        .arg(Arg::with_name("signal")
                 .help("Send signal to process upon changes, e.g. SIGHUP")
                 .short("s")
                 .long("signal")
                 .takes_value(true)
                 .number_of_values(1)
                 .value_name("signal"))
        .arg(Arg::with_name("kill")
                 .help("Send SIGKILL to child processes (deprecated, use -s SIGKILL instead)")
                 .short("k")
                 .long("kill"))
        .arg(Arg::with_name("debounce")
                 .help("Set the timeout between detected change and command execution, defaults to 500ms")
                 .takes_value(true)
                 .value_name("milliseconds")
                 .short("d")
                 .long("debounce"))
        .arg(Arg::with_name("verbose")
                 .help("Print debugging messages to stderr")
                 .short("v")
                 .long("verbose"))
        .arg(Arg::with_name("filter")
                 .help("Ignore all modifications except those matching the pattern")
                 .short("f")
                 .long("filter")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("ignore")
                 .help("Ignore modifications to paths matching the pattern")
                 .short("i")
                 .long("ignore")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
                 .help("Skip auto-loading of .gitignore files for filtering")
                 .long("no-vcs-ignore"))
        .arg(Arg::with_name("no-ignore")
                 .help("Skip auto-loading of ignore files (.gitignore, .ignore, etc.) for filtering")
                 .long("no-ignore"))
        .arg(Arg::with_name("no-default-ignore")
                 .help("Skip auto-ignoring of commonly ignored globs")
                 .long("no-default-ignore"))
        .arg(Arg::with_name("postpone")
                 .help("Wait until first change to execute command")
                 .short("p")
                 .long("postpone"))
        .arg(Arg::with_name("poll")
                 .help("Force polling mode (interval in milliseconds)")
                 .long("force-poll")
                 .value_name("interval"))
        .arg(Arg::with_name("no-shell")
                 .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
                 .short("n")
                 .long("no-shell"))
        .arg(Arg::with_name("no-meta")
                 .help("Ignore metadata changes")
                 .long("no-meta"))
        .arg(Arg::with_name("no-environment")
                 .help("Do not set WATCHEXEC_*_PATH environment variables for child process")
                 .long("no-environment"))
        .arg(Arg::with_name("once").short("1").hidden(true))
        .arg(Arg::with_name("watch-when-idle")
                 .help("Ignore events while the process is still running")
                 .short("W")
                 .long("watch-when-idle"));

    let args = match from {
        None => app.get_matches(),
        Some(i) => app.get_matches_from(i),
    };

    let cmd: Vec<String> = values_t!(args.values_of("command"), String)?;
    let paths = values_t!(args.values_of("path"), String)
        .unwrap_or_else(|_| vec![".".into()])
        .iter()
        .map(|string_path| string_path.into())
        .collect();

    // Treat --kill as --signal SIGKILL (for compatibility with older syntax)
    let signal = if args.is_present("kill") {
        Some("SIGKILL".to_string())
    } else {
        // Convert Option<&str> to Option<String>
        args.value_of("signal").map(str::to_string)
    };

    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or_else(|_| Vec::new());

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',').filter_map(|ext| {
                if ext.is_empty() {
                    None
                } else {
                    Some(format!("*.{}", ext.replace(".", "")))
                }
            }));
        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![
        format!("**{}.DS_Store", MAIN_SEPARATOR),
        String::from("*.py[co]"),
        String::from("#*#"),
        String::from(".#*"),
        String::from(".*.kate-swp"),
        String::from(".*.sw?"),
        String::from(".*.sw?x"),
        format!("**{}.git{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("**{}.hg{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("**{}.svn{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
    ];

    if args.occurrences_of("no-default-ignore") == 0 {
        ignores.extend(default_ignores)
    };
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or_else(|_| Vec::new()));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    let debounce = if args.occurrences_of("debounce") > 0 {
        value_t!(args.value_of("debounce"), u64).unwrap_or_else(|e| e.exit())
    } else {
        500
    };

    if signal.is_some() && args.is_present("postpone") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--postpone and --signal are mutually exclusive".to_string())
            .exit();
    }

    if signal.is_some() && args.is_present("kill") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--kill and --signal is ambiguous.\n       Hint: Use only '--signal SIGKILL' without --kill".to_string())
            .exit();
    }

    Ok(Args {
        cmd,
        paths,
        filters,
        ignores,
        signal,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debounce,
        debug: args.is_present("verbose"),
        run_initially: !args.is_present("postpone"),
        no_shell: args.is_present("no-shell"),
        no_meta: args.is_present("no-meta"),
        no_environment: args.is_present("no-environment"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        no_ignore: args.is_present("no-ignore"),
        once: args.is_present("once"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval,
        watch_when_idle: args.is_present("watch-when-idle"),
    })
}
<|endoftext|>


<commit_before>const INTERPRETER_START: u32 = 0x000;
const INTERPRETER_END: u32 = 0x1FF;
const INTERPRETER_LENGTH: u32 = INTERPRETER_END - INTERPRETER_START;

const FONT_SET_START: usize = 0x050;
const FONT_SET_END: usize = 0x0A0;
const FONT_SET_LENGTH: usize = FONT_SET_END - FONT_SET_START;

const DATA_START: usize = 0x200;
const DATA_END: usize = 0xFFF;
const DATA_LENGTH: usize = DATA_END - DATA_START;

const MEM_LENGTH: usize = 4096;
const STACK_LEVEL: usize = 16;
const REG_NUM: usize = 16;
const GFX_WIDTH: usize = 64;
const GFX_HEIGHT: usize = 32;

const FONTSET: [u8; 80] = [
    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
    0x20, 0x60, 0x20, 0x20, 0x70, // 1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
    0xF0, 0x80, 0xF0, 0x80, 0x80  // F
];

pub fn init() -> Cpu {
    let mut ret = Cpu {
        pc: 0x200,
        opcode: 0,
        memory: vec![0; MEM_LENGTH],
        reg: vec![0; REG_NUM],
        index: 0,
        sp: 0,
        stack: vec![0; STACK_LEVEL],
        // gfx: vec![vec![0; GFX_HEIGHT]; GFX_WIDTH],
        gfx: vec![0; GFX_WIDTH * GFX_HEIGHT],
        delay_timer: 0,
        sound_timer: 0,
        key: vec![0; STACK_LEVEL],
    };
    ret.load_fontset();
    ret
}

#[derive(Debug)]
pub struct Cpu {
    pc: usize,
    opcode: u16,
    memory: Vec<u8>,
    reg: Vec<u8>,
    index: u16,
    // gfx: Vec<Vec<u8>>,
    gfx: Vec<u8>,
    delay_timer: u8,
    sound_timer: u8,
    stack: Vec<usize>,
    sp: usize,
    key: Vec<u8>,
}

impl Cpu {
    fn load_fontset(&mut self) {
        for i in 0..FONT_SET_LENGTH {
            self.memory[FONT_SET_START + i] = FONTSET[i];
        }
    }

    pub fn load_rom(&mut self, rom: Box<[u8]>) {
        for i in 0..rom.len() {
            self.memory[DATA_START + i] = rom[i];
        }
    }

    pub fn emulate_cycle(&mut self) {
        self.opcode = (self.memory[self.pc] as u16) << 8 | (self.memory[self.pc+1] as u16);

        match self.opcode & 0xF000 {
            0x2000 => { // 2NNN: Calls subroutine at NNN
                let addr = self.opcode & 0x0FFF;
                self.stack[self.sp] = self.pc;
                self.sp += 1;
                self.pc = addr as usize;
                println!("pc: {:X}", self.pc);
            },
            0x6000 => { //6XNN: Sets VX to NN
                let index = (self.opcode & 0x0F00) >> 8;
                let val = self.opcode & 0x00FF;
                self.reg[index as usize] = val as u8;
                println!("set V{:X} to: {:X}", index, self.reg[index as usize]);
                self.pc += 2;
            },
            0xA000 => { //ANNN: Sets I to the address NNN
                let val = self.opcode & 0x0FFF;
                self.index = val;
                println!("Set I to: {:X}", self.index);
                self.pc += 2;
            },
            0xD000 => { //DXYN: Draws sprite at cordinate VX, VY with height N
                let x = (self.opcode & 0x0F00) >> 8;
                let y = (self.opcode & 0x00F0) >> 4;
                let n = self.opcode & 0x000F;
                let mut pix: u8;

                let tmp = self.index as usize;
                let sprite = &self.memory[tmp..(tmp + (n as usize))];

                self.reg[0xF] = 0;
                for i in 0..n {
                    pix = (&sprite)[i as usize];
                    for j in 0..8 {
                        if (pix & (0x80 >> j)) != 0 {
                            if self.gfx[(x + j + ((y + i) * 64)) as usize] == 1 {
                                self.reg[0xF] = 1;
                            }
                            self.gfx[(x + j + ((y + i) * 64)) as usize] ^= 1;
                        }
                    }
                }

                println!("gfx: {:?}", self.gfx);
                self.pc += 2;
            }
            _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
        }
    }
}
<commit_msg>Add opcode FX33<commit_after>const INTERPRETER_START: u32 = 0x000;
const INTERPRETER_END: u32 = 0x1FF;
const INTERPRETER_LENGTH: u32 = INTERPRETER_END - INTERPRETER_START;

const FONT_SET_START: usize = 0x050;
const FONT_SET_END: usize = 0x0A0;
const FONT_SET_LENGTH: usize = FONT_SET_END - FONT_SET_START;

const DATA_START: usize = 0x200;
const DATA_END: usize = 0xFFF;
const DATA_LENGTH: usize = DATA_END - DATA_START;

const MEM_LENGTH: usize = 4096;
const STACK_LEVEL: usize = 16;
const REG_NUM: usize = 16;
const GFX_WIDTH: usize = 64;
const GFX_HEIGHT: usize = 32;

const FONTSET: [u8; 80] = [
    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
    0x20, 0x60, 0x20, 0x20, 0x70, // 1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
    0xF0, 0x80, 0xF0, 0x80, 0x80  // F
];

pub fn init() -> Cpu {
    let mut ret = Cpu {
        pc: 0x200,
        opcode: 0,
        memory: vec![0; MEM_LENGTH],
        reg: vec![0; REG_NUM],
        index: 0,
        sp: 0,
        stack: vec![0; STACK_LEVEL],
        // gfx: vec![vec![0; GFX_HEIGHT]; GFX_WIDTH],
        gfx: vec![0; GFX_WIDTH * GFX_HEIGHT],
        delay_timer: 0,
        sound_timer: 0,
        key: vec![0; STACK_LEVEL],
    };
    ret.load_fontset();
    ret
}

#[derive(Debug)]
pub struct Cpu {
    pc: usize,
    opcode: u16,
    memory: Vec<u8>,
    reg: Vec<u8>,
    index: usize,
    // gfx: Vec<Vec<u8>>,
    gfx: Vec<u8>,
    delay_timer: u8,
    sound_timer: u8,
    stack: Vec<usize>,
    sp: usize,
    key: Vec<u8>,
}

impl Cpu {
    fn load_fontset(&mut self) {
        for i in 0..FONT_SET_LENGTH {
            self.memory[FONT_SET_START + i] = FONTSET[i];
        }
    }

    pub fn load_rom(&mut self, rom: Box<[u8]>) {
        for i in 0..rom.len() {
            self.memory[DATA_START + i] = rom[i];
        }
    }

    pub fn emulate_cycle(&mut self) {
        self.opcode = (self.memory[self.pc] as u16) << 8 | (self.memory[self.pc+1] as u16);

        match self.opcode & 0xF000 {
            0x2000 => { // 2NNN: Calls subroutine at NNN
                let addr = self.opcode & 0x0FFF;
                self.stack[self.sp] = self.pc;
                self.sp += 1;
                self.pc = addr as usize;
            },
            0x6000 => { // 6XNN: Sets VX to NN
                let index = (self.opcode & 0x0F00) >> 8;
                let val = self.opcode & 0x00FF;
                self.reg[index as usize] = val as u8;
                self.pc += 2;
            },
            0xA000 => { // ANNN: Sets I to the address NNN
                let val = self.opcode & 0x0FFF;
                self.index = val as usize;
                self.pc += 2;
            },
            0xD000 => { // DXYN: Draws sprite at cordinate VX, VY with height N
                let x = (self.opcode & 0x0F00) >> 8;
                let y = (self.opcode & 0x00F0) >> 4;
                let n = self.opcode & 0x000F;
                let mut pix: u8;

                let tmp = self.index as usize;
                let sprite = &self.memory[tmp..(tmp + (n as usize))];

                self.reg[0xF] = 0;
                for i in 0..n {
                    pix = (&sprite)[i as usize];
                    for j in 0..8 {
                        if (pix & (0x80 >> j)) != 0 {
                            if self.gfx[(x + j + ((y + i) * 64)) as usize] == 1 {
                                self.reg[0xF] = 1;
                            }
                            self.gfx[(x + j + ((y + i) * 64)) as usize] ^= 1;
                        }
                    }
                }
                self.pc += 2;
            },
            0xF000 => {
                match self.opcode & 0x00FF {
                    0x0033 => { // FX33 set memory at I:I+2 to VX
                        let x = self.opcode & 0x0F00 >> 8;
                        let val = self.reg[x as usize];
                        self.memory[self.index] = val / 100;
                        self.memory[self.index + 1] = (val / 10) % 10;
                        self.memory[self.index + 2] = val % 10;
                        self.pc += 2;
                    },
                    _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                }
            },
            _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
        }
    }
}
<|endoftext|>


<commit_before>extern crate cgmath;

pub mod cuboid;
pub mod component;

use self::cgmath::{
    VectorSpace, Rotation,
    Point3, Vector3, Quaternion
};

use core::{Data, EventEmitter, Listener};

use self::component::Component;

use std::any::Any;
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;

/// Holds common virtual world object's properties and components.
pub struct Entity {
    pub position: Point3<f32>,
    pub orientation: Quaternion<f32>,
    pub scale: f32,
    emitter: EventEmitter<Any>,
    components: Vec<Rc<Any>>
}

impl Entity {
    /// Create a new entity.
    pub fn new() -> Entity {
        Entity::from(Point3::new(0.0, 0.0, 0.0), Quaternion::zero(), 1.0)
    }

    /// Create a new entity from properties.
    pub fn from(position: Point3<f32>, orientation: Quaternion<f32>, scale: f32) -> Entity {
        return Entity {
            position: position,
            orientation: orientation,
            scale: scale,
            emitter: EventEmitter::new(),
            components: Vec::new()
        };
    }

    /// Translate the entity `n` units towards it's orientation direction.
    ///
    /// Negative value indicates backwards translation.
    #[inline]
    pub fn move_by(&mut self, units: f32) {
        self.position += units * self.orientation.rotate_vector(Vector3::zero());
    }

    /// Rotate the entity.
    #[inline]
    pub fn look_at(&mut self, dir: Vector3<f32>, up: Vector3<f32>) {
        self.orientation = Quaternion::look_at(dir, up);
    }

    /// Add a component to the entity.
    ///
    /// Returns `Some` if the component is unique for the entity.
    /// Any non unique components will be ignored and `None` will be returned.
    pub fn add<T: Any + Component>(&mut self, component: T) -> Option<Rc<RefCell<T>>> {
        if let None = self.component::<T>() {
            // Wrap the component.
            let wrapped = wrap!(component);

            // Create a weak from the wrapper to clone later.
            let weak = Rc::downgrade(&wrapped);

            // Bypass rust safety checks.
            let this = Data::from(self);

            // Call the component's init method.
            wrapped.borrow_mut().init(self,
                &move |events, closure| {
                    // Create a listener from the given closure.
                    let listener = Listener::<Any>::new(weak.clone(), closure);
                    // Go through the events that the listener wants to listen for.
                    for event in events.into_iter() {
                        // Subscribe the listener to each of those events.
                        this.to::<Entity>().on(event, listener.clone());
                    }
                }
            );

            // Finally take in the wrapped component.
            self.components.push(wrapped.clone());

            return Some(wrapped);
        }

        return None;
    }

    /// Get a component by type.
    pub fn component<T: Any + Component>(&self) -> Option<&RefCell<T>> {
        for component in &self.components {
            if let Some(target) = component.downcast_ref::<RefCell<T>>() {
                return Some(target);
            }
        }

        return None
    }
}

impl Deref for Entity {
    type Target = EventEmitter<Any>;

    fn deref(&self) -> &Self::Target {
        &self.emitter
    }
}

impl DerefMut for Entity {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.emitter
    }
}
<commit_msg>Line endings fix<commit_after>extern crate cgmath;

pub mod cuboid;
pub mod component;

use self::cgmath::{
    VectorSpace, Rotation,
    Point3, Vector3, Quaternion
};

use core::{Data, EventEmitter, Listener};

use self::component::Component;

use std::any::Any;
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;

/// Holds common virtual world object's properties and components.
pub struct Entity {
    pub position: Point3<f32>,
    pub orientation: Quaternion<f32>,
    pub scale: f32,
    emitter: EventEmitter<Any>,
    components: Vec<Rc<Any>>
}

impl Entity {
    /// Create a new entity.
    pub fn new() -> Entity {
        Entity::from(Point3::new(0.0, 0.0, 0.0), Quaternion::zero(), 1.0)
    }

    /// Create a new entity from properties.
    pub fn from(position: Point3<f32>, orientation: Quaternion<f32>, scale: f32) -> Entity {
        return Entity {
            position: position,
            orientation: orientation,
            scale: scale,
            emitter: EventEmitter::new(),
            components: Vec::new()
        };
    }

    /// Translate the entity `n` units towards it's orientation direction.
    ///
    /// Negative value indicates backwards translation.
    #[inline]
    pub fn move_by(&mut self, units: f32) {
        self.position += units * self.orientation.rotate_vector(Vector3::zero());
    }

    /// Rotate the entity.
    #[inline]
    pub fn look_at(&mut self, dir: Vector3<f32>, up: Vector3<f32>) {
        self.orientation = Quaternion::look_at(dir, up);
    }

    /// Add a component to the entity.
    ///
    /// Returns `Some` if the component is unique for the entity.
    /// Any non unique components will be ignored and `None` will be returned.
    pub fn add<T: Any + Component>(&mut self, component: T) -> Option<Rc<RefCell<T>>> {
        if let None = self.component::<T>() {
            // Wrap the component.
            let wrapped = wrap!(component);

            // Create a weak from the wrapper to clone later.
            let weak = Rc::downgrade(&wrapped);

            // Bypass rust safety checks.
            let this = Data::from(self);

            // Call the component's init method.
            wrapped.borrow_mut().init(self,
                &move |events, closure| {
                    // Create a listener from the given closure.
                    let listener = Listener::<Any>::new(weak.clone(), closure);
                    // Go through the events that the listener wants to listen for.
                    for event in events.into_iter() {
                        // Subscribe the listener to each of those events.
                        this.to::<Entity>().on(event, listener.clone());
                    }
                }
            );

            // Finally take in the wrapped component.
            self.components.push(wrapped.clone());

            return Some(wrapped);
        }

        return None;
    }

    /// Get a component by type.
    pub fn component<T: Any + Component>(&self) -> Option<&RefCell<T>> {
        for component in &self.components {
            if let Some(target) = component.downcast_ref::<RefCell<T>>() {
                return Some(target);
            }
        }

        return None
    }
}

impl Deref for Entity {
    type Target = EventEmitter<Any>;

    fn deref(&self) -> &Self::Target {
        &self.emitter
    }
}

impl DerefMut for Entity {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.emitter
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::sync::mpsc::TryRecvError;

use futures::{Future, Poll};
use futures_io::IoFuture;
use mio::channel;

use {ReadinessStream, LoopHandle};

/// The transmission half of a channel used for sending messages to a receiver.
///
/// A `Sender` can be `clone`d to have multiple threads or instances sending
/// messages to one receiver.
///
/// This type is created by the `LoopHandle::channel` method.
pub struct Sender<T> {
    tx: channel::Sender<T>,
}

/// The receiving half of a channel used for processing messages sent by a
/// `Sender`.
///
/// A `Receiver` cannot be cloned and is not `Sync`, so only one thread can
/// receive messages at a time.
///
/// This type is created by the `LoopHandle::channel` method.
pub struct Receiver<T> {
    rx: ReadinessStream<channel::Receiver<T>>,
}

impl LoopHandle {
    /// Creates a new in-memory channel used for sending data across `Send +
    /// 'static` boundaries, frequently threads.
    ///
    /// This type can be used to conveniently send messages between futures.
    /// Unlike the futures crate `channel` method and types, the returned tx/rx
    /// pair is a multi-producer single-consumer (mpsc) channel *with no
    /// backpressure*. Currently it's left up to the application to implement a
    /// mechanism, if necessary, to avoid messages piling up.
    ///
    /// The returned `Sender` can be used to send messages that are processed by
    /// the returned `Receiver`. The `Sender` can be cloned to send messages
    /// from multiple sources simultaneously.
    pub fn channel<T>(self) -> (Sender<T>, IoFuture<Receiver<T>>)
        where T: Send + 'static,
    {
        let (tx, rx) = channel::channel();
        let rx = ReadinessStream::new(self, rx).map(|rx| Receiver { rx: rx });
        (Sender { tx: tx }, rx.boxed())
    }
}

impl<T> Sender<T> {
    /// Sends a message to the corresponding receiver of this sender.
    ///
    /// The message provided will be enqueued on the channel immediately, and
    /// this function will return immediately. Keep in mind that the
    /// underlying channel has infinite capacity, and this may not always be
    /// desired.
    ///
    /// If an I/O error happens while sending the message, or if the receiver
    /// has gone away, then an error will be returned. Note that I/O errors here
    /// are generally quite abnormal.
    pub fn send(&self, t: T) -> io::Result<()> {
        self.tx.send(t).map_err(|e| {
            match e {
                channel::SendError::Io(e) => e,
                channel::SendError::Disconnected(_) => {
                    io::Error::new(io::ErrorKind::Other,
                                   "channel has been disconnected")
                }
            }
        })
    }
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Sender<T> {
        Sender { tx: self.tx.clone() }
    }
}

impl<T> Receiver<T> {
    /// Attempts to receive a message sent on this channel.
    ///
    /// This method will attempt to dequeue any messages sent on this channel
    /// from any corresponding sender. If no message is available, but senders
    /// are still detected, then `Poll::NotReady` is returned and the current
    /// future task is scheduled to receive a notification when a message is
    /// available.
    ///
    /// If an I/O error happens or if all senders have gone away (the channel is
    /// disconnected) then `Poll::Err` will be returned.
    pub fn recv(&self) -> Poll<T, io::Error> {
        match self.rx.get_ref().try_recv() {
            Ok(t) => Poll::Ok(t),
            Err(TryRecvError::Empty) => {
                self.rx.need_read();
                Poll::NotReady
            }
            Err(TryRecvError::Disconnected) => {
                Poll::Err(io::Error::new(io::ErrorKind::Other,
                                         "channel has been disconnected"))
            }
        }
    }
}
<commit_msg>Implement Stream for Receiver<commit_after>use std::io;
use std::sync::mpsc::TryRecvError;

use futures::{Future, Poll};
use futures::stream::Stream;
use futures_io::IoFuture;
use mio::channel;

use {ReadinessStream, LoopHandle};

/// The transmission half of a channel used for sending messages to a receiver.
///
/// A `Sender` can be `clone`d to have multiple threads or instances sending
/// messages to one receiver.
///
/// This type is created by the `LoopHandle::channel` method.
pub struct Sender<T> {
    tx: channel::Sender<T>,
}

/// The receiving half of a channel used for processing messages sent by a
/// `Sender`.
///
/// A `Receiver` cannot be cloned, so only one thread can receive messages at a
/// time.
///
/// This type is created by the `LoopHandle::channel` method and implements the
/// `Stream` trait to represent received messages.
pub struct Receiver<T> {
    rx: ReadinessStream<channel::Receiver<T>>,
}

impl LoopHandle {
    /// Creates a new in-memory channel used for sending data across `Send +
    /// 'static` boundaries, frequently threads.
    ///
    /// This type can be used to conveniently send messages between futures.
    /// Unlike the futures crate `channel` method and types, the returned tx/rx
    /// pair is a multi-producer single-consumer (mpsc) channel *with no
    /// backpressure*. Currently it's left up to the application to implement a
    /// mechanism, if necessary, to avoid messages piling up.
    ///
    /// The returned `Sender` can be used to send messages that are processed by
    /// the returned `Receiver`. The `Sender` can be cloned to send messages
    /// from multiple sources simultaneously.
    pub fn channel<T>(self) -> (Sender<T>, IoFuture<Receiver<T>>)
        where T: Send + 'static,
    {
        let (tx, rx) = channel::channel();
        let rx = ReadinessStream::new(self, rx).map(|rx| Receiver { rx: rx });
        (Sender { tx: tx }, rx.boxed())
    }
}

impl<T> Sender<T> {
    /// Sends a message to the corresponding receiver of this sender.
    ///
    /// The message provided will be enqueued on the channel immediately, and
    /// this function will return immediately. Keep in mind that the
    /// underlying channel has infinite capacity, and this may not always be
    /// desired.
    ///
    /// If an I/O error happens while sending the message, or if the receiver
    /// has gone away, then an error will be returned. Note that I/O errors here
    /// are generally quite abnormal.
    pub fn send(&self, t: T) -> io::Result<()> {
        self.tx.send(t).map_err(|e| {
            match e {
                channel::SendError::Io(e) => e,
                channel::SendError::Disconnected(_) => {
                    io::Error::new(io::ErrorKind::Other,
                                   "channel has been disconnected")
                }
            }
        })
    }
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Sender<T> {
        Sender { tx: self.tx.clone() }
    }
}

impl<T> Stream for Receiver<T> {
    type Item = T;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<T>, io::Error> {
        match self.rx.get_ref().try_recv() {
            Ok(t) => Poll::Ok(Some(t)),
            Err(TryRecvError::Empty) => {
                self.rx.need_read();
                Poll::NotReady
            }
            Err(TryRecvError::Disconnected) => Poll::Ok(None),
        }
    }
}
<|endoftext|>


<commit_before>extern crate user32;
extern crate kernel32;
extern crate winapi;
extern crate gdi32;

use std::ffi::CString;
use std::ptr;
use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;
use std::mem;

use self::winapi::windef::HWND;
use self::winapi::winuser::WS_OVERLAPPEDWINDOW;
use self::winapi::winuser::WNDCLASSW;
use self::winapi::wingdi::BITMAPINFOHEADER;
use self::winapi::wingdi::RGBQUAD;

static mut CLOSE_APP: bool = false;

// Wrap this so we can have a proper numbef of bmiColors to write in
#[repr(C)]
struct BitmapInfo {
     pub bmi_header: BITMAPINFOHEADER,
     pub bmi_colors: [RGBQUAD; 3],
}

unsafe extern "system" fn wnd_proc(window: winapi::HWND, msg: winapi::UINT,
                                   wparam: winapi::WPARAM, lparam: winapi::LPARAM)
                                   -> winapi::LRESULT
{
    match msg {
        winapi::winuser::WM_KEYDOWN => {
            if (wparam & 0xff) == 27 {
                CLOSE_APP = true;
            }
        }

        winapi::winuser::WM_PAINT => {
            let mut rect: winapi::RECT = mem::uninitialized();
            let buffer = user32::GetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA);

            user32::GetClientRect(window, &mut rect);

            let mut bitmap_info: BitmapInfo = mem::zeroed();
            let width = rect.right - rect.left;
            let height = rect.bottom - rect.top;

            bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
            bitmap_info.bmi_header.biPlanes = 1;
            bitmap_info.bmi_header.biBitCount = 32;
            bitmap_info.bmi_header.biCompression = winapi::wingdi::BI_BITFIELDS;
            bitmap_info.bmi_header.biWidth = width;
            bitmap_info.bmi_header.biHeight = -height;
            bitmap_info.bmi_colors[0].rgbRed = 0xff;
            bitmap_info.bmi_colors[1].rgbGreen = 0xff;
            bitmap_info.bmi_colors[2].rgbBlue = 0xff;

            let dc = user32::GetDC(window);

            gdi32::StretchDIBits(dc, 0, 0, width, height, 0, 0, width, height,
                                        mem::transmute(buffer),
                                        mem::transmute(&bitmap_info),
                                        winapi::wingdi::DIB_RGB_COLORS,
                                        winapi::wingdi::SRCCOPY);

            user32::ValidateRect(window, ptr::null_mut());

            user32::ReleaseDC(window, dc);
        }

        _ => (),
    }

    return user32::DefWindowProcW(window, msg, wparam, lparam);
}

pub enum MinifbError {
    UnableToCreateWindow,
}

fn to_wstring(str : &str) -> *const u16 {
    let v : Vec<u16> = OsStr::new(str).encode_wide(). chain(Some(0).into_iter()).collect();
    v.as_ptr()
}

pub struct Minifb {
    window: HWND,
}

impl Minifb {
    fn open_window(name: &str, width: usize, height: usize) -> HWND {
        unsafe {
            let class_name = to_wstring("minifb_window");
            let s = CString::new(name).unwrap();

            let class = WNDCLASSW {
                style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
                lpfnWndProc: Some(wnd_proc),
                cbClsExtra: 0,
                cbWndExtra: 0,
                hInstance: kernel32::GetModuleHandleA(ptr::null()),
                hIcon: ptr::null_mut(),
                hCursor: ptr::null_mut(),
                hbrBackground: ptr::null_mut(),
                lpszMenuName: ptr::null(),
                lpszClassName: class_name,
            };

            user32::RegisterClassW(&class);

            let mut rect = winapi::RECT {
                left: 0, right: width as winapi::LONG,
                top: 0, bottom: height as winapi::LONG,
            };

            user32::AdjustWindowRect(&mut rect, winapi::WS_POPUP | winapi::WS_SYSMENU | winapi::WS_CAPTION, 0);

            rect.right -= rect.left;
            rect.bottom -= rect.top;

            let handle = user32::CreateWindowExA(0,
                "minifb_window".as_ptr() as *mut _, s.as_ptr(),
                winapi::WS_OVERLAPPEDWINDOW & !winapi::WS_MAXIMIZEBOX & !winapi::WS_THICKFRAME,
                winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                rect.right, rect.bottom,
                ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), ptr::null_mut());

            if !handle.is_null() {
                user32::ShowWindow(handle, winapi::SW_NORMAL);
            }

            return handle;
        }
    }

    pub fn new(name: &str, width: usize, height: usize) -> Option<Minifb> {
        let handle = Minifb::open_window(name, width, height);

        match handle.is_null() {
            true => None,
            false => Some(Minifb { window : handle }),
        }
    }

    pub fn update(&mut self, buffer: &[u32]) -> bool {
        unsafe {
            let mut msg = mem::uninitialized();

            user32::SetWindowLongPtrW(self.window, winapi::winuser::GWLP_USERDATA, buffer.as_ptr() as i64);
            user32::InvalidateRect(self.window, ptr::null_mut(), winapi::TRUE);

            while user32::PeekMessageW(&mut msg, self.window, 0, 0, winapi::winuser::PM_REMOVE) != 0 {
                user32::TranslateMessage(&mut msg);
                user32::DispatchMessageW(&mut msg);
            }
        }

        unsafe {
            return !CLOSE_APP;
        }
    }
}

<commit_msg>Ran rustfmt<commit_after>extern crate user32;
extern crate kernel32;
extern crate winapi;
extern crate gdi32;

use std::ffi::CString;
use std::ptr;
use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;
use std::mem;

use self::winapi::windef::HWND;
use self::winapi::winuser::WS_OVERLAPPEDWINDOW;
use self::winapi::winuser::WNDCLASSW;
use self::winapi::wingdi::BITMAPINFOHEADER;
use self::winapi::wingdi::RGBQUAD;

static mut CLOSE_APP: bool = false;

// Wrap this so we can have a proper numbef of bmiColors to write in
#[repr(C)]
struct BitmapInfo {
    pub bmi_header: BITMAPINFOHEADER,
    pub bmi_colors: [RGBQUAD; 3],
}

unsafe extern "system" fn wnd_proc(window: winapi::HWND,
                                   msg: winapi::UINT,
                                   wparam: winapi::WPARAM,
                                   lparam: winapi::LPARAM)
                                   -> winapi::LRESULT {
    match msg {
        winapi::winuser::WM_KEYDOWN => {
            if (wparam & 0xff) == 27 {
                CLOSE_APP = true;
            }
        }

        winapi::winuser::WM_PAINT => {
            let mut rect: winapi::RECT = mem::uninitialized();
            let buffer = user32::GetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA);

            user32::GetClientRect(window, &mut rect);

            let mut bitmap_info: BitmapInfo = mem::zeroed();
            let width = rect.right - rect.left;
            let height = rect.bottom - rect.top;

            bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
            bitmap_info.bmi_header.biPlanes = 1;
            bitmap_info.bmi_header.biBitCount = 32;
            bitmap_info.bmi_header.biCompression = winapi::wingdi::BI_BITFIELDS;
            bitmap_info.bmi_header.biWidth = width;
            bitmap_info.bmi_header.biHeight = -height;
            bitmap_info.bmi_colors[0].rgbRed = 0xff;
            bitmap_info.bmi_colors[1].rgbGreen = 0xff;
            bitmap_info.bmi_colors[2].rgbBlue = 0xff;

            let dc = user32::GetDC(window);

            gdi32::StretchDIBits(dc,
                                 0,
                                 0,
                                 width,
                                 height,
                                 0,
                                 0,
                                 width,
                                 height,
                                 mem::transmute(buffer),
                                 mem::transmute(&bitmap_info),
                                 winapi::wingdi::DIB_RGB_COLORS,
                                 winapi::wingdi::SRCCOPY);

            user32::ValidateRect(window, ptr::null_mut());

            user32::ReleaseDC(window, dc);
        }

        _ => (),
    }

    return user32::DefWindowProcW(window, msg, wparam, lparam);
}

pub enum MinifbError {
    UnableToCreateWindow,
}

fn to_wstring(str: &str) -> *const u16 {
    let v: Vec<u16> = OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect();
    v.as_ptr()
}

pub struct Minifb {
    window: HWND,
}

impl Minifb {
    fn open_window(name: &str, width: usize, height: usize) -> HWND {
        unsafe {
            let class_name = to_wstring("minifb_window");
            let s = CString::new(name).unwrap();

            let class = WNDCLASSW {
                style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
                lpfnWndProc: Some(wnd_proc),
                cbClsExtra: 0,
                cbWndExtra: 0,
                hInstance: kernel32::GetModuleHandleA(ptr::null()),
                hIcon: ptr::null_mut(),
                hCursor: ptr::null_mut(),
                hbrBackground: ptr::null_mut(),
                lpszMenuName: ptr::null(),
                lpszClassName: class_name,
            };

            user32::RegisterClassW(&class);

            let mut rect = winapi::RECT {
                left: 0,
                right: width as winapi::LONG,
                top: 0,
                bottom: height as winapi::LONG,
            };

            user32::AdjustWindowRect(&mut rect,
                                     winapi::WS_POPUP | winapi::WS_SYSMENU | winapi::WS_CAPTION,
                                     0);

            rect.right -= rect.left;
            rect.bottom -= rect.top;

            let handle = user32::CreateWindowExA(0,
                                                 "minifb_window".as_ptr() as *mut _,
                                                 s.as_ptr(),
                                                 winapi::WS_OVERLAPPEDWINDOW &
                                                 !winapi::WS_MAXIMIZEBOX &
                                                 !winapi::WS_THICKFRAME,
                                                 winapi::CW_USEDEFAULT,
                                                 winapi::CW_USEDEFAULT,
                                                 rect.right,
                                                 rect.bottom,
                                                 ptr::null_mut(),
                                                 ptr::null_mut(),
                                                 ptr::null_mut(),
                                                 ptr::null_mut());

            if !handle.is_null() {
                user32::ShowWindow(handle, winapi::SW_NORMAL);
            }

            return handle;
        }
    }

    pub fn new(name: &str, width: usize, height: usize) -> Option<Minifb> {
        let handle = Minifb::open_window(name, width, height);

        match handle.is_null() {
            true => None,
            false => Some(Minifb { window: handle }),
        }
    }

    pub fn update(&mut self, buffer: &[u32]) -> bool {
        unsafe {
            let mut msg = mem::uninitialized();

            user32::SetWindowLongPtrW(self.window,
                                      winapi::winuser::GWLP_USERDATA,
                                      buffer.as_ptr() as i64);
            user32::InvalidateRect(self.window, ptr::null_mut(), winapi::TRUE);

            while user32::PeekMessageW(&mut msg, self.window, 0, 0, winapi::winuser::PM_REMOVE) !=
                  0 {
                user32::TranslateMessage(&mut msg);
                user32::DispatchMessageW(&mut msg);
            }
        }

        unsafe {
            return !CLOSE_APP;
        }
    }
}
<|endoftext|>