<commit_before>use std::io::{Result, Write};

use analysis;
use library;
use env::Env;
use super::child_properties;
use super::function;
use super::general;
use super::properties;
use super::signal;
use super::trait_impls;
use super::trampoline;

pub fn generate(
    w: &mut Write,
    env: &Env,
    analysis: &analysis::object::Info,
    generate_display_trait: bool,
) -> Result<()> {
    try!(general::start_comments(w, &env.config));
    try!(general::uses(w, env, &analysis.imports));

    try!(general::define_object_type(
        w,
        env,
        &analysis.name,
        &analysis.c_type,
        &analysis.c_class_type.as_ref().map(|s| &s[..]),
        &analysis.rust_class_type.as_ref().map(|s| &s[..]),
        &analysis.get_type,
        analysis.is_interface,
        &analysis.supertypes,
    ));

    if need_generate_inherent(analysis) {
        try!(writeln!(w));
        try!(write!(w, "impl {} {{", analysis.name));
        for func_analysis in &analysis.constructors() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

        if !need_generate_trait(analysis) {
            for func_analysis in &analysis.methods() {
                try!(function::generate(w, env, func_analysis, false, false, 1));
            }

            for property in &analysis.properties {
                try!(properties::generate(w, env, property, false, false, 1));
            }

            for child_property in &analysis.child_properties {
                try!(child_properties::generate(
                    w,
                    env,
                    child_property,
                    false,
                    false,
                    1,
                ));
            }
        }

        for func_analysis in &analysis.functions() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

        if !need_generate_trait(analysis) {
            for signal_analysis in analysis
                .signals
                .iter()
                .chain(analysis.notify_signals.iter())
            {
                try!(signal::generate(
                    w,
                    env,
                    signal_analysis,
                    &analysis.trampolines,
                    false,
                    false,
                    1,
                ));
            }
        }

        try!(writeln!(w, "}}"));

        try!(general::declare_default_from_new(
            w,
            env,
            &analysis.name,
            &analysis.functions
        ));
    }

    try!(trait_impls::generate(
        w,
        &analysis.name,
        &analysis.functions,
        &analysis.specials,
        if need_generate_trait(analysis) {
            Some(&analysis.trait_name)
        } else {
            None
        },
    ));

    if analysis.concurrency != library::Concurrency::None {
        try!(writeln!(w));
    }

    match analysis.concurrency {
        library::Concurrency::Send | library::Concurrency::SendSync => {
            try!(writeln!(w, "unsafe impl Send for {} {{}}", analysis.name));
        }
        library::Concurrency::SendUnique => {
            if env.namespaces.is_glib_crate {
                try!(writeln!(w, "unsafe impl ::SendUnique for {} {{", analysis.name));
            } else {
                try!(writeln!(w, "unsafe impl glib::SendUnique for {} {{", analysis.name));
            }

            try!(writeln!(w, "    fn is_unique(&self) -> bool {{"));
            try!(writeln!(w, "        self.ref_count() == 1"));
            try!(writeln!(w, "    }}"));

            try!(writeln!(w, "}}"));
        },
        _ => (),
    }

    if let library::Concurrency::SendSync = analysis.concurrency {
        try!(writeln!(w, "unsafe impl Sync for {} {{}}", analysis.name));
    }

    if need_generate_trait(analysis) {
        try!(writeln!(w));
        try!(generate_trait(w, env, analysis));
    }

    if !analysis.trampolines.is_empty() {
        for trampoline in &analysis.trampolines {
            try!(trampoline::generate(
                w,
                env,
                trampoline,
                need_generate_trait(analysis),
                &analysis.name,
            ));
        }
    }

    if generate_display_trait {
        try!(writeln!(
            w,
            "\nimpl fmt::Display for {} {{",
            analysis.name,
        ));
        // Generate Display trait implementation.
        try!(writeln!(w, "\tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{\n\
                            \t\twrite!(f, \"{}\")\n\
                          \t}}\n\
                        }}", analysis.name));
    }

    Ok(())
}

fn generate_trait(
    w: &mut Write,
    env: &Env,
    analysis: &analysis::object::Info,
) -> Result<()> {
    try!(write!(w, "pub trait {}: 'static {{", analysis.trait_name));

    for func_analysis in &analysis.methods() {
        try!(function::generate(w, env, func_analysis, true, true, 1));
    }
    for property in &analysis.properties {
        try!(properties::generate(w, env, property, true, true, 1));
    }
    for child_property in &analysis.child_properties {
        try!(child_properties::generate(
            w,
            env,
            child_property,
            true,
            true,
            1,
        ));
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        try!(signal::generate(
            w,
            env,
            signal_analysis,
            &analysis.trampolines,
            true,
            true,
            1,
        ));
    }
    try!(writeln!(w, "}}"));

    try!(writeln!(w));
    try!(write!(
        w,
        "impl<O: IsA<{}>> {} for O {{",
        analysis.name,
        analysis.trait_name,
    ));

    for func_analysis in &analysis.methods() {
        try!(function::generate(w, env, func_analysis, true, false, 1));
    }
    for property in &analysis.properties {
        try!(properties::generate(w, env, property, true, false, 1));
    }
    for child_property in &analysis.child_properties {
        try!(child_properties::generate(
            w,
            env,
            child_property,
            true,
            false,
            1,
        ));
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        try!(signal::generate(
            w,
            env,
            signal_analysis,
            &analysis.trampolines,
            true,
            false,
            1,
        ));
    }
    try!(writeln!(w, "}}"));

    Ok(())
}

fn need_generate_inherent(analysis: &analysis::object::Info) -> bool {
    analysis.has_constructors || analysis.has_functions || !need_generate_trait(analysis)
}

fn need_generate_trait(analysis: &analysis::object::Info) -> bool {
    analysis.generate_trait
}

pub fn generate_reexports(
    env: &Env,
    analysis: &analysis::object::Info,
    module_name: &str,
    contents: &mut Vec<String>,
    traits: &mut Vec<String>,
) {
    let mut cfgs: Vec<String> = Vec::new();
    if let Some(cfg) = general::cfg_condition_string(&analysis.cfg_condition, false, 0) {
        cfgs.push(cfg);
    }
    if let Some(cfg) = general::version_condition_string(env, analysis.version, false, 0) {
        cfgs.push(cfg);
    }
    contents.push("".to_owned());
    contents.extend_from_slice(&cfgs);
    contents.push(format!("mod {};", module_name));
    contents.extend_from_slice(&cfgs);
    if let Some(ref class_name) = analysis.rust_class_type {
        contents.push(format!("pub use self::{}::{{{}, {}}};", module_name, analysis.name, class_name));
    } else {
        contents.push(format!("pub use self::{}::{};", module_name, analysis.name));
    }
    if need_generate_trait(analysis) {
        contents.extend_from_slice(&cfgs);
        contents.push(format!(
            "pub use self::{}::{};",
            module_name,
            analysis.trait_name
        ));
        for cfg in &cfgs {
            traits.push(format!("\t{}", cfg));
        }
        traits.push(format!("\tpub use super::{};", analysis.trait_name));
    }
}
<commit_msg>Generate a typed None constant for references to Objects<commit_after>use std::io::{Result, Write};

use case::CaseExt;
use analysis;
use library;
use env::Env;
use super::child_properties;
use super::function;
use super::general;
use super::properties;
use super::signal;
use super::trait_impls;
use super::trampoline;

pub fn generate(
    w: &mut Write,
    env: &Env,
    analysis: &analysis::object::Info,
    generate_display_trait: bool,
) -> Result<()> {
    try!(general::start_comments(w, &env.config));
    try!(general::uses(w, env, &analysis.imports));

    try!(general::define_object_type(
        w,
        env,
        &analysis.name,
        &analysis.c_type,
        &analysis.c_class_type.as_ref().map(|s| &s[..]),
        &analysis.rust_class_type.as_ref().map(|s| &s[..]),
        &analysis.get_type,
        analysis.is_interface,
        &analysis.supertypes,
    ));

    if need_generate_inherent(analysis) {
        try!(writeln!(w));
        try!(write!(w, "impl {} {{", analysis.name));
        for func_analysis in &analysis.constructors() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

        if !need_generate_trait(analysis) {
            for func_analysis in &analysis.methods() {
                try!(function::generate(w, env, func_analysis, false, false, 1));
            }

            for property in &analysis.properties {
                try!(properties::generate(w, env, property, false, false, 1));
            }

            for child_property in &analysis.child_properties {
                try!(child_properties::generate(
                    w,
                    env,
                    child_property,
                    false,
                    false,
                    1,
                ));
            }
        }

        for func_analysis in &analysis.functions() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

        if !need_generate_trait(analysis) {
            for signal_analysis in analysis
                .signals
                .iter()
                .chain(analysis.notify_signals.iter())
            {
                try!(signal::generate(
                    w,
                    env,
                    signal_analysis,
                    &analysis.trampolines,
                    false,
                    false,
                    1,
                ));
            }
        }

        try!(writeln!(w, "}}"));

        try!(general::declare_default_from_new(
            w,
            env,
            &analysis.name,
            &analysis.functions
        ));
    }

    try!(trait_impls::generate(
        w,
        &analysis.name,
        &analysis.functions,
        &analysis.specials,
        if need_generate_trait(analysis) {
            Some(&analysis.trait_name)
        } else {
            None
        },
    ));

    if analysis.concurrency != library::Concurrency::None {
        try!(writeln!(w));
    }

    match analysis.concurrency {
        library::Concurrency::Send | library::Concurrency::SendSync => {
            try!(writeln!(w, "unsafe impl Send for {} {{}}", analysis.name));
        }
        library::Concurrency::SendUnique => {
            if env.namespaces.is_glib_crate {
                try!(writeln!(w, "unsafe impl ::SendUnique for {} {{", analysis.name));
            } else {
                try!(writeln!(w, "unsafe impl glib::SendUnique for {} {{", analysis.name));
            }

            try!(writeln!(w, "    fn is_unique(&self) -> bool {{"));
            try!(writeln!(w, "        self.ref_count() == 1"));
            try!(writeln!(w, "    }}"));

            try!(writeln!(w, "}}"));
        },
        _ => (),
    }

    if let library::Concurrency::SendSync = analysis.concurrency {
        try!(writeln!(w, "unsafe impl Sync for {} {{}}", analysis.name));
    }

    try!(writeln!(w));
    try!(writeln!(w, "pub const NONE_{}: Option<&{}> = None;", analysis.name.to_snake().to_uppercase(), analysis.name));

    if need_generate_trait(analysis) {
        try!(writeln!(w));
        try!(generate_trait(w, env, analysis));
    }

    if !analysis.trampolines.is_empty() {
        for trampoline in &analysis.trampolines {
            try!(trampoline::generate(
                w,
                env,
                trampoline,
                need_generate_trait(analysis),
                &analysis.name,
            ));
        }
    }

    if generate_display_trait {
        try!(writeln!(
            w,
            "\nimpl fmt::Display for {} {{",
            analysis.name,
        ));
        // Generate Display trait implementation.
        try!(writeln!(w, "\tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{\n\
                            \t\twrite!(f, \"{}\")\n\
                          \t}}\n\
                        }}", analysis.name));
    }

    Ok(())
}

