<commit_before>//! Utility functions and helpers specific to Windows

use std::mem::{transmute, size_of, MaybeUninit};
use std::os::raw::{c_int, c_void};
use std::ptr;

use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::processenv::GetStdHandle;
pub use winapi::shared::windef::{HDC, HWND};
pub use winapi::shared::minwindef::DWORD;
use winapi::shared::minwindef::ULONG;
pub use winapi::shared::windef::COLORREF;  // = DWORD
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::winbase::STD_ERROR_HANDLE;
use winapi::um::wincon::{GetConsoleWindow, GetConsoleScreenBufferInfo, GetCurrentConsoleFont};
pub use winapi::um::wincon::CONSOLE_SCREEN_BUFFER_INFO;
pub use winapi::um::wincontypes::CONSOLE_FONT_INFO;
use winapi::um::wingdi::{GetPixel, SetPixelV, StretchDIBits,
  BITMAPINFOHEADER, BITMAPINFO, BI_RGB, CLR_INVALID, DIB_RGB_COLORS, GDI_ERROR, RGB, RGBQUAD, SRCCOPY};
pub use winapi::um::winnt::HANDLE;
use winapi::um::winuser::{GetDC, ReleaseDC};

pub struct DeviceContext {
  /// cf. https://docs.microsoft.com/en-us/windows/console/getconsolewindow
  pub console_window: HWND,
  /// Device Context belonging to `console_window`
  pub dc: HDC,
  /// Hidden Error Handler: for when we can not return (such as in a `drop` RAII)
  pub heh: &'static dyn Fn (&'static str, DWORD),
  /// How wide can we paint, in pixels, set by `scan_size`
  pub width: i32,
  /// How far can we paint, in pixels, set by `scan_size`
  pub height: i32,
  /// Console Error: `STD_ERROR_HANDLE` retrieved with `GetStdHandle`,
  /// need it to get the font size and cursor position from the “console's active screen buffer”,
  /// to align graphics with text
  pub ce: HANDLE}

unsafe impl Send for DeviceContext {}

impl Drop for DeviceContext {
  fn drop (&mut self) {
    let rc = unsafe {ReleaseDC (self.console_window, self.dc)};
    if rc != 1 {(self.heh) ("ReleaseDC(dc)", unsafe {GetLastError()})}}}

impl DeviceContext {
  /// Obtains console window, Device Context and Console Error
  /// * `heh` - Error handler for when we can not return (such as in a `drop` RAII)
  pub fn with_heh (heh: &'static dyn Fn (&'static str, DWORD)) -> Result<DeviceContext, String> {
    let console_window = unsafe {GetConsoleWindow()};
    if console_window == ptr::null_mut() {return ERR! ("!GetConsoleWindow")}

    let dc = unsafe {GetDC (console_window)};
    if dc == ptr::null_mut() {return ERR! ("!GetDC")}

    let ce = unsafe {GetStdHandle (STD_ERROR_HANDLE)};
    if ce == INVALID_HANDLE_VALUE {return ERR! ("!GetStdHandle")}

    Ok (DeviceContext {
      console_window,
      dc,
      heh,
      width: 0,
      height: 0,
      ce})}

  /// Obtains console window, Device Context and Console Error
  pub fn new() -> Result<DeviceContext, String> {
    DeviceContext::with_heh (&|_label, _errno| {})}

  /// Packs RGB for a `stretch_to` pixel
  pub fn rgba (r: u8, g: u8, b: u8) -> u32 {
    let quad = RGBQUAD {
      rgbBlue: b,
      rgbGreen: g,
      rgbRed: r,
      rgbReserved: 0};
    unsafe {transmute (quad)}}

  /// Paints the given `rgba`
  /// Stretches the image if `w` <> `sw` or `h` <> `sh`
  /// `rgba` position `i = iy * sw + ix`
  pub fn stretch (&self, x: i32, y: i32, w: i32, h: i32, sx: i32, sy: i32, sw: i32, sh: i32, rgba: &[u32])
  -> Result<i32, DWORD> {
    let mut inf: BITMAPINFO = unsafe {MaybeUninit::zeroed().assume_init()};
    inf.bmiHeader.biSize = size_of::<BITMAPINFOHEADER>() as u32;
    inf.bmiHeader.biWidth = sw;
    inf.bmiHeader.biHeight = -sh;  // “top-down DIB”
    inf.bmiHeader.biPlanes = 1;
    inf.bmiHeader.biBitCount = 32;
    inf.bmiHeader.biCompression = BI_RGB;
    inf.bmiHeader.biSizeImage = (sw * sh * 4) as u32;

    // https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-stretchdibits
    let rc = unsafe {StretchDIBits (
      self.dc, x, y, w, h, sx, sy, sw, sh, rgba.as_ptr() as *const c_void, &inf, DIB_RGB_COLORS, SRCCOPY)};
    if rc == 0 || rc as ULONG == GDI_ERROR {Err (unsafe {GetLastError()})} else {Ok (rc)}}

  /// cf. https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixelv
  pub fn set_pixel (&self, x: i32, y: i32, r: u8, g: u8, b: u8) -> Result<(), DWORD> {
    let rc = unsafe {SetPixelV (self.dc, x, y, RGB (r, g, b))};
    if rc == 0 {Err (unsafe {GetLastError()})} else {Ok(())}}

  /// cf. https://docs.microsoft.com/en-us/windows/win32/gdi/colorref
  pub fn get_pixel (&self, x: i32, y: i32) -> Result<COLORREF, ()> {
    let rc = unsafe {GetPixel (self.dc, x as c_int, y as c_int)};
    if rc == CLR_INVALID {
      Err (())
    } else {
      Ok (rc)}}

  /// Experimentally determine max `width` and `height` in pixels
  pub fn scan_size (&mut self) {
    // NB: GetDeviceCaps with HORZRES and VERTRES returns bogus values
    //   GetWindowRect too: it seems to match results obtained
    //   multiplying GetConsoleFontSize by GetConsoleScreenBufferInfo/dwSize,
    //   but the actual number of pixels is different
    let (mut width, mut height) = (0, 0);
    while self.get_pixel (width + 31, height + 31) .is_ok() {width += 31; height += 31}
    while self.get_pixel (width + 9, height) .is_ok() {width += 9}
    while self.get_pixel (width + 1, height) .is_ok() {width += 1}
    while self.get_pixel (width, height + 1) .is_ok() {height += 1}
    self.width = width + 1; self.height = height + 1}

  /// cf. https://docs.microsoft.com/en-us/windows/console/console-font-info-str
  pub fn font (&self) -> Result<CONSOLE_FONT_INFO, String> {
    let mut font: CONSOLE_FONT_INFO = unsafe {MaybeUninit::zeroed().assume_init()};
    let rc = unsafe {GetCurrentConsoleFont (self.ce, 0, &mut font)};
    if rc == 0 {ERR! ("!GetCurrentConsoleFont")} else {Ok (font)}}

  /// cf. https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
  pub fn screen_buffer_info (&self) -> Result<CONSOLE_SCREEN_BUFFER_INFO, DWORD> {
    let mut sbi: CONSOLE_SCREEN_BUFFER_INFO = unsafe {MaybeUninit::zeroed().assume_init()};
    let rc = unsafe {GetConsoleScreenBufferInfo (self.ce, &mut sbi)};
    if rc == 0 {Err (unsafe {GetLastError()})} else {Ok (sbi)}}

  /// Bridges character position to pixels
  /// Depends on `scan_size` (called separately) to know the actual pixel dimensions
  pub fn translate (&self) -> Result<(Translation, CONSOLE_SCREEN_BUFFER_INFO), String> {
    let sbi = try_s! (self.screen_buffer_info());
    // The actual character size in Windows might differ from the one reported in `CONSOLE_FONT_INFO`
    let (mut tw, mut th) = (1, 2);
    let sw = (sbi.srWindow.Right - sbi.srWindow.Left) as i16;
    if sw > 0 {while (tw + 1) as i32 * sw as i32 <= self.width {tw += 1}}

    let sh = (sbi.srWindow.Bottom - sbi.srWindow.Top) as i16 + 1;
    if sh > 0 {while (th + 1) as i32 * sh as i32 <= self.height {th += 1}}
    //println! ("\nself.height {} vs th*sh= {}; th {}\n", self.height, th as i16 * sh, th);

    Ok ((Translation {
      cxa: sbi.dwCursorPosition.X as i16,
      left: sbi.srWindow.Left as i16,
      cya: sbi.dwCursorPosition.Y as i16,
      top: sbi.srWindow.Top as i16,
      sw,
      sh,
      tw,
      th
    }, sbi))}}

/// Bridges character position to pixels
#[derive(Clone, Debug)]
pub struct Translation {
  /// Cursor X, Absolute, in characters, 0-based
  pub cxa: i16,
  /// Horizontal scrolling
  pub left: i16,
  /// Cursor Y, Absolute, in characters, 0-based
  /// Mind the scrolling: if `cy` equals `sh` then the measurement
  /// was taken at the bottom of the visible screen
  /// Also with lines recently printed on
  /// the actual *paint* of characters by the terminal might happen after a small delay,
  /// overwriting whatever graphics we put there: should either wait for the terminal *paint* to settle
  /// or better yet maintain a set of overlays to be redrawn periodically
  pub cya: i16,
  /// Vertical scrolling
  pub top: i16,
  /// Screen Width in characters (`Right - Left`)
  pub sw: i16,
  /// Screen Height in characters (`Bottom - Top`)
  pub sh: i16,
  /// Text Width: a likely number of horisontal pixels in a character
  pub tw: i8,
  /// Text Height: a likely number of vertical pixels in a character
  pub th: i8}

impl Translation {
  pub fn cx (&self) -> i32 {
    self.cxa as i32 - self.left as i32}

  pub fn cy (&self) -> i32 {
    self.cya as i32 - self.top as i32}}
<commit_msg>Keep width and height when get_pixel is out of comission<commit_after>//! Utility functions and helpers specific to Windows

use std::mem::{transmute, size_of, MaybeUninit};
use std::os::raw::{c_int, c_void};
use std::ptr;

use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::processenv::GetStdHandle;
pub use winapi::shared::windef::{HDC, HWND};
pub use winapi::shared::minwindef::DWORD;
use winapi::shared::minwindef::ULONG;
pub use winapi::shared::windef::COLORREF;  // = DWORD
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::winbase::STD_ERROR_HANDLE;
use winapi::um::wincon::{GetConsoleWindow, GetConsoleScreenBufferInfo, GetCurrentConsoleFont};
pub use winapi::um::wincon::CONSOLE_SCREEN_BUFFER_INFO;
pub use winapi::um::wincontypes::CONSOLE_FONT_INFO;
use winapi::um::wingdi::{GetPixel, SetPixelV, StretchDIBits,
  BITMAPINFOHEADER, BITMAPINFO, BI_RGB, CLR_INVALID, DIB_RGB_COLORS, GDI_ERROR, RGB, RGBQUAD, SRCCOPY};
