<commit_before>use std::mem;
use rect::Rect;
use get_error;
use SdlResult;
use std::ptr;
use libc::c_int;
use pixels;
use rwops;

#[allow(non_camel_case_types)]
pub mod ll {
    use pixels::ll::SDL_PixelFormat;
    use pixels::ll::SDL_Palette;
    use render::ll::SDL_BlendMode;
    use rwops::ll::SDL_RWops;
    use rect::Rect;
    use libc::{c_int, c_void, uint32_t, uint8_t};
    pub type SDL_Rect = Rect;
    pub type SDL_bool = c_int;

    pub type SDL_SurfaceFlag = c_int;

    pub static SDL_SWSURFACE: SDL_SurfaceFlag = 0;
    pub static SDL_PREALLOC: SDL_SurfaceFlag = 0x00000001;
    pub static SDL_RLEACCEL: SDL_SurfaceFlag = 0x00000002;
    pub static SDL_DONTFREE: SDL_SurfaceFlag = 0x00000004;

    //SDL_surface.h
    pub struct SDL_BlitMap;

    pub struct SDL_Surface {
        pub flags: uint32_t,
        pub format: *const SDL_PixelFormat,
        pub w: c_int,
        pub h: c_int,
        pub pitch: c_int,
        pub pixels: *const c_void,
        pub userdata: *const c_void,
        pub locked: c_int,
        pub lock_data: *const c_void,
        pub clip_rect: SDL_Rect,
        pub map: *const SDL_BlitMap,
        pub refcount: c_int
    }

    extern "C" {
        pub fn SDL_CreateRGBSurface(flags: uint32_t, width: c_int, height: c_int, depth: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *const SDL_Surface;
        pub fn SDL_CreateRGBSurfaceFrom(pixels: *const c_void, width: c_int, height: c_int, depth: c_int, pitch: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *const SDL_Surface;
        pub fn SDL_FreeSurface(surface: *const SDL_Surface);
        pub fn SDL_SetSurfacePalette(surface: *const SDL_Surface, palette: *const SDL_Palette) -> c_int;
        pub fn SDL_LockSurface(surface: *const SDL_Surface) -> c_int;
        pub fn SDL_UnlockSurface(surface: *const SDL_Surface);
        pub fn SDL_LoadBMP_RW(src: *const SDL_RWops, freesrc: c_int) ->  *const SDL_Surface;
        pub fn SDL_SaveBMP_RW(surface: *const SDL_Surface, dst: *const SDL_RWops, freedst: c_int) -> c_int;
        pub fn SDL_SetSurfaceRLE(surface: *const SDL_Surface, flag: c_int) -> c_int;
        pub fn SDL_SetColorKey(surface: *const SDL_Surface, flag: c_int, key: uint32_t) -> c_int;
        pub fn SDL_GetColorKey(surface: *const SDL_Surface, key: *const uint32_t) -> c_int;
        pub fn SDL_SetSurfaceColorMod(surface: *const SDL_Surface, r: uint8_t, g: uint8_t, b: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceColorMod(surface: *const SDL_Surface, r: *const uint8_t, g: *const uint8_t, b: *const uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceAlphaMod(surface: *const SDL_Surface, alpha: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceAlphaMod(surface: *const SDL_Surface, alpha: *const uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceBlendMode(surface: *const SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
        pub fn SDL_GetSurfaceBlendMode(surface: *const SDL_Surface, blendMode: *const SDL_BlendMode) -> c_int;
        pub fn SDL_SetClipRect(surface: *const SDL_Surface, rect: *const SDL_Rect) ->  SDL_bool;
        pub fn SDL_GetClipRect(surface: *const SDL_Surface, rect: *const SDL_Rect);
        pub fn SDL_ConvertSurface(src: *const SDL_Surface, fmt: *const SDL_PixelFormat, flags: uint32_t) ->  *const SDL_Surface;
        pub fn SDL_ConvertSurfaceFormat(src: *const SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *const SDL_Surface;
        pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *const c_void, src_pitch: c_int, dst_format: uint32_t, dst: *const c_void, dst_pitch: c_int) -> c_int;
        pub fn SDL_FillRect(dst: *const SDL_Surface, rect: *const SDL_Rect, color: uint32_t) -> c_int;
        pub fn SDL_FillRects(dst: *const SDL_Surface, rects: *const SDL_Rect, count: c_int, color: uint32_t) -> c_int;
        pub fn SDL_UpperBlit(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
        pub fn SDL_LowerBlit(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
        pub fn SDL_SoftStretch(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
        pub fn SDL_UpperBlitScaled(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
        pub fn SDL_LowerBlitScaled(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
    }
}

bitflags!(flags SurfaceFlag: u32 {
    static SWSurface = ll::SDL_SWSURFACE as u32,
    static PreAlloc = ll::SDL_PREALLOC as u32,
    static RLEAccel = ll::SDL_RLEACCEL as u32,
    static DontFree = ll::SDL_DONTFREE as u32
})

#[deriving(PartialEq)]
#[allow(raw_pointer_deriving)]
pub struct Surface {
    raw: *const ll::SDL_Surface,
    owned: bool
}

impl Drop for Surface {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                ll::SDL_FreeSurface(self.raw);
            }
        }
    }
}

impl_raw_accessors!(Surface, *const ll::SDL_Surface)
impl_owned_accessors!(Surface, owned)
impl_raw_constructor!(Surface -> Surface (raw: *const ll::SDL_Surface, owned: bool))

impl Surface {
    pub fn new(surface_flags: SurfaceFlag, width: int, height: int, bpp: int,
               rmask: u32, gmask: u32, bmask: u32, amask: u32) -> SdlResult<Surface> {
        unsafe {
            let raw = ll::SDL_CreateRGBSurface(surface_flags.bits(), width as c_int, height as c_int, bpp as c_int,
                                               rmask, gmask, bmask, amask);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface { raw: raw, owned: true })
            }
        }
    }

    //TODO: From Data
    pub fn get_width(&self) -> u16 {
        unsafe { (*self.raw).w as u16 }
    }

    pub fn get_height(&self) -> u16 {
        unsafe { (*self.raw).h as u16 }
    }

    pub fn get_size(&self) -> (u16, u16) {
        (self.get_width(), self.get_height())
    }

    pub fn get_rect(&self) -> Rect {
        Rect {
            x: 0,
            y: 0,
            w: self.get_width() as i32,
            h: self.get_height() as i32
        }
    }

    pub fn get_pixel_format(&self) -> pixels::PixelFormat {
        unsafe {
            pixels::PixelFormat::from_ll((*self.raw).format)
        }
    }

    pub fn lock(&self) -> bool {
        unsafe { ll::SDL_LockSurface(self.raw) == 0 }
    }

    /// Locks a surface so that the pixels can be directly accessed safely.
    pub fn with_lock<R>(&self, f: |pixels: &mut [u8]| -> R) -> R {
        unsafe {
            if ll::SDL_LockSurface(self.raw) != 0 { fail!("could not lock surface"); }
            let len = (*self.raw).pitch as uint * ((*self.raw).h as uint);
            let pixels: &mut [u8] = mem::transmute(((*self.raw).pixels, len));
            let rv = f(pixels);
            ll::SDL_UnlockSurface(self.raw);
            rv
        }
    }

    pub fn unlock(&self) {
        unsafe { ll::SDL_UnlockSurface(self.raw); }
    }

    pub fn from_bmp(path: &Path) -> SdlResult<Surface> {
        let raw = unsafe {
            ll::SDL_LoadBMP_RW(try!(rwops::RWops::from_file(path, "rb")).raw(), 0)
        };

        if raw.is_null() { Err(get_error()) }
        else { Ok(Surface{raw: raw, owned: true}) }
    }

    pub fn save_bmp(&self, path: &Path) -> SdlResult<()> {
	let ret = unsafe {
            ll::SDL_SaveBMP_RW(self.raw, try!(rwops::RWops::from_file(path, "rb")).raw(), 0)
	};
        if ret == 0 { Ok(()) }
        else { Err(get_error()) }
    }

    pub fn set_palette(&self, palette: &pixels::Palette) -> bool {
        unsafe {
            ll::SDL_SetSurfacePalette(self.raw, palette.raw()) == 0
        }
    }

    #[allow(non_snake_case_functions)]
    pub fn enable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 1) == 0
        }
    }

    #[allow(non_snake_case_functions)]
    pub fn disable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 0) == 0
        }
    }

    pub fn set_color_key(&self, enable: bool, color: pixels::Color) -> SdlResult<()> {
        let key = color.to_u32(&self.get_pixel_format());
        let result = unsafe {
            ll::SDL_SetColorKey(self.raw, if enable { 1 } else { 0 }, key)
        };
        if result == 0 {
            Ok(())
        } else {
            Err(get_error())
        }
    }

    pub fn get_color_key(&self) -> SdlResult<pixels::Color> {
        let key: u32 = 0;
        let result = unsafe {
            ll::SDL_GetColorKey(self.raw, &key)
        };

        if result == 0 {
            Ok(pixels::Color::from_u32(&self.get_pixel_format(), key))
        } else {
            Err(get_error())
        }
    }

    pub fn set_color_mod(&self, color: pixels::Color) -> bool {
        let (r, g, b) = match color {
            pixels::RGB(r, g, b) => (r, g, b),
            pixels::RGBA(r, g, b, _) => (r, g, b)
        };

        unsafe {
            ll::SDL_SetSurfaceColorMod(self.raw, r, g, b) == 0
        }
    }

    pub fn get_color_mod(&self) -> SdlResult<pixels::Color> {
        let r: u8 = 0;
        let g: u8 = 0;
        let b: u8 = 0;

        let result = unsafe {
            ll::SDL_GetSurfaceColorMod(self.raw, &r, &g, &b) == 0
        };

        if result {
            Ok(pixels::RGB(r,g,b))
        } else {
            Err(get_error())
        }
    }

    pub fn blit( &self, src: &Surface, dstrect: Option<Rect>, srcrect: Option<Rect> ) -> bool {
        unsafe {
            let dstrect_ptr = mem::transmute( dstrect.as_ref() );
            let srcrect_ptr = mem::transmute( srcrect.as_ref() );
            ll::SDL_UpperBlit( src.raw, srcrect_ptr, self.raw, dstrect_ptr ) == 0
        }
    }

    /*
    pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
    pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
    pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
    pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
    pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
    pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
    pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
    pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
    pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
    pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int)*/
}
<commit_msg>surface.rs: added get_pitch, changed width and height casts to int.<commit_after>use std::mem;
use rect::Rect;
use get_error;
use SdlResult;
use std::ptr;
use libc::c_int;
use pixels;
use rwops;

#[allow(non_camel_case_types)]
pub mod ll {
    use pixels::ll::SDL_PixelFormat;
    use pixels::ll::SDL_Palette;
    use render::ll::SDL_BlendMode;
    use rwops::ll::SDL_RWops;
    use rect::Rect;
    use libc::{c_int, c_void, uint32_t, uint8_t};
    pub type SDL_Rect = Rect;
    pub type SDL_bool = c_int;

