<commit_before>export writeinstr;
export writer;
export writer_util;
export make_writer;
export future_writer;

enum writeinstr {
    write(str),
    done
}

type writer = fn~(+writeinstr);

impl writer_util for writer {
    fn write_str(str: str) {
        self(write(str));
    }

    fn write_line(str: str) {
        self.write_str(str + "\n");
    }

    fn write_done() {
        self(done)
    }
}

fn make_writer(config: config::config) -> writer {
    markdown_writer(config)
}

fn markdown_writer(config: config::config) -> writer {
    let filename = make_filename(config);
    let ch = task::spawn_listener {|po: comm::port<writeinstr>|
        let markdown = "";
        let keep_going = true;
        while keep_going {
            alt comm::recv(po) {
              write(s) { markdown += s; }
              done { keep_going = false; }
            }
        }
        write_file(filename, markdown);
    };

    fn~(+instr: writeinstr) {
        comm::send(ch, instr);
    }
}

fn make_filename(config: config::config) -> str {
    import std::fs;
    let cratefile = fs::basename(config.input_crate);
    let cratename = tuple::first(fs::splitext(cratefile));
    fs::connect(config.output_dir, cratename + ".md")
}

fn write_file(path: str, s: str) {
    import std::io;
    import std::io::writer_util;

    alt io::file_writer(path, [io::create, io::truncate]) {
      result::ok(writer) {
        writer.write_str(s);
      }
      result::err(e) { fail e }
    }
}

#[test]
fn should_use_markdown_file_name_based_off_crate() {
    let config = {
        output_dir: "output/dir"
        with config::default_config("input/test.rc")
    };
    assert make_filename(config) == "output/dir/test.md";
}

fn future_writer() -> (writer, future::future<str>) {
    let port = comm::port();
    let chan = comm::chan(port);
    let writer = fn~(+instr: writeinstr) {
        comm::send(chan, copy instr);
    };
    let future = future::from_fn {||
        let res = "";
        while true {
            alt comm::recv(port) {
              write(s) { res += s }
              done { break }
            }
        }
        res
    };
    (writer, future)
}
<commit_msg>rustdoc: Teach rustdoc to run pandoc<commit_after>export writeinstr;
export writer;
export writer_util;
export make_writer;
export future_writer;

enum writeinstr {
    write(str),
    done
}

type writer = fn~(+writeinstr);

impl writer_util for writer {
    fn write_str(str: str) {
        self(write(str));
    }

    fn write_line(str: str) {
        self.write_str(str + "\n");
    }

    fn write_done() {
        self(done)
    }
}

fn make_writer(config: config::config) -> writer {
    alt config.output_format {
      config::markdown {
        markdown_writer(config)
      }
      config::pandoc_html {
        pandoc_writer(config)
      }
    }
}

fn markdown_writer(config: config::config) -> writer {
    let filename = make_filename(config, "md");
    generic_writer {|markdown|
        write_file(filename, markdown);
    }
}

fn pandoc_writer(config: config::config) -> writer {
    assert option::is_some(config.pandoc_cmd);
    let pandoc_cmd = option::get(config.pandoc_cmd);
    let filename = make_filename(config, "html");

    let pandoc_args = [
        "--standalone",
        "--toc",
        "--section-divs",
        "--from=markdown",
        "--to=html",
        "--css=rust.css",
        "--output=" + filename
    ];

    generic_writer {|markdown|
        import std::run;
        import std::os;
        import std::io;
        import std::io::writer_util;

        #debug("pandoc cmd: %s", pandoc_cmd);
        #debug("pandoc args: %s", str::connect(pandoc_args, " "));

        let pipe_in = os::pipe();
        let pipe_out = os::pipe();
        let pipe_err = os::pipe();
        let pid = run::spawn_process(
            pandoc_cmd, pandoc_args, none, none,
            pipe_in.in, pipe_out.out, pipe_err.out);

        if pid != -1 as ctypes::pid_t {
            let writer = io::fd_writer(pipe_in.out, false);
            writer.write_str(markdown);
        }

        os::close(pipe_in.in);
        os::close(pipe_out.out);
        os::close(pipe_err.out);
        os::close(pipe_in.out);
        os::close(pipe_out.in);
        os::close(pipe_err.in);

        if pid == -1 as ctypes::pid_t {
            fail "failed to run pandoc";
        }

        let status = run::waitpid(pid);
        #debug("pandoc result: %i", status);
        if status != 0 {
            fail "pandoc failed";
        }
    }
}

fn generic_writer(process: fn~(markdown: str)) -> writer {
    let ch = task::spawn_listener {|po: comm::port<writeinstr>|
        let markdown = "";
        let keep_going = true;
        while keep_going {
            alt comm::recv(po) {
              write(s) { markdown += s; }
              done { keep_going = false; }
            }
        }
        process(markdown);
    };

    fn~(+instr: writeinstr) {
        comm::send(ch, instr);
    }
}

fn make_filename(config: config::config, ext: str) -> str {
    import std::fs;
    let cratefile = fs::basename(config.input_crate);
    let cratename = tuple::first(fs::splitext(cratefile));
    fs::connect(config.output_dir, cratename + "." + ext)
}

fn write_file(path: str, s: str) {
    import std::io;
    import std::io::writer_util;

    alt io::file_writer(path, [io::create, io::truncate]) {
      result::ok(writer) {
        writer.write_str(s);
      }
      result::err(e) { fail e }
    }
}

#[test]
fn should_use_markdown_file_name_based_off_crate() {
    let config = {
        output_dir: "output/dir"
        with config::default_config("input/test.rc")
    };
    assert make_filename(config, "md") == "output/dir/test.md";
}

fn future_writer() -> (writer, future::future<str>) {
    let port = comm::port();
    let chan = comm::chan(port);
    let writer = fn~(+instr: writeinstr) {
        comm::send(chan, copy instr);
    };
    let future = future::from_fn {||
        let res = "";
        while true {
            alt comm::recv(port) {
              write(s) { res += s }
              done { break }
            }
        }
        res
    };
    (writer, future)
}
<|endoftext|>


<commit_before>use screen::*;
use piston_window;

pub struct MainMenuScreen;

impl Screen for MainMenuScreen {
    fn on_input(&mut self, input: &piston_window::Input) -> InputResults {
        // TODO: FIXME:
        use piston_window::{Input, Button, Key};

        let mut result = Vec::new();

        match input {
            &Input::Press(_) => {
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new())));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0., 0., 1., 1.0], graphics);
        });
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
    }
}
<commit_msg>Menu screen: mouse button<commit_after>use screen::*;
use piston_window;

pub struct MainMenuScreen;

impl Screen for MainMenuScreen {
    fn on_input(&mut self, input: &piston_window::Input) -> InputResults {
        // TODO: FIXME:
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new())));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0., 0., 1., 1.0], graphics);
        });
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
    }
}
<|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 fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
use fontconfig::fontconfig::{FcConfigGetCurrent, FcConfigGetFonts, FcConfigSubstitute};
use fontconfig::fontconfig::{FcDefaultSubstitute, FcFontMatch, FcNameParse, FcPatternGetString};
use fontconfig::fontconfig::{FcFontSetDestroy, FcMatchPattern, FcPatternCreate, FcPatternDestroy};
use fontconfig::fontconfig::{FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy, FcPatternAddString};
use fontconfig::fontconfig::{FcObjectSetAdd, FcPatternGetInteger};
use libc;
use libc::{c_char, c_int};
use std::borrow::ToOwned;
use std::ffi::CString;
use std::ptr;
use super::c_str_to_string;

static FC_FAMILY: &'static [u8] = b"family\0";
static FC_FILE: &'static [u8] = b"file\0";
static FC_INDEX: &'static [u8] = b"index\0";
static FC_FONTFORMAT: &'static [u8] = b"fontformat\0";

pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
    unsafe {
        let config = FcConfigGetCurrent();
        let font_set = FcConfigGetFonts(config, FcSetSystem);
        for i in 0..((*font_set).nfont as isize) {
            let font = (*font_set).fonts.offset(i);
            let mut family: *mut FcChar8 = ptr::null_mut();
            let mut format: *mut FcChar8 = ptr::null_mut();
            let mut v: c_int = 0;
            if FcPatternGetString(*font, FC_FONTFORMAT.as_ptr() as *mut c_char, v, &mut format) != FcResultMatch {
                continue;
            }

            // Skip bitmap fonts. They aren't supported by FreeType.
            let fontformat = c_str_to_string(format as *const c_char);
            if fontformat != "TrueType" &&
               fontformat != "CFF" &&
               fontformat != "Type 1" {
                continue;
            }

            while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut c_char, v, &mut family) == FcResultMatch {
                let family_name = c_str_to_string(family as *const c_char);
                callback(family_name);
                v += 1;
            }
        }
    }
}

pub fn for_each_variation<F>(family_name: &str, mut callback: F)
    where F: FnMut(String)
{
    debug!("getting variations for {}", family_name);
    unsafe {
        let config = FcConfigGetCurrent();
        let mut font_set = FcConfigGetFonts(config, FcSetSystem);
        let font_set_array_ptr = &mut font_set;
        let pattern = FcPatternCreate();
        assert!(!pattern.is_null());
        let family_name_c = CString::new(family_name).unwrap();
        let family_name = family_name_c.as_ptr();
        let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut c_char, family_name as *mut FcChar8);
        assert!(ok != 0);

        let object_set = FcObjectSetCreate();
        assert!(!object_set.is_null());

        FcObjectSetAdd(object_set, FC_FILE.as_ptr() as *mut c_char);
        FcObjectSetAdd(object_set, FC_INDEX.as_ptr() as *mut c_char);

        let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);

        debug!("found {} variations", (*matches).nfont);

        for i in 0..((*matches).nfont as isize) {
            let font = (*matches).fonts.offset(i);
            let mut file: *mut FcChar8 = ptr::null_mut();
            let result = FcPatternGetString(*font, FC_FILE.as_ptr() as *mut c_char, 0, &mut file);
            let file = if result == FcResultMatch {
                c_str_to_string(file as *const c_char)
            } else {
                panic!();
            };
            let mut index: libc::c_int = 0;
            let result = FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut c_char, 0, &mut index);
            let index = if result == FcResultMatch {
                index
            } else {
                panic!();
            };

            debug!("variation file: {}", file);
            debug!("variation index: {}", index);

            callback(file);
        }

        FcFontSetDestroy(matches);
        FcPatternDestroy(pattern);
        FcObjectSetDestroy(object_set);
    }
}