fn generate_trait(
    w: &mut Write,
    env: &Env,
    analysis: &analysis::object::Info,
) -> Result<()> {
    try!(write!(w, "pub trait {}: 'static {{", analysis.trait_name));

    for func_analysis in &analysis.methods() {
        try!(function::generate(w, env, func_analysis, true, true, 1));
    }
    for property in &analysis.properties {
        try!(properties::generate(w, env, property, true, true, 1));
    }
    for child_property in &analysis.child_properties {
        try!(child_properties::generate(
            w,
            env,
            child_property,
            true,
            true,
            1,
        ));
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        try!(signal::generate(
            w,
            env,
            signal_analysis,
            &analysis.trampolines,
            true,
            true,
            1,
        ));
    }
    try!(writeln!(w, "}}"));

    try!(writeln!(w));
    try!(write!(
        w,
        "impl<O: IsA<{}>> {} for O {{",
        analysis.name,
        analysis.trait_name,
    ));

    for func_analysis in &analysis.methods() {
        try!(function::generate(w, env, func_analysis, true, false, 1));
    }
    for property in &analysis.properties {
        try!(properties::generate(w, env, property, true, false, 1));
    }
    for child_property in &analysis.child_properties {
        try!(child_properties::generate(
            w,
            env,
            child_property,
            true,
            false,
            1,
        ));
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        try!(signal::generate(
            w,
            env,
            signal_analysis,
            &analysis.trampolines,
            true,
            false,
            1,
        ));
    }
    try!(writeln!(w, "}}"));

    Ok(())
}

fn need_generate_inherent(analysis: &analysis::object::Info) -> bool {
    analysis.has_constructors || analysis.has_functions || !need_generate_trait(analysis)
}

fn need_generate_trait(analysis: &analysis::object::Info) -> bool {
    analysis.generate_trait
}

pub fn generate_reexports(
    env: &Env,
    analysis: &analysis::object::Info,
    module_name: &str,
    contents: &mut Vec<String>,
    traits: &mut Vec<String>,
) {
    let mut cfgs: Vec<String> = Vec::new();
    if let Some(cfg) = general::cfg_condition_string(&analysis.cfg_condition, false, 0) {
        cfgs.push(cfg);
    }
    if let Some(cfg) = general::version_condition_string(env, analysis.version, false, 0) {
        cfgs.push(cfg);
    }
    contents.push("".to_owned());
    contents.extend_from_slice(&cfgs);
    contents.push(format!("mod {};", module_name));
    contents.extend_from_slice(&cfgs);
    if let Some(ref class_name) = analysis.rust_class_type {
        contents.push(format!("pub use self::{}::{{{}, {}, {}}};", module_name, analysis.name, class_name, format!("NONE_{}", analysis.name.to_snake().to_uppercase())));
    } else {
        contents.push(format!("pub use self::{}::{{{}, {}}};", module_name, analysis.name, format!("NONE_{}", analysis.name.to_snake().to_uppercase())));
    }
    if need_generate_trait(analysis) {
        contents.extend_from_slice(&cfgs);
        contents.push(format!(
            "pub use self::{}::{};",
            module_name,
            analysis.trait_name
        ));
        for cfg in &cfgs {
            traits.push(format!("\t{}", cfg));
        }
        traits.push(format!("\tpub use super::{};", analysis.trait_name));
    }
}
<|endoftext|>


<commit_before>#[link(name = "x86_64_asm", kind = "static")]
extern "C" {
    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_interrupt_enable"
    )]
    pub(crate) fn x86_64_asm_interrupt_enable();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_interrupt_disable"
    )]
    pub(crate) fn x86_64_asm_interrupt_disable();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_interrupt_enable_and_hlt"
    )]
    pub(crate) fn x86_64_asm_interrupt_enable_and_hlt();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_int3"
    )]
    pub(crate) fn x86_64_asm_int3();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_hlt"
    )]
    pub(crate) fn x86_64_asm_hlt();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_nop"
    )]
    pub(crate) fn x86_64_asm_nop();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_bochs"
    )]
    pub(crate) fn x86_64_asm_bochs();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_from_port_u8"
    )]
    pub(crate) fn x86_64_asm_read_from_port_u8(port: u16) -> u8;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_from_port_u16"
    )]
    pub(crate) fn x86_64_asm_read_from_port_u16(port: u16) -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_from_port_u32"
    )]
    pub(crate) fn x86_64_asm_read_from_port_u32(port: u16) -> u32;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_to_port_u8"
    )]
    pub(crate) fn x86_64_asm_write_to_port_u8(port: u16, value: u8);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_to_port_u16"
    )]
    pub(crate) fn x86_64_asm_write_to_port_u16(port: u16, value: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_to_port_u32"
    )]
    pub(crate) fn x86_64_asm_write_to_port_u32(port: u16, value: u32);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_set_cs"
    )]
    pub(crate) fn x86_64_asm_set_cs(sel: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_ss"
    )]
    pub(crate) fn x86_64_asm_load_ss(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_ds"
    )]
    pub(crate) fn x86_64_asm_load_ds(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_es"
    )]
    pub(crate) fn x86_64_asm_load_es(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_fs"
    )]
    pub(crate) fn x86_64_asm_load_fs(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_gs"
    )]
    pub(crate) fn x86_64_asm_load_gs(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_ss"
    )]
    pub(crate) fn x86_64_asm_get_ss() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_ds"
    )]
    pub(crate) fn x86_64_asm_get_ds() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_es"
    )]
    pub(crate) fn x86_64_asm_get_es() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_fs"
    )]
    pub(crate) fn x86_64_asm_get_fs() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_gs"
    )]
    pub(crate) fn x86_64_asm_get_gs() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_swapgs"
    )]
    pub(crate) fn x86_64_asm_swapgs();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_cs"
    )]
    pub(crate) fn x86_64_asm_get_cs() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_lgdt"
    )]
    pub(crate) fn x86_64_asm_lgdt(gdt: *const crate::instructions::tables::DescriptorTablePointer);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_lidt"
    )]
    pub(crate) fn x86_64_asm_lidt(idt: *const crate::instructions::tables::DescriptorTablePointer);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_sidt"
    )]
    pub(crate) fn x86_64_asm_sidt(idt: *mut crate::instructions::tables::DescriptorTablePointer);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_ltr"
    )]
    pub(crate) fn x86_64_asm_ltr(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_invlpg"
    )]
    pub(crate) fn x86_64_asm_invlpg(addr: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_invpcid"
    )]
    pub(crate) fn x86_64_asm_invpcid(kind: u64, desc: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_cr0"
    )]
    pub(crate) fn x86_64_asm_read_cr0() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_cr0"
    )]
    pub(crate) fn x86_64_asm_write_cr0(value: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_cr2"
    )]
    pub(crate) fn x86_64_asm_read_cr2() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_cr3"
    )]
    pub(crate) fn x86_64_asm_read_cr3() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_cr3"
    )]
    pub(crate) fn x86_64_asm_write_cr3(value: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_cr4"
    )]
    pub(crate) fn x86_64_asm_read_cr4() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_cr4"
    )]
    pub(crate) fn x86_64_asm_write_cr4(value: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_rdmsr"
    )]
    pub(crate) fn x86_64_asm_rdmsr(msr: u32) -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_wrmsr"
    )]
    pub(crate) fn x86_64_asm_wrmsr(msr: u32, low: u32, high: u32);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_rflags"
    )]
    pub(crate) fn x86_64_asm_read_rflags() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_rflags"
    )]
    pub(crate) fn x86_64_asm_write_rflags(val: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_rdfsbase"
    )]
    pub(crate) fn x86_64_asm_rdfsbase() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_wrfsbase"
    )]
    pub(crate) fn x86_64_asm_wrfsbase(val: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_rdgsbase"
    )]
    pub(crate) fn x86_64_asm_rdgsbase() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_wrgsbase"
    )]
    pub(crate) fn x86_64_asm_wrgsbase(val: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_xgetbv"
    )]
    pub(crate) fn x86_64_asm_xgetbv(xcr: u32) -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_xsetbv"
    )]
    pub(crate) fn x86_64_asm_xsetbv(xcr: u32, low: u32, high: u32);
}
<commit_msg>chore: specify `sysv64` for the calling convention (#267)<commit_after>#[link(name = "x86_64_asm", kind = "static")]
extern "sysv64" {
    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_interrupt_enable"
    )]
    pub(crate) fn x86_64_asm_interrupt_enable();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_interrupt_disable"
    )]
    pub(crate) fn x86_64_asm_interrupt_disable();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_interrupt_enable_and_hlt"
    )]
    pub(crate) fn x86_64_asm_interrupt_enable_and_hlt();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_int3"
    )]
    pub(crate) fn x86_64_asm_int3();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_hlt"
    )]
    pub(crate) fn x86_64_asm_hlt();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_nop"
    )]
    pub(crate) fn x86_64_asm_nop();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_bochs"
    )]
    pub(crate) fn x86_64_asm_bochs();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_from_port_u8"
    )]
    pub(crate) fn x86_64_asm_read_from_port_u8(port: u16) -> u8;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_from_port_u16"
    )]
    pub(crate) fn x86_64_asm_read_from_port_u16(port: u16) -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_from_port_u32"
    )]
    pub(crate) fn x86_64_asm_read_from_port_u32(port: u16) -> u32;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_to_port_u8"
    )]
    pub(crate) fn x86_64_asm_write_to_port_u8(port: u16, value: u8);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_to_port_u16"
    )]
    pub(crate) fn x86_64_asm_write_to_port_u16(port: u16, value: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_to_port_u32"
    )]
    pub(crate) fn x86_64_asm_write_to_port_u32(port: u16, value: u32);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_set_cs"
    )]
    pub(crate) fn x86_64_asm_set_cs(sel: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_ss"
    )]
    pub(crate) fn x86_64_asm_load_ss(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_ds"
    )]
    pub(crate) fn x86_64_asm_load_ds(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_es"
    )]
    pub(crate) fn x86_64_asm_load_es(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_fs"
    )]
    pub(crate) fn x86_64_asm_load_fs(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_load_gs"
    )]
    pub(crate) fn x86_64_asm_load_gs(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_ss"
    )]
    pub(crate) fn x86_64_asm_get_ss() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_ds"
    )]
    pub(crate) fn x86_64_asm_get_ds() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_es"
    )]
    pub(crate) fn x86_64_asm_get_es() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_fs"
    )]
    pub(crate) fn x86_64_asm_get_fs() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_gs"
    )]
    pub(crate) fn x86_64_asm_get_gs() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_swapgs"
    )]
    pub(crate) fn x86_64_asm_swapgs();

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_get_cs"
    )]
    pub(crate) fn x86_64_asm_get_cs() -> u16;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_lgdt"
    )]
    pub(crate) fn x86_64_asm_lgdt(gdt: *const crate::instructions::tables::DescriptorTablePointer);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_lidt"
    )]
    pub(crate) fn x86_64_asm_lidt(idt: *const crate::instructions::tables::DescriptorTablePointer);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_sidt"
    )]
    pub(crate) fn x86_64_asm_sidt(idt: *mut crate::instructions::tables::DescriptorTablePointer);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_ltr"
    )]
    pub(crate) fn x86_64_asm_ltr(sel: u16);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_invlpg"
    )]
    pub(crate) fn x86_64_asm_invlpg(addr: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_invpcid"
    )]
    pub(crate) fn x86_64_asm_invpcid(kind: u64, desc: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_cr0"
    )]
    pub(crate) fn x86_64_asm_read_cr0() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_cr0"
    )]
    pub(crate) fn x86_64_asm_write_cr0(value: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_cr2"
    )]
    pub(crate) fn x86_64_asm_read_cr2() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_cr3"
    )]
    pub(crate) fn x86_64_asm_read_cr3() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_cr3"
    )]
    pub(crate) fn x86_64_asm_write_cr3(value: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_cr4"
    )]
    pub(crate) fn x86_64_asm_read_cr4() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_cr4"
    )]
    pub(crate) fn x86_64_asm_write_cr4(value: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_rdmsr"
    )]
    pub(crate) fn x86_64_asm_rdmsr(msr: u32) -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_wrmsr"
    )]
    pub(crate) fn x86_64_asm_wrmsr(msr: u32, low: u32, high: u32);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_read_rflags"
    )]
    pub(crate) fn x86_64_asm_read_rflags() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_write_rflags"
    )]
    pub(crate) fn x86_64_asm_write_rflags(val: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_rdfsbase"
    )]
    pub(crate) fn x86_64_asm_rdfsbase() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_wrfsbase"
    )]
    pub(crate) fn x86_64_asm_wrfsbase(val: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_rdgsbase"
    )]
    pub(crate) fn x86_64_asm_rdgsbase() -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_wrgsbase"
    )]
    pub(crate) fn x86_64_asm_wrgsbase(val: u64);

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_xgetbv"
    )]
    pub(crate) fn x86_64_asm_xgetbv(xcr: u32) -> u64;

    #[cfg_attr(
        any(target_env = "gnu", target_env = "musl"),
        link_name = "_x86_64_asm_xsetbv"
    )]
    pub(crate) fn x86_64_asm_xsetbv(xcr: u32, low: u32, high: u32);
}
<|endoftext|>