    pub type SDL_SurfaceFlag = c_int;

    pub static SDL_SWSURFACE: SDL_SurfaceFlag = 0;
    pub static SDL_PREALLOC: SDL_SurfaceFlag = 0x00000001;
    pub static SDL_RLEACCEL: SDL_SurfaceFlag = 0x00000002;
    pub static SDL_DONTFREE: SDL_SurfaceFlag = 0x00000004;

    //SDL_surface.h
    pub struct SDL_BlitMap;

    pub struct SDL_Surface {
        pub flags: uint32_t,
        pub format: *const SDL_PixelFormat,
        pub w: c_int,
        pub h: c_int,
        pub pitch: c_int,
        pub pixels: *const c_void,
        pub userdata: *const c_void,
        pub locked: c_int,
        pub lock_data: *const c_void,
        pub clip_rect: SDL_Rect,
        pub map: *const SDL_BlitMap,
        pub refcount: c_int
    }

    extern "C" {
        pub fn SDL_CreateRGBSurface(flags: uint32_t, width: c_int, height: c_int, depth: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *const SDL_Surface;
        pub fn SDL_CreateRGBSurfaceFrom(pixels: *const c_void, width: c_int, height: c_int, depth: c_int, pitch: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *const SDL_Surface;
        pub fn SDL_FreeSurface(surface: *const SDL_Surface);
        pub fn SDL_SetSurfacePalette(surface: *const SDL_Surface, palette: *const SDL_Palette) -> c_int;
        pub fn SDL_LockSurface(surface: *const SDL_Surface) -> c_int;
        pub fn SDL_UnlockSurface(surface: *const SDL_Surface);
        pub fn SDL_LoadBMP_RW(src: *const SDL_RWops, freesrc: c_int) ->  *const SDL_Surface;
        pub fn SDL_SaveBMP_RW(surface: *const SDL_Surface, dst: *const SDL_RWops, freedst: c_int) -> c_int;
        pub fn SDL_SetSurfaceRLE(surface: *const SDL_Surface, flag: c_int) -> c_int;
        pub fn SDL_SetColorKey(surface: *const SDL_Surface, flag: c_int, key: uint32_t) -> c_int;
        pub fn SDL_GetColorKey(surface: *const SDL_Surface, key: *const uint32_t) -> c_int;
        pub fn SDL_SetSurfaceColorMod(surface: *const SDL_Surface, r: uint8_t, g: uint8_t, b: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceColorMod(surface: *const SDL_Surface, r: *const uint8_t, g: *const uint8_t, b: *const uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceAlphaMod(surface: *const SDL_Surface, alpha: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceAlphaMod(surface: *const SDL_Surface, alpha: *const uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceBlendMode(surface: *const SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
        pub fn SDL_GetSurfaceBlendMode(surface: *const SDL_Surface, blendMode: *const SDL_BlendMode) -> c_int;
        pub fn SDL_SetClipRect(surface: *const SDL_Surface, rect: *const SDL_Rect) ->  SDL_bool;
        pub fn SDL_GetClipRect(surface: *const SDL_Surface, rect: *const SDL_Rect);
        pub fn SDL_ConvertSurface(src: *const SDL_Surface, fmt: *const SDL_PixelFormat, flags: uint32_t) ->  *const SDL_Surface;
        pub fn SDL_ConvertSurfaceFormat(src: *const SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *const SDL_Surface;
        pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *const c_void, src_pitch: c_int, dst_format: uint32_t, dst: *const c_void, dst_pitch: c_int) -> c_int;
        pub fn SDL_FillRect(dst: *const SDL_Surface, rect: *const SDL_Rect, color: uint32_t) -> c_int;
        pub fn SDL_FillRects(dst: *const SDL_Surface, rects: *const SDL_Rect, count: c_int, color: uint32_t) -> c_int;
        pub fn SDL_UpperBlit(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
        pub fn SDL_LowerBlit(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
        pub fn SDL_SoftStretch(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
        pub fn SDL_UpperBlitScaled(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
        pub fn SDL_LowerBlitScaled(src: *const SDL_Surface, srcrect: *const SDL_Rect, dst: *const SDL_Surface, dstrect: *const SDL_Rect) -> c_int;
    }
}

bitflags!(flags SurfaceFlag: u32 {
    static SWSurface = ll::SDL_SWSURFACE as u32,
    static PreAlloc = ll::SDL_PREALLOC as u32,
    static RLEAccel = ll::SDL_RLEACCEL as u32,
    static DontFree = ll::SDL_DONTFREE as u32
})

#[deriving(PartialEq)]
#[allow(raw_pointer_deriving)]
pub struct Surface {
    raw: *const ll::SDL_Surface,
    owned: bool
}

impl Drop for Surface {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                ll::SDL_FreeSurface(self.raw);
            }
        }
    }
}

impl_raw_accessors!(Surface, *const ll::SDL_Surface)
impl_owned_accessors!(Surface, owned)
impl_raw_constructor!(Surface -> Surface (raw: *const ll::SDL_Surface, owned: bool))

impl Surface {
    pub fn new(surface_flags: SurfaceFlag, width: int, height: int, bpp: int,
               rmask: u32, gmask: u32, bmask: u32, amask: u32) -> SdlResult<Surface> {
        unsafe {
            let raw = ll::SDL_CreateRGBSurface(surface_flags.bits(), width as c_int, height as c_int, bpp as c_int,
                                               rmask, gmask, bmask, amask);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface { raw: raw, owned: true })
            }
        }
    }

    //TODO: From Data
    pub fn get_width(&self) -> int {
        unsafe { (*self.raw).w as int }
    }

    pub fn get_height(&self) -> int {
        unsafe { (*self.raw).h as int }
    }

    pub fn get_pitch(&self) -> int {
        unsafe { (*self.raw).pitch as int }
    }

    pub fn get_size(&self) -> (int, int) {
        (self.get_width(), self.get_height())
    }

    pub fn get_rect(&self) -> Rect {
        Rect {
            x: 0,
            y: 0,
            w: self.get_width() as i32,
            h: self.get_height() as i32
        }
    }

    pub fn get_pixel_format(&self) -> pixels::PixelFormat {
        unsafe {
            pixels::PixelFormat::from_ll((*self.raw).format)
        }
    }

    pub fn lock(&self) -> bool {
        unsafe { ll::SDL_LockSurface(self.raw) == 0 }
    }

    /// Locks a surface so that the pixels can be directly accessed safely.
    pub fn with_lock<R>(&self, f: |pixels: &mut [u8]| -> R) -> R {
        unsafe {
            if ll::SDL_LockSurface(self.raw) != 0 { fail!("could not lock surface"); }
            let len = (*self.raw).pitch as uint * ((*self.raw).h as uint);
            let pixels: &mut [u8] = mem::transmute(((*self.raw).pixels, len));
            let rv = f(pixels);
            ll::SDL_UnlockSurface(self.raw);
            rv
        }
    }

    pub fn unlock(&self) {
        unsafe { ll::SDL_UnlockSurface(self.raw); }
    }

    pub fn from_bmp(path: &Path) -> SdlResult<Surface> {
        let raw = unsafe {
            ll::SDL_LoadBMP_RW(try!(rwops::RWops::from_file(path, "rb")).raw(), 0)
        };

        if raw.is_null() { Err(get_error()) }
        else { Ok(Surface{raw: raw, owned: true}) }
    }

    pub fn save_bmp(&self, path: &Path) -> SdlResult<()> {
	let ret = unsafe {
            ll::SDL_SaveBMP_RW(self.raw, try!(rwops::RWops::from_file(path, "rb")).raw(), 0)
	};
        if ret == 0 { Ok(()) }
        else { Err(get_error()) }
    }

    pub fn set_palette(&self, palette: &pixels::Palette) -> bool {
        unsafe {
            ll::SDL_SetSurfacePalette(self.raw, palette.raw()) == 0
        }
    }

    #[allow(non_snake_case_functions)]
    pub fn enable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 1) == 0
        }
    }

    #[allow(non_snake_case_functions)]
    pub fn disable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 0) == 0
        }
    }

    pub fn set_color_key(&self, enable: bool, color: pixels::Color) -> SdlResult<()> {
        let key = color.to_u32(&self.get_pixel_format());
        let result = unsafe {
            ll::SDL_SetColorKey(self.raw, if enable { 1 } else { 0 }, key)
        };
        if result == 0 {
            Ok(())
        } else {
            Err(get_error())
        }
    }

    pub fn get_color_key(&self) -> SdlResult<pixels::Color> {
        let key: u32 = 0;
        let result = unsafe {
            ll::SDL_GetColorKey(self.raw, &key)
        };

        if result == 0 {
            Ok(pixels::Color::from_u32(&self.get_pixel_format(), key))
        } else {
            Err(get_error())
        }
    }

    pub fn set_color_mod(&self, color: pixels::Color) -> bool {
        let (r, g, b) = match color {
            pixels::RGB(r, g, b) => (r, g, b),
            pixels::RGBA(r, g, b, _) => (r, g, b)
        };

        unsafe {
            ll::SDL_SetSurfaceColorMod(self.raw, r, g, b) == 0
        }
    }

    pub fn get_color_mod(&self) -> SdlResult<pixels::Color> {
        let r: u8 = 0;
        let g: u8 = 0;
        let b: u8 = 0;

        let result = unsafe {
            ll::SDL_GetSurfaceColorMod(self.raw, &r, &g, &b) == 0
        };

        if result {
            Ok(pixels::RGB(r,g,b))
        } else {
            Err(get_error())
        }
    }

