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

//! Some functions to escape character for display in HTML or LaTeX.
//!
//! The two most useful ones are `tex` and `html`.
//!
//! # Example
//!
//! ```
//! use crowbook_text_processing::escape;
//! let input = "<foo> & <bar>";
//! let output = escape::html(input);
//! assert_eq!(&output, "<foo> & <bar>");
//!
//! let input = "#2: 20%";
//! let output = escape::tex(input);
//! assert_eq!(&output, r"\#2: 20\%");
//! ```

use std::borrow::Cow;

use regex::Regex;
use regex::Captures;

use common::{NB_CHAR, NB_CHAR_NARROW, NB_CHAR_EM};

/// Escape narrow non-breaking spaces for HTML.
///
/// This is unfortunately sometimes necessary as some fonts/renderers don't support the
/// narrow non breaking space character.
///
/// This function works by declaring a span with class "nnbsp" containing
/// the previous and next word, and replacing narrow non breaking space with the non-breaking
/// space character.
///
/// Thus, in order to display correctly, you will need to add some style to this span, e.g.:
///
/// ```css
/// .nnbsp {
///    word-spacing: -0.13em;
///  }
/// ```
pub fn nnbsp<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    lazy_static! {
        static ref REGEX: Regex = Regex::new(r"\S*\x{202F}[\S\x{202F}]*").unwrap();
        static ref REGEX_LOCAL: Regex = Regex::new(r"\x{202F}").unwrap();
    }
    if REGEX.is_match(&input) {
        let res = REGEX.replace_all(&input, |caps: &Captures| {
            format!("{}",
                    REGEX_LOCAL.replace_all(&caps[0], " "))
        });
        Cow::Owned(res.into_owned())
    } else {
        input
    }
}

/// Escape non breaking spaces for HTML.
///
/// This is done so there is no problem for
/// displaying them if the font or browser doesn't know what to do
/// with them (the narrow non breaking space which isn't  very well supported).
///
/// In order to work correctly, this will require a CSS style with
///
/// ```css
/// .nnbsp {
///    white-space: nowrap;
/// }
/// ```
///
/// Else, narrow spaces won't be no-breaking, and that might be ugly.
#[deprecated(since="0.2.6", note="use `nnbsp` instead")]
pub fn nb_spaces<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    if let Some(first) = input.chars().position(|c| match c {
        NB_CHAR | NB_CHAR_NARROW | NB_CHAR_EM => true,
        _ => false,
    }) {
        let mut chars = input.chars().collect::<Vec<_>>();
        let rest = chars.split_off(first);
        let mut output = chars.into_iter().collect::<String>();
        for c in rest {
            match c {
                NB_CHAR_NARROW => output.push_str(r#" "#),
                NB_CHAR_EM => output.push_str(r#" "#),
                NB_CHAR => output.push_str(r#" "#),
                _ => output.push(c),
            }
        }
        Cow::Owned(output)
    } else {
        input.into()
    }
}

/// Escape non breaking spaces for LaTeX, replacing them with `~`.
///
/// # Example
///
/// ```
/// use crowbook_text_processing::escape;
/// let s = escape::nb_spaces_tex("Des espaces insécables ? Ça alors !");
/// assert_eq!(&s, "Des espaces insécables~? Ça alors~!");
/// ```
pub fn nb_spaces_tex<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    if let Some(first) = input.chars().position(|c| match c {
        NB_CHAR | NB_CHAR_NARROW | NB_CHAR_EM => true,
        _ => false,
    }) {
        let mut chars = input.chars().collect::<Vec<_>>();
        let rest = chars.split_off(first);
        let mut output = chars.into_iter().collect::<String>();
        for c in rest {
            match c {
                NB_CHAR_NARROW | NB_CHAR_EM | NB_CHAR => output.push('~'),
                _ => output.push(c),
            }
        }
        Cow::Owned(output)
    } else {
        input.into()
    }
}

/// Escape characters for HTML output, replacing  `<`, `>`, and `&` with appropriate
/// HTML entities.
///
/// **Warning**: this function was written for escaping text in a markdown
/// text processor that is designed to run on a local machine, where the content
/// can actually be trusted. It should *not* be used for untrusted content.
///
/// # Example
///
/// ```
/// use crowbook_text_processing::escape;
/// let s = escape::html("<foo> & <bar>");
/// assert_eq!(&s, "<foo> & <bar>");
/// ```
pub fn html<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    lazy_static! {
        static ref REGEX: Regex = Regex::new("[<>&]").unwrap();
    }
    let input = input.into();
    let first = REGEX.find(&input)
        .map(|mat| mat.start());
    if let Some(first) = first {
        let len = input.len();
        let mut output = Vec::with_capacity(len + len / 2);
        output.extend_from_slice(input[0..first].as_bytes());
        let rest = input[first..].bytes();
        for c in rest {
            match c {
                b'<' => output.extend_from_slice(b"<"),
                b'>' => output.extend_from_slice(b">"),
                b'&' => output.extend_from_slice(b"&"),
                _ => output.push(c),
            }
        }
        Cow::Owned(String::from_utf8(output).unwrap())
    } else {
        input
    }
}

/// Very naively escape quotes
///
/// Simply replace `"` by `'`
pub fn quotes<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    if input.contains('"') {
        let mut output = String::with_capacity(input.len());
        for c in input.chars() {
            match c {
                '"' => output.push('\''),
                _ => output.push(c),
            }
        }
        Cow::Owned(output)
    } else {
        input
    }
}

/// Escape characters for LaTeX
///
/// # Example
///
/// ```
/// use crowbook_text_processing::escape;
/// let s = escape::tex("command --foo # calls command with option foo");
/// assert_eq!(&s, r"command -{}-foo \# calls command with option foo");
/// ```
pub fn tex<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    const REGEX_LITERAL: &'static str = r"[&%$#_\x7E\x2D\{\}\^\\]";
    lazy_static! {
       static ref REGEX: Regex = Regex::new(REGEX_LITERAL).unwrap();
    }

    let first = REGEX.find(&input)
        .map(|mat| mat.start());
    if let Some(first) = first {
        let len = input.len();
        let mut output = Vec::with_capacity(len + len / 2);
        output.extend_from_slice(input[0..first].as_bytes());
        let mut bytes: Vec<_> = input[first..].bytes().collect();
        bytes.push(b' '); // add a dummy char for call to .windows()
        // for &[c, next] in chars.windows(2) { // still experimental, uncomment when stable
        for win in bytes.windows(2) {
            let c = win[0];
            let next = win[1];
            match c {
                b'-' => {
                    if next == b'-' {
                        // if next char is also a -, to avoid tex ligatures
                        output.extend_from_slice(br"-{}");
                    } else {
                        output.push(c);
                    }
                }
                b'&' => output.extend_from_slice(br"\&"),
                b'%' => output.extend_from_slice(br"\%"),
                b'$' => output.extend_from_slice(br"\$"),
                b'#' => output.extend_from_slice(br"\#"),
                b'_' => output.extend_from_slice(br"\_"),
                b'{' => output.extend_from_slice(br"\{"),
                b'}' => output.extend_from_slice(br"\}"),
                b'~' => output.extend_from_slice(br"\textasciitilde{}"),
                b'^' => output.extend_from_slice(br"\textasciicircum{}"),
                b'\\' => output.extend_from_slice(br"\textbackslash{}"),
                _ => output.push(c),
            }
        }
        Cow::Owned(String::from_utf8(output).unwrap())
    } else {
        input
    }
}

#[test]
fn html_0() {
    let s = "Some string without any character to escape";
    let result = html(s);
    assert_eq!(s, &result);
}

#[test]
fn tex_0() {
    let s = "Some string without any character to escape";
    let result = tex(s);
    assert_eq!(s, &result);
}

#[test]
fn nb_spaces_0() {
    let s = "Some string without any character to escape";
    let result = nb_spaces(s);
    assert_eq!(s, &result);
}

#[test]
fn tex_nb_spaces_0() {
    let s = "Some string without any character to escape";
    let result = nb_spaces_tex(s);
    assert_eq!(s, &result);
}

#[test]
fn quotes_0() {
    let s = "Some string without any character to escape";
    let result = quotes(s);
    assert_eq!(s, &result);
}

#[test]
fn html_1() {
    let s = "
Some characters need escaping & something
";
    let expected = "<p>Some characters need escaping & something</p>";
    let actual = html(s);
    assert_eq!(expected, &actual);
}

#[test]
fn html_2() {
    let actual = html("<foo> & <bar>");
    let expected = "<foo> & <bar>";
    assert_eq!(&actual, expected);
}

#[test]
fn tex_braces() {
    let actual = tex(r"\foo{bar}");
    let expected = r"\textbackslash{}foo\{bar\}";
    assert_eq!(&actual, expected);
}

#[test]
fn tex_dashes() {
    let actual = tex("--foo, ---bar");
    let expected = r"-{}-foo, -{}-{}-bar";
    assert_eq!(&actual, expected);
}

#[test]
fn tex_numbers() {
    let actual = tex(r"30000$ is 10% of number #1 income");
    let expected = r"30000\$ is 10\% of number \#1 income";
    assert_eq!(&actual, expected);
}

#[test]
fn quotes_escape() {
    let actual = quotes(r#"Some text with "quotes""#);
    let expected = r#"Some text with 'quotes'"#;
    assert_eq!(&actual, expected);
}

#[test]
fn nb_spaces_escape() {
    let actual = nb_spaces("This contains non breaking spaces");
    let expected = "This contains\
                     non breaking spaces";
    assert_eq!(&actual, expected);
}

#[test]
fn nnbsp_1() {
    let actual = nnbsp("Test ?"); // nnbsp before ?
    let expected = "Test ?";
    assert_eq!(&actual, expected);
}

#[test]
fn nnbsp_2() {
    let actual = nnbsp("Ceci est un « Test » !"); // nnbsp before ! and before/after quotes
    let expected = "Ceci est un « Test » !";
    assert_eq!(&actual, expected);
}
<commit_msg>Escape square brackets in LaTeX<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! Some functions to escape character for display in HTML or LaTeX.
//!
//! The two most useful ones are `tex` and `html`.
//!
//! # Example
//!
//! ```
//! use crowbook_text_processing::escape;
//! let input = "<foo> & <bar>";
//! let output = escape::html(input);
//! assert_eq!(&output, "<foo> & <bar>");
//!
//! let input = "#2: 20%";
//! let output = escape::tex(input);
//! assert_eq!(&output, r"\#2: 20\%");
//! ```

use std::borrow::Cow;

use regex::Regex;
use regex::Captures;

use common::{NB_CHAR, NB_CHAR_NARROW, NB_CHAR_EM};

/// Escape narrow non-breaking spaces for HTML.
///
/// This is unfortunately sometimes necessary as some fonts/renderers don't support the
/// narrow non breaking space character.
///
/// This function works by declaring a span with class "nnbsp" containing
/// the previous and next word, and replacing narrow non breaking space with the non-breaking
/// space character.
///
/// Thus, in order to display correctly, you will need to add some style to this span, e.g.:
///
/// ```css
/// .nnbsp {
///    word-spacing: -0.13em;
///  }
/// ```
pub fn nnbsp<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    lazy_static! {
        static ref REGEX: Regex = Regex::new(r"\S*\x{202F}[\S\x{202F}]*").unwrap();
        static ref REGEX_LOCAL: Regex = Regex::new(r"\x{202F}").unwrap();
    }
    if REGEX.is_match(&input) {
        let res = REGEX.replace_all(&input, |caps: &Captures| {
            format!("{}",
                    REGEX_LOCAL.replace_all(&caps[0], " "))
        });
        Cow::Owned(res.into_owned())
    } else {
        input
    }
}

