<commit_before>// a & a: same side, a & A: Different side
const THEOREM: &'static [&'staic str] = ["
+ + ! +x+
 0  ! x0x
+ + ! +x+
", "
+ + + + ! + + + +
        !   | x
+ + + + ! +x+-+x+
 0 3    ! x0x3|
+ + + + ! +x+-+x+
        !   | x
+ + + + ! + + + +
", "
+ + + ! +x+ + +
 0    ! x0x
+ + + ! +x+-+ +
   3  !   |3 a
+ + + ! + + + +
      !    A
+ + + ! + + + +
", "
+ + + ! + + +
      !   xa
+ + + ! + + +
 3 3  ! |3|3|
+ + + ! + + +
      !   xA
n+ + + ! + + +
", "
+ + + ! +-+ +
 2    !  2xa
+ + + ! + + +
 3 3  ! |3|3|
+ + + ! + + +
      !   xA
+ + + ! + + +
", "
+ + + + + ! + + + + +
          !   x
+ + + + + ! +x+-+ + +
   3      !   |3 a
+ + + + + ! + + + + +
     3    !    A 3|
+ + + + + ! + + +-+x+
          !       x
+ + + + + ! + + + + +
", "
+ + + + + + ! + + + + + +
            !   x     x
+ + + + + + ! +x+-+x+-+x+
   3   3    !   |3 a 3|
+ + + + + + ! + + + + + +
     3      !    A|3|A
+ + + + + + ! + +x+-+x+ +
            !     x x
+ + + + + + ! + + + + + +
", "
+ + + + ! + +x+ +
  | |   !   | |
+ +-+ + ! +x+-+x+
        !   x x
+ + + + ! + + + +
", "
+-+ ! +-+
 1  ! x1x
+ + ! +x+
", "
+-+ ! +-+
x1x ! x1x
+x+ ! +x+
", "
+ + + ! +x+ +
 2|   ! x2|
+-+ + ! +-+x+
      !   x
+ + + ! + + +
", "
+ + ! +x+
|2| ! |2|
+ + ! +x+
", "
+x+ + ! +x+ +
x2    ! x2|
+ + + ! +-+x+
      !   x
+ + + ! + + +
", "
+x+ ! +x+
 2  ! |2|
+x+ ! +x+
", "
+ + + + ! + +x+ +
  |3|   !   |3|
+ +-+ + ! +x+-+x+
        !   x x
+ + + + ! + + + +
", "
+ +x+ + ! + +x+ +
   3    !   |3|
+ + + + ! +x+-+x+
        !   x x
+ + + + ! + + + +
", "
+ + + ! + + +
      !   x
+-+ + ! +-+x+
  |   !   |
+ + + ! + + +
", "
+ + + ! + + +
      !   x
+-+-+ ! +-+-+
      !   x
+ + + ! + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + +x+ +
 a 1    !  ax1 b
+ + + + ! + + + +
        !    B
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
 a 2    !  a 2 A
+ + + + ! + + + +
        !    A
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !   xa
+ + + + ! +x+-+ +
 a 3    !  a|3 b
+ + + + ! + + + +
        !    B
+ + + + ! + + + +
", "
+ + + ! + + +
   a  !    a
+ + + ! + + +
 A 1  !  A 1x
+ + + ! + +x+
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
 A 2    !  A 2 b
+ + + + ! + + + +
        !    B
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
 A 3    !  A 3|
+ + + + ! + +-+x+
        !     x
+ + + + ! + + + +
", "
+ + + ! + + +
  x   !   x
+ + + ! +-+ +
 3 1  !  3 1x
+ + + ! + +x+
", "
+ + + + + ! + + +-+ +
     2x   !    a 2x
+ + + + + ! + + + + +
   3      !   |3 A
+ + + + + ! +x+-+ + +
          !   x
+ + + + + ! + + + + +
", "
+ + + + ! + +-+ +
   2x   !    2x
+ + +-+ ! + + +-+
   3    !   |3
+ + + + ! +x+-+ +
        !   x
+ + + + ! + + + +
", "
+ + + + ! + + +
    |   !     |
+ + + + ! + + +
   3    !   |3
+ + + + ! +x+-+
        !   x
+ + + + ! + + +
", "
+ +  + + ! + +  + +
      a  !       a
+ +  + + ! + +  + +
   3a    !   |3a
+ +  + + ! +x+--+ +
         !   x
+ +  + + ! + +  + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + +x+ +
   1    !  b 1 B
+ + + + ! + +x+ +
   a    !    a
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
   2    !  A 2 A
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + +-+ +
   3    !  b 3 B
+ + + + ! + +-+ +
   a    !    a
+ + + + ! + + + +
", "
+ + ! + +
 a  !  a
+ + ! + +
 1  ! x1x
+ + ! + +
 A  !  A
+ + ! + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
   2    !  b 2 B
+ + + + ! + + + +
   A    !    A
+ + + + ! + + + +
", "
+ + ! + +
 a  !  a
+ + ! + +
 3  ! |3|
+ + ! + +
 A  !  A
+ + ! + +
"];
<commit_msg>theorem: fix typo<commit_after>// a & a: same side, a & A: Different side
const THEOREM: &'static [&'staic str] = ["
+ + ! +x+
 0  ! x0x
+ + ! +x+
", "
+ + + + ! + + + +
        !   | x
+ + + + ! +x+-+x+
 0 3    ! x0x3|
+ + + + ! +x+-+x+
        !   | x
+ + + + ! + + + +
", "
+ + + ! +x+ + +
 0    ! x0x
+ + + ! +x+-+ +
   3  !   |3 a
+ + + ! + + + +
      !    A
+ + + ! + + + +
", "
+ + + ! + + +
      !   xa
+ + + ! + + +
 3 3  ! |3|3|
+ + + ! + + +
      !   xA
+ + + ! + + +
", "
+ + + ! +-+ +
 2    !  2xa
+ + + ! + + +
 3 3  ! |3|3|
+ + + ! + + +
      !   xA
+ + + ! + + +
", "
+ + + + + ! + + + + +
          !   x
+ + + + + ! +x+-+ + +
   3      !   |3 a
+ + + + + ! + + + + +
     3    !    A 3|
+ + + + + ! + + +-+x+
          !       x
+ + + + + ! + + + + +
", "
+ + + + + + ! + + + + + +
            !   x     x
+ + + + + + ! +x+-+x+-+x+
   3   3    !   |3 a 3|
+ + + + + + ! + + + + + +
     3      !    A|3|A
+ + + + + + ! + +x+-+x+ +
            !     x x
+ + + + + + ! + + + + + +
", "
+ + + + ! + +x+ +
  | |   !   | |
+ +-+ + ! +x+-+x+
        !   x x
+ + + + ! + + + +
", "
+-+ ! +-+
 1  ! x1x
+ + ! +x+
", "
+-+ ! +-+
x1x ! x1x
+x+ ! +x+
", "
+ + + ! +x+ +
 2|   ! x2|
+-+ + ! +-+x+
      !   x
+ + + ! + + +
", "
+ + ! +x+
|2| ! |2|
+ + ! +x+
", "
+x+ + ! +x+ +
x2    ! x2|
+ + + ! +-+x+
      !   x
+ + + ! + + +
", "
+x+ ! +x+
 2  ! |2|
+x+ ! +x+
", "
+ + + + ! + +x+ +
  |3|   !   |3|
+ +-+ + ! +x+-+x+
        !   x x
+ + + + ! + + + +
", "
+ +x+ + ! + +x+ +
   3    !   |3|
+ + + + ! +x+-+x+
        !   x x
+ + + + ! + + + +
", "
+ + + ! + + +
      !   x
+-+ + ! +-+x+
  |   !   |
+ + + ! + + +
", "
+ + + ! + + +
      !   x
+-+-+ ! +-+-+
      !   x
+ + + ! + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + +x+ +
 a 1    !  ax1 b
+ + + + ! + + + +
        !    B
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
 a 2    !  a 2 A
+ + + + ! + + + +
        !    A
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !   xa
+ + + + ! +x+-+ +
 a 3    !  a|3 b
+ + + + ! + + + +
        !    B
+ + + + ! + + + +
", "
+ + + ! + + +
   a  !    a
+ + + ! + + +
 A 1  !  A 1x
+ + + ! + +x+
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
 A 2    !  A 2 b
+ + + + ! + + + +
        !    B
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
 A 3    !  A 3|
+ + + + ! + +-+x+
        !     x
+ + + + ! + + + +
", "
+ + + ! + + +
  x   !   x
+ + + ! +-+ +
 3 1  !  3 1x
+ + + ! + +x+
", "
+ + + + + ! + + +-+ +
     2x   !    a 2x
+ + + + + ! + + + + +
   3      !   |3 A
+ + + + + ! +x+-+ + +
          !   x
+ + + + + ! + + + + +
", "
+ + + + ! + +-+ +
   2x   !    2x
+ + +-+ ! + + +-+
   3    !   |3
+ + + + ! +x+-+ +
        !   x
+ + + + ! + + + +
", "
+ + + + ! + + +
    |   !     |
+ + + + ! + + +
   3    !   |3
+ + + + ! +x+-+
        !   x
+ + + + ! + + +
", "
+ +  + + ! + +  + +
      a  !       a
+ +  + + ! + +  + +
   3a    !   |3a
+ +  + + ! +x+--+ +
         !   x
+ +  + + ! + +  + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + +x+ +
   1    !  b 1 B
+ + + + ! + +x+ +
   a    !    a
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
   2    !  A 2 A
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + +-+ +
   3    !  b 3 B
+ + + + ! + +-+ +
   a    !    a
+ + + + ! + + + +
", "
+ + ! + +
 a  !  a
+ + ! + +
 1  ! x1x
+ + ! + +
 A  !  A
+ + ! + +
", "
+ + + + ! + + + +
   a    !    a
+ + + + ! + + + +
   2    !  b 2 B
+ + + + ! + + + +
   A    !    A
+ + + + ! + + + +
", "
+ + ! + +
 a  !  a
+ + ! + +
 3  ! |3|
+ + ! + +
 A  !  A
+ + ! + +
"];
<|endoftext|>


<commit_before>extern crate rgmk;
extern crate byteorder;
extern crate env_logger;

use std::fs::File;
use std::io::prelude::*;
use std::io::{BufReader, BufWriter, Cursor};

fn main() {
    env_logger::init().unwrap();
    let original = {
        let mut args = std::env::args().skip(1);
        let path = args.next().expect("Expected path as argument");
        let mut file = File::open(&path).unwrap();
        let mut vec = Vec::new();
        file.read_to_end(&mut vec).unwrap();
        vec
    };
    let game_data = rgmk::GameData::from_reader(&mut BufReader::new(Cursor::new(&original[..])))
                        .unwrap();
    let mut new: Vec<u8> = Vec::with_capacity(original.len());
    unsafe {
        new.set_len(original.len());
    }
    game_data.write_to_writer(&mut BufWriter::new(Cursor::new(&mut new[..]))).unwrap();
    for (i, (o, n)) in original[..].iter().zip(new[..].iter()).enumerate() {
        if o != n {
            use byteorder::{ReadBytesExt, LittleEndian};
            let orig = (&original[i..i + 4]).read_u32::<LittleEndian>().unwrap();
            let new = (&new[i..i + 4]).read_u32::<LittleEndian>().unwrap();
            panic!("Difference at offset {}. orig {} vs new {}", i, orig, new);
        }
    }
}
<commit_msg>Remove unsafe code from identity test<commit_after>extern crate rgmk;
extern crate byteorder;
extern crate env_logger;

use std::fs::File;
use std::io::prelude::*;
use std::io::{BufReader, BufWriter, Cursor};

fn main() {
    env_logger::init().unwrap();
    let original = {
        let mut args = std::env::args().skip(1);
        let path = args.next().expect("Expected path as argument");
        let mut file = File::open(&path).unwrap();
        let mut vec = Vec::new();
        file.read_to_end(&mut vec).unwrap();
        vec
    };
    let game_data = rgmk::GameData::from_reader(&mut BufReader::new(Cursor::new(&original[..])))
                        .unwrap();
    let mut new: Vec<u8> = vec![0; original.len()];
    game_data.write_to_writer(&mut BufWriter::new(Cursor::new(&mut new[..]))).unwrap();
    for (i, (o, n)) in original[..].iter().zip(new[..].iter()).enumerate() {
        if o != n {
            use byteorder::{ReadBytesExt, LittleEndian};
            let orig = (&original[i..i + 4]).read_u32::<LittleEndian>().unwrap();
            let new = (&new[i..i + 4]).read_u32::<LittleEndian>().unwrap();
            panic!("Difference at offset {}. orig {} vs new {}", i, orig, new);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>runtime/rust: de-dup handle validation code<commit_after><|endoftext|>


<commit_before>use ::toyunda_player::*;
use ::toyunda_player::error::{Result,Error};
use std::cmp::{min,max};
use std::path::PathBuf;

#[derive(Debug)]
pub enum Command {
    AddVolume(i64),
    SetSpeed(f64),
    Framestep(i32),
    Seek(f64),
    TogglePause,
    ToggleFullscreen,
    ToggleDisplaySubtitles,
    AddToQueue(PathBuf),
    PlayNext,
    ClearQueue,
    EndFile,
}

impl<'a> ToyundaPlayer<'a> {
    pub fn execute_command(&mut self,command:Command) -> Result<ToyundaAction> {
        match command {
            Command::SetSpeed(speed) => {
                self.mpv_mut().set_property_async("speed", speed, 1)
                              .map_err(|e| Error::MpvError(e))
                              .map(|_| ToyundaAction::Nothing)
            },
            Command::TogglePause => {
                match self.mpv().get_property("pause") {
                    Ok(true) => {
                        self.mpv_mut().set_property_async("pause", false, 1)

                    }
                    Ok(false) => {
                        self.mpv_mut().set_property_async("pause", true, 1)
                    },
                    e @ Err(_) => e.map(|_| ())
                }
                .map_err(|e| Error::MpvError(e))
                .map(|_| ToyundaAction::Nothing)
            }
            Command::AddVolume(delta) => {
                let max_volume = self.mpv().get_property::<i64>("volume-max");
                let current_volume= self.mpv().get_property::<i64>("volume");
                match (max_volume,current_volume) {
                    (e @ Err(_),_) => e.map(|_| ToyundaAction::Nothing),
                    (_,e @ Err(_)) => e.map(|_| ToyundaAction::Nothing),
                    (Ok(max_volume),Ok(current_volume)) => {
                        let new_volume = min(max(current_volume + delta, 0), max_volume);
                        self.mpv_mut().set_property("volume", new_volume)
                            .map(|_| ToyundaAction::Nothing)
                    }
                }
                .map_err(|e| Error::MpvError(e))
            }
            Command::ToggleFullscreen => {
                use sdl2::video::FullscreenType;
                let new_fullscreen_type =
                    match self.displayer().sdl_renderer().window().unwrap().fullscreen_state() {
                        FullscreenType::True | FullscreenType::Desktop => { // TODO warn if 'True'
                            FullscreenType::Off
                        },
                        FullscreenType::Off => {
                            FullscreenType::Desktop
                        }
                    };
                self.displayer_mut()
                    .sdl_renderer_mut()
                    .window_mut()
                    .unwrap()
                    .set_fullscreen(new_fullscreen_type)
                    .map_err(|e| Error::Text(e))
                    .map(|_| ToyundaAction::Nothing)
            }
            Command::Framestep(step) => {
                let (frame_step_type,_step) = if step >= 0 {
                    ("frame-step",step)
                }  else {
                    ("frame-back-step",-step)
                };
                self.mpv_mut()
                    .command(&[frame_step_type])
                    .map_err(|e| Error::MpvError(e))
                    .map(|_| ToyundaAction::Nothing)
            },
            Command::Seek(delta) => {
                self.mpv_mut()
                    .command(&["seek",delta.to_string().as_str()])
                    .map_err(|e| Error::MpvError(e))
                    .map(|_| ToyundaAction::Nothing)
            },
            Command::ToggleDisplaySubtitles => {
                let current_value = self.options().display_subtitles;
                self.options_mut().display_subtitles = !current_value ;
                Ok(ToyundaAction::Nothing)
            },
            Command::PlayNext => {
                let video_path = self.queue_mut().pop_front();
                match self.mpv_mut().command(&["stop"]) {
                    Err(e) => {error!("Unexpected error {} ({:?}) happened when stopping player",e,e)},
                    _ => {}
                };
                match video_path {
                    None => {
                        match self.options().quit_when_finished {
                            None => {
                                match self.options().mode {
                                    ToyundaMode::KaraokeMode | ToyundaMode::EditMode =>
                                        Ok(ToyundaAction::Nothing),
                                    ToyundaMode::NormalMode =>
                                        Ok(ToyundaAction::Terminate)
                                }
                            },
                            Some(b) => {
                                if b { // "quit_when_finished" override
                                    Ok(ToyundaAction::Terminate)
                                } else { // "dont_quit_when_finished" override
                                    Ok(ToyundaAction::Nothing)
                                }
                            }
                        }
                    },
                    Some(video_path) => {
                        match video_path.to_str() {
                            None => {
                                error!("Invalid UTF-8 Path for {} , skipping file",video_path.display());
                                Ok(ToyundaAction::PlayNext)
                            },
                            Some(video_path) => {
                                match self.mpv_mut().command(&["loadfile",video_path]) {
                                    Ok(_) => {
                                        match self.import_subtitles(video_path) {
                                            Ok(_) => {
                                                info!("Now playing : '{}'",video_path);
                                                Ok(ToyundaAction::Nothing)
                                            },
                                            Err(e) => {
                                                error!("Error was received when importing subtitles : {} , file {} will be skipped",e,video_path);
                                                Ok(ToyundaAction::PlayNext)
                                            }
                                        }
                                    },
                                    Err(e) => {
                                        error!("Trying to play file {} but error {} occured. Skiping file ...",video_path,e);
                                        Ok(ToyundaAction::PlayNext)
                                    }
                                }
                            }
                        }
                    }
                }
            },
            Command::ClearQueue => {
                self.queue_mut().clear();
                Ok(ToyundaAction::Nothing)
            },
            Command::AddToQueue(path) => {
                self.queue_mut().push_back(path);
                Ok(ToyundaAction::Nothing)
            }
            Command::EndFile => {
                self.clear_subtitles();
                Ok(ToyundaAction::Nothing)
            }
        }
    }
}
<commit_msg>Skip file without subtitles in karaoke mode only<commit_after>use ::toyunda_player::*;
use ::toyunda_player::error::{Result,Error};
use std::cmp::{min,max};
use std::path::PathBuf;

#[derive(Debug)]
pub enum Command {
    AddVolume(i64),
    SetSpeed(f64),
    Framestep(i32),
    Seek(f64),
    TogglePause,
    ToggleFullscreen,
    ToggleDisplaySubtitles,
    AddToQueue(PathBuf),
    PlayNext,
    ClearQueue,
    EndFile,
}

impl<'a> ToyundaPlayer<'a> {
    pub fn execute_command(&mut self,command:Command) -> Result<ToyundaAction> {
        match command {
            Command::SetSpeed(speed) => {
                self.mpv_mut().set_property_async("speed", speed, 1)
                              .map_err(|e| Error::MpvError(e))
                              .map(|_| ToyundaAction::Nothing)
            },
            Command::TogglePause => {
                match self.mpv().get_property("pause") {
                    Ok(true) => {
                        self.mpv_mut().set_property_async("pause", false, 1)

                    }
                    Ok(false) => {
                        self.mpv_mut().set_property_async("pause", true, 1)
                    },
                    e @ Err(_) => e.map(|_| ())
                }
                .map_err(|e| Error::MpvError(e))
                .map(|_| ToyundaAction::Nothing)
            }
            Command::AddVolume(delta) => {
                let max_volume = self.mpv().get_property::<i64>("volume-max");
                let current_volume= self.mpv().get_property::<i64>("volume");
                match (max_volume,current_volume) {
                    (e @ Err(_),_) => e.map(|_| ToyundaAction::Nothing),
                    (_,e @ Err(_)) => e.map(|_| ToyundaAction::Nothing),
                    (Ok(max_volume),Ok(current_volume)) => {
                        let new_volume = min(max(current_volume + delta, 0), max_volume);
                        self.mpv_mut().set_property("volume", new_volume)
                            .map(|_| ToyundaAction::Nothing)
                    }
                }
                .map_err(|e| Error::MpvError(e))
            }
            Command::ToggleFullscreen => {
                use sdl2::video::FullscreenType;
                let new_fullscreen_type =
                    match self.displayer().sdl_renderer().window().unwrap().fullscreen_state() {
                        FullscreenType::True | FullscreenType::Desktop => { // TODO warn if 'True'
                            FullscreenType::Off
                        },
                        FullscreenType::Off => {
                            FullscreenType::Desktop
                        }
                    };
                self.displayer_mut()
                    .sdl_renderer_mut()
                    .window_mut()
                    .unwrap()
                    .set_fullscreen(new_fullscreen_type)
                    .map_err(|e| Error::Text(e))
                    .map(|_| ToyundaAction::Nothing)
            }
            Command::Framestep(step) => {
                let (frame_step_type,_step) = if step >= 0 {
                    ("frame-step",step)
                }  else {
                    ("frame-back-step",-step)
                };
                self.mpv_mut()
                    .command(&[frame_step_type])
                    .map_err(|e| Error::MpvError(e))
                    .map(|_| ToyundaAction::Nothing)
            },
            Command::Seek(delta) => {
                self.mpv_mut()
                    .command(&["seek",delta.to_string().as_str()])
                    .map_err(|e| Error::MpvError(e))
                    .map(|_| ToyundaAction::Nothing)
            },
            Command::ToggleDisplaySubtitles => {
                let current_value = self.options().display_subtitles;
                self.options_mut().display_subtitles = !current_value ;
                Ok(ToyundaAction::Nothing)
            },
            Command::PlayNext => {
                let video_path = self.queue_mut().pop_front();
                match self.mpv_mut().command(&["stop"]) {
                    Err(e) => {error!("Unexpected error {} ({:?}) happened when stopping player",e,e)},
                    _ => {}
                };
                match video_path {
                    None => {
                        match self.options().quit_when_finished {
                            None => {
                                match self.options().mode {
                                    ToyundaMode::KaraokeMode | ToyundaMode::EditMode =>
                                        Ok(ToyundaAction::Nothing),
                                    ToyundaMode::NormalMode =>
                                        Ok(ToyundaAction::Terminate)
                                }
                            },
                            Some(b) => {
                                if b { // "quit_when_finished" override
                                    Ok(ToyundaAction::Terminate)
                                } else { // "dont_quit_when_finished" override
                                    Ok(ToyundaAction::Nothing)
                                }
                            }
                        }
                    },
                    Some(video_path) => {
                        match video_path.to_str() {
                            None => {
                                error!("Invalid UTF-8 Path for {} , skipping file",video_path.display());
                                Ok(ToyundaAction::PlayNext)
                            },
                            Some(video_path) => {
                                match self.mpv_mut().command(&["loadfile",video_path]) {
                                    Ok(_) => {
                                        match self.import_subtitles(video_path) {
                                            Ok(_) => {
                                                info!("Now playing : '{}'",video_path);
                                                Ok(ToyundaAction::Nothing)
                                            },
                                            Err(e) => {
                                                if self.options().mode == ToyundaMode::KaraokeMode {
                                                    error!("Error was received when importing subtitles : {} , file {} will be skipped",e,video_path);
                                                    Ok(ToyundaAction::PlayNext)
                                                } else {
                                                    error!("Error was received when importing subtitles : {}",e);
                                                    Ok(ToyundaAction::Nothing)
                                                }
                                            }
                                        }
                                    },
                                    Err(e) => {
                                        error!("Trying to play file {} but error {} occured. Skiping file ...",video_path,e);
                                        Ok(ToyundaAction::PlayNext)
                                    }
                                }
                            }
                        }
                    }
                }
            },
            Command::ClearQueue => {
                self.queue_mut().clear();
                Ok(ToyundaAction::Nothing)
            },
            Command::AddToQueue(path) => {
                self.queue_mut().push_back(path);
                Ok(ToyundaAction::Nothing)
            }
            Command::EndFile => {
                self.clear_subtitles();
                Ok(ToyundaAction::Nothing)
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::utils::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind, VisibilityKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};

declare_clippy_lint! {
    /// **What it does:** Checks for items declared `pub(crate)` that are not crate visible because they
    /// are inside a private module.
    ///
    /// **Why is this bad?** Writing `pub(crate)` is misleading when it's redundant due to the parent
    /// module's visibility.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// mod internal {
    ///     pub(crate) fn internal_fn() { }
    /// }
    /// ```
    /// This function is not visible outside the module and it can be declared with `pub` or
    /// private visibility
    /// ```rust
    /// mod internal {
    ///     pub fn internal_fn() { }
    /// }
    /// ```
    pub REDUNDANT_PUB_CRATE,
    nursery,
    "Using `pub(crate)` visibility on items that are not crate visible due to the visibility of the module that contains them."
}

#[derive(Default)]
pub struct RedundantPubCrate {
    is_exported: Vec<bool>,
}

impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPubCrate {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) {
        if let VisibilityKind::Crate { .. } = item.vis.node {
            if !cx.access_levels.is_exported(item.hir_id) {
                if let Some(false) = self.is_exported.last() {
                    let span = item.span.with_hi(item.ident.span.hi());
                    span_lint_and_then(
                        cx,
                        REDUNDANT_PUB_CRATE,
                        span,
                        &format!("pub(crate) {} inside private module", item.kind.descr()),
                        |diag| {
                            diag.span_suggestion(
                                item.vis.span,
                                "consider using",
                                "pub".to_string(),
                                Applicability::MachineApplicable,
                            );
                        },
                    )
                }
            }
        }

        if let ItemKind::Mod { .. } = item.kind {
            self.is_exported.push(cx.access_levels.is_exported(item.hir_id));
        }
    }

    fn check_item_post(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) {
        if let ItemKind::Mod { .. } = item.kind {
            self.is_exported.pop().expect("unbalanced check_item/check_item_post");
        }
    }
}
<commit_msg>Auto merge of #5533 - phansch:rustup001, r=matthiaskrgr<commit_after>use crate::utils::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind, VisibilityKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};

declare_clippy_lint! {
    /// **What it does:** Checks for items declared `pub(crate)` that are not crate visible because they
    /// are inside a private module.
    ///
    /// **Why is this bad?** Writing `pub(crate)` is misleading when it's redundant due to the parent
    /// module's visibility.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// mod internal {
    ///     pub(crate) fn internal_fn() { }
    /// }
    /// ```
    /// This function is not visible outside the module and it can be declared with `pub` or
    /// private visibility
    /// ```rust
    /// mod internal {
    ///     pub fn internal_fn() { }
    /// }
    /// ```
    pub REDUNDANT_PUB_CRATE,
    nursery,
    "Using `pub(crate)` visibility on items that are not crate visible due to the visibility of the module that contains them."
}

#[derive(Default)]
pub struct RedundantPubCrate {
    is_exported: Vec<bool>,
}

impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPubCrate {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) {
        if let VisibilityKind::Crate { .. } = item.vis.node {
            if !cx.access_levels.is_exported(item.hir_id) {
                if let Some(false) = self.is_exported.last() {
                    let span = item.span.with_hi(item.ident.span.hi());
                    let def_id = cx.tcx.hir().local_def_id(item.hir_id);
                    let descr = cx.tcx.def_kind(def_id).descr(def_id.to_def_id());
                    span_lint_and_then(
                        cx,
                        REDUNDANT_PUB_CRATE,
                        span,
                        &format!("pub(crate) {} inside private module", descr),
                        |diag| {
                            diag.span_suggestion(
                                item.vis.span,
                                "consider using",
                                "pub".to_string(),
                                Applicability::MachineApplicable,
                            );
                        },
                    )
                }
            }
        }

        if let ItemKind::Mod { .. } = item.kind {
            self.is_exported.push(cx.access_levels.is_exported(item.hir_id));
        }
    }

    fn check_item_post(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) {
        if let ItemKind::Mod { .. } = item.kind {
            self.is_exported.pop().expect("unbalanced check_item/check_item_post");
        }
    }
}
<|endoftext|>


<commit_before>//! [Church pairs](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::{Term, Error, abs};
use term::Term::*;
use term::Error::*;
use church::booleans::{tru, fls};

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// PAIR := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::pair;
/// use lambda_calculus::church::numerals::{zero, one};
///
/// let pair01 = app!(pair(), zero(), one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
/// assert_eq!(pair01.snd_ref(), Ok(&one()));
/// # }
/// ```
pub fn pair() -> Term {
    abs(abs(abs(
        app!(Var(1), Var(3), Var(2))
    )))
}

/// Applied to a Church-encoded pair `(a, b)` it yields `a`.
///
/// FST := λp.p TRUE = λ 1 TRUE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, fst};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(fst().app(pair_0_1), NOR, 0, false), zero());
/// # }
/// ```
pub fn fst() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair `(a, b)` it yields `b`.
///
/// SND := λp.p FALSE = λ 1 FALSE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, snd};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(snd().app(pair_0_1), NOR, 0, false), one());
/// # }
/// ```
pub fn snd() -> Term { abs(Var(1).app(fls())) }

impl Term {
    /// Checks whether `self` is a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert!(pair01.is_pair());
    /// # }
    /// ```
    pub fn is_pair(&self) -> bool {
        self.unpair_ref().is_ok()
    }

    /// Splits a Church-encoded pair into a pair of terms, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair(), Ok((zero(), one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair(self) -> Result<(Term, Term), Error> {
        let candidate = if let Abs(abstracted) = self { *abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp() {
            Ok((try!(wrapped_a.rhs()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Splits a Church-encoded pair into a pair of references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
        let candidate = if let Abs(ref abstracted) = *self { abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp_ref() {
            Ok((try!(wrapped_a.rhs_ref()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_mut(), Ok((&mut zero(), &mut one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        let candidate = if let Abs(ref mut abstracted) = *self { abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp_mut() {
            Ok((try!(wrapped_a.rhs_mut()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Returns the first term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst(), Ok(zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).0)
    }

    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_ref(), Ok(&zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).0)
    }

    /// Returns a mutable reference to the first term of a Church-encoded pair.
    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_mut(), Ok(&mut zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_mut()).0)
    }

    /// Returns the second term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd(), Ok(one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).1)
    }

    /// Returns a reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_ref(), Ok(&one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).1)
    }

    /// Returns a mutable reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_mut(), Ok(&mut one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_mut()).1)
    }
}

impl From<(Term, Term)> for Term {
    fn from((t1, t2): (Term, Term)) -> Self {
        abs(app!(Var(1), t1, t2))
    }
}
<commit_msg>add uncurry<commit_after>//! [Church pairs](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::{Term, Error, abs};
use term::Term::*;
use term::Error::*;
use church::booleans::{tru, fls};

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// PAIR := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::pair;
/// use lambda_calculus::church::numerals::{zero, one};
///
/// let pair01 = app!(pair(), zero(), one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
/// assert_eq!(pair01.snd_ref(), Ok(&one()));
/// # }
/// ```
pub fn pair() -> Term {
    abs(abs(abs(
        app!(Var(1), Var(3), Var(2))
    )))
}

/// Applied to a Church-encoded pair `(a, b)` it yields `a`.
///
/// FST := λp.p TRUE = λ 1 TRUE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, fst};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(fst().app(pair_0_1), NOR, 0, false), zero());
/// # }
/// ```
pub fn fst() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair `(a, b)` it yields `b`.
///
/// SND := λp.p FALSE = λ 1 FALSE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, snd};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(snd().app(pair_0_1), NOR, 0, false), one());
/// # }
/// ```
pub fn snd() -> Term { abs(Var(1).app(fls())) }

/// Applied to a function and a Church-encoded pair `(a, b)` it uncurrys the pair and applies the
/// function to `a` and then `b`.
///
/// UNCURRY := λf.λp.f (FST p) (SND p) = λ λ 2 (FST 1) (SND 1)
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, uncurry};
/// use lambda_calculus::church::numerals::{succ, one, plus};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_3_5 = app!(pair(), 3.into(), 5.into());
///
/// assert_eq!(beta(app!(uncurry(), plus(), pair_3_5), NOR, 0, false), 8.into());
/// assert_eq!(beta(uncurry(), NOR, 0, false), uncurry());
/// # }
/// ```
/// λλ2(1(λλ2))(1(λλ1))
pub fn uncurry() -> Term {
    abs(abs(
        app!(Var(2), Var(1).app(abs(abs(Var(2)))), Var(1).app(abs(abs(Var(1)))))
    ))
}

impl Term {
    /// Checks whether `self` is a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert!(pair01.is_pair());
    /// # }
    /// ```
    pub fn is_pair(&self) -> bool {
        self.unpair_ref().is_ok()
    }

    /// Splits a Church-encoded pair into a pair of terms, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair(), Ok((zero(), one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair(self) -> Result<(Term, Term), Error> {
        let candidate = if let Abs(abstracted) = self { *abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp() {
            Ok((try!(wrapped_a.rhs()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Splits a Church-encoded pair into a pair of references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
        let candidate = if let Abs(ref abstracted) = *self { abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp_ref() {
            Ok((try!(wrapped_a.rhs_ref()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_mut(), Ok((&mut zero(), &mut one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        let candidate = if let Abs(ref mut abstracted) = *self { abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp_mut() {
            Ok((try!(wrapped_a.rhs_mut()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Returns the first term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst(), Ok(zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).0)
    }

    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_ref(), Ok(&zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).0)
    }

    /// Returns a mutable reference to the first term of a Church-encoded pair.
    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_mut(), Ok(&mut zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_mut()).0)
    }

    /// Returns the second term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd(), Ok(one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).1)
    }

    /// Returns a reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_ref(), Ok(&one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).1)
    }

    /// Returns a mutable reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_mut(), Ok(&mut one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_mut()).1)
    }
}

impl From<(Term, Term)> for Term {
    fn from((t1, t2): (Term, Term)) -> Self {
        abs(app!(Var(1), t1, t2))
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::fs;
use std::env;

enum Op {
    Inc(i32),
    Move(isize),
    Loop(Box<[Op]>),
    Print
}
use Op::*;

struct Tape {
    pos: usize,
    tape: Vec<i32>
}

impl Tape {
    fn new() -> Tape { Tape { pos: 0, tape: vec![0] } }
    fn get(&self) -> i32 { self.tape[self.pos] }
    fn inc(&mut self, x: i32) { self.tape[self.pos] += x; }
    fn mov(&mut self, x: isize) {
        self.pos = (self.pos as isize + x) as usize;
        while self.pos >= self.tape.len() { self.tape.push(0); }
    }
}

struct Printer {
    sum1: i32,
    sum2: i32,
    quiet: bool
}

impl Printer {
    fn new(quiet: bool) -> Printer { Printer { sum1: 0, sum2: 0, quiet: quiet} }

    fn print(&mut self, n: i32) {
        if self.quiet {
            self.sum1 = (self.sum1 + n) % 255;
            self.sum2 = (self.sum2 + self.sum1) % 255;
        } else {
            print!("{}", n as u8 as char);
            io::Write::flush(&mut io::stdout()).unwrap();
        }
    }

    fn get_checksum(&self) -> i32 {
        (self.sum2 << 8) | self.sum1
    }
}

fn _run(program: &[Op], tape: &mut Tape, p: &mut Printer) {
    for op in program {
        match *op {
            Inc(x) => tape.inc(x),
            Move(x) => tape.mov(x),
            Loop(ref program) => while tape.get() > 0 {
                _run(program, tape, p);
            },
            Print => {
                p.print(tape.get());
            }
        }
    }
}

fn parse<I: Iterator<Item=char>>(it: &mut I) -> Box<[Op]> {
    let mut buf = Vec::new();
    while let Some(c) = it.next() {
        buf.push( match c {
            '+' => Inc(1),
            '-' => Inc(-1),
            '>' => Move(1),
            '<' => Move(-1),
            '.' => Print,
            '[' => Loop(parse(it)),
            ']' => break,
            _ => continue,
        } );
    }
    buf.into_boxed_slice()
}

struct Program {
    ops: Box<[Op]>
}

impl Program {
    fn new(code: String) -> Program { Program { ops: parse(&mut code.chars()) } }
    fn run(&self, p: &mut Printer) {
        let mut tape = Tape::new();
        _run(&self.ops, &mut tape, p);
    }
}

fn notify(msg: &str) {
    use std::io::Write;

    if let Ok(mut stream) = std::net::TcpStream::connect("localhost:9001") {
        stream.write_all(msg.as_bytes()).unwrap();
    }
}

fn verify() {
    let s = String::from("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>
        ---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.");
    let mut p_left = Printer::new(true);
    Program::new(s).run(&mut p_left);
    let left = p_left.get_checksum();

    let mut p_right = Printer::new(true);
    for c in "Hello World!\n".chars() {
        p_right.print(c as i32);
    }
    let right = p_right.get_checksum();
    if left != right {
        eprintln!("{:?} != {:?}", left, right);
        std::process::exit(-1);
    }
}

fn main() {
    verify();

    let arg1 = env::args().nth(1).unwrap();
    let s = fs::read_to_string(arg1).unwrap();
    let mut p = Printer::new(std::env::var("QUIET").is_ok());

    notify(&format!("Rust\t{}", std::process::id()));
    Program::new(s).run(&mut p);
    notify("stop");

    if p.quiet {
        println!("Output checksum: {}", p.get_checksum());
    }
}
<commit_msg>Update the Rust's brainfuck implementation (#325)<commit_after>use std::env;
use std::fs;
use std::io::{self, prelude::*};
use std::process;

enum Op {
    Dec,
    Inc,
    Prev,
    Next,
    Loop(Box<[Op]>),
    Print,
}
use Op::*;

struct Tape {
    pos: usize,
    tape: Vec<i32>,
}

impl Tape {
    fn new() -> Self {
        Default::default()
    }

    fn get(&self) -> i32 {
        // Always safe
        unsafe { *self.tape.get_unchecked(self.pos) }
    }

    fn dec(&mut self) {
        // Always safe
        unsafe {
            *self.tape.get_unchecked_mut(self.pos) -= 1;
        }
    }

    fn inc(&mut self) {
        // Always safe
        unsafe {
            *self.tape.get_unchecked_mut(self.pos) += 1;
        }
    }

    fn prev(&mut self) {
        self.pos -= 1;
    }

    fn next(&mut self) {
        self.pos += 1;
        if self.pos >= self.tape.len() {
            self.tape.resize(self.pos << 1, 0);
        }
    }
}

impl Default for Tape {
    fn default() -> Self {
        Self {
            pos: 0,
            tape: vec![0],
        }
    }
}

#[derive(Default)]
struct Printer {
    sum1: i32,
    sum2: i32,
    quiet: bool,
}

impl Printer {
    fn new(quiet: bool) -> Self {
        Self {
            quiet,
            ..Default::default()
        }
    }

    fn print(&mut self, n: i32) {
        if self.quiet {
            self.sum1 = (self.sum1 + n) % 255;
            self.sum2 = (self.sum2 + self.sum1) % 255;
        } else {
            let mut stdout = io::stdout();
            stdout.lock().write_all(&[n as u8]).ok();
            stdout.flush().ok();
        }
    }

    fn get_checksum(&self) -> i32 {
        (self.sum2 << 8) | self.sum1
    }
}

fn run(program: &[Op], tape: &mut Tape, p: &mut Printer) {
    for op in program {
        match *op {
            Dec => tape.dec(),
            Inc => tape.inc(),
            Prev => tape.prev(),
            Next => tape.next(),
            Loop(ref program) => {
                while tape.get() > 0 {
                    run(program, tape, p);
                }
            }
            Print => {
                p.print(tape.get());
            }
        }
    }
}

fn parse<I: Iterator<Item = char>>(it: &mut I) -> Box<[Op]> {
    let mut buf = vec![];
    while let Some(c) = it.next() {
        buf.push(match c {
            '-' => Dec,
            '+' => Inc,
            '<' => Prev,
            '>' => Next,
            '.' => Print,
            '[' => Loop(parse(it)),
            ']' => break,
            _ => continue,
        });
    }
    buf.into_boxed_slice()
}

struct Program {
    ops: Box<[Op]>,
}

impl Program {
    fn new(code: &str) -> Self {
        Self {
            ops: parse(&mut code.chars()),
        }
    }

    fn run(&self, p: &mut Printer) {
        let mut tape = Tape::new();
        run(&self.ops, &mut tape, p);
    }
}

fn notify(msg: &str) {
    if let Ok(mut stream) = std::net::TcpStream::connect("localhost:9001") {
        stream.write_all(msg.as_bytes()).ok();
    }
}

fn verify() {
    let s = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>
             ---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
    let mut p_left = Printer::new(true);
    Program::new(s).run(&mut p_left);
    let left = p_left.get_checksum();

    let mut p_right = Printer::new(true);
    for c in "Hello World!\n".chars() {
        p_right.print(c as i32);
    }
    let right = p_right.get_checksum();
    if left != right {
        eprintln!("{} != {}", left, right);
        process::exit(-1);
    }
}

fn main() {
    verify();

    let arg1 = env::args().nth(1).unwrap();
    let s = fs::read_to_string(arg1).unwrap();
    let mut p = Printer::new(env::var("QUIET").is_ok());

    notify(&format!("Rust\t{}", process::id()));
    Program::new(&s).run(&mut p);
    notify("stop");

    if p.quiet {
        println!("Output checksum: {}", p.get_checksum());
    }
}

<|endoftext|>


<commit_before>//! Functions for altering and converting the color of pixelbufs

use num_traits::{Num, NumCast};
use std::f64::consts::PI;

use crate::color::{Luma, Rgba};
use crate::image::{GenericImage, GenericImageView};
use crate::math::nq;
use crate::math::utils::clamp;
use crate::traits::{Pixel, Primitive};
use crate::ImageBuffer;

type Subpixel<I> = <<I as GenericImageView>::Pixel as Pixel>::Subpixel;

/// Convert the supplied image to grayscale
pub fn grayscale<I: GenericImageView>(image: &I) -> ImageBuffer<Luma<Subpixel<I>>, Vec<Subpixel<I>>>
where
    Subpixel<I>: 'static,
    <Subpixel<I> as Num>::FromStrRadixErr: 'static,
{
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    for y in 0..height {
        for x in 0..width {
            let p = image.get_pixel(x, y).to_luma();
            out.put_pixel(x, y, p);
        }
    }

    out
}

/// Invert each pixel within the supplied image.
/// This function operates in place.
pub fn invert<I: GenericImage>(image: &mut I) {
    let (width, height) = image.dimensions();

    for y in 0..height {
        for x in 0..width {
            let mut p = image.get_pixel(x, y);
            p.invert();

            image.put_pixel(x, y, p);
        }
    }
}

/// Adjust the contrast of the supplied image.
/// ```contrast``` is the amount to adjust the contrast by.
/// Negative values decrease the contrast and positive values increase the contrast.
pub fn contrast<I, P, S>(image: &I, contrast: f32) -> ImageBuffer<P, Vec<S>>
where
    I: GenericImageView<Pixel = P>,
    P: Pixel<Subpixel = S> + 'static,
    S: Primitive + 'static,
{
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let max = S::max_value();
    let max: f32 = NumCast::from(max).unwrap();

    let percent = ((100.0 + contrast) / 100.0).powi(2);

    for y in 0..height {
        for x in 0..width {
            let f = image.get_pixel(x, y).map(|b| {
                let c: f32 = NumCast::from(b).unwrap();

                let d = ((c / max - 0.5) * percent + 0.5) * max;
                let e = clamp(d, 0.0, max);

                NumCast::from(e).unwrap()
            });

            out.put_pixel(x, y, f);
        }
    }

    out
}

/// Brighten the supplied image.
/// ```value``` is the amount to brighten each pixel by.
/// Negative values decrease the brightness and positive values increase it.
pub fn brighten<I, P, S>(image: &I, value: i32) -> ImageBuffer<P, Vec<S>>
where
    I: GenericImageView<Pixel = P>,
    P: Pixel<Subpixel = S> + 'static,
    S: Primitive + 'static,
{
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let max = S::max_value();
    let max: i32 = NumCast::from(max).unwrap();

    for y in 0..height {
        for x in 0..width {
            let e = image.get_pixel(x, y).map_with_alpha(
                |b| {
                    let c: i32 = NumCast::from(b).unwrap();
                    let d = clamp(c + value, 0, max);

                    NumCast::from(d).unwrap()
                },
                |alpha| alpha,
            );

            out.put_pixel(x, y, e);
        }
    }

    out
}

/// Hue rotate the supplied image.
/// `value` is the degrees to rotate each pixel by.
/// 0 and 360 do nothing, the rest rotates by the given degree value.
/// just like the css webkit filter hue-rotate(180)
pub fn huerotate<I, P, S>(image: &I, value: i32) -> ImageBuffer<P, Vec<S>>
where
    I: GenericImageView<Pixel = P>,
    P: Pixel<Subpixel = S> + 'static,
    S: Primitive + 'static,
{
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let angle: f64 = NumCast::from(value).unwrap();

    let cosv = (angle * PI / 180.0).cos();
    let sinv = (angle * PI / 180.0).sin();
    let matrix: [f64; 9] = [
        // Reds
        0.213 + cosv * 0.787 - sinv * 0.213,
        0.715 - cosv * 0.715 - sinv * 0.715,
        0.072 - cosv * 0.072 + sinv * 0.928,
        // Greens
        0.213 - cosv * 0.213 + sinv * 0.143,
        0.715 + cosv * 0.285 + sinv * 0.140,
        0.072 - cosv * 0.072 - sinv * 0.283,
        // Blues
        0.213 - cosv * 0.213 - sinv * 0.787,
        0.715 - cosv * 0.715 + sinv * 0.715,
        0.072 + cosv * 0.928 + sinv * 0.072,
    ];
    for (x, y, pixel) in out.enumerate_pixels_mut() {
        let p = image.get_pixel(x, y);
        let (k1, k2, k3, k4) = p.channels4();
        let vec: (f64, f64, f64, f64) = (
            NumCast::from(k1).unwrap(),
            NumCast::from(k2).unwrap(),
            NumCast::from(k3).unwrap(),
            NumCast::from(k4).unwrap(),
        );

        let r = vec.0;
        let g = vec.1;
        let b = vec.2;

        let new_r = matrix[0] * r + matrix[1] * g + matrix[2] * b;
        let new_g = matrix[3] * r + matrix[4] * g + matrix[5] * b;
        let new_b = matrix[6] * r + matrix[7] * g + matrix[8] * b;
        let max = 255f64;
        let outpixel = Pixel::from_channels(
            NumCast::from(clamp(new_r, 0.0, max)).unwrap(),
            NumCast::from(clamp(new_g, 0.0, max)).unwrap(),
            NumCast::from(clamp(new_b, 0.0, max)).unwrap(),
            NumCast::from(clamp(vec.3, 0.0, max)).unwrap(),
        );
        *pixel = outpixel;
    }
    out
}

/// A color map
pub trait ColorMap {
    /// The color type on which the map operates on
    type Color;
    /// Returns the index of the closest match of `color`
    /// in the color map.
    fn index_of(&self, color: &Self::Color) -> usize;
    /// Looks up color by index in the color map.  If `idx` is out of range for the color map,
    /// `None` is returned.
    fn lookup(&self, idx: usize) -> Option<Self::Color>;
    /// Maps `color` to the closest color in the color map.
    fn map_color(&self, color: &mut Self::Color);
}

/// A bi-level color map
///
/// # Examples
/// ```
/// use image::imageops::colorops::{index_colors, BiLevel, ColorMap};
/// use image::{ImageBuffer, Luma};
///
/// let (w, h) = (16, 16);
/// // Create an image with a smooth horizontal gradient from black (0) to white (255).
/// let gray = ImageBuffer::from_fn(w, h, |x, y| -> Luma<u8> { [(255 * x / w) as u8].into() });
/// // Mapping the gray image through the `BiLevel` filter should map gray pixels less than half
/// // intensity (127) to black (0), and anything greater to white (255).
/// let cmap = BiLevel;
/// let palletized = index_colors(&gray, &cmap);
/// let mapped = ImageBuffer::from_fn(w, h, |x, y| {
///     let p = palletized.get_pixel(x, y);
///     cmap.lookup(p.0[0] as usize)
///         .expect("indexed color out-of-range")
/// });
/// // Create an black and white image of expected output.
/// let bw = ImageBuffer::from_fn(w, h, |x, y| -> Luma<u8> {
///     if x <= (w / 2) {
///         [0].into()
///     } else {
///         [255].into()
///     }
/// });
/// assert_eq!(mapped, bw);
/// ```
#[derive(Clone, Copy)]
pub struct BiLevel;

impl ColorMap for BiLevel {
    type Color = Luma<u8>;

    #[inline(always)]
    fn index_of(&self, color: &Luma<u8>) -> usize {
        let luma = color.0;
        if luma[0] > 127 {
            1
        } else {
            0
        }
    }

    #[inline(always)]
    fn lookup(&self, idx: usize) -> Option<Self::Color> {
        match idx {
            0 => Some([0].into()),
            1 => Some([255].into()),
            _ => None,
        }
    }

    #[inline(always)]
    fn map_color(&self, color: &mut Luma<u8>) {
        let new_color = 0xFF * self.index_of(color) as u8;
        let luma = &mut color.0;
        luma[0] = new_color;
    }
}

impl ColorMap for nq::NeuQuant {
    type Color = Rgba<u8>;

    #[inline(always)]
    fn index_of(&self, color: &Rgba<u8>) -> usize {
        self.index_of(color.channels())
    }

    #[inline(always)]
    fn lookup(&self, idx: usize) -> Option<Self::Color> {
        self.lookup(idx).map(|p| p.into())
    }

    #[inline(always)]
    fn map_color(&self, color: &mut Rgba<u8>) {
        self.map_pixel(color.channels_mut())
    }
}

/// Floyd-Steinberg error diffusion
fn diffuse_err<P: Pixel<Subpixel = u8>>(pixel: &mut P, error: [i16; 3], factor: i16) {
    for (e, c) in error.iter().zip(pixel.channels_mut().iter_mut()) {
        *c = match <i16 as From<_>>::from(*c) + e * factor / 16 {
            val if val < 0 => 0,
            val if val > 0xFF => 0xFF,
            val => val as u8,
        }
    }
}

macro_rules! do_dithering(
    ($map:expr, $image:expr, $err:expr, $x:expr, $y:expr) => (
        {
            let old_pixel = $image[($x, $y)];
            let new_pixel = $image.get_pixel_mut($x, $y);
            $map.map_color(new_pixel);
            for ((e, &old), &new) in $err.iter_mut()
                                        .zip(old_pixel.channels().iter())
                                        .zip(new_pixel.channels().iter())
            {
                *e = <i16 as From<_>>::from(old) - <i16 as From<_>>::from(new)
            }
        }
    )
);

/// Reduces the colors of the image using the supplied `color_map` while applying
/// Floyd-Steinberg dithering to improve the visual conception
pub fn dither<Pix, Map>(image: &mut ImageBuffer<Pix, Vec<u8>>, color_map: &Map)
where
    Map: ColorMap<Color = Pix>,
    Pix: Pixel<Subpixel = u8> + 'static,
{
    let (width, height) = image.dimensions();
    let mut err: [i16; 3] = [0; 3];
    for y in 0..height - 1 {
        let x = 0;
        do_dithering!(color_map, image, err, x, y);
        diffuse_err(image.get_pixel_mut(x + 1, y), err, 7);
        diffuse_err(image.get_pixel_mut(x, y + 1), err, 5);
        diffuse_err(image.get_pixel_mut(x + 1, y + 1), err, 1);
        for x in 1..width - 1 {
            do_dithering!(color_map, image, err, x, y);
            diffuse_err(image.get_pixel_mut(x + 1, y), err, 7);
            diffuse_err(image.get_pixel_mut(x - 1, y + 1), err, 3);
            diffuse_err(image.get_pixel_mut(x, y + 1), err, 5);
            diffuse_err(image.get_pixel_mut(x + 1, y + 1), err, 1);
        }
        let x = width - 1;
        do_dithering!(color_map, image, err, x, y);
        diffuse_err(image.get_pixel_mut(x - 1, y + 1), err, 3);
        diffuse_err(image.get_pixel_mut(x, y + 1), err, 5);
    }
    let y = height - 1;
    let x = 0;
    do_dithering!(color_map, image, err, x, y);
    diffuse_err(image.get_pixel_mut(x + 1, y), err, 7);
    for x in 1..width - 1 {
        do_dithering!(color_map, image, err, x, y);
        diffuse_err(image.get_pixel_mut(x + 1, y), err, 7);
    }
    let x = width - 1;
    do_dithering!(color_map, image, err, x, y);
}

/// Reduces the colors using the supplied `color_map` and returns an image of the indices
pub fn index_colors<Pix, Map>(
    image: &ImageBuffer<Pix, Vec<u8>>,
    color_map: &Map,
) -> ImageBuffer<Luma<u8>, Vec<u8>>
where
    Map: ColorMap<Color = Pix>,
    Pix: Pixel<Subpixel = u8> + 'static,
{
    let mut indices = ImageBuffer::new(image.width(), image.height());
    for (pixel, idx) in image.pixels().zip(indices.pixels_mut()) {
        *idx = Luma([color_map.index_of(pixel) as u8])
    }
    indices
}

#[cfg(test)]
mod test {

    use super::*;
    use crate::ImageBuffer;

    #[test]
    fn test_dither() {
        let mut image = ImageBuffer::from_raw(2, 2, vec![127, 127, 127, 127]).unwrap();
        let cmap = BiLevel;
        dither(&mut image, &cmap);
        assert_eq!(&*image, &[0, 0xFF, 0xFF, 0]);
        assert_eq!(index_colors(&image, &cmap).into_raw(), vec![0, 1, 1, 0])
    }
}
<commit_msg>imageops/colorops: add default implementation for `ColorMap::lookup`.<commit_after>//! Functions for altering and converting the color of pixelbufs

use num_traits::{Num, NumCast};
use std::f64::consts::PI;

use crate::color::{Luma, Rgba};
use crate::image::{GenericImage, GenericImageView};
use crate::math::nq;
use crate::math::utils::clamp;
use crate::traits::{Pixel, Primitive};
use crate::ImageBuffer;

type Subpixel<I> = <<I as GenericImageView>::Pixel as Pixel>::Subpixel;

/// Convert the supplied image to grayscale
pub fn grayscale<I: GenericImageView>(image: &I) -> ImageBuffer<Luma<Subpixel<I>>, Vec<Subpixel<I>>>
where
    Subpixel<I>: 'static,
    <Subpixel<I> as Num>::FromStrRadixErr: 'static,
{
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    for y in 0..height {
        for x in 0..width {
            let p = image.get_pixel(x, y).to_luma();
            out.put_pixel(x, y, p);
        }
    }

    out
}

/// Invert each pixel within the supplied image.
/// This function operates in place.
pub fn invert<I: GenericImage>(image: &mut I) {
    let (width, height) = image.dimensions();

    for y in 0..height {
        for x in 0..width {
            let mut p = image.get_pixel(x, y);
            p.invert();

            image.put_pixel(x, y, p);
        }
    }
}

/// Adjust the contrast of the supplied image.
/// ```contrast``` is the amount to adjust the contrast by.
/// Negative values decrease the contrast and positive values increase the contrast.
pub fn contrast<I, P, S>(image: &I, contrast: f32) -> ImageBuffer<P, Vec<S>>
where
    I: GenericImageView<Pixel = P>,
    P: Pixel<Subpixel = S> + 'static,
    S: Primitive + 'static,
{
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let max = S::max_value();
    let max: f32 = NumCast::from(max).unwrap();

    let percent = ((100.0 + contrast) / 100.0).powi(2);

    for y in 0..height {
        for x in 0..width {
            let f = image.get_pixel(x, y).map(|b| {
                let c: f32 = NumCast::from(b).unwrap();

                let d = ((c / max - 0.5) * percent + 0.5) * max;
                let e = clamp(d, 0.0, max);

                NumCast::from(e).unwrap()
            });

            out.put_pixel(x, y, f);
        }
    }

    out
}

/// Brighten the supplied image.
/// ```value``` is the amount to brighten each pixel by.
/// Negative values decrease the brightness and positive values increase it.
pub fn brighten<I, P, S>(image: &I, value: i32) -> ImageBuffer<P, Vec<S>>
where
    I: GenericImageView<Pixel = P>,
    P: Pixel<Subpixel = S> + 'static,
    S: Primitive + 'static,
{
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let max = S::max_value();
    let max: i32 = NumCast::from(max).unwrap();

    for y in 0..height {
        for x in 0..width {
            let e = image.get_pixel(x, y).map_with_alpha(
                |b| {
                    let c: i32 = NumCast::from(b).unwrap();
                    let d = clamp(c + value, 0, max);

                    NumCast::from(d).unwrap()
                },
                |alpha| alpha,
            );

            out.put_pixel(x, y, e);
        }
    }

    out
}

/// Hue rotate the supplied image.
/// `value` is the degrees to rotate each pixel by.
/// 0 and 360 do nothing, the rest rotates by the given degree value.
/// just like the css webkit filter hue-rotate(180)
pub fn huerotate<I, P, S>(image: &I, value: i32) -> ImageBuffer<P, Vec<S>>
where
    I: GenericImageView<Pixel = P>,
    P: Pixel<Subpixel = S> + 'static,
    S: Primitive + 'static,
{
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    let angle: f64 = NumCast::from(value).unwrap();

    let cosv = (angle * PI / 180.0).cos();
    let sinv = (angle * PI / 180.0).sin();
    let matrix: [f64; 9] = [
        // Reds
        0.213 + cosv * 0.787 - sinv * 0.213,
        0.715 - cosv * 0.715 - sinv * 0.715,
        0.072 - cosv * 0.072 + sinv * 0.928,
        // Greens
        0.213 - cosv * 0.213 + sinv * 0.143,
        0.715 + cosv * 0.285 + sinv * 0.140,
        0.072 - cosv * 0.072 - sinv * 0.283,
        // Blues
        0.213 - cosv * 0.213 - sinv * 0.787,
        0.715 - cosv * 0.715 + sinv * 0.715,
        0.072 + cosv * 0.928 + sinv * 0.072,
    ];
    for (x, y, pixel) in out.enumerate_pixels_mut() {
        let p = image.get_pixel(x, y);
        let (k1, k2, k3, k4) = p.channels4();
        let vec: (f64, f64, f64, f64) = (
            NumCast::from(k1).unwrap(),
            NumCast::from(k2).unwrap(),
            NumCast::from(k3).unwrap(),
            NumCast::from(k4).unwrap(),
        );

        let r = vec.0;
        let g = vec.1;
        let b = vec.2;

        let new_r = matrix[0] * r + matrix[1] * g + matrix[2] * b;
        let new_g = matrix[3] * r + matrix[4] * g + matrix[5] * b;
        let new_b = matrix[6] * r + matrix[7] * g + matrix[8] * b;
        let max = 255f64;
        let outpixel = Pixel::from_channels(
            NumCast::from(clamp(new_r, 0.0, max)).unwrap(),
            NumCast::from(clamp(new_g, 0.0, max)).unwrap(),
            NumCast::from(clamp(new_b, 0.0, max)).unwrap(),
            NumCast::from(clamp(vec.3, 0.0, max)).unwrap(),
        );
        *pixel = outpixel;
    }
    out
}

/// A color map
pub trait ColorMap {
    /// The color type on which the map operates on
    type Color;
    /// Returns the index of the closest match of `color`
    /// in the color map.
    fn index_of(&self, color: &Self::Color) -> usize;
    /// Looks up color by index in the color map.  If `idx` is out of range for the color map, or
    /// ColorMap doesn't implement `lookup` `None` is returned.
    fn lookup(&self, _idx: usize) -> Option<Self::Color> {
        None
    }
    /// Determine if this implementation of ColorMap overrides the default `lookup`.
    fn has_lookup(&self) -> bool {
        false
    }
    /// Maps `color` to the closest color in the color map.
    fn map_color(&self, color: &mut Self::Color);
}

/// A bi-level color map
///
/// # Examples
/// ```
/// use image::imageops::colorops::{index_colors, BiLevel, ColorMap};
/// use image::{ImageBuffer, Luma};
///
/// let (w, h) = (16, 16);
/// // Create an image with a smooth horizontal gradient from black (0) to white (255).
/// let gray = ImageBuffer::from_fn(w, h, |x, y| -> Luma<u8> { [(255 * x / w) as u8].into() });
/// // Mapping the gray image through the `BiLevel` filter should map gray pixels less than half
/// // intensity (127) to black (0), and anything greater to white (255).
/// let cmap = BiLevel;
/// let palletized = index_colors(&gray, &cmap);
/// let mapped = ImageBuffer::from_fn(w, h, |x, y| {
///     let p = palletized.get_pixel(x, y);
///     cmap.lookup(p.0[0] as usize)
///         .expect("indexed color out-of-range")
/// });
/// // Create an black and white image of expected output.
/// let bw = ImageBuffer::from_fn(w, h, |x, y| -> Luma<u8> {
///     if x <= (w / 2) {
///         [0].into()
///     } else {
///         [255].into()
///     }
/// });
/// assert_eq!(mapped, bw);
/// ```
#[derive(Clone, Copy)]
pub struct BiLevel;

impl ColorMap for BiLevel {
    type Color = Luma<u8>;

    #[inline(always)]
    fn index_of(&self, color: &Luma<u8>) -> usize {
        let luma = color.0;
        if luma[0] > 127 {
            1
        } else {
            0
        }
    }

    #[inline(always)]
    fn lookup(&self, idx: usize) -> Option<Self::Color> {
        match idx {
            0 => Some([0].into()),
            1 => Some([255].into()),
            _ => None,
        }
    }

    /// Indicate NeuQuant implements `lookup`.
    fn has_lookup(&self) -> bool {
        true
    }

    #[inline(always)]
    fn map_color(&self, color: &mut Luma<u8>) {
        let new_color = 0xFF * self.index_of(color) as u8;
        let luma = &mut color.0;
        luma[0] = new_color;
    }
}

impl ColorMap for nq::NeuQuant {
    type Color = Rgba<u8>;

    #[inline(always)]
    fn index_of(&self, color: &Rgba<u8>) -> usize {
        self.index_of(color.channels())
    }

    #[inline(always)]
    fn lookup(&self, idx: usize) -> Option<Self::Color> {
        self.lookup(idx).map(|p| p.into())
    }

    /// Indicate NeuQuant implements `lookup`.
    fn has_lookup(&self) -> bool {
        true
    }

    #[inline(always)]
    fn map_color(&self, color: &mut Rgba<u8>) {
        self.map_pixel(color.channels_mut())
    }
}

/// Floyd-Steinberg error diffusion
fn diffuse_err<P: Pixel<Subpixel = u8>>(pixel: &mut P, error: [i16; 3], factor: i16) {
    for (e, c) in error.iter().zip(pixel.channels_mut().iter_mut()) {
        *c = match <i16 as From<_>>::from(*c) + e * factor / 16 {
            val if val < 0 => 0,
            val if val > 0xFF => 0xFF,
            val => val as u8,
        }
    }
}

macro_rules! do_dithering(
    ($map:expr, $image:expr, $err:expr, $x:expr, $y:expr) => (
        {
            let old_pixel = $image[($x, $y)];
            let new_pixel = $image.get_pixel_mut($x, $y);
            $map.map_color(new_pixel);
            for ((e, &old), &new) in $err.iter_mut()
                                        .zip(old_pixel.channels().iter())
                                        .zip(new_pixel.channels().iter())
            {
                *e = <i16 as From<_>>::from(old) - <i16 as From<_>>::from(new)
            }
        }
    )
);

/// Reduces the colors of the image using the supplied `color_map` while applying
/// Floyd-Steinberg dithering to improve the visual conception
pub fn dither<Pix, Map>(image: &mut ImageBuffer<Pix, Vec<u8>>, color_map: &Map)
where
    Map: ColorMap<Color = Pix>,
    Pix: Pixel<Subpixel = u8> + 'static,
{
    let (width, height) = image.dimensions();
    let mut err: [i16; 3] = [0; 3];
    for y in 0..height - 1 {
        let x = 0;
        do_dithering!(color_map, image, err, x, y);
        diffuse_err(image.get_pixel_mut(x + 1, y), err, 7);
        diffuse_err(image.get_pixel_mut(x, y + 1), err, 5);
        diffuse_err(image.get_pixel_mut(x + 1, y + 1), err, 1);
        for x in 1..width - 1 {
            do_dithering!(color_map, image, err, x, y);
            diffuse_err(image.get_pixel_mut(x + 1, y), err, 7);
            diffuse_err(image.get_pixel_mut(x - 1, y + 1), err, 3);
            diffuse_err(image.get_pixel_mut(x, y + 1), err, 5);
            diffuse_err(image.get_pixel_mut(x + 1, y + 1), err, 1);
        }
        let x = width - 1;
        do_dithering!(color_map, image, err, x, y);
        diffuse_err(image.get_pixel_mut(x - 1, y + 1), err, 3);
        diffuse_err(image.get_pixel_mut(x, y + 1), err, 5);
    }
    let y = height - 1;
    let x = 0;
    do_dithering!(color_map, image, err, x, y);
    diffuse_err(image.get_pixel_mut(x + 1, y), err, 7);
    for x in 1..width - 1 {
        do_dithering!(color_map, image, err, x, y);
        diffuse_err(image.get_pixel_mut(x + 1, y), err, 7);
    }
    let x = width - 1;
    do_dithering!(color_map, image, err, x, y);
}

/// Reduces the colors using the supplied `color_map` and returns an image of the indices
pub fn index_colors<Pix, Map>(
    image: &ImageBuffer<Pix, Vec<u8>>,
    color_map: &Map,
) -> ImageBuffer<Luma<u8>, Vec<u8>>
where
    Map: ColorMap<Color = Pix>,
    Pix: Pixel<Subpixel = u8> + 'static,
{
    let mut indices = ImageBuffer::new(image.width(), image.height());
    for (pixel, idx) in image.pixels().zip(indices.pixels_mut()) {
        *idx = Luma([color_map.index_of(pixel) as u8])
    }
    indices
}

#[cfg(test)]
mod test {

    use super::*;
    use crate::ImageBuffer;

    #[test]
    fn test_dither() {
        let mut image = ImageBuffer::from_raw(2, 2, vec![127, 127, 127, 127]).unwrap();
        let cmap = BiLevel;
        dither(&mut image, &cmap);
        assert_eq!(&*image, &[0, 0xFF, 0xFF, 0]);
        assert_eq!(index_colors(&image, &cmap).into_raw(), vec![0, 1, 1, 0])
    }
}
<|endoftext|>


<commit_before>use super::Mode;
use super::KeyMap;
use super::Key;
use super::Command;
use super::KeyMapState;
use super::Direction;
use super::WordEdgeMatch;
use super::OverlayType;

pub struct NormalMode {
    keymap: KeyMap,
}

impl NormalMode {

    pub fn new() -> NormalMode {
        NormalMode {
            keymap: NormalMode::key_defaults(),
        }
    }

    fn key_defaults() -> KeyMap {
        let mut keymap = KeyMap::new();

        // movement
        keymap.bind_key(Key::Up, Command::MoveCursor(Direction::Up(1)));
        keymap.bind_key(Key::Down, Command::MoveCursor(Direction::Down(1)));
        keymap.bind_key(Key::Left, Command::MoveCursor(Direction::Left(1)));
        keymap.bind_key(Key::Right, Command::MoveCursor(Direction::Right(1)));
        keymap.bind_key(Key::Char('h'), Command::MoveCursor(Direction::Left(1)));
        keymap.bind_key(Key::Char('j'), Command::MoveCursor(Direction::Down(1)));
        keymap.bind_key(Key::Char('k'), Command::MoveCursor(Direction::Up(1)));
        keymap.bind_key(Key::Char('l'), Command::MoveCursor(Direction::Right(1)));
        keymap.bind_key(Key::Char('W'), Command::MoveCursor(Direction::RightWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_key(Key::Char('B'), Command::MoveCursor(Direction::LeftWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_key(Key::Char('w'), Command::MoveCursor(Direction::RightWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('b'), Command::MoveCursor(Direction::LeftWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('0'), Command::LineStart);
        keymap.bind_key(Key::Char('$'), Command::LineEnd);

        // editing
        keymap.bind_keys(&[Key::Char('d'), Key::Char('W')], Command::Delete(Direction::RightWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('B')], Command::Delete(Direction::LeftWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('w')], Command::Delete(Direction::RightWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('b')], Command::Delete(Direction::LeftWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('x'), Command::Delete(Direction::Right(1)));
        keymap.bind_key(Key::Char('X'), Command::Delete(Direction::Left(1)));
        keymap.bind_key(Key::Char('u'), Command::Undo);
        keymap.bind_key(Key::Ctrl('r'), Command::Redo);

        // open a prompt to the user
        keymap.bind_key(Key::Char(':'), Command::SetOverlay(OverlayType::Prompt));

        keymap
    }

}

impl Mode for NormalMode {
    fn handle_key_event(&mut self, key: Key) -> Command {
        if let KeyMapState::Match(command) = self.keymap.check_key(key) {
            return command
        }

        Command::Unknown
    }
}
<commit_msg>Added basic test for normal mode<commit_after>use super::Mode;
use super::KeyMap;
use super::Key;
use super::Command;
use super::KeyMapState;
use super::Direction;
use super::WordEdgeMatch;
use super::OverlayType;

pub struct NormalMode {
    keymap: KeyMap,
}

impl NormalMode {

    pub fn new() -> NormalMode {
        NormalMode {
            keymap: NormalMode::key_defaults(),
        }
    }

    fn key_defaults() -> KeyMap {
        let mut keymap = KeyMap::new();

        // movement
        keymap.bind_key(Key::Up, Command::MoveCursor(Direction::Up(1)));
        keymap.bind_key(Key::Down, Command::MoveCursor(Direction::Down(1)));
        keymap.bind_key(Key::Left, Command::MoveCursor(Direction::Left(1)));
        keymap.bind_key(Key::Right, Command::MoveCursor(Direction::Right(1)));
        keymap.bind_key(Key::Char('h'), Command::MoveCursor(Direction::Left(1)));
        keymap.bind_key(Key::Char('j'), Command::MoveCursor(Direction::Down(1)));
        keymap.bind_key(Key::Char('k'), Command::MoveCursor(Direction::Up(1)));
        keymap.bind_key(Key::Char('l'), Command::MoveCursor(Direction::Right(1)));
        keymap.bind_key(Key::Char('W'), Command::MoveCursor(Direction::RightWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_key(Key::Char('B'), Command::MoveCursor(Direction::LeftWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_key(Key::Char('w'), Command::MoveCursor(Direction::RightWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('b'), Command::MoveCursor(Direction::LeftWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('0'), Command::LineStart);
        keymap.bind_key(Key::Char('$'), Command::LineEnd);

        // editing
        keymap.bind_keys(&[Key::Char('d'), Key::Char('W')], Command::Delete(Direction::RightWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('B')], Command::Delete(Direction::LeftWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('w')], Command::Delete(Direction::RightWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('b')], Command::Delete(Direction::LeftWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('x'), Command::Delete(Direction::Right(1)));
        keymap.bind_key(Key::Char('X'), Command::Delete(Direction::Left(1)));
        keymap.bind_key(Key::Char('u'), Command::Undo);
        keymap.bind_key(Key::Ctrl('r'), Command::Redo);

        // open a prompt to the user
        keymap.bind_key(Key::Char(':'), Command::SetOverlay(OverlayType::Prompt));

        keymap
    }

}

impl Mode for NormalMode {
    fn handle_key_event(&mut self, key: Key) -> Command {
        if let KeyMapState::Match(command) = self.keymap.check_key(key) {
            return command
        }

        Command::Unknown
    }
}

#[cfg(test)]
mod tests {
    use editor::Command;
    use buffer::Direction;
    use keyboard::Key;
    use modes::Mode;
    use super::*;

    fn expect_key_command(k: Key, c: Command) {
        let mut mode: Box<Mode> = box NormalMode::new();
        let command = mode.handle_key_event(k);
        assert_eq!(command, c)
    }

    #[test]
    fn test_movement_keybindings() {
        expect_key_command(Key::Char('h'), Command::MoveCursor(Direction::Left(1)));
        expect_key_command(Key::Char('j'), Command::MoveCursor(Direction::Down(1)));
        expect_key_command(Key::Char('k'), Command::MoveCursor(Direction::Up(1)));
        expect_key_command(Key::Char('l'), Command::MoveCursor(Direction::Right(1)));
    }
}
<|endoftext|>


<commit_before>use std::ptr;
use std::mem;
use super::LayoutBox;

/// Mutable iterator over LayoutBuffer
pub struct LayoutBoxIterMut {
    current: *mut LayoutBox,
}

impl LayoutBoxIterMut {
    pub fn new(boxes: &mut Box<[LayoutBox]>) -> LayoutBoxIterMut {
        let lbox = boxes.iter().next().unwrap();
        LayoutBoxIterMut {
            current: unsafe { mem::transmute(lbox) }
        }
    }

    pub unsafe fn new_with_childnode(lbox: & LayoutBox) -> LayoutBoxIterMut {
        let ptr: *mut LayoutBox = mem::transmute(lbox);
        LayoutBoxIterMut {
            current: ptr.offset(1)
        }
    }

    pub fn new_empty() -> LayoutBoxIterMut {
        LayoutBoxIterMut {
            current: ptr::null_mut()
        }
    }
}

impl<'a> Iterator for LayoutBoxIterMut {
    type Item = &'a mut LayoutBox;

    fn next(&mut self) -> Option<&mut LayoutBox> {
        if self.current.is_null() {
            None
        } else {
            let node = unsafe { &mut *self.current };
            if node.next_sibling > 0 {
                unsafe {
                    self.current = self.current.offset(node.next_sibling);
                }
            } else {
                self.current = ptr::null_mut();
            }
            Some(node)
        }
    }
}

/// Immutable iterator over LayoutBuffer
pub struct LayoutBoxIter {
    current: *const LayoutBox,
}

impl LayoutBoxIter {
    pub fn new(boxes: &Box<[LayoutBox]>) -> LayoutBoxIter {
        let lbox = boxes.iter().next().unwrap();
        LayoutBoxIter {
            current: unsafe { mem::transmute(lbox) }
        }
    }

    pub unsafe fn new_with_childnode(lbox: & LayoutBox) -> LayoutBoxIter {
        let ptr: *mut LayoutBox = mem::transmute(lbox);
        LayoutBoxIter {
            current: ptr.offset(1)
        }
    }

    pub fn new_empty() -> LayoutBoxIter {
        LayoutBoxIter {
            current: ptr::null()
        }
    }
}

impl<'a> Iterator for LayoutBoxIter {
    type Item = &'a LayoutBox;

    fn next(&mut self) -> Option<&LayoutBox> {
        if self.current.is_null() {
            None
        } else {
            let node = unsafe { &*self.current };
            if node.next_sibling > 0 {
                unsafe {
                    self.current = self.current.offset(node.next_sibling);
                }
            } else {
                self.current = ptr::null();
            }
            Some(node)
        }
    }
}
<commit_msg>Added PhantomData to limit lifetime of iterators to the lifetime of the LayoutBuffer. --Need tests.<commit_after>use std::ptr;
use std::mem;
use std::marker;
use super::LayoutBox;
use layout::LayoutBuffer;

/// Mutable iterator over LayoutBuffer
pub struct LayoutBoxIterMut<'a> {
    current: *mut LayoutBox,
    _marker: marker::PhantomData<&'a mut LayoutBuffer>,
}

impl<'s> LayoutBoxIterMut<'s> {
    pub fn new<'a>(boxes: &'a mut Box<[LayoutBox]>) -> LayoutBoxIterMut<'a> {
        let lbox = boxes.iter().next().unwrap();
        LayoutBoxIterMut {
            current: unsafe { mem::transmute(lbox) },
            _marker: marker::PhantomData
        }
    }

    pub unsafe fn new_with_childnode<'a>(lbox: &'a LayoutBox) -> LayoutBoxIterMut<'a> {
        let ptr: *mut LayoutBox = mem::transmute(lbox);
        LayoutBoxIterMut {
            current: ptr.offset(1),
            _marker: marker::PhantomData
        }
    }

    pub fn new_empty<'a>() -> LayoutBoxIterMut<'a> {
        LayoutBoxIterMut {
            current: ptr::null_mut(),
            _marker: marker::PhantomData
        }
    }
}

impl<'b, 'a> Iterator for LayoutBoxIterMut<'b> {
    type Item = &'a mut LayoutBox;

    fn next(&mut self) -> Option<&mut LayoutBox> {
        if self.current.is_null() {
            None
        } else {
            let node = unsafe { &mut *self.current };
            if node.next_sibling > 0 {
                unsafe {
                    self.current = self.current.offset(node.next_sibling);
                }
            } else {
                self.current = ptr::null_mut();
            }
            Some(node)
        }
    }
}

/// Immutable iterator over LayoutBuffer
pub struct LayoutBoxIter<'a> {
    current: *const LayoutBox,
    _marker: marker::PhantomData<&'a LayoutBuffer>,
}

impl<'s> LayoutBoxIter<'s> {
    pub fn new<'a>(boxes: &'a Box<[LayoutBox]>) -> LayoutBoxIter<'a> {
        let lbox = boxes.iter().next().unwrap();
        LayoutBoxIter {
            current: unsafe { mem::transmute(lbox) },
            _marker: marker::PhantomData
        }
    }

    pub unsafe fn new_with_childnode<'a>(lbox: &'a LayoutBox) -> LayoutBoxIter<'a> {
        let ptr: *mut LayoutBox = mem::transmute(lbox);
        LayoutBoxIter {
            current: ptr.offset(1),
            _marker: marker::PhantomData
        }
    }

    pub fn new_empty<'a>() -> LayoutBoxIter<'a> {
        LayoutBoxIter {
            current: ptr::null(),
            _marker: marker::PhantomData
        }
    }
}

impl<'a, 'b> Iterator for LayoutBoxIter<'b> {
    type Item = &'a LayoutBox;

    fn next(&mut self) -> Option<&LayoutBox> {
        if self.current.is_null() {
            None
        } else {
            let node = unsafe { &*self.current };
            if node.next_sibling > 0 {
                unsafe {
                    self.current = self.current.offset(node.next_sibling);
                }
            } else {
                self.current = ptr::null();
            }
            Some(node)
        }
    }
}
<|endoftext|>