    pub fn blit( &self, src: &Surface, dstrect: Option<Rect>, srcrect: Option<Rect> ) -> bool {
        unsafe {
            let dstrect_ptr = mem::transmute( dstrect.as_ref() );
            let srcrect_ptr = mem::transmute( srcrect.as_ref() );
            ll::SDL_UpperBlit( src.raw, srcrect_ptr, self.raw, dstrect_ptr ) == 0
        }
    }

    /*
    pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
    pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
    pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
    pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
    pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
    pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
    pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
    pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
    pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
    pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int)*/
}
<|endoftext|>


<commit_before>use std::sync::mpsc::{SyncSender, Receiver, Sender, channel};
use std::sync::Arc;
use std::thread::Thread;

use uci::Response;
use game::{Move, Position, receive_legal, make_move};
use types::NumPlies;
use eval::{Score, ScoreUnit};

use super::types::{State, Cmd};
use super::negamax::{self, negamax, Data};

pub fn start(mut state: State, rx: Receiver<Cmd>, tx:SyncSender<Response>) {
    if state.param.ponder {
        debug!("pondering, waiting for next command");
        // Actually should ponder, but now just waits for our move.
        for cmd in rx.iter() {
            match cmd {
                Cmd::SetDebug(val) => {
                    // TODO set debug
                    debug!("debug is now {:?}", val);
                },
                Cmd::PonderHit => {
                    debug!("ponder hit when pondering");
                    state.param.ponder = false;
                    break;
                },
                Cmd::Stop => {
                    debug!("stop from pondering");
                    // TODO report stuff.about pondering and terminate.
                    unimplemented!();
                },
            }
        }
        if state.param.ponder {
            panic!("Sender hung up while pondering");
        }
        debug!("pondering finished");
    }

    // This is a hack required because Send currently requires 'static
    // TODO remove the Arc when Send does not require 'static
    let search_move_pos_arc: Arc<Vec<(Move, Position)>> = Arc::new({
        let legal_moves_chan = receive_legal(state.pos.clone());
        let legal_moves = legal_moves_chan.iter();
        let mut search_moves: Vec<Move> = match state.param.search_moves {
            None => legal_moves.collect(),
            Some(ref val) => legal_moves.filter(|x| val.contains(x)).collect(),
        };
        if search_moves.is_empty() {
            panic!("No legal moves searched in searched position");
        }
        search_moves.drain().map(|x: Move| {
            let mut new_pos = state.pos.clone();
            make_move(&mut new_pos, &x);
            (x, new_pos)
        }).collect()
    });

    let mut best_score = None::<Score>;
    let mut best_move = search_move_pos_arc[0].0.clone();
    let mut total_search_data = Data;

    let mut curr_plies = NumPlies(1);

    let (search_tx, mut search_rx) = channel::<(Score, Move, Data)>();
    let (mut kill_tx, kill_rx) = channel::<()>();

    let temp_search_move_pos_arc = search_move_pos_arc.clone();
    let mut search_guard = Thread::scoped(move ||
        depth_limited_search(temp_search_move_pos_arc, curr_plies, search_tx, kill_rx));

    loop {
        // This is a hack to get around a problem in select! {}
        // TODO remove this hack after the problem is solved
        let mut search_rx_opt: Option<Receiver<(Score, Move, Data)>> = None;
        select! {
            val = rx.recv() => {
                let cmd = val.ok().expect("Sender hung up while calculating");
                match cmd {
                    Cmd::SetDebug(val) => {
                        // TODO set debug
                        debug!("debug is now {:?}", val);
                    },
                    Cmd::PonderHit => {
                        debug!("ponder hit when not pondering (ignored)");
                        // Ignore this cmd
                    },
                    Cmd::Stop => {
                        let _ = kill_tx.send(());
                        search_guard.join().ok().expect("depth_limited_search panicked");
                        debug!("stop search");
                        // TODO send info again
                        tx.send(Response::BestMove(best_move, None))
                          .ok().expect("output channel closed");
                        return;
                    }
                }
            },
            search_res = search_rx.recv() => {
                search_guard.join().ok().expect("depth_limited_search panicked");

                let (temp_best_score, temp_best_move, curr_search_data) = search_res.ok()
                    .expect("depth_limited_search unexpectedly dropped Sender");

                best_score = Some(temp_best_score);
                best_move = temp_best_move;

                total_search_data = total_search_data.combine(curr_search_data);

                // TODO use search data
                // TODO send info

                curr_plies.0 += 1;

                let (new_search_tx, new_search_rx) = channel::<(Score, Move, Data)>();
                search_rx_opt = Some(new_search_rx);
                let (new_kill_tx, new_kill_rx) = channel::<()>();
                kill_tx = new_kill_tx;

                let temp_search_move_pos_arc = search_move_pos_arc.clone();
                search_guard = Thread::scoped(move ||
                    depth_limited_search(temp_search_move_pos_arc, curr_plies,
                                         new_search_tx, new_kill_rx));
            }
        }
        if let Some(val) = search_rx_opt { search_rx = val; }
    }
}

fn depth_limited_search(search_move_pos_arc: Arc<Vec<(Move, Position)>>,
                        depth: NumPlies,
                        tx: Sender<(Score, Move, Data)>,
                        kill_rx: Receiver<()>) {
    debug_assert!(!search_move_pos_arc.is_empty());
    debug_assert!(depth.0 >= 1);

    // TODO This clone() shouldn't be needed
    let mut search_move_pos = (*search_move_pos_arc).clone();

    // TODO Take this draw_val value from somewhere else
    let draw_val: ScoreUnit = 0;

    let next_depth = NumPlies(depth.0 - 1);
    let next_draw_val = -draw_val;

    let param = negamax::Param { draw_val: next_draw_val };

    let mut ans_iter = {
        search_move_pos.iter_mut().map( |&mut (ref mut curr_move, ref mut curr_pos)| {
            let (next_score, next_move_opt, data) = negamax(curr_pos, next_depth, param.clone());
            let score = next_score.increment();
            (score, curr_move.clone(), data)
        })
    };

    let first_ans: (Score, Move, Data) = ans_iter.next().unwrap();
    let ans = ans_iter.fold(first_ans, |prev_ans, curr_ans| {
        let (prev_score, prev_move, prev_data) = prev_ans;
        let (curr_score, curr_move, curr_data) = curr_ans;

        let combined_data = prev_data.combine(curr_data);

        if curr_score > prev_score {
            (curr_score, curr_move, combined_data)
        } else {
            (prev_score, prev_move, combined_data)
        }
    });
    let _ = tx.send(ans);

    // TODO respond to kill_rx
}
<commit_msg>Fix search::start<commit_after>use std::sync::mpsc::{SyncSender, Receiver, Sender, channel};
use std::sync::Arc;
use std::thread::Thread;

use uci::Response;
use game::{Move, Position, receive_legal, make_move};
use types::NumPlies;
use eval::{Score, ScoreUnit};

use super::types::{State, Cmd};
use super::negamax::{self, negamax, Data};

pub fn start(mut state: State, rx: Receiver<Cmd>, tx:SyncSender<Response>) {
    if state.param.ponder {
        debug!("pondering, waiting for next command");
        // Actually should ponder, but now just waits for our move.
        for cmd in rx.iter() {
            match cmd {
                Cmd::SetDebug(val) => {
                    // TODO set debug
                    debug!("debug is now {:?}", val);
                },
                Cmd::PonderHit => {
                    debug!("ponder hit when pondering");
                    state.param.ponder = false;
                    break;
                },
                Cmd::Stop => {
                    debug!("stop from pondering");
                    // TODO report stuff.about pondering and terminate.
                    unimplemented!();
                },
            }
        }
        if state.param.ponder {
            panic!("Sender hung up while pondering");
        }
        debug!("pondering finished");
    }

    // This is a hack required because Send currently requires 'static
    // TODO remove the Arc when Send does not require 'static
    let search_move_pos_arc: Arc<Vec<(Move, Position)>> = Arc::new({
        let legal_moves_chan = receive_legal(state.pos.clone());
        let legal_moves = legal_moves_chan.iter();
        let mut search_moves: Vec<Move> = match state.param.search_moves {
            None => legal_moves.collect(),
            Some(ref val) => legal_moves.filter(|x| val.contains(x)).collect(),
        };
        if search_moves.is_empty() {
            panic!("No legal moves searched in searched position");
        }
        search_moves.drain().map(|x: Move| {
            let mut new_pos = state.pos.clone();
            make_move(&mut new_pos, &x);
            (x, new_pos)
        }).collect()
    });

    let mut best_score = None::<Score>;
    let mut best_move = search_move_pos_arc[0].0.clone();
    let mut total_search_data = Data;

    let mut curr_plies = NumPlies(1);

    let (search_tx, mut search_rx) = channel::<(Score, Move, Data)>();
    let (mut kill_tx, kill_rx) = channel::<()>();

    let temp_search_move_pos_arc = search_move_pos_arc.clone();

    debug!("Starting depth limited search with depth = {} plies", curr_plies.0);
    let mut search_guard = Thread::scoped(move ||
        depth_limited_search(temp_search_move_pos_arc, curr_plies, search_tx, kill_rx));

    loop {
        // This is a hack to get around a problem in select! {}
        // TODO remove this hack after the problem is solved
        let mut search_rx_opt: Option<Receiver<(Score, Move, Data)>> = None;
        select! {
            val = rx.recv() => {
                let cmd = val.ok().expect("Sender hung up while calculating");
                debug!("received command {:?}", cmd);
                match cmd {
                    Cmd::SetDebug(val) => {
                        // TODO set debug
                        debug!("debug is now {:?}", val);
                    },
                    Cmd::PonderHit => {
                        debug!("ponder hit when not pondering (ignored)");
                        // Ignore this cmd
                    },
                    Cmd::Stop => {

                        debug!("killing search");
                        let _ = kill_tx.send(())
                          .ok().expect("output channel closed");

                        debug!("reporting result");
                        // TODO send info again
                        tx.send(Response::BestMove(best_move, None))
                          .ok().expect("output channel unexpectedly closed");

                        debug!("attempting join of depth_limited_search");
                        search_guard.join().ok().expect("depth_limited_search panicked");
                        debug!("joined depth_limited_search");
                        return;
                    }
                }
            },
            search_res = search_rx.recv() => {
                debug!("receiving result from depth_limited_search");

                search_guard.join().ok().expect("depth_limited_search panicked");

                let (temp_best_score, temp_best_move, curr_search_data) = search_res.ok()
                    .expect("depth_limited_search unexpectedly dropped Sender");

                best_score = Some(temp_best_score);
                best_move = temp_best_move;

                total_search_data = total_search_data.combine(curr_search_data);

                // TODO use search data
                // TODO send info

                curr_plies.0 += 1;

                let (new_search_tx, new_search_rx) = channel::<(Score, Move, Data)>();
                search_rx_opt = Some(new_search_rx);
                let (new_kill_tx, new_kill_rx) = channel::<()>();
                kill_tx = new_kill_tx;

                let temp_search_move_pos_arc = search_move_pos_arc.clone();

                debug!("Starting depth limited search with depth = {} plies", curr_plies.0);
                search_guard = Thread::scoped(move ||
                    depth_limited_search(temp_search_move_pos_arc, curr_plies,
                                         new_search_tx, new_kill_rx));
            }
        }
        if let Some(val) = search_rx_opt { search_rx = val; }
    }
}

fn depth_limited_search(search_move_pos_arc: Arc<Vec<(Move, Position)>>,
                        depth: NumPlies,
                        tx: Sender<(Score, Move, Data)>,
                        kill_rx: Receiver<()>) {
    debug_assert!(!search_move_pos_arc.is_empty());
    debug_assert!(depth.0 >= 1);

    // TODO This clone() shouldn't be needed
    let mut search_move_pos = (*search_move_pos_arc).clone();

    // TODO Take this draw_val value from somewhere else
    let draw_val: ScoreUnit = 0;

    let next_depth = NumPlies(depth.0 - 1);
    let next_draw_val = -draw_val;

    let param = negamax::Param { draw_val: next_draw_val };

    let mut ans_iter = {
        search_move_pos.iter_mut().map( |&mut (ref mut curr_move, ref mut curr_pos)| {
            let (next_score, next_move_opt, data) = negamax(curr_pos, next_depth, param.clone());
            let score = next_score.increment();
            (score, curr_move.clone(), data)
        })
    };

    let first_ans: (Score, Move, Data) = ans_iter.next().unwrap();
    let ans = ans_iter.fold(first_ans, |prev_ans, curr_ans| {
        let (prev_score, prev_move, prev_data) = prev_ans;
        let (curr_score, curr_move, curr_data) = curr_ans;

        let combined_data = prev_data.combine(curr_data);

        if curr_score > prev_score {
            (curr_score, curr_move, combined_data)
        } else {
            (prev_score, prev_move, combined_data)
        }
    });
    let _ = tx.send(ans);

    // TODO respond to kill_rx
}
<|endoftext|>


<commit_before>use std::iter::{from_fn, FromIterator};

use indexmap::IndexSet;

use crate::{
    Direction::Outgoing,
    EdgeType,
    Graph,
    graph::IndexType,
    prelude::NodeIndex,
};

/// Returns iterator that produces all simple paths from `from` node to `to`, which contains at least `min_intermidiate_nodes` nodes
/// and at most `max_intermidiate_nodes`, if given, limited by graph's order otherwise
/// Simple path is path without repetitions
/// Algorithm is adopted from https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.simple_paths.all_simple_paths.html
pub fn all_simple_paths<'g, TargetIter: 'g, N, E, Ty, Ix>(graph: &'g Graph<N, E, Ty, Ix>,
                                                          from: NodeIndex<Ix>,
                                                          to: NodeIndex<Ix>,
                                                          min_intermidiate_nodes: usize,
                                                          max_intermidiate_nodes: Option<usize>) -> impl Iterator<Item=TargetIter> + 'g
    where Ix: IndexType, Ty: EdgeType, TargetIter: FromIterator<NodeIndex<Ix>>
{
    // how many nodes are allowed in simple path up to target node
    // it is min/max allowed path length minus one, because it is more appropriate when implementing lookahead
    // that constantly add 1 to length of current path
    let max_length = if let Some(l) = max_intermidiate_nodes {
        l + 1
    } else {
        graph.node_count() - 1
    };

    let min_length = min_intermidiate_nodes + 1;

    // list of visited nodes
    let mut visited: IndexSet<NodeIndex<Ix>> = IndexSet::from_iter(Some(from));
    // list of childs of currently exploring path nodes,
    // last elem is list of childs of last visited node
    let mut stack = vec![graph.neighbors_directed(from, Outgoing)];

    from_fn(move || {
        while let Some(children) = stack.last_mut() {
            if let Some(child) = children.next() {
                if visited.len() < max_length {
                    if child == to {
                        if visited.len() >= min_length {
                            let path = visited.iter().cloned().chain(Some(to)).collect::<TargetIter>();
                            return Some(path);
                        }
                    } else if !visited.contains(&child) {
                        visited.insert(child);
                        stack.push(graph.neighbors_directed(child, Outgoing));
                    }
                } else {
                    if (child == to || children.any(|v| v == to)) && visited.len() >= min_length {
                        let path = visited.iter().cloned().chain(Some(to)).collect::<TargetIter>();
                        return Some(path);
                    }
                    stack.pop();
                    visited.pop();
                }
            } else {
                stack.pop();
                visited.pop();
            }
        }
        None
    })
}

#[cfg(test)]
mod test {
    use std::{
        collections::HashSet,
        iter::FromIterator
    };