/// Escape non breaking spaces for HTML.
///
/// This is done so there is no problem for
/// displaying them if the font or browser doesn't know what to do
/// with them (the narrow non breaking space which isn't  very well supported).
///
/// In order to work correctly, this will require a CSS style with
///
/// ```css
/// .nnbsp {
///    white-space: nowrap;
/// }
/// ```
///
/// Else, narrow spaces won't be no-breaking, and that might be ugly.
#[deprecated(since="0.2.6", note="use `nnbsp` instead")]
pub fn nb_spaces<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    if let Some(first) = input.chars().position(|c| match c {
        NB_CHAR | NB_CHAR_NARROW | NB_CHAR_EM => true,
        _ => false,
    }) {
        let mut chars = input.chars().collect::<Vec<_>>();
        let rest = chars.split_off(first);
        let mut output = chars.into_iter().collect::<String>();
        for c in rest {
            match c {
                NB_CHAR_NARROW => output.push_str(r#" "#),
                NB_CHAR_EM => output.push_str(r#" "#),
                NB_CHAR => output.push_str(r#" "#),
                _ => output.push(c),
            }
        }
        Cow::Owned(output)
    } else {
        input.into()
    }
}

/// Escape non breaking spaces for LaTeX, replacing them with `~`.
///
/// # Example
///
/// ```
/// use crowbook_text_processing::escape;
/// let s = escape::nb_spaces_tex("Des espaces insécables ? Ça alors !");
/// assert_eq!(&s, "Des espaces insécables~? Ça alors~!");
/// ```
pub fn nb_spaces_tex<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    if let Some(first) = input.chars().position(|c| match c {
        NB_CHAR | NB_CHAR_NARROW | NB_CHAR_EM => true,
        _ => false,
    }) {
        let mut chars = input.chars().collect::<Vec<_>>();
        let rest = chars.split_off(first);
        let mut output = chars.into_iter().collect::<String>();
        for c in rest {
            match c {
                NB_CHAR_NARROW | NB_CHAR_EM | NB_CHAR => output.push('~'),
                _ => output.push(c),
            }
        }
        Cow::Owned(output)
    } else {
        input.into()
    }
}

/// Escape characters for HTML output, replacing  `<`, `>`, and `&` with appropriate
/// HTML entities.
///
/// **Warning**: this function was written for escaping text in a markdown
/// text processor that is designed to run on a local machine, where the content
/// can actually be trusted. It should *not* be used for untrusted content.
///
/// # Example
///
/// ```
/// use crowbook_text_processing::escape;
/// let s = escape::html("<foo> & <bar>");
/// assert_eq!(&s, "<foo> & <bar>");
/// ```
pub fn html<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    lazy_static! {
        static ref REGEX: Regex = Regex::new("[<>&]").unwrap();
    }
    let input = input.into();
    let first = REGEX.find(&input)
        .map(|mat| mat.start());
    if let Some(first) = first {
        let len = input.len();
        let mut output = Vec::with_capacity(len + len / 2);
        output.extend_from_slice(input[0..first].as_bytes());
        let rest = input[first..].bytes();
        for c in rest {
            match c {
                b'<' => output.extend_from_slice(b"<"),
                b'>' => output.extend_from_slice(b">"),
                b'&' => output.extend_from_slice(b"&"),
                _ => output.push(c),
            }
        }
        Cow::Owned(String::from_utf8(output).unwrap())
    } else {
        input
    }
}

/// Very naively escape quotes
///
/// Simply replace `"` by `'`
pub fn quotes<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    if input.contains('"') {
        let mut output = String::with_capacity(input.len());
        for c in input.chars() {
            match c {
                '"' => output.push('\''),
                _ => output.push(c),
            }
        }
        Cow::Owned(output)
    } else {
        input
    }
}

/// Escape characters for LaTeX
///
/// # Example
///
/// ```
/// use crowbook_text_processing::escape;
/// let s = escape::tex("command --foo # calls command with option foo");
/// assert_eq!(&s, r"command -{}-foo \# calls command with option foo");
/// ```
pub fn tex<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
    let input = input.into();
    const REGEX_LITERAL: &'static str = r"[&%$#_\x7E\x2D\{\}\[\]\^\\]";
    lazy_static! {
       static ref REGEX: Regex = Regex::new(REGEX_LITERAL).unwrap();
    }

    let first = REGEX.find(&input)
        .map(|mat| mat.start());
    if let Some(first) = first {
        let len = input.len();
        let mut output = Vec::with_capacity(len + len / 2);
        output.extend_from_slice(input[0..first].as_bytes());
        let mut bytes: Vec<_> = input[first..].bytes().collect();
        bytes.push(b' '); // add a dummy char for call to .windows()
        // for &[c, next] in chars.windows(2) { // still experimental, uncomment when stable
        for win in bytes.windows(2) {
            let c = win[0];
            let next = win[1];
            match c {
                b'-' => {
                    if next == b'-' {
                        // if next char is also a -, to avoid tex ligatures
                        output.extend_from_slice(br"-{}");
                    } else {
                        output.push(c);
                    }
                }
                b'&' => output.extend_from_slice(br"\&"),
                b'%' => output.extend_from_slice(br"\%"),
                b'$' => output.extend_from_slice(br"\$"),
                b'#' => output.extend_from_slice(br"\#"),
                b'_' => output.extend_from_slice(br"\_"),
                b'{' => output.extend_from_slice(br"\{"),
                b'}' => output.extend_from_slice(br"\}"),
                b'[' => output.extend_from_slice(br"{[}"),
                b']' => output.extend_from_slice(br"{]}"),
                b'~' => output.extend_from_slice(br"\textasciitilde{}"),
                b'^' => output.extend_from_slice(br"\textasciicircum{}"),
                b'\\' => output.extend_from_slice(br"\textbackslash{}"),
                _ => output.push(c),
            }
        }
        Cow::Owned(String::from_utf8(output).unwrap())
    } else {
        input
    }
}

#[test]
fn html_0() {
    let s = "Some string without any character to escape";
    let result = html(s);
    assert_eq!(s, &result);
}

#[test]
fn tex_0() {
    let s = "Some string without any character to escape";
    let result = tex(s);
    assert_eq!(s, &result);
}

#[test]
fn nb_spaces_0() {
    let s = "Some string without any character to escape";
    let result = nb_spaces(s);
    assert_eq!(s, &result);
}

#[test]
fn tex_nb_spaces_0() {
    let s = "Some string without any character to escape";
    let result = nb_spaces_tex(s);
    assert_eq!(s, &result);
}

#[test]
fn quotes_0() {
    let s = "Some string without any character to escape";
    let result = quotes(s);
    assert_eq!(s, &result);
}

#[test]
fn html_1() {
    let s = "
Some characters need escaping & something
";
    let expected = "<p>Some characters need escaping & something</p>";
    let actual = html(s);
    assert_eq!(expected, &actual);
}

#[test]
fn html_2() {
    let actual = html("<foo> & <bar>");
    let expected = "<foo> & <bar>";
    assert_eq!(&actual, expected);
}

#[test]
fn tex_braces() {
    let actual = tex(r"\foo{bar}");
    let expected = r"\textbackslash{}foo\{bar\}";
    assert_eq!(&actual, expected);
}

#[test]
fn tex_square_braces() {
    let actual = tex(r"foo[bar]");
    let expected = r"foo{[}bar{]}";
    assert_eq!(&actual, expected);
}

#[test]
fn tex_dashes() {
    let actual = tex("--foo, ---bar");
    let expected = r"-{}-foo, -{}-{}-bar";
    assert_eq!(&actual, expected);
}

#[test]
fn tex_numbers() {
    let actual = tex(r"30000$ is 10% of number #1 income");
    let expected = r"30000\$ is 10\% of number \#1 income";
    assert_eq!(&actual, expected);
}

#[test]
fn quotes_escape() {
    let actual = quotes(r#"Some text with "quotes""#);
    let expected = r#"Some text with 'quotes'"#;
    assert_eq!(&actual, expected);
}

#[test]
fn nb_spaces_escape() {
    let actual = nb_spaces("This contains non breaking spaces");
    let expected = "This contains\
                     non breaking spaces";
    assert_eq!(&actual, expected);
}

#[test]
fn nnbsp_1() {
    let actual = nnbsp("Test ?"); // nnbsp before ?
    let expected = "Test ?";
    assert_eq!(&actual, expected);
}

#[test]
fn nnbsp_2() {
    let actual = nnbsp("Ceci est un « Test » !"); // nnbsp before ! and before/after quotes
    let expected = "Ceci est un « Test » !";
    assert_eq!(&actual, expected);
}
<|endoftext|>


<commit_before>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_id = "jit"]
#![comment = "LibJIT Bindings"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![allow(raw_pointer_deriving, dead_code, non_camel_case_types)]
#![deny(unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_allocation, uppercase_variables, unused_must_use)]
#![feature(globs, macro_rules)]
#![stable]
//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! extern crate jit;
//! use jit::{C_DECL, Context, Function, Type, Types, get_type};
//! fn main() {
//!     let cx = Context::new();
//!     cx.build(|| {
//!         // build the IR
//!         let sig = get_type(fn(int, int) -> int);
//!         let func = Function::new(cx, sig);
//!         let x = func.get_param(0);
//!         let y = func.get_param(1);
//!         let result = func.insn_mul(&x, &y);
//!         func.insn_return(&result);
//!         /// run the IR
//!         func.compile();
//!         let rfunc:fn(int, int) -> int = func.closure2();
//!         assert_eq(rfunc(4, 5), 20)
//!     });
//! }
//! ```