pub fn system_default_family(generic_name: &str) -> Option<String> {
    let generic_name_c = CString::new(generic_name).unwrap();
    let generic_name_ptr = generic_name_c.as_ptr();

    unsafe {
        let pattern = FcNameParse(generic_name_ptr as *mut FcChar8);

        FcConfigSubstitute(ptr::null_mut(), pattern, FcMatchPattern);
        FcDefaultSubstitute(pattern);

        let mut result = 0;
        let family_match = FcFontMatch(ptr::null_mut(), pattern, &mut result);

        let family_name = if result == FcResultMatch {
            let mut match_string: *mut FcChar8 = ptr::null_mut();
            FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut c_char, 0, &mut match_string);
            let result = c_str_to_string(match_string as *const c_char);
            FcPatternDestroy(family_match);
            Some(result)
        } else {
            None
        };

        FcPatternDestroy(pattern);
        family_name
    }
}

#[cfg(target_os = "linux")]
pub fn last_resort_font_families() -> Vec<String> {
    vec!(
        "Fira Sans".to_owned(),
        "DejaVu Sans".to_owned(),
        "Arial".to_owned()
    )
}

#[cfg(target_os = "windows")]
pub fn last_resort_font_families() -> Vec<String> {
    vec!(
        "Arial".to_owned()
    )
}

#[cfg(target_os = "linux")]
pub static SANS_SERIF_FONT_FAMILY: &'static str = "DejaVu Sans";

#[cfg(target_os = "windows")]
pub static SANS_SERIF_FONT_FAMILY: &'static str = "Arial";

<commit_msg>clean up cjk for os<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 fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
use fontconfig::fontconfig::{FcConfigGetCurrent, FcConfigGetFonts, FcConfigSubstitute};
use fontconfig::fontconfig::{FcDefaultSubstitute, FcFontMatch, FcNameParse, FcPatternGetString};
use fontconfig::fontconfig::{FcFontSetDestroy, FcMatchPattern, FcPatternCreate, FcPatternDestroy};
use fontconfig::fontconfig::{FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy, FcPatternAddString};
use fontconfig::fontconfig::{FcObjectSetAdd, FcPatternGetInteger};
use libc;
use libc::{c_char, c_int};
use std::borrow::ToOwned;
use std::ffi::CString;
use std::ptr;
use super::c_str_to_string;

static FC_FAMILY: &'static [u8] = b"family\0";
static FC_FILE: &'static [u8] = b"file\0";
static FC_INDEX: &'static [u8] = b"index\0";
static FC_FONTFORMAT: &'static [u8] = b"fontformat\0";

pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
    unsafe {
        let config = FcConfigGetCurrent();
        let font_set = FcConfigGetFonts(config, FcSetSystem);
        for i in 0..((*font_set).nfont as isize) {
            let font = (*font_set).fonts.offset(i);
            let mut family: *mut FcChar8 = ptr::null_mut();
            let mut format: *mut FcChar8 = ptr::null_mut();
            let mut v: c_int = 0;
            if FcPatternGetString(*font, FC_FONTFORMAT.as_ptr() as *mut c_char, v, &mut format) != FcResultMatch {
                continue;
            }

            // Skip bitmap fonts. They aren't supported by FreeType.
            let fontformat = c_str_to_string(format as *const c_char);
            if fontformat != "TrueType" &&
               fontformat != "CFF" &&
               fontformat != "Type 1" {
                continue;
            }

            while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut c_char, v, &mut family) == FcResultMatch {
                let family_name = c_str_to_string(family as *const c_char);
                callback(family_name);
                v += 1;
            }
        }
    }
}

pub fn for_each_variation<F>(family_name: &str, mut callback: F)
    where F: FnMut(String)
{
    debug!("getting variations for {}", family_name);
    unsafe {
        let config = FcConfigGetCurrent();
        let mut font_set = FcConfigGetFonts(config, FcSetSystem);
        let font_set_array_ptr = &mut font_set;
        let pattern = FcPatternCreate();
        assert!(!pattern.is_null());
        let family_name_c = CString::new(family_name).unwrap();
        let family_name = family_name_c.as_ptr();
        let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut c_char, family_name as *mut FcChar8);
        assert!(ok != 0);

        let object_set = FcObjectSetCreate();
        assert!(!object_set.is_null());

        FcObjectSetAdd(object_set, FC_FILE.as_ptr() as *mut c_char);
        FcObjectSetAdd(object_set, FC_INDEX.as_ptr() as *mut c_char);

        let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);

        debug!("found {} variations", (*matches).nfont);

        for i in 0..((*matches).nfont as isize) {
            let font = (*matches).fonts.offset(i);
            let mut file: *mut FcChar8 = ptr::null_mut();
            let result = FcPatternGetString(*font, FC_FILE.as_ptr() as *mut c_char, 0, &mut file);
            let file = if result == FcResultMatch {
                c_str_to_string(file as *const c_char)
            } else {
                panic!();
            };
            let mut index: libc::c_int = 0;
            let result = FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut c_char, 0, &mut index);
            let index = if result == FcResultMatch {
                index
            } else {
                panic!();
            };

            debug!("variation file: {}", file);
            debug!("variation index: {}", index);

            callback(file);
        }

        FcFontSetDestroy(matches);
        FcPatternDestroy(pattern);
        FcObjectSetDestroy(object_set);
    }
}

pub fn system_default_family(generic_name: &str) -> Option<String> {
    let generic_name_c = CString::new(generic_name).unwrap();
    let generic_name_ptr = generic_name_c.as_ptr();

    unsafe {
        let pattern = FcNameParse(generic_name_ptr as *mut FcChar8);

        FcConfigSubstitute(ptr::null_mut(), pattern, FcMatchPattern);
        FcDefaultSubstitute(pattern);

        let mut result = 0;
        let family_match = FcFontMatch(ptr::null_mut(), pattern, &mut result);

        let family_name = if result == FcResultMatch {
            let mut match_string: *mut FcChar8 = ptr::null_mut();
            FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut c_char, 0, &mut match_string);
            let result = c_str_to_string(match_string as *const c_char);
            FcPatternDestroy(family_match);
            Some(result)
        } else {
            None
        };

        FcPatternDestroy(pattern);
        family_name
    }
}

pub fn last_resort_font_families() -> Vec<String> {
    vec!(
        "Fira Sans".to_owned(),
        "DejaVu Sans".to_owned(),
        "Arial".to_owned()
    )
}

pub static SANS_SERIF_FONT_FAMILY: &'static str = "DejaVu Sans";
<|endoftext|>


<commit_before>#![allow(unsafe_code)]
//! This module implements the standard attribute dictionary.
//!
//! This dictionary is a singleton containing all information about the
//! DICOM attributes specified in the standard according to DICOM PS3.6 2016c,
//! and it will be used by default
//!
//! When not using private tags, this dictionary should suffice.

extern crate lazy_static;

mod entries;

use std::collections::HashMap;
use std::fmt;
use std::fmt::{Display, Formatter};
use attribute::dictionary::{AttributeDictionary, DictionaryEntry};
use self::entries::ENTRIES;

lazy_static! {
    static ref DICT: StandardAttributeDictionary = {
        init_dictionary()
    };
}

/// Retrieve a singleton instance of the standard dictionary.
pub fn get_instance() -> &'static StandardAttributeDictionary {
    &DICT
}

/// The data struct for the standard dictionary.
#[derive(Debug)]
pub struct StandardAttributeDictionary {
    name_to_pair: HashMap<&'static str, &'static DictionaryEntry<'static>>,
    pair_to_name: HashMap<(u16, u16), &'static DictionaryEntry<'static>>
}

impl StandardAttributeDictionary {
    fn new() -> StandardAttributeDictionary {
        StandardAttributeDictionary {
            name_to_pair: HashMap::new(),
            pair_to_name: HashMap::new()
        }
    }

    fn index(&mut self, entry: &'static DictionaryEntry<'static>) -> &mut Self {
        self.name_to_pair.insert(entry.alias, entry);
        self.pair_to_name.insert(entry.tag, entry);
        self
    }
}

impl AttributeDictionary<'static> for StandardAttributeDictionary {
    fn get_by_name(&self, name: &str) -> Option<&'static DictionaryEntry<'static>> {
        self.name_to_pair.get(name).map(|r| { *r })
    }

    fn get_by_tag(&self, tag: (u16, u16)) -> Option<&'static DictionaryEntry<'static>> {
        self.pair_to_name.get(&tag).map(|r| { *r })
    }
}

impl Display for StandardAttributeDictionary {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        f.write_str("Standard Attribute Dictionary")
    }
}

fn init_dictionary() -> StandardAttributeDictionary {
    let mut d = StandardAttributeDictionary::new();
    for entry in ENTRIES {
        d.index(&entry);
    }
    d
}
<commit_msg>Add file meta dictionary entries manually<commit_after>#![allow(unsafe_code)]
//! This module implements the standard attribute dictionary.
//!
//! This dictionary is a singleton containing all information about the
//! DICOM attributes specified in the standard according to DICOM PS3.6 2016c,
//! and it will be used by default
//!
//! When not using private tags, this dictionary should suffice.