    use itertools::assert_equal;

    use crate::{
        dot::Dot,
        prelude::DiGraph,
    };

    use super::all_simple_paths;

    #[test]
    fn test_all_simple_paths() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (0, 2),
            (0, 3),
            (1, 2),
            (1, 3),
            (2, 3),
            (2, 4),
            (3, 2),
            (3, 4),
            (4, 2),
            (4, 5),
            (5, 2),
            (5, 3)
        ]);

        let expexted_simple_paths_0_to_5 = vec![
            vec![0usize, 1, 2, 3, 4, 5],
            vec![0, 1, 2, 4, 5],
            vec![0, 1, 3, 2, 4, 5],
            vec![0, 1, 3, 4, 5],
            vec![0, 2, 3, 4, 5],
            vec![0, 2, 4, 5],
            vec![0, 3, 2, 4, 5],
            vec![0, 3, 4, 5],
        ];

        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_5: HashSet<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 5u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();
        assert_eq!(actual_simple_paths_0_to_5.len(), 8);
        assert_eq!(HashSet::from_iter(expexted_simple_paths_0_to_5), actual_simple_paths_0_to_5);
    }

    #[test]
    fn test_one_simple_path() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (2, 1)
        ]);

        let expexted_simple_paths_0_to_1 = &[
            vec![0usize, 1],
        ];
        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_1: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 1u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();

        assert_eq!(actual_simple_paths_0_to_1.len(), 1);
        assert_equal(expexted_simple_paths_0_to_1, &actual_simple_paths_0_to_1);
    }

    #[test]
    fn test_no_simple_paths() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (2, 1)
        ]);

        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_2: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 2u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();

        assert_eq!(actual_simple_paths_0_to_2.len(), 0);
    }
}
<commit_msg>Get rid of hardcoded graph type, migrate to `visit` traits Rename TargetIter to TargetColl Formatting<commit_after>use std::{
    hash::Hash,
    iter::{from_fn, FromIterator},
};

use indexmap::IndexSet;

use crate::{
    Direction::Outgoing,
    visit::{
        GraphBase,
        IntoNeighborsDirected,
        NodeCount,
    },
};

/// Returns iterator that produces all simple paths from `from` node to `to`, which contains at least `min_intermidiate_nodes` nodes
/// and at most `max_intermidiate_nodes`, if given, limited by graph's order otherwise
/// Simple path is path without repetitions
/// Algorithm is adopted from https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.simple_paths.all_simple_paths.html
pub fn all_simple_paths<'g, TargetColl: 'g, G>(graph: &'g G,
                                               from: G::NodeId,
                                               to: G::NodeId,
                                               min_intermidiate_nodes: usize,
                                               max_intermidiate_nodes: Option<usize>) -> impl Iterator<Item=TargetColl> + 'g
    where G: NodeCount,
          G: GraphBase<NodeId=<&'g G as GraphBase>::NodeId>,
          &'g G: IntoNeighborsDirected,
          G::NodeId: Eq + Hash,
          TargetColl: FromIterator<G::NodeId>
{
    // how many nodes are allowed in simple path up to target node
    // it is min/max allowed path length minus one, because it is more appropriate when implementing lookahead
    // than constantly add 1 to length of current path
    let max_length = if let Some(l) = max_intermidiate_nodes {
        l + 1
    } else {
        graph.node_count() - 1
    };

    let min_length = min_intermidiate_nodes + 1;

    // list of visited nodes
    let mut visited: IndexSet<G::NodeId> = IndexSet::from_iter(Some(from));
    // list of childs of currently exploring path nodes,
    // last elem is list of childs of last visited node
    let mut stack = vec![graph.neighbors_directed(from, Outgoing)];

    from_fn(move || {
        while let Some(children) = stack.last_mut() {
            if let Some(child) = children.next() {
                if visited.len() < max_length {
                    if child == to {
                        if visited.len() >= min_length {
                            let path = visited.iter().cloned().chain(Some(to)).collect::<TargetColl>();
                            return Some(path);
                        }
                    } else if !visited.contains(&child) {
                        visited.insert(child);
                        stack.push(graph.neighbors_directed(child, Outgoing));
                    }
                } else {
                    if (child == to || children.any(|v| v == to)) && visited.len() >= min_length {
                        let path = visited.iter().cloned().chain(Some(to)).collect::<TargetColl>();
                        return Some(path);
                    }
                    stack.pop();
                    visited.pop();
                }
            } else {
                stack.pop();
                visited.pop();
            }
        }
        None
    })
}

#[cfg(test)]
mod test {
    use std::{
        collections::HashSet,
        iter::FromIterator,
    };

    use itertools::assert_equal;

    use crate::{
        dot::Dot,
        prelude::DiGraph,
    };

    use super::all_simple_paths;

