<commit_before>use analysis::namespaces;
use codegen::general::{self, version_condition, version_condition_string};
use config::gobjects::GObject;
use env::Env;
use file_saver;
use library::*;
use std::cmp;
use std::io::prelude::*;
use std::io::Result;
use std::path::Path;
use traits::*;

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    let path = root_path.join("flags.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        let configs: Vec<&GObject> = env.config
            .objects
            .values()
            .filter(|c| {
                c.status.need_generate() &&
                    c.type_id.map_or(false, |tid| tid.ns_id == namespaces::MAIN)
            })
            .collect();

        let mut has_get_type = false;
        for config in &configs {
            if let Type::Bitfield(ref flags) = *env.library.type_(config.type_id.unwrap()) {
                if flags.glib_get_type.is_some() {
                    has_get_type = true;
                    break;
                }
            }
        }

        try!(general::start_comments(w, &env.config));
        try!(writeln!(w, ""));
        try!(writeln!(w, "use ffi;"));
        if env.namespaces.glib_ns_id == namespaces::MAIN {
            if has_get_type {
                try!(writeln!(w, "use Type;"));
                try!(writeln!(w, "use StaticType;"));
                try!(writeln!(w, "use Value;"));
                try!(writeln!(w, "use SetValue;"));
                try!(writeln!(w, "use FromValue;"));
                try!(writeln!(w, "use FromValueOptional;"));
                try!(writeln!(w, "use gobject_ffi;"));
            }
            try!(writeln!(w, "use translate::*;"));
        } else {
            if has_get_type {
                try!(writeln!(w, "use glib::Type;"));
                try!(writeln!(w, "use glib::StaticType;"));
                try!(writeln!(
                    w,
                    "use glib::value::{{Value, SetValue, FromValue, FromValueOptional}};"
                ));
                try!(writeln!(w, "use gobject_ffi;"));
            }
            try!(writeln!(w, "use glib::translate::*;"));
        }
        try!(writeln!(w, ""));

        let mut first = true;
        for config in &configs {
            if let Type::Bitfield(ref flags) = *env.library.type_(config.type_id.unwrap()) {
                if first {
                    mod_rs.push("\nmod flags;".into());
                    first = false;
                }
                if let Some(cfg) = version_condition_string(env, flags.version, false, 0) {
                    mod_rs.push(cfg);
                }
                mod_rs.push(format!("pub use self::flags::{};", flags.name));
                try!(generate_flags(env, w, mod_rs, flags, config));
            }
        }

        Ok(())
    });
}

fn generate_flags(
    env: &Env,
    w: &mut Write,
    mod_rs: &mut Vec<String>,
    flags: &Bitfield,
    config: &GObject,
) -> Result<()> {
    try!(version_condition(w, env, flags.version, false, 0));
    try!(writeln!(w, "bitflags! {{"));
    try!(writeln!(w, "    pub struct {}: u32 {{", flags.name));
    for member in &flags.members {
        let member_config = config.members.matched(&member.name);
        let ignore = member_config.iter().any(|m| m.ignore);
        if ignore {
            continue;
        }

        let name = member.name.to_uppercase();
        let val: i64 = member.value.parse().unwrap();
        let version = member_config.iter().filter_map(|m| m.version).next();
        try!(version_condition(w, env, version, false, 2));
        try!(writeln!(w, "\t\tconst {} = {};", name, val as u32));
        if let Some(cfg) =
            version_condition_string(env, cmp::max(flags.version, version), false, 0)
        {
            mod_rs.push(cfg);
        }
    }

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

    try!(version_condition(w, env, flags.version, false, 0));
    try!(writeln!(
        w,
        "#[doc(hidden)]
impl ToGlib for {name} {{
    type GlibType = ffi::{ffi_name};

    fn to_glib(&self) -> ffi::{ffi_name} {{
        ffi::{ffi_name}::from_bits_truncate(self.bits())
    }}
}}
",
        name = flags.name,
        ffi_name = flags.c_type
    ));

    let assert = if env.config.generate_safety_asserts {
        "skip_assert_initialized!();\n\t\t"
    } else {
        ""
    };

    try!(version_condition(w, env, flags.version, false, 0));
    try!(writeln!(
        w,
        "#[doc(hidden)]
impl FromGlib<ffi::{ffi_name}> for {name} {{
    fn from_glib(value: ffi::{ffi_name}) -> {name} {{
        {assert}{name}::from_bits_truncate(value.bits())
    }}
}}
",
        name = flags.name,
        ffi_name = flags.c_type,
        assert = assert
    ));

    if let Some(ref get_type) = flags.glib_get_type {
        try!(version_condition(w, env, flags.version, false, 0));
        try!(writeln!(
            w,
            "impl StaticType for {name} {{
    fn static_type() -> Type {{
        unsafe {{ from_glib(ffi::{get_type}()) }}
    }}
}}",
            name = flags.name,
            get_type = get_type
        ));
        try!(writeln!(w, ""));

        try!(version_condition(w, env, flags.version, false, 0));
        try!(writeln!(
            w,
            "impl<'a> FromValueOptional<'a> for {name} {{
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {{
        Some(FromValue::from_value(value))
    }}
}}",
            name = flags.name,
        ));
        try!(writeln!(w, ""));

        try!(version_condition(w, env, flags.version, false, 0));
        try!(writeln!(
            w,
            "impl<'a> FromValue<'a> for {name} {{
    unsafe fn from_value(value: &Value) -> Self {{
        from_glib(ffi::{ffi_name}::from_bits_truncate(gobject_ffi::g_value_get_flags(value.to_glib_none().0)))
    }}
}}",
            name = flags.name,
            ffi_name = flags.c_type,
        ));
        try!(writeln!(w, ""));

        try!(version_condition(w, env, flags.version, false, 0));
        try!(writeln!(
            w,
            "impl SetValue for {name} {{
    unsafe fn set_value(value: &mut Value, this: &Self) {{
        gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib().bits())
    }}
}}",
            name = flags.name,
        ));

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

    Ok(())
}
<commit_msg>Remove forgotten version conditions for flag elements in mod.rs<commit_after>use analysis::namespaces;
use codegen::general::{self, version_condition, version_condition_string};
use config::gobjects::GObject;
use env::Env;
use file_saver;
use library::*;
use std::io::prelude::*;
use std::io::Result;
use std::path::Path;
use traits::*;

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    let path = root_path.join("flags.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        let configs: Vec<&GObject> = env.config
            .objects
            .values()
            .filter(|c| {
                c.status.need_generate() &&
                    c.type_id.map_or(false, |tid| tid.ns_id == namespaces::MAIN)
            })
            .collect();

        let mut has_get_type = false;
        for config in &configs {
            if let Type::Bitfield(ref flags) = *env.library.type_(config.type_id.unwrap()) {
                if flags.glib_get_type.is_some() {
                    has_get_type = true;
                    break;
                }
            }
        }

        try!(general::start_comments(w, &env.config));
        try!(writeln!(w, ""));
        try!(writeln!(w, "use ffi;"));
        if env.namespaces.glib_ns_id == namespaces::MAIN {
            if has_get_type {
                try!(writeln!(w, "use Type;"));
                try!(writeln!(w, "use StaticType;"));
                try!(writeln!(w, "use Value;"));
                try!(writeln!(w, "use SetValue;"));
                try!(writeln!(w, "use FromValue;"));
                try!(writeln!(w, "use FromValueOptional;"));
                try!(writeln!(w, "use gobject_ffi;"));
            }
            try!(writeln!(w, "use translate::*;"));
        } else {
            if has_get_type {
                try!(writeln!(w, "use glib::Type;"));
                try!(writeln!(w, "use glib::StaticType;"));
                try!(writeln!(
                    w,
                    "use glib::value::{{Value, SetValue, FromValue, FromValueOptional}};"
                ));
                try!(writeln!(w, "use gobject_ffi;"));
            }
            try!(writeln!(w, "use glib::translate::*;"));
        }
        try!(writeln!(w, ""));

        let mut first = true;
        for config in &configs {
            if let Type::Bitfield(ref flags) = *env.library.type_(config.type_id.unwrap()) {
                if first {
                    mod_rs.push("\nmod flags;".into());
                    first = false;
                }
                if let Some(cfg) = version_condition_string(env, flags.version, false, 0) {
                    mod_rs.push(cfg);
                }
                mod_rs.push(format!("pub use self::flags::{};", flags.name));
                try!(generate_flags(env, w, flags, config));
            }
        }

        Ok(())
    });
}

fn generate_flags(
    env: &Env,
    w: &mut Write,
    flags: &Bitfield,
    config: &GObject,
) -> Result<()> {
    try!(version_condition(w, env, flags.version, false, 0));
    try!(writeln!(w, "bitflags! {{"));
    try!(writeln!(w, "    pub struct {}: u32 {{", flags.name));
    for member in &flags.members {
        let member_config = config.members.matched(&member.name);
        let ignore = member_config.iter().any(|m| m.ignore);
        if ignore {
            continue;
        }

        let name = member.name.to_uppercase();
        let val: i64 = member.value.parse().unwrap();
        let version = member_config.iter().filter_map(|m| m.version).next();
        try!(version_condition(w, env, version, false, 2));
        try!(writeln!(w, "\t\tconst {} = {};", name, val as u32));
    }

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

    try!(version_condition(w, env, flags.version, false, 0));
    try!(writeln!(
        w,
        "#[doc(hidden)]
impl ToGlib for {name} {{
    type GlibType = ffi::{ffi_name};

    fn to_glib(&self) -> ffi::{ffi_name} {{
        ffi::{ffi_name}::from_bits_truncate(self.bits())
    }}
}}
",
        name = flags.name,
        ffi_name = flags.c_type
    ));

    let assert = if env.config.generate_safety_asserts {
        "skip_assert_initialized!();\n\t\t"
    } else {
        ""
    };

    try!(version_condition(w, env, flags.version, false, 0));
    try!(writeln!(
        w,
        "#[doc(hidden)]
impl FromGlib<ffi::{ffi_name}> for {name} {{
    fn from_glib(value: ffi::{ffi_name}) -> {name} {{
        {assert}{name}::from_bits_truncate(value.bits())
    }}
}}
",
        name = flags.name,
        ffi_name = flags.c_type,
        assert = assert
    ));

    if let Some(ref get_type) = flags.glib_get_type {
        try!(version_condition(w, env, flags.version, false, 0));
        try!(writeln!(
            w,
            "impl StaticType for {name} {{
    fn static_type() -> Type {{
        unsafe {{ from_glib(ffi::{get_type}()) }}
    }}
}}",
            name = flags.name,
            get_type = get_type
        ));
        try!(writeln!(w, ""));

        try!(version_condition(w, env, flags.version, false, 0));
        try!(writeln!(
            w,
            "impl<'a> FromValueOptional<'a> for {name} {{
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {{
        Some(FromValue::from_value(value))
    }}
}}",
            name = flags.name,
        ));
        try!(writeln!(w, ""));

        try!(version_condition(w, env, flags.version, false, 0));
        try!(writeln!(
            w,
            "impl<'a> FromValue<'a> for {name} {{
    unsafe fn from_value(value: &Value) -> Self {{
        from_glib(ffi::{ffi_name}::from_bits_truncate(gobject_ffi::g_value_get_flags(value.to_glib_none().0)))
    }}
}}",
            name = flags.name,
            ffi_name = flags.c_type,
        ));
        try!(writeln!(w, ""));

        try!(version_condition(w, env, flags.version, false, 0));
        try!(writeln!(
            w,
            "impl SetValue for {name} {{
    unsafe fn set_value(value: &mut Value, this: &Self) {{
        gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib().bits())
    }}
}}",
            name = flags.name,
        ));

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

    Ok(())
}
<|endoftext|>