extern crate lazy_static;

mod entries;

use std::collections::HashMap;
use std::fmt;
use std::fmt::{Display, Formatter};
use attribute::dictionary::{AttributeDictionary, DictionaryEntry};
use attribute::ValueRepresentation;
use self::entries::ENTRIES;

lazy_static! {
    static ref DICT: StandardAttributeDictionary = {
        init_dictionary()
    };
}

/// Retrieve a singleton instance of the standard dictionary.
pub fn get_instance() -> &'static StandardAttributeDictionary {
    &DICT
}

/// The data struct for the standard dictionary.
#[derive(Debug)]
pub struct StandardAttributeDictionary {
    name_to_pair: HashMap<&'static str, &'static DictionaryEntry<'static>>,
    pair_to_name: HashMap<(u16, u16), &'static DictionaryEntry<'static>>
}

impl StandardAttributeDictionary {
    fn new() -> StandardAttributeDictionary {
        StandardAttributeDictionary {
            name_to_pair: HashMap::new(),
            pair_to_name: HashMap::new()
        }
    }

    fn index(&mut self, entry: &'static DictionaryEntry<'static>) -> &mut Self {
        self.name_to_pair.insert(entry.alias, entry);
        self.pair_to_name.insert(entry.tag, entry);
        self
    }
}

impl AttributeDictionary<'static> for StandardAttributeDictionary {
    fn get_by_name(&self, name: &str) -> Option<&'static DictionaryEntry<'static>> {
        self.name_to_pair.get(name).map(|r| { *r })
    }

    fn get_by_tag(&self, tag: (u16, u16)) -> Option<&'static DictionaryEntry<'static>> {
        self.pair_to_name.get(&tag).map(|r| { *r })
    }
}

impl Display for StandardAttributeDictionary {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        f.write_str("Standard Attribute Dictionary")
    }
}

fn init_dictionary() -> StandardAttributeDictionary {
    let mut d = StandardAttributeDictionary::new();
    for entry in ENTRIES {
        d.index(&entry);
    }
    for entry in META_ENTRIES {
        d.index(&entry);
    }
    d
}

// meta information entries
type E<'a> = DictionaryEntry<'a>;
const META_ENTRIES : &'static [E<'static>] = &[
    E {tag: (0x0002,0x0000), alias: "FileMetaInformationGroupLength", vr: ValueRepresentation::UL},
    E {tag: (0x0002,0x0001), alias: "FileMetaInformationVersion", vr: ValueRepresentation::OB},
    E {tag: (0x0002,0x0002), alias: "MediaStorageSOPClassUID", vr: ValueRepresentation::UI},
    E {tag: (0x0002,0x0003), alias: "MediaStorageSOPInstanceUID", vr: ValueRepresentation::UI},
    E {tag: (0x0002,0x0010), alias: "TransferSyntaxUID", vr: ValueRepresentation::UI},
    E {tag: (0x0002,0x0012), alias: "ImplementationClassUID", vr: ValueRepresentation::UI},
    E {tag: (0x0002,0x0013), alias: "ImplentationVersionName", vr: ValueRepresentation::SH},
    E {tag: (0x0002,0x0016), alias: "SourceApplicationEntityTitle", vr: ValueRepresentation::AE},
    E {tag: (0x0002,0x0017), alias: "SendingApplicationEntityTitle", vr: ValueRepresentation::AE},
    E {tag: (0x0002,0x0018), alias: "ReceivingApplicationEntityTitle", vr: ValueRepresentation::AE},
    E {tag: (0x0002,0x0100), alias: "PrivateInformationCreatorUID", vr: ValueRepresentation::UI},
    E {tag: (0x0002,0x0102), alias: "PrivateInformation", vr: ValueRepresentation::OB},
];
<|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<()>
{
    while !solver.all_filled() {
        let rev = solver.revision();

        try!(solver.apply_all_theorem());
        if solver.revision() != rev {
            continue
        }

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

        break
    }

    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: small refactoring<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>;

enum FillResult {
    Completed(Solver),
    Partial(Solver, Vec<CellId>)
}

#[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 fill_absolutely_fixed(solver: &mut Solver) -> SolverResult<()> {
    while !solver.all_filled() {
        let rev = solver.revision();

        try!(solver.apply_all_theorem());
        if solver.revision() != rev {
            continue
        }

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

        break
    }

    Ok(())
}

fn fill_by_shallow_backtracking(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_in = solver.clone();
        solver_in.set_inside(p);

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

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

        if fill_absolutely_fixed(&mut solver_out).is_err() {
            *solver = solver_in;
        }
    }

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

fn fill(mut solver: Solver) -> SolverResult<FillResult> {
    try!(fill_absolutely_fixed(&mut solver));

    if solver.all_filled() {
        return Ok(FillResult::Completed(solver))
    }

    let mut pts = solver.get_unknown_points();
    while try!(fill_by_shallow_backtracking(&mut solver, &pts)) {
        if solver.all_filled() {
            return Ok(FillResult::Completed(solver))
        }
        pts = solver.get_unknown_points();
    }

    Ok(FillResult::Partial(solver, pts))
}

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))];

    while let Some(solver) = queue.pop() {
        let (solver,pts) = match fill(solver) {
            Ok(FillResult::Completed(mut solver)) => {
                if solver.validate_result().is_err() {
                    continue
                }
                return solver.into()
            }
            Ok(FillResult::Partial(solver, pts)) => (solver, pts),
            Err(_) => continue
        };

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

    Err(LogicError)
}
<|endoftext|>


<commit_before>use std::sync::RwLock;
use std::collections::{BTreeMap, HashMap};

use rocksdb::{DB, Writable, WriteBatch, IteratorMode, Direction};
use byteorder::{ByteOrder, BigEndian, WriteBytesExt};

use errors::{RocksDBReadError, RocksDBWriteError};
use key_builder::KeyBuilder;
use segment_ops::SegmentMergeError;
use search::doc_id_set::DocIdSet;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct DocRef(u32, u16);

impl DocRef {
    pub fn segment(&self) -> u32 {
        self.0
    }

    pub fn ord(&self) -> u16 {
        self.1
    }

    pub fn as_u64(&self) -> u64 {
        (self.0 as u64) << 16 | (self.1 as u64)
    }

    pub fn from_segment_ord(segment: u32, ord: u16) -> DocRef {
        DocRef(segment, ord)
    }

    pub fn from_u64(val: u64) -> DocRef {
        let segment = (val >> 16) & 0xFFFFFFFF;
        let ord = val & 0xFFFF;
        DocRef(segment as u32, ord as u16)
    }
}

/// Manages the index's "document index"
pub struct DocumentIndexManager {
    primary_key_index: RwLock<BTreeMap<Vec<u8>, DocRef>>,
}

impl DocumentIndexManager {
    /// Generates a new document index
    pub fn new(_db: &DB) -> Result<DocumentIndexManager, RocksDBWriteError> {
        Ok(DocumentIndexManager {
            primary_key_index: RwLock::new(BTreeMap::new()),
        })
    }

    /// Loads the document index from an index
    pub fn open(db: &DB) -> Result<DocumentIndexManager, RocksDBReadError> {
        // Read primary key index
        let mut primary_key_index = BTreeMap::new();
        for (k, v) in db.iterator(IteratorMode::From(b"k", Direction::Forward)) {
            if k[0] != b'k' {
                break;
            }

            let segment = BigEndian::read_u32(&v[0..4]);
            let ord = BigEndian::read_u16(&v[4..6]);
            let doc_ref = DocRef::from_segment_ord(segment, ord);

            primary_key_index.insert(k[1..].to_vec(), doc_ref);
        }

        Ok(DocumentIndexManager {
            primary_key_index: RwLock::new(primary_key_index),
        })
    }

    fn delete_document_by_ref_unchecked(&self, write_batch: &WriteBatch, doc_ref: DocRef) -> Result<(), RocksDBWriteError> {
        let kb = KeyBuilder::segment_del_list(doc_ref.segment());
        let mut previous_doc_id_bytes = [0; 2];
        BigEndian::write_u16(&mut previous_doc_id_bytes, doc_ref.ord());
        if let Err(e) = write_batch.merge(&kb.key(), &previous_doc_id_bytes) {
            return Err(RocksDBWriteError::new_merge(kb.key().to_vec(), e));
        }

        // Increment deleted docs
        let kb = KeyBuilder::segment_stat(doc_ref.segment(), b"deleted_docs");
        let mut inc_bytes = [0; 8];
        BigEndian::write_i64(&mut inc_bytes, 1);
        if let Err(e) = write_batch.merge(&kb.key(), &inc_bytes) {
            return Err(RocksDBWriteError::new_merge(kb.key().to_vec(), e));
        }

        Ok(())
    }

    pub fn insert_or_replace_key(&self, db: &DB, key: &Vec<u8>, doc_ref: DocRef) -> Result<Option<DocRef>, RocksDBWriteError> {
        // Update primary_key_index
        let write_batch = WriteBatch::new();
        let previous_doc_ref = self.primary_key_index.write().unwrap().insert(key.clone(), doc_ref);

        let kb = KeyBuilder::primary_key_index(key);
        let mut doc_ref_bytes = [0; 6];
        BigEndian::write_u32(&mut doc_ref_bytes, doc_ref.segment());
        BigEndian::write_u16(&mut doc_ref_bytes[4..], doc_ref.ord());
        if let Err(e) = write_batch.put(&kb.key(), &doc_ref_bytes) {
            return Err(RocksDBWriteError::new_put(kb.key().to_vec(), e));
        }

        // If there was a document there previously, delete it
        if let Some(previous_doc_ref) = previous_doc_ref {
            try!(self.delete_document_by_ref_unchecked(&write_batch, previous_doc_ref));
        }

        // Write document data
        if let Err(e) = db.write(write_batch) {
            return Err(RocksDBWriteError::new_commit_write_batch(e));
        }

        Ok(previous_doc_ref)
    }