    #[test]
    fn test_all_simple_paths() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (0, 2),
            (0, 3),
            (1, 2),
            (1, 3),
            (2, 3),
            (2, 4),
            (3, 2),
            (3, 4),
            (4, 2),
            (4, 5),
            (5, 2),
            (5, 3)
        ]);

        let expexted_simple_paths_0_to_5 = vec![
            vec![0usize, 1, 2, 3, 4, 5],
            vec![0, 1, 2, 4, 5],
            vec![0, 1, 3, 2, 4, 5],
            vec![0, 1, 3, 4, 5],
            vec![0, 2, 3, 4, 5],
            vec![0, 2, 4, 5],
            vec![0, 3, 2, 4, 5],
            vec![0, 3, 4, 5],
        ];

        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_5: HashSet<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 5u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();
        assert_eq!(actual_simple_paths_0_to_5.len(), 8);
        assert_eq!(HashSet::from_iter(expexted_simple_paths_0_to_5), actual_simple_paths_0_to_5);
    }

    #[test]
    fn test_one_simple_path() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (2, 1)
        ]);

        let expexted_simple_paths_0_to_1 = &[
            vec![0usize, 1],
        ];
        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_1: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 1u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();

        assert_eq!(actual_simple_paths_0_to_1.len(), 1);
        assert_equal(expexted_simple_paths_0_to_1, &actual_simple_paths_0_to_1);
    }

    #[test]
    fn test_no_simple_paths() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (2, 1)
        ]);

        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_2: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 2u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();

        assert_eq!(actual_simple_paths_0_to_2.len(), 0);
    }
}
<|endoftext|>


<commit_before>use std::slice::Iter;
use edit::buffer::{TextBuffer, SplitBuffer};
use state::cursor::Cursor;
use io::graphics::StatusBar;
use io::key::{Key, Cmd};
use io::key_state::KeyState;
use state::options::Options;
use io::parse::Inst;
use io::redraw::RedrawTask;

#[cfg(feature = "orbital")]
use orbclient::Window;

use std::env::args;

// TODO: write proper help message
const HELP: &'static str = "Don't panic!";

/// A SplitBuffer and related state
pub struct Buffer {
    /// The document
    pub raw_buffer: SplitBuffer,
    /// The current cursor
    pub current_cursor: u8,
    /// The cursors
    pub cursors: Vec<Cursor>,
    /// The x coordinate of the scroll
    pub scroll_x: usize,
    /// The y coordinate of the scroll
    pub scroll_y: usize,
    /// The title of the document
    pub title: Option<String>,
    /// True if the buffer is transient and should be deleted when
    /// it is no longer the current buffer.
    pub is_transient: bool,
}

impl Buffer {
    /// Create a new Buffer with default values.
    fn new() -> Buffer {
        Buffer {
            raw_buffer: SplitBuffer::new(),
            current_cursor: 0,
            cursors: vec![Cursor::new()],
            scroll_x: 0,
            scroll_y: 0,
            title: None,
            is_transient: false,
        }
    }
}

impl From<SplitBuffer> for Buffer {
    fn from(b: SplitBuffer) -> Buffer {
        let mut info = Buffer::new();
        info.raw_buffer = b;

        info
    }
}

/// Provides access to buffer manipulation functions.
pub struct BufferManager {
    buffers: Vec<Buffer>,
    current_buffer_index: usize,
}

impl BufferManager {
    /// Create a new BufferManager with default values.
    pub fn new() -> BufferManager {
        BufferManager {
            buffers: vec![Buffer::new()],
            current_buffer_index: 0,
        }
    }

    /// Adds the specified buffer to the set of buffers and returns
    /// its index.
    pub fn new_buffer(&mut self, buffer: Buffer) -> usize {
        self.buffers.push(buffer);

        self.buffers.len() - 1
    }

    /// Returns an iterator over the buffers.
    pub fn iter(&self) -> Iter<Buffer> {
        self.buffers.iter()
    }

    /// Gets the number of buffers.
    pub fn len(&self) -> usize {
        self.buffers.len()
    }

    /// Gets the index of the current buffer.
    pub fn current_buffer_index(&self) -> usize {
        self.current_buffer_index
    }

    /// Get a reference to the currently open buffer.
    pub fn current_buffer(&self) -> &SplitBuffer {
        &self.current_buffer_info().raw_buffer
    }

    /// Get a mutable reference to the currently open buffer.
    pub fn current_buffer_mut(&mut self) -> &mut SplitBuffer {
        &mut self.current_buffer_info_mut().raw_buffer
    }

    /// Get a reference to the currently open buffer information.
    pub fn current_buffer_info(&self) -> &Buffer {
        &self.buffers[self.current_buffer_index]
    }

    /// Get a mutable reference to the currently open buffer information.
    pub fn current_buffer_info_mut(&mut self) -> &mut Buffer {
        &mut self.buffers[self.current_buffer_index]
    }

    /// Switch the current buffer to the specified buffer
    pub fn switch_to(&mut self, n: usize) {
        debug_assert!(n < self.buffers.len(), "Buffer index out of bounds");

        // if the current view is transient, delete it
        let mut n = n;
        if self.current_buffer_info().is_transient {
            let index = self.current_buffer_index;
            self.delete_buffer(index);

            // if the current view is less than the view to switch to
            // then we need to account for the view we just removed
            if index <= n {
                n -= 1;
            }
        }

        self.current_buffer_index = n;
    }

    /// Delete the specified buffer
    pub fn delete_buffer(&mut self, n: usize) {
        assert!(n < self.buffers.len(), "Buffer index out of bounds");

        self.buffers.remove(n);

        if self.buffers.len() == 0 {
            self.buffers.push(Buffer::new());
            self.current_buffer_index = 0;
        } else if self.current_buffer_index <= n {
            self.current_buffer_index  -= 1;
        }
    }

    /// Validates that the specifed buffer index is valid
    pub fn is_buffer_index_valid(&self, n: usize) -> bool {
        n < self.buffers.iter().filter(|b| !b.is_transient).count()
    }
}

/// The current state of the editor, including the file, the cursor, the scrolling info, etc.
pub struct Editor {
    /// The buffers and related state
    pub buffers: BufferManager,
    /// The window
    #[cfg(feature = "orbital")]
    pub window: Window,
    /// The status bar
    pub status_bar: StatusBar,
    /// The prompt
    pub prompt: String,
    /// The settings
    pub options: Options,
    /// The key state
    pub key_state: KeyState,
    /// Redraw
    pub redraw_task: RedrawTask,
    /// The previous instruction
    pub previous_instruction: Option<Inst>,
}

impl Editor {
    /// Create new default state editor
    pub fn init() {

        #[cfg(feature = "orbital")]
        let window = Window::new(-1, -1, 700, 500, &"Sodium").unwrap();

        #[cfg(feature = "orbital")]
        let mut editor = Editor {
            buffers: BufferManager::new(),
            window: window,
            status_bar: StatusBar::new(),
            prompt: String::new(),
            options: Options::new(),
            key_state: KeyState::new(),
            redraw_task: RedrawTask::None,
            previous_instruction: None,
        };

        #[cfg(not(feature = "orbital"))]
        let mut editor = Editor {
            buffers: BufferManager::new(),
            status_bar: StatusBar::new(),
            prompt: String::new(),
            options: Options::new(),
            key_state: KeyState::new(),
            redraw_task: RedrawTask::None,
            previous_instruction: None,
        };

        let mut files: Vec<String> = Vec::new();

        for arg in args().skip(1) {
            match arg.as_str() {
                "--version" => {
                    println!("Sodium {}", option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"));
                    return;
                },
                "--help" | "-h" => {
                    println!("{}", HELP);
                    return;
                }
                "-R" => {
                    unimplemented!();
                    /*
                    match editor.options.set("readonly") {
                        Ok(_) => debugln!(editor, "Set readonly mode"),
                        Err(_) => println!("Could not set readonly mode")
                    }
                    */
                }
                _ => {
                    files.push(arg);
                }
            }
        }

        if files.len() > 0 {
            // TODO: open multiple files into separate buffers
            editor.open(&files[0]);
        }

        debugln!(editor, "Starting Sodium");

        editor.redraw();

        debugln!(editor, "First redraw of the screen");

        loop {
            let inp = editor.get_inst();
            if let Inst(_, Cmd { key: Key::Quit }) = inp {
                debugln!(editor, "C'ya");
                break;
            }
            editor.exec(inp);
            editor.status_bar.mode = editor.cursor().mode.to_string();
            editor.redraw();
        }
    }

    /// Hint the buffer about the cursor position.
    pub fn hint(&mut self) {
        let x = self.cursor().x;
        let y = self.cursor().y;

        self.buffers.current_buffer_mut().focus_hint_y(y);
        self.buffers.current_buffer_mut().focus_hint_x(x);
    }
}
<commit_msg>Use help.txt as help message text.<commit_after>use std::slice::Iter;
use edit::buffer::{TextBuffer, SplitBuffer};
use state::cursor::Cursor;
use io::graphics::StatusBar;
use io::key::{Key, Cmd};
use io::key_state::KeyState;
use state::options::Options;
use io::parse::Inst;
use io::redraw::RedrawTask;

#[cfg(feature = "orbital")]
use orbclient::Window;

use std::env::args;

const HELP: &'static str = include_str!("../../help.txt");

/// A SplitBuffer and related state
pub struct Buffer {
    /// The document
    pub raw_buffer: SplitBuffer,
    /// The current cursor
    pub current_cursor: u8,
    /// The cursors
    pub cursors: Vec<Cursor>,
    /// The x coordinate of the scroll
    pub scroll_x: usize,
    /// The y coordinate of the scroll
    pub scroll_y: usize,
    /// The title of the document
    pub title: Option<String>,
    /// True if the buffer is transient and should be deleted when
    /// it is no longer the current buffer.
    pub is_transient: bool,
}

impl Buffer {
    /// Create a new Buffer with default values.
    fn new() -> Buffer {
        Buffer {
            raw_buffer: SplitBuffer::new(),
            current_cursor: 0,
            cursors: vec![Cursor::new()],
            scroll_x: 0,
            scroll_y: 0,
            title: None,
            is_transient: false,
        }
    }
}

impl From<SplitBuffer> for Buffer {
    fn from(b: SplitBuffer) -> Buffer {
        let mut info = Buffer::new();
        info.raw_buffer = b;

        info
    }
}

/// Provides access to buffer manipulation functions.
pub struct BufferManager {
    buffers: Vec<Buffer>,
    current_buffer_index: usize,
}

impl BufferManager {
    /// Create a new BufferManager with default values.
    pub fn new() -> BufferManager {
        BufferManager {
            buffers: vec![Buffer::new()],
            current_buffer_index: 0,
        }
    }