<commit_before>use crate::cxx_string::CxxString;
use std::ffi::c_void;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
    T: UniquePtrTarget,
{
    repr: *mut c_void,
    ty: PhantomData<T>,
}

impl<T> UniquePtr<T>
where
    T: UniquePtrTarget,
{
    /// Makes a new UniquePtr wrapping a null pointer.
    ///
    /// Matches the behavior of default-constructing a std::unique\_ptr.
    pub fn null() -> Self {
        UniquePtr {
            repr: T::__null(),
            ty: PhantomData,
        }
    }

    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
    pub fn new(value: T) -> Self {
        UniquePtr {
            repr: T::__new(value),
            ty: PhantomData,
        }
    }

    /// Checks whether the UniquePtr does not own an object.
    ///
    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
    pub fn is_null(&self) -> bool {
        let ptr = unsafe { T::__get(self.repr) };
        ptr.is_null()
    }

    /// Returns a reference to the object owned by this UniquePtr if any,
    /// otherwise None.
    pub fn as_ref(&self) -> Option<&T> {
        unsafe { T::__get(self.repr).as_ref() }
    }

    /// Returns a mutable reference to the object owned by this UniquePtr if
    /// any, otherwise None.
    pub fn as_mut(&mut self) -> Option<&mut T> {
        unsafe { (T::__get(self.repr) as *mut T).as_mut() }
    }

    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
    ///
    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
    pub fn into_raw(self) -> *mut T {
        let ptr = unsafe { T::__release(self.repr) };
        mem::forget(self);
        ptr
    }

    /// Constructs a UniquePtr retaking ownership of a pointer previously
    /// obtained from `into_raw`.
    ///
    /// # Safety
    ///
    /// This function is unsafe because improper use may lead to memory
    /// problems. For example a double-free may occur if the function is called
    /// twice on the same raw pointer.
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        UniquePtr {
            repr: T::__raw(raw),
            ty: PhantomData,
        }
    }
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}

impl<T> Drop for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn drop(&mut self) {
        unsafe { T::__drop(self.repr) }
    }
}

impl<T> Deref for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        match self.as_ref() {
            Some(target) => target,
            None => panic!("called deref on a null UniquePtr"),
        }
    }
}

impl<T> DerefMut for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self.as_mut() {
            Some(target) => target,
            None => panic!("called deref_mut on a null UniquePtr"),
        }
    }
}

impl<T> Debug for UniquePtr<T>
where
    T: Debug + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Debug::fmt(value, formatter),
        }
    }
}

impl<T> Display for UniquePtr<T>
where
    T: Display + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Display::fmt(value, formatter),
        }
    }
}

// Methods are private; not intended to be implemented outside of cxxbridge
// codebase.
pub unsafe trait UniquePtrTarget {
    #[doc(hidden)]
    const __NAME: &'static str;
    #[doc(hidden)]
    fn __null() -> *mut c_void;
    #[doc(hidden)]
    fn __new(value: Self) -> *mut c_void
    where
        Self: Sized,
    {
        // Opaque C types do not get this method because they can never exist by
        // value on the Rust side of the bridge.
        let _ = value;
        unreachable!()
    }
    #[doc(hidden)]
    unsafe fn __raw(raw: *mut Self) -> *mut c_void;
    #[doc(hidden)]
    unsafe fn __get(repr: *mut c_void) -> *const Self;
    #[doc(hidden)]
    unsafe fn __release(repr: *mut c_void) -> *mut Self;
    #[doc(hidden)]
    unsafe fn __drop(repr: *mut c_void);
}

extern "C" {
    #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
    fn unique_ptr_std_string_null(this: *mut *mut c_void);
    #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
    fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
    #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
    fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
    fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
    fn unique_ptr_std_string_drop(this: *mut *mut c_void);
}

unsafe impl UniquePtrTarget for CxxString {
    const __NAME: &'static str = "CxxString";
    fn __null() -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unsafe { unique_ptr_std_string_null(&mut repr) }
        repr
    }
    unsafe fn __raw(raw: *mut Self) -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unique_ptr_std_string_raw(&mut repr, raw);
        repr
    }
    unsafe fn __get(repr: *mut c_void) -> *const Self {
        unique_ptr_std_string_get(&repr)
    }
    unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
        unique_ptr_std_string_release(&mut repr)
    }
    unsafe fn __drop(mut repr: *mut c_void) {
        unique_ptr_std_string_drop(&mut repr);
    }
}
<commit_msg>Show UniquePtr target type name in panics<commit_after>use crate::cxx_string::CxxString;
use std::ffi::c_void;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
    T: UniquePtrTarget,
{
    repr: *mut c_void,
    ty: PhantomData<T>,
}

impl<T> UniquePtr<T>
where
    T: UniquePtrTarget,
{
    /// Makes a new UniquePtr wrapping a null pointer.
    ///
    /// Matches the behavior of default-constructing a std::unique\_ptr.
    pub fn null() -> Self {
        UniquePtr {
            repr: T::__null(),
            ty: PhantomData,
        }
    }

    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
    pub fn new(value: T) -> Self {
        UniquePtr {
            repr: T::__new(value),
            ty: PhantomData,
        }
    }

    /// Checks whether the UniquePtr does not own an object.
    ///
    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
    pub fn is_null(&self) -> bool {
        let ptr = unsafe { T::__get(self.repr) };
        ptr.is_null()
    }

    /// Returns a reference to the object owned by this UniquePtr if any,
    /// otherwise None.
    pub fn as_ref(&self) -> Option<&T> {
        unsafe { T::__get(self.repr).as_ref() }
    }

    /// Returns a mutable reference to the object owned by this UniquePtr if
    /// any, otherwise None.
    pub fn as_mut(&mut self) -> Option<&mut T> {
        unsafe { (T::__get(self.repr) as *mut T).as_mut() }
    }

    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
    ///
    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
    pub fn into_raw(self) -> *mut T {
        let ptr = unsafe { T::__release(self.repr) };
        mem::forget(self);
        ptr
    }

    /// Constructs a UniquePtr retaking ownership of a pointer previously
    /// obtained from `into_raw`.
    ///
    /// # Safety
    ///
    /// This function is unsafe because improper use may lead to memory
    /// problems. For example a double-free may occur if the function is called
    /// twice on the same raw pointer.
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        UniquePtr {
            repr: T::__raw(raw),
            ty: PhantomData,
        }
    }
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}

impl<T> Drop for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn drop(&mut self) {
        unsafe { T::__drop(self.repr) }
    }
}

impl<T> Deref for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        match self.as_ref() {
            Some(target) => target,
            None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
        }
    }
}

impl<T> DerefMut for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self.as_mut() {
            Some(target) => target,
            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
        }
    }
}

impl<T> Debug for UniquePtr<T>
where
    T: Debug + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Debug::fmt(value, formatter),
        }
    }
}

impl<T> Display for UniquePtr<T>
where
    T: Display + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Display::fmt(value, formatter),
        }
    }
}

// Methods are private; not intended to be implemented outside of cxxbridge
// codebase.
pub unsafe trait UniquePtrTarget {
    #[doc(hidden)]
    const __NAME: &'static str;
    #[doc(hidden)]
    fn __null() -> *mut c_void;
    #[doc(hidden)]
    fn __new(value: Self) -> *mut c_void
    where
        Self: Sized,
    {
        // Opaque C types do not get this method because they can never exist by
        // value on the Rust side of the bridge.
        let _ = value;
        unreachable!()
    }
    #[doc(hidden)]
    unsafe fn __raw(raw: *mut Self) -> *mut c_void;
    #[doc(hidden)]
    unsafe fn __get(repr: *mut c_void) -> *const Self;
    #[doc(hidden)]
    unsafe fn __release(repr: *mut c_void) -> *mut Self;
    #[doc(hidden)]
    unsafe fn __drop(repr: *mut c_void);
}