    pub fn delete_document_by_key(&self, db: &DB, key: &Vec<u8>) -> Result<Option<DocRef>, RocksDBWriteError> {
        // Remove document from index
        let doc_ref = self.primary_key_index.write().unwrap().remove(key);

        if let Some(doc_ref) = doc_ref {
            let mut write_batch = WriteBatch::new();

            try!(self.delete_document_by_ref_unchecked(&mut write_batch, doc_ref));

            if let Err(e) = db.write(write_batch) {
                return Err(RocksDBWriteError::new_commit_write_batch(e));
            }
        }

        Ok(doc_ref)
    }

    pub fn contains_document_key(&self, key: &Vec<u8>) -> bool {
        self.primary_key_index.read().unwrap().contains_key(key)
    }

    pub fn commit_segment_merge(&self, db: &DB, write_batch: WriteBatch, source_segments: &Vec<u32>, dest_segment: u32, doc_ref_mapping: &HashMap<DocRef, u16>) -> Result<(), SegmentMergeError> {
        // Lock the primary key index
        let mut primary_key_index = self.primary_key_index.write().unwrap();

        // Update primary keys to point to their new locations
        let mut keys_to_update: HashMap<Vec<u8>, DocRef> = HashMap::with_capacity(doc_ref_mapping.len());
        for (key, doc_ref) in primary_key_index.iter() {
            if doc_ref_mapping.contains_key(&doc_ref) {
                keys_to_update.insert(key.clone(), *doc_ref);
            }
        }

        for (key, doc_ref) in keys_to_update {
            let new_doc_ord = doc_ref_mapping.get(&doc_ref).unwrap();
            let new_doc_ref = DocRef::from_segment_ord(dest_segment, *new_doc_ord);

            primary_key_index.insert(key, new_doc_ref);
        }

        // Merge deletion lists
        // Must be done while the primary_key_index is locked as this prevents any more documents being deleted
        let mut deletion_list = Vec::new();
        for source_segment in source_segments {
            let kb = KeyBuilder::segment_del_list(*source_segment);
            match db.get(&kb.key()) {
                Ok(Some(docid_set)) => {
                    for doc_id in DocIdSet::FromRDB(docid_set).iter() {
                        let doc_ref = DocRef::from_segment_ord(*source_segment, doc_id);
                        let new_doc_id = doc_ref_mapping.get(&doc_ref).unwrap();
                        deletion_list.write_u16::<BigEndian>(*new_doc_id).unwrap();
                    }
                }
                Ok(None) => {},
                Err(e) => return Err(RocksDBReadError::new(kb.key().to_vec(), e).into()),
            }
        }

        let kb = KeyBuilder::segment_del_list(dest_segment);
        if let Err(e) = db.put(&kb.key(), &deletion_list) {
            return Err(RocksDBWriteError::new_put(kb.key().to_vec(), e).into());
        }

        // Commit!
        if let Err(e) = db.write(write_batch) {
            return Err(RocksDBWriteError::new_commit_write_batch(e).into());
        }

        Ok(())
    }
}
<commit_msg>Flush PK index change to disk after segment merge<commit_after>use std::sync::RwLock;
use std::collections::{BTreeMap, HashMap};

use rocksdb::{DB, Writable, WriteBatch, IteratorMode, Direction};
use byteorder::{ByteOrder, BigEndian, WriteBytesExt};

use errors::{RocksDBReadError, RocksDBWriteError};
use key_builder::KeyBuilder;
use segment_ops::SegmentMergeError;
use search::doc_id_set::DocIdSet;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct DocRef(u32, u16);

impl DocRef {
    pub fn segment(&self) -> u32 {
        self.0
    }

    pub fn ord(&self) -> u16 {
        self.1
    }

    pub fn as_u64(&self) -> u64 {
        (self.0 as u64) << 16 | (self.1 as u64)
    }

    pub fn from_segment_ord(segment: u32, ord: u16) -> DocRef {
        DocRef(segment, ord)
    }

    pub fn from_u64(val: u64) -> DocRef {
        let segment = (val >> 16) & 0xFFFFFFFF;
        let ord = val & 0xFFFF;
        DocRef(segment as u32, ord as u16)
    }
}

/// Manages the index's "document index"
pub struct DocumentIndexManager {
    primary_key_index: RwLock<BTreeMap<Vec<u8>, DocRef>>,
}

impl DocumentIndexManager {
    /// Generates a new document index
    pub fn new(_db: &DB) -> Result<DocumentIndexManager, RocksDBWriteError> {
        Ok(DocumentIndexManager {
            primary_key_index: RwLock::new(BTreeMap::new()),
        })
    }

    /// Loads the document index from an index
    pub fn open(db: &DB) -> Result<DocumentIndexManager, RocksDBReadError> {
        // Read primary key index
        let mut primary_key_index = BTreeMap::new();
        for (k, v) in db.iterator(IteratorMode::From(b"k", Direction::Forward)) {
            if k[0] != b'k' {
                break;
            }

            let segment = BigEndian::read_u32(&v[0..4]);
            let ord = BigEndian::read_u16(&v[4..6]);
            let doc_ref = DocRef::from_segment_ord(segment, ord);

            primary_key_index.insert(k[1..].to_vec(), doc_ref);
        }

        Ok(DocumentIndexManager {
            primary_key_index: RwLock::new(primary_key_index),
        })
    }

    fn delete_document_by_ref_unchecked(&self, write_batch: &WriteBatch, doc_ref: DocRef) -> Result<(), RocksDBWriteError> {
        let kb = KeyBuilder::segment_del_list(doc_ref.segment());
        let mut previous_doc_id_bytes = [0; 2];
        BigEndian::write_u16(&mut previous_doc_id_bytes, doc_ref.ord());
        if let Err(e) = write_batch.merge(&kb.key(), &previous_doc_id_bytes) {
            return Err(RocksDBWriteError::new_merge(kb.key().to_vec(), e));
        }

        // Increment deleted docs
        let kb = KeyBuilder::segment_stat(doc_ref.segment(), b"deleted_docs");
        let mut inc_bytes = [0; 8];
        BigEndian::write_i64(&mut inc_bytes, 1);
        if let Err(e) = write_batch.merge(&kb.key(), &inc_bytes) {
            return Err(RocksDBWriteError::new_merge(kb.key().to_vec(), e));
        }

        Ok(())
    }

    pub fn insert_or_replace_key(&self, db: &DB, key: &Vec<u8>, doc_ref: DocRef) -> Result<Option<DocRef>, RocksDBWriteError> {
        // Update primary_key_index
        let write_batch = WriteBatch::new();
        let previous_doc_ref = self.primary_key_index.write().unwrap().insert(key.clone(), doc_ref);

        let kb = KeyBuilder::primary_key_index(key);
        let mut doc_ref_bytes = [0; 6];
        BigEndian::write_u32(&mut doc_ref_bytes, doc_ref.segment());
        BigEndian::write_u16(&mut doc_ref_bytes[4..], doc_ref.ord());
        if let Err(e) = write_batch.put(&kb.key(), &doc_ref_bytes) {
            return Err(RocksDBWriteError::new_put(kb.key().to_vec(), e));
        }

        // If there was a document there previously, delete it
        if let Some(previous_doc_ref) = previous_doc_ref {
            try!(self.delete_document_by_ref_unchecked(&write_batch, previous_doc_ref));
        }

        // Write document data
        if let Err(e) = db.write(write_batch) {
            return Err(RocksDBWriteError::new_commit_write_batch(e));
        }

        Ok(previous_doc_ref)
    }

    pub fn delete_document_by_key(&self, db: &DB, key: &Vec<u8>) -> Result<Option<DocRef>, RocksDBWriteError> {
        // Remove document from index
        let doc_ref = self.primary_key_index.write().unwrap().remove(key);

        if let Some(doc_ref) = doc_ref {
            let mut write_batch = WriteBatch::new();

            try!(self.delete_document_by_ref_unchecked(&mut write_batch, doc_ref));

            if let Err(e) = db.write(write_batch) {
                return Err(RocksDBWriteError::new_commit_write_batch(e));
            }
        }

        Ok(doc_ref)
    }

    pub fn contains_document_key(&self, key: &Vec<u8>) -> bool {
        self.primary_key_index.read().unwrap().contains_key(key)
    }