pub use winapi::um::winnt::HANDLE;
use winapi::um::winuser::{GetDC, ReleaseDC};

pub struct DeviceContext {
  /// cf. https://docs.microsoft.com/en-us/windows/console/getconsolewindow
  pub console_window: HWND,
  /// Device Context belonging to `console_window`
  pub dc: HDC,
  /// Hidden Error Handler: for when we can not return (such as in a `drop` RAII)
  pub heh: &'static dyn Fn (&'static str, DWORD),
  /// How wide can we paint, in pixels, set by `scan_size`
  pub width: i32,
  /// How far can we paint, in pixels, set by `scan_size`
  pub height: i32,
  /// Console Error: `STD_ERROR_HANDLE` retrieved with `GetStdHandle`,
  /// need it to get the font size and cursor position from the “console's active screen buffer”,
  /// to align graphics with text
  pub ce: HANDLE}

unsafe impl Send for DeviceContext {}

impl Drop for DeviceContext {
  fn drop (&mut self) {
    let rc = unsafe {ReleaseDC (self.console_window, self.dc)};
    if rc != 1 {(self.heh) ("ReleaseDC(dc)", unsafe {GetLastError()})}}}

impl DeviceContext {
  /// Obtains console window, Device Context and Console Error
  /// * `heh` - Error handler for when we can not return (such as in a `drop` RAII)
  pub fn with_heh (heh: &'static dyn Fn (&'static str, DWORD)) -> Result<DeviceContext, String> {
    let console_window = unsafe {GetConsoleWindow()};
    if console_window == ptr::null_mut() {return ERR! ("!GetConsoleWindow")}

    let dc = unsafe {GetDC (console_window)};
    if dc == ptr::null_mut() {return ERR! ("!GetDC")}

    let ce = unsafe {GetStdHandle (STD_ERROR_HANDLE)};
    if ce == INVALID_HANDLE_VALUE {return ERR! ("!GetStdHandle")}

    Ok (DeviceContext {
      console_window,
      dc,
      heh,
      width: 0,
      height: 0,
      ce})}

  /// Obtains console window, Device Context and Console Error
  pub fn new() -> Result<DeviceContext, String> {
    DeviceContext::with_heh (&|_label, _errno| {})}

  /// Packs RGB for a `stretch_to` pixel
  pub fn rgba (r: u8, g: u8, b: u8) -> u32 {
    let quad = RGBQUAD {
      rgbBlue: b,
      rgbGreen: g,
      rgbRed: r,
      rgbReserved: 0};
    unsafe {transmute (quad)}}

  /// Paints the given `rgba`
  /// Stretches the image if `w` <> `sw` or `h` <> `sh`
  /// `rgba` position `i = iy * sw + ix`
  pub fn stretch (&self, x: i32, y: i32, w: i32, h: i32, sx: i32, sy: i32, sw: i32, sh: i32, rgba: &[u32])
  -> Result<i32, DWORD> {
    let mut inf: BITMAPINFO = unsafe {MaybeUninit::zeroed().assume_init()};
    inf.bmiHeader.biSize = size_of::<BITMAPINFOHEADER>() as u32;
    inf.bmiHeader.biWidth = sw;
    inf.bmiHeader.biHeight = -sh;  // “top-down DIB”
    inf.bmiHeader.biPlanes = 1;
    inf.bmiHeader.biBitCount = 32;
    inf.bmiHeader.biCompression = BI_RGB;
    inf.bmiHeader.biSizeImage = (sw * sh * 4) as u32;

    // https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-stretchdibits
    let rc = unsafe {StretchDIBits (
      self.dc, x, y, w, h, sx, sy, sw, sh, rgba.as_ptr() as *const c_void, &inf, DIB_RGB_COLORS, SRCCOPY)};
    if rc == 0 || rc as ULONG == GDI_ERROR {Err (unsafe {GetLastError()})} else {Ok (rc)}}

  /// cf. https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixelv
  pub fn set_pixel (&self, x: i32, y: i32, r: u8, g: u8, b: u8) -> Result<(), DWORD> {
    let rc = unsafe {SetPixelV (self.dc, x, y, RGB (r, g, b))};
    if rc == 0 {Err (unsafe {GetLastError()})} else {Ok(())}}

  /// cf. https://docs.microsoft.com/en-us/windows/win32/gdi/colorref
  /// NB: Looks like the window needs to be visible in order for `get_pixel` to work
  pub fn get_pixel (&self, x: i32, y: i32) -> Result<COLORREF, ()> {
    let rc = unsafe {GetPixel (self.dc, x as c_int, y as c_int)};
    if rc == CLR_INVALID {
      Err (())
    } else {
      Ok (rc)}}

  /// Experimentally determine max `width` and `height` in pixels
  /// NB: Looks like the window needs to be visible in order for `get_pixel` to work
  pub fn scan_size (&mut self) {
    if let Err (()) = self.get_pixel (1, 1) {  // Return early if `get_pixel` doesn't work (window hidden)
      let errno = unsafe {GetLastError()};
      if errno != 0 {(self.heh) ("get_pixel (1, 1)", errno)}
      return}

    // NB: GetDeviceCaps with HORZRES and VERTRES returns bogus values
    //   GetWindowRect too: it seems to match results obtained
    //   multiplying GetConsoleFontSize by GetConsoleScreenBufferInfo/dwSize,
    //   but the actual number of pixels is different
    let (mut width, mut height) = (0, 0);
    while self.get_pixel (width + 31, height + 31) .is_ok() {width += 31; height += 31}
    while self.get_pixel (width + 9, height) .is_ok() {width += 9}
    while self.get_pixel (width + 1, height) .is_ok() {width += 1}
    while self.get_pixel (width, height + 1) .is_ok() {height += 1}
    self.width = width + 1; self.height = height + 1}

  /// cf. https://docs.microsoft.com/en-us/windows/console/console-font-info-str
  pub fn font (&self) -> Result<CONSOLE_FONT_INFO, String> {
    let mut font: CONSOLE_FONT_INFO = unsafe {MaybeUninit::zeroed().assume_init()};
    let rc = unsafe {GetCurrentConsoleFont (self.ce, 0, &mut font)};
    if rc == 0 {ERR! ("!GetCurrentConsoleFont")} else {Ok (font)}}

  /// cf. https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
  pub fn screen_buffer_info (&self) -> Result<CONSOLE_SCREEN_BUFFER_INFO, DWORD> {
    let mut sbi: CONSOLE_SCREEN_BUFFER_INFO = unsafe {MaybeUninit::zeroed().assume_init()};
    let rc = unsafe {GetConsoleScreenBufferInfo (self.ce, &mut sbi)};
    if rc == 0 {Err (unsafe {GetLastError()})} else {Ok (sbi)}}

  /// Bridges character position to pixels
  /// Depends on `scan_size` (called separately) to know the actual pixel dimensions
  pub fn translate (&self) -> Result<(Translation, CONSOLE_SCREEN_BUFFER_INFO), String> {
    let sbi = try_s! (self.screen_buffer_info());
    // The actual character size in Windows might differ from the one reported in `CONSOLE_FONT_INFO`
    let (mut tw, mut th) = (1, 2);
    let sw = (sbi.srWindow.Right - sbi.srWindow.Left) as i16;
    if sw > 0 {while (tw + 1) as i32 * sw as i32 <= self.width {tw += 1}}

    let sh = (sbi.srWindow.Bottom - sbi.srWindow.Top) as i16 + 1;
    if sh > 0 {while (th + 1) as i32 * sh as i32 <= self.height {th += 1}}
    //println! ("\nself.height {} vs th*sh= {}; th {}\n", self.height, th as i16 * sh, th);

    Ok ((Translation {
      cxa: sbi.dwCursorPosition.X as i16,
      left: sbi.srWindow.Left as i16,
      cya: sbi.dwCursorPosition.Y as i16,
      top: sbi.srWindow.Top as i16,
      sw,
      sh,
      tw,
      th
    }, sbi))}}

/// Bridges character position to pixels
#[derive(Clone, Debug)]
pub struct Translation {
  /// Cursor X, Absolute, in characters, 0-based
  pub cxa: i16,
  /// Horizontal scrolling
  pub left: i16,
  /// Cursor Y, Absolute, in characters, 0-based
  /// Mind the scrolling: if `cy` equals `sh` then the measurement
  /// was taken at the bottom of the visible screen
  /// Also with lines recently printed on
  /// the actual *paint* of characters by the terminal might happen after a small delay,
  /// overwriting whatever graphics we put there: should either wait for the terminal *paint* to settle
  /// or better yet maintain a set of overlays to be redrawn periodically
  pub cya: i16,
  /// Vertical scrolling
  pub top: i16,
  /// Screen Width in characters (`Right - Left`)
  pub sw: i16,
  /// Screen Height in characters (`Bottom - Top`)
  pub sh: i16,
  /// Text Width: a likely number of horisontal pixels in a character
  pub tw: i8,
  /// Text Height: a likely number of vertical pixels in a character
  pub th: i8}

impl Translation {
  pub fn cx (&self) -> i32 {
    self.cxa as i32 - self.left as i32}

  pub fn cy (&self) -> i32 {
    self.cya as i32 - self.top as i32}}
<|endoftext|>


<commit_before>//! Slither Link solver logic.

#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate union_find;
extern crate slsr_core;

use std::fmt;
use slsr_core::board::Board;
use slsr_core::geom::CellId;

use solver::Solver;
use theorem_define::THEOREM_DEFINE;

mod model {
    pub mod connect_map;
    pub mod side_map;
    pub mod theorem;
}
mod step {
    pub mod apply_theorem;
    pub mod connect_analysis;
}
mod theorem_define;
mod solver;

#[derive(Copy, Clone, Debug)]
pub struct LogicError;

impl fmt::Display for LogicError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", *self)
    }
}

pub type SolverResult<T> = Result<T, LogicError>;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum State<T> {
    Fixed(T), Unknown, Conflict
}

impl<T> Into<Result<Option<T>, LogicError>> for State<T> {
    fn into(self) -> Result<Option<T>, LogicError> {
        match self {
            State::Fixed(st) => Ok(Some(st)),
            State::Unknown => Ok(None),
            State::Conflict => Err(LogicError)
        }
    }
}