extern "C" {
    #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
    fn unique_ptr_std_string_null(this: *mut *mut c_void);
    #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
    fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
    #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
    fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
    fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
    fn unique_ptr_std_string_drop(this: *mut *mut c_void);
}

unsafe impl UniquePtrTarget for CxxString {
    const __NAME: &'static str = "CxxString";
    fn __null() -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unsafe { unique_ptr_std_string_null(&mut repr) }
        repr
    }
    unsafe fn __raw(raw: *mut Self) -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unique_ptr_std_string_raw(&mut repr, raw);
        repr
    }
    unsafe fn __get(repr: *mut c_void) -> *const Self {
        unique_ptr_std_string_get(&repr)
    }
    unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
        unique_ptr_std_string_release(&mut repr)
    }
    unsafe fn __drop(mut repr: *mut c_void) {
        unique_ptr_std_string_drop(&mut repr);
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;

use std::env::args;
use std::io::{self, Write};
use std::process::exit;
use std::thread::sleep;
use std::time::Duration;

use coreutils::extra::OptionalExt;

static HELP: &'static str = r#"
    NAME
        rem - set a count-down.
    SYNOPSIS
        rem [-h | --help] [-m N | --minutes N] [-H N | --hours N] [-s N | --seconds N] [-M N | --milliseconds N] [-n | --len]
    DESCRIPTION
        This utility lets you set a count-down with a progress bar. The options can be given in combination, adding together the durations given.
    OPTIONS
        -h
        --help
            Print this manual page.
        -m N
        --minutes N
            Wait N minutes.
        -H N
        --hours N
            Wait N hours.
        -s N
        --seconds N
            Wait N seconds.
        -M N
        --milliseconds N
            Wait N milliseconds.
        -n
        --len
            Length of the progress bar.
    AUTHOR
        This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 Ticki

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let mut args = args().skip(1);
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    let mut ms = 0u64;
    let mut len = 20;

    // Loop over the arguments.
    loop {
        let arg = if let Some(x) = args.next() {
            x
        } else {
            break;
        };

        match arg.as_str() {
            "-h" | "--help" => {
                // Print help.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
                return;
            },
            "-n" | "--len" => len = args.next().fail("no number after -n.", &mut stderr).parse().try(&mut stderr),
            t => {
                // Find number input.
                let num: u64 = args.next().unwrap_or_else(|| {
                    stderr.write(b"error: incorrectly formatted number.\
                                   Please input a positive integer.").try(&mut stderr);
                    stderr.flush().try(&mut stderr);
                    exit(1);
                }).parse().try(&mut stderr);
                ms += num * match t {
                    "-m" | "--minutes" => 1000 * 60,
                    "-H" | "--hours" => 1000 * 60 * 60,
                    "-s" | "--seconds" => 1000,
                    "-M" | "--milliseconds" => 1,
                    _ => {
                        // Unknown argument.
                        stderr.write(b"error: unknown argument, ").try(&mut stderr);
                        stderr.write(t.as_bytes()).try(&mut stderr);
                        stderr.write(b".\n").try(&mut stderr);
                        stderr.flush().try(&mut stderr);
                        exit(1);
                    },

                };
            },
        }
    }

    // Hide the cursor.
    stdout.write(b"\x1b[?25l").try(&mut stderr);
    // Draw the empty progress bar.
    for _ in 0..len + 1 {
        stdout.write(b" ").try(&mut stderr);
    }
    stdout.write(b"]").try(&mut stderr);

    stdout.write(b"\r[").try(&mut stderr);

    // As time goes, update the progress bar.
    for _ in 0..len {
        stdout.write(b"#").try(&mut stderr);
        stdout.flush().try(&mut stderr);
        // Sleep.
        sleep(Duration::from_millis(ms / len));
    }

    // Show the cursor again.
    stdout.write(b"\x1b[?25h").try(&mut stderr);
    stdout.write(b"\n").try(&mut stderr);
}
<commit_msg>Add --blink flag<commit_after>#![deny(warnings)]

extern crate coreutils;

use std::env::args;
use std::io::{self, Write};
use std::process::exit;
use std::thread::sleep;
use std::time::Duration;

use coreutils::extra::OptionalExt;

static HELP: &'static str = r#"
    NAME
        rem - set a count-down.
    SYNOPSIS
        rem [-h | --help] [-m N | --minutes N] [-H N | --hours N] [-s N | --seconds N] [-M N | --milliseconds N] [-n | --len] [-b | --blink]
    DESCRIPTION
        This utility lets you set a count-down with a progress bar. The options can be given in combination, adding together the durations given.
    OPTIONS
        -h
        --help
            Print this manual page.
        -m N
        --minutes N
            Wait N minutes.
        -H N
        --hours N
            Wait N hours.
        -s N
        --seconds N
            Wait N seconds.
        -M N
        --milliseconds N
            Wait N milliseconds.
        -n
        --len
            Length of the progress bar.
        -b
        --blink
            Blink with a red banner when done.
    AUTHOR
        This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 Ticki

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let mut args = args().skip(1);
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    let mut ms = 0u64;
    let mut len = 20;
    let mut blink = false;

    // Loop over the arguments.
    loop {
        let arg = if let Some(x) = args.next() {
            x
        } else {
            break;
        };

        match arg.as_str() {
            "-h" | "--help" => {
                // Print help.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
                return;
            },
            "-n" | "--len" => len = args.next().fail("no number after -n.", &mut stderr).parse().try(&mut stderr),
            "-b" | "--blink" => blink = true,
            t => {
                // Find number input.
                let num: u64 = args.next().unwrap_or_else(|| {
                    stderr.write(b"error: incorrectly formatted number.\
                                   Please input a positive integer.").try(&mut stderr);
                    stderr.flush().try(&mut stderr);
                    exit(1);
                }).parse().try(&mut stderr);
                ms += num * match t {
                    "-m" | "--minutes" => 1000 * 60,
                    "-H" | "--hours" => 1000 * 60 * 60,
                    "-s" | "--seconds" => 1000,
                    "-M" | "--milliseconds" => 1,
                    _ => {
                        // Unknown argument.
                        stderr.write(b"error: unknown argument, ").try(&mut stderr);
                        stderr.write(t.as_bytes()).try(&mut stderr);
                        stderr.write(b".\n").try(&mut stderr);
                        stderr.flush().try(&mut stderr);
                        exit(1);
                    },

                };
            },
        }
    }

    // Hide the cursor.
    stdout.write(b"\x1b[?25l").try(&mut stderr);
    // Draw the empty progress bar.
    for _ in 0..len + 1 {
        stdout.write(b" ").try(&mut stderr);
    }
    stdout.write(b"]").try(&mut stderr);

    stdout.write(b"\r[").try(&mut stderr);

    // As time goes, update the progress bar.
    for _ in 0..len {
        stdout.write(b"#").try(&mut stderr);
        stdout.flush().try(&mut stderr);
        // Sleep.
        sleep(Duration::from_millis(ms / len));
    }

    if blink {
        for _ in 0..13 {
            stdout.write(b"\x1b[41m").try(&mut stderr);
            stdout.write(b"\x1b[2K").try(&mut stderr);
            stdout.flush().try(&mut stderr);
            sleep(Duration::from_millis(200));

            stdout.write(b"\x1b[0m").try(&mut stderr);
            stdout.write(b"\x1b[2K").try(&mut stderr);
            stdout.flush().try(&mut stderr);
            sleep(Duration::from_millis(200));
        }
    }

    // Show the cursor again.
    stdout.write(b"\x1b[?25h").try(&mut stderr);
    stdout.write(b"\n").try(&mut stderr);
}
<|endoftext|>


<commit_before>//! Connection helper.

extern crate tokio_dns;
extern crate tokio_tcp;

use std::net::SocketAddr;
use std::io::Result as IoResult;

use self::tokio_tcp::TcpStream;

use futures::{future, Future};
use tokio_io::{AsyncRead, AsyncWrite};

use tungstenite::Error;
use tungstenite::client::url_mode;
use tungstenite::handshake::client::Response;

use stream::{NoDelay, PeerAddr};
use super::{WebSocketStream, Request, client_async};

impl NoDelay for TcpStream {
    fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
        TcpStream::set_nodelay(self, nodelay)
    }
}

impl PeerAddr for TcpStream {
    fn peer_addr(&self) -> IoResult<SocketAddr> {
        self.peer_addr()
    }
}

#[cfg(feature="tls")]
mod encryption {
    extern crate native_tls;
    extern crate tokio_tls;

    use self::native_tls::TlsConnector;
    use self::tokio_tls::{TlsConnector as TokioTlsConnector, TlsStream};

    use std::net::SocketAddr;
    use std::io::{Read, Write, Result as IoResult};

    use futures::{future, Future};
    use tokio_io::{AsyncRead, AsyncWrite};

    use tungstenite::Error;
    use tungstenite::stream::Mode;

    use stream::{NoDelay, PeerAddr, Stream as StreamSwitcher};

    /// A stream that might be protected with TLS.
    pub type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>;

    pub type AutoStream<S> = MaybeTlsStream<S>;

    impl<T: Read + Write + NoDelay> NoDelay for TlsStream<T> {
        fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
            self.get_mut().get_mut().set_nodelay(nodelay)
        }
    }

    impl<S: Read + Write + PeerAddr> PeerAddr for TlsStream<S> {
        fn peer_addr(&self) -> IoResult<SocketAddr> {
            self.get_ref().get_ref().peer_addr()
        }
    }

    pub fn wrap_stream<S>(socket: S, domain: String, mode: Mode)
        -> Box<Future<Item=AutoStream<S>, Error=Error> + Send>
    where
        S: 'static + AsyncRead + AsyncWrite + Send,
    {
        match mode {
            Mode::Plain => Box::new(future::ok(StreamSwitcher::Plain(socket))),
            Mode::Tls => {
                Box::new(future::result(TlsConnector::new())
                            .map(TokioTlsConnector::from)
                            .and_then(move |connector| connector.connect(&domain, socket))
                            .map(|s| StreamSwitcher::Tls(s))
                            .map_err(|e| Error::Tls(e)))
            }
        }
    }
}

#[cfg(feature="tls")]
pub use self::encryption::MaybeTlsStream;

#[cfg(not(feature="tls"))]
mod encryption {
    use futures::{future, Future};
    use tokio_io::{AsyncRead, AsyncWrite};