    pub fn commit_segment_merge(&self, db: &DB, write_batch: WriteBatch, source_segments: &Vec<u32>, dest_segment: u32, doc_ref_mapping: &HashMap<DocRef, u16>) -> Result<(), SegmentMergeError> {
        // Lock the primary key index
        let mut primary_key_index = self.primary_key_index.write().unwrap();

        // Update primary keys to point to their new locations
        let mut keys_to_update: HashMap<Vec<u8>, DocRef> = HashMap::with_capacity(doc_ref_mapping.len());
        for (key, doc_ref) in primary_key_index.iter() {
            if doc_ref_mapping.contains_key(&doc_ref) {
                keys_to_update.insert(key.clone(), *doc_ref);
            }
        }

        for (key, doc_ref) in keys_to_update {
            let new_doc_ord = doc_ref_mapping.get(&doc_ref).unwrap();
            let new_doc_ref = DocRef::from_segment_ord(dest_segment, *new_doc_ord);

            let kb = KeyBuilder::primary_key_index(&key);
            let mut doc_ref_bytes = [0; 6];
            BigEndian::write_u32(&mut doc_ref_bytes, new_doc_ref.segment());
            BigEndian::write_u16(&mut doc_ref_bytes[4..], new_doc_ref.ord());
            if let Err(e) = write_batch.put(&kb.key(), &doc_ref_bytes) {
                return Err(RocksDBWriteError::new_put(kb.key().to_vec(), e).into());
            }

            primary_key_index.insert(key, new_doc_ref);
        }

        // Merge deletion lists
        // Must be done while the primary_key_index is locked as this prevents any more documents being deleted
        let mut deletion_list = Vec::new();
        for source_segment in source_segments {
            let kb = KeyBuilder::segment_del_list(*source_segment);
            match db.get(&kb.key()) {
                Ok(Some(docid_set)) => {
                    for doc_id in DocIdSet::FromRDB(docid_set).iter() {
                        let doc_ref = DocRef::from_segment_ord(*source_segment, doc_id);
                        let new_doc_id = doc_ref_mapping.get(&doc_ref).unwrap();
                        deletion_list.write_u16::<BigEndian>(*new_doc_id).unwrap();
                    }
                }
                Ok(None) => {},
                Err(e) => return Err(RocksDBReadError::new(kb.key().to_vec(), e).into()),
            }
        }

        let kb = KeyBuilder::segment_del_list(dest_segment);
        if let Err(e) = db.put(&kb.key(), &deletion_list) {
            return Err(RocksDBWriteError::new_put(kb.key().to_vec(), e).into());
        }

        // Commit!
        if let Err(e) = db.write(write_batch) {
            return Err(RocksDBWriteError::new_commit_write_batch(e).into());
        }

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


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// no-pretty-expanded FIXME #15189
// ignore-windows FIXME #13259
use std::os;
use std::io::process::Command;
use std::finally::Finally;
use std::str;

#[inline(never)]
fn foo() {
    let _v = vec![1i, 2, 3];
    if os::getenv("IS_TEST").is_some() {
        panic!()
    }
}

#[inline(never)]
fn double() {
    (|| {
        panic!("once");
    }).finally(|| {
        panic!("twice");
    })
}

fn runtest(me: &str) {
    let mut template = Command::new(me);
    template.env("IS_TEST", "1");

    // Make sure that the stack trace is printed
    let p = template.clone().arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(out.error.as_slice()).unwrap();
    assert!(s.contains("stack backtrace") && s.contains("foo::h"),
            "bad output: {}", s);

    // Make sure the stack trace is *not* printed
    let p = template.clone().arg("fail").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(out.error.as_slice()).unwrap();
    assert!(!s.contains("stack backtrace") && !s.contains("foo::h"),
            "bad output2: {}", s);

    // Make sure a stack trace is printed
    let p = template.clone().arg("double-fail").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(out.error.as_slice()).unwrap();
    assert!(s.contains("stack backtrace") && s.contains("double::h"),
            "bad output3: {}", s);

    // Make sure a stack trace isn't printed too many times
    let p = template.clone().arg("double-fail")
                                .env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(out.error.as_slice()).unwrap();
    let mut i = 0;
    for _ in range(0i, 2) {
        i += s.slice_from(i + 10).find_str("stack backtrace").unwrap() + 10;
    }
    assert!(s.slice_from(i + 10).find_str("stack backtrace").is_none(),
            "bad output4: {}", s);
}

fn main() {
    let args = os::args();
    let args = args.as_slice();
    if args.len() >= 2 && args[1].as_slice() == "fail" {
        foo();
    } else if args.len() >= 2 && args[1].as_slice() == "double-fail" {
        double();
    } else {
        runtest(args[0].as_slice());
    }
}
<commit_msg>Loosen possibly bogus constraints in backtrace test<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// no-pretty-expanded FIXME #15189
// ignore-windows FIXME #13259
use std::os;
use std::io::process::Command;
use std::finally::Finally;
use std::str;

#[inline(never)]
fn foo() {
    let _v = vec![1i, 2, 3];
    if os::getenv("IS_TEST").is_some() {
        panic!()
    }
}

#[inline(never)]
fn double() {
    (|| {
        panic!("once");
    }).finally(|| {
        panic!("twice");
    })
}

fn runtest(me: &str) {
    let mut template = Command::new(me);
    template.env("IS_TEST", "1");

    // Make sure that the stack trace is printed
    let p = template.clone().arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(out.error.as_slice()).unwrap();
    assert!(s.contains("stack backtrace") && s.contains("foo::h"),
            "bad output: {}", s);

    // Make sure the stack trace is *not* printed
    let p = template.clone().arg("fail").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(out.error.as_slice()).unwrap();
    assert!(!s.contains("stack backtrace") && !s.contains("foo::h"),
            "bad output2: {}", s);

    // Make sure a stack trace is printed
    let p = template.clone().arg("double-fail").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(out.error.as_slice()).unwrap();
    // loosened the following from double::h to double:: due to
    // spurious failures on mac, 32bit, optimized
    assert!(s.contains("stack backtrace") && s.contains("double::"),
            "bad output3: {}", s);

    // Make sure a stack trace isn't printed too many times
    let p = template.clone().arg("double-fail")
                                .env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(out.error.as_slice()).unwrap();
    let mut i = 0;
    for _ in range(0i, 2) {
        i += s.slice_from(i + 10).find_str("stack backtrace").unwrap() + 10;
    }
    assert!(s.slice_from(i + 10).find_str("stack backtrace").is_none(),
            "bad output4: {}", s);
}

fn main() {
    let args = os::args();
    let args = args.as_slice();
    if args.len() >= 2 && args[1].as_slice() == "fail" {
        foo();
    } else if args.len() >= 2 && args[1].as_slice() == "double-fail" {
        double();
    } else {
        runtest(args[0].as_slice());
    }
}
<|endoftext|>


<commit_before>use std::iter::Peekable;

/// An iterator that performs a lookahead of 1, utilizing the existing Peakable Iterator
/// Can be stacked to perform an even greater lookahead
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Peeking<I, A> where
    A: Clone,
    I: Iterator<Item=A>,
{
    iter: Peekable<I>,
}

impl<I, A> Iterator for Peeking<I, A> where
    A: Clone,
    I: Iterator<Item=A>
{
    type Item = (A, Option<A>);

    #[inline]
    fn next(&mut self) -> Option<(A, Option<A>)> {
        match self.iter.next() {
            Some(item) => Some((item,
                match self.iter.peek() {
                    Some(ref item) => Some((*item).clone()),
                    None => None,
                }
            )),
            None => None,
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

pub trait PeekingExt {
    fn peeking(self) -> Peeking<Self, Self::Item>
        where Self: Sized+Iterator,
              Self::Item: Clone;
}

impl<A: Clone, I: Sized+Iterator<Item=A>> PeekingExt for I {
    fn peeking(self) -> Peeking<Self, A>
        where Self: Sized+Iterator
    {
         Peeking { iter: self.peekable() }
    }
}

/// An iterator to maintain state while iterating another iterator and allows filtering
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct FilteringScan<I, St, F> {
    iter: I,
    f: F,
    state: St,
}

impl<B, I, St, F> Iterator for FilteringScan<I, St, F> where
    I: Iterator,
    F: FnMut(&mut St, I::Item) -> Option<B>,
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        loop {
            match self.iter.next() {
                Some(next) => match (self.f)(&mut self.state, next) {
                    Some(result) => return Some(result),
                    None => continue,
                },
                None => return None,
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.iter.size_hint();
        (0, upper) // can't know a lower bound, due to the scan function
    }
}

pub trait FilteringScanExt {
    fn scan_filter<St, B, F>(self, initial_state: St, f: F) -> FilteringScan<Self, St, F>
        where Self: Sized+Iterator, F: FnMut(&mut St, Self::Item) -> Option<B>;
}

impl<I: Sized+Iterator> FilteringScanExt for I {
    fn scan_filter<St, B, F>(self, initial_state: St, f: F) -> FilteringScan<Self, St, F>
        where Self: Sized+Iterator, F: FnMut(&mut St, I::Item) -> Option<B>,
    {
        FilteringScan{iter: self, f: f, state: initial_state}
    }
}

#[derive(Clone)]
pub enum ParseResult {
    Continue,
    Halt,
    End,
}

/// An iterator to maintain state while iterating another iterator and allows more complex parsing
// (allowing holding the current iterator value, continue if its goes empty and filter the output)
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Parser<I, A, St, F> where
    A: Clone,
    I: Iterator<Item=A>,
{
    iter: I,
    f: F,
    state: St,

    iter_state: ParseResult,
    current_elem: Option<A>,
}

impl<B, I, St, F, A> Iterator for Parser<I, A, St, F> where
    A: Clone,
    I: Iterator<Item=A>,
    F: FnMut(&mut St, Option<I::Item>) -> (ParseResult, Option<B>),
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        loop {
            match self.iter_state {
                ParseResult::Continue => self.current_elem = self.iter.next(),
                ParseResult::Halt => {},
                ParseResult::End => return None,
            };

            let (new_state, result) = (self.f) (&mut self.state, self.current_elem.clone());

            self.iter_state = new_state;

            match result {
                Some(result) => return Some(result),
                None => continue,
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None) // can't know a lower or upper bound, due to the parse function
    }
}

pub trait ParserExt {
    fn parsing<St, B, F>(self, initial_state: St, f: F) -> Parser<Self, Self::Item, St, F>
        where Self: Sized+Iterator, Self::Item: Clone, F: Fn(&mut St, Option<Self::Item>) -> (ParseResult, Option<B>);
}

impl<A:Clone, I: Sized+Iterator<Item=A>>ParserExt for I {
    fn parsing<St, B, F>(self, initial_state: St, f: F) -> Parser<Self, A, St, F>
        where F: FnMut(&mut St, Option<A>) -> (ParseResult, Option<B>),
    {
        Parser{iter: self, f: f, state: initial_state, iter_state: ParseResult::Continue, current_elem: None}
    }
}

#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Wait<B, I, E, F>
    where
    I: Iterator,
    F: FnMut(&mut E, I::Item) -> Option<B> {
        iter: I,
        f: F,
        current_elem: Option<B>,
}

impl<B, I, E, F> Iterator for Wait<B, I, E, F> where
    I: Iterator,
    F: FnMut(&mut E, I::Item) -> Option<B>,
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        while let Some(elem) =  self.iter.next() {
            match self.f(self.current_elem, elem) {
                Some(elem) => {
                    let return_val = self.current_elem;
                    self.current_elem = elem;
                    match return_val {
                        Some(value) => return Some(value),
                        None => continue,
                    }
                },
                None => continue,
            }
        }
        None
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.iter.size_hint();
        (0, upper) // can't know a lower bound, due to the waiting function
    }
}

#[test]
fn peeking_test() {
    let test = vec!["first", "second", "third"];
    let mut index = 0;
    for (elem, peek) in test.into_iter().peeking() {
        match elem {
            "first" => {
                assert_eq!(peek, Some("second"));
                index += 1;
            },
            "second" => {
                assert_eq!(peek, Some("third"));
                index += 1;
            },
            "third" => {
                assert_eq!(peek, None);
                index += 1;
            },
            _ => assert!(false),
        }
    }
    assert_eq!(index, 3);
}

#[test]
fn filtering_scan_test() {
    let test = vec![1, 3, 1, 3];
    let index = 0;
    let mut sum = 0;
    for elem in test.into_iter().scan_filter(index, |index, x| {
        *index += 1;
        if (*index % 2) == 1 {
            Some(x)
        } else {
            None
        }
    }) {
        sum += elem;
    }
    assert_eq!(sum, 2);
}

#[test]
fn parsing_test() {

    struct ParseState {
        one_halt_test: u32,
        two_counter: u32,
        one_more_test: bool,
    }

    let mut result = vec![];

    let test = vec![1, 2, 2, 3];
    for elem in test.into_iter().parsing(
        ParseState {
            one_halt_test: 3,
            two_counter: 1,
            one_more_test: true,
        },
        |state, elem| {
            match elem {
                Some(1) => {
                    state.one_halt_test -= 1;
                    if state.one_halt_test == 0 {
                        (ParseResult::Continue, Some(1))
                    } else {
                        (ParseResult::Halt, None)
                    }
                },
                Some(2) => {
                    state.two_counter += 1;
                    (ParseResult::Continue, Some(state.two_counter))
                },
                Some(3) => {
                    (ParseResult::Continue, Some(4))
                },
                Some(_) => { panic!("found a bug in rust") },
                None => {
                    if state.one_more_test {
                        state.one_more_test = false;
                        (ParseResult::Continue, Some(5))
                    } else {
                        (ParseResult::End, None)
                    }
                }
            }
        }
    ) {
        result.push(elem);
    }

    assert_eq!(result, vec![1, 2, 3, 4, 5]);
}
<commit_msg>Finished new (renamed) construct extension<commit_after>use std::iter::Peekable;

/// An iterator that performs a lookahead of 1, utilizing the existing Peakable Iterator
/// Can be stacked to perform an even greater lookahead
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Peeking<I, A> where
    A: Clone,
    I: Iterator<Item=A>,
{
    iter: Peekable<I>,
}

impl<I, A> Iterator for Peeking<I, A> where
    A: Clone,
    I: Iterator<Item=A>
{
    type Item = (A, Option<A>);

    #[inline]
    fn next(&mut self) -> Option<(A, Option<A>)> {
        match self.iter.next() {
            Some(item) => Some((item,
                match self.iter.peek() {
                    Some(ref item) => Some((*item).clone()),
                    None => None,
                }
            )),
            None => None,
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

pub trait PeekingExt {
    fn peeking(self) -> Peeking<Self, Self::Item>
        where Self: Sized+Iterator,
              Self::Item: Clone;
}

impl<A: Clone, I: Sized+Iterator<Item=A>> PeekingExt for I {
    fn peeking(self) -> Peeking<Self, A>
        where Self: Sized+Iterator
    {
         Peeking { iter: self.peekable() }
    }
}

/// An iterator to maintain state while iterating another iterator and allows filtering
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct FilteringScan<I, St, F> {
    iter: I,
    f: F,
    state: St,
}

impl<B, I, St, F> Iterator for FilteringScan<I, St, F> where
    I: Iterator,
    F: FnMut(&mut St, I::Item) -> Option<B>,
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        loop {
            match self.iter.next() {
                Some(next) => match (self.f)(&mut self.state, next) {
                    Some(result) => return Some(result),
                    None => continue,
                },
                None => return None,
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.iter.size_hint();
        (0, upper) // can't know a lower bound, due to the scan function
    }
}

pub trait FilteringScanExt {
    fn scan_filter<St, B, F>(self, initial_state: St, f: F) -> FilteringScan<Self, St, F>
        where Self: Sized+Iterator, F: FnMut(&mut St, Self::Item) -> Option<B>;
}

impl<I: Sized+Iterator> FilteringScanExt for I {
    fn scan_filter<St, B, F>(self, initial_state: St, f: F) -> FilteringScan<Self, St, F>
        where Self: Sized+Iterator, F: FnMut(&mut St, I::Item) -> Option<B>,
    {
        FilteringScan{iter: self, f: f, state: initial_state}
    }
}

#[derive(Clone)]
pub enum ParseResult {
    Continue,
    Halt,
    End,
}

/// An iterator to maintain state while iterating another iterator and allows more complex parsing
// (allowing holding the current iterator value, continue if its goes empty and filter the output)
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Parser<I, A, St, F> where
    A: Clone,
    I: Iterator<Item=A>,
{
    iter: I,
    f: F,
    state: St,

    iter_state: ParseResult,
    current_elem: Option<A>,
}

impl<B, I, St, F, A> Iterator for Parser<I, A, St, F> where
    A: Clone,
    I: Iterator<Item=A>,
    F: FnMut(&mut St, Option<I::Item>) -> (ParseResult, Option<B>),
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        loop {
            match self.iter_state {
                ParseResult::Continue => self.current_elem = self.iter.next(),
                ParseResult::Halt => {},
                ParseResult::End => return None,
            };

            let (new_state, result) = (self.f) (&mut self.state, self.current_elem.clone());

            self.iter_state = new_state;

            match result {
                Some(result) => return Some(result),
                None => continue,
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None) // can't know a lower or upper bound, due to the parse function
    }
}

pub trait ParserExt {
    fn parsing<St, B, F>(self, initial_state: St, f: F) -> Parser<Self, Self::Item, St, F>
        where Self: Sized+Iterator, Self::Item: Clone, F: Fn(&mut St, Option<Self::Item>) -> (ParseResult, Option<B>);
}

impl<A:Clone, I: Sized+Iterator<Item=A>>ParserExt for I {
    fn parsing<St, B, F>(self, initial_state: St, f: F) -> Parser<Self, A, St, F>
        where F: FnMut(&mut St, Option<A>) -> (ParseResult, Option<B>),
    {
        Parser{iter: self, f: f, state: initial_state, iter_state: ParseResult::Continue, current_elem: None}
    }
}

#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Constructor<I, B, F>
    where
    I: Iterator,
    B: Clone,
    F: FnMut(&mut Option<B>, I::Item) -> Option<B> {
        iter: I,
        f: F,
        current_elem: Option<B>,
}

impl<I, B, F> Iterator for Constructor<I, B, F> where
    I: Iterator,
    B: Clone,
    F: FnMut(&mut Option<B>, I::Item) -> Option<B>,
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        while let Some(elem) =  self.iter.next() {
            match (self.f)(&mut self.current_elem, elem) {
                Some(elem) => {
                    let return_val = self.current_elem.clone();
                    self.current_elem = Some(elem);
                    match return_val {
                        Some(value) => return Some(value),
                        None => continue,
                    }
                },
                None => continue,
            }
        }

        let result = self.current_elem.clone();
        self.current_elem = None;
        result
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.iter.size_hint();
        (0, upper) // can't know a lower bound, due to the waiting function
    }
}

pub trait ConstructorExt {
    fn construct<F, B>(self, f: F) -> Constructor<Self, B, F>
        where Self: Sized+Iterator, B: Clone, F: Fn(&mut Option<B>, Self::Item) -> Option<B>;
}

impl<I: Sized+Iterator>ConstructorExt for I {
    fn construct<F, B>(self, f: F) -> Constructor<Self, B, F>
        where Self: Sized+Iterator, B: Clone, F: Fn(&mut Option<B>, I::Item) -> Option<B>,
    {
        Constructor{iter: self, f: f, current_elem: None}
    }
}

#[test]
fn peeking_test() {
    let test = vec!["first", "second", "third"];
    let mut index = 0;
    for (elem, peek) in test.into_iter().peeking() {
        match elem {
            "first" => {
                assert_eq!(peek, Some("second"));
                index += 1;
            },
            "second" => {
                assert_eq!(peek, Some("third"));
                index += 1;
            },
            "third" => {
                assert_eq!(peek, None);
                index += 1;
            },
            _ => assert!(false),
        }
    }
    assert_eq!(index, 3);
}

#[test]
fn filtering_scan_test() {
    let test = vec![1, 3, 1, 3];
    let index = 0;
    let mut sum = 0;
    for elem in test.into_iter().scan_filter(index, |index, x| {
        *index += 1;
        if (*index % 2) == 1 {
            Some(x)
        } else {
            None
        }
    }) {
        sum += elem;
    }
    assert_eq!(sum, 2);
}

#[test]
fn parsing_test() {

    struct ParseState {
        one_halt_test: u32,
        two_counter: u32,
        one_more_test: bool,
    }

    let mut result = vec![];

    let test = vec![1, 2, 2, 3];
    for elem in test.into_iter().parsing(
        ParseState {
            one_halt_test: 3,
            two_counter: 1,
            one_more_test: true,
        },
        |state, elem| {
            match elem {
                Some(1) => {
                    state.one_halt_test -= 1;
                    if state.one_halt_test == 0 {
                        (ParseResult::Continue, Some(1))
                    } else {
                        (ParseResult::Halt, None)
                    }
                },
                Some(2) => {
                    state.two_counter += 1;
                    (ParseResult::Continue, Some(state.two_counter))
                },
                Some(3) => {
                    (ParseResult::Continue, Some(4))
                },
                Some(_) => { panic!("found a bug in rust") },
                None => {
                    if state.one_more_test {
                        state.one_more_test = false;
                        (ParseResult::Continue, Some(5))
                    } else {
                        (ParseResult::End, None)
                    }
                }
            }
        }
    ) {
        result.push(elem);
    }

    assert_eq!(result, vec![1, 2, 3, 4, 5]);
}

#[test]
fn construct_test() {
    use std::cell::Cell;

    let test: Vec<u8> = vec![3, 3, 3, 2, 4, 5, 2];

    let result : Vec<u8> = test.into_iter().construct(|ref mut value, i| {
        if value.is_none() {
            return Some(Cell::new(i)); //first value
        }

        let old_val = value.as_ref().unwrap().get();
        value.as_ref().unwrap().set(old_val + i);

        if value.as_ref().unwrap().get() >= 5 {
            Some(Cell::new(0)) //new value
        } else {
            None //continue constucting
        }
    }).map(|x| { x.get() % 5 }).collect();

    assert_eq!(result, vec![1, 0, 4, 2]);
}
<|endoftext|>


<commit_before>use super::on_conflict_actions::*;
use super::on_conflict_clause::*;
use super::on_conflict_target::*;
use query_builder::{AsChangeset, InsertStatement, UndecoratedInsertRecord};
use query_source::QuerySource;

impl<T, U, Op, Ret> InsertStatement<T, U, Op, Ret>
where
    U: UndecoratedInsertRecord<T>,
{
    /// Adds `ON CONFLICT DO NOTHING` to the insert statement, without
    /// specifying any columns or constraints to restrict the conflict to.
    ///
    /// # Examples
    ///
    /// ### Single Record
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Sean", };
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&user)
    ///     .on_conflict_do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), inserted_row_count);
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&user)
    ///     .on_conflict_do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(0), inserted_row_count);
    /// # }
    /// ```
    ///
    /// ### Vec of Records
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Sean", };
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&vec![user, user])
    ///     .on_conflict_do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), inserted_row_count);
    /// # }
    /// ```
    pub fn on_conflict_do_nothing(
        self,
    ) -> InsertStatement<T, OnConflictValues<U, NoConflictTarget, DoNothing>, Op, Ret> {
        self.replace_values(OnConflictValues::do_nothing)
    }

    /// Adds an `ON CONFLICT` to the insert statement, if a conflict occurs
    /// for the given unique constraint.
    ///
    /// `Target` can be one of:
    ///
    /// - A column
    /// - A tuple of columns
    /// - [`on_constraint("constraint_name")`][`on_constraint`]
    ///
    /// # Examples
    ///
    /// ### Specifying a column as the target
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// conn.execute("CREATE UNIQUE INDEX users_name ON users (name)").unwrap();
    /// let user = User { id: 1, name: "Sean", };
    /// let same_name_different_id = User { id: 2, name: "Sean" };
    /// let same_id_different_name = User { id: 1, name: "Pascal" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&same_name_different_id)
    ///     .on_conflict(name)
    ///     .do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(0), inserted_row_count);
    ///
    /// let pk_conflict_result = diesel::insert_into(users)
    ///     .values(&same_id_different_name)
    ///     .on_conflict(name)
    ///     .do_nothing()
    ///     .execute(&conn);
    /// assert!(pk_conflict_result.is_err());
    /// # }
    /// ```
    ///
    /// ### Specifying multiple columns as the target
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #         hair_color -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # #[derive(Clone, Copy, Insertable)]
    /// # #[table_name="users"]
    /// # struct User<'a> {
    /// #     id: i32,
    /// #     name: &'a str,
    /// #     hair_color: &'a str,
    /// # }
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// use diesel::pg::upsert::*;
    ///
    /// #     let conn = establish_connection();
    /// #     conn.execute("DROP TABLE users").unwrap();
    /// #     conn.execute("CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT, hair_color TEXT)").unwrap();
    /// conn.execute("CREATE UNIQUE INDEX users_name_hair_color ON users (name, hair_color)").unwrap();
    /// let user = User { id: 1, name: "Sean", hair_color: "black" };
    /// let same_name_different_hair_color = User { id: 2, name: "Sean", hair_color: "brown" };
    /// let same_same_name_same_hair_color = User { id: 3, name: "Sean", hair_color: "black" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&same_name_different_hair_color)
    ///     .on_conflict((name, hair_color))
    ///     .do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), inserted_row_count);
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&same_same_name_same_hair_color)
    ///     .on_conflict((name, hair_color))
    ///     .do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(0), inserted_row_count);
    /// # }
    /// ```
    ///
    /// See the documentation for [`on_constraint`] and [`do_update`] for
    /// more examples.
    ///
    /// [`on_constraint`]: ../pg/upsert/fn.on_constraint.html
    /// [`do_update`]: ../pg/upsert/struct.IncompleteOnConflict.html#method.do_update
    pub fn on_conflict<Target>(
        self,
        target: Target,
    ) -> IncompleteOnConflict<Self, ConflictTarget<Target>>
    where
        ConflictTarget<Target>: OnConflictTarget<T>,
    {
        IncompleteOnConflict {
            stmt: self,
            target: ConflictTarget(target),
        }
    }
}