fn solve_by_logic(solver: &mut Solver) -> SolverResult<()>
{
    let mut rev = solver.revision();

    while !solver.all_filled() {
        try!(solver.apply_all_theorem());

        if solver.all_filled() {
            return Ok(())
        }
        // FIXME: apply_all_theorem do the same thing with this
        if solver.revision() != rev {
            rev = solver.revision();
            continue
        }

        try!(solver.connect_analysis());
        if solver.revision() == rev {
            break;
        }

        rev = solver.revision();
    }

    Ok(())
}

fn solve_by_backtracking_one_step(solver: &mut Solver, pts: &[CellId])
                                  -> SolverResult<bool>
{
    let rev = solver.revision();

    for &p in pts {
        match solver.get_side(p) {
            State::Fixed(_) => continue,
            State::Unknown => {}
            State::Conflict => { return Err(LogicError) }
        }

        let mut solver_0 = solver.clone();
        solver_0.set_inside(p);

        if solve_by_logic(&mut solver_0).is_err() {
            solver.set_outside(p);
            try!(solve_by_logic(solver));
            continue
        }

        let mut solver_1 = solver.clone();
        solver_1.set_outside(p);

        if solve_by_logic(&mut solver_1).is_err() {
            *solver = solver_0;
        }
    }

    Ok(solver.revision() != rev)
}

pub fn solve(board: &Board) -> Result<Board, LogicError> {
    let theorem = THEOREM_DEFINE.iter().map(|theo| theo.parse().unwrap());

    let mut queue = vec![try!(Solver::new(board, theorem))];

    'failure: while let Some(mut solver) = queue.pop() {
        if solve_by_logic(&mut solver).is_err() {
            continue
        }

        if solver.all_filled() {
            if solver.validate_result().is_err() {
                continue
            }
            return solver.into()
        }

        let mut pts = solver.get_unknown_points();
        loop {
            match solve_by_backtracking_one_step(&mut solver, &pts) {
                Ok(true) => {
                    if solver.all_filled() {
                        if solver.validate_result().is_err() {
                            continue
                        }
                        return solver.into()
                    }
                    pts = solver.get_unknown_points();
                }
                Ok(false) => break,
                Err(_) => continue 'failure,
            }
        }

        let p = *pts.last().unwrap();
        let mut solver_0 = solver.clone();
        let mut solver_1 = solver;
        solver_0.set_outside(p);
        solver_1.set_inside(p);
        queue.push(solver_0);
        queue.push(solver_1);
    }

    Err(LogicError)
}
<commit_msg>solver: remove extra condition<commit_after>//! Slither Link solver logic.

#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate union_find;
extern crate slsr_core;

use std::fmt;
use slsr_core::board::Board;
use slsr_core::geom::CellId;

use solver::Solver;
use theorem_define::THEOREM_DEFINE;

mod model {
    pub mod connect_map;
    pub mod side_map;
    pub mod theorem;
}
mod step {
    pub mod apply_theorem;
    pub mod connect_analysis;
}
mod theorem_define;
mod solver;

#[derive(Copy, Clone, Debug)]
pub struct LogicError;

impl fmt::Display for LogicError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", *self)
    }
}

pub type SolverResult<T> = Result<T, LogicError>;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum State<T> {
    Fixed(T), Unknown, Conflict
}

impl<T> Into<Result<Option<T>, LogicError>> for State<T> {
    fn into(self) -> Result<Option<T>, LogicError> {
        match self {
            State::Fixed(st) => Ok(Some(st)),
            State::Unknown => Ok(None),
            State::Conflict => Err(LogicError)
        }
    }
}

fn solve_by_logic(solver: &mut Solver) -> SolverResult<()>
{
    let mut rev = solver.revision();

    while !solver.all_filled() {
        try!(solver.apply_all_theorem());

        if solver.all_filled() {
            return Ok(())
        }

        try!(solver.connect_analysis());
        if solver.revision() == rev {
            break;
        }

        rev = solver.revision();
    }

    Ok(())
}

fn solve_by_backtracking_one_step(solver: &mut Solver, pts: &[CellId])
                                  -> SolverResult<bool>
{
    let rev = solver.revision();

    for &p in pts {
        match solver.get_side(p) {
            State::Fixed(_) => continue,
            State::Unknown => {}
            State::Conflict => { return Err(LogicError) }
        }

        let mut solver_0 = solver.clone();
        solver_0.set_inside(p);

        if solve_by_logic(&mut solver_0).is_err() {
            solver.set_outside(p);
            try!(solve_by_logic(solver));
            continue
        }

        let mut solver_1 = solver.clone();
        solver_1.set_outside(p);

        if solve_by_logic(&mut solver_1).is_err() {
            *solver = solver_0;
        }
    }

    Ok(solver.revision() != rev)
}

pub fn solve(board: &Board) -> Result<Board, LogicError> {
    let theorem = THEOREM_DEFINE.iter().map(|theo| theo.parse().unwrap());

    let mut queue = vec![try!(Solver::new(board, theorem))];

    'failure: while let Some(mut solver) = queue.pop() {
        if solve_by_logic(&mut solver).is_err() {
            continue
        }

        if solver.all_filled() {
            if solver.validate_result().is_err() {
                continue
            }
            return solver.into()
        }

        let mut pts = solver.get_unknown_points();
        loop {
            match solve_by_backtracking_one_step(&mut solver, &pts) {
                Ok(true) => {
                    if solver.all_filled() {
                        if solver.validate_result().is_err() {
                            continue
                        }
                        return solver.into()
                    }
                    pts = solver.get_unknown_points();
                }
                Ok(false) => break,
                Err(_) => continue 'failure,
            }
        }

        let p = *pts.last().unwrap();
        let mut solver_0 = solver.clone();
        let mut solver_1 = solver;
        solver_0.set_outside(p);
        solver_1.set_inside(p);
        queue.push(solver_0);
        queue.push(solver_1);
    }

    Err(LogicError)
}
<|endoftext|>


<commit_before>//! A small TCP server to handle collection of diagnostics information in a
//! cross-platform way for the `cargo fix` command.

use std::collections::HashSet;
use std::env;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread::{self, JoinHandle};

use failure::{Error, ResultExt};
use log::warn;
use serde::{Deserialize, Serialize};

use crate::util::errors::CargoResult;
use crate::util::{Config, ProcessBuilder};

const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
const PLEASE_REPORT_THIS_BUG: &str =
    "\
     This likely indicates a bug in either rustc or cargo itself,\n\
     and we would appreciate a bug report! You're likely to see \n\
     a number of compiler warnings after this message which cargo\n\
     attempted to fix but failed. If you could open an issue at\n\
     https://github.com/rust-lang/cargo/issues\n\
     quoting the full output of this command we'd be very appreciative!\n\n\
     ";

#[derive(Deserialize, Serialize)]
pub enum Message {
    Fixing {
        file: String,
        fixes: u32,
    },
    FixFailed {
        files: Vec<String>,
        krate: Option<String>,
        errors: Vec<String>,
    },
    ReplaceFailed {
        file: String,
        message: String,
    },
    EditionAlreadyEnabled {
        file: String,
        edition: String,
    },
    IdiomEditionMismatch {
        file: String,
        idioms: String,
        edition: Option<String>,
    },
}

impl Message {
    pub fn post(&self) -> Result<(), Error> {
        let addr =
            env::var(DIAGNOSICS_SERVER_VAR).context("diagnostics collector misconfigured")?;
        let mut client =
            TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?;

        let s = serde_json::to_string(self).context("failed to serialize message")?;
        client
            .write_all(s.as_bytes())
            .context("failed to write message to diagnostics target")?;
        client
            .shutdown(Shutdown::Write)
            .context("failed to shutdown")?;

        let mut tmp = Vec::new();
        client
            .read_to_end(&mut tmp)
            .context("failed to receive a disconnect")?;

        Ok(())
    }
}

pub struct DiagnosticPrinter<'a> {
    config: &'a Config,
    edition_already_enabled: HashSet<String>,
    idiom_mismatch: HashSet<String>,
}