    use tungstenite::Error;
    use tungstenite::stream::Mode;

    pub type AutoStream<S> = S;

    pub fn wrap_stream<S>(socket: S, _domain: String, mode: Mode)
        -> Box<Future<Item=AutoStream<S>, Error=Error> + Send>
    where
        S: 'static + AsyncRead + AsyncWrite + Send,
    {
        match mode {
            Mode::Plain => Box::new(future::ok(socket)),
            Mode::Tls => Box::new(future::err(Error::Url("TLS support not compiled in.".into()))),
        }
    }
}

use self::encryption::{AutoStream, wrap_stream};

/// Get a domain from an URL.
#[inline]
fn domain(request: &Request) -> Result<String, Error> {
    match request.url.host_str() {
        Some(d) => Ok(d.to_string()),
        None => Err(Error::Url("no host name in the url".into())),
    }
}

/// Creates a WebSocket handshake from a request and a stream,
/// upgrading the stream to TLS if required.
pub fn client_async_tls<R, S>(request: R, stream: S)
    -> Box<Future<Item=(WebSocketStream<AutoStream<S>>, Response), Error=Error> + Send>
where
    R: Into<Request<'static>>,
    S: 'static + AsyncRead + AsyncWrite + NoDelay + Send,
{
    let request: Request = request.into();

    let domain = match domain(&request) {
        Ok(domain) => domain,
        Err(err) => return Box::new(future::err(err)),
    };

    // Make sure we check domain and mode first. URL must be valid.
    let mode = match url_mode(&request.url) {
        Ok(m) => m,
        Err(e) => return Box::new(future::err(e.into())),
    };

    Box::new(wrap_stream(stream, domain, mode)
                .and_then(|mut stream| {
                    NoDelay::set_nodelay(&mut stream, true)
                        .map(move |()| stream)
                        .map_err(|e| e.into())
                })
                .and_then(move |stream| client_async(request, stream)))
}

/// Connect to a given URL.
pub fn connect_async<R>(request: R)
    -> Box<Future<Item=(WebSocketStream<AutoStream<TcpStream>>, Response), Error=Error> + Send>
where
    R: Into<Request<'static>>
{
    let request: Request = request.into();

    let domain = match domain(&request) {
        Ok(domain) => domain,
        Err(err) => return Box::new(future::err(err)),
    };
    let port = request.url.port_or_known_default().expect("Bug: port unknown");

    Box::new(tokio_dns::TcpStream::connect((domain.as_str(), port)).map_err(|e| e.into())
                .and_then(move |socket| client_async_tls(request, socket)))
}
<commit_msg>Add `dyn` to silence compiler warnings<commit_after>//! Connection helper.

extern crate tokio_dns;
extern crate tokio_tcp;

use std::net::SocketAddr;
use std::io::Result as IoResult;

use self::tokio_tcp::TcpStream;

use futures::{future, Future};
use tokio_io::{AsyncRead, AsyncWrite};

use tungstenite::Error;
use tungstenite::client::url_mode;
use tungstenite::handshake::client::Response;

use stream::{NoDelay, PeerAddr};
use super::{WebSocketStream, Request, client_async};

impl NoDelay for TcpStream {
    fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
        TcpStream::set_nodelay(self, nodelay)
    }
}

impl PeerAddr for TcpStream {
    fn peer_addr(&self) -> IoResult<SocketAddr> {
        self.peer_addr()
    }
}

#[cfg(feature="tls")]
mod encryption {
    extern crate native_tls;
    extern crate tokio_tls;

    use self::native_tls::TlsConnector;
    use self::tokio_tls::{TlsConnector as TokioTlsConnector, TlsStream};

    use std::net::SocketAddr;
    use std::io::{Read, Write, Result as IoResult};

    use futures::{future, Future};
    use tokio_io::{AsyncRead, AsyncWrite};

    use tungstenite::Error;
    use tungstenite::stream::Mode;

    use stream::{NoDelay, PeerAddr, Stream as StreamSwitcher};

    /// A stream that might be protected with TLS.
    pub type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>;

    pub type AutoStream<S> = MaybeTlsStream<S>;

    impl<T: Read + Write + NoDelay> NoDelay for TlsStream<T> {
        fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
            self.get_mut().get_mut().set_nodelay(nodelay)
        }
    }

    impl<S: Read + Write + PeerAddr> PeerAddr for TlsStream<S> {
        fn peer_addr(&self) -> IoResult<SocketAddr> {
            self.get_ref().get_ref().peer_addr()
        }
    }

    pub fn wrap_stream<S>(socket: S, domain: String, mode: Mode)
        -> Box<dyn Future<Item=AutoStream<S>, Error=Error> + Send>
    where
        S: 'static + AsyncRead + AsyncWrite + Send,
    {
        match mode {
            Mode::Plain => Box::new(future::ok(StreamSwitcher::Plain(socket))),
            Mode::Tls => {
                Box::new(future::result(TlsConnector::new())
                            .map(TokioTlsConnector::from)
                            .and_then(move |connector| connector.connect(&domain, socket))
                            .map(|s| StreamSwitcher::Tls(s))
                            .map_err(|e| Error::Tls(e)))
            }
        }
    }
}

#[cfg(feature="tls")]
pub use self::encryption::MaybeTlsStream;

#[cfg(not(feature="tls"))]
mod encryption {
    use futures::{future, Future};
    use tokio_io::{AsyncRead, AsyncWrite};

    use tungstenite::Error;
    use tungstenite::stream::Mode;

    pub type AutoStream<S> = S;

    pub fn wrap_stream<S>(socket: S, _domain: String, mode: Mode)
        -> Box<Future<Item=AutoStream<S>, Error=Error> + Send>
    where
        S: 'static + AsyncRead + AsyncWrite + Send,
    {
        match mode {
            Mode::Plain => Box::new(future::ok(socket)),
            Mode::Tls => Box::new(future::err(Error::Url("TLS support not compiled in.".into()))),
        }
    }
}

use self::encryption::{AutoStream, wrap_stream};

/// Get a domain from an URL.
#[inline]
fn domain(request: &Request) -> Result<String, Error> {
    match request.url.host_str() {
        Some(d) => Ok(d.to_string()),
        None => Err(Error::Url("no host name in the url".into())),
    }
}

/// Creates a WebSocket handshake from a request and a stream,
/// upgrading the stream to TLS if required.
pub fn client_async_tls<R, S>(request: R, stream: S)
    -> Box<dyn Future<Item=(WebSocketStream<AutoStream<S>>, Response), Error=Error> + Send>
where
    R: Into<Request<'static>>,
    S: 'static + AsyncRead + AsyncWrite + NoDelay + Send,
{
    let request: Request = request.into();

    let domain = match domain(&request) {
        Ok(domain) => domain,
        Err(err) => return Box::new(future::err(err)),
    };

    // Make sure we check domain and mode first. URL must be valid.
    let mode = match url_mode(&request.url) {
        Ok(m) => m,
        Err(e) => return Box::new(future::err(e.into())),
    };

    Box::new(wrap_stream(stream, domain, mode)
                .and_then(|mut stream| {
                    NoDelay::set_nodelay(&mut stream, true)
                        .map(move |()| stream)
                        .map_err(|e| e.into())
                })
                .and_then(move |stream| client_async(request, stream)))
}

/// Connect to a given URL.
pub fn connect_async<R>(request: R)
    -> Box<dyn Future<Item=(WebSocketStream<AutoStream<TcpStream>>, Response), Error=Error> + Send>
where
    R: Into<Request<'static>>
{
    let request: Request = request.into();

    let domain = match domain(&request) {
        Ok(domain) => domain,
        Err(err) => return Box::new(future::err(err)),
    };
    let port = request.url.port_or_known_default().expect("Bug: port unknown");

    Box::new(tokio_dns::TcpStream::connect((domain.as_str(), port)).map_err(|e| e.into())
                .and_then(move |socket| client_async_tls(request, socket)))
}
<|endoftext|>


<commit_before>extern crate pq_sys;
extern crate libc;

mod cursor;

pub use self::cursor::Cursor;

use db_result::DbResult;
use expression::{AsExpression, Expression, NonAggregate};
use expression::predicates::Eq;
use persistable::{Insertable, InsertableColumns};
use query_builder::{AsQuery, Query, QueryFragment, QueryBuilder};
use query_builder::pg::PgQueryBuilder;
use query_dsl::{FilterDsl, LimitDsl};
use query_source::{Table, Column, Queriable};
use result::*;
use self::pq_sys::*;
use std::cell::Cell;
use std::ffi::{CString, CStr};
use std::{str, ptr, result};
use types::{NativeSqlType, ToSql, ValuesToSql};

pub struct Connection {
    internal_connection: *mut PGconn,
    transaction_depth: Cell<i32>,
}

type PrimaryKey<T> = <T as Table>::PrimaryKey;
type PkType<T> = <PrimaryKey<T> as Expression>::SqlType;
type FindPredicate<T, PK> = Eq<PrimaryKey<T>, <PK as AsExpression<PkType<T>>>::Expression>;
type FindOutput<T, PK> = <T as FilterDsl<FindPredicate<T, PK>>>::Output;

impl Connection {
    pub fn establish(database_url: &str) -> ConnectionResult<Connection> {
        let connection_string = try!(CString::new(database_url));
        let connection_ptr = unsafe { PQconnectdb(connection_string.as_ptr()) };
        let connection_status = unsafe { PQstatus(connection_ptr) };
        match connection_status {
            CONNECTION_OK => {
                Ok(Connection {
                    internal_connection: connection_ptr,
                    transaction_depth: Cell::new(0),
                })
            },
            _ => {
                let message = last_error_message(connection_ptr);
                Err(ConnectionError::BadConnection(message))
            }
        }
    }

    pub fn transaction<T, E, F>(&self, f: F) -> TransactionResult<T, E> where
        F: FnOnce() -> result::Result<T, E>,
    {
        try!(self.begin_transaction());
        match f() {
            Ok(value) => {
                try!(self.commit_transaction());
                Ok(value)
            },
            Err(e) => {
                try!(self.rollback_transaction());
                Err(TransactionError::UserReturnedError(e))
            },
        }
    }

    pub fn begin_test_transaction(&self) -> Result<usize> {
        assert_eq!(self.transaction_depth.get(), 0);
        self.begin_transaction()
    }

    pub fn test_transaction<T, E, F>(&self, f: F) -> T where
        F: FnOnce() -> result::Result<T, E>,
    {
        let mut user_result = None;
        let _ = self.transaction::<(), _, _>(|| {
            user_result = f().ok();
            Err(())
        });
        user_result.expect("Transaction did not succeed")
    }