    /// Adds the specified buffer to the set of buffers and returns
    /// its index.
    pub fn new_buffer(&mut self, buffer: Buffer) -> usize {
        self.buffers.push(buffer);

        self.buffers.len() - 1
    }

    /// Returns an iterator over the buffers.
    pub fn iter(&self) -> Iter<Buffer> {
        self.buffers.iter()
    }

    /// Gets the number of buffers.
    pub fn len(&self) -> usize {
        self.buffers.len()
    }

    /// Gets the index of the current buffer.
    pub fn current_buffer_index(&self) -> usize {
        self.current_buffer_index
    }

    /// Get a reference to the currently open buffer.
    pub fn current_buffer(&self) -> &SplitBuffer {
        &self.current_buffer_info().raw_buffer
    }

    /// Get a mutable reference to the currently open buffer.
    pub fn current_buffer_mut(&mut self) -> &mut SplitBuffer {
        &mut self.current_buffer_info_mut().raw_buffer
    }

    /// Get a reference to the currently open buffer information.
    pub fn current_buffer_info(&self) -> &Buffer {
        &self.buffers[self.current_buffer_index]
    }

    /// Get a mutable reference to the currently open buffer information.
    pub fn current_buffer_info_mut(&mut self) -> &mut Buffer {
        &mut self.buffers[self.current_buffer_index]
    }

    /// Switch the current buffer to the specified buffer
    pub fn switch_to(&mut self, n: usize) {
        debug_assert!(n < self.buffers.len(), "Buffer index out of bounds");

        // if the current view is transient, delete it
        let mut n = n;
        if self.current_buffer_info().is_transient {
            let index = self.current_buffer_index;
            self.delete_buffer(index);

            // if the current view is less than the view to switch to
            // then we need to account for the view we just removed
            if index <= n {
                n -= 1;
            }
        }

        self.current_buffer_index = n;
    }

    /// Delete the specified buffer
    pub fn delete_buffer(&mut self, n: usize) {
        assert!(n < self.buffers.len(), "Buffer index out of bounds");

        self.buffers.remove(n);

        if self.buffers.len() == 0 {
            self.buffers.push(Buffer::new());
            self.current_buffer_index = 0;
        } else if self.current_buffer_index <= n {
            self.current_buffer_index  -= 1;
        }
    }

    /// Validates that the specifed buffer index is valid
    pub fn is_buffer_index_valid(&self, n: usize) -> bool {
        n < self.buffers.iter().filter(|b| !b.is_transient).count()
    }
}

/// The current state of the editor, including the file, the cursor, the scrolling info, etc.
pub struct Editor {
    /// The buffers and related state
    pub buffers: BufferManager,
    /// The window
    #[cfg(feature = "orbital")]
    pub window: Window,
    /// The status bar
    pub status_bar: StatusBar,
    /// The prompt
    pub prompt: String,
    /// The settings
    pub options: Options,
    /// The key state
    pub key_state: KeyState,
    /// Redraw
    pub redraw_task: RedrawTask,
    /// The previous instruction
    pub previous_instruction: Option<Inst>,
}

impl Editor {
    /// Create new default state editor
    pub fn init() {

        #[cfg(feature = "orbital")]
        let window = Window::new(-1, -1, 700, 500, &"Sodium").unwrap();

        #[cfg(feature = "orbital")]
        let mut editor = Editor {
            buffers: BufferManager::new(),
            window: window,
            status_bar: StatusBar::new(),
            prompt: String::new(),
            options: Options::new(),
            key_state: KeyState::new(),
            redraw_task: RedrawTask::None,
            previous_instruction: None,
        };

        #[cfg(not(feature = "orbital"))]
        let mut editor = Editor {
            buffers: BufferManager::new(),
            status_bar: StatusBar::new(),
            prompt: String::new(),
            options: Options::new(),
            key_state: KeyState::new(),
            redraw_task: RedrawTask::None,
            previous_instruction: None,
        };

        let mut files: Vec<String> = Vec::new();

        for arg in args().skip(1) {
            match arg.as_str() {
                "--version" => {
                    println!("Sodium {}", option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"));
                    return;
                },
                "--help" | "-h" => {
                    println!("{}", HELP);
                    return;
                }
                "-R" => {
                    unimplemented!();
                    /*
                    match editor.options.set("readonly") {
                        Ok(_) => debugln!(editor, "Set readonly mode"),
                        Err(_) => println!("Could not set readonly mode")
                    }
                    */
                }
                _ => {
                    files.push(arg);
                }
            }
        }

        if files.len() > 0 {
            // TODO: open multiple files into separate buffers
            editor.open(&files[0]);
        }

        debugln!(editor, "Starting Sodium");

        editor.redraw();

        debugln!(editor, "First redraw of the screen");

        loop {
            let inp = editor.get_inst();
            if let Inst(_, Cmd { key: Key::Quit }) = inp {
                debugln!(editor, "C'ya");
                break;
            }
            editor.exec(inp);
            editor.status_bar.mode = editor.cursor().mode.to_string();
            editor.redraw();
        }
    }

    /// Hint the buffer about the cursor position.
    pub fn hint(&mut self) {
        let x = self.cursor().x;
        let y = self.cursor().y;

        self.buffers.current_buffer_mut().focus_hint_y(y);
        self.buffers.current_buffer_mut().focus_hint_x(x);
    }
}
<|endoftext|>


<commit_before>use semver::Version;

/// A part of a semver version: Major.Minor.Patch
arg_enum! {
    #[derive(Eq, PartialEq, Debug)]
    pub enum VersionKind {
        Major,
        Minor,
        Patch
    }
}

impl VersionKind {
    pub fn increment(&self, mut version: Version) -> Version {
        match *self {
            VersionKind::Major => version.increment_major(),
            VersionKind::Minor => version.increment_minor(),
            VersionKind::Patch => version.increment_patch()
        }

        version
    }
}
<commit_msg>VersionKind::increment: borrow the version argument<commit_after>use semver::Version;

/// A part of a semver version: Major.Minor.Patch
arg_enum! {
    #[derive(Eq, PartialEq, Debug)]
    pub enum VersionKind {
        Major,
        Minor,
        Patch
    }
}

impl VersionKind {
    pub fn increment(&self, version: &Version) -> Version {
        let mut new_vers = version.clone();
        match *self {
            VersionKind::Major => new_vers.increment_major(),
            VersionKind::Minor => new_vers.increment_minor(),
            VersionKind::Patch => new_vers.increment_patch()
        }

        new_vers
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;
use integer::Integer;
use traits::{Zero, One};

use biguint::BigUint;

struct MontyReducer<'a> {
    p: &'a BigUint,
    n: Vec<u32>,
    n0inv: u64
}

// Calculate the modular inverse of `num`, using Extended GCD.
//
// Reference:
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.20
fn inv_mod_u32(num: u32) -> u64 {
    // num needs to be relatively prime to u32::max_value()
    assert!(num % 2 != 0);

    let mut a: i64 = num as i64;
    let mut b: i64 = (u32::max_value() as i64) + 1;
    let mu = b;

    // ExtendedGcd
    // Input: positive integers a and b
    // Output: integers (g, u, v) such that g = gcd(a, b) = ua + vb
    // As we don't need v for modular inverse, we don't calculate it.

    // 1: (u, w) <- (1, 0)
    let mut u = 1;
    let mut w = 0;
    // 3: while b != 0
    while b != 0 {
        // 4: (q, r) <- DivRem(a, b)
        let q = a / b;
        let r = a % b;
        // 5: (a, b) <- (b, r)
        a = b; b = r;
        // 6: (u, w) <- (w, u - qw)
        let m = u - w*q;
        u = w; w = m;
    }

    assert!(a == 1);
    // Ensure returned value is in-range
    if u < 0 {
        (u + mu) as u64
    } else {
        u as u64
    }
}

impl<'a> MontyReducer<'a> {
    fn new(p: &'a BigUint) -> Self {
        let n : Vec<u32> = p.data.clone();
        let n0inv = inv_mod_u32(n[0]);
        MontyReducer { p: p, n: n, n0inv: n0inv }
    }
}

// Montgomery Reduction
//
// Reference:
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 2.6
fn monty_redc(a: BigUint, mr: &MontyReducer) -> BigUint {
    let mut c = a.data;
    let n = &mr.n;
    let n_size = n.len();
    let old_size = c.len();

    // Allocate sufficient work space
    c.reserve(2*n_size+2-old_size);
    c.extend(repeat(0).take(2*n_size+2-old_size));

    // β is the size of a word, in this case 32 bits. So "a mod β" is
    // equivalent to masking a to 32 bits.
    let beta_mask = u32::max_value() as u64;
    // mu <- -N^(-1) mod β
    let mu = (beta_mask-mr.n0inv)+1;

    // 1: for i = 0 to (n-1)
    for i in 0..n_size {
        // Carry storage
        let mut carry = 0;

        // 2: q_i <- mu*c_i mod β
        let q_i = ((c[i] as u64) * mu) & beta_mask;

        // 3: C <- C + q_i * N * β^i
        // When iterating over each word, this becomes:
        for j in 0..n_size {
            // c_(i+j) <- c_(i+j) + q_i * n_j
            let x = (c[i+j] as u64) + q_i * (n[j] as u64) + carry;
            c[i+j] = (x & beta_mask) as u32;
            carry = x >> 32;
        }

        // Apply the remaining carry to the rest of the work space
        for j in n_size..2*n_size-i+2 {
            let x = (c[i+j] as u64) + carry;
            c[i+j] = (x & beta_mask) as u32;
            carry = x >> 32;
        }
    }

    // 4: R <- C * β^(-n)
    // This is an n-word bitshift, equivalent to skipping n words.
    let r : Vec<u32> = c.iter().skip(n_size).cloned().collect();
    let ret = BigUint::new(r);

    // 5: if R >= β^n then return R-N else return R.
    if &ret < mr.p {
        ret
    } else {
        &ret-mr.p
    }
}

// Montgomery Multiplication
fn monty_mult(a: BigUint, b: &BigUint, mr: &MontyReducer) -> BigUint {
    monty_redc(a * b, mr)
}

// Montgomery Squaring
fn monty_sqr(a: BigUint, mr: &MontyReducer) -> BigUint {
    // TODO: Replace with an optimised squaring function
    monty_redc(&a * &a, mr)
}

pub fn monty_modpow(a: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint{
    let mr = MontyReducer::new(modulus);

    // Calculate the Montgomery parameter
    let mut r : BigUint = One::one();
    while &r < mr.p {
        r = r << 32;
    }

    // Map the base to the Montgomery domain
    let mut apri = a * &r % mr.p;

    // Binary exponentiation
    let mut ans = &r % mr.p;
    let mut e = exp.clone();
    let zero = Zero::zero();
    while e > zero {
        if e.is_odd() {
            ans = monty_mult(ans, &apri, &mr);
        }
        apri = monty_sqr(apri, &mr);
        e = e >> 1;
    }

    // Map the result back to the residues domain
    monty_redc(ans, &mr)
}
<commit_msg>bigint::monty: store the inverse as u32<commit_after>use std::iter::repeat;
use integer::Integer;
use traits::{Zero, One};

use biguint::BigUint;

struct MontyReducer<'a> {
    p: &'a BigUint,
    n: Vec<u32>,
    n0inv: u32
}

// Calculate the modular inverse of `num`, using Extended GCD.
//
// Reference:
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.20
fn inv_mod_u32(num: u32) -> u32 {
    // num needs to be relatively prime to 2**32 -- i.e. it must be odd.
    assert!(num % 2 != 0);

    let mut a: i64 = num as i64;
    let mut b: i64 = (u32::max_value() as i64) + 1;

    // ExtendedGcd
    // Input: positive integers a and b
    // Output: integers (g, u, v) such that g = gcd(a, b) = ua + vb
    // As we don't need v for modular inverse, we don't calculate it.

    // 1: (u, w) <- (1, 0)
    let mut u = 1;
    let mut w = 0;
    // 3: while b != 0
    while b != 0 {
        // 4: (q, r) <- DivRem(a, b)
        let q = a / b;
        let r = a % b;
        // 5: (a, b) <- (b, r)
        a = b; b = r;
        // 6: (u, w) <- (w, u - qw)
        let m = u - w*q;
        u = w; w = m;
    }

    assert!(a == 1);
    // Downcasting acts like a mod 2^32 too.
    u as u32
}

impl<'a> MontyReducer<'a> {
    fn new(p: &'a BigUint) -> Self {
        let n : Vec<u32> = p.data.clone();
        let n0inv = inv_mod_u32(n[0]);
        MontyReducer { p: p, n: n, n0inv: n0inv }
    }
}

// Montgomery Reduction
//
// Reference:
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 2.6
fn monty_redc(a: BigUint, mr: &MontyReducer) -> BigUint {
    let mut c = a.data;
    let n = &mr.n;
    let n_size = n.len();
    let old_size = c.len();

    // Allocate sufficient work space
    c.reserve(2*n_size+2-old_size);
    c.extend(repeat(0).take(2*n_size+2-old_size));

    // β is the size of a word, in this case 32 bits. So "a mod β" is
    // equivalent to masking a to 32 bits.
    let beta_mask = u32::max_value() as u64;
    // mu <- -N^(-1) mod β
    let mu = (beta_mask-mr.n0inv as u64)+1;

    // 1: for i = 0 to (n-1)
    for i in 0..n_size {
        // Carry storage
        let mut carry = 0;

        // 2: q_i <- mu*c_i mod β
        let q_i = ((c[i] as u64) * mu) & beta_mask;

        // 3: C <- C + q_i * N * β^i
        // When iterating over each word, this becomes:
        for j in 0..n_size {
            // c_(i+j) <- c_(i+j) + q_i * n_j
            let x = (c[i+j] as u64) + q_i * (n[j] as u64) + carry;
            c[i+j] = (x & beta_mask) as u32;
            carry = x >> 32;
        }

        // Apply the remaining carry to the rest of the work space
        for j in n_size..2*n_size-i+2 {
            let x = (c[i+j] as u64) + carry;
            c[i+j] = (x & beta_mask) as u32;
            carry = x >> 32;
        }
    }

    // 4: R <- C * β^(-n)
    // This is an n-word bitshift, equivalent to skipping n words.
    let r : Vec<u32> = c.iter().skip(n_size).cloned().collect();
    let ret = BigUint::new(r);

    // 5: if R >= β^n then return R-N else return R.
    if &ret < mr.p {
        ret
    } else {
        &ret-mr.p
    }
}

// Montgomery Multiplication
fn monty_mult(a: BigUint, b: &BigUint, mr: &MontyReducer) -> BigUint {
    monty_redc(a * b, mr)
}

// Montgomery Squaring
fn monty_sqr(a: BigUint, mr: &MontyReducer) -> BigUint {
    // TODO: Replace with an optimised squaring function
    monty_redc(&a * &a, mr)
}

pub fn monty_modpow(a: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint{
    let mr = MontyReducer::new(modulus);

    // Calculate the Montgomery parameter
    let mut r : BigUint = One::one();
    while &r < mr.p {
        r = r << 32;
    }

    // Map the base to the Montgomery domain
    let mut apri = a * &r % mr.p;

    // Binary exponentiation
    let mut ans = &r % mr.p;
    let mut e = exp.clone();
    let zero = Zero::zero();
    while e > zero {
        if e.is_odd() {
            ans = monty_mult(ans, &apri, &mr);
        }
        apri = monty_sqr(apri, &mr);
        e = e >> 1;
    }

    // Map the result back to the residues domain
    monty_redc(ans, &mr)
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

#[deny(string_add)]
#[allow(string_add_assign)]
fn add_only() { // ignores assignment distinction
	let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you add something to a string.
    }

    let y = "".to_owned();
    let z = y + "..."; //~ERROR you add something to a string.

    assert_eq!(&x, &z);
}

#[deny(string_add_assign)]
fn add_assign_only() {
	let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you assign the result of adding something to this string.
    }

    let y = "".to_owned();
    let z = y + "...";

    assert_eq!(&x, &z);
}

#[deny(string_add, string_add_assign)]
fn both() {
    let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you assign the result of adding something to this string.
    }