impl<'a> DiagnosticPrinter<'a> {
    pub fn new(config: &'a Config) -> DiagnosticPrinter<'a> {
        DiagnosticPrinter {
            config,
            edition_already_enabled: HashSet::new(),
            idiom_mismatch: HashSet::new(),
        }
    }

    pub fn print(&mut self, msg: &Message) -> CargoResult<()> {
        match msg {
            Message::Fixing { file, fixes } => {
                let msg = if *fixes == 1 { "fix" } else { "fixes" };
                let msg = format!("{} ({} {})", file, fixes, msg);
                self.config.shell().status("Fixing", msg)
            }
            Message::ReplaceFailed { file, message } => {
                let msg = format!("error applying suggestions to `{}`\n", file);
                self.config.shell().warn(&msg)?;
                write!(
                    self.config.shell().err(),
                    "The full error message was:\n\n> {}\n\n",
                    message,
                )?;
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::FixFailed {
                files,
                krate,
                errors,
            } => {
                if let Some(ref krate) = *krate {
                    self.config.shell().warn(&format!(
                        "failed to automatically apply fixes suggested by rustc \
                         to crate `{}`",
                        krate,
                    ))?;
                } else {
                    self.config
                        .shell()
                        .warn("failed to automatically apply fixes suggested by rustc")?;
                }
                if !files.is_empty() {
                    writeln!(
                        self.config.shell().err(),
                        "\nafter fixes were automatically applied the compiler \
                         reported errors within these files:\n"
                    )?;
                    for file in files {
                        writeln!(self.config.shell().err(), "  * {}", file)?;
                    }
                    writeln!(self.config.shell().err())?;
                }
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                if !errors.is_empty() {
                    writeln!(
                        self.config.shell().err(),
                        "The following errors were reported:"
                    )?;
                    for error in errors {
                        write!(self.config.shell().err(), "{}", error)?;
                        if !error.ends_with('\n') {
                            writeln!(self.config.shell().err())?;
                        }
                    }
                }
                writeln!(
                    self.config.shell().err(),
                    "Original diagnostics will follow.\n"
                )?;
                Ok(())
            }
            Message::EditionAlreadyEnabled { file, edition } => {
                // Like above, only warn once per file
                if !self.edition_already_enabled.insert(file.clone()) {
                    return Ok(());
                }

                let msg = format!(
                    "\
cannot prepare for the {} edition when it is enabled, so cargo cannot
automatically fix errors in `{}`

To prepare for the {0} edition you should first remove `edition = '{0}'` from
your `Cargo.toml` and then rerun this command. Once all warnings have been fixed
then you can re-enable the `edition` key in `Cargo.toml`. For some more
information about transitioning to the {0} edition see:

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html
",
                    edition,
                    file,
                );
                self.config.shell().error(&msg)?;
                Ok(())
            }
            Message::IdiomEditionMismatch {
                file,
                idioms,
                edition,
            } => {
                // Same as above
                if !self.idiom_mismatch.insert(file.clone()) {
                    return Ok(());
                }
                self.config.shell().error(&format!(
                    "\
cannot migrate to the idioms of the {} edition for `{}`
because it is compiled {}, which doesn't match {0}

consider migrating to the {0} edition by adding `edition = '{0}'` to
`Cargo.toml` and then rerunning this command; a more detailed transition
guide can be found at

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html
",
                    idioms,
                    file,
                    match edition {
                        Some(s) => format!("with the {} edition", s),
                        None => "without an edition".to_string(),
                    },
                ))?;
                Ok(())
            }
        }
    }
}

#[derive(Debug)]
pub struct RustfixDiagnosticServer {
    listener: TcpListener,
    addr: SocketAddr,
}

pub struct StartedServer {
    addr: SocketAddr,
    done: Arc<AtomicBool>,
    thread: Option<JoinHandle<()>>,
}

impl RustfixDiagnosticServer {
    pub fn new() -> Result<Self, Error> {
        let listener = TcpListener::bind("127.0.0.1:0")
            .with_context(|_| "failed to bind TCP listener to manage locking")?;
        let addr = listener.local_addr()?;

        Ok(RustfixDiagnosticServer { listener, addr })
    }

    pub fn configure(&self, process: &mut ProcessBuilder) {
        process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string());
    }

    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>
    where
        F: Fn(Message) + Send + 'static,
    {
        let addr = self.addr;
        let done = Arc::new(AtomicBool::new(false));
        let done2 = done.clone();
        let thread = thread::spawn(move || {
            self.run(&on_message, &done2);
        });

        Ok(StartedServer {
            addr,
            thread: Some(thread),
            done,
        })
    }

    fn run(self, on_message: &dyn Fn(Message), done: &AtomicBool) {
        while let Ok((client, _)) = self.listener.accept() {
            let client = BufReader::new(client);
            match serde_json::from_reader(client) {
                Ok(message) => on_message(message),
                Err(e) => warn!("invalid diagnostics message: {}", e),
            }
            if done.load(Ordering::SeqCst) {
                break;
            }
        }
    }
}

impl Drop for StartedServer {
    fn drop(&mut self) {
        self.done.store(true, Ordering::SeqCst);
        // Ignore errors here as this is largely best-effort
        if TcpStream::connect(&self.addr).is_err() {
            return;
        }
        drop(self.thread.take().unwrap().join());
    }
}
<commit_msg>Fix a very minor race condition in `cargo fix`.<commit_after>//! A small TCP server to handle collection of diagnostics information in a
//! cross-platform way for the `cargo fix` command.

use std::collections::HashSet;
use std::env;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread::{self, JoinHandle};

use failure::{Error, ResultExt};
use log::warn;
use serde::{Deserialize, Serialize};

use crate::util::errors::CargoResult;
use crate::util::{Config, ProcessBuilder};

const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
const PLEASE_REPORT_THIS_BUG: &str =
    "\
     This likely indicates a bug in either rustc or cargo itself,\n\
     and we would appreciate a bug report! You're likely to see \n\
     a number of compiler warnings after this message which cargo\n\
     attempted to fix but failed. If you could open an issue at\n\
     https://github.com/rust-lang/cargo/issues\n\
     quoting the full output of this command we'd be very appreciative!\n\n\
     ";

#[derive(Deserialize, Serialize)]
pub enum Message {
    Fixing {
        file: String,
        fixes: u32,
    },
    FixFailed {
        files: Vec<String>,
        krate: Option<String>,
        errors: Vec<String>,
    },
    ReplaceFailed {
        file: String,
        message: String,
    },
    EditionAlreadyEnabled {
        file: String,
        edition: String,
    },
    IdiomEditionMismatch {
        file: String,
        idioms: String,
        edition: Option<String>,
    },
}

impl Message {
    pub fn post(&self) -> Result<(), Error> {
        let addr =
            env::var(DIAGNOSICS_SERVER_VAR).context("diagnostics collector misconfigured")?;
        let mut client =
            TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?;

        let s = serde_json::to_string(self).context("failed to serialize message")?;
        client
            .write_all(s.as_bytes())
            .context("failed to write message to diagnostics target")?;
        client
            .shutdown(Shutdown::Write)
            .context("failed to shutdown")?;

        let mut tmp = Vec::new();
        client
            .read_to_end(&mut tmp)
            .context("failed to receive a disconnect")?;

        Ok(())
    }
}

pub struct DiagnosticPrinter<'a> {
    config: &'a Config,
    edition_already_enabled: HashSet<String>,
    idiom_mismatch: HashSet<String>,
}