extern crate libc;
use bindings::{
    jit_init,
    jit_uses_interpreter,
    jit_supports_threads,
    jit_supports_virtual_memory
};
pub use bindings::{
    jit_nint,
    jit_nuint
};
pub use compile::Compile;
pub use context::{
    Context,
    InContext,
    Functions
};
pub use function::{
    ABI,
    CDECL,
    Function
};
pub use label::Label;
pub use types::*;
pub use get_type = types::get;
pub use util::NativeRef;
pub use value::Value;

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
    unsafe {
        jit_init()
    }
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
    unsafe {
        jit_uses_interpreter() != 0
    }
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
    unsafe {
        jit_supports_threads() != 0
    }
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
    unsafe {
        jit_supports_virtual_memory() != 0
    }
}
#[macro_escape]
mod macros;
mod bindings;
mod context;
mod compile;
mod elf;
mod function;
mod label;
#[cfg(test)]
mod tests;
mod types;
mod util;
mod value;<commit_msg>Update docs<commit_after>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_id = "jit"]
#![comment = "LibJIT Bindings"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![allow(raw_pointer_deriving, dead_code, non_camel_case_types)]
#![deny(unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_allocation, uppercase_variables, unused_must_use)]
#![feature(globs, macro_rules)]
#![stable]
//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! extern crate jit;
//! use jit::{C_DECL, Context, Function, Type, Types, get_type};
//! fn main() {
//!     let cx = Context::new();
//!     cx.build(|| {
//!         // build the IR
//!         let sig = get_type::<fn(int, int) -> int>();
//!         let func = Function::new(cx, sig);
//!         let x = func.get_param(0);
//!         let y = func.get_param(1);
//!         let result = func.insn_mul(&x, &y);
//!         func.insn_return(&result);
//!         /// compile the IR into machine code
//!         func.compile();
//!         /// get the machine code as a function
//!         func.with_closure2(|mul:fn(int, int) -> int| {
//!             assert_eq!(mul(4, 5), 20);
//!         });
//!     });
//! }
//! ```

extern crate libc;
use bindings::{
    jit_init,
    jit_uses_interpreter,
    jit_supports_threads,
    jit_supports_virtual_memory
};
pub use bindings::{
    jit_nint,
    jit_nuint
};
pub use compile::Compile;
pub use context::{
    Context,
    InContext,
    Functions
};
pub use function::{
    ABI,
    CDECL,
    Function
};
pub use label::Label;
pub use types::*;
pub use get_type = types::get;
pub use util::NativeRef;
pub use value::Value;

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
    unsafe {
        jit_init()
    }
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
    unsafe {
        jit_uses_interpreter() != 0
    }
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
    unsafe {
        jit_supports_threads() != 0
    }
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
    unsafe {
        jit_supports_virtual_memory() != 0
    }
}
#[macro_escape]
mod macros;
mod bindings;
mod context;
mod compile;
mod elf;
mod function;
mod label;
#[cfg(test)]
mod tests;
mod types;
mod util;
mod value;<|endoftext|>


<commit_before>use std::iter;
use std::{fmt, ops};
use board::std_board::{Square};

#[derive(PartialEq, Eq, Clone, Copy, Hash)]
pub struct BitBoard {
    pub board: u64,
}

impl ops::BitOr for BitBoard {
    type Output = BitBoard;
    fn bitor(self, rhs: BitBoard) -> BitBoard {
        BitBoard::from_u64(self.board | rhs.board)
    }
}

impl ops::BitAnd for BitBoard {
    type Output = BitBoard;
    fn bitand(self, rhs: BitBoard) -> BitBoard {
        BitBoard::from_u64(self.board & rhs.board)
    }
}

impl ops::Not for BitBoard {
    type Output = BitBoard;
    fn not(self) -> BitBoard {
        BitBoard::from_u64(!self.board)
    }
}

impl BitBoard {
    pub const fn empty() -> Self {
        BitBoard { board: 0 }
    }
    pub const fn from_u64(n: u64) -> Self {
        BitBoard { board: n }
    }

    /// Returns a board with the diagonal neighbours squares (up to 4) set
    pub fn diagonal_neighbours(square: Square) -> BitBoard {
        DIAGONAL_NEIGHBOURS[square.0 as usize]
    }

    pub fn orthogonal_neighbours(square: Square) -> BitBoard {
        ORTHOGONAL_NEIGHBOURS[square.0 as usize]
    }

    pub const fn get(&self, square: Square) -> bool {
        self.board & (1<<square.0) != 0
    }
    // Sets the square to true
    pub const fn set(self, square: Square) -> Self {
        BitBoard::from_u64(self.board | 1<<square.0)
    }
    #[allow(dead_code)]
    // Sets the square to false
    pub const fn clear(self, square: Square) -> Self {
        BitBoard::from_u64(self.board & !(1<<square.0))
    }

    pub const fn is_empty(&self) -> bool {
        self.board == 0
    }

    pub const fn popcount(&self) -> u32 {
        self.board.count_ones()
    }

    /// Get a single rank
    /// Ranks are numbered from 0 (black's back rank) to 7 (white's back rank)
    pub const fn rank(self, rank: u8) -> u8 {
        (self.board >> (rank * 8)) as u8
    }
    #[allow(dead_code)]
    pub const fn file(self, file: u8) -> u8 {
        self.rotate().rank(file)
    }
    pub const fn rotate(&self) -> Self {
        self.flip_vertical().flip_diagonal()
    }
    pub const fn rotate_270(&self) -> Self {
        self.flip_diagonal().flip_vertical()
    }
    pub const fn rotate_45(&self) -> Self {
        let k1 = 0xAAAAAAAAAAAAAAAA;
        let k2 = 0xCCCCCCCCCCCCCCCC;
        let k4 = 0xF0F0F0F0F0F0F0F0;
        let mut x = self.board;
        x ^= k1 & (x ^ x.rotate_right(8));
        x ^= k2 & (x ^ x.rotate_right(16));
        x ^= k4 & (x ^ x.rotate_right(32));
        Self::from_u64(x)
    }
    pub const fn rotate_315(&self) -> Self {
        let k1 = 0x5555555555555555;
        let k2 = 0x3333333333333333;
        let k4 = 0x0f0f0f0f0f0f0f0f;
        let mut x = self.board;
        x ^= k1 & (x ^ x.rotate_right(8));
        x ^= k2 & (x ^ x.rotate_right(16));
        x ^= k4 & (x ^ x.rotate_right(32));
        Self::from_u64(x)
    }
    #[allow(dead_code)]
    pub const fn flip_horizontal(&self) -> Self {
        let k1 = 0x5555555555555555;
        let k2 = 0x3333333333333333;
        let k4 = 0x0f0f0f0f0f0f0f0f;
        let mut x = self.board;
        x = ((x >> 1) & k1) +  2*(x & k1);
        x = ((x >> 2) & k2) +  4*(x & k2);
        x = ((x >> 4) & k4) + 16*(x & k4);
        BitBoard::from_u64(x)
    }
    pub const fn flip_vertical(&self) -> Self {
        BitBoard::from_u64(self.board.swap_bytes())
    }

    pub const fn flip_diagonal(&self) -> Self {
        let k1 = 0x5500550055005500;
        let k2 = 0x3333000033330000;
        let k4 = 0x0f0f0f0f00000000;
        let mut x = self.board;
        let mut t = k4 & (x ^ (x << 28));
        x ^=       t ^ (t >> 28) ;
        t  = k2 & (x ^ (x << 14));
        x ^=       t ^ (t >> 14) ;
        t  = k1 & (x ^ (x <<  7));
        x ^=       t ^ (t >>  7) ;
        BitBoard::from_u64(x)
    }
    /// Diagonal_id is rank + file
    /// Assumes board is already rotated
    pub fn diagonal(&self, diagonal_id: u8) -> u8 {
        let len = if diagonal_id >= 8 { 15 - diagonal_id } else { diagonal_id + 1 };
        let n = diagonal_id as i8 - 7;
        //let offset = ((7 * n + 8)) % 64;
        let offset = if n <= 0 { n * (-8)} else { 8 * (8 - n) + n };
        ((self.board >> offset) & !(!0 << len)) as u8
    }

    /// Diagonal_id is rank - file
    /// Assumes board is already rotated
    pub fn antidiagonal(&self, diagonal_id: i8) -> u8 {
        let len = 8 - diagonal_id.abs(); // Between 1 and 8
        let n = diagonal_id as i16;
        let offset = if n <= 0 { n * (-8) - n} else { 8 * (8 - n) };
        ((self.board >> offset) & !(!0 << len as u64)) as u8
    }

    pub fn first_piece(&self) -> Option<Square> {
        let square = self.board.trailing_zeros();
        if square == 64 {
            None
        }
        else {
            Some(Square(square as u8))
        }
    }
}

impl fmt::Debug for BitBoard {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for n in 0..8 {
            writeln!(f, "{:08b}", (self.board >> (n * 8)) as u8).unwrap();
        }
        Ok(())
    }
}

impl IntoIterator for BitBoard {
    type Item = Square;
    type IntoIter = BitBoardIterator;

    fn into_iter(self) -> Self::IntoIter {
        BitBoardIterator::new(self)
    }
}

impl iter::FromIterator<Square> for BitBoard {
    fn from_iter<T: IntoIterator<Item=Square>>(iter: T) -> Self {
        let mut board = Self::empty();
        for square in iter {
            board = board.set(square);
        }
        board
    }
}

pub struct BitBoardIterator {
    board: BitBoard,
}

impl BitBoardIterator {
    const fn new(board: BitBoard) -> Self {
        Self { board }
    }
}

impl Iterator for BitBoardIterator {
    type Item = Square;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(next) = self.board.first_piece() {
            self.board = self.board.clear(next);
            Some(next)
        }
        else {
            None
        }
    }
}

lazy_static!(
    static ref DIAGONAL_NEIGHBOURS : [BitBoard; 64] = {
        let mut table : [BitBoard; 64] = [BitBoard::empty(); 64];

        for i in 0..64 {
            let mut board = BitBoard::empty();
            let (file, rank) = Square(i).file_rank();

            for &x in &[u8::overflowing_sub(file, 1).0, file + 1] {
                for &y in &[u8::overflowing_sub(rank, 1).0, rank + 1] {
                    if x < 8 && y < 8 {
                        board = board.set(Square::from_ints(x, y));
                    }
                }
            }
            table[i as usize] = board;
        }
        table
    };

    static ref RANK_NEIGHBOURS : [BitBoard; 64] = {
        let mut table : [BitBoard; 64] = [BitBoard::empty(); 64];
        for i in 0..64 {
            let (file, rank) = Square(i).file_rank();
            let mut board = BitBoard::empty();
            if file > 0 {
                board = board.set(Square::from_ints(file - 1, rank));
            }
            if file < 7 {
                board = board.set(Square::from_ints(file + 1, rank));
            }
            table[i as usize] = board;
        }
        table
    };

    static ref FILE_NEIGHBOURS : [BitBoard; 64] = {
        let mut table : [BitBoard; 64] = [BitBoard::empty(); 64];

        for i in 0..64 {
            let (file, rank) = Square(i).file_rank();
            let mut board = BitBoard::empty();
            if rank > 0 {
                board = board.set(Square::from_ints(file, rank - 1));
            }
            if rank < 7 {
                board = board.set(Square::from_ints(file, rank + 1));
            }
            table[i as usize] = board;
        }
        table
    };

    static ref ORTHOGONAL_NEIGHBOURS : [BitBoard; 64] = {
        let mut table : [BitBoard; 64] = [BitBoard::empty(); 64];

        for i in 0..64 {
            table[i] = RANK_NEIGHBOURS[i] | FILE_NEIGHBOURS[i];
        }
        table
    };
);<commit_msg>Implement AddAssign and OrAssign for BitBoard<commit_after>use std::iter;
use std::{fmt, ops};
use board::std_board::{Square};