    pub fn execute(&self, query: &str) -> Result<usize> {
        self.execute_inner(query).map(|res| res.rows_affected())
    }

    pub fn query_one<T, U>(&self, source: T) -> Result<Option<U>> where
        T: AsQuery,
        U: Queriable<T::SqlType>,
    {
        self.query_all(source).map(|mut e| e.nth(0))
    }

    pub fn query_all<T, U>(&self, source: T) -> Result<Cursor<T::SqlType, U>> where
        T: AsQuery,
        U: Queriable<T::SqlType>,
    {
        let (sql, params, types) = self.prepare_query(&source.as_query());
        self.exec_sql_params(&sql, &params, &Some(types)).map(Cursor::new)
    }

    pub fn query_sql<T, U>(&self, query: &str) -> Result<Cursor<T, U>> where
        T: NativeSqlType,
        U: Queriable<T>,
    {
        let result = try!(self.execute_inner(query));
        Ok(Cursor::new(result))
    }

    pub fn query_sql_params<T, U, PT, P>(&self, query: &str, params: &P)
        -> Result<Cursor<T, U>> where
        T: NativeSqlType,
        U: Queriable<T>,
        PT: NativeSqlType,
        P: ValuesToSql<PT>,
    {
        let param_data = params.values_to_sql().unwrap();
        let db_result = try!(self.exec_sql_params(query, &param_data, &None));
        Ok(Cursor::new(db_result))
    }

    fn exec_sql_params(&self, query: &str, param_data: &Vec<Option<Vec<u8>>>, param_types: &Option<Vec<u32>>) -> Result<DbResult> {
        let query = try!(CString::new(query));
        let params_pointer = param_data.iter()
            .map(|data| data.as_ref().map(|d| d.as_ptr() as *const libc::c_char)
                 .unwrap_or(ptr::null()))
            .collect::<Vec<_>>();
        let param_types_ptr = param_types.as_ref()
            .map(|types| types.as_ptr())
            .unwrap_or(ptr::null());
        let param_lengths = param_data.iter()
            .map(|data| data.as_ref().map(|d| d.len() as libc::c_int)
                 .unwrap_or(0))
            .collect::<Vec<_>>();
        let param_formats = vec![1; param_data.len()];

        let internal_res = unsafe {
            PQexecParams(
                self.internal_connection,
                query.as_ptr(),
                params_pointer.len() as libc::c_int,
                param_types_ptr,
                params_pointer.as_ptr(),
                param_lengths.as_ptr(),
                param_formats.as_ptr(),
                1,
            )
        };

        DbResult::new(self, internal_res)
    }

    pub fn find<T, U, PK>(&self, source: T, id: PK) -> Result<Option<U>> where
        T: Table + FilterDsl<FindPredicate<T, PK>>,
        FindOutput<T, PK>: LimitDsl,
        U: Queriable<<<FindOutput<T, PK> as LimitDsl>::Output as Query>::SqlType>,
        PK: AsExpression<PkType<T>>,
        <PK as AsExpression<PkType<T>>>::Expression: NonAggregate,
    {
        let pk = source.primary_key();
        self.query_one(source.filter(pk.eq(id)).limit(1))
    }