    let y = "".to_owned();
    let z = y + "..."; //~ERROR you add something to a string.

    assert_eq!(&x, &z);
}

fn main() {
	add_only();
	add_assign_only();
	both();

	// the add is only caught for String
	let mut x = 1;
	x = x + 1;
	assert_eq!(2, x);
}
<commit_msg>fixed error messages in compile-fail test<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#[deny(string_add)]
#[allow(string_add_assign)]
fn add_only() { // ignores assignment distinction
	let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you added something to a string.
    }

    let y = "".to_owned();
    let z = y + "..."; //~ERROR you added something to a string.

    assert_eq!(&x, &z);
}

#[deny(string_add_assign)]
fn add_assign_only() {
	let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you assigned the result of adding something to this string.
    }

    let y = "".to_owned();
    let z = y + "...";

    assert_eq!(&x, &z);
}

#[deny(string_add, string_add_assign)]
fn both() {
    let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you assigned the result of adding something to this string.
    }

    let y = "".to_owned();
    let z = y + "..."; //~ERROR you added something to a string.

    assert_eq!(&x, &z);
}

fn main() {
	add_only();
	add_assign_only();
	both();

	// the add is only caught for String
	let mut x = 1;
	x = x + 1;
	assert_eq!(2, x);
}
<|endoftext|>


<commit_before>use rustwlc::{Point, ResizeEdge, Geometry,
              RESIZE_LEFT, RESIZE_RIGHT, RESIZE_TOP, RESIZE_BOTTOM};

use super::super::{Action, Direction, LayoutTree, TreeError};
use super::super::commands::{CommandResult};
use super::super::core::container::{ContainerType, MIN_SIZE};
use uuid::Uuid;

#[derive(Debug, Clone, Copy)]
pub enum ResizeErr {
    /// Expected the node associated with the UUID to be floating.
    ExpectedFloating(Uuid),
    /// Expected the node associated with the UUID to not be floating
    ExpectedNotFloating(Uuid)
}

impl LayoutTree {
    /// Resizes a floating container. If the container was not floating, an Err is returned.
    pub fn resize_floating(&mut self, id: Uuid, edge: ResizeEdge, pointer: Point,
                           action: &mut Action) -> CommandResult {
        let container = try!(self.lookup_mut(id));
        if !container.floating() {
            return Err(TreeError::Resize(ResizeErr::ExpectedFloating(container.get_id())))
        }
        match container.get_type() {
            ContainerType::View | ContainerType::Container => {},
            _ => return Err(TreeError::UuidWrongType(container.get_id(),
                                                     vec!(ContainerType::View)))
        }
        let geo = container.get_geometry()
            .expect("Could not get geometry of the container");

        let new_geo = calculate_resize(geo, edge, pointer, action.grab);
        action.grab = pointer;

        container.set_geometry(edge, new_geo);
        Ok(())
    }

    pub fn resize_tiled(&mut self, id: Uuid, edge: ResizeEdge, pointer: Point,
                        action: &mut Action) -> CommandResult {
        // There can be multiple directions we are moving in, e.g up and left.
        let dirs_moving_in = Direction::from_edge(edge);
        let siblings: Vec<Uuid> = dirs_moving_in.iter()
            .map(|dir| self.sibling_in_dir(id, *dir))
            // TODO There MUST be a better way to do something like this...
            .filter(|thing| thing.is_ok())
            .map(|thing| thing.unwrap())
            .collect();

        // Because we can't have multiple mutable references active in the tree at once,
        // first we modify the one the user is resizing and then adjust the siblings.
        {
            let container = try!(self.lookup_mut(id));
            if container.floating() {
                return Err(TreeError::Resize(ResizeErr::ExpectedNotFloating(container.get_id())))
            }
            match container.get_type() {
                ContainerType::View | ContainerType::Container => {},
                _ => return Err(TreeError::UuidWrongType(container.get_id(),
                                                        vec!(ContainerType::View)))
            }
            let geo = container.get_geometry()
                .expect("Could not get geometry of the container");
            let new_geo = calculate_resize(geo, edge, pointer, action.grab);
            container.set_geometry(edge, new_geo);
        }
        // and now we mutate the siblings
        let reversed_dir: Vec<Direction> = dirs_moving_in.iter()
            .map(|dir| dir.reverse()).collect();
        let reversed_edge = Direction::to_edge(reversed_dir.as_slice());
        for sibling in siblings {
            // TODO Abstract, the only thing different from above
            // is the edge and the exact node we are doing the calc on
            let container = try!(self.lookup_mut(sibling));
            if container.floating() {
                return Err(TreeError::Resize(ResizeErr::ExpectedNotFloating(container.get_id())))
            }
            match container.get_type() {
                ContainerType::View | ContainerType::Container => {},
                _ => return Err(TreeError::UuidWrongType(container.get_id(),
                                                         vec!(ContainerType::View)))
            }
            let geo = container.get_geometry()
                .expect("Could not get geometry of the container");
            let new_geo = calculate_resize(geo, reversed_edge, pointer, action.grab);
            action.grab = pointer;
            container.set_geometry(reversed_edge, new_geo);
        }
        let node_ix = self.tree.lookup_id(id).unwrap();
        self.layout(node_ix);
        action.grab = pointer;
        Ok(())
    }
}