impl<'a> DiagnosticPrinter<'a> {
    pub fn new(config: &'a Config) -> DiagnosticPrinter<'a> {
        DiagnosticPrinter {
            config,
            edition_already_enabled: HashSet::new(),
            idiom_mismatch: HashSet::new(),
        }
    }

    pub fn print(&mut self, msg: &Message) -> CargoResult<()> {
        match msg {
            Message::Fixing { file, fixes } => {
                let msg = if *fixes == 1 { "fix" } else { "fixes" };
                let msg = format!("{} ({} {})", file, fixes, msg);
                self.config.shell().status("Fixing", msg)
            }
            Message::ReplaceFailed { file, message } => {
                let msg = format!("error applying suggestions to `{}`\n", file);
                self.config.shell().warn(&msg)?;
                write!(
                    self.config.shell().err(),
                    "The full error message was:\n\n> {}\n\n",
                    message,
                )?;
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::FixFailed {
                files,
                krate,
                errors,
            } => {
                if let Some(ref krate) = *krate {
                    self.config.shell().warn(&format!(
                        "failed to automatically apply fixes suggested by rustc \
                         to crate `{}`",
                        krate,
                    ))?;
                } else {
                    self.config
                        .shell()
                        .warn("failed to automatically apply fixes suggested by rustc")?;
                }
                if !files.is_empty() {
                    writeln!(
                        self.config.shell().err(),
                        "\nafter fixes were automatically applied the compiler \
                         reported errors within these files:\n"
                    )?;
                    for file in files {
                        writeln!(self.config.shell().err(), "  * {}", file)?;
                    }
                    writeln!(self.config.shell().err())?;
                }
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                if !errors.is_empty() {
                    writeln!(
                        self.config.shell().err(),
                        "The following errors were reported:"
                    )?;
                    for error in errors {
                        write!(self.config.shell().err(), "{}", error)?;
                        if !error.ends_with('\n') {
                            writeln!(self.config.shell().err())?;
                        }
                    }
                }
                writeln!(
                    self.config.shell().err(),
                    "Original diagnostics will follow.\n"
                )?;
                Ok(())
            }
            Message::EditionAlreadyEnabled { file, edition } => {
                // Like above, only warn once per file
                if !self.edition_already_enabled.insert(file.clone()) {
                    return Ok(());
                }

                let msg = format!(
                    "\
cannot prepare for the {} edition when it is enabled, so cargo cannot
automatically fix errors in `{}`

To prepare for the {0} edition you should first remove `edition = '{0}'` from
your `Cargo.toml` and then rerun this command. Once all warnings have been fixed
then you can re-enable the `edition` key in `Cargo.toml`. For some more
information about transitioning to the {0} edition see:

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html
",
                    edition,
                    file,
                );
                self.config.shell().error(&msg)?;
                Ok(())
            }
            Message::IdiomEditionMismatch {
                file,
                idioms,
                edition,
            } => {
                // Same as above
                if !self.idiom_mismatch.insert(file.clone()) {
                    return Ok(());
                }
                self.config.shell().error(&format!(
                    "\
cannot migrate to the idioms of the {} edition for `{}`
because it is compiled {}, which doesn't match {0}

consider migrating to the {0} edition by adding `edition = '{0}'` to
`Cargo.toml` and then rerunning this command; a more detailed transition
guide can be found at

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html
",
                    idioms,
                    file,
                    match edition {
                        Some(s) => format!("with the {} edition", s),
                        None => "without an edition".to_string(),
                    },
                ))?;
                Ok(())
            }
        }
    }
}

#[derive(Debug)]
pub struct RustfixDiagnosticServer {
    listener: TcpListener,
    addr: SocketAddr,
}

pub struct StartedServer {
    addr: SocketAddr,
    done: Arc<AtomicBool>,
    thread: Option<JoinHandle<()>>,
}

impl RustfixDiagnosticServer {
    pub fn new() -> Result<Self, Error> {
        let listener = TcpListener::bind("127.0.0.1:0")
            .with_context(|_| "failed to bind TCP listener to manage locking")?;
        let addr = listener.local_addr()?;

        Ok(RustfixDiagnosticServer { listener, addr })
    }

    pub fn configure(&self, process: &mut ProcessBuilder) {
        process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string());
    }

    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>
    where
        F: Fn(Message) + Send + 'static,
    {
        let addr = self.addr;
        let done = Arc::new(AtomicBool::new(false));
        let done2 = done.clone();
        let thread = thread::spawn(move || {
            self.run(&on_message, &done2);
        });

        Ok(StartedServer {
            addr,
            thread: Some(thread),
            done,
        })
    }

    fn run(self, on_message: &dyn Fn(Message), done: &AtomicBool) {
        while let Ok((client, _)) = self.listener.accept() {
            if done.load(Ordering::SeqCst) {
                break;
            }
            let mut client = BufReader::new(client);
            let mut s = String::new();
            if let Err(e) = client.read_to_string(&mut s) {
                warn!("diagnostic server failed to read: {}", e);
            } else {
                match serde_json::from_str(&s) {
                    Ok(message) => on_message(message),
                    Err(e) => warn!("invalid diagnostics message: {}", e),
                }
            }
            // The client should be kept alive until after `on_message` is
            // called to ensure that the client doesn't exit too soon (and
            // Message::Finish getting posted before Message::FixDiagnostic).
            drop(client);
        }
    }
}

impl Drop for StartedServer {
    fn drop(&mut self) {
        self.done.store(true, Ordering::SeqCst);
        // Ignore errors here as this is largely best-effort
        if TcpStream::connect(&self.addr).is_err() {
            return;
        }
        drop(self.thread.take().unwrap().join());
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
use layout::flow::{FloatFlow, FlowData};
use layout::model::{MaybeAuto};
use layout::float_context::{FloatContext, PlacementInfo, FloatType};

use std::cell::Cell;
use geom::point::Point2D;
use geom::rect::Rect;
use gfx::display_list::DisplayList;
use gfx::geometry::Au;
use gfx::geometry;
use servo_util::tree::{TreeNodeRef, TreeUtils};

pub struct FloatFlowData {
    /// Data common to all flows.
    common: FlowData,

    /// The associated render box.
    box: Option<RenderBox>,

    containing_width: Au,

    /// Offset relative to where the parent tried to position this flow
    rel_pos: Point2D<Au>,

    /// Left or right?
    float_type: FloatType,

    /// Index into the box list for inline floats
    index: Option<uint>,

}

impl FloatFlowData {
    pub fn new(common: FlowData, float_type: FloatType) -> FloatFlowData {
        FloatFlowData {
            common: common,
            containing_width: Au(0),
            box: None,
            index: None,
            float_type: float_type,
            rel_pos: Point2D(Au(0), Au(0)),
        }
    }

    pub fn teardown(&mut self) {
        self.common.teardown();
        for self.box.iter().advance |box| {
            box.teardown();
        }
        self.box = None;
        self.index = None;
    }
}

impl FloatFlowData {
    pub fn bubble_widths_float(@mut self, ctx: &LayoutContext) {
        let mut min_width = Au(0);
        let mut pref_width = Au(0);

        self.common.num_floats = 1;

        for FloatFlow(self).each_child |child_ctx| {
            //assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());

            do child_ctx.with_mut_base |child_node| {
                min_width = geometry::max(min_width, child_node.min_width);
                pref_width = geometry::max(pref_width, child_node.pref_width);
                child_node.floats_in = FloatContext::new(child_node.num_floats);
            }
        }

        self.box.map(|&box| {
            let style = box.style();
            do box.with_model |model| {
                model.compute_borders(style)
            }

            min_width = min_width.add(&box.get_min_width(ctx));
            pref_width = pref_width.add(&box.get_pref_width(ctx));
        });

        self.common.min_width = min_width;
        self.common.pref_width = pref_width;
    }

    pub fn assign_widths_float(@mut self, _: &LayoutContext) {
        debug!("assign_widths_float: assigning width for flow %?",  self.common.id);
        // position.size.width is set by parent even though we don't know
        // position.origin yet.
        let mut remaining_width = self.common.position.size.width;
        self.containing_width = remaining_width;
        let mut x_offset = Au(0);

        for self.box.iter().advance |&box| {
            let style = box.style();
            do box.with_model |model| {
                // Can compute padding here since we know containing block width.
                model.compute_padding(style, remaining_width);

                // Margins for floats are 0 if auto.
                let margin_top = MaybeAuto::from_margin(style.margin_top(),
                                                        remaining_width,
                                                        style.font_size()).specified_or_zero();
                let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(),
                                                           remaining_width,
                                                           style.font_size()).specified_or_zero();
                let margin_left = MaybeAuto::from_margin(style.margin_left(),
                                                         remaining_width,
                                                         style.font_size()).specified_or_zero();
                let margin_right = MaybeAuto::from_margin(style.margin_right(),
                                                          remaining_width,
                                                          style.font_size()).specified_or_zero();

                let shrink_to_fit = geometry::min(self.common.pref_width,
                                                  geometry::max(self.common.min_width,
                                                                remaining_width));

                let width = MaybeAuto::from_width(style.width(),
                                                  remaining_width,
                                                  style.font_size()).specified_or_default(shrink_to_fit);
                debug!("assign_widths_float -- width: %?", width);

                model.margin.top = margin_top;
                model.margin.right = margin_right;
                model.margin.bottom = margin_bottom;
                model.margin.left = margin_left;

                x_offset = model.offset();
                remaining_width = width;
            }

            do box.with_mut_base |base| {
                //The associated box is the border box of this flow
                base.position.origin.x = base.model.margin.left;

                let pb = base.model.padding.left + base.model.padding.right +
                    base.model.border.left + base.model.border.right;
                base.position.size.width = remaining_width + pb;
            }
        }

        self.common.position.size.width = remaining_width;

        for FloatFlow(self).each_child |kid| {
            //assert!(kid.starts_block_flow() || kid.starts_inline_flow());

            do kid.with_mut_base |child_node| {
                child_node.position.origin.x = x_offset;
                child_node.position.size.width = remaining_width;
            }
        }
    }

    pub fn assign_height_float(@mut self, ctx: &mut LayoutContext) {
        for FloatFlow(self).each_child |kid| {
            kid.assign_height(ctx);
        }

        let mut cur_y = Au(0);
        let mut top_offset = Au(0);

        for self.box.iter().advance |&box| {
            do box.with_model |model| {
                top_offset = model.margin.top + model.border.top + model.padding.top;
                cur_y = cur_y + top_offset;
            }
        }

        for FloatFlow(self).each_child |kid| {
            do kid.with_mut_base |child_node| {
                child_node.position.origin.y = cur_y;
                cur_y = cur_y + child_node.position.size.height;
            };
        }

        let mut height = cur_y - top_offset;

        let mut noncontent_height = Au(0);
        self.box.map(|&box| {
            do box.with_mut_base |base| {
                //The associated box is the border box of this flow
                base.position.origin.y = base.model.margin.top;

                noncontent_height = base.model.padding.top + base.model.padding.bottom +
                    base.model.border.top + base.model.border.bottom;
                base.position.size.height = height + noncontent_height;

                noncontent_height = noncontent_height + base.model.margin.top + base.model.margin.bottom;
            }
        });

        //TODO(eatkinson): compute heights properly using the 'height' property.
        for self.box.iter().advance |&box| {
            let height_prop =
                MaybeAuto::from_height(box.style().height(),
                                       Au(0),
                                       box.style().font_size()).specified_or_zero();

            height = geometry::max(height, height_prop) + noncontent_height;
            debug!("assign_height_float -- height: %?", height);
            do box.with_mut_base |base| {
                base.position.size.height = height;
            }
        }

        let info = PlacementInfo {
            width: self.common.position.size.width,
            height: height,
            ceiling: Au(0),
            max_width: self.containing_width,
            f_type: self.float_type,
        };

        // Place the float and return the FloatContext back to the parent flow.
        // After, grab the position and use that to set our position.
        self.common.floats_out = self.common.floats_in.add_float(&info);
        self.rel_pos = self.common.floats_out.last_float_pos();
    }

    pub fn build_display_list_float<E:ExtraDisplayListData>(@mut self,
                                                            builder: &DisplayListBuilder,
                                                            dirty: &Rect<Au>,
                                                            list: &Cell<DisplayList<E>>)
                                                            -> bool {

        let abs_rect = Rect(self.common.abs_position, self.common.position.size);
        if !abs_rect.intersects(dirty) {
            return false;
        }

        let offset = self.common.abs_position + self.rel_pos;
        // add box that starts block context
        self.box.map(|&box| {
            box.build_display_list(builder, dirty, &offset, list)
        });

        // TODO: handle any out-of-flow elements

        // go deeper into the flow tree
        let flow = FloatFlow(self);
        for flow.each_child |child| {
            do child.with_mut_base |base| {
                base.abs_position = offset + base.position.origin;
            }
        }

        true
    }
}

<commit_msg>Fix calculation of float height and width.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
use layout::flow::{FloatFlow, FlowData};
use layout::model::{MaybeAuto};
use layout::float_context::{FloatContext, PlacementInfo, FloatType};

use std::cell::Cell;
use geom::point::Point2D;
use geom::rect::Rect;
use gfx::display_list::DisplayList;
use gfx::geometry::Au;
use gfx::geometry;
use servo_util::tree::{TreeNodeRef, TreeUtils};

pub struct FloatFlowData {
    /// Data common to all flows.
    common: FlowData,

    /// The associated render box.
    box: Option<RenderBox>,

    containing_width: Au,

    /// Offset relative to where the parent tried to position this flow
    rel_pos: Point2D<Au>,

    /// Left or right?
    float_type: FloatType,

    /// Index into the box list for inline floats
    index: Option<uint>,

}

impl FloatFlowData {
    pub fn new(common: FlowData, float_type: FloatType) -> FloatFlowData {
        FloatFlowData {
            common: common,
            containing_width: Au(0),
            box: None,
            index: None,
            float_type: float_type,
            rel_pos: Point2D(Au(0), Au(0)),
        }
    }

    pub fn teardown(&mut self) {
        self.common.teardown();
        for self.box.iter().advance |box| {
            box.teardown();
        }
        self.box = None;
        self.index = None;
    }
}

impl FloatFlowData {
    pub fn bubble_widths_float(@mut self, ctx: &LayoutContext) {
        let mut min_width = Au(0);
        let mut pref_width = Au(0);

        self.common.num_floats = 1;

        for FloatFlow(self).each_child |child_ctx| {
            //assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());

            do child_ctx.with_mut_base |child_node| {
                min_width = geometry::max(min_width, child_node.min_width);
                pref_width = geometry::max(pref_width, child_node.pref_width);
                child_node.floats_in = FloatContext::new(child_node.num_floats);
            }
        }

        self.box.map(|&box| {
            let style = box.style();
            do box.with_model |model| {
                model.compute_borders(style)
            }

            min_width = min_width.add(&box.get_min_width(ctx));
            pref_width = pref_width.add(&box.get_pref_width(ctx));
        });

        self.common.min_width = min_width;
        self.common.pref_width = pref_width;
    }

    pub fn assign_widths_float(@mut self, _: &LayoutContext) {
        debug!("assign_widths_float: assigning width for flow %?",  self.common.id);
        // position.size.width is set by parent even though we don't know
        // position.origin yet.
        let mut remaining_width = self.common.position.size.width;
        self.containing_width = remaining_width;
        let mut x_offset = Au(0);

        for self.box.iter().advance |&box| {
            let style = box.style();
            do box.with_model |model| {
                // Can compute padding here since we know containing block width.
                model.compute_padding(style, remaining_width);

                // Margins for floats are 0 if auto.
                let margin_top = MaybeAuto::from_margin(style.margin_top(),
                                                        remaining_width,
                                                        style.font_size()).specified_or_zero();
                let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(),
                                                           remaining_width,
                                                           style.font_size()).specified_or_zero();
                let margin_left = MaybeAuto::from_margin(style.margin_left(),
                                                         remaining_width,
                                                         style.font_size()).specified_or_zero();
                let margin_right = MaybeAuto::from_margin(style.margin_right(),
                                                          remaining_width,
                                                          style.font_size()).specified_or_zero();

                let shrink_to_fit = geometry::min(self.common.pref_width,
                                                  geometry::max(self.common.min_width,
                                                                remaining_width));

                let width = MaybeAuto::from_width(style.width(),
                                                  remaining_width,
                                                  style.font_size()).specified_or_default(shrink_to_fit);
                debug!("assign_widths_float -- width: %?", width);

                model.margin.top = margin_top;
                model.margin.right = margin_right;
                model.margin.bottom = margin_bottom;
                model.margin.left = margin_left;

                x_offset = model.offset();
                remaining_width = width;
            }

            do box.with_mut_base |base| {
                //The associated box is the border box of this flow
                base.position.origin.x = base.model.margin.left;

                let pb = base.model.padding.left + base.model.padding.right +
                    base.model.border.left + base.model.border.right;
                base.position.size.width = remaining_width + pb;
            }
        }