    pub fn insert<'a, T: 'a, U, Out>(&self, source: &T, records: &'a [U])
        -> Result<Cursor<T::SqlType, Out>> where
        T: Table,
        U: Insertable<'a, T>,
        Out: Queriable<T::SqlType>,
    {
        let (param_placeholders, params, param_types) = self.placeholders_for_insert(records);
        let sql = format!(
            "INSERT INTO {} ({}) VALUES {} RETURNING *",
            source.name(),
            U::columns().names(),
            param_placeholders,
        );
        self.exec_sql_params(&sql, &params, &Some(param_types)).map(Cursor::new)
    }

    pub fn insert_returning_count<'a, T: 'a, U>(&self, source: &T, records: &'a [U])
        -> Result<usize> where
        T: Table,
        U: Insertable<'a, T>,
    {
        let (param_placeholders, params, param_types) = self.placeholders_for_insert(records);
        let sql = format!(
            "INSERT INTO {} ({}) VALUES {}",
            source.name(),
            U::columns().names(),
            &param_placeholders,
        );
        self.exec_sql_params(&sql, &params, &Some(param_types)).map(|r| r.rows_affected())
    }

    pub fn execute_returning_count<T>(&self, source: &T) -> Result<usize> where
        T: QueryFragment,
    {
        let (sql, params, param_types) = self.prepare_query(source);
        self.exec_sql_params(&sql, &params, &Some(param_types))
            .map(|r| r.rows_affected())
    }

    fn prepare_query<T: QueryFragment>(&self, source: &T)
        -> (String, Vec<Option<Vec<u8>>>, Vec<u32>)
    {
        let mut query_builder = PgQueryBuilder::new(self);
        source.to_sql(&mut query_builder).unwrap();
        (query_builder.sql, query_builder.binds, query_builder.bind_types)
    }

    fn execute_inner(&self, query: &str) -> Result<DbResult> {
        self.exec_sql_params(query, &Vec::new(), &None)
    }

    pub fn last_error_message(&self) -> String {
        last_error_message(self.internal_connection)
    }

    fn placeholders_for_insert<'a, T: 'a, U>(&self, records: &'a [U])
        -> (String, Vec<Option<Vec<u8>>>, Vec<u32>) where
        T: Table,
        U: Insertable<'a, T>,
    {
        let mut query_builder = PgQueryBuilder::new(self);
        for (i, record) in records.into_iter().enumerate() {
            if i != 0 {
                query_builder.push_sql(", ");
            }
            query_builder.push_sql("(");
            Expression::to_insert_sql(&record.values(), &mut query_builder).unwrap();
            query_builder.push_sql(")");
        }
        (query_builder.sql, query_builder.binds, query_builder.bind_types)
    }

    fn begin_transaction(&self) -> Result<usize> {
        let transaction_depth = self.transaction_depth.get();
        self.change_transaction_depth(1, if transaction_depth == 0 {
            self.execute("BEGIN")
        } else {
            self.execute(&format!("SAVEPOINT yaqb_savepoint_{}", transaction_depth))
        })
    }

    fn rollback_transaction(&self) -> Result<usize> {
        let transaction_depth = self.transaction_depth.get();
        self.change_transaction_depth(-1, if transaction_depth == 1 {
            self.execute("ROLLBACK")
        } else {
            self.execute(&format!("ROLLBACK TO SAVEPOINT yaqb_savepoint_{}",
                                  transaction_depth - 1))
        })
    }

    fn commit_transaction(&self) -> Result<usize> {
        let transaction_depth = self.transaction_depth.get();
        self.change_transaction_depth(-1, if transaction_depth <= 1 {
            self.execute("COMMIT")
        } else {
            self.execute(&format!("RELEASE SAVEPOINT yaqb_savepoint_{}",
                                  transaction_depth - 1))
        })
    }

    fn change_transaction_depth(&self, by: i32, query: Result<usize>) -> Result<usize> {
        if query.is_ok() {
            self.transaction_depth.set(self.transaction_depth.get() + by);
        }
        query
    }

    pub fn escape_identifier(&self, identifier: &str) -> Result<PgString> {
        let result_ptr = unsafe { PQescapeIdentifier(
            self.internal_connection,
            identifier.as_ptr() as *const libc::c_char,
            identifier.len() as libc::size_t,
        ) };

        if result_ptr.is_null() {
            Err(Error::DatabaseError(last_error_message(self.internal_connection)))
        } else {
            unsafe {
                Ok(PgString::new(result_ptr))
            }
        }
    }
}

fn last_error_message(conn: *const PGconn) -> String {
    unsafe {
        let error_ptr = PQerrorMessage(conn);
        let bytes = CStr::from_ptr(error_ptr).to_bytes();
        str::from_utf8_unchecked(bytes).to_string()
    }
}

impl Drop for Connection {
    fn drop(&mut self) {
        unsafe { PQfinish(self.internal_connection) };
    }
}

pub struct PgString {
    pg_str: *mut libc::c_char,
}

impl PgString {
    unsafe fn new(ptr: *mut libc::c_char) -> Self {
        PgString {
            pg_str: ptr,
        }
    }
}

impl ::std::ops::Deref for PgString {
    type Target = str;

    fn deref(&self) -> &str {
        unsafe {
            let c_string = CStr::from_ptr(self.pg_str);
            str::from_utf8_unchecked(c_string.to_bytes())
        }
    }
}

impl Drop for PgString {
    fn drop(&mut self) {
        unsafe {
            PQfreemem(self.pg_str as *mut libc::c_void)
        }
    }
}
<commit_msg>Correct the type signature of `insert`<commit_after>extern crate pq_sys;
extern crate libc;

mod cursor;

pub use self::cursor::Cursor;

use db_result::DbResult;
use expression::{AsExpression, Expression, NonAggregate};
use expression::predicates::Eq;
use persistable::{Insertable, InsertableColumns};
use query_builder::{AsQuery, Query, QueryFragment, QueryBuilder};
use query_builder::pg::PgQueryBuilder;
use query_dsl::{FilterDsl, LimitDsl};
use query_source::{Table, Column, Queriable};
use result::*;
use self::pq_sys::*;
use std::cell::Cell;
use std::ffi::{CString, CStr};
use std::{str, ptr, result};
use types::{NativeSqlType, ToSql, ValuesToSql};

pub struct Connection {
    internal_connection: *mut PGconn,
    transaction_depth: Cell<i32>,
}

type PrimaryKey<T> = <T as Table>::PrimaryKey;
type PkType<T> = <PrimaryKey<T> as Expression>::SqlType;
type FindPredicate<T, PK> = Eq<PrimaryKey<T>, <PK as AsExpression<PkType<T>>>::Expression>;
type FindOutput<T, PK> = <T as FilterDsl<FindPredicate<T, PK>>>::Output;

impl Connection {
    pub fn establish(database_url: &str) -> ConnectionResult<Connection> {
        let connection_string = try!(CString::new(database_url));
        let connection_ptr = unsafe { PQconnectdb(connection_string.as_ptr()) };
        let connection_status = unsafe { PQstatus(connection_ptr) };
        match connection_status {
            CONNECTION_OK => {
                Ok(Connection {
                    internal_connection: connection_ptr,
                    transaction_depth: Cell::new(0),
                })
            },
            _ => {
                let message = last_error_message(connection_ptr);
                Err(ConnectionError::BadConnection(message))
            }
        }
    }

    pub fn transaction<T, E, F>(&self, f: F) -> TransactionResult<T, E> where
        F: FnOnce() -> result::Result<T, E>,
    {
        try!(self.begin_transaction());
        match f() {
            Ok(value) => {
                try!(self.commit_transaction());
                Ok(value)
            },
            Err(e) => {
                try!(self.rollback_transaction());
                Err(TransactionError::UserReturnedError(e))
            },
        }
    }

    pub fn begin_test_transaction(&self) -> Result<usize> {
        assert_eq!(self.transaction_depth.get(), 0);
        self.begin_transaction()
    }

    pub fn test_transaction<T, E, F>(&self, f: F) -> T where
        F: FnOnce() -> result::Result<T, E>,
    {
        let mut user_result = None;
        let _ = self.transaction::<(), _, _>(|| {
            user_result = f().ok();
            Err(())
        });
        user_result.expect("Transaction did not succeed")
    }

    pub fn execute(&self, query: &str) -> Result<usize> {
        self.execute_inner(query).map(|res| res.rows_affected())
    }

    pub fn query_one<T, U>(&self, source: T) -> Result<Option<U>> where
        T: AsQuery,
        U: Queriable<T::SqlType>,
    {
        self.query_all(source).map(|mut e| e.nth(0))
    }

    pub fn query_all<T, U>(&self, source: T) -> Result<Cursor<T::SqlType, U>> where
        T: AsQuery,
        U: Queriable<T::SqlType>,
    {
        let (sql, params, types) = self.prepare_query(&source.as_query());
        self.exec_sql_params(&sql, &params, &Some(types)).map(Cursor::new)
    }

    pub fn query_sql<T, U>(&self, query: &str) -> Result<Cursor<T, U>> where
        T: NativeSqlType,
        U: Queriable<T>,
    {
        let result = try!(self.execute_inner(query));
        Ok(Cursor::new(result))
    }

    pub fn query_sql_params<T, U, PT, P>(&self, query: &str, params: &P)
        -> Result<Cursor<T, U>> where
        T: NativeSqlType,
        U: Queriable<T>,
        PT: NativeSqlType,
        P: ValuesToSql<PT>,
    {
        let param_data = params.values_to_sql().unwrap();
        let db_result = try!(self.exec_sql_params(query, &param_data, &None));
        Ok(Cursor::new(db_result))
    }

    fn exec_sql_params(&self, query: &str, param_data: &Vec<Option<Vec<u8>>>, param_types: &Option<Vec<u32>>) -> Result<DbResult> {
        let query = try!(CString::new(query));
        let params_pointer = param_data.iter()
            .map(|data| data.as_ref().map(|d| d.as_ptr() as *const libc::c_char)
                 .unwrap_or(ptr::null()))
            .collect::<Vec<_>>();
        let param_types_ptr = param_types.as_ref()
            .map(|types| types.as_ptr())
            .unwrap_or(ptr::null());
        let param_lengths = param_data.iter()
            .map(|data| data.as_ref().map(|d| d.len() as libc::c_int)
                 .unwrap_or(0))
            .collect::<Vec<_>>();
        let param_formats = vec![1; param_data.len()];

        let internal_res = unsafe {
            PQexecParams(
                self.internal_connection,
                query.as_ptr(),
                params_pointer.len() as libc::c_int,
                param_types_ptr,
                params_pointer.as_ptr(),
                param_lengths.as_ptr(),
                param_formats.as_ptr(),
                1,
            )
        };

        DbResult::new(self, internal_res)
    }

    pub fn find<T, U, PK>(&self, source: T, id: PK) -> Result<Option<U>> where
        T: Table + FilterDsl<FindPredicate<T, PK>>,
        FindOutput<T, PK>: LimitDsl,
        U: Queriable<<<FindOutput<T, PK> as LimitDsl>::Output as Query>::SqlType>,
        PK: AsExpression<PkType<T>>,
        <PK as AsExpression<PkType<T>>>::Expression: NonAggregate,
    {
        let pk = source.primary_key();
        self.query_one(source.filter(pk.eq(id)).limit(1))
    }

    pub fn insert<'a, T: 'a, U, Out>(&self, source: &T, records: &'a [U])
        -> Result<Cursor<<T::Star as Expression>::SqlType, Out>> where
        T: Table,
        U: Insertable<'a, T>,
        Out: Queriable<<T::Star as Expression>::SqlType>,
    {
        let (param_placeholders, params, param_types) = self.placeholders_for_insert(records);
        let sql = format!(
            "INSERT INTO {} ({}) VALUES {} RETURNING *",
            source.name(),
            U::columns().names(),
            param_placeholders,
        );
        self.exec_sql_params(&sql, &params, &Some(param_types)).map(Cursor::new)
    }

    pub fn insert_returning_count<'a, T: 'a, U>(&self, source: &T, records: &'a [U])
        -> Result<usize> where
        T: Table,
        U: Insertable<'a, T>,
    {
        let (param_placeholders, params, param_types) = self.placeholders_for_insert(records);
        let sql = format!(
            "INSERT INTO {} ({}) VALUES {}",
            source.name(),
            U::columns().names(),
            &param_placeholders,
        );
        self.exec_sql_params(&sql, &params, &Some(param_types)).map(|r| r.rows_affected())
    }

    pub fn execute_returning_count<T>(&self, source: &T) -> Result<usize> where
        T: QueryFragment,
    {
        let (sql, params, param_types) = self.prepare_query(source);
        self.exec_sql_params(&sql, &params, &Some(param_types))
            .map(|r| r.rows_affected())
    }

    fn prepare_query<T: QueryFragment>(&self, source: &T)
        -> (String, Vec<Option<Vec<u8>>>, Vec<u32>)
    {
        let mut query_builder = PgQueryBuilder::new(self);
        source.to_sql(&mut query_builder).unwrap();
        (query_builder.sql, query_builder.binds, query_builder.bind_types)
    }

    fn execute_inner(&self, query: &str) -> Result<DbResult> {
        self.exec_sql_params(query, &Vec::new(), &None)
    }

    pub fn last_error_message(&self) -> String {
        last_error_message(self.internal_connection)
    }

    fn placeholders_for_insert<'a, T: 'a, U>(&self, records: &'a [U])
        -> (String, Vec<Option<Vec<u8>>>, Vec<u32>) where
        T: Table,
        U: Insertable<'a, T>,
    {
        let mut query_builder = PgQueryBuilder::new(self);
        for (i, record) in records.into_iter().enumerate() {
            if i != 0 {
                query_builder.push_sql(", ");
            }
            query_builder.push_sql("(");
            Expression::to_insert_sql(&record.values(), &mut query_builder).unwrap();
            query_builder.push_sql(")");
        }
        (query_builder.sql, query_builder.binds, query_builder.bind_types)
    }

    fn begin_transaction(&self) -> Result<usize> {
        let transaction_depth = self.transaction_depth.get();
        self.change_transaction_depth(1, if transaction_depth == 0 {
            self.execute("BEGIN")
        } else {
            self.execute(&format!("SAVEPOINT yaqb_savepoint_{}", transaction_depth))
        })
    }

    fn rollback_transaction(&self) -> Result<usize> {
        let transaction_depth = self.transaction_depth.get();
        self.change_transaction_depth(-1, if transaction_depth == 1 {
            self.execute("ROLLBACK")
        } else {
            self.execute(&format!("ROLLBACK TO SAVEPOINT yaqb_savepoint_{}",
                                  transaction_depth - 1))
        })
    }

    fn commit_transaction(&self) -> Result<usize> {
        let transaction_depth = self.transaction_depth.get();
        self.change_transaction_depth(-1, if transaction_depth <= 1 {
            self.execute("COMMIT")
        } else {
            self.execute(&format!("RELEASE SAVEPOINT yaqb_savepoint_{}",
                                  transaction_depth - 1))
        })
    }

    fn change_transaction_depth(&self, by: i32, query: Result<usize>) -> Result<usize> {
        if query.is_ok() {
            self.transaction_depth.set(self.transaction_depth.get() + by);
        }
        query
    }

    pub fn escape_identifier(&self, identifier: &str) -> Result<PgString> {
        let result_ptr = unsafe { PQescapeIdentifier(
            self.internal_connection,
            identifier.as_ptr() as *const libc::c_char,
            identifier.len() as libc::size_t,
        ) };

        if result_ptr.is_null() {
            Err(Error::DatabaseError(last_error_message(self.internal_connection)))
        } else {
            unsafe {
                Ok(PgString::new(result_ptr))
            }
        }
    }
}

fn last_error_message(conn: *const PGconn) -> String {
    unsafe {
        let error_ptr = PQerrorMessage(conn);
        let bytes = CStr::from_ptr(error_ptr).to_bytes();
        str::from_utf8_unchecked(bytes).to_string()
    }
}

impl Drop for Connection {
    fn drop(&mut self) {
        unsafe { PQfinish(self.internal_connection) };
    }
}

pub struct PgString {
    pg_str: *mut libc::c_char,
}

impl PgString {
    unsafe fn new(ptr: *mut libc::c_char) -> Self {
        PgString {
            pg_str: ptr,
        }
    }
}

impl ::std::ops::Deref for PgString {
    type Target = str;

    fn deref(&self) -> &str {
        unsafe {
            let c_string = CStr::from_ptr(self.pg_str);
            str::from_utf8_unchecked(c_string.to_bytes())
        }
    }
}

impl Drop for PgString {
    fn drop(&mut self) {
        unsafe {
            PQfreemem(self.pg_str as *mut libc::c_void)
        }
    }
}
<|endoftext|>


<commit_before>
import ast::ty_mach;
import ast::ty_mach_to_str;
import std::map::new_str_hash;
import util::interner;
import std::int;
import std::uint;
import std::str;

type str_num = uint;

tag binop {
    PLUS;
    MINUS;
    STAR;
    SLASH;
    PERCENT;
    CARET;
    AND;
    OR;
    LSL;
    LSR;
    ASR;
}

tag token {

    /* Expression-operator symbols. */
    EQ;
    LT;
    LE;
    EQEQ;
    NE;
    GE;
    GT;
    ANDAND;
    OROR;
    NOT;
    TILDE;
    BINOP(binop);
    BINOPEQ(binop);

    /* Structural symbols */
    AT;
    DOT;
    ELLIPSIS;
    COMMA;
    SEMI;
    COLON;
    MOD_SEP;
    QUES;
    RARROW;
    SEND;
    RECV;
    LARROW;
    DARROW;
    LPAREN;
    RPAREN;
    LBRACKET;
    RBRACKET;
    LBRACE;
    RBRACE;
    POUND;
    POUND_LBRACE;
    POUND_LT;

    /* Literals */
    LIT_INT(int);
    LIT_UINT(uint);
    LIT_MACH_INT(ty_mach, int);
    LIT_FLOAT(str_num);
    LIT_MACH_FLOAT(ty_mach, str_num);
    LIT_STR(str_num);
    LIT_CHAR(char);
    LIT_BOOL(bool);

    /* Name components */
    IDENT(str_num, bool);
    IDX(int);
    UNDERSCORE;
    BRACEQUOTE(str_num);
    EOF;
}

fn binop_to_str(binop o) -> str {
    alt (o) {
        case (PLUS) { ret "+"; }
        case (MINUS) { ret "-"; }
        case (STAR) { ret "*"; }
        case (SLASH) { ret "/"; }
        case (PERCENT) { ret "%"; }
        case (CARET) { ret "^"; }
        case (AND) { ret "&"; }
        case (OR) { ret "|"; }
        case (LSL) { ret "<<"; }
        case (LSR) { ret ">>"; }
        case (ASR) { ret ">>>"; }
    }
}

fn to_str(lexer::reader r, token t) -> str {
    alt (t) {
        case (EQ) { ret "="; }
        case (LT) { ret "<"; }
        case (LE) { ret "<="; }
        case (EQEQ) { ret "=="; }
        case (NE) { ret "!="; }
        case (GE) { ret ">="; }
        case (GT) { ret ">"; }
        case (NOT) { ret "!"; }
        case (TILDE) { ret "~"; }
        case (OROR) { ret "||"; }
        case (ANDAND) { ret "&&"; }
        case (BINOP(?op)) { ret binop_to_str(op); }
        case (BINOPEQ(?op)) { ret binop_to_str(op) + "="; }
             /* Structural symbols */
        case (AT) { ret "@"; }
        case (DOT) { ret "."; }
        case (ELLIPSIS) { ret "..."; }
        case (COMMA) { ret ","; }
        case (SEMI) { ret ";"; }
        case (COLON) { ret ":"; }
        case (MOD_SEP) { ret "::"; }
        case (QUES) { ret "?"; }
        case (RARROW) { ret "->"; }
        case (SEND) { ret "<|"; }
        case (RECV) { ret "|>"; }
        case (LARROW) { ret "<-"; }
        case (DARROW) { ret "<->"; }
        case (LPAREN) { ret "("; }
        case (RPAREN) { ret ")"; }
        case (LBRACKET) { ret "["; }
        case (RBRACKET) { ret "]"; }
        case (LBRACE) { ret "{"; }
        case (RBRACE) { ret "}"; }
        case (POUND) { ret "#"; }
        case (POUND_LBRACE) { ret "#{"; }
        case (POUND_LT) { ret "#<"; }
             /* Literals */
        case (LIT_INT(?i)) { ret int::to_str(i, 10u); }
        case (LIT_UINT(?u)) { ret uint::to_str(u, 10u); }
        case (LIT_MACH_INT(?tm, ?i)) {
            ret int::to_str(i, 10u) + "_" + ty_mach_to_str(tm);
        }
        case (LIT_MACH_FLOAT(?tm, ?s)) {
            ret interner::get[str](*r.get_interner(), s) + "_" +
                    ty_mach_to_str(tm);
        }
        case (LIT_FLOAT(?s)) { ret interner::get[str](*r.get_interner(), s); }
        case (LIT_STR(?s)) { // FIXME: escape.
            ret "\"" + interner::get[str](*r.get_interner(), s) + "\"";
        }
        case (LIT_CHAR(?c)) {
            // FIXME: escape.
            auto tmp = "'";
            str::push_char(tmp, c);
            str::push_byte(tmp, '\'' as u8);
            ret tmp;
        }
        case (LIT_BOOL(?b)) { if (b) { ret "true"; } else { ret "false"; } }
             /* Name components */
        case (IDENT(?s, _)) { ret interner::get[str](*r.get_interner(), s); }
        case (IDX(?i)) { ret "_" + int::to_str(i, 10u); }
        case (UNDERSCORE) { ret "_"; }
        case (BRACEQUOTE(_)) { ret "<bracequote>"; }
        case (EOF) { ret "<eof>"; }
    }
}

pred can_begin_expr(token t) -> bool {
    alt (t) {
        case (LPAREN) { true }
        case (LBRACE) { true }
        case (IDENT(_,_)) { true }
        case (UNDERSCORE) { true }
        case (TILDE) { true }
        case (LIT_INT(_)) { true }
        case (LIT_UINT(_)) { true }
        case (LIT_MACH_INT(_,_)) { true }
        case (LIT_FLOAT(_)) { true }
        case (LIT_MACH_FLOAT(_,_)) { true }
        case (LIT_STR(_)) { true }
        case (LIT_CHAR(_)) { true }
        case (POUND) { true }
        case (AT) { true }
        case (_) { false }
    }
}
// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Add some missing cases to token::can_begin_expr<commit_after>
import ast::ty_mach;
import ast::ty_mach_to_str;
import std::map::new_str_hash;
import util::interner;
import std::int;
import std::uint;
import std::str;

type str_num = uint;

tag binop {
    PLUS;
    MINUS;
    STAR;
    SLASH;
    PERCENT;
    CARET;
    AND;
    OR;
    LSL;
    LSR;
    ASR;
}

tag token {

    /* Expression-operator symbols. */
    EQ;
    LT;
    LE;
    EQEQ;
    NE;
    GE;
    GT;
    ANDAND;
    OROR;
    NOT;
    TILDE;
    BINOP(binop);
    BINOPEQ(binop);

    /* Structural symbols */
    AT;
    DOT;
    ELLIPSIS;
    COMMA;
    SEMI;
    COLON;
    MOD_SEP;
    QUES;
    RARROW;
    SEND;
    RECV;
    LARROW;
    DARROW;
    LPAREN;
    RPAREN;
    LBRACKET;
    RBRACKET;
    LBRACE;
    RBRACE;
    POUND;
    POUND_LBRACE;
    POUND_LT;

    /* Literals */
    LIT_INT(int);
    LIT_UINT(uint);
    LIT_MACH_INT(ty_mach, int);
    LIT_FLOAT(str_num);
    LIT_MACH_FLOAT(ty_mach, str_num);
    LIT_STR(str_num);
    LIT_CHAR(char);
    LIT_BOOL(bool);

    /* Name components */
    IDENT(str_num, bool);
    IDX(int);
    UNDERSCORE;
    BRACEQUOTE(str_num);
    EOF;
}

fn binop_to_str(binop o) -> str {
    alt (o) {
        case (PLUS) { ret "+"; }
        case (MINUS) { ret "-"; }
        case (STAR) { ret "*"; }
        case (SLASH) { ret "/"; }
        case (PERCENT) { ret "%"; }
        case (CARET) { ret "^"; }
        case (AND) { ret "&"; }
        case (OR) { ret "|"; }
        case (LSL) { ret "<<"; }
        case (LSR) { ret ">>"; }
        case (ASR) { ret ">>>"; }
    }
}

fn to_str(lexer::reader r, token t) -> str {
    alt (t) {
        case (EQ) { ret "="; }
        case (LT) { ret "<"; }
        case (LE) { ret "<="; }
        case (EQEQ) { ret "=="; }
        case (NE) { ret "!="; }
        case (GE) { ret ">="; }
        case (GT) { ret ">"; }
        case (NOT) { ret "!"; }
        case (TILDE) { ret "~"; }
        case (OROR) { ret "||"; }
        case (ANDAND) { ret "&&"; }
        case (BINOP(?op)) { ret binop_to_str(op); }
        case (BINOPEQ(?op)) { ret binop_to_str(op) + "="; }
             /* Structural symbols */
        case (AT) { ret "@"; }
        case (DOT) { ret "."; }
        case (ELLIPSIS) { ret "..."; }
        case (COMMA) { ret ","; }
        case (SEMI) { ret ";"; }
        case (COLON) { ret ":"; }
        case (MOD_SEP) { ret "::"; }
        case (QUES) { ret "?"; }
        case (RARROW) { ret "->"; }
        case (SEND) { ret "<|"; }
        case (RECV) { ret "|>"; }
        case (LARROW) { ret "<-"; }
        case (DARROW) { ret "<->"; }
        case (LPAREN) { ret "("; }
        case (RPAREN) { ret ")"; }
        case (LBRACKET) { ret "["; }
        case (RBRACKET) { ret "]"; }
        case (LBRACE) { ret "{"; }
        case (RBRACE) { ret "}"; }
        case (POUND) { ret "#"; }
        case (POUND_LBRACE) { ret "#{"; }
        case (POUND_LT) { ret "#<"; }
             /* Literals */
        case (LIT_INT(?i)) { ret int::to_str(i, 10u); }
        case (LIT_UINT(?u)) { ret uint::to_str(u, 10u); }
        case (LIT_MACH_INT(?tm, ?i)) {
            ret int::to_str(i, 10u) + "_" + ty_mach_to_str(tm);
        }
        case (LIT_MACH_FLOAT(?tm, ?s)) {
            ret interner::get[str](*r.get_interner(), s) + "_" +
                    ty_mach_to_str(tm);
        }
        case (LIT_FLOAT(?s)) { ret interner::get[str](*r.get_interner(), s); }
        case (LIT_STR(?s)) { // FIXME: escape.
            ret "\"" + interner::get[str](*r.get_interner(), s) + "\"";
        }
        case (LIT_CHAR(?c)) {
            // FIXME: escape.
            auto tmp = "'";
            str::push_char(tmp, c);
            str::push_byte(tmp, '\'' as u8);
            ret tmp;
        }
        case (LIT_BOOL(?b)) { if (b) { ret "true"; } else { ret "false"; } }
             /* Name components */
        case (IDENT(?s, _)) { ret interner::get[str](*r.get_interner(), s); }
        case (IDX(?i)) { ret "_" + int::to_str(i, 10u); }
        case (UNDERSCORE) { ret "_"; }
        case (BRACEQUOTE(_)) { ret "<bracequote>"; }
        case (EOF) { ret "<eof>"; }
    }
}

pred can_begin_expr(token t) -> bool {
    alt (t) {
        case (LPAREN) { true }
        case (LBRACE) { true }
        case (LBRACKET) { true }
        case (IDENT(_,_)) { true }
        case (UNDERSCORE) { true }
        case (TILDE) { true }
        case (LIT_INT(_)) { true }
        case (LIT_UINT(_)) { true }
        case (LIT_MACH_INT(_,_)) { true }
        case (LIT_FLOAT(_)) { true }
        case (LIT_MACH_FLOAT(_,_)) { true }
        case (LIT_STR(_)) { true }
        case (LIT_CHAR(_)) { true }
        case (POUND) { true }
        case (AT) { true }
        case (NOT) { true }
        case (BINOP(MINUS)) { true }
        case (BINOP(STAR)) { true }
        case (_) { false }
    }
}
// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before><commit_msg>Deprecate some old obj stuff<commit_after><|endoftext|>