<commit_before>extern crate parse_collada;

use parse_collada::*;

#[test]
fn collada_element() {
    static DOCUMENT: &'static str =
r#"<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
</COLLADA>
"#;

    let collada = Collada::from_str(DOCUMENT).unwrap();
    assert_eq!(collada.version, "1.4.1");
}

#[test]
fn collada_element_whitespace() {
    static DOCUMENT: &'static str =
r#"
<?xml version="1.0" encoding="utf-8"?>

<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">

</COLLADA>

"#;

    let collada = Collada::from_str(DOCUMENT).unwrap();
    assert_eq!(collada.version, "1.4.1");
}

#[test]
fn collada_element_missing_version() {
    static DOCUMENT: &'static str =
r#"<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema">
</COLLADA>
"#;

    let error = Collada::from_str(DOCUMENT).unwrap_err();
    assert_eq!(TextPosition { row: 1, column: 0 }, error.position());
    assert_eq!(&ErrorKind::MissingAttribute { element: "COLLADA".into(), attribute: "version".into() }, error.kind());
}

#[test]
fn collada_element_unexpected_attrib() {
    static DOCUMENT: &'static str =
r#"<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" foo="bar">
</COLLADA>
"#;

    let error = Collada::from_str(DOCUMENT).unwrap_err();
    assert_eq!(TextPosition { row: 1, column: 0 }, error.position());
    assert_eq!(&ErrorKind::UnexpectedAttribute { element: "COLLADA".into(), attribute: "foo".into(), expected: COLLADA_ATTRIBS }, error.kind());
}
<commit_msg>Add tests for missing <?xml>, presence of <!DOCTYPE><commit_after>extern crate parse_collada;

use parse_collada::*;

#[test]
fn collada_element() {
    static DOCUMENT: &'static str =
r#"<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
</COLLADA>
"#;

    let collada = Collada::from_str(DOCUMENT).unwrap();
    assert_eq!(collada.version, "1.4.1");
}

#[test]
fn collada_element_whitespace() {
    static DOCUMENT: &'static str =
r#"
<?xml version="1.0" encoding="utf-8"?>

<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">

</COLLADA>

"#;

    let collada = Collada::from_str(DOCUMENT).unwrap();
    assert_eq!(collada.version, "1.4.1");
}

#[test]
fn no_xml_decl() {
    static DOCUMENT: &'static str =
r#"<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
</COLLADA>
"#;

    let collada = Collada::from_str(DOCUMENT).unwrap();
    assert_eq!(collada.version, "1.4.1");
}

#[test]
fn doctype() {
    static DOCUMENT: &'static str =
r#"<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note SYSTEM "Note.dtd">
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
</COLLADA>
"#;

    let collada = Collada::from_str(DOCUMENT).unwrap();
    assert_eq!(collada.version, "1.4.1");
}

#[test]
fn collada_element_missing_version() {
    static DOCUMENT: &'static str =
r#"<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema">
</COLLADA>
"#;

    let error = Collada::from_str(DOCUMENT).unwrap_err();
    assert_eq!(TextPosition { row: 1, column: 0 }, error.position());
    assert_eq!(&ErrorKind::MissingAttribute { element: "COLLADA".into(), attribute: "version".into() }, error.kind());
}