        self.common.position.size.width = remaining_width;

        for FloatFlow(self).each_child |kid| {
            //assert!(kid.starts_block_flow() || kid.starts_inline_flow());

            do kid.with_mut_base |child_node| {
                child_node.position.origin.x = x_offset;
                child_node.position.size.width = remaining_width;
            }
        }
    }

    pub fn assign_height_float(@mut self, ctx: &mut LayoutContext) {
        for FloatFlow(self).each_child |kid| {
            kid.assign_height(ctx);
        }

        let mut cur_y = Au(0);
        let mut top_offset = Au(0);

        for self.box.iter().advance |&box| {
            do box.with_model |model| {
                top_offset = model.margin.top + model.border.top + model.padding.top;
                cur_y = cur_y + top_offset;
            }
        }

        for FloatFlow(self).each_child |kid| {
            do kid.with_mut_base |child_node| {
                child_node.position.origin.y = cur_y;
                cur_y = cur_y + child_node.position.size.height;
            };
        }

        let mut height = cur_y - top_offset;

        let mut noncontent_width = Au(0);
        let mut noncontent_height = Au(0);
        let mut full_noncontent_width = Au(0);
        let mut full_noncontent_height = Au(0);
        self.box.map(|&box| {
            do box.with_mut_base |base| {
                //The associated box is the border box of this flow
                base.position.origin.y = base.model.margin.top;

                noncontent_width = base.model.padding.left + base.model.padding.right +
                    base.model.border.left + base.model.border.right;
                noncontent_height = base.model.padding.top + base.model.padding.bottom +
                    base.model.border.top + base.model.border.bottom;
                base.position.size.height = height + noncontent_height;

                full_noncontent_width = noncontent_width + base.model.margin.left + base.model.margin.right;
                full_noncontent_height = noncontent_height + base.model.margin.top + base.model.margin.bottom;
            }
        });

        //TODO(eatkinson): compute heights properly using the 'height' property.
        for self.box.iter().advance |&box| {
            let height_prop =
                MaybeAuto::from_height(box.style().height(),
                                       Au(0),
                                       box.style().font_size()).specified_or_zero();

            height = geometry::max(height, height_prop) + noncontent_height;
            debug!("assign_height_float -- height: %?", height);
            do box.with_mut_base |base| {
                base.position.size.height = height;
            }
        }

        let info = PlacementInfo {
            width: self.common.position.size.width + full_noncontent_width,
            height: height + full_noncontent_height,
            ceiling: Au(0),
            max_width: self.containing_width,
            f_type: self.float_type,
        };

        // Place the float and return the FloatContext back to the parent flow.
        // After, grab the position and use that to set our position.
        self.common.floats_out = self.common.floats_in.add_float(&info);
        self.rel_pos = self.common.floats_out.last_float_pos();
    }