/// A partially constructed `ON CONFLICT` clause.
#[derive(Debug, Clone, Copy)]
pub struct IncompleteOnConflict<Stmt, Target> {
    stmt: Stmt,
    target: Target,
}

impl<T, U, Op, Ret, Target> IncompleteOnConflict<InsertStatement<T, U, Op, Ret>, Target> {
    /// Creates a query with `ON CONFLICT (target) DO NOTHING`
    ///
    /// If you want to do nothing when *any* constraint conflicts, use
    /// [`on_conflict_do_nothing`] instead. See [`on_conflict`] for usage
    /// examples.
    ///
    /// [`on_conflict_do_nothing`]: ../../query_builder/struct.InsertStatement.html#method.on_conflict_do_nothing
    /// [`on_conflict`]: ../../query_builder/struct.InsertStatement.html#method.on_conflict
    pub fn do_nothing(self) -> InsertStatement<T, OnConflictValues<U, Target, DoNothing>, Op, Ret> {
        let target = self.target;
        self.stmt
            .replace_values(|values| OnConflictValues::new(values, target, DoNothing))
    }
}

impl<Stmt, Target> IncompleteOnConflict<Stmt, Target> {
    /// Used to create a query in the form `ON CONFLICT (...) DO UPDATE ...`
    ///
    /// Call `.set` on the result of this function with the changes you want to
    /// apply. The argument to `set` can be anything that implements `AsChangeset`
    /// (e.g. anything you could pass to `set` on a normal update statement).
    ///
    /// Note: When inserting more than one row at a time, this query can still fail
    /// if the rows being inserted conflict with each other.
    ///
    /// # Examples
    ///
    /// ## Set specific value on conflict
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Pascal" };
    /// let user2 = User { id: 1, name: "Sean" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let insert_count = diesel::insert_into(users)
    ///     .values(&user2)
    ///     .on_conflict(id)
    ///     .do_update()
    ///     .set(name.eq("I DONT KNOW ANYMORE"))
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), insert_count);
    ///
    /// let users_in_db = users.load(&conn);
    /// assert_eq!(Ok(vec![(1, "I DONT KNOW ANYMORE".to_string())]), users_in_db);
    /// # }
    /// ```
    ///
    /// ## Set `AsChangeset` struct on conflict
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Pascal" };
    /// let user2 = User { id: 1, name: "Sean" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let insert_count = diesel::insert_into(users)
    ///     .values(&user2)
    ///     .on_conflict(id)
    ///     .do_update()
    ///     .set(&user2)
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), insert_count);
    ///
    /// let users_in_db = users.load(&conn);
    /// assert_eq!(Ok(vec![(1, "Sean".to_string())]), users_in_db);
    /// # }
    /// ```
    ///
    /// ## Use `excluded` to get the rejected value
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// use diesel::pg::upsert::excluded;
    ///
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Pascal" };
    /// let user2 = User { id: 1, name: "Sean" };
    /// let user3 = User { id: 2, name: "Tess" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let insert_count = diesel::insert_into(users)
    ///     .values(&vec![user2, user3])
    ///     .on_conflict(id)
    ///     .do_update()
    ///     .set(name.eq(excluded(name)))
    ///     .execute(&conn);
    /// assert_eq!(Ok(2), insert_count);
    ///
    /// let users_in_db = users.load(&conn);
    /// assert_eq!(Ok(vec![(1, "Sean".to_string()), (2, "Tess".to_string())]), users_in_db);
    /// # }
    /// ```
    pub fn do_update(self) -> IncompleteDoUpdate<Stmt, Target> {
        IncompleteDoUpdate {
            stmt: self.stmt,
            target: self.target,
        }
    }
}