#[derive(PartialEq, Eq, Clone, Copy, Hash)]
pub struct BitBoard {
    pub board: u64,
}

impl ops::BitOr for BitBoard {
    type Output = BitBoard;
    fn bitor(self, rhs: BitBoard) -> BitBoard {
        BitBoard::from_u64(self.board | rhs.board)
    }
}

impl ops::BitOrAssign for BitBoard {
    fn bitor_assign(&mut self, rhs: BitBoard) {
        self.board |= rhs.board
    }
}

impl ops::BitAnd for BitBoard {
    type Output = BitBoard;
    fn bitand(self, rhs: BitBoard) -> BitBoard {
        BitBoard::from_u64(self.board & rhs.board)
    }
}

impl ops::BitAndAssign for BitBoard {
    fn bitand_assign(&mut self, rhs: BitBoard) {
        self.board &= rhs.board
    }
}

impl ops::Not for BitBoard {
    type Output = BitBoard;
    fn not(self) -> BitBoard {
        BitBoard::from_u64(!self.board)
    }
}

impl BitBoard {
    pub const fn empty() -> Self {
        BitBoard { board: 0 }
    }
    pub const fn from_u64(n: u64) -> Self {
        BitBoard { board: n }
    }

    /// Returns a board with the diagonal neighbours squares (up to 4) set
    pub fn diagonal_neighbours(square: Square) -> BitBoard {
        DIAGONAL_NEIGHBOURS[square.0 as usize]
    }

    pub fn orthogonal_neighbours(square: Square) -> BitBoard {
        ORTHOGONAL_NEIGHBOURS[square.0 as usize]
    }

    pub const fn get(&self, square: Square) -> bool {
        self.board & (1<<square.0) != 0
    }
    // Sets the square to true
    pub const fn set(self, square: Square) -> Self {
        BitBoard::from_u64(self.board | 1<<square.0)
    }
    #[allow(dead_code)]
    // Sets the square to false
    pub const fn clear(self, square: Square) -> Self {
        BitBoard::from_u64(self.board & !(1<<square.0))
    }

    pub const fn is_empty(&self) -> bool {
        self.board == 0
    }

    pub const fn popcount(&self) -> u32 {
        self.board.count_ones()
    }

    /// Get a single rank
    /// Ranks are numbered from 0 (black's back rank) to 7 (white's back rank)
    pub const fn rank(self, rank: u8) -> u8 {
        (self.board >> (rank * 8)) as u8
    }
    #[allow(dead_code)]
    pub const fn file(self, file: u8) -> u8 {
        self.rotate().rank(file)
    }
    pub const fn rotate(&self) -> Self {
        self.flip_vertical().flip_diagonal()
    }
    pub const fn rotate_270(&self) -> Self {
        self.flip_diagonal().flip_vertical()
    }
    pub const fn rotate_45(&self) -> Self {
        let k1 = 0xAAAAAAAAAAAAAAAA;
        let k2 = 0xCCCCCCCCCCCCCCCC;
        let k4 = 0xF0F0F0F0F0F0F0F0;
        let mut x = self.board;
        x ^= k1 & (x ^ x.rotate_right(8));
        x ^= k2 & (x ^ x.rotate_right(16));
        x ^= k4 & (x ^ x.rotate_right(32));
        Self::from_u64(x)
    }
    pub const fn rotate_315(&self) -> Self {
        let k1 = 0x5555555555555555;
        let k2 = 0x3333333333333333;
        let k4 = 0x0f0f0f0f0f0f0f0f;
        let mut x = self.board;
        x ^= k1 & (x ^ x.rotate_right(8));
        x ^= k2 & (x ^ x.rotate_right(16));
        x ^= k4 & (x ^ x.rotate_right(32));
        Self::from_u64(x)
    }
    #[allow(dead_code)]
    pub const fn flip_horizontal(&self) -> Self {
        let k1 = 0x5555555555555555;
        let k2 = 0x3333333333333333;
        let k4 = 0x0f0f0f0f0f0f0f0f;
        let mut x = self.board;
        x = ((x >> 1) & k1) +  2*(x & k1);
        x = ((x >> 2) & k2) +  4*(x & k2);
        x = ((x >> 4) & k4) + 16*(x & k4);
        BitBoard::from_u64(x)
    }
    pub const fn flip_vertical(&self) -> Self {
        BitBoard::from_u64(self.board.swap_bytes())
    }

    pub const fn flip_diagonal(&self) -> Self {
        let k1 = 0x5500550055005500;
        let k2 = 0x3333000033330000;
        let k4 = 0x0f0f0f0f00000000;
        let mut x = self.board;
        let mut t = k4 & (x ^ (x << 28));
        x ^=       t ^ (t >> 28) ;
        t  = k2 & (x ^ (x << 14));
        x ^=       t ^ (t >> 14) ;
        t  = k1 & (x ^ (x <<  7));
        x ^=       t ^ (t >>  7) ;
        BitBoard::from_u64(x)
    }
    /// Diagonal_id is rank + file
    /// Assumes board is already rotated
    pub fn diagonal(&self, diagonal_id: u8) -> u8 {
        let len = if diagonal_id >= 8 { 15 - diagonal_id } else { diagonal_id + 1 };
        let n = diagonal_id as i8 - 7;
        //let offset = ((7 * n + 8)) % 64;
        let offset = if n <= 0 { n * (-8)} else { 8 * (8 - n) + n };
        ((self.board >> offset) & !(!0 << len)) as u8
    }

    /// Diagonal_id is rank - file
    /// Assumes board is already rotated
    pub fn antidiagonal(&self, diagonal_id: i8) -> u8 {
        let len = 8 - diagonal_id.abs(); // Between 1 and 8
        let n = diagonal_id as i16;
        let offset = if n <= 0 { n * (-8) - n} else { 8 * (8 - n) };
        ((self.board >> offset) & !(!0 << len as u64)) as u8
    }

    pub fn first_piece(&self) -> Option<Square> {
        let square = self.board.trailing_zeros();
        if square == 64 {
            None
        }
        else {
            Some(Square(square as u8))
        }
    }
}

impl fmt::Debug for BitBoard {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for n in 0..8 {
            writeln!(f, "{:08b}", (self.board >> (n * 8)) as u8).unwrap();
        }
        Ok(())
    }
}

impl IntoIterator for BitBoard {
    type Item = Square;
    type IntoIter = BitBoardIterator;

    fn into_iter(self) -> Self::IntoIter {
        BitBoardIterator::new(self)
    }
}

impl iter::FromIterator<Square> for BitBoard {
    fn from_iter<T: IntoIterator<Item=Square>>(iter: T) -> Self {
        let mut board = Self::empty();
        for square in iter {
            board = board.set(square);
        }
        board
    }
}

pub struct BitBoardIterator {
    board: BitBoard,
}

impl BitBoardIterator {
    const fn new(board: BitBoard) -> Self {
        Self { board }
    }
}

impl Iterator for BitBoardIterator {
    type Item = Square;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(next) = self.board.first_piece() {
            self.board = self.board.clear(next);
            Some(next)
        }
        else {
            None
        }
    }
}

lazy_static!(
    static ref DIAGONAL_NEIGHBOURS : [BitBoard; 64] = {
        let mut table : [BitBoard; 64] = [BitBoard::empty(); 64];

        for i in 0..64 {
            let mut board = BitBoard::empty();
            let (file, rank) = Square(i).file_rank();

            for &x in &[u8::overflowing_sub(file, 1).0, file + 1] {
                for &y in &[u8::overflowing_sub(rank, 1).0, rank + 1] {
                    if x < 8 && y < 8 {
                        board = board.set(Square::from_ints(x, y));
                    }
                }
            }
            table[i as usize] = board;
        }
        table
    };

    static ref RANK_NEIGHBOURS : [BitBoard; 64] = {
        let mut table : [BitBoard; 64] = [BitBoard::empty(); 64];
        for i in 0..64 {
            let (file, rank) = Square(i).file_rank();
            let mut board = BitBoard::empty();
            if file > 0 {
                board = board.set(Square::from_ints(file - 1, rank));
            }
            if file < 7 {
                board = board.set(Square::from_ints(file + 1, rank));
            }
            table[i as usize] = board;
        }
        table
    };

    static ref FILE_NEIGHBOURS : [BitBoard; 64] = {
        let mut table : [BitBoard; 64] = [BitBoard::empty(); 64];

        for i in 0..64 {
            let (file, rank) = Square(i).file_rank();
            let mut board = BitBoard::empty();
            if rank > 0 {
                board = board.set(Square::from_ints(file, rank - 1));
            }
            if rank < 7 {
                board = board.set(Square::from_ints(file, rank + 1));
            }
            table[i as usize] = board;
        }
        table
    };

    static ref ORTHOGONAL_NEIGHBOURS : [BitBoard; 64] = {
        let mut table : [BitBoard; 64] = [BitBoard::empty(); 64];

        for i in 0..64 {
            table[i] = RANK_NEIGHBOURS[i] | FILE_NEIGHBOURS[i];
        }
        table
    };
);<|endoftext|>


<commit_before>use engine::{Map, Tile};
use engine::builders::{MapBuilder, MapBuildResult};
use util::units::{AsTuple, Size};

use std::iter::repeat;

pub struct MapFromString {
    s: String,
}

impl MapFromString {

    pub fn new(s: &str) -> MapFromString {
        MapFromString { s: s.to_string() }
    }

}

impl MapBuilder for MapFromString {
    fn build(&self) -> MapBuildResult {
        let lines : Vec<_> = self.s.split('\n').collect();

        println!("{}", lines);

        let size = Size::new(10, 10);
        let (width, height) = size.as_tuple();
        let tiles: Vec<Vec<Tile>> = range(0, height).map(|_| repeat(Tile::Empty).take(width).collect()).collect();
        Ok(Map::new(tiles))
    }
}
<commit_msg>Implement MapFromString<commit_after>use engine::{Map, Tile};
use engine::builders::{MapBuilder, MapBuildError, MapBuildResult};

use std::iter::{IteratorExt};

pub struct MapFromString {
    s: String,
}

impl MapFromString {

    pub fn new(s: &str) -> MapFromString {
        MapFromString { s: s.to_string() }
    }

    fn build_line(&self, line: &str) -> Vec<Tile> {
        line.chars().map(|char| self.build_cell(char)).collect()
    }

    fn build_cell(&self, cell: char) -> Tile {
        match cell {
            ' ' => Tile::Empty,
            '.' => Tile::Floor,
            '#' => Tile::Wall,
            _ => { panic!("Invalid character in level string: {}", cell); }
        }
    }
}

impl MapBuilder for MapFromString {
    fn build(&self) -> MapBuildResult {
        let lines : Vec<_> = self.s.split('\n').collect();

        if !lines.iter().all(|x| x.len() == lines[0].len()) { return Err(MapBuildError::new("Different length lines")) };

        println!("{}", lines);

        let tiles: Vec<Vec<Tile>> = lines.iter().map(|&line| self.build_line(line)).collect();

        println!("{}", tiles);

        Ok(Map::new(tiles))
    }
}
<|endoftext|>