    pub fn build_display_list_float<E:ExtraDisplayListData>(@mut self,
                                                            builder: &DisplayListBuilder,
                                                            dirty: &Rect<Au>,
                                                            list: &Cell<DisplayList<E>>)
                                                            -> bool {

        let abs_rect = Rect(self.common.abs_position, self.common.position.size);
        if !abs_rect.intersects(dirty) {
            return false;
        }

        let offset = self.common.abs_position + self.rel_pos;
        // add box that starts block context
        self.box.map(|&box| {
            box.build_display_list(builder, dirty, &offset, list)
        });

        // TODO: handle any out-of-flow elements

        // go deeper into the flow tree
        let flow = FloatFlow(self);
        for flow.each_child |child| {
            do child.with_mut_base |base| {
                base.abs_position = offset + base.position.origin;
            }
        }

        true
    }
}

<|endoftext|>


<commit_before>extern crate shiplift;

use shiplift::Docker;
use std::io::prelude::*;
use std::io::copy;
use std::fs::OpenOptions;

fn main() {
  let docker = Docker::new();
  let export = OpenOptions::new().write(true).create(true).open("export.tgz").unwrap();
  let images = docker.images();
  let mut exported = images.get("nginx").export().unwrap();
  println!("copying");
  copy(&mut exported, &mut export).unwrap();
  println!("copied");
}
<commit_msg>imporve export example<commit_after>extern crate shiplift;

use shiplift::Docker;
use std::env;
use std::io::prelude::*;
use std::io::copy;
use std::fs::OpenOptions;

fn main() {
    let docker = Docker::new();
    if let Some(id) = env::args().nth(1) {
        let mut export = OpenOptions::new()
            .write(true)
            .create(true)
            .open(format!("{}.tgz", &id))
            .unwrap();
        let images = docker.images();
        let mut exported = images.get(&id).export().unwrap();
        println!("copying");
        copy(&mut exported, &mut export).unwrap();
        println!("copied");
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate typedopts;
extern crate serialize;

use getopts::{reqopt,optopt,optflag,getopts,OptGroup};
use std::os;
use typedopts::{DecoderResult,UnimplementedDecoder,MissingField,ExpectedType};

#[deriving(Decodable)]
enum Color {
  red,
  blue
}

#[deriving(Decodable)]
struct TestStruct1  {
  data_int: u8,
  data_str: ~str,
  color: Color,
  maybe: Option<int>
}

fn print_usage(program: &str, _opts: &[OptGroup]) {
    println!("Usage: {} [options]", program);
    println!("-o\t\tOutput");
    println!("-d --data_int\tNumber");
    println!("-h --help\tUsage");
}

fn main() {
  let args = os::args();

  let program = args[0].clone();

  let opts = ~[
    optopt("o", "", "set output file name", "NAME"),
    reqopt("d", "data_int", "number", "NB"),
    reqopt("s", "data_str", "str", "NB"),
    reqopt("c", "color", "scolored", ""),
    optopt("m", "maybe", "maybe int", ""),
    optflag("h", "help", "print this help menu")
  ];
  let matches = match getopts(args.tail(), opts) {
    Ok(m) => { m }
    Err(f) => { fail!(f.to_err_msg()) }
  };

  if matches.opt_present("h") {
    print_usage(program, opts);
    return;
  }

  let result: typedopts::DecoderResult<TestStruct1> = typedopts::decode(matches);

  match result {
    Ok(decoded) => {
      println!("got data: s -> {} n -> {}", decoded.data_str, decoded.data_int);
      match decoded.color {
        red  => println!("red"),
        blue => println!("blue")
      }

      match decoded.maybe {
        None    => println!("maybe is none"),
        Some(i) => println!("maybe is {}", i)
      }
    },
    Err(UnimplementedDecoder) => println!("this function is not implemented"),
    Err(MissingField(ref s))  => println!("the required field '{}' is not present", s),
    Err(ExpectedType(ref field, ref expected, ref value)) => {
      println!("Expected type '{}' for field '{}' but got value '{}'", expected, field, value)
    }
  }
}
<commit_msg>trigger the travis rebuild<commit_after>extern crate getopts;
extern crate typedopts;
extern crate serialize;

use std::os;
use getopts::{reqopt,optopt,optflag,getopts,OptGroup};
use typedopts::{DecoderResult,UnimplementedDecoder,MissingField,ExpectedType};

#[deriving(Decodable)]
enum Color {
  red,
  blue
}

#[deriving(Decodable)]
struct TestStruct1  {
  data_int: u8,
  data_str: ~str,
  color: Color,
  maybe: Option<int>
}

fn print_usage(program: &str, _opts: &[OptGroup]) {
    println!("Usage: {} [options]", program);
    println!("-o\t\tOutput");
    println!("-d --data_int\tNumber");
    println!("-h --help\tUsage");
}

fn main() {
  let args = os::args();

  let program = args[0].clone();

  let opts = ~[
    optopt("o", "", "set output file name", "NAME"),
    reqopt("d", "data_int", "number", "NB"),
    reqopt("s", "data_str", "str", "NB"),
    reqopt("c", "color", "scolored", ""),
    optopt("m", "maybe", "maybe int", ""),
    optflag("h", "help", "print this help menu")
  ];
  let matches = match getopts(args.tail(), opts) {
    Ok(m) => { m }
    Err(f) => { fail!(f.to_err_msg()) }
  };

  if matches.opt_present("h") {
    print_usage(program, opts);
    return;
  }

  let result: typedopts::DecoderResult<TestStruct1> = typedopts::decode(matches);

  match result {
    Ok(decoded) => {
      println!("got data: s -> {} n -> {}", decoded.data_str, decoded.data_int);
      match decoded.color {
        red  => println!("red"),
        blue => println!("blue")
      }

      match decoded.maybe {
        None    => println!("maybe is none"),
        Some(i) => println!("maybe is {}", i)
      }
    },
    Err(UnimplementedDecoder) => println!("this function is not implemented"),
    Err(MissingField(ref s))  => println!("the required field '{}' is not present", s),
    Err(ExpectedType(ref field, ref expected, ref value)) => {
      println!("Expected type '{}' for field '{}' but got value '{}'", expected, field, value)
    }
  }
}
<|endoftext|>


<commit_before>extern crate tetrahedrane;

use tetrahedrane::vid::*;
use tetrahedrane::start;
use tetrahedrane::shaders;

fn main() {
    let mut window = start::Window::new(640, 480, "Hello World!", 1 as usize);

    let mut shaders: Vec<Shader> = Vec::new();

    let triangle = Triangle::new(DepthPoint::new(0.0, -0.5, 3.0),
                                 DepthPoint::new(0.5, 0.5, 3.0),
                                 DepthPoint::new(-0.5, 0.5, 3.0),
                                 0.0, 0.0, 0.0,
                                 Color::new(200, 200, 200));

    let mut triangle_group = TriangleGroup::square(0.0, 0.0, 3.0, 1.0, 1.0);

    //let mut triangle_group = TriangleGroup::new(vec![triangle]);

    shaders.push(shaders::filled_texture(1, &"bmp/crate.bmp", 0.0, 0.0, 0.0, 1.0, 1.0, 1.0));
    shaders.push(shaders::filled_texture(2, &"bmp/crate.bmp", 0.0, 0.0, 1.0, 0.0, 1.0, 1.0));
    //shaders.push(shaders::filled_triangle_color(1));
    //shaders.push(shaders::wireframe(1));

    //triangle_group.triangles[0].shader_ids[0] = 1;

    loop {
        window.window.set(Color::new(20, 40, 60).orb_color());
        window.window.set(Color::new(20, 40, 60).orb_color());

        //triangle.coord_rotate_x_y(0.0, 0.0, 0.01);
        //triangle.coord_rotate_x_z(0.0, 3.0, 0.02);
        //triangle.coord_rotate_y_z(0.0, 3.0, 0.03);

        window.render_addon_shader(triangle_group.triangles[0], &shaders, [1, 0, 0, 0, 0, 0, 0, 0]);
        window.render_addon_shader(triangle_group.triangles[1], &shaders, [2, 0, 0, 0, 0, 0, 0, 0]);

        window.window.sync();

        //std::thread::sleep(std::time::Duration::from_millis(33));
    }
}<commit_msg>Added square rotation<commit_after>extern crate tetrahedrane;

use tetrahedrane::vid::*;
use tetrahedrane::start;
use tetrahedrane::shaders;
use tetrahedrane::texture;

fn main() {
    let mut window = start::Window::new(640, 480, "Hello World!", 1 as usize);

    let mut shaders: Vec<Shader> = Vec::new();

    let triangle = Triangle::new(DepthPoint::new(0.0, -0.5, 3.0),
                                 DepthPoint::new(0.5, 0.5, 3.0),
                                 DepthPoint::new(-0.5, 0.5, 3.0),
                                 0.0, 0.0, 0.0,
                                 Color::new(200, 200, 200));

    let mut triangle_group = TriangleGroup::square(-0.5, -0.5, 3.0, 1.0, 1.0);

    //let mut triangle_group = TriangleGroup::new(vec![triangle]);

    let texture = texture::UVTexture::path(&"bmp/crate.bmp");
    shaders.push(shaders::filled_texture(1, texture, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0));

    let texture = texture::UVTexture::path(&"bmp/crate.bmp");
    shaders.push(shaders::filled_texture(2, texture, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0));
    //shaders.push(shaders::filled_triangle_color(1));
    //shaders.push(shaders::wireframe(1));

    //triangle_group.triangles[0].shader_ids[0] = 1;

    loop {
        window.window.set(Color::new(20, 40, 60).orb_color());
        window.window.set(Color::new(20, 40, 60).orb_color());

        for triangle in &mut triangle_group.triangles {
            triangle.coord_rotate_x_y(0.5, 0.5, 0.01);
            triangle.coord_rotate_x_z(0.5, 0.0, 0.02);
            triangle.coord_rotate_y_z(0.5, 0.0, 0.03);
        }

        window.render_addon_shader(triangle_group.triangles[0], &shaders, [1, 0, 0, 0, 0, 0, 0, 0]);
        window.render_addon_shader(triangle_group.triangles[1], &shaders, [2, 0, 0, 0, 0, 0, 0, 0]);

        window.window.sync();

        //std::thread::sleep(std::time::Duration::from_millis(33));
    }
}<|endoftext|>


<commit_before>#![feature(phase)]
#[phase(plugin, link)]
extern crate stainless;

describe! top_level {
    before_each {
        let mut foo = 1u;
    }

    after_each {
        assert_eq!(foo, 20)
    }

    describe! nested {
        before_each {
            assert_eq!(foo, 1);
            foo += 1;
        }

        it "should be more specific" {
            assert_eq!(foo, 2);
            foo += 1;
        }

        after_each {
            assert_eq!(foo, 3);
            foo += 1;
        }
    }
}
<commit_msg>End `assert_eq!` call with a semicolon. Everything works now. See #10.<commit_after>#![feature(phase)]
#[phase(plugin, link)]
extern crate stainless;

describe! top_level {
    before_each {
        let mut foo = 1u;
    }

    after_each {
        assert_eq!(foo, 4);
    }

    describe! nested {
        before_each {
            assert_eq!(foo, 1);
            foo += 1;
        }

        it "should be more specific" {
            assert_eq!(foo, 2);
            foo += 1;
        }

        after_each {
            assert_eq!(foo, 3);
            foo += 1;
        }
    }
}
<|endoftext|>


<commit_before>use cocoa::base::id;
use cocoa::foundation::NSUInteger;
use objc::runtime::BOOL;
use MTLTextureType;

/// A `MTLArgument` object describes a single argument to a Metal function. Your
/// app uses the `MTLArgument` properties to read details about a function
/// argument as it was defined in the Metal Shading Language. You can determine
/// the argument’s data type, access restrictions, and its associated resource
/// type. For buffer, texture, and threadgroup memory arguments, additional
/// properties can be read to determine more details about the argument.
///
/// Your app does not create a `MTLArgument` object directly. Creating a
/// MTLRenderPipelineState or `MTLComputePipelineState` object can generate a
/// reflection object (`MTLRenderPipelineReflection` or
/// `MTLComputePipelineReflection`) that contains `MTLArgument` objects.
pub trait MTLArgument {
    /// The name of the function argument. (read-only)
    unsafe fn name(self) -> id;

    /// The function’s read and/or write access to the argument. (read-only)
    unsafe fn access(self) -> MTLArgumentAccess;

    /// If `YES`, this argument is used in a Metal shading language function and
    /// has been set to an index in an argument table. If `NO`, this argument is
    /// not used in a Metal shading language function and can be ignored.
    /// (read-only)
    unsafe fn active(self) -> BOOL;

    /// The index in the argument table that corresponds to the function argument. (read-only)
    ///
    /// #Discussion
    ///
    /// A command encoder (`MTLComputeCommandEncoder` or `MTLRenderCommandEncoder`) specifies the
    /// index in the corresponding argument table. For example, an app can call the
    /// `setTexture:atIndex:` method of `MTLComputeCommandEncoder` to specify an index in the
    /// texture argument table for a `MTLTexture` object that is used as an argument of a
    /// compute function.
    unsafe fn index(self) -> NSUInteger;

    /// The argument’s resource type. (read-only)
    ///
    /// #Discussion
    ///
    /// This property indicates which type of resource is used (buffer, texture, sampler, or
    /// threadgroup memory) in the shading language code. For information on possible values,
    /// see `MTLArgumentType`.
    unsafe fn getType(self) -> MTLArgumentType;

    /// The required byte alignment in memory for the buffer data in the function argument.
    /// (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a buffer, querying this property is a fatal error.
    unsafe fn bufferAlignment(self) -> NSUInteger;

    /// The size, in bytes, of the buffer data in the function argument. (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a buffer, querying this property is a fatal error.
    unsafe fn bufferDataSize(self) -> NSUInteger;

    /// The data type of the buffer data in the function argument. (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a buffer, querying this property is a fatal error.
    unsafe fn bufferDataType(self) -> MTLDataType;

    /// Returns a description of the structure data contained in the buffer argument.
    /// (read-only)
    ///
    /// #Discussion
    ///
    /// For information on possible returned values, see `MTLStructType`. If the
    /// argument is not a buffer, querying this property is a fatal error. If
    /// the argument is a buffer but the buffer’s data type is not a struct,
    /// the value of this property is nil.
    unsafe fn bufferStructType(self) -> id;

    /// The data type of a texture argument. (read-only)
    ///
    /// #Discussion
    ///
    /// For information on possible values, see `MTLDataType`. If the argument
    /// is not a texture, querying this property is a fatal error.
    unsafe fn textureDataType(self) -> MTLDataType;

    /// The texture type of a texture argument. (read-only)
    ///
    /// #Discussion
    ///
    /// For information on possible values, see `MTLTextureType`. If the
    /// argument is not a texture, querying this property is a fatal error.
    unsafe fn textureType(self) -> MTLTextureType;

    /// The required byte alignment in memory for the threadgroup data in
    /// the argument of a compute function. (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a threadgroup, querying this property is a
    /// fatal error. The Metal implementation determines this value.
    unsafe fn threadgroupMemoryAlignment(self) -> NSUInteger;

    /// The size, in bytes, of the threadgroup data in the argument of a
    /// compute function. (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a threadgroup, querying this property is
    /// a fatal error. The Metal implementation determines this value.
    unsafe fn threadgroupMemoryDataSize(self) -> NSUInteger;
}

impl MTLArgument for id {
    unsafe fn name(self) -> id {
        msg_send![self, name]
    }

    unsafe fn access(self) -> MTLArgumentAccess {
        msg_send![self, access]
    }

    unsafe fn active(self) -> BOOL {
        msg_send![self, access]
    }

    unsafe fn index(self) -> NSUInteger {
        msg_send![self, index]
    }

    unsafe fn getType(self) -> MTLArgumentType {
        msg_send![self, getType]
    }

    unsafe fn bufferAlignment(self) -> NSUInteger {
        msg_send![self, bufferAlignment]
    }
    unsafe fn bufferDataSize(self) -> NSUInteger {
        msg_send![self, bufferDataSize]
    }
    unsafe fn bufferDataType(self) -> MTLDataType {
        msg_send![self, bufferDataType]
    }
    unsafe fn bufferStructType(self) -> id {
        msg_send![self, bufferStructType]
    }

    unsafe fn textureDataType(self) -> MTLDataType {
        msg_send![self, textureDataType]
    }
    unsafe fn textureType(self) -> MTLTextureType {
        msg_send![self, textureType]
    }

    unsafe fn threadgroupMemoryAlignment(self) -> NSUInteger {
        msg_send![self, threadgroupMemoryAlignment]
    }
    unsafe fn threadgroupMemoryDataSize(self) -> NSUInteger {
        msg_send![self, threadGroupMemoryDataSize]
    }
}

/// Function access restrictions to argument data in the shading language code.
#[repr(usize)]
pub enum MTLArgumentAccess {
    MTLArgumentAccessReadOnly = 0,
    MTLArgumentAccessReadWrite = 1,
    MTLArgumentAccessWriteOnly = 2
}

/// The resource type associated with an argument of a function.
#[repr(usize)]
pub enum MTLArgumentType {
    MTLArgumentTypeBuffer = 0,
    MTLArgumentTypeThreadgroupMemory = 1,
    MTLArgumentTypeTexture = 2,
    MTLArgumentTypeSampler = 3
}

/// The data type of a function argument, as it is declared in the shading
/// language code.
#[repr(usize)]
pub enum MTLDataType {
    MTLDataTypeNone = 0,
    MTLDataTypeStruct = 1,
    MTLDataTypeArray = 2,

    MTLDataTypeFloat = 3,
    MTLDataTypeFloat2 = 4,
    MTLDataTypeFloat3 = 5,
    MTLDataTypeFloat4 = 6,

    MTLDataTypeFloat2x2 = 7,
    MTLDataTypeFloat2x3 = 8,
    MTLDataTypeFloat2x4 = 9,

    MTLDataTypeFloat3x2 = 10,
    MTLDataTypeFloat3x3 = 11,
    MTLDataTypeFloat3x4 = 12,
    MTLDataTypeFloat4x2 = 13,
    MTLDataTypeFloat4x3 = 14,
    MTLDataTypeFloat4x4 = 15,

    MTLDataTypeHalf = 16,
    MTLDataTypeHalf2 = 17,
    MTLDataTypeHalf3 = 18,
    MTLDataTypeHalf4 = 19,

    MTLDataTypeHalf2x2 = 20,
    MTLDataTypeHalf2x3 = 21,
    MTLDataTypeHalf2x4 = 22,

    MTLDataTypeHalf3x2 = 23,
    MTLDataTypeHalf3x3 = 24,
    MTLDataTypeHalf3x4 = 25,

    MTLDataTypeHalf4x2 = 26,
    MTLDataTypeHalf4x3 = 27,
    MTLDataTypeHalf4x4 = 28,

    MTLDataTypeInt = 29,
    MTLDataTypeInt2 = 30,
    MTLDataTypeInt3 = 31,
    MTLDataTypeInt4 = 32,
    MTLDataTypeUInt = 33,
    MTLDataTypeUInt2 = 34,
    MTLDataTypeUInt3 = 35,
    MTLDataTypeUInt4 = 36,

    MTLDataTypeShort = 37,
    MTLDataTypeShort2 = 38,
    MTLDataTypeShort3 = 39,
    MTLDataTypeShort4 = 40,

    MTLDataTypeUShort = 41,
    MTLDataTypeUShort2 = 42,
    MTLDataTypeUShort3 = 43,
    MTLDataTypeUShort4 = 44,

    MTLDataTypeChar = 45,
    MTLDataTypeChar2 = 46,
    MTLDataTypeChar3 = 47,
    MTLDataTypeChar4 = 48,

    MTLDataTypeUChar = 49,
    MTLDataTypeUChar2 = 50,
    MTLDataTypeUChar3 = 51,
    MTLDataTypeUChar4 = 52,

    MTLDataTypeBool = 53,
    MTLDataTypeBool2 = 54,
    MTLDataTypeBool3 = 55,
    MTLDataTypeBool4 = 56
}
<commit_msg>Remove unused import<commit_after>use cocoa::base::id;
use cocoa::foundation::NSUInteger;
use MTLTextureType;

/// A `MTLArgument` object describes a single argument to a Metal function. Your
/// app uses the `MTLArgument` properties to read details about a function
/// argument as it was defined in the Metal Shading Language. You can determine
/// the argument’s data type, access restrictions, and its associated resource
/// type. For buffer, texture, and threadgroup memory arguments, additional
/// properties can be read to determine more details about the argument.
///
/// Your app does not create a `MTLArgument` object directly. Creating a
/// MTLRenderPipelineState or `MTLComputePipelineState` object can generate a
/// reflection object (`MTLRenderPipelineReflection` or
/// `MTLComputePipelineReflection`) that contains `MTLArgument` objects.
pub trait MTLArgument {
    /// The name of the function argument. (read-only)
    unsafe fn name(self) -> id;

    /// The function’s read and/or write access to the argument. (read-only)
    unsafe fn access(self) -> MTLArgumentAccess;

    /// If `YES`, this argument is used in a Metal shading language function and
    /// has been set to an index in an argument table. If `NO`, this argument is
    /// not used in a Metal shading language function and can be ignored.
    /// (read-only)
    unsafe fn active(self) -> BOOL;

    /// The index in the argument table that corresponds to the function argument. (read-only)
    ///
    /// #Discussion
    ///
    /// A command encoder (`MTLComputeCommandEncoder` or `MTLRenderCommandEncoder`) specifies the
    /// index in the corresponding argument table. For example, an app can call the
    /// `setTexture:atIndex:` method of `MTLComputeCommandEncoder` to specify an index in the
    /// texture argument table for a `MTLTexture` object that is used as an argument of a
    /// compute function.
    unsafe fn index(self) -> NSUInteger;

    /// The argument’s resource type. (read-only)
    ///
    /// #Discussion
    ///
    /// This property indicates which type of resource is used (buffer, texture, sampler, or
    /// threadgroup memory) in the shading language code. For information on possible values,
    /// see `MTLArgumentType`.
    unsafe fn getType(self) -> MTLArgumentType;

    /// The required byte alignment in memory for the buffer data in the function argument.
    /// (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a buffer, querying this property is a fatal error.
    unsafe fn bufferAlignment(self) -> NSUInteger;

    /// The size, in bytes, of the buffer data in the function argument. (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a buffer, querying this property is a fatal error.
    unsafe fn bufferDataSize(self) -> NSUInteger;

    /// The data type of the buffer data in the function argument. (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a buffer, querying this property is a fatal error.
    unsafe fn bufferDataType(self) -> MTLDataType;

    /// Returns a description of the structure data contained in the buffer argument.
    /// (read-only)
    ///
    /// #Discussion
    ///
    /// For information on possible returned values, see `MTLStructType`. If the
    /// argument is not a buffer, querying this property is a fatal error. If
    /// the argument is a buffer but the buffer’s data type is not a struct,
    /// the value of this property is nil.
    unsafe fn bufferStructType(self) -> id;

    /// The data type of a texture argument. (read-only)
    ///
    /// #Discussion
    ///
    /// For information on possible values, see `MTLDataType`. If the argument
    /// is not a texture, querying this property is a fatal error.
    unsafe fn textureDataType(self) -> MTLDataType;

    /// The texture type of a texture argument. (read-only)
    ///
    /// #Discussion
    ///
    /// For information on possible values, see `MTLTextureType`. If the
    /// argument is not a texture, querying this property is a fatal error.
    unsafe fn textureType(self) -> MTLTextureType;

    /// The required byte alignment in memory for the threadgroup data in
    /// the argument of a compute function. (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a threadgroup, querying this property is a
    /// fatal error. The Metal implementation determines this value.
    unsafe fn threadgroupMemoryAlignment(self) -> NSUInteger;

    /// The size, in bytes, of the threadgroup data in the argument of a
    /// compute function. (read-only)
    ///
    /// #Discussion
    ///
    /// If the argument is not a threadgroup, querying this property is
    /// a fatal error. The Metal implementation determines this value.
    unsafe fn threadgroupMemoryDataSize(self) -> NSUInteger;
}

impl MTLArgument for id {
    unsafe fn name(self) -> id {
        msg_send![self, name]
    }

    unsafe fn access(self) -> MTLArgumentAccess {
        msg_send![self, access]
    }

    unsafe fn active(self) -> BOOL {
        msg_send![self, access]
    }

    unsafe fn index(self) -> NSUInteger {
        msg_send![self, index]
    }

    unsafe fn getType(self) -> MTLArgumentType {
        msg_send![self, getType]
    }

    unsafe fn bufferAlignment(self) -> NSUInteger {
        msg_send![self, bufferAlignment]
    }
    unsafe fn bufferDataSize(self) -> NSUInteger {
        msg_send![self, bufferDataSize]
    }
    unsafe fn bufferDataType(self) -> MTLDataType {
        msg_send![self, bufferDataType]
    }
    unsafe fn bufferStructType(self) -> id {
        msg_send![self, bufferStructType]
    }

    unsafe fn textureDataType(self) -> MTLDataType {
        msg_send![self, textureDataType]
    }
    unsafe fn textureType(self) -> MTLTextureType {
        msg_send![self, textureType]
    }

    unsafe fn threadgroupMemoryAlignment(self) -> NSUInteger {
        msg_send![self, threadgroupMemoryAlignment]
    }
    unsafe fn threadgroupMemoryDataSize(self) -> NSUInteger {
        msg_send![self, threadGroupMemoryDataSize]
    }
}

/// Function access restrictions to argument data in the shading language code.
#[repr(usize)]
pub enum MTLArgumentAccess {
    MTLArgumentAccessReadOnly = 0,
    MTLArgumentAccessReadWrite = 1,
    MTLArgumentAccessWriteOnly = 2
}

/// The resource type associated with an argument of a function.
#[repr(usize)]
pub enum MTLArgumentType {
    MTLArgumentTypeBuffer = 0,
    MTLArgumentTypeThreadgroupMemory = 1,
    MTLArgumentTypeTexture = 2,
    MTLArgumentTypeSampler = 3
}

/// The data type of a function argument, as it is declared in the shading
/// language code.
#[repr(usize)]
pub enum MTLDataType {
    MTLDataTypeNone = 0,
    MTLDataTypeStruct = 1,
    MTLDataTypeArray = 2,

    MTLDataTypeFloat = 3,
    MTLDataTypeFloat2 = 4,
    MTLDataTypeFloat3 = 5,
    MTLDataTypeFloat4 = 6,

    MTLDataTypeFloat2x2 = 7,
    MTLDataTypeFloat2x3 = 8,
    MTLDataTypeFloat2x4 = 9,

    MTLDataTypeFloat3x2 = 10,
    MTLDataTypeFloat3x3 = 11,
    MTLDataTypeFloat3x4 = 12,
    MTLDataTypeFloat4x2 = 13,
    MTLDataTypeFloat4x3 = 14,
    MTLDataTypeFloat4x4 = 15,

    MTLDataTypeHalf = 16,
    MTLDataTypeHalf2 = 17,
    MTLDataTypeHalf3 = 18,
    MTLDataTypeHalf4 = 19,

    MTLDataTypeHalf2x2 = 20,
    MTLDataTypeHalf2x3 = 21,
    MTLDataTypeHalf2x4 = 22,

    MTLDataTypeHalf3x2 = 23,
    MTLDataTypeHalf3x3 = 24,
    MTLDataTypeHalf3x4 = 25,

    MTLDataTypeHalf4x2 = 26,
    MTLDataTypeHalf4x3 = 27,
    MTLDataTypeHalf4x4 = 28,

    MTLDataTypeInt = 29,
    MTLDataTypeInt2 = 30,
    MTLDataTypeInt3 = 31,
    MTLDataTypeInt4 = 32,
    MTLDataTypeUInt = 33,
    MTLDataTypeUInt2 = 34,
    MTLDataTypeUInt3 = 35,
    MTLDataTypeUInt4 = 36,

    MTLDataTypeShort = 37,
    MTLDataTypeShort2 = 38,
    MTLDataTypeShort3 = 39,
    MTLDataTypeShort4 = 40,

    MTLDataTypeUShort = 41,
    MTLDataTypeUShort2 = 42,
    MTLDataTypeUShort3 = 43,
    MTLDataTypeUShort4 = 44,

    MTLDataTypeChar = 45,
    MTLDataTypeChar2 = 46,
    MTLDataTypeChar3 = 47,
    MTLDataTypeChar4 = 48,

    MTLDataTypeUChar = 49,
    MTLDataTypeUChar2 = 50,
    MTLDataTypeUChar3 = 51,
    MTLDataTypeUChar4 = 52,

    MTLDataTypeBool = 53,
    MTLDataTypeBool2 = 54,
    MTLDataTypeBool3 = 55,
    MTLDataTypeBool4 = 56
}
<|endoftext|>