/// Calculates what the new geometry is of a window.
/// Needs the geometry of the window, the edge direction the pointer is moving in,
/// the current position of the pointer, and the previous place the pointer was at.
fn calculate_resize(geo: Geometry, edge: ResizeEdge,
                    cur_pointer: Point, prev_pointer: Point) -> Geometry {
    let mut new_geo = geo.clone();
    let dx = cur_pointer.x - prev_pointer.x;
    let dy = cur_pointer.y - prev_pointer.y;
    if edge.contains(RESIZE_LEFT) {
        if dx < 0 {
            new_geo.size.w = geo.size.w.saturating_add(dx.abs() as u32);
        } else {
            new_geo.size.w = geo.size.w.saturating_sub(dx.abs() as u32);
        }
        new_geo.origin.x += dx;
    }
    else if edge.contains(RESIZE_RIGHT) {
        if dx < 0 {
            new_geo.size.w = geo.size.w.saturating_sub(dx.abs() as u32);
        } else {
            new_geo.size.w = geo.size.w.saturating_add(dx.abs() as u32);
        }
    }

    if edge.contains(RESIZE_TOP) {
        if dy < 0 {
            new_geo.size.h = geo.size.h.saturating_add(dy.abs() as u32);
        } else {
            new_geo.size.h = geo.size.h.saturating_sub(dy.abs() as u32);
        }
        new_geo.origin.y += dy;
    }
    else if edge.contains(RESIZE_BOTTOM) {
        if dy < 0 {
            new_geo.size.h = geo.size.h.saturating_sub(dy.abs() as u32);
        } else {
            new_geo.size.h = geo.size.h.saturating_add(dy.abs() as u32);
        }
    }

    if new_geo.size.w <= MIN_SIZE.w {
        new_geo.origin.x = geo.origin.x;
        new_geo.size.w = geo.size.w;
    }

    if new_geo.size.h <= MIN_SIZE.h {
        new_geo.origin.y = geo.origin.y;
        new_geo.size.h = geo.size.h;
    }
    new_geo
}
<commit_msg>Pointer now sticks to container when resizing<commit_after>use rustwlc::{input, Point, ResizeEdge, Geometry,
              RESIZE_LEFT, RESIZE_RIGHT, RESIZE_TOP, RESIZE_BOTTOM,
              RESIZE_TOPLEFT, RESIZE_TOPRIGHT, RESIZE_BOTTOMLEFT, RESIZE_BOTTOMRIGHT,
};

use super::super::{Action, Direction, LayoutTree, TreeError};
use super::super::commands::{CommandResult};
use super::super::core::container::{ContainerType, MIN_SIZE};
use uuid::Uuid;

#[derive(Debug, Clone, Copy)]
pub enum ResizeErr {
    /// Expected the node associated with the UUID to be floating.
    ExpectedFloating(Uuid),
    /// Expected the node associated with the UUID to not be floating
    ExpectedNotFloating(Uuid)
}

impl LayoutTree {
    /// Updates pointer position for the node behind the id,
    /// in the same direction as the edge.
    pub fn update_pointer_pos(&self, id: Uuid, edge: ResizeEdge) -> CommandResult {
        let container = try!(self.lookup(id));
        let Geometry { mut origin, size } = container.get_geometry()
            .expect("Container had no geometry");
        drop(container);
        if edge.contains(RESIZE_TOPLEFT) {
            input::pointer::set_position(origin);
        } else if edge.contains(RESIZE_TOPRIGHT) {
            origin.x += size.w as i32;
            input::pointer::set_position(origin);
        } else if edge.contains(RESIZE_BOTTOMLEFT) {
            origin.y += size.h as i32;
            input::pointer::set_position(origin);
        } else if edge.contains(RESIZE_BOTTOMRIGHT) {
            origin.x += size.w as i32;
            origin.y += size.h as i32;
            input::pointer::set_position(origin);
        }
        Ok(())
    }

    /// Resizes a floating container. If the container was not floating, an Err is returned.
    pub fn resize_floating(&mut self, id: Uuid, edge: ResizeEdge, pointer: Point,
                           action: &mut Action) -> CommandResult {
        {
            let container = try!(self.lookup_mut(id));
            if !container.floating() {
                return Err(TreeError::Resize(ResizeErr::ExpectedFloating(container.get_id())))
            }
            match container.get_type() {
                ContainerType::View | ContainerType::Container => {},
                _ => return Err(TreeError::UuidWrongType(container.get_id(),
                                                        vec!(ContainerType::View)))
            }
            let geo = container.get_geometry()
                .expect("Could not get geometry of the container");

            let new_geo = calculate_resize(geo, edge, pointer, action.grab);
            action.grab = pointer;
            container.set_geometry(edge, new_geo);
        }
        self.update_pointer_pos(id, edge)
    }

    pub fn resize_tiled(&mut self, id: Uuid, edge: ResizeEdge, pointer: Point,
                        action: &mut Action) -> CommandResult {
        // There can be multiple directions we are moving in, e.g up and left.
        let dirs_moving_in = Direction::from_edge(edge);
        let siblings: Vec<Uuid> = dirs_moving_in.iter()
            .map(|dir| self.sibling_in_dir(id, *dir))
            // TODO There MUST be a better way to do something like this...
            .filter(|thing| thing.is_ok())
            .map(|thing| thing.unwrap())
            .collect();

        // Because we can't have multiple mutable references active in the tree at once,
        // first we modify the one the user is resizing and then adjust the siblings.
        {
            let container = try!(self.lookup_mut(id));
            if container.floating() {
                return Err(TreeError::Resize(ResizeErr::ExpectedNotFloating(container.get_id())))
            }
            match container.get_type() {
                ContainerType::View | ContainerType::Container => {},
                _ => return Err(TreeError::UuidWrongType(container.get_id(),
                                                        vec!(ContainerType::View)))
            }
            let geo = container.get_geometry()
                .expect("Could not get geometry of the container");
            let new_geo = calculate_resize(geo, edge, pointer, action.grab);
            container.set_geometry(edge, new_geo);
        }
        // and now we mutate the siblings
        let reversed_dir: Vec<Direction> = dirs_moving_in.iter()
            .map(|dir| dir.reverse()).collect();
        let reversed_edge = Direction::to_edge(reversed_dir.as_slice());
        for sibling in siblings {
            // TODO Abstract, the only thing different from above
            // is the edge and the exact node we are doing the calc on
            let container = try!(self.lookup_mut(sibling));
            if container.floating() {
                return Err(TreeError::Resize(ResizeErr::ExpectedNotFloating(container.get_id())))
            }
            match container.get_type() {
                ContainerType::View | ContainerType::Container => {},
                _ => return Err(TreeError::UuidWrongType(container.get_id(),
                                                         vec!(ContainerType::View)))
            }
            let geo = container.get_geometry()
                .expect("Could not get geometry of the container");
            let new_geo = calculate_resize(geo, reversed_edge, pointer, action.grab);
            action.grab = pointer;
            container.set_geometry(reversed_edge, new_geo);
        }
        let node_ix = self.tree.lookup_id(id).unwrap();
        self.layout(node_ix);
        action.grab = pointer;
        self.update_pointer_pos(id, edge)
    }
}

/// Calculates what the new geometry is of a window.
/// Needs the geometry of the window, the edge direction the pointer is moving in,
/// the current position of the pointer, and the previous place the pointer was at.
fn calculate_resize(geo: Geometry, edge: ResizeEdge,
                    cur_pointer: Point, prev_pointer: Point) -> Geometry {
    let mut new_geo = geo.clone();
    let dx = cur_pointer.x - prev_pointer.x;
    let dy = cur_pointer.y - prev_pointer.y;
    if edge.contains(RESIZE_LEFT) {
        if dx < 0 {
            new_geo.size.w = geo.size.w.saturating_add(dx.abs() as u32);
        } else {
            new_geo.size.w = geo.size.w.saturating_sub(dx.abs() as u32);
        }
        new_geo.origin.x += dx;
    }
    else if edge.contains(RESIZE_RIGHT) {
        if dx < 0 {
            new_geo.size.w = geo.size.w.saturating_sub(dx.abs() as u32);
        } else {
            new_geo.size.w = geo.size.w.saturating_add(dx.abs() as u32);
        }
    }

    if edge.contains(RESIZE_TOP) {
        if dy < 0 {
            new_geo.size.h = geo.size.h.saturating_add(dy.abs() as u32);
        } else {
            new_geo.size.h = geo.size.h.saturating_sub(dy.abs() as u32);
        }
        new_geo.origin.y += dy;
    }
    else if edge.contains(RESIZE_BOTTOM) {
        if dy < 0 {
            new_geo.size.h = geo.size.h.saturating_sub(dy.abs() as u32);
        } else {
            new_geo.size.h = geo.size.h.saturating_add(dy.abs() as u32);
        }
    }

    if new_geo.size.w <= MIN_SIZE.w {
        new_geo.origin.x = geo.origin.x;
        new_geo.size.w = geo.size.w;
    }

    if new_geo.size.h <= MIN_SIZE.h {
        new_geo.origin.y = geo.origin.y;
        new_geo.size.h = geo.size.h;
    }
    new_geo
}
<|endoftext|>