<commit_before>extern crate clap;
#[macro_use] extern crate log;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate libimagstore;
extern crate libimagrt;
extern crate libimagtag;
extern crate libimagutil;

mod ui;

fn main() {
    println!("Hello, world!");
}
<commit_msg>Implement main()<commit_after>extern crate clap;
#[macro_use] extern crate log;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate libimagstore;
extern crate libimagrt;
extern crate libimagtag;
extern crate libimagutil;

use std::process::exit;

use libimagrt::runtime::Runtime;
use libimagtag::tagable::Tagable;

mod ui;
mod util;

use ui::build_ui;
use util::build_entry_path;

use libimagutil::trace::trace_error;

fn main() {
    let name = "imag-store";
    let version = &version!()[..];
    let about = "Direct interface to the store. Use with great care!";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.err().unwrap());
            exit(1);
        }
    };

    rt.init_logger();

    debug!("Hello. Logging was just enabled");
    debug!("I already set up the Runtime object and build the commandline interface parser.");
    debug!("Lets get rollin' ...");

    let id = rt.cli().value_of("id").unwrap(); // enforced by clap
    rt.cli()
        .subcommand_name()
        .map_or_else(
            || {
                let add = rt.cli().value_of("add");
                let rem = rt.cli().value_of("remove");
                let set = rt.cli().value_of("set");

                alter(&rt, id, add, rem, set);
            },
            |name| {
                debug!("Call: {}", name);
                match name {
                    "list" => list(id, &rt),
                    _ => {
                        warn!("Unknown command");
                        // More error handling
                    },
                };
            });
}

fn alter(rt: &Runtime, id: &str, add: Option<&str>, rem: Option<&str>, set: Option<&str>) {
    let path = build_entry_path(rt, id);
    debug!("path = {:?}", path);
    rt.store()
        // "id" must be present, enforced via clap spec
        .retrieve(path)
        .map(|mut e| {
            add.map(|tags| {
                let tags = tags.split(",");
                for tag in tags {
                    info!("Adding tag '{}'", tag);
                    e.add_tag(String::from(tag)).map_err(|e| trace_error(&e));
                }
            });

            rem.map(|tags| {
                let tags = tags.split(",");
                for tag in tags {
                    info!("Removing tag '{}'", tag);
                    e.remove_tag(String::from(tag)).map_err(|e| trace_error(&e));
                }
            });

            set.map(|tags| {
                info!("Setting tags '{}'", tags);
                let tags = tags.split(",").map(String::from).collect();
                e.set_tags(tags);
            });
        })
        .map_err(|e| {
            info!("No entry.");
            debug!("{}", e);
        });
}

fn list(id: &str, rt: &Runtime) {
    let path = build_entry_path(rt, id);
    debug!("path = {:?}", path);

    let entry = rt.store().retrieve(path.clone());
    if entry.is_err() {
        debug!("Could not retrieve '{:?}' => {:?}", id, path);
        warn!("Could not retrieve entry '{}'", id);
        trace_error(&entry.err().unwrap());
        exit(1);
    }
    let entry = entry.unwrap();

    let scmd = rt.cli().subcommand_matches("list").unwrap(); // safe, we checked in main()

    let json_out = scmd.is_present("json");
    let line_out = scmd.is_present("linewise");
    let sepp_out = scmd.is_present("sep");
    let mut comm_out = scmd.is_present("commasep");

    let flags = vec![json_out, line_out, comm_out, sepp_out];

    if flags.iter().filter(|x| **x).count() > 1 {
        // More than one flag passed
        info!("Cannot do more than one thing");
        exit(1);
    }

    if !flags.iter().any(|v| *v) {
        // None of the flags passed, go to default
        comm_out = true;
    }

    let tags = entry.get_tags();
    if tags.is_err() {
        trace_error(&tags.err().unwrap());
        exit(1);
    }
    let tags = tags.unwrap();

    if json_out {
        unimplemented!()
    }

    if line_out {
        for tag in &tags {
            println!("{}", tag);
        }
    }

    if sepp_out {
        let sepp = scmd.value_of("sep").unwrap(); // we checked before
        println!("{}", tags.join(sepp));
    }

    if comm_out {
        println!("{}", tags.join(", "));
    }
}

<|endoftext|>


<commit_before>use super::invoke::{Invoke, Identity};
use super::code::{self, SignaturesBuilder, FunctionBuilder};
use super::{import, export};
use elements;

/// Module builder
pub struct ModuleBuilder<F=Identity> {
    callback: F,
    module: ModuleScaffold,
}

/// Location of the internal module function
pub struct CodeLocation {
    /// Location (index in 'functions' section) of the signature
    pub signature: u32,
    /// Location (index in the 'code' section) of the body
    pub body: u32,
}

#[derive(Default)]
struct ModuleScaffold {
    pub types: elements::TypeSection,
    pub import: elements::ImportSection,
    pub functions: elements::FunctionsSection,
    pub table: elements::TableSection,
    pub memory: elements::MemorySection,
    pub global: elements::GlobalSection,
    pub export: elements::ExportSection,
    pub start: Option<u32>,
    pub element: elements::ElementSection,
    pub code: elements::CodeSection,
    pub data: elements::DataSection,
    pub other: Vec<elements::Section>,
}

impl From<elements::Module> for ModuleScaffold {
    fn from(module: elements::Module) -> Self {
        let mut types: Option<elements::TypeSection> = None;
        let mut import: Option<elements::ImportSection> = None;
        let mut funcs: Option<elements::FunctionsSection> = None;
        let mut table: Option<elements::TableSection> = None;
        let mut memory: Option<elements::MemorySection> = None;
        let mut global: Option<elements::GlobalSection> = None;
        let mut export: Option<elements::ExportSection> = None;
        let mut start: Option<u32> = None;
        let mut element: Option<elements::ElementSection> = None;
        let mut code: Option<elements::CodeSection> = None;
        let mut data: Option<elements::DataSection> = None;

        let mut sections = module.into_sections();
        while let Some(section) = sections.pop() {
            match section {
                elements::Section::Type(sect) => { types = Some(sect); }
                elements::Section::Import(sect) => { import = Some(sect); }
                elements::Section::Function(sect) => { funcs = Some(sect); }
                elements::Section::Table(sect) => { table = Some(sect); }
                elements::Section::Memory(sect) => { memory = Some(sect); }
                elements::Section::Global(sect) => { global = Some(sect); }
                elements::Section::Export(sect) => { export = Some(sect); }
                elements::Section::Start(index) => { start = Some(index); }
                elements::Section::Element(sect) => { element = Some(sect); }
                elements::Section::Code(sect) => { code = Some(sect); }
                elements::Section::Data(sect) => { data = Some(sect); }
                _ => {}
            }
        }

        ModuleScaffold {
            types: types.unwrap_or_default(),
            import: import.unwrap_or_default(),
            functions: funcs.unwrap_or_default(),
            table: table.unwrap_or_default(),
            memory: memory.unwrap_or_default(),
            global: global.unwrap_or_default(),
            export: export.unwrap_or_default(),
            start: start,
            element: element.unwrap_or_default(),
            code: code.unwrap_or_default(),
            data: data.unwrap_or_default(),
            other: sections,
        }
    }
}

impl From<ModuleScaffold> for elements::Module {
    fn from(module: ModuleScaffold) -> Self {
        let mut sections = Vec::new();

        let types = module.types;
        if types.types().len() > 0 {
            sections.push(elements::Section::Type(types));
        }
        let import = module.import;
        if import.entries().len() > 0 {
            sections.push(elements::Section::Import(import));
        }
        let functions = module.functions;
        if functions.entries().len() > 0 {
            sections.push(elements::Section::Function(functions));
        }
        let table = module.table;
        if table.entries().len() > 0 {
            sections.push(elements::Section::Table(table));
        }
        let memory = module.memory;
        if memory.entries().len() > 0 {
            sections.push(elements::Section::Memory(memory));
        }
        let global = module.global;
        if global.entries().len() > 0 {
            sections.push(elements::Section::Global(global));
        }
        let export = module.export;
        if export.entries().len() > 0 {
            sections.push(elements::Section::Export(export));
        }
        if let Some(start) = module.start {
            sections.push(elements::Section::Start(start));
        }
        let element = module.element;
        if element.entries().len() > 0 {
            sections.push(elements::Section::Element(element));
        }
        let code = module.code;
        if code.bodies().len() > 0 {
            sections.push(elements::Section::Code(code));
        }
        let data = module.data;
        if data.entries().len() > 0 {
            sections.push(elements::Section::Data(data));
        }
        sections.extend(module.other);
        elements::Module::new(sections)
    }
}

impl ModuleBuilder {
    /// New empty module builder
    pub fn new() -> Self {
        ModuleBuilder::with_callback(Identity)
    }
}

impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
    /// New module builder with bound callback
    pub fn with_callback(callback: F) -> Self {
        ModuleBuilder {
            callback: callback,
            module: Default::default(),
        }
    }

    /// Builder from raw module
    pub fn with_module(mut self, module: elements::Module) -> Self {
        self.module = module.into();
        self
    }

    /// Fill module with sections from iterator
    pub fn with_sections<I>(mut self, sections: I) -> Self
        where I: IntoIterator<Item=elements::Section>
    {
        self.module.other.extend(sections);
        self
    }

    /// Add additional section
    pub fn with_section(mut self, section: elements::Section) -> Self {
        self.module.other.push(section);
        self
    }

    /// Binds to the type section, creates additional types when required
    pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
        self.push_signatures(bindings);
        self
    }

    /// Push stand-alone function definition, creating sections, signature and code blocks
    /// in corresponding sections.
    /// `FunctionDefinition` can be build using `builder::function` builder
    pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation {
        let signature = func.signature;
        let body = func.code;

        let type_ref = self.resolve_type_ref(signature);

        self.module.functions.entries_mut().push(elements::Func::new(type_ref));
        let signature_index = self.module.functions.entries_mut().len() as u32 - 1;
        self.module.code.bodies_mut().push(body);
        let body_index = self.module.code.bodies_mut().len() as u32 - 1;

        CodeLocation {
            signature: signature_index,
            body: body_index,
        }
    }

    fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
        match signature {
            code::Signature::Inline(func_type) => {
                // todo: maybe search for existing type
                self.module.types.types_mut().push(elements::Type::Function(func_type));
                self.module.types.types().len() as u32 - 1
            }
            code::Signature::TypeReference(type_ref) => {
                type_ref
            }
        }
    }

    /// Push one function signature, returning it's calling index.
    /// Can create corresponding type in type section.
    pub fn push_signature(&mut self, signature: code::Signature) -> u32 {
        self.resolve_type_ref(signature)
    }

    /// Push signatures in the module, returning corresponding indices of pushed signatures
    pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
        signatures.into_iter().map(|binding|
            self.resolve_type_ref(binding)
        ).collect()
    }

    /// Push import entry to module. Not that it does not update calling indices in
    /// function bodies.
    pub fn push_import(&mut self, import: elements::ImportEntry) -> u32 {
        self.module.import.entries_mut().push(import);
        // todo: actually update calling addresses in function bodies
        // todo: also batch push

        self.module.import.entries_mut().len() as u32 - 1
    }

    /// Add new function using dedicated builder
    pub fn function(self) -> FunctionBuilder<Self> {
        FunctionBuilder::with_callback(self)
    }

    /// Define functions section
    pub fn functions(self) -> SignaturesBuilder<Self> {
        SignaturesBuilder::with_callback(self)
    }

    /// With inserted import entry
    pub fn with_import(mut self, entry: elements::ImportEntry) -> Self {
        self.module.import.entries_mut().push(entry);
        self
    }

    /// With inserted import entry
    pub fn with_export(mut self, entry: elements::ExportEntry) -> Self {
        self.module.export.entries_mut().push(entry);
        self
    }

    /// Import entry builder
    pub fn import(self) -> import::ImportBuilder<Self> {
        import::ImportBuilder::with_callback(self)
    }

    /// Export entry builder
    pub fn export(self) -> export::ExportBuilder<Self> {
        export::ExportBuilder::with_callback(self)
    }

    /// Build module (final step)
    pub fn build(self) -> F::Result {
        self.callback.invoke(self.module.into())
    }
}