/// A partially constructed `ON CONFLICT DO UPDATE` clause.
#[derive(Debug, Clone, Copy)]
pub struct IncompleteDoUpdate<Stmt, Target> {
    stmt: Stmt,
    target: Target,
}

impl<T, U, Op, Ret, Target> IncompleteDoUpdate<InsertStatement<T, U, Op, Ret>, Target> {
    /// See [`do_update`] for usage examples.
    ///
    /// [`do_update`]: struct.IncompleteOnConflict.html#method.do_update
    pub fn set<Changes>(
        self,
        changes: Changes,
    ) -> InsertStatement<T, OnConflictValues<U, Target, DoUpdate<Changes::Changeset>>, Op, Ret>
    where
        T: QuerySource,
        Changes: AsChangeset<Target = T>,
    {
        let target = self.target;
        self.stmt.replace_values(|values| {
            OnConflictValues::new(values, target, DoUpdate::new(changes.as_changeset()))
        })
    }
}
<commit_msg>Fix variable name in doc comment for on_conflict()<commit_after>use super::on_conflict_actions::*;
use super::on_conflict_clause::*;
use super::on_conflict_target::*;
use query_builder::{AsChangeset, InsertStatement, UndecoratedInsertRecord};
use query_source::QuerySource;

impl<T, U, Op, Ret> InsertStatement<T, U, Op, Ret>
where
    U: UndecoratedInsertRecord<T>,
{
    /// Adds `ON CONFLICT DO NOTHING` to the insert statement, without
    /// specifying any columns or constraints to restrict the conflict to.
    ///
    /// # Examples
    ///
    /// ### Single Record
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Sean", };
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&user)
    ///     .on_conflict_do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), inserted_row_count);
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&user)
    ///     .on_conflict_do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(0), inserted_row_count);
    /// # }
    /// ```
    ///
    /// ### Vec of Records
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Sean", };
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&vec![user, user])
    ///     .on_conflict_do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), inserted_row_count);
    /// # }
    /// ```
    pub fn on_conflict_do_nothing(
        self,
    ) -> InsertStatement<T, OnConflictValues<U, NoConflictTarget, DoNothing>, Op, Ret> {
        self.replace_values(OnConflictValues::do_nothing)
    }

    /// Adds an `ON CONFLICT` to the insert statement, if a conflict occurs
    /// for the given unique constraint.
    ///
    /// `Target` can be one of:
    ///
    /// - A column
    /// - A tuple of columns
    /// - [`on_constraint("constraint_name")`][`on_constraint`]
    ///
    /// # Examples
    ///
    /// ### Specifying a column as the target
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// conn.execute("CREATE UNIQUE INDEX users_name ON users (name)").unwrap();
    /// let user = User { id: 1, name: "Sean", };
    /// let same_name_different_id = User { id: 2, name: "Sean" };
    /// let same_id_different_name = User { id: 1, name: "Pascal" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&same_name_different_id)
    ///     .on_conflict(name)
    ///     .do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(0), inserted_row_count);
    ///
    /// let pk_conflict_result = diesel::insert_into(users)
    ///     .values(&same_id_different_name)
    ///     .on_conflict(name)
    ///     .do_nothing()
    ///     .execute(&conn);
    /// assert!(pk_conflict_result.is_err());
    /// # }
    /// ```
    ///
    /// ### Specifying multiple columns as the target
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #         hair_color -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # #[derive(Clone, Copy, Insertable)]
    /// # #[table_name="users"]
    /// # struct User<'a> {
    /// #     id: i32,
    /// #     name: &'a str,
    /// #     hair_color: &'a str,
    /// # }
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// use diesel::pg::upsert::*;
    ///
    /// #     let conn = establish_connection();
    /// #     conn.execute("DROP TABLE users").unwrap();
    /// #     conn.execute("CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT, hair_color TEXT)").unwrap();
    /// conn.execute("CREATE UNIQUE INDEX users_name_hair_color ON users (name, hair_color)").unwrap();
    /// let user = User { id: 1, name: "Sean", hair_color: "black" };
    /// let same_name_different_hair_color = User { id: 2, name: "Sean", hair_color: "brown" };
    /// let same_name_same_hair_color = User { id: 3, name: "Sean", hair_color: "black" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&same_name_different_hair_color)
    ///     .on_conflict((name, hair_color))
    ///     .do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), inserted_row_count);
    ///
    /// let inserted_row_count = diesel::insert_into(users)
    ///     .values(&same_name_same_hair_color)
    ///     .on_conflict((name, hair_color))
    ///     .do_nothing()
    ///     .execute(&conn);
    /// assert_eq!(Ok(0), inserted_row_count);
    /// # }
    /// ```
    ///
    /// See the documentation for [`on_constraint`] and [`do_update`] for
    /// more examples.
    ///
    /// [`on_constraint`]: ../pg/upsert/fn.on_constraint.html
    /// [`do_update`]: ../pg/upsert/struct.IncompleteOnConflict.html#method.do_update
    pub fn on_conflict<Target>(
        self,
        target: Target,
    ) -> IncompleteOnConflict<Self, ConflictTarget<Target>>
    where
        ConflictTarget<Target>: OnConflictTarget<T>,
    {
        IncompleteOnConflict {
            stmt: self,
            target: ConflictTarget(target),
        }
    }
}