#[test]
fn collada_element_unexpected_attrib() {
    static DOCUMENT: &'static str =
r#"<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" foo="bar">
</COLLADA>
"#;

    let error = Collada::from_str(DOCUMENT).unwrap_err();
    assert_eq!(TextPosition { row: 1, column: 0 }, error.position());
    assert_eq!(&ErrorKind::UnexpectedAttribute { element: "COLLADA".into(), attribute: "foo".into(), expected: COLLADA_ATTRIBS }, error.kind());
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate comm;

use comm::address::Address;
use comm::client;
use comm::client::{Client, Event, Task, TaskSender};
use comm::network::Network;
use comm::node::{Node, UdpNode};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::sync::mpsc;
use std::thread;

#[no_mangle]
pub extern "C" fn comm_initialize() {
    env_logger::init().expect("Couldn't initialize logger");
}

#[no_mangle]
pub extern "C" fn comm_address_for_content(content: *const c_char) -> *const Address {
    let c_str: &CStr = unsafe { CStr::from_ptr(content) };
    let address = Address::for_content(c_str.to_str().unwrap());
    Box::into_raw(Box::new(address))
}

#[no_mangle]
pub extern "C" fn comm_address_from_str(string: *const c_char) -> *const Address {
    let c_str: &CStr = unsafe { CStr::from_ptr(string) };
    let address = Address::from_str(c_str.to_str().unwrap());
    Box::into_raw(Box::new(address))
}

#[no_mangle]
pub extern "C" fn comm_address_null() -> *const Address {
    Box::into_raw(Box::new(Address::null()))
}

#[no_mangle]
pub extern "C" fn comm_address_copy(address: *const Address) -> *const Address {
    let copy = unsafe { *address }.clone();
    Box::into_raw(Box::new(copy))
}

#[no_mangle]
pub extern "C" fn comm_address_to_str(address: *const Address) -> *const c_char {
    let string = unsafe { *address }.to_str();
    let string = CString::new(string).unwrap();
    let pointer = string.as_ptr();
    std::mem::forget(string);
    pointer
}

#[no_mangle]
pub unsafe extern "C" fn comm_address_destroy(address: *mut Address) {
    let _ = Box::from_raw(address);
}

#[no_mangle]
pub extern "C" fn comm_udp_node_new(
    address: *const Address, socket_address: *const c_char) -> *const UdpNode {
    let socket_address: &CStr = unsafe { CStr::from_ptr(socket_address) };
    let node = UdpNode::new(unsafe { *address }, socket_address.to_str().unwrap());
    Box::into_raw(Box::new(node))
}

#[no_mangle]
pub unsafe extern "C" fn comm_udp_node_destroy(udp_node: *mut UdpNode) {
    let _ = Box::from_raw(udp_node);
}

#[no_mangle]
pub extern "C" fn comm_network_new(
    self_address: *mut Address, host: *const c_char, routers: *mut *mut UdpNode, routers_count: usize) -> *mut Network {
    let self_address = unsafe { *self_address };
    let host: &CStr = unsafe { CStr::from_ptr(host) };
    let routers = unsafe { Vec::from_raw_parts(routers, routers_count, routers_count) };
    let routers: Vec<Box<Node>> = routers.into_iter().map(|r| unsafe {
        Box::from_raw(r) as Box<Node>
    }).collect();
    let network = Network::new(self_address, host.to_str().unwrap(), routers);
    Box::into_raw(Box::new(network))
}

#[no_mangle]
pub unsafe extern "C" fn comm_network_run(network: *mut Network) {
    let network = Box::from_raw(network);
    network.run();
}

#[no_mangle]
pub unsafe extern "C" fn comm_network_destroy(network: *mut Network) {
    let _ = Box::from_raw(network);
}

#[no_mangle]
pub extern "C" fn comm_text_message_new(sender: *mut Address, text: *const c_char) -> *const client::messages::TextMessage {
    let sender = unsafe { *Box::from_raw(sender) };
    let c_str: &CStr = unsafe { CStr::from_ptr(text) };
    let message_text = c_str.to_str().unwrap().to_string();

    Box::into_raw(Box::new(client::messages::TextMessage::new(sender, message_text)))
}

#[no_mangle]
pub extern "C" fn comm_text_message_text(text_message: *const client::messages::TextMessage) -> *const c_char {
    let text_message = unsafe { &*text_message };
    let string = CString::new(text_message.text.clone()).unwrap();
    let pointer = string.as_ptr();
    std::mem::forget(string);
    pointer
}

#[no_mangle]
pub extern "C" fn comm_text_message_sender(text_message: *const client::messages::TextMessage) -> *const Address {
    let text_message = unsafe { &*text_message };
    Box::into_raw(Box::new(text_message.sender))
}

#[no_mangle]
pub unsafe extern "C" fn comm_client_new(address: *const Address) -> *mut Client {
    Box::into_raw(Box::new(Client::new(*address)))
}

#[no_mangle]
pub unsafe extern "C" fn comm_client_run(
    client: *mut Client, network: *mut Network) -> *mut TaskSender {
    let client = Box::from_raw(client);
    let network = *Box::from_raw(network);
    Box::into_raw(Box::new(client.run(network)))
}

#[no_mangle]
pub extern "C" fn comm_client_register_text_message_received_callback(
    client: *mut Client, callback: extern fn(*const client::messages::TextMessage) -> ()) {

    let client = unsafe { &mut *client };
    let (event_sender, events) = mpsc::channel();
    client.register_event_listener(event_sender);

    thread::spawn(move || {
        for event in events {
            if let Event::ReceivedTextMessage(text_message) = event {
                callback(Box::into_raw(Box::new(text_message)));
            }
        }
    });
}

#[no_mangle]
pub extern "C" fn comm_client_commands_send_text_message(
    commands: *mut TaskSender,
    recipient: *mut Address,
    text_message: *mut client::messages::TextMessage) {
    let commands = unsafe { &mut *commands };
    let recipient = unsafe { *Box::from_raw(recipient) };
    let text_message = unsafe { *Box::from_raw(text_message) };
    commands.send(Task::ScheduleMessageDelivery(recipient, text_message)).unwrap();
}

#[no_mangle]
pub unsafe extern "C" fn comm_client_destroy(client: *mut Client) {
    let _ = Box::from_raw(client);
}
<commit_msg>Add TODOs about string leaking<commit_after>extern crate env_logger;
extern crate comm;

use comm::address::Address;
use comm::client;
use comm::client::{Client, Event, Task, TaskSender};
use comm::network::Network;
use comm::node::{Node, UdpNode};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::sync::mpsc;
use std::thread;

#[no_mangle]
pub extern "C" fn comm_initialize() {
    env_logger::init().expect("Couldn't initialize logger");
}

#[no_mangle]
pub extern "C" fn comm_address_for_content(content: *const c_char) -> *const Address {
    let c_str: &CStr = unsafe { CStr::from_ptr(content) };
    let address = Address::for_content(c_str.to_str().unwrap());
    Box::into_raw(Box::new(address))
}

#[no_mangle]
pub extern "C" fn comm_address_from_str(string: *const c_char) -> *const Address {
    let c_str: &CStr = unsafe { CStr::from_ptr(string) };
    let address = Address::from_str(c_str.to_str().unwrap());
    Box::into_raw(Box::new(address))
}

#[no_mangle]
pub extern "C" fn comm_address_null() -> *const Address {
    Box::into_raw(Box::new(Address::null()))
}

#[no_mangle]
pub extern "C" fn comm_address_copy(address: *const Address) -> *const Address {
    let copy = unsafe { *address }.clone();
    Box::into_raw(Box::new(copy))
}

// TODO: impl API to clean up leaked strings
#[no_mangle]
pub extern "C" fn comm_address_to_str(address: *const Address) -> *const c_char {
    let string = unsafe { *address }.to_str();
    let string = CString::new(string).unwrap();
    let pointer = string.as_ptr();
    std::mem::forget(string);
    pointer
}

#[no_mangle]
pub unsafe extern "C" fn comm_address_destroy(address: *mut Address) {
    let _ = Box::from_raw(address);
}

#[no_mangle]
pub extern "C" fn comm_udp_node_new(
    address: *const Address, socket_address: *const c_char) -> *const UdpNode {
    let socket_address: &CStr = unsafe { CStr::from_ptr(socket_address) };
    let node = UdpNode::new(unsafe { *address }, socket_address.to_str().unwrap());
    Box::into_raw(Box::new(node))
}

#[no_mangle]
pub unsafe extern "C" fn comm_udp_node_destroy(udp_node: *mut UdpNode) {
    let _ = Box::from_raw(udp_node);
}

#[no_mangle]
pub extern "C" fn comm_network_new(
    self_address: *mut Address, host: *const c_char, routers: *mut *mut UdpNode, routers_count: usize) -> *mut Network {
    let self_address = unsafe { *self_address };
    let host: &CStr = unsafe { CStr::from_ptr(host) };
    let routers = unsafe { Vec::from_raw_parts(routers, routers_count, routers_count) };
    let routers: Vec<Box<Node>> = routers.into_iter().map(|r| unsafe {
        Box::from_raw(r) as Box<Node>
    }).collect();
    let network = Network::new(self_address, host.to_str().unwrap(), routers);
    Box::into_raw(Box::new(network))
}

#[no_mangle]
pub unsafe extern "C" fn comm_network_run(network: *mut Network) {
    let network = Box::from_raw(network);
    network.run();
}

#[no_mangle]
pub unsafe extern "C" fn comm_network_destroy(network: *mut Network) {
    let _ = Box::from_raw(network);
}

#[no_mangle]
pub extern "C" fn comm_text_message_new(sender: *mut Address, text: *const c_char) -> *const client::messages::TextMessage {
    let sender = unsafe { *Box::from_raw(sender) };
    let c_str: &CStr = unsafe { CStr::from_ptr(text) };
    let message_text = c_str.to_str().unwrap().to_string();

    Box::into_raw(Box::new(client::messages::TextMessage::new(sender, message_text)))
}

// TODO: impl API to clean up leaked strings
#[no_mangle]
pub extern "C" fn comm_text_message_text(text_message: *const client::messages::TextMessage) -> *const c_char {
    let text_message = unsafe { &*text_message };
    let string = CString::new(text_message.text.clone()).unwrap();
    let pointer = string.as_ptr();
    std::mem::forget(string);
    pointer
}

#[no_mangle]
pub extern "C" fn comm_text_message_sender(text_message: *const client::messages::TextMessage) -> *const Address {
    let text_message = unsafe { &*text_message };
    Box::into_raw(Box::new(text_message.sender))
}

#[no_mangle]
pub unsafe extern "C" fn comm_client_new(address: *const Address) -> *mut Client {
    Box::into_raw(Box::new(Client::new(*address)))
}

#[no_mangle]
pub unsafe extern "C" fn comm_client_run(
    client: *mut Client, network: *mut Network) -> *mut TaskSender {
    let client = Box::from_raw(client);
    let network = *Box::from_raw(network);
    Box::into_raw(Box::new(client.run(network)))
}

#[no_mangle]
pub extern "C" fn comm_client_register_text_message_received_callback(
    client: *mut Client, callback: extern fn(*const client::messages::TextMessage) -> ()) {

    let client = unsafe { &mut *client };
    let (event_sender, events) = mpsc::channel();
    client.register_event_listener(event_sender);

    thread::spawn(move || {
        for event in events {
            if let Event::ReceivedTextMessage(text_message) = event {
                callback(Box::into_raw(Box::new(text_message)));
            }
        }
    });
}

#[no_mangle]
pub extern "C" fn comm_client_commands_send_text_message(
    commands: *mut TaskSender,
    recipient: *mut Address,
    text_message: *mut client::messages::TextMessage) {
    let commands = unsafe { &mut *commands };
    let recipient = unsafe { *Box::from_raw(recipient) };
    let text_message = unsafe { *Box::from_raw(text_message) };
    commands.send(Task::ScheduleMessageDelivery(recipient, text_message)).unwrap();
}

#[no_mangle]
pub unsafe extern "C" fn comm_client_destroy(client: *mut Client) {
    let _ = Box::from_raw(client);
}
<|endoftext|>


<commit_before>use serde::{
    Deserialize,
    Serialize,
};

use typed_builder::TypedBuilder;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Name {
    #[serde(rename = "$value")]
    value: String,
}

impl Name {
    pub fn new(value: String) -> Self { Self { value } }
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Description {
    #[serde(rename = "$value")]
    value: String,
}

impl Description {
    pub fn new(value: String) -> Self { Self { value } }
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Field {
    name: String,
    #[serde(rename = "$value")]
    value: String,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct AdditionalFields {
    #[serde(rename = "field", default)]
    fields: Vec<Field>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Ref {
    dbname: String,
    dbkey: String,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct CrossReferences {
    #[serde(rename = "ref", default)]
    refs: Vec<Ref>,
}

#[derive(TypedBuilder, Debug, Deserialize, Serialize, PartialEq)]
pub struct Entry {
    id: String,
    name: Name,
    description: Description,
    cross_references: CrossReferences,
    additional_fields: AdditionalFields,
}

impl Default for CrossReferences {
    fn default() -> Self {
        Self {
            refs: Vec::new(),
        }
    }
}

impl Default for AdditionalFields {
    fn default() -> Self {
        Self {
            fields: Vec::new(),
        }
    }
}

impl CrossReferences {
    pub fn add_ref(&mut self, database_name: &str, key: &str) {
        self.refs.push(Ref {
            dbname: database_name.to_string(),
            dbkey: key.to_string(),
        });
    }
}

impl AdditionalFields {
    pub fn add_field(&mut self, name: &str, value: &str) {
        self.fields.push(Field {
            name: name.to_string(),
            value: value.to_string(),
        });
    }
}
<commit_msg>Try adding trees to xml schema<commit_after>use serde::{
    Deserialize,
    Serialize,
};

use typed_builder::TypedBuilder;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Name {
    #[serde(rename = "$value")]
    value: String,
}

impl Name {
    pub fn new(value: String) -> Self { Self { value } }
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Description {
    #[serde(rename = "$value")]
    value: String,
}

impl Description {
    pub fn new(value: String) -> Self { Self { value } }
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct FieldChild {
    #[serde(rename = "$value")]
    value: String
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct HierarchicalField {
    name: String,

    root: FieldChild,
    #[serde(rename = "child")]
    children: Vec<FieldChild>
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct ValueField {
    name: String,
    #[serde(rename = "$value")]
    value: String,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct AdditionalFields {
    #[serde(rename = "field", default)]
    fields: Vec<ValueField>,

    #[serde(rename = "hierarchical_field", default)]
    trees: Vec<HierarchicalField>
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Ref {
    dbname: String,
    dbkey: String,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct CrossReferences {
    #[serde(rename = "ref", default)]
    refs: Vec<Ref>,
}

#[derive(TypedBuilder, Debug, Deserialize, Serialize, PartialEq)]
pub struct Entry {
    id: String,
    name: Name,
    description: Description,
    cross_references: CrossReferences,
    additional_fields: AdditionalFields,
}

impl Default for CrossReferences {
    fn default() -> Self {
        Self {
            refs: Vec::new(),
        }
    }
}

impl Default for AdditionalFields {
    fn default() -> Self {
        Self {
            fields: Vec::new(),
            trees: Vec::new()
        }
    }
}

impl CrossReferences {
    pub fn add_ref(&mut self, database_name: &str, key: &str) {
        self.refs.push(Ref {
            dbname: database_name.to_string(),
            dbkey: key.to_string(),
        });
    }
}

impl AdditionalFields {
    pub fn add_field(&mut self, name: &str, value: &str) {
        self.fields.push(ValueField {
            name: name.to_string(),
            value: value.to_string(),
        });
    }

    pub fn add_tree(&mut self, name: &str, root: FieldChild, children: Vec<FieldChild>) {
        self.trees.push(HierarchicalField {
            name: name.to_string(),
            root,
            children,
        });
    }
}
<|endoftext|>


<commit_before>use super::RootMove;
use super::super::MAX_THREADS;
use super::root_moves_list::{RootMoveList,RawRootMoveList};

use std::heap::{Alloc, Layout, Heap};
use std::ptr::Unique;
use std::sync::Arc;
use std::sync::atomic::{Ordering,AtomicUsize,fence,compiler_fence};
use std::mem;

use std::iter::{Iterator,IntoIterator};

use pleco::Board;
use pleco::board::movegen::{MoveGen,Legal};
use pleco::core::mono_traits::AllGenType;

//struct RawRmManager {
//    pub rms: [RawRootMoveList; MAX_THREADS]
//}
//
//impl RawRmManager {
//    pub fn new() -> Unique<RawRmManager> {
//        unsafe {
//            println!("Raw RMManager create: start");
//            let ptr = Heap.alloc_zeroed(Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
//            println!("Raw RMManager create: created ptr");
//            let new_ptr = match ptr {
//                Ok(ptr) => ptr,
//                Err(err) => Heap.oom(err),
//            };
//            println!("Raw RMManager create: created new_ptr");
//            let raw = Unique::new(new_ptr as *mut RawRmManager).unwrap();
//            for x in 0..MAX_THREADS {
//                print!("Attempt {} :", x);
//                let mut list = mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(raw.as_ptr())
//                    .offset(x as isize);
//
//                let raw_list: &mut RawRootMoveList = (*raw.as_ptr()).rms.get_unchecked_mut(x);
//                print!(" raw_list ... ");
//                (*list).init();
//                raw_list.init();
//                println!("Made raw list");
//            }
////            println!("Raw RMManager create: Done!");
//            println!("Raw RMManager created raw ptr! Success");
//            raw
//        }
//    }
//}

pub struct RmManager {
    threads: Arc<AtomicUsize>,
    moves: Unique<RawRmManager>,
    ref_count: Arc<AtomicUsize>
}

unsafe impl Send for RmManager {}

impl Clone for RmManager {
    fn clone(&self) -> Self {
        let ref_count: Arc<AtomicUsize> = self.ref_count.clone();
        ref_count.fetch_add(1, Ordering::SeqCst);
        RmManager {
            threads: self.threads.clone(),
            moves: self.moves.clone(),
            ref_count
        }
    }
}

impl RmManager {
    pub fn new() -> Self {
        let mut rms = RmManager::init();
        rms.allocate();
        unsafe { rms.set_states();}
        rms
    }

    fn init() -> Self {
        RmManager {
            threads: Arc::new(AtomicUsize::new(0)),
            moves: Unique::empty(),
            ref_count: Arc::new(AtomicUsize::new(1))
        }
    }

    fn allocate(&mut self) {
        unsafe {
            let elem_size = mem::size_of::<RawRootMoveList>();
            let alloc_size = elem_size * MAX_THREADS;
            let align = mem::align_of::<RawRootMoveList>();
            let layout = Layout::from_size_align(alloc_size, align).unwrap();
            let result = Heap.alloc_zeroed(layout);
            let new_ptr = match result {
                Ok(ptr) => ptr,
                Err(err) => Heap.oom(err),
            };
            self.moves = Unique::new_unchecked(new_ptr as *mut RawRmManager);
        }
    }

    unsafe fn set_states(&mut self) {
        for x in 0..MAX_THREADS {
            print!("Attempt {} :", x);
            let mut raw_list = self.get_list_unchecked(x);
            print!(" raw_list ... ");
            raw_list.init();
            println!("Made raw list");
        }
    }

    pub fn threads(&self) -> usize {
        self.threads.load(Ordering::Relaxed)
    }

    pub fn add_thread(&mut self) -> Option<RootMoveList> {
        if self.threads() >= MAX_THREADS {
            None
        } else {
            let thread_idx = self.threads.fetch_add(1, Ordering::SeqCst);
            unsafe {
                Some(self.get_list_unchecked(thread_idx))
            }
        }
    }

    pub fn get_list(&self, num: usize) -> Option<RootMoveList> {
        if num >= self.threads() {
            None
        } else {
            unsafe {
                Some(self.get_list_unchecked(num))
            }
        }
    }

    pub unsafe fn get_list_unchecked(&self, num: usize) -> RootMoveList {
        RootMoveList {
            moves: self.as_raw_ptr().offset(num as isize)
        }
    }

    pub unsafe fn replace_moves(&mut self, board: &Board) {
        let legal_moves = MoveGen::generate::<Legal, AllGenType>(&board);
        let mut first = self.as_ptr();
        first.replace(&legal_moves);
        let num = self.threads();
        for i in 1..num {
            self.get_list_unchecked(i).clone_from_other(&first);
        }
    }

    pub unsafe fn as_ptr(&self) -> RootMoveList {
        RootMoveList {
            moves: mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
        }
    }

    unsafe fn as_raw_ptr(&self) -> *mut RawRootMoveList {
        mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
    }

    pub fn wait_for_finish(&self) {
        unsafe {
            for i in 0..self.threads() {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(true);
            }
        }
    }
    pub fn wait_for_start(&self) {
        unsafe {
            let num_threads = self.threads();
            for i in 0..num_threads {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(false);
            }
        }
    }

    pub fn reset_depths(&self) {
        unsafe {
            for i in 0..self.threads() {
                self.get_list_unchecked(i).set_depth_completed(0);
            }
        }
    }

    pub fn thread_best_move_and_depth(&self, thread_id: usize) -> (RootMove, u16) {
        unsafe {
            let mut thread = self.get_list_unchecked(thread_id);
            (thread.first().clone(), thread.depth_completed())
        }

    }

    pub fn best_rootmove(&self, use_stdout: bool) -> RootMove {
        let (mut best_root_move, mut depth_reached): (RootMove, u16) = self.thread_best_move_and_depth(0);
        if use_stdout {
            println!("id: 0, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}", best_root_move.score, best_root_move.prev_score, best_root_move.depth_reached,depth_reached, best_root_move.bit_move);
        }

        for x in 1..self.threads() {
            let (thread_move, thread_depth): (RootMove, u16)  = self.thread_best_move_and_depth(x);
            let depth_diff = thread_depth as i32 - depth_reached as i32;
            let value_diff = thread_move.score - best_root_move.score;
            if x != 0 {
                // If it has a bigger value and greater or equal depth
                if value_diff > 0 && depth_diff >= 0 {
                    best_root_move = thread_move;
                    depth_reached = thread_depth;
                }
            }

            if use_stdout {
                println!("id: {}, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}",x, thread_move.score, thread_move.prev_score, thread_move.depth_reached,thread_depth, thread_move.bit_move);
            }
        }
        best_root_move
    }
}

pub struct RootMovesIter<'a> {
    root_moves: &'a RmManager,
    threads: usize,
    idx: usize,
}

impl<'a> Iterator for RootMovesIter<'a> {
    type Item = RootMoveList;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.threads {
            None
        } else {
            unsafe {
                Some(self.root_moves.get_list_unchecked(self.idx))
            }
        }
    }

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

impl<'a> IntoIterator for &'a RmManager {
    type Item = RootMoveList;
    type IntoIter = RootMovesIter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        RootMovesIter {
            root_moves: &self,
            threads: self.threads(),
            idx: 0,
        }
    }
}

impl Drop for RmManager {
    fn drop(&mut self) {
        let num = self.ref_count.fetch_sub(1, Ordering::SeqCst);
        if num == 1 {
            unsafe {
                Heap.dealloc(self.as_raw_ptr() as *mut _,
                             Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn rm_basic() {
        let mut rms = RmManager::new();
        assert_eq!(rms.threads(), 0);
        let moves_1 = rms.add_thread().unwrap();
        assert_eq!(rms.threads(), 1);
        assert_eq!(moves_1.len(), 0);
        let board = Board::default();
        unsafe {
            rms.replace_moves(&board);
            let moves_1_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_1.len(), moves_1_clone.len());
            let moves_2 = rms.add_thread().unwrap();
            assert_eq!(rms.threads(), 2);
            rms.replace_moves(&board);
            let moves_2_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_2.len(), moves_2_clone.len());
            assert_eq!(moves_1.len(), moves_2_clone.len());
        }
    }

    #[test]
    fn rm_cloning() {
        let mut rms = RmManager::new();
        let rmsc = rms.clone();
        rms.add_thread();
        rms.add_thread();
        assert_eq!(rms.threads(), rmsc.threads());
    }
}<commit_msg>Forgot a type Alias<commit_after>use super::RootMove;
use super::super::MAX_THREADS;
use super::root_moves_list::{RootMoveList,RawRootMoveList};

use std::heap::{Alloc, Layout, Heap};
use std::ptr::Unique;
use std::sync::Arc;
use std::sync::atomic::{Ordering,AtomicUsize,fence,compiler_fence};
use std::mem;

use std::iter::{Iterator,IntoIterator};

use pleco::Board;
use pleco::board::movegen::{MoveGen,Legal};
use pleco::core::mono_traits::AllGenType;

//struct RawRmManager {
//    pub rms: [RawRootMoveList; MAX_THREADS]
//}
//
//impl RawRmManager {
//    pub fn new() -> Unique<RawRmManager> {
//        unsafe {
//            println!("Raw RMManager create: start");
//            let ptr = Heap.alloc_zeroed(Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
//            println!("Raw RMManager create: created ptr");
//            let new_ptr = match ptr {
//                Ok(ptr) => ptr,
//                Err(err) => Heap.oom(err),
//            };
//            println!("Raw RMManager create: created new_ptr");
//            let raw = Unique::new(new_ptr as *mut RawRmManager).unwrap();
//            for x in 0..MAX_THREADS {
//                print!("Attempt {} :", x);
//                let mut list = mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(raw.as_ptr())
//                    .offset(x as isize);
//
//                let raw_list: &mut RawRootMoveList = (*raw.as_ptr()).rms.get_unchecked_mut(x);
//                print!(" raw_list ... ");
//                (*list).init();
//                raw_list.init();
//                println!("Made raw list");
//            }
////            println!("Raw RMManager create: Done!");
//            println!("Raw RMManager created raw ptr! Success");
//            raw
//        }
//    }
//}

pub type RawRmManager = [RawRootMoveList; MAX_THREADS];

pub struct RmManager {
    threads: Arc<AtomicUsize>,
    moves: Unique<RawRmManager>,
    ref_count: Arc<AtomicUsize>
}

unsafe impl Send for RmManager {}

impl Clone for RmManager {
    fn clone(&self) -> Self {
        let ref_count: Arc<AtomicUsize> = self.ref_count.clone();
        ref_count.fetch_add(1, Ordering::SeqCst);
        RmManager {
            threads: self.threads.clone(),
            moves: self.moves.clone(),
            ref_count
        }
    }
}

impl RmManager {
    pub fn new() -> Self {
        let mut rms = RmManager::init();
        rms.allocate();
        unsafe { rms.set_states();}
        rms
    }

    fn init() -> Self {
        RmManager {
            threads: Arc::new(AtomicUsize::new(0)),
            moves: Unique::empty(),
            ref_count: Arc::new(AtomicUsize::new(1))
        }
    }

    fn allocate(&mut self) {
        unsafe {
            let elem_size = mem::size_of::<RawRootMoveList>();
            let alloc_size = elem_size * MAX_THREADS;
            let align = mem::align_of::<RawRootMoveList>();
            let layout = Layout::from_size_align(alloc_size, align).unwrap();
            let result = Heap.alloc_zeroed(layout);
            let new_ptr = match result {
                Ok(ptr) => ptr,
                Err(err) => Heap.oom(err),
            };
            self.moves = Unique::new_unchecked(new_ptr as *mut RawRmManager);
        }
    }

    unsafe fn set_states(&mut self) {
        for x in 0..MAX_THREADS {
            print!("Attempt {} :", x);
            let mut raw_list = self.get_list_unchecked(x);
            print!(" raw_list ... ");
            raw_list.init();
            println!("Made raw list");
        }
    }

    pub fn threads(&self) -> usize {
        self.threads.load(Ordering::Relaxed)
    }

    pub fn add_thread(&mut self) -> Option<RootMoveList> {
        if self.threads() >= MAX_THREADS {
            None
        } else {
            let thread_idx = self.threads.fetch_add(1, Ordering::SeqCst);
            unsafe {
                Some(self.get_list_unchecked(thread_idx))
            }
        }
    }

    pub fn get_list(&self, num: usize) -> Option<RootMoveList> {
        if num >= self.threads() {
            None
        } else {
            unsafe {
                Some(self.get_list_unchecked(num))
            }
        }
    }

    pub unsafe fn get_list_unchecked(&self, num: usize) -> RootMoveList {
        RootMoveList {
            moves: self.as_raw_ptr().offset(num as isize)
        }
    }

    pub unsafe fn replace_moves(&mut self, board: &Board) {
        let legal_moves = MoveGen::generate::<Legal, AllGenType>(&board);
        let mut first = self.as_ptr();
        first.replace(&legal_moves);
        let num = self.threads();
        for i in 1..num {
            self.get_list_unchecked(i).clone_from_other(&first);
        }
    }

    pub unsafe fn as_ptr(&self) -> RootMoveList {
        RootMoveList {
            moves: mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
        }
    }

    unsafe fn as_raw_ptr(&self) -> *mut RawRootMoveList {
        mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
    }

    pub fn wait_for_finish(&self) {
        unsafe {
            for i in 0..self.threads() {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(true);
            }
        }
    }
    pub fn wait_for_start(&self) {
        unsafe {
            let num_threads = self.threads();
            for i in 0..num_threads {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(false);
            }
        }
    }

    pub fn reset_depths(&self) {
        unsafe {
            for i in 0..self.threads() {
                self.get_list_unchecked(i).set_depth_completed(0);
            }
        }
    }

    pub fn thread_best_move_and_depth(&self, thread_id: usize) -> (RootMove, u16) {
        unsafe {
            let mut thread = self.get_list_unchecked(thread_id);
            (thread.first().clone(), thread.depth_completed())
        }

    }

    pub fn best_rootmove(&self, use_stdout: bool) -> RootMove {
        let (mut best_root_move, mut depth_reached): (RootMove, u16) = self.thread_best_move_and_depth(0);
        if use_stdout {
            println!("id: 0, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}", best_root_move.score, best_root_move.prev_score, best_root_move.depth_reached,depth_reached, best_root_move.bit_move);
        }

        for x in 1..self.threads() {
            let (thread_move, thread_depth): (RootMove, u16)  = self.thread_best_move_and_depth(x);
            let depth_diff = thread_depth as i32 - depth_reached as i32;
            let value_diff = thread_move.score - best_root_move.score;
            if x != 0 {
                // If it has a bigger value and greater or equal depth
                if value_diff > 0 && depth_diff >= 0 {
                    best_root_move = thread_move;
                    depth_reached = thread_depth;
                }
            }

            if use_stdout {
                println!("id: {}, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}",x, thread_move.score, thread_move.prev_score, thread_move.depth_reached,thread_depth, thread_move.bit_move);
            }
        }
        best_root_move
    }
}

pub struct RootMovesIter<'a> {
    root_moves: &'a RmManager,
    threads: usize,
    idx: usize,
}

impl<'a> Iterator for RootMovesIter<'a> {
    type Item = RootMoveList;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.threads {
            None
        } else {
            unsafe {
                Some(self.root_moves.get_list_unchecked(self.idx))
            }
        }
    }

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

impl<'a> IntoIterator for &'a RmManager {
    type Item = RootMoveList;
    type IntoIter = RootMovesIter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        RootMovesIter {
            root_moves: &self,
            threads: self.threads(),
            idx: 0,
        }
    }
}

impl Drop for RmManager {
    fn drop(&mut self) {
        let num = self.ref_count.fetch_sub(1, Ordering::SeqCst);
        if num == 1 {
            unsafe {
                Heap.dealloc(self.as_raw_ptr() as *mut _,
                             Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn rm_basic() {
        let mut rms = RmManager::new();
        assert_eq!(rms.threads(), 0);
        let moves_1 = rms.add_thread().unwrap();
        assert_eq!(rms.threads(), 1);
        assert_eq!(moves_1.len(), 0);
        let board = Board::default();
        unsafe {
            rms.replace_moves(&board);
            let moves_1_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_1.len(), moves_1_clone.len());
            let moves_2 = rms.add_thread().unwrap();
            assert_eq!(rms.threads(), 2);
            rms.replace_moves(&board);
            let moves_2_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_2.len(), moves_2_clone.len());
            assert_eq!(moves_1.len(), moves_2_clone.len());
        }
    }

    #[test]
    fn rm_cloning() {
        let mut rms = RmManager::new();
        let rmsc = rms.clone();
        rms.add_thread();
        rms.add_thread();
        assert_eq!(rms.threads(), rmsc.threads());
    }
}<|endoftext|>


<commit_before>use {Client, Result};
use Error::{self, ArgumentError, OperationError};

use bson::{self, Bson, oid};
use chrono::{DateTime, UTC};

use coll::options::FindOptions;
use command_type::CommandType;
use connstring::{self, Host};
use cursor::Cursor;
use pool::ConnectionPool;
use wire_protocol::flags::OpQueryFlags;

use std::collections::BTreeMap;
use std::sync::{Arc, Condvar, Mutex, RwLock};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};

use time;

use super::server::{ServerDescription, ServerType};
use super::{DEFAULT_HEARTBEAT_FREQUENCY_MS, TopologyDescription};

const DEFAULT_MAX_BSON_OBJECT_SIZE: i64 = 16 * 1024 * 1024;
const DEFAULT_MAX_MESSAGE_SIZE_BYTES: i64 = 48000000;

/// The result of an isMaster operation.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct IsMasterResult {
    pub ok: bool,
    pub is_master: bool,
    pub max_bson_object_size: i64,
    pub max_message_size_bytes: i64,
    pub local_time: Option<DateTime<UTC>>,
    pub min_wire_version: i64,
    pub max_wire_version: i64,

    /// Shard-specific. mongos instances will add this field to the
    /// isMaster reply, and it will contain the value "isdbgrid".
    pub msg: String,

    // Replica Set specific
    pub is_replica_set: bool,
    pub is_secondary: bool,
    pub me: Option<Host>,
    pub hosts: Vec<Host>,
    pub passives: Vec<Host>,
    pub arbiters: Vec<Host>,
    pub arbiter_only: bool,
    pub tags: BTreeMap<String, String>,
    pub set_name: String,
    pub election_id: Option<oid::ObjectId>,
    pub primary: Option<Host>,
    pub hidden: bool,
}

/// Monitors and updates server and topology information.
pub struct Monitor {
    // Host being monitored.
    host: Host,
    // Connection pool for the host.
    server_pool: Arc<ConnectionPool>,
    // Topology description to update.
    top_description: Arc<RwLock<TopologyDescription>>,
    // Server description to update.
    server_description: Arc<RwLock<ServerDescription>>,
    // Client reference.
    client: Client,
    // Owned, single-threaded pool.
    personal_pool: Arc<ConnectionPool>,
    // Owned copy of the topology's heartbeat frequency.
    heartbeat_frequency_ms: AtomicUsize,
    // Used for condvar functionality.
    dummy_lock: Mutex<()>,
    // To allow servers to request an immediate update, this
    // condvar can be notified to wake up the monitor.
    condvar: Condvar,
    /// While true, the monitor will check server connection health
    /// at the topology's heartbeat frequency rate.
    pub running: Arc<AtomicBool>,
}

impl IsMasterResult {
    /// Parses an isMaster response document from the server.
    pub fn new(doc: bson::Document) -> Result<IsMasterResult> {
        let ok = match doc.get("ok") {
            Some(&Bson::I64(v)) => if v == 0 { false } else { true },
            _ => return Err(ArgumentError("result does not contain `ok`.".to_owned())),
        };

        let mut result = IsMasterResult {
            ok: ok,
            is_master: false,
            max_bson_object_size: DEFAULT_MAX_BSON_OBJECT_SIZE,
            max_message_size_bytes: DEFAULT_MAX_MESSAGE_SIZE_BYTES,
            local_time: None,
            min_wire_version: -1,
            max_wire_version: -1,
            msg: String::new(),
            is_secondary: false,
            is_replica_set: false,
            me: None,
            hosts: Vec::new(),
            passives: Vec::new(),
            arbiters: Vec::new(),
            arbiter_only: false,
            tags: BTreeMap::new(),
            set_name: String::new(),
            election_id: None,
            primary: None,
            hidden: false,
        };

        if let Some(&Bson::Boolean(b)) = doc.get("ismaster") {
            result.is_master = b;
        }

        if let Some(&Bson::UtcDatetime(ref datetime)) = doc.get("localTime") {
            result.local_time = Some(datetime.clone());
        }

        if let Some(&Bson::I64(v)) = doc.get("minWireVersion") {
            result.min_wire_version = v;
        }

        if let Some(&Bson::I64(v)) = doc.get("maxWireVersion") {
            result.max_wire_version = v;
        }

        if let Some(&Bson::String(ref s)) = doc.get("msg") {
            result.msg = s.to_owned();
        }

        if let Some(&Bson::Boolean(ref b)) = doc.get("secondary") {
            result.is_secondary = *b;
        }

        if let Some(&Bson::Boolean(ref b)) = doc.get("isreplicaset") {
            result.is_replica_set = *b;
        }

        if let Some(&Bson::String(ref s)) = doc.get("setName") {
            result.set_name = s.to_owned();
        }

        if let Some(&Bson::String(ref s)) = doc.get("me") {
            result.me = Some(try!(connstring::parse_host(s)));
        }

        if let Some(&Bson::Array(ref arr)) = doc.get("hosts") {
            result.hosts = arr.iter().filter_map(|bson| match bson {
                &Bson::String(ref s) => connstring::parse_host(s).ok(),
                _ => None,
            }).collect();
        }

        if let Some(&Bson::Array(ref arr)) = doc.get("passives") {
            result.passives = arr.iter().filter_map(|bson| match bson {
                &Bson::String(ref s) => connstring::parse_host(s).ok(),
                _ => None,
            }).collect();
        }

        if let Some(&Bson::Array(ref arr)) = doc.get("arbiters") {
            result.arbiters = arr.iter().filter_map(|bson| match bson {
                &Bson::String(ref s) => connstring::parse_host(s).ok(),
                _ => None,
            }).collect();
        }

        if let Some(&Bson::String(ref s)) = doc.get("primary") {
            result.primary = Some(try!(connstring::parse_host(s)));
        }

        if let Some(&Bson::Boolean(ref b)) = doc.get("arbiterOnly") {
            result.arbiter_only = *b;
        }

        if let Some(&Bson::Boolean(ref h)) = doc.get("hidden") {
            result.hidden = *h;
        }

        if let Some(&Bson::Document(ref doc)) = doc.get("tags") {
            for (k, v) in doc.into_iter() {
                if let &Bson::String(ref tag) = v {
                    result.tags.insert(k.to_owned(), tag.to_owned());
                }
            }
        }

        match doc.get("electionId") {
            Some(&Bson::ObjectId(ref id)) => result.election_id = Some(id.clone()),
            Some(&Bson::Document(ref doc)) => if let Some(&Bson::String(ref s)) = doc.get("$oid") {
                result.election_id = Some(try!(oid::ObjectId::with_string(s)));
            },
            _ => (),
        }

        Ok(result)
    }
}

impl Monitor {
    /// Returns a new monitor connected to the server.
    pub fn new(client: Client, host: Host, pool: Arc<ConnectionPool>,
               top_description: Arc<RwLock<TopologyDescription>>,
               server_description: Arc<RwLock<ServerDescription>>) -> Monitor {

        Monitor {
            client: client,
            host: host.clone(),
            server_pool: pool,
            personal_pool: Arc::new(ConnectionPool::with_size(host, 1)),
            top_description: top_description,
            server_description: server_description,
            heartbeat_frequency_ms: AtomicUsize::new(DEFAULT_HEARTBEAT_FREQUENCY_MS as usize),
            dummy_lock: Mutex::new(()),
            condvar: Condvar::new(),
            running: Arc::new(AtomicBool::new(false)),
        }
    }

    // Set server description error field.
    fn set_err(&self, err: Error) {
        let mut server_description = self.server_description.write().unwrap();
        server_description.set_err(err);
        self.update_top_description(server_description.clone());
    }

    /// Returns an isMaster server response using an owned monitor socket.
    pub fn is_master(&self) -> Result<(Cursor, i64)> {
        let options = FindOptions::new().with_limit(1);
        let flags = OpQueryFlags::with_find_options(&options);
        let mut filter = bson::Document::new();
        filter.insert("isMaster".to_owned(), Bson::I32(1));

        let stream = try!(self.personal_pool.acquire_stream());

        let time_start = time::get_time();

        let cursor = try!(Cursor::query_with_stream(
            stream, self.client.clone(), "local.$cmd".to_owned(), 1,
            flags, options.skip as i32, 1, filter.clone(), options.projection.clone(),
            CommandType::IsMaster, false, None));

        let time_end = time::get_time();

        let sec_start_ms: i64 = time_start.sec * 1000;
        let start_ms = sec_start_ms + time_start.nsec as i64 / 1000000;

        let sec_end_ms: i64 = time_end.sec * 1000;
        let end_ms = sec_end_ms + time_end.nsec as i64 / 1000000;

        let round_trip_time = end_ms - start_ms;
        Ok((cursor, round_trip_time))
    }

    pub fn request_update(&self) {
        self.condvar.notify_one();
    }

    // Updates the server description associated with this monitor using an isMaster server response.
    fn update_server_description(&self, doc: bson::Document,
                                 round_trip_time: i64) -> Result<ServerDescription> {

        let ismaster_result = IsMasterResult::new(doc);
        let mut server_description = self.server_description.write().unwrap();
        match ismaster_result {
            Ok(ismaster) => server_description.update(ismaster, round_trip_time),
            Err(err) => {
                server_description.set_err(err);
                return Err(OperationError("Failed to parse ismaster result.".to_owned()))
            },
        }

        Ok(server_description.clone())
    }

    // Updates the topology description associated with this monitor using a new server description.
    fn update_top_description(&self, description: ServerDescription) {
        let mut top_description = self.top_description.write().unwrap();
        top_description.update(self.host.clone(), description, self.client.clone(),
                               self.top_description.clone());
    }

    // Updates server and topology descriptions using a successful isMaster cursor result.
    fn update_with_is_master_cursor(&self, cursor: &mut Cursor, round_trip_time: i64) {
        match cursor.next() {
            Some(Ok(doc)) => {
                if let Ok(description) = self.update_server_description(doc, round_trip_time) {
                    self.update_top_description(description);
                }
            },
            Some(Err(err)) => {
                self.set_err(err);
            },
            None => {
                self.set_err(OperationError("ismaster returned no response.".to_owned()));
            }
        }
    }

    /// Execute isMaster and update the server and topology.
    fn execute_update(&self) {
        match self.is_master() {
            Ok((mut cursor, rtt)) => self.update_with_is_master_cursor(&mut cursor, rtt),
            Err(err) => {
                // Refresh all connections
                self.server_pool.clear();
                self.personal_pool.clear();

                let stype = self.server_description.read().unwrap().server_type;

                if stype == ServerType::Unknown {
                    self.set_err(err);
                } else {
                    // Retry once
                    match self.is_master() {
                        Ok((mut cursor, rtt)) => self.update_with_is_master_cursor(&mut cursor, rtt),
                        Err(err) => self.set_err(err),
                    }
                }
            }
        }
    }

    /// Starts server monitoring.
    pub fn run(&self) {
        if self.running.load(Ordering::SeqCst) {
            return;
        }

        self.running.store(true, Ordering::SeqCst);

        let mut guard = self.dummy_lock.lock().unwrap();

        loop {
            if !self.running.load(Ordering::SeqCst) {
                break;
            }

            self.execute_update();

            if let Ok(description) = self.top_description.read() {
                self.heartbeat_frequency_ms.store(description.heartbeat_frequency_ms as usize,
                                                  Ordering::SeqCst);
            }

            let frequency = self.heartbeat_frequency_ms.load(Ordering::SeqCst) as u32;
            guard = self.condvar.wait_timeout_ms(guard, frequency).unwrap().0;
        }
    }
}
<commit_msg>Fix type mismatch on is_master result<commit_after>use {Client, Result};
use Error::{self, ArgumentError, OperationError};

use bson::{self, Bson, oid};
use chrono::{DateTime, UTC};

use coll::options::FindOptions;
use command_type::CommandType;
use connstring::{self, Host};
use cursor::Cursor;
use pool::ConnectionPool;
use wire_protocol::flags::OpQueryFlags;

use std::collections::BTreeMap;
use std::sync::{Arc, Condvar, Mutex, RwLock};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};

use time;

use super::server::{ServerDescription, ServerType};
use super::{DEFAULT_HEARTBEAT_FREQUENCY_MS, TopologyDescription};

const DEFAULT_MAX_BSON_OBJECT_SIZE: i64 = 16 * 1024 * 1024;
const DEFAULT_MAX_MESSAGE_SIZE_BYTES: i64 = 48000000;

/// The result of an isMaster operation.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct IsMasterResult {
    pub ok: bool,
    pub is_master: bool,
    pub max_bson_object_size: i64,
    pub max_message_size_bytes: i64,
    pub local_time: Option<DateTime<UTC>>,
    pub min_wire_version: i64,
    pub max_wire_version: i64,

    /// Shard-specific. mongos instances will add this field to the
    /// isMaster reply, and it will contain the value "isdbgrid".
    pub msg: String,

    // Replica Set specific
    pub is_replica_set: bool,
    pub is_secondary: bool,
    pub me: Option<Host>,
    pub hosts: Vec<Host>,
    pub passives: Vec<Host>,
    pub arbiters: Vec<Host>,
    pub arbiter_only: bool,
    pub tags: BTreeMap<String, String>,
    pub set_name: String,
    pub election_id: Option<oid::ObjectId>,
    pub primary: Option<Host>,
    pub hidden: bool,
}

/// Monitors and updates server and topology information.
pub struct Monitor {
    // Host being monitored.
    host: Host,
    // Connection pool for the host.
    server_pool: Arc<ConnectionPool>,
    // Topology description to update.
    top_description: Arc<RwLock<TopologyDescription>>,
    // Server description to update.
    server_description: Arc<RwLock<ServerDescription>>,
    // Client reference.
    client: Client,
    // Owned, single-threaded pool.
    personal_pool: Arc<ConnectionPool>,
    // Owned copy of the topology's heartbeat frequency.
    heartbeat_frequency_ms: AtomicUsize,
    // Used for condvar functionality.
    dummy_lock: Mutex<()>,
    // To allow servers to request an immediate update, this
    // condvar can be notified to wake up the monitor.
    condvar: Condvar,
    /// While true, the monitor will check server connection health
    /// at the topology's heartbeat frequency rate.
    pub running: Arc<AtomicBool>,
}

impl IsMasterResult {
    /// Parses an isMaster response document from the server.
    pub fn new(doc: bson::Document) -> Result<IsMasterResult> {
        let ok = match doc.get("ok") {
            Some(&Bson::I32(v)) => if v == 0 { false } else { true },
            Some(&Bson::I64(v)) => if v == 0 { false } else { true },
            Some(&Bson::FloatingPoint(v)) => if v == 0.0 { false } else { true },
            _ => return Err(ArgumentError("result does not contain `ok`.".to_owned())),
        };

        let mut result = IsMasterResult {
            ok: ok,
            is_master: false,
            max_bson_object_size: DEFAULT_MAX_BSON_OBJECT_SIZE,
            max_message_size_bytes: DEFAULT_MAX_MESSAGE_SIZE_BYTES,
            local_time: None,
            min_wire_version: -1,
            max_wire_version: -1,
            msg: String::new(),
            is_secondary: false,
            is_replica_set: false,
            me: None,
            hosts: Vec::new(),
            passives: Vec::new(),
            arbiters: Vec::new(),
            arbiter_only: false,
            tags: BTreeMap::new(),
            set_name: String::new(),
            election_id: None,
            primary: None,
            hidden: false,
        };

        if let Some(&Bson::Boolean(b)) = doc.get("ismaster") {
            result.is_master = b;
        }

        if let Some(&Bson::UtcDatetime(ref datetime)) = doc.get("localTime") {
            result.local_time = Some(datetime.clone());
        }

        if let Some(&Bson::I64(v)) = doc.get("minWireVersion") {
            result.min_wire_version = v;
        }

        if let Some(&Bson::I64(v)) = doc.get("maxWireVersion") {
            result.max_wire_version = v;
        }

        if let Some(&Bson::String(ref s)) = doc.get("msg") {
            result.msg = s.to_owned();
        }

        if let Some(&Bson::Boolean(ref b)) = doc.get("secondary") {
            result.is_secondary = *b;
        }

        if let Some(&Bson::Boolean(ref b)) = doc.get("isreplicaset") {
            result.is_replica_set = *b;
        }

        if let Some(&Bson::String(ref s)) = doc.get("setName") {
            result.set_name = s.to_owned();
        }

        if let Some(&Bson::String(ref s)) = doc.get("me") {
            result.me = Some(try!(connstring::parse_host(s)));
        }

        if let Some(&Bson::Array(ref arr)) = doc.get("hosts") {
            result.hosts = arr.iter().filter_map(|bson| match bson {
                &Bson::String(ref s) => connstring::parse_host(s).ok(),
                _ => None,
            }).collect();
        }

        if let Some(&Bson::Array(ref arr)) = doc.get("passives") {
            result.passives = arr.iter().filter_map(|bson| match bson {
                &Bson::String(ref s) => connstring::parse_host(s).ok(),
                _ => None,
            }).collect();
        }

        if let Some(&Bson::Array(ref arr)) = doc.get("arbiters") {
            result.arbiters = arr.iter().filter_map(|bson| match bson {
                &Bson::String(ref s) => connstring::parse_host(s).ok(),
                _ => None,
            }).collect();
        }

        if let Some(&Bson::String(ref s)) = doc.get("primary") {
            result.primary = Some(try!(connstring::parse_host(s)));
        }

        if let Some(&Bson::Boolean(ref b)) = doc.get("arbiterOnly") {
            result.arbiter_only = *b;
        }

        if let Some(&Bson::Boolean(ref h)) = doc.get("hidden") {
            result.hidden = *h;
        }

        if let Some(&Bson::Document(ref doc)) = doc.get("tags") {
            for (k, v) in doc.into_iter() {
                if let &Bson::String(ref tag) = v {
                    result.tags.insert(k.to_owned(), tag.to_owned());
                }
            }
        }

        match doc.get("electionId") {
            Some(&Bson::ObjectId(ref id)) => result.election_id = Some(id.clone()),
            Some(&Bson::Document(ref doc)) => if let Some(&Bson::String(ref s)) = doc.get("$oid") {
                result.election_id = Some(try!(oid::ObjectId::with_string(s)));
            },
            _ => (),
        }

        Ok(result)
    }
}

impl Monitor {
    /// Returns a new monitor connected to the server.
    pub fn new(client: Client, host: Host, pool: Arc<ConnectionPool>,
               top_description: Arc<RwLock<TopologyDescription>>,
               server_description: Arc<RwLock<ServerDescription>>) -> Monitor {

        Monitor {
            client: client,
            host: host.clone(),
            server_pool: pool,
            personal_pool: Arc::new(ConnectionPool::with_size(host, 1)),
            top_description: top_description,
            server_description: server_description,
            heartbeat_frequency_ms: AtomicUsize::new(DEFAULT_HEARTBEAT_FREQUENCY_MS as usize),
            dummy_lock: Mutex::new(()),
            condvar: Condvar::new(),
            running: Arc::new(AtomicBool::new(false)),
        }
    }

    // Set server description error field.
    fn set_err(&self, err: Error) {
        let mut server_description = self.server_description.write().unwrap();
        server_description.set_err(err);
        self.update_top_description(server_description.clone());
    }

    /// Returns an isMaster server response using an owned monitor socket.
    pub fn is_master(&self) -> Result<(Cursor, i64)> {
        let options = FindOptions::new().with_limit(1);
        let flags = OpQueryFlags::with_find_options(&options);
        let mut filter = bson::Document::new();
        filter.insert("isMaster".to_owned(), Bson::I32(1));

        let stream = try!(self.personal_pool.acquire_stream());

        let time_start = time::get_time();

        let cursor = try!(Cursor::query_with_stream(
            stream, self.client.clone(), "local.$cmd".to_owned(), 1,
            flags, options.skip as i32, 1, filter.clone(), options.projection.clone(),
            CommandType::IsMaster, false, None));

        let time_end = time::get_time();

        let sec_start_ms: i64 = time_start.sec * 1000;
        let start_ms = sec_start_ms + time_start.nsec as i64 / 1000000;

        let sec_end_ms: i64 = time_end.sec * 1000;
        let end_ms = sec_end_ms + time_end.nsec as i64 / 1000000;

        let round_trip_time = end_ms - start_ms;
        Ok((cursor, round_trip_time))
    }

    pub fn request_update(&self) {
        self.condvar.notify_one();
    }

    // Updates the server description associated with this monitor using an isMaster server response.
    fn update_server_description(&self, doc: bson::Document,
                                 round_trip_time: i64) -> Result<ServerDescription> {

        let ismaster_result = IsMasterResult::new(doc);
        let mut server_description = self.server_description.write().unwrap();
        match ismaster_result {
            Ok(ismaster) => server_description.update(ismaster, round_trip_time),
            Err(err) => {
                server_description.set_err(err);
                return Err(OperationError("Failed to parse ismaster result.".to_owned()))
            },
        }

        Ok(server_description.clone())
    }

    // Updates the topology description associated with this monitor using a new server description.
    fn update_top_description(&self, description: ServerDescription) {
        let mut top_description = self.top_description.write().unwrap();
        top_description.update(self.host.clone(), description, self.client.clone(),
                               self.top_description.clone());
    }

    // Updates server and topology descriptions using a successful isMaster cursor result.
    fn update_with_is_master_cursor(&self, cursor: &mut Cursor, round_trip_time: i64) {
        match cursor.next() {
            Some(Ok(doc)) => {
                if let Ok(description) = self.update_server_description(doc, round_trip_time) {
                    self.update_top_description(description);
                }
            },
            Some(Err(err)) => {
                self.set_err(err);
            },
            None => {
                self.set_err(OperationError("ismaster returned no response.".to_owned()));
            }
        }
    }

    /// Execute isMaster and update the server and topology.
    fn execute_update(&self) {
        match self.is_master() {
            Ok((mut cursor, rtt)) => self.update_with_is_master_cursor(&mut cursor, rtt),
            Err(err) => {
                // Refresh all connections
                self.server_pool.clear();
                self.personal_pool.clear();

                let stype = self.server_description.read().unwrap().server_type;

                if stype == ServerType::Unknown {
                    self.set_err(err);
                } else {
                    // Retry once
                    match self.is_master() {
                        Ok((mut cursor, rtt)) => self.update_with_is_master_cursor(&mut cursor, rtt),
                        Err(err) => self.set_err(err),
                    }
                }
            }
        }
    }

    /// Starts server monitoring.
    pub fn run(&self) {
        if self.running.load(Ordering::SeqCst) {
            return;
        }

        self.running.store(true, Ordering::SeqCst);

        let mut guard = self.dummy_lock.lock().unwrap();

        loop {
            if !self.running.load(Ordering::SeqCst) {
                break;
            }

            self.execute_update();

            if let Ok(description) = self.top_description.read() {
                self.heartbeat_frequency_ms.store(description.heartbeat_frequency_ms as usize,
                                                  Ordering::SeqCst);
            }

            let frequency = self.heartbeat_frequency_ms.load(Ordering::SeqCst) as u32;
            guard = self.condvar.wait_timeout_ms(guard, frequency).unwrap().0;
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests;

use std::fmt;

#[derive(Debug, PartialEq, Clone)]
pub enum Node {
    Number(f64),
    Bool(bool),
    String(String),
    Symbol {
        ns: Option<String>,
        name: String,
    },
    Keyword {
        ns: Option<String>,
        name: String,
    },
    List(Vec<Node>),
    Vec(Vec<Node>),
    Let {
        bindings: Vec<Node>,
        body: Vec<Node>,
    },
    Fn {
        params: Vec<Node>,
        body: Vec<Node>,
    },
    Macro {
        params: Vec<Node>,
        body: Vec<Node>,
    },
    Def {
        sym: String,
        expr: Box<Node>,
    },
    Call {
        ns: Option<String>,
        name: String,
        args: Vec<Node>,
    },
}

impl Node {
    pub fn as_bool(&self) -> bool {
        if let Node::Bool(b) = *self {
            b
        } else {
            true
        }
    }

    pub fn is_symbol(&self, name: &str) -> bool {
        if let Node::Symbol { name: ref n, .. } = *self {
            &n[..] == name
        } else {
            false
        }
    }

    pub fn is_macro(&self) -> bool {
        if let Node::Macro { .. } = *self {
            true
        } else {
            false
        }
    }

    pub fn is_call_of(&self, name: &str) -> bool {
        if let Node::Call { name: ref n, .. } = *self {
            &n[..] == name
        } else {
            false
        }
    }
}

fn format_vec(v: &[Node]) -> String {
    let mut a = String::new();
    if !v.is_empty() {
        let last_idx = v.len() - 1;
        for (i, e) in v.iter().enumerate() {
            if i < last_idx {
                a.push_str(&format!("{} ", e))
            } else {
                a.push_str(&format!("{}", e))
            }
        }
    }
    a
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Node::Number(n) => {
                write!(f, "{}", n)
            },
            Node::Bool(b) => {
                write!(f, "{}", b)
            },
            Node::Symbol { ref ns, ref name, .. } => {
                if let Some(ref ns) = *ns {
                    write!(f, "{}/{}", ns, name)
                } else {
                    write!(f, "{}", name)
                }
            },
            Node::Keyword { ref ns, ref name, .. } => {
                if let Some(ref ns) = *ns {
                    write!(f, ":{}/{}", ns, name)
                } else {
                    write!(f, ":{}", name)
                }
            },
            Node::String(ref s) => {
                write!(f, r#""{}""#, s)
            },
            Node::List(ref l) => {
                write!(f, "({})", format_vec(l))
            },
            Node::Vec(ref v) => {
                write!(f, "[{}]", format_vec(v))
            },
            Node::Def { ref sym, ref expr } => {
                write!(f, "(def {} {})", sym, expr)
            },
            Node::Let { ref bindings, ref body } => {
                write!(f, "(let [{}] {})", format_vec(bindings), format_vec(body))
            },
            Node::Fn { ref params, ref body } => {
                write!(f, "(fn [{}] {})", format_vec(params), format_vec(body))
            },
            Node::Macro { ref params, ref body } => {
                write!(f, "(macro [{}] {})", format_vec(params), format_vec(body))
            },
            Node::Call { ref ns, ref name, ref args } => {
                let mut a = "(".to_string();
                if let Some(ref ns) = *ns {
                    a.push_str(&format!("{}/{}", ns, name));
                } else {
                    a.push_str(&format!("{}", name));
                }
                if args.is_empty() {
                    a.push_str(")")
                } else {
                    a.push_str(&format!(" {})", format_vec(args)))
                }
                write!(f, "{}", a)
            },
        }
    }
}
<commit_msg>Add Alias Node variant to implement refer builtin<commit_after>#[cfg(test)]
mod tests;

use std::fmt;

#[derive(Debug, PartialEq, Clone)]
pub enum Node {
    Number(f64),
    Bool(bool),
    String(String),
    Symbol {
        ns: Option<String>,
        name: String,
    },
    Keyword {
        ns: Option<String>,
        name: String,
    },
    Alias {
        ns: String,
        name: String,
    },
    List(Vec<Node>),
    Vec(Vec<Node>),
    Let {
        bindings: Vec<Node>,
        body: Vec<Node>,
    },
    Fn {
        params: Vec<Node>,
        body: Vec<Node>,
    },
    Macro {
        params: Vec<Node>,
        body: Vec<Node>,
    },
    Def {
        sym: String,
        expr: Box<Node>,
    },
    Call {
        ns: Option<String>,
        name: String,
        args: Vec<Node>,
    },
}

impl Node {
    pub fn as_bool(&self) -> bool {
        if let Node::Bool(b) = *self {
            b
        } else {
            true
        }
    }

    pub fn is_symbol(&self, name: &str) -> bool {
        if let Node::Symbol { name: ref n, .. } = *self {
            &n[..] == name
        } else {
            false
        }
    }

    pub fn is_macro(&self) -> bool {
        if let Node::Macro { .. } = *self {
            true
        } else {
            false
        }
    }

    pub fn is_call_of(&self, name: &str) -> bool {
        if let Node::Call { name: ref n, .. } = *self {
            &n[..] == name
        } else {
            false
        }
    }
}

fn format_vec(v: &[Node]) -> String {
    let mut a = String::new();
    if !v.is_empty() {
        let last_idx = v.len() - 1;
        for (i, e) in v.iter().enumerate() {
            if i < last_idx {
                a.push_str(&format!("{} ", e))
            } else {
                a.push_str(&format!("{}", e))
            }
        }
    }
    a
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Node::Number(n) => {
                write!(f, "{}", n)
            },
            Node::Bool(b) => {
                write!(f, "{}", b)
            },
            Node::Symbol { ref ns, ref name, .. } => {
                if let Some(ref ns) = *ns {
                    write!(f, "{}/{}", ns, name)
                } else {
                    write!(f, "{}", name)
                }
            },
            Node::Alias { ref ns, ref name, .. } => {
                write!(f, "{}/{}", ns, name)
            },
            Node::Keyword { ref ns, ref name, .. } => {
                if let Some(ref ns) = *ns {
                    write!(f, ":{}/{}", ns, name)
                } else {
                    write!(f, ":{}", name)
                }
            },
            Node::String(ref s) => {
                write!(f, r#""{}""#, s)
            },
            Node::List(ref l) => {
                write!(f, "({})", format_vec(l))
            },
            Node::Vec(ref v) => {
                write!(f, "[{}]", format_vec(v))
            },
            Node::Def { ref sym, ref expr } => {
                write!(f, "(def {} {})", sym, expr)
            },
            Node::Let { ref bindings, ref body } => {
                write!(f, "(let [{}] {})", format_vec(bindings), format_vec(body))
            },
            Node::Fn { ref params, ref body } => {
                write!(f, "(fn [{}] {})", format_vec(params), format_vec(body))
            },
            Node::Macro { ref params, ref body } => {
                write!(f, "(macro [{}] {})", format_vec(params), format_vec(body))
            },
            Node::Call { ref ns, ref name, ref args } => {
                let mut a = "(".to_string();
                if let Some(ref ns) = *ns {
                    a.push_str(&format!("{}/{}", ns, name));
                } else {
                    a.push_str(&format!("{}", name));
                }
                if args.is_empty() {
                    a.push_str(")")
                } else {
                    a.push_str(&format!(" {})", format_vec(args)))
                }
                write!(f, "{}", a)
            },
        }
    }
}
<|endoftext|>


<commit_before>
pub struct DepthStencil {
    depth_write: bool,
    depth_compare: Compare,
    depth_bounds_test: bool,
}

    VkBool32                                    depthTestEnable;
    VkBool32                                    depthWriteEnable;
    VkCompareOp                                 depthCompareOp;
    VkBool32                                    depthBoundsTestEnable;
    VkBool32                                    stencilTestEnable;
    VkStencilOpState                            front;
    VkStencilOpState                            back;
    float                                       minDepthBounds;
    float                                       maxDepthBounds;

typedef struct {
    VkStencilOp                                 stencilFailOp;
    VkStencilOp                                 stencilPassOp;
    VkStencilOp                                 stencilDepthFailOp;
    VkCompareOp                                 stencilCompareOp;
    uint32_t                                    stencilCompareMask;
    uint32_t                                    stencilWriteMask;
    uint32_t                                    stencilReference;
} VkStencilOpState;

/// Specifies how two values should be compared to decide whether a test passes or fails.
///
/// Used for both depth testing and stencil testing.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum Compare {
    /// The test never passes.
    Never => vk::COMPARE_OP_NEVER,
    /// The test passes if `value < reference_value`.
    Less => vk::COMPARE_OP_LESS,
    /// The test passes if `value == reference_value`.
    Equal => vk::COMPARE_OP_EQUAL,
    /// The test passes if `value <= reference_value`.
    LessOrEqual => vk::COMPARE_OP_LESS_OR_EQUAL,
    /// The test passes if `value > reference_value`.
    Greater => vk::COMPARE_OP_GREATER,
    /// The test passes if `value != reference_value`.
    NotEqual => vk::COMPARE_OP_NOT_EQUAL,
    /// The test passes if `value >= reference_value`.
    GreaterOrEqual => vk::COMPARE_OP_GREATER_OR_EQUAL,
    /// The test always passes.
    Always => vk::COMPARE_OP_ALWAYS,
}
<commit_msg>Minor work on depth stencil<commit_after>use std::ops::Range;

pub struct DepthStencil {
    depth_write: bool,
    depth_compare: Compare,
    depth_bounds_test: Option<Range<f32>>,
}

impl Default for DepthStencil {
    #[inline]
    fn default() -> DepthStencil {
        DepthStencil {
            depth_write: false,
            depth_compare: Compare::Always,
            depth_bounds_test: None,
        }
    }
}

    VkBool32                                    depthTestEnable;
    VkBool32                                    depthWriteEnable;
    VkCompareOp                                 depthCompareOp;
    VkBool32                                    depthBoundsTestEnable;
    VkBool32                                    stencilTestEnable;
    VkStencilOpState                            front;
    VkStencilOpState                            back;
    float                                       minDepthBounds;
    float                                       maxDepthBounds;

typedef struct {
    VkStencilOp                                 stencilFailOp;
    VkStencilOp                                 stencilPassOp;
    VkStencilOp                                 stencilDepthFailOp;
    VkCompareOp                                 stencilCompareOp;
    uint32_t                                    stencilCompareMask;
    uint32_t                                    stencilWriteMask;
    uint32_t                                    stencilReference;
} VkStencilOpState;

/// Specifies how two values should be compared to decide whether a test passes or fails.
///
/// Used for both depth testing and stencil testing.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum Compare {
    /// The test never passes.
    Never => vk::COMPARE_OP_NEVER,
    /// The test passes if `value < reference_value`.
    Less => vk::COMPARE_OP_LESS,
    /// The test passes if `value == reference_value`.
    Equal => vk::COMPARE_OP_EQUAL,
    /// The test passes if `value <= reference_value`.
    LessOrEqual => vk::COMPARE_OP_LESS_OR_EQUAL,
    /// The test passes if `value > reference_value`.
    Greater => vk::COMPARE_OP_GREATER,
    /// The test passes if `value != reference_value`.
    NotEqual => vk::COMPARE_OP_NOT_EQUAL,
    /// The test passes if `value >= reference_value`.
    GreaterOrEqual => vk::COMPARE_OP_GREATER_OR_EQUAL,
    /// The test always passes.
    Always => vk::COMPARE_OP_ALWAYS,
}
<|endoftext|>