impl<F> Invoke<elements::FunctionsSection> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
	type Result = Self;

	fn invoke(self, section: elements::FunctionsSection) -> Self {
		self.with_section(elements::Section::Function(section))
    }
}

impl<F> Invoke<code::SignatureBindings> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, bindings: code::SignatureBindings) -> Self {
        self.with_signatures(bindings)
    }
}

impl<F> Invoke<code::FunctionDefinition> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, def: code::FunctionDefinition) -> Self {
        let mut b = self;
        b.push_function(def);
        b
    }
}

impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, entry: elements::ImportEntry) -> Self::Result {
        self.with_import(entry)
    }
}

impl<F> Invoke<elements::ExportEntry> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, entry: elements::ExportEntry) -> Self::Result {
        self.with_export(entry)
    }
}

/// Start new module builder
pub fn module() -> ModuleBuilder {
    ModuleBuilder::new()
}

/// Start builder to extend existing module
pub fn from_module(module: elements::Module) -> ModuleBuilder {
    ModuleBuilder::new().with_module(module)
}

#[cfg(test)]
mod tests {

    use super::module;

    #[test]
    fn smoky() {
        let module = module().build();
        assert_eq!(module.sections().len(), 0);
    }

    #[test]
    fn functions() {
        let module = module()
            .function()
                .signature().param().i32().build()
                .body().build()
                .build()
            .build();

        assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
        assert_eq!(module.functions_section().expect("function section to exist").entries().len(), 1);
        assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
    }

    #[test]
    fn export() {
        let module = module()
            .export().field("call").internal().func(0).build()
            .build();

        assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
    }
}
<commit_msg>global builder to module<commit_after>use super::invoke::{Invoke, Identity};
use super::code::{self, SignaturesBuilder, FunctionBuilder};
use super::{import, export, global};
use elements;

/// Module builder
pub struct ModuleBuilder<F=Identity> {
    callback: F,
    module: ModuleScaffold,
}

/// Location of the internal module function
pub struct CodeLocation {
    /// Location (index in 'functions' section) of the signature
    pub signature: u32,
    /// Location (index in the 'code' section) of the body
    pub body: u32,
}

#[derive(Default)]
struct ModuleScaffold {
    pub types: elements::TypeSection,
    pub import: elements::ImportSection,
    pub functions: elements::FunctionsSection,
    pub table: elements::TableSection,
    pub memory: elements::MemorySection,
    pub global: elements::GlobalSection,
    pub export: elements::ExportSection,
    pub start: Option<u32>,
    pub element: elements::ElementSection,
    pub code: elements::CodeSection,
    pub data: elements::DataSection,
    pub other: Vec<elements::Section>,
}

impl From<elements::Module> for ModuleScaffold {
    fn from(module: elements::Module) -> Self {
        let mut types: Option<elements::TypeSection> = None;
        let mut import: Option<elements::ImportSection> = None;
        let mut funcs: Option<elements::FunctionsSection> = None;
        let mut table: Option<elements::TableSection> = None;
        let mut memory: Option<elements::MemorySection> = None;
        let mut global: Option<elements::GlobalSection> = None;
        let mut export: Option<elements::ExportSection> = None;
        let mut start: Option<u32> = None;
        let mut element: Option<elements::ElementSection> = None;
        let mut code: Option<elements::CodeSection> = None;
        let mut data: Option<elements::DataSection> = None;

        let mut sections = module.into_sections();
        while let Some(section) = sections.pop() {
            match section {
                elements::Section::Type(sect) => { types = Some(sect); }
                elements::Section::Import(sect) => { import = Some(sect); }
                elements::Section::Function(sect) => { funcs = Some(sect); }
                elements::Section::Table(sect) => { table = Some(sect); }
                elements::Section::Memory(sect) => { memory = Some(sect); }
                elements::Section::Global(sect) => { global = Some(sect); }
                elements::Section::Export(sect) => { export = Some(sect); }
                elements::Section::Start(index) => { start = Some(index); }
                elements::Section::Element(sect) => { element = Some(sect); }
                elements::Section::Code(sect) => { code = Some(sect); }
                elements::Section::Data(sect) => { data = Some(sect); }
                _ => {}
            }
        }

        ModuleScaffold {
            types: types.unwrap_or_default(),
            import: import.unwrap_or_default(),
            functions: funcs.unwrap_or_default(),
            table: table.unwrap_or_default(),
            memory: memory.unwrap_or_default(),
            global: global.unwrap_or_default(),
            export: export.unwrap_or_default(),
            start: start,
            element: element.unwrap_or_default(),
            code: code.unwrap_or_default(),
            data: data.unwrap_or_default(),
            other: sections,
        }
    }
}

impl From<ModuleScaffold> for elements::Module {
    fn from(module: ModuleScaffold) -> Self {
        let mut sections = Vec::new();

        let types = module.types;
        if types.types().len() > 0 {
            sections.push(elements::Section::Type(types));
        }
        let import = module.import;
        if import.entries().len() > 0 {
            sections.push(elements::Section::Import(import));
        }
        let functions = module.functions;
        if functions.entries().len() > 0 {
            sections.push(elements::Section::Function(functions));
        }
        let table = module.table;
        if table.entries().len() > 0 {
            sections.push(elements::Section::Table(table));
        }
        let memory = module.memory;
        if memory.entries().len() > 0 {
            sections.push(elements::Section::Memory(memory));
        }
        let global = module.global;
        if global.entries().len() > 0 {
            sections.push(elements::Section::Global(global));
        }
        let export = module.export;
        if export.entries().len() > 0 {
            sections.push(elements::Section::Export(export));
        }
        if let Some(start) = module.start {
            sections.push(elements::Section::Start(start));
        }
        let element = module.element;
        if element.entries().len() > 0 {
            sections.push(elements::Section::Element(element));
        }
        let code = module.code;
        if code.bodies().len() > 0 {
            sections.push(elements::Section::Code(code));
        }
        let data = module.data;
        if data.entries().len() > 0 {
            sections.push(elements::Section::Data(data));
        }
        sections.extend(module.other);
        elements::Module::new(sections)
    }
}

impl ModuleBuilder {
    /// New empty module builder
    pub fn new() -> Self {
        ModuleBuilder::with_callback(Identity)
    }
}

impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
    /// New module builder with bound callback
    pub fn with_callback(callback: F) -> Self {
        ModuleBuilder {
            callback: callback,
            module: Default::default(),
        }
    }

    /// Builder from raw module
    pub fn with_module(mut self, module: elements::Module) -> Self {
        self.module = module.into();
        self
    }

    /// Fill module with sections from iterator
    pub fn with_sections<I>(mut self, sections: I) -> Self
        where I: IntoIterator<Item=elements::Section>
    {
        self.module.other.extend(sections);
        self
    }

    /// Add additional section
    pub fn with_section(mut self, section: elements::Section) -> Self {
        self.module.other.push(section);
        self
    }

    /// Binds to the type section, creates additional types when required
    pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
        self.push_signatures(bindings);
        self
    }

    /// Push stand-alone function definition, creating sections, signature and code blocks
    /// in corresponding sections.
    /// `FunctionDefinition` can be build using `builder::function` builder
    pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation {
        let signature = func.signature;
        let body = func.code;

        let type_ref = self.resolve_type_ref(signature);

        self.module.functions.entries_mut().push(elements::Func::new(type_ref));
        let signature_index = self.module.functions.entries_mut().len() as u32 - 1;
        self.module.code.bodies_mut().push(body);
        let body_index = self.module.code.bodies_mut().len() as u32 - 1;

        CodeLocation {
            signature: signature_index,
            body: body_index,
        }
    }

    fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
        match signature {
            code::Signature::Inline(func_type) => {
                // todo: maybe search for existing type
                self.module.types.types_mut().push(elements::Type::Function(func_type));
                self.module.types.types().len() as u32 - 1
            }
            code::Signature::TypeReference(type_ref) => {
                type_ref
            }
        }
    }

    /// Push one function signature, returning it's calling index.
    /// Can create corresponding type in type section.
    pub fn push_signature(&mut self, signature: code::Signature) -> u32 {
        self.resolve_type_ref(signature)
    }

    /// Push signatures in the module, returning corresponding indices of pushed signatures
    pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
        signatures.into_iter().map(|binding|
            self.resolve_type_ref(binding)
        ).collect()
    }

    /// Push import entry to module. Not that it does not update calling indices in
    /// function bodies.
    pub fn push_import(&mut self, import: elements::ImportEntry) -> u32 {
        self.module.import.entries_mut().push(import);
        // todo: actually update calling addresses in function bodies
        // todo: also batch push

        self.module.import.entries_mut().len() as u32 - 1
    }

    /// Add new function using dedicated builder
    pub fn function(self) -> FunctionBuilder<Self> {
        FunctionBuilder::with_callback(self)
    }

    /// Define functions section
    pub fn functions(self) -> SignaturesBuilder<Self> {
        SignaturesBuilder::with_callback(self)
    }

    /// With inserted import entry
    pub fn with_import(mut self, entry: elements::ImportEntry) -> Self {
        self.module.import.entries_mut().push(entry);
        self
    }

    /// With inserted export entry
    pub fn with_export(mut self, entry: elements::ExportEntry) -> Self {
        self.module.export.entries_mut().push(entry);
        self
    }

    /// With inserted global entry
    pub fn with_global(mut self, entry: elements::GlobalEntry) -> Self {
        self.module.global.entries_mut().push(entry);
        self
    }

    /// Import entry builder
    pub fn import(self) -> import::ImportBuilder<Self> {
        import::ImportBuilder::with_callback(self)
    }

    /// Export entry builder
    pub fn export(self) -> export::ExportBuilder<Self> {
        export::ExportBuilder::with_callback(self)
    }

    /// Glboal entry builder
    pub fn global(self) -> global::GlobalBuilder<Self> {
        global::GlobalBuilder::with_callback(self)
    }

    /// Build module (final step)
    pub fn build(self) -> F::Result {
        self.callback.invoke(self.module.into())
    }
}