/// A partially constructed `ON CONFLICT` clause.
#[derive(Debug, Clone, Copy)]
pub struct IncompleteOnConflict<Stmt, Target> {
    stmt: Stmt,
    target: Target,
}

impl<T, U, Op, Ret, Target> IncompleteOnConflict<InsertStatement<T, U, Op, Ret>, Target> {
    /// Creates a query with `ON CONFLICT (target) DO NOTHING`
    ///
    /// If you want to do nothing when *any* constraint conflicts, use
    /// [`on_conflict_do_nothing`] instead. See [`on_conflict`] for usage
    /// examples.
    ///
    /// [`on_conflict_do_nothing`]: ../../query_builder/struct.InsertStatement.html#method.on_conflict_do_nothing
    /// [`on_conflict`]: ../../query_builder/struct.InsertStatement.html#method.on_conflict
    pub fn do_nothing(self) -> InsertStatement<T, OnConflictValues<U, Target, DoNothing>, Op, Ret> {
        let target = self.target;
        self.stmt
            .replace_values(|values| OnConflictValues::new(values, target, DoNothing))
    }
}

impl<Stmt, Target> IncompleteOnConflict<Stmt, Target> {
    /// Used to create a query in the form `ON CONFLICT (...) DO UPDATE ...`
    ///
    /// Call `.set` on the result of this function with the changes you want to
    /// apply. The argument to `set` can be anything that implements `AsChangeset`
    /// (e.g. anything you could pass to `set` on a normal update statement).
    ///
    /// Note: When inserting more than one row at a time, this query can still fail
    /// if the rows being inserted conflict with each other.
    ///
    /// # Examples
    ///
    /// ## Set specific value on conflict
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Pascal" };
    /// let user2 = User { id: 1, name: "Sean" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let insert_count = diesel::insert_into(users)
    ///     .values(&user2)
    ///     .on_conflict(id)
    ///     .do_update()
    ///     .set(name.eq("I DONT KNOW ANYMORE"))
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), insert_count);
    ///
    /// let users_in_db = users.load(&conn);
    /// assert_eq!(Ok(vec![(1, "I DONT KNOW ANYMORE".to_string())]), users_in_db);
    /// # }
    /// ```
    ///
    /// ## Set `AsChangeset` struct on conflict
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Pascal" };
    /// let user2 = User { id: 1, name: "Sean" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let insert_count = diesel::insert_into(users)
    ///     .values(&user2)
    ///     .on_conflict(id)
    ///     .do_update()
    ///     .set(&user2)
    ///     .execute(&conn);
    /// assert_eq!(Ok(1), insert_count);
    ///
    /// let users_in_db = users.load(&conn);
    /// assert_eq!(Ok(vec![(1, "Sean".to_string())]), users_in_db);
    /// # }
    /// ```
    ///
    /// ## Use `excluded` to get the rejected value
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("on_conflict_docs_setup.rs");
    /// #
    /// # fn main() {
    /// #     use users::dsl::*;
    /// use diesel::pg::upsert::excluded;
    ///
    /// #     let conn = establish_connection();
    /// #     conn.execute("TRUNCATE TABLE users").unwrap();
    /// let user = User { id: 1, name: "Pascal" };
    /// let user2 = User { id: 1, name: "Sean" };
    /// let user3 = User { id: 2, name: "Tess" };
    ///
    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
    ///
    /// let insert_count = diesel::insert_into(users)
    ///     .values(&vec![user2, user3])
    ///     .on_conflict(id)
    ///     .do_update()
    ///     .set(name.eq(excluded(name)))
    ///     .execute(&conn);
    /// assert_eq!(Ok(2), insert_count);
    ///
    /// let users_in_db = users.load(&conn);
    /// assert_eq!(Ok(vec![(1, "Sean".to_string()), (2, "Tess".to_string())]), users_in_db);
    /// # }
    /// ```
    pub fn do_update(self) -> IncompleteDoUpdate<Stmt, Target> {
        IncompleteDoUpdate {
            stmt: self.stmt,
            target: self.target,
        }
    }
}

/// A partially constructed `ON CONFLICT DO UPDATE` clause.
#[derive(Debug, Clone, Copy)]
pub struct IncompleteDoUpdate<Stmt, Target> {
    stmt: Stmt,
    target: Target,
}

impl<T, U, Op, Ret, Target> IncompleteDoUpdate<InsertStatement<T, U, Op, Ret>, Target> {
    /// See [`do_update`] for usage examples.
    ///
    /// [`do_update`]: struct.IncompleteOnConflict.html#method.do_update
    pub fn set<Changes>(
        self,
        changes: Changes,
    ) -> InsertStatement<T, OnConflictValues<U, Target, DoUpdate<Changes::Changeset>>, Op, Ret>
    where
        T: QuerySource,
        Changes: AsChangeset<Target = T>,
    {
        let target = self.target;
        self.stmt.replace_values(|values| {
            OnConflictValues::new(values, target, DoUpdate::new(changes.as_changeset()))
        })
    }
}
<|endoftext|>