impl<F> Invoke<elements::FunctionsSection> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
	type Result = Self;

	fn invoke(self, section: elements::FunctionsSection) -> Self {
		self.with_section(elements::Section::Function(section))
    }
}

impl<F> Invoke<code::SignatureBindings> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, bindings: code::SignatureBindings) -> Self {
        self.with_signatures(bindings)
    }
}

impl<F> Invoke<code::FunctionDefinition> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, def: code::FunctionDefinition) -> Self {
        let mut b = self;
        b.push_function(def);
        b
    }
}

impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, entry: elements::ImportEntry) -> Self::Result {
        self.with_import(entry)
    }
}

impl<F> Invoke<elements::ExportEntry> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, entry: elements::ExportEntry) -> Self::Result {
        self.with_export(entry)
    }
}

impl<F> Invoke<elements::GlobalEntry> for ModuleBuilder<F>
    where F: Invoke<elements::Module>
{
    type Result = Self;

    fn invoke(self, entry: elements::GlobalEntry) -> Self::Result {
        self.with_global(entry)
    }
}

/// Start new module builder
pub fn module() -> ModuleBuilder {
    ModuleBuilder::new()
}

/// Start builder to extend existing module
pub fn from_module(module: elements::Module) -> ModuleBuilder {
    ModuleBuilder::new().with_module(module)
}

#[cfg(test)]
mod tests {

    use super::module;

    #[test]
    fn smoky() {
        let module = module().build();
        assert_eq!(module.sections().len(), 0);
    }

    #[test]
    fn functions() {
        let module = module()
            .function()
                .signature().param().i32().build()
                .body().build()
                .build()
            .build();

        assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
        assert_eq!(module.functions_section().expect("function section to exist").entries().len(), 1);
        assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
    }

    #[test]
    fn export() {
        let module = module()
            .export().field("call").internal().func(0).build()
            .build();

        assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
    }

    #[test]
    fn global() {
        let module = module()
            .global().value_type().i64().mutable().init_expr(::elements::Opcode::I64Const(5)).build()
            .build();

        assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
    }
 }
<|endoftext|>


<commit_before>//! ODBC types those representation is compatible with the ODBC C API.
//!
//! This layer has not been created using automatic code generation. It is incomplete, i.e. it does
//! not contain every symbol or constant defined in the ODBC C headers. Symbols which are
//! deprecated since ODBC 3 have been left out intentionally. While some extra type safety has been
//! added by grouping some of C's `#define` constants into `enum`-types it mostly offers the same
//! power (all) and safety guarantess(none) as the wrapped C-API.
//! ODBC 4.0 is still under development by Microsoft, so these symbols are deactivated by default
//! in the cargo.toml

mod sqlreturn;
pub use self::sqlreturn::*;
mod info_type;
pub use self::info_type::*;
mod fetch_orientation;
pub use self::fetch_orientation::*;
mod attributes;
pub use self::attributes::*;
use std::os::raw::{c_void, c_short, c_ushort, c_int};

//These types can never be instantiated in Rust code.
pub enum Obj {}
pub enum Env {}
pub enum Dbc {}
pub enum Stmt {}

pub type SQLHANDLE = *mut Obj;
pub type SQLHENV = *mut Env;

/// The connection handle references storage of all information about the connection to the data
/// source, including status, transaction state, and error information.
pub type SQLHDBC = *mut Dbc;
pub type SQLHSTMT = *mut Stmt;

pub type SQLSMALLINT = c_short;
pub type SQLUSMALLINT = c_ushort;
pub type SQLINTEGER = c_int;
pub type SQLPOINTER = *mut c_void;
pub type SQLCHAR = u8;

#[cfg(all(windows, target_pointer_width = "64"))]
pub type SQLLEN = i64;
#[cfg(not(windows))]
pub type SQLLEN = SQLINTEGER;

pub type SQLHWND = SQLPOINTER;

// flags for null-terminated string
pub const SQL_NTS: SQLSMALLINT = -3;
pub const SQL_NTSL: SQLINTEGER = -3;

/// Maximum message length
pub const SQL_MAX_MESSAGE_LENGTH: SQLSMALLINT = 512;
pub const SQL_SQLSTATE_SIZE: usize = 5;

// Special SQLGetData indicator values
pub const SQL_NULL_DATA: SQLLEN = -1;
pub const SQL_NO_TOTAL: SQLLEN = -4;

/// SQL Data Types
#[repr(i16)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlDataType {
    SQL_UNKNOWN_TYPE = 0, // also called SQL_VARIANT_TYPE since odbc 4.0
    SQL_CHAR = 1,
    SQL_NUMERIC = 2,
    SQL_DECIMAL = 3,
    SQL_INTEGER = 4,
    SQL_SMALLINT = 5,
    SQL_FLOAT = 6,
    SQL_REAL = 7,
    SQL_DOUBLE = 8,
    SQL_DATETIME = 9,
    SQL_VARCHAR = 12,
    #[cfg(feature = "odbc_version_4")]
    SQL_UDT = 17,
    #[cfg(feature = "odbc_version_4")]
    SQL_ROW = 19,
    #[cfg(feature = "odbc_version_4")]
    SQL_ARRAY = 50,
    #[cfg(feature = "odbc_version_4")]
    SQL_MULTISET = 55,
}
pub use self::SqlDataType::*;

#[repr(i16)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlCDataType {
    SQL_C_CHAR = 1,
}
pub use self::SqlCDataType::*;

/// Represented in C headers as SQLSMALLINT
#[repr(i16)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum HandleType {
    SQL_HANDLE_ENV = 1,
    SQL_HANDLE_DBC = 2,
    SQL_HANDLE_STMT = 3,
    SQL_HANDLE_DESC = 4,
}
pub use self::HandleType::*;

/// Options for `SQLDriverConnect`
#[repr(u16)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlDriverConnectOption {
    SQL_DRIVER_NOPROMPT = 0,
    SQL_DRIVER_COMPLETE = 1,
    SQL_DRIVER_PROMPT = 2,
    SQL_DRIVER_COMPLETE_REQUIRED = 3,
}
pub use self::SqlDriverConnectOption::*;

#[cfg_attr(windows, link(name="odbc32"))]
#[cfg_attr(not(windows), link(name="odbc"))]
extern "C" {
    /// Allocates an environment, connection, statement, or descriptor handle.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLAllocHandle(handle_type: HandleType,
                          input_handle: SQLHANDLE,
                          output_Handle: *mut SQLHANDLE)
                          -> SQLRETURN;

    /// Frees resources associated with a specific environment, connection, statement, or
    /// descriptor handle.
    ///
    /// If `SQL_ERRQR` is returned the handle is still valid.
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLFreeHandle(handle_type: HandleType, handle: SQLHANDLE) -> SQLRETURN;

    /// Sets attributes that govern aspects of environments
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLSetEnvAttr(environment_handle: SQLHENV,
                         attribute: EnvironmentAttribute,
                         value: SQLPOINTER,
                         string_length: SQLINTEGER)
                         -> SQLRETURN;

    pub fn SQLDisconnect(connection_handle: SQLHDBC) -> SQLRETURN;

    pub fn SQLGetDiagRec(handle_type: HandleType,
                         handle: SQLHANDLE,
                         RecNumber: SQLSMALLINT,
                         state: *mut SQLCHAR,
                         native_error_ptr: *mut SQLINTEGER,
                         message_text: *mut SQLCHAR,
                         buffer_length: SQLSMALLINT,
                         text_length_ptr: *mut SQLSMALLINT)
                         -> SQLRETURN;

    pub fn SQLExecDirect(statement_handle: SQLHSTMT,
                         statement_text: *const SQLCHAR,
                         text_length: SQLINTEGER)
                         -> SQLRETURN;

    pub fn SQLNumResultCols(statement_handle: SQLHSTMT,
                            column_count_ptr: *mut SQLSMALLINT)
                            -> SQLRETURN;

    // Can be used since odbc version 3.8 to stream results
    pub fn SQLGetData(statement_handle: SQLHSTMT,
                      col_or_param_num: SQLUSMALLINT,
                      target_type: SqlCDataType,
                      target_value_ptr: SQLPOINTER,
                      buffer_length: SQLLEN,
                      str_len_or_ind_ptr: *mut SQLLEN)
                      -> SQLRETURN;

    pub fn SQLFetch(statement_handle: SQLHSTMT) -> SQLRETURN;

    /// Returns general information about the driver and data source associated with a connection
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLGetInfo(connection_handle: SQLHDBC,
                      info_type: InfoType,
                      info_value_ptr: SQLPOINTER,
                      buffer_length: SQLSMALLINT,
                      string_length_ptr: *mut SQLSMALLINT)
                      -> SQLRETURN;

    /// SQLConnect establishes connections to a driver and a data source.
    ///
    /// The connection handle references storage of all information about the connection to the
    /// data source, including status, transaction state, and error information.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, or
    /// `SQL_STILL_EXECUTING`
    pub fn SQLConnect(connection_handle: SQLHDBC,
                      server_name: *const SQLCHAR,
                      name_length_1: SQLSMALLINT,
                      user_name: *const SQLCHAR,
                      name_length_2: SQLSMALLINT,
                      authentication: *const SQLCHAR,
                      name_length_3: SQLSMALLINT)
                      -> SQLRETURN;

    /// Returns the list of table, catalog, or schema names, and table types, stored in a specific
    /// data source. The driver returns the information as a result set
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, or
    /// `SQL_STILL_EXECUTING`
    pub fn SQLTables(statement_handle: SQLHSTMT,
                     catalog_name: *const SQLCHAR,
                     name_length_1: SQLSMALLINT,
                     schema_name: *const SQLCHAR,
                     name_length_2: SQLSMALLINT,
                     table_name: *const SQLCHAR,
                     name_length_3: SQLSMALLINT,
                     TableType: *const SQLCHAR,
                     name_length_4: SQLSMALLINT)
                     -> SQLRETURN;

    /// Returns information about a data source. This function is implemented only by the Driver
    /// Manager.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, or `SQL_NO_DATA`
    pub fn SQLDataSources(environment_handle: SQLHENV,
                          direction: FetchOrientation,
                          server_name: *mut SQLCHAR,
                          buffer_length_1: SQLSMALLINT,
                          name_length_1: *mut SQLSMALLINT,
                          description: *mut SQLCHAR,
                          buffer_length_2: SQLSMALLINT,
                          name_length_2: *mut SQLSMALLINT)
                          -> SQLRETURN;

    /// An alternative to `SQLConnect`. It supports data sources that require more connection
    /// information than the three arguments in `SQLConnect`, dialog boxes to prompt the user for
    /// all connection information, and data sources that are not defined in the system information
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, `SQL_NO_DATA`,
    /// or `SQL_STILL_EXECUTING`
    pub fn SQLDriverConnect(connection_handle: SQLHDBC,
                            window_handle: SQLHWND,
                            in_connection_string: *const SQLCHAR,
                            string_length_1: SQLSMALLINT,
                            out_connection_string: *mut SQLCHAR,
                            buffer_length: SQLSMALLINT,
                            string_length_2: *mut SQLSMALLINT,
                            DriverCompletion: SqlDriverConnectOption)
                            -> SQLRETURN;

    /// Lists driver descriptions and driver attribute keywords. This function is implemented only
    /// by the Driver Manager.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, or `SQL_NO_DATA`
    pub fn SQLDrivers(henv: SQLHENV,
                      direction: FetchOrientation,
                      driver_desc: *mut SQLCHAR,
                      driver_desc_max: SQLSMALLINT,
                      out_driver_desc: *mut SQLSMALLINT,
                      driver_attributes: *mut SQLCHAR,
                      drvr_attr_max: SQLSMALLINT,
                      out_drvr_attr: *mut SQLSMALLINT)
                      -> SQLRETURN;
}
<commit_msg>Added comments<commit_after>//! ODBC types those representation is compatible with the ODBC C API.
//!
//! This layer has not been created using automatic code generation. It is incomplete, i.e. it does
//! not contain every symbol or constant defined in the ODBC C headers. Symbols which are
//! deprecated since ODBC 3 have been left out intentionally. While some extra type safety has been
//! added by grouping some of C's `#define` constants into `enum`-types it mostly offers the same
//! power (all) and safety guarantess(none) as the wrapped C-API.
//! ODBC 4.0 is still under development by Microsoft, so these symbols are deactivated by default
//! in the cargo.toml

mod sqlreturn;
pub use self::sqlreturn::*;
mod info_type;
pub use self::info_type::*;
mod fetch_orientation;
pub use self::fetch_orientation::*;
mod attributes;
pub use self::attributes::*;
use std::os::raw::{c_void, c_short, c_ushort, c_int};

//These types can never be instantiated in Rust code.
pub enum Obj {}
pub enum Env {}
pub enum Dbc {}
pub enum Stmt {}

pub type SQLHANDLE = *mut Obj;
pub type SQLHENV = *mut Env;

/// The connection handle references storage of all information about the connection to the data
/// source, including status, transaction state, and error information.
pub type SQLHDBC = *mut Dbc;
pub type SQLHSTMT = *mut Stmt;

/// 16 Bit signed integer
pub type SQLSMALLINT = c_short;
pub type SQLUSMALLINT = c_ushort;
pub type SQLINTEGER = c_int;
pub type SQLPOINTER = *mut c_void;
pub type SQLCHAR = u8;

#[cfg(all(windows, target_pointer_width = "64"))]
pub type SQLLEN = i64;
#[cfg(not(windows))]
pub type SQLLEN = SQLINTEGER;

pub type SQLHWND = SQLPOINTER;

// flags for null-terminated string
pub const SQL_NTS: SQLSMALLINT = -3;
pub const SQL_NTSL: SQLINTEGER = -3;

/// Maximum message length
pub const SQL_MAX_MESSAGE_LENGTH: SQLSMALLINT = 512;
pub const SQL_SQLSTATE_SIZE: usize = 5;

// Special SQLGetData indicator values
pub const SQL_NULL_DATA: SQLLEN = -1;
pub const SQL_NO_TOTAL: SQLLEN = -4;

/// SQL Data Types
#[repr(i16)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlDataType {
    SQL_UNKNOWN_TYPE = 0, // also called SQL_VARIANT_TYPE since odbc 4.0
    SQL_CHAR = 1,
    SQL_NUMERIC = 2,
    SQL_DECIMAL = 3,
    SQL_INTEGER = 4,
    SQL_SMALLINT = 5,
    SQL_FLOAT = 6,
    SQL_REAL = 7,
    SQL_DOUBLE = 8,
    SQL_DATETIME = 9,
    SQL_VARCHAR = 12,
    #[cfg(feature = "odbc_version_4")]
    SQL_UDT = 17,
    #[cfg(feature = "odbc_version_4")]
    SQL_ROW = 19,
    #[cfg(feature = "odbc_version_4")]
    SQL_ARRAY = 50,
    #[cfg(feature = "odbc_version_4")]
    SQL_MULTISET = 55,
}
pub use self::SqlDataType::*;

#[repr(i16)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlCDataType {
    SQL_C_CHAR = 1,
}
pub use self::SqlCDataType::*;

/// Represented in C headers as SQLSMALLINT
#[repr(i16)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum HandleType {
    SQL_HANDLE_ENV = 1,
    SQL_HANDLE_DBC = 2,
    SQL_HANDLE_STMT = 3,
    SQL_HANDLE_DESC = 4,
}
pub use self::HandleType::*;

/// Options for `SQLDriverConnect`
#[repr(u16)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlDriverConnectOption {
    SQL_DRIVER_NOPROMPT = 0,
    SQL_DRIVER_COMPLETE = 1,
    SQL_DRIVER_PROMPT = 2,
    SQL_DRIVER_COMPLETE_REQUIRED = 3,
}
pub use self::SqlDriverConnectOption::*;

#[cfg_attr(windows, link(name="odbc32"))]
#[cfg_attr(not(windows), link(name="odbc"))]
extern "C" {
    /// Allocates an environment, connection, statement, or descriptor handle.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLAllocHandle(handle_type: HandleType,
                          input_handle: SQLHANDLE,
                          output_Handle: *mut SQLHANDLE)
                          -> SQLRETURN;

    /// Frees resources associated with a specific environment, connection, statement, or
    /// descriptor handle.
    ///
    /// If `SQL_ERRQR` is returned the handle is still valid.
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLFreeHandle(handle_type: HandleType, handle: SQLHANDLE) -> SQLRETURN;

    /// Sets attributes that govern aspects of environments
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLSetEnvAttr(environment_handle: SQLHENV,
                         attribute: EnvironmentAttribute,
                         value: SQLPOINTER,
                         string_length: SQLINTEGER)
                         -> SQLRETURN;

    /// Closes the connection associated with a specific connection handle.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLDisconnect(connection_handle: SQLHDBC) -> SQLRETURN;

    pub fn SQLGetDiagRec(handle_type: HandleType,
                         handle: SQLHANDLE,
                         RecNumber: SQLSMALLINT,
                         state: *mut SQLCHAR,
                         native_error_ptr: *mut SQLINTEGER,
                         message_text: *mut SQLCHAR,
                         buffer_length: SQLSMALLINT,
                         text_length_ptr: *mut SQLSMALLINT)
                         -> SQLRETURN;

    pub fn SQLExecDirect(statement_handle: SQLHSTMT,
                         statement_text: *const SQLCHAR,
                         text_length: SQLINTEGER)
                         -> SQLRETURN;

    pub fn SQLNumResultCols(statement_handle: SQLHSTMT,
                            column_count_ptr: *mut SQLSMALLINT)
                            -> SQLRETURN;

    // Can be used since odbc version 3.8 to stream results
    pub fn SQLGetData(statement_handle: SQLHSTMT,
                      col_or_param_num: SQLUSMALLINT,
                      target_type: SqlCDataType,
                      target_value_ptr: SQLPOINTER,
                      buffer_length: SQLLEN,
                      str_len_or_ind_ptr: *mut SQLLEN)
                      -> SQLRETURN;

    pub fn SQLFetch(statement_handle: SQLHSTMT) -> SQLRETURN;

    /// Returns general information about the driver and data source associated with a connection
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, or `SQL_INVALID_HANDLE`
    pub fn SQLGetInfo(connection_handle: SQLHDBC,
                      info_type: InfoType,
                      info_value_ptr: SQLPOINTER,
                      buffer_length: SQLSMALLINT,
                      string_length_ptr: *mut SQLSMALLINT)
                      -> SQLRETURN;

    /// SQLConnect establishes connections to a driver and a data source.
    ///
    /// The connection handle references storage of all information about the connection to the
    /// data source, including status, transaction state, and error information.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, or
    /// `SQL_STILL_EXECUTING`
    pub fn SQLConnect(connection_handle: SQLHDBC,
                      server_name: *const SQLCHAR,
                      name_length_1: SQLSMALLINT,
                      user_name: *const SQLCHAR,
                      name_length_2: SQLSMALLINT,
                      authentication: *const SQLCHAR,
                      name_length_3: SQLSMALLINT)
                      -> SQLRETURN;

    /// Returns the list of table, catalog, or schema names, and table types, stored in a specific
    /// data source. The driver returns the information as a result set
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, or
    /// `SQL_STILL_EXECUTING`
    pub fn SQLTables(statement_handle: SQLHSTMT,
                     catalog_name: *const SQLCHAR,
                     name_length_1: SQLSMALLINT,
                     schema_name: *const SQLCHAR,
                     name_length_2: SQLSMALLINT,
                     table_name: *const SQLCHAR,
                     name_length_3: SQLSMALLINT,
                     TableType: *const SQLCHAR,
                     name_length_4: SQLSMALLINT)
                     -> SQLRETURN;

    /// Returns information about a data source. This function is implemented only by the Driver
    /// Manager.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, or `SQL_NO_DATA`
    pub fn SQLDataSources(environment_handle: SQLHENV,
                          direction: FetchOrientation,
                          server_name: *mut SQLCHAR,
                          buffer_length_1: SQLSMALLINT,
                          name_length_1: *mut SQLSMALLINT,
                          description: *mut SQLCHAR,
                          buffer_length_2: SQLSMALLINT,
                          name_length_2: *mut SQLSMALLINT)
                          -> SQLRETURN;

    /// An alternative to `SQLConnect`. It supports data sources that require more connection
    /// information than the three arguments in `SQLConnect`, dialog boxes to prompt the user for
    /// all connection information, and data sources that are not defined in the system information
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, `SQL_NO_DATA`,
    /// or `SQL_STILL_EXECUTING`
    pub fn SQLDriverConnect(connection_handle: SQLHDBC,
                            window_handle: SQLHWND,
                            in_connection_string: *const SQLCHAR,
                            string_length_1: SQLSMALLINT,
                            out_connection_string: *mut SQLCHAR,
                            buffer_length: SQLSMALLINT,
                            string_length_2: *mut SQLSMALLINT,
                            DriverCompletion: SqlDriverConnectOption)
                            -> SQLRETURN;

    /// Lists driver descriptions and driver attribute keywords. This function is implemented only
    /// by the Driver Manager.
    ///
    /// # Returns
    /// `SQL_SUCCESS`, `SQL_SUCCESS_WITH_INFO`, `SQL_ERROR`, `SQL_INVALID_HANDLE`, or `SQL_NO_DATA`
    pub fn SQLDrivers(henv: SQLHENV,
                      direction: FetchOrientation,
                      driver_desc: *mut SQLCHAR,
                      driver_desc_max: SQLSMALLINT,
                      out_driver_desc: *mut SQLSMALLINT,
                      driver_attributes: *mut SQLCHAR,
                      drvr_attr_max: SQLSMALLINT,
                      out_drvr_attr: *mut SQLSMALLINT)
                      -> SQLRETURN;
}
<|endoftext|>