<commit_before>//! Utilities for translating from codespan types into Language Server Protocol (LSP) types

use codespan::{
    ByteIndex, ByteOffset, ColumnIndex, FileId, Files, LineIndex, LineIndexOutOfBoundsError,
    LocationError, RawIndex, RawOffset, Span, SpanOutOfBoundsError,
};
use codespan_reporting::{Diagnostic, Severity};
use lsp_types as lsp;
use std::error;
use url::Url;

#[derive(derive_more::Display, Debug, PartialEq)]
pub enum Error {
    #[display(fmt = "Unable to correlate filename `{}` to url", _0)]
    UnableToCorrelateFilename(String),
    #[display(fmt = "Column out of bounds - given: {}, max: {}", given, max)]
    ColumnOutOfBounds {
        given: ColumnIndex,
        max: ColumnIndex,
    },
    Location(LocationError),
    LineIndexOutOfBounds(LineIndexOutOfBoundsError),
    SpanOutOfBounds(SpanOutOfBoundsError),
}

impl From<LocationError> for Error {
    fn from(e: LocationError) -> Error {
        Error::Location(e)
    }
}

impl From<LineIndexOutOfBoundsError> for Error {
    fn from(e: LineIndexOutOfBoundsError) -> Error {
        Error::LineIndexOutOfBounds(e)
    }
}

impl From<SpanOutOfBoundsError> for Error {
    fn from(e: SpanOutOfBoundsError) -> Error {
        Error::SpanOutOfBounds(e)
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Error::UnableToCorrelateFilename(_) | Error::ColumnOutOfBounds { .. } => None,
            Error::Location(error) => Some(error),
            Error::LineIndexOutOfBounds(error) => Some(error),
            Error::SpanOutOfBounds(error) => Some(error),
        }
    }
}

fn location_to_position(
    line_str: &str,
    line: LineIndex,
    column: ColumnIndex,
    byte_index: ByteIndex,
) -> Result<lsp::Position, Error> {
    if column.to_usize() > line_str.len() {
        let max = ColumnIndex(line_str.len() as RawIndex);
        let given = column;

        Err(Error::ColumnOutOfBounds { given, max })
    } else if !line_str.is_char_boundary(column.to_usize()) {
        let given = byte_index;

        Err(LocationError::InvalidCharBoundary { given }.into())
    } else {
        let line_utf16 = line_str[..column.to_usize()].encode_utf16();
        let character = line_utf16.count() as u64;
        let line = line.to_usize() as u64;

        Ok(lsp::Position { line, character })
    }
}

pub fn byte_index_to_position(
    files: &Files,
    file_id: FileId,
    byte_index: ByteIndex,
) -> Result<lsp::Position, Error> {
    let location = files.location(file_id, byte_index)?;
    let line_span = files.line_span(file_id, location.line)?;
    let line_str = files.source_slice(file_id, line_span)?;
    let column = ColumnIndex::from((byte_index - line_span.start()).0 as RawIndex);

    location_to_position(line_str, location.line, column, byte_index)
}

pub fn byte_span_to_range(files: &Files, file_id: FileId, span: Span) -> Result<lsp::Range, Error> {
    Ok(lsp::Range {
        start: byte_index_to_position(files, file_id, span.start())?,
        end: byte_index_to_position(files, file_id, span.end())?,
    })
}

pub fn character_to_line_offset(line: &str, character: u64) -> Result<ByteOffset, Error> {
    let line_len = ByteOffset::from(line.len() as RawOffset);
    let mut character_offset = 0;

    let mut chars = line.chars();
    while let Some(ch) = chars.next() {
        if character_offset == character {
            let chars_off = ByteOffset::from_str_len_utf8(chars.as_str());
            let ch_off = ByteOffset::from_char_len_utf8(ch);

            return Ok(line_len - chars_off - ch_off);
        }

        character_offset += ch.len_utf16() as u64;
    }

    // Handle positions after the last character on the line
    if character_offset == character {
        Ok(line_len)
    } else {
        Err(Error::ColumnOutOfBounds {
            given: ColumnIndex(character_offset as RawIndex),
            max: ColumnIndex(line.len() as RawIndex),
        })
    }
}

pub fn position_to_byte_index(
    files: &Files,
    file_id: FileId,
    position: &lsp::Position,
) -> Result<ByteIndex, Error> {
    let line_span = files.line_span(file_id, position.line as RawIndex)?;
    let source = files.source_slice(file_id, line_span)?;
    let byte_offset = character_to_line_offset(source, position.character)?;

    Ok(line_span.start() + byte_offset)
}

pub fn range_to_byte_span(
    files: &Files,
    file_id: FileId,
    range: &lsp::Range,
) -> Result<Span, Error> {
    Ok(Span::new(
        position_to_byte_index(files, file_id, &range.start)?,
        position_to_byte_index(files, file_id, &range.end)?,
    ))
}

pub fn make_lsp_severity(severity: Severity) -> lsp::DiagnosticSeverity {
    match severity {
        Severity::Error | Severity::Bug => lsp::DiagnosticSeverity::Error,
        Severity::Warning => lsp::DiagnosticSeverity::Warning,
        Severity::Note => lsp::DiagnosticSeverity::Information,
        Severity::Help => lsp::DiagnosticSeverity::Hint,
    }
}

/// Translates a `codespan_reporting::Diagnostic` to a
/// `languageserver_types::Diagnostic`.
///
/// Since the language client requires `Url`s to locate the diagnostics,
/// `correlate_file_url` is necessary to resolve codespan `FileName`s
///
/// `code` and `file` are left empty by this function
pub fn make_lsp_diagnostic(
    files: &Files,
    source: impl Into<Option<String>>,
    diagnostic: Diagnostic,
    mut correlate_file_url: impl FnMut(FileId, &str) -> Result<Url, ()>,
) -> Result<lsp::Diagnostic, Error> {
    // We need a position for the primary error so take the span from the first primary label
    let primary_file_id = diagnostic.primary_label.file_id;
    let primary_span = diagnostic.primary_label.span;
    let primary_label_range = byte_span_to_range(files, primary_file_id, primary_span)?;

    let related_information = diagnostic
        .secondary_labels
        .into_iter()
        .map(|label| {
            let file_id = label.file_id;
            let range = byte_span_to_range(files, file_id, label.span)?;
            let uri = correlate_file_url(file_id, files.name(file_id))
                .map_err(|()| Error::UnableToCorrelateFilename(files.name(file_id).to_owned()))?;

            Ok(lsp::DiagnosticRelatedInformation {
                location: lsp::Location { uri, range },
                message: label.message,
            })
        })
        .collect::<Result<Vec<_>, Error>>()?;

    Ok(lsp::Diagnostic {
        range: primary_label_range,
        code: diagnostic.code.map(lsp::NumberOrString::String),
        source: source.into(),
        severity: Some(make_lsp_severity(diagnostic.severity)),
        message: diagnostic.message,
        related_information: if related_information.is_empty() {
            None
        } else {
            Some(related_information)
        },
    })
}

#[cfg(test)]
mod tests {
    use codespan::Location;

    use super::*;

    #[test]
    fn position() {
        let text = r#"
let test = 2
let test1 = ""
test
"#;
        let mut files = Files::new();
        let file_id = files.add("test", text);
        let pos = position_to_byte_index(
            &files,
            file_id,
            &lsp::Position {
                line: 3,
                character: 2,
            },
        )
        .unwrap();
        assert_eq!(Location::new(3, 2), files.location(file_id, pos).unwrap());
    }

    // The protocol specifies that each `character` in position is a UTF-16 character.
    // This means that `å` and `ä` here counts as 1 while `𐐀` counts as 2.
    const UNICODE: &str = "åä t𐐀b";

    #[test]
    fn unicode_get_byte_index() {
        let mut files = Files::new();
        let file_id = files.add("unicode", UNICODE);

        let result = position_to_byte_index(
            &files,
            file_id,
            &lsp::Position {
                line: 0,
                character: 3,
            },
        );
        assert_eq!(result, Ok(ByteIndex::from(5)));

        let result = position_to_byte_index(
            &files,
            file_id,
            &lsp::Position {
                line: 0,
                character: 6,
            },
        );
        assert_eq!(result, Ok(ByteIndex::from(10)));
    }

    #[test]
    fn unicode_get_position() {
        let mut files = Files::new();
        let file_id = files.add("unicode", UNICODE);

        let result = byte_index_to_position(&files, file_id, ByteIndex::from(5));
        assert_eq!(
            result,
            Ok(lsp::Position {
                line: 0,
                character: 3,
            })
        );

        let result = byte_index_to_position(&files, file_id, ByteIndex::from(10));
        assert_eq!(
            result,
            Ok(lsp::Position {
                line: 0,
                character: 6,
            })
        );
    }
}
<commit_msg>Remove useless parameter from closure<commit_after>//! Utilities for translating from codespan types into Language Server Protocol (LSP) types

use codespan::{
    ByteIndex, ByteOffset, ColumnIndex, FileId, Files, LineIndex, LineIndexOutOfBoundsError,
    LocationError, RawIndex, RawOffset, Span, SpanOutOfBoundsError,
};
use codespan_reporting::{Diagnostic, Severity};
use lsp_types as lsp;
use std::error;
use url::Url;

#[derive(derive_more::Display, Debug, PartialEq)]
pub enum Error {
    #[display(fmt = "Unable to correlate filename `{}` to url", _0)]
    UnableToCorrelateFilename(String),
    #[display(fmt = "Column out of bounds - given: {}, max: {}", given, max)]
    ColumnOutOfBounds {
        given: ColumnIndex,
        max: ColumnIndex,
    },
    Location(LocationError),
    LineIndexOutOfBounds(LineIndexOutOfBoundsError),
    SpanOutOfBounds(SpanOutOfBoundsError),
}

impl From<LocationError> for Error {
    fn from(e: LocationError) -> Error {
        Error::Location(e)
    }
}

impl From<LineIndexOutOfBoundsError> for Error {
    fn from(e: LineIndexOutOfBoundsError) -> Error {
        Error::LineIndexOutOfBounds(e)
    }
}

impl From<SpanOutOfBoundsError> for Error {
    fn from(e: SpanOutOfBoundsError) -> Error {
        Error::SpanOutOfBounds(e)
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Error::UnableToCorrelateFilename(_) | Error::ColumnOutOfBounds { .. } => None,
            Error::Location(error) => Some(error),
            Error::LineIndexOutOfBounds(error) => Some(error),
            Error::SpanOutOfBounds(error) => Some(error),
        }
    }
}

fn location_to_position(
    line_str: &str,
    line: LineIndex,
    column: ColumnIndex,
    byte_index: ByteIndex,
) -> Result<lsp::Position, Error> {
    if column.to_usize() > line_str.len() {
        let max = ColumnIndex(line_str.len() as RawIndex);
        let given = column;

        Err(Error::ColumnOutOfBounds { given, max })
    } else if !line_str.is_char_boundary(column.to_usize()) {
        let given = byte_index;

        Err(LocationError::InvalidCharBoundary { given }.into())
    } else {
        let line_utf16 = line_str[..column.to_usize()].encode_utf16();
        let character = line_utf16.count() as u64;
        let line = line.to_usize() as u64;

        Ok(lsp::Position { line, character })
    }
}

pub fn byte_index_to_position(
    files: &Files,
    file_id: FileId,
    byte_index: ByteIndex,
) -> Result<lsp::Position, Error> {
    let location = files.location(file_id, byte_index)?;
    let line_span = files.line_span(file_id, location.line)?;
    let line_str = files.source_slice(file_id, line_span)?;
    let column = ColumnIndex::from((byte_index - line_span.start()).0 as RawIndex);

    location_to_position(line_str, location.line, column, byte_index)
}

pub fn byte_span_to_range(files: &Files, file_id: FileId, span: Span) -> Result<lsp::Range, Error> {
    Ok(lsp::Range {
        start: byte_index_to_position(files, file_id, span.start())?,
        end: byte_index_to_position(files, file_id, span.end())?,
    })
}

pub fn character_to_line_offset(line: &str, character: u64) -> Result<ByteOffset, Error> {
    let line_len = ByteOffset::from(line.len() as RawOffset);
    let mut character_offset = 0;

    let mut chars = line.chars();
    while let Some(ch) = chars.next() {
        if character_offset == character {
            let chars_off = ByteOffset::from_str_len_utf8(chars.as_str());
            let ch_off = ByteOffset::from_char_len_utf8(ch);

            return Ok(line_len - chars_off - ch_off);
        }

        character_offset += ch.len_utf16() as u64;
    }

    // Handle positions after the last character on the line
    if character_offset == character {
        Ok(line_len)
    } else {
        Err(Error::ColumnOutOfBounds {
            given: ColumnIndex(character_offset as RawIndex),
            max: ColumnIndex(line.len() as RawIndex),
        })
    }
}

pub fn position_to_byte_index(
    files: &Files,
    file_id: FileId,
    position: &lsp::Position,
) -> Result<ByteIndex, Error> {
    let line_span = files.line_span(file_id, position.line as RawIndex)?;
    let source = files.source_slice(file_id, line_span)?;
    let byte_offset = character_to_line_offset(source, position.character)?;

    Ok(line_span.start() + byte_offset)
}

pub fn range_to_byte_span(
    files: &Files,
    file_id: FileId,
    range: &lsp::Range,
) -> Result<Span, Error> {
    Ok(Span::new(
        position_to_byte_index(files, file_id, &range.start)?,
        position_to_byte_index(files, file_id, &range.end)?,
    ))
}

pub fn make_lsp_severity(severity: Severity) -> lsp::DiagnosticSeverity {
    match severity {
        Severity::Error | Severity::Bug => lsp::DiagnosticSeverity::Error,
        Severity::Warning => lsp::DiagnosticSeverity::Warning,
        Severity::Note => lsp::DiagnosticSeverity::Information,
        Severity::Help => lsp::DiagnosticSeverity::Hint,
    }
}

/// Translates a `codespan_reporting::Diagnostic` to a
/// `languageserver_types::Diagnostic`.
///
/// Since the language client requires `Url`s to locate the diagnostics,
/// `correlate_file_url` is necessary to resolve codespan `FileName`s
///
/// `code` and `file` are left empty by this function
pub fn make_lsp_diagnostic(
    files: &Files,
    source: impl Into<Option<String>>,
    diagnostic: Diagnostic,
    mut correlate_file_url: impl FnMut(FileId) -> Result<Url, ()>,
) -> Result<lsp::Diagnostic, Error> {
    // We need a position for the primary error so take the span from the first primary label
    let primary_file_id = diagnostic.primary_label.file_id;
    let primary_span = diagnostic.primary_label.span;
    let primary_label_range = byte_span_to_range(files, primary_file_id, primary_span)?;

    let related_information = diagnostic
        .secondary_labels
        .into_iter()
        .map(|label| {
            let file_id = label.file_id;
            let range = byte_span_to_range(files, file_id, label.span)?;
            let uri = correlate_file_url(file_id)
                .map_err(|()| Error::UnableToCorrelateFilename(files.name(file_id).to_owned()))?;

            Ok(lsp::DiagnosticRelatedInformation {
                location: lsp::Location { uri, range },
                message: label.message,
            })
        })
        .collect::<Result<Vec<_>, Error>>()?;

    Ok(lsp::Diagnostic {
        range: primary_label_range,
        code: diagnostic.code.map(lsp::NumberOrString::String),
        source: source.into(),
        severity: Some(make_lsp_severity(diagnostic.severity)),
        message: diagnostic.message,
        related_information: if related_information.is_empty() {
            None
        } else {
            Some(related_information)
        },
    })
}

#[cfg(test)]
mod tests {
    use codespan::Location;

    use super::*;

    #[test]
    fn position() {
        let text = r#"
let test = 2
let test1 = ""
test
"#;
        let mut files = Files::new();
        let file_id = files.add("test", text);
        let pos = position_to_byte_index(
            &files,
            file_id,
            &lsp::Position {
                line: 3,
                character: 2,
            },
        )
        .unwrap();
        assert_eq!(Location::new(3, 2), files.location(file_id, pos).unwrap());
    }

    // The protocol specifies that each `character` in position is a UTF-16 character.
    // This means that `å` and `ä` here counts as 1 while `𐐀` counts as 2.
    const UNICODE: &str = "åä t𐐀b";

    #[test]
    fn unicode_get_byte_index() {
        let mut files = Files::new();
        let file_id = files.add("unicode", UNICODE);

        let result = position_to_byte_index(
            &files,
            file_id,
            &lsp::Position {
                line: 0,
                character: 3,
            },
        );
        assert_eq!(result, Ok(ByteIndex::from(5)));

        let result = position_to_byte_index(
            &files,
            file_id,
            &lsp::Position {
                line: 0,
                character: 6,
            },
        );
        assert_eq!(result, Ok(ByteIndex::from(10)));
    }

    #[test]
    fn unicode_get_position() {
        let mut files = Files::new();
        let file_id = files.add("unicode", UNICODE);

        let result = byte_index_to_position(&files, file_id, ByteIndex::from(5));
        assert_eq!(
            result,
            Ok(lsp::Position {
                line: 0,
                character: 3,
            })
        );

        let result = byte_index_to_position(&files, file_id, ByteIndex::from(10));
        assert_eq!(
            result,
            Ok(lsp::Position {
                line: 0,
                character: 6,
            })
        );
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(maud_macros)]

extern crate maud;

#[test]
fn literals() {
    let s = html!("du\tcks" -23 3.14 '\n' "geese").to_string();
    assert_eq!(s, "du\tcks-233.14\ngeese");
}

#[test]
fn escaping() {
    let s = html!("<flim&flam>").to_string();
    assert_eq!(s, "<flim&flam>");
}

#[test]
fn semicolons() {
    let s = html! {
        "one";
        "two";
        "three";
        ;;;;;;;;;;;;;;;;;;;;;;;;
        "four";
    }.to_string();
    assert_eq!(s, "onetwothreefour");
}

#[test]
fn blocks() {
    let s = html! {
        "hello"
        {
            " ducks" " geese"
        }
        " swans"
    }.to_string();
    assert_eq!(s, "hello ducks geese swans");
}

mod elements {
    #[test]
    fn simple() {
        let s = html! {
            p { b { "pickle" } "barrel" i { "kumquat" } }
        }.to_string();
        assert_eq!(s, "
picklebarrelkumquat
");
    }

    #[test]
    fn nesting() {
        let s = html!(html body div p sup "butts").to_string();
        assert_eq!(s, "

butts

");
    }

    #[test]
    fn empty() {
        let s = html!("pinkie" br/ "pie").to_string();
        assert_eq!(s, "pinkie
pie");
    }

    #[test]
    fn attributes() {
        let s = html! {
            link rel="stylesheet" href="styles.css"/
            section id="midriff" {
                p class="hotpink" "Hello!"
            }
        }.to_string();
        assert_eq!(s, concat!(
                r#"<link rel="stylesheet" href="styles.css">"#,
                r#"

Hello!

"#));
    }

    #[test]
    fn empty_attributes() {
        let s = html! { div readonly? input type="checkbox" checked? / }.to_string();
        assert_eq!(s, r#"
<input type="checkbox" checked>
"#);
    }
}

mod splices {
    #[test]
    fn literals() {
        let s = html! { $"<pinkie>" }.to_string();
        assert_eq!(s, "<pinkie>");
    }

    #[test]
    fn raw_literals() {
        let s = html! { $$"<pinkie>" }.to_string();
        assert_eq!(s, "<pinkie>");
    }

    #[test]
    fn blocks() {
        let s = html! {
            ${
                let mut result = 1i32;
                for i in 2..11 {
                    result *= i;
                }
                result
            }
        }.to_string();
        assert_eq!(s, "3628800");
    }

    #[test]
    fn attributes() {
        let rocks = true;
        let s = html! {
            input checked?=true /
            input checked?=false /
            input checked?=rocks /
            input checked?=(!rocks) /
        }.to_string();
        assert_eq!(s, concat!(
                r#"<input checked>"#,
                r#"<input>"#,
                r#"<input checked>"#,
                r#"<input>"#));
    }

    static BEST_PONY: &'static str = "Pinkie Pie";

    #[test]
    fn statics() {
        let s = html! { $BEST_PONY }.to_string();
        assert_eq!(s, "Pinkie Pie");
    }

    #[test]
    fn closures() {
        let best_pony = "Pinkie Pie";
        let s = html! { $best_pony }.to_string();
        assert_eq!(s, "Pinkie Pie");
    }

    /// An example struct, for testing purposes only
    struct Creature {
        name: &'static str,
        /// Rating out of 10, where:
        /// * 0 is a naked mole rat with dysentery
        /// * 10 is Sweetie Belle in a milkshake
        adorableness: u32,
    }

    impl Creature {
        fn repugnance(&self) -> u32 {
            10 - self.adorableness
        }
    }

    #[test]
    fn structs() {
        let pinkie = Creature {
            name: "Pinkie Pie",
            adorableness: 9,
        };
        let s = html! {
            "Name: " $pinkie.name ". Rating: " $pinkie.repugnance()
        }.to_string();
        assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
    }

    // FIXME: See <https://github.com/rust-lang/rust/issues/16617>
    // for why this is commented out
    /*
    #[test]
    fn nested_macro_invocation() {
        let best_pony = "Pinkie Pie";
        let s = html! { $(format!("{}", best_pony)) }.to_string();
        assert_eq!(s, "Pinkie Pie");
    }
    */
}

#[test]
fn issue_1() {
    let markup = html! { "Test" };
    let _ = markup.to_string();
}

mod control {
    #[test]
    fn if_expr() {
        for (number, &name) in (1..4).zip(["one", "two", "three"].iter()) {
            let s = html! {
                $if number == 1 {
                    "one"
                } $else if number == 2 {
                    "two"
                } $else if number == 3 {
                    "three"
                } $else {
                    "oh noes"
                }
            }.to_string();
            assert_eq!(s, name);
        }
    }

    #[test]
    fn if_let() {
        for &(input, output) in [(Some("yay"), "yay"), (None, "oh noes")].iter() {
            let s = html! {
                $if let Some(value) = input {
                    $value
                } $else {
                    "oh noes"
                }
            }.to_string();
            assert_eq!(s, output);
        }
    }

    #[test]
    fn for_expr() {
        let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
        let s = html! {
            ul $for pony in &ponies {
                li $pony
            }
        }.to_string();
        assert_eq!(s, concat!(
                "
",
                "
Apple Bloom
",
                "
Scootaloo
",
                "
Sweetie Belle
",
                "
"));
    }
}
<commit_msg>Add regression test for #13<commit_after>#![feature(plugin)]
#![plugin(maud_macros)]

extern crate maud;

#[test]
fn literals() {
    let s = html!("du\tcks" -23 3.14 '\n' "geese").to_string();
    assert_eq!(s, "du\tcks-233.14\ngeese");
}

#[test]
fn escaping() {
    let s = html!("<flim&flam>").to_string();
    assert_eq!(s, "<flim&flam>");
}

#[test]
fn semicolons() {
    let s = html! {
        "one";
        "two";
        "three";
        ;;;;;;;;;;;;;;;;;;;;;;;;
        "four";
    }.to_string();
    assert_eq!(s, "onetwothreefour");
}

#[test]
fn blocks() {
    let s = html! {
        "hello"
        {
            " ducks" " geese"
        }
        " swans"
    }.to_string();
    assert_eq!(s, "hello ducks geese swans");
}

mod elements {
    #[test]
    fn simple() {
        let s = html! {
            p { b { "pickle" } "barrel" i { "kumquat" } }
        }.to_string();
        assert_eq!(s, "
picklebarrelkumquat
");
    }

    #[test]
    fn nesting() {
        let s = html!(html body div p sup "butts").to_string();
        assert_eq!(s, "

butts

");
    }

    #[test]
    fn empty() {
        let s = html!("pinkie" br/ "pie").to_string();
        assert_eq!(s, "pinkie
pie");
    }

    #[test]
    fn attributes() {
        let s = html! {
            link rel="stylesheet" href="styles.css"/
            section id="midriff" {
                p class="hotpink" "Hello!"
            }
        }.to_string();
        assert_eq!(s, concat!(
                r#"<link rel="stylesheet" href="styles.css">"#,
                r#"

Hello!

"#));
    }

    #[test]
    fn empty_attributes() {
        let s = html! { div readonly? input type="checkbox" checked? / }.to_string();
        assert_eq!(s, r#"
<input type="checkbox" checked>
"#);
    }
}

mod splices {
    #[test]
    fn literals() {
        let s = html! { $"<pinkie>" }.to_string();
        assert_eq!(s, "<pinkie>");
    }

    #[test]
    fn raw_literals() {
        let s = html! { $$"<pinkie>" }.to_string();
        assert_eq!(s, "<pinkie>");
    }

    #[test]
    fn blocks() {
        let s = html! {
            ${
                let mut result = 1i32;
                for i in 2..11 {
                    result *= i;
                }
                result
            }
        }.to_string();
        assert_eq!(s, "3628800");
    }

    #[test]
    fn attributes() {
        let rocks = true;
        let s = html! {
            input checked?=true /
            input checked?=false /
            input checked?=rocks /
            input checked?=(!rocks) /
        }.to_string();
        assert_eq!(s, concat!(
                r#"<input checked>"#,
                r#"<input>"#,
                r#"<input checked>"#,
                r#"<input>"#));
    }

    static BEST_PONY: &'static str = "Pinkie Pie";

    #[test]
    fn statics() {
        let s = html! { $BEST_PONY }.to_string();
        assert_eq!(s, "Pinkie Pie");
    }

    #[test]
    fn closures() {
        let best_pony = "Pinkie Pie";
        let s = html! { $best_pony }.to_string();
        assert_eq!(s, "Pinkie Pie");
    }

    /// An example struct, for testing purposes only
    struct Creature {
        name: &'static str,
        /// Rating out of 10, where:
        /// * 0 is a naked mole rat with dysentery
        /// * 10 is Sweetie Belle in a milkshake
        adorableness: u32,
    }

    impl Creature {
        fn repugnance(&self) -> u32 {
            10 - self.adorableness
        }
    }

    #[test]
    fn structs() {
        let pinkie = Creature {
            name: "Pinkie Pie",
            adorableness: 9,
        };
        let s = html! {
            "Name: " $pinkie.name ". Rating: " $pinkie.repugnance()
        }.to_string();
        assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
    }

    // FIXME: See <https://github.com/rust-lang/rust/issues/16617>
    // for why this is commented out
    /*
    #[test]
    fn nested_macro_invocation() {
        let best_pony = "Pinkie Pie";
        let s = html! { $(format!("{}", best_pony)) }.to_string();
        assert_eq!(s, "Pinkie Pie");
    }
    */
}

#[test]
fn issue_1() {
    let markup = html! { "Test" };
    let _ = markup.to_string();
}

#[test]
fn issue_13() {
    let owned = String::from("yay");
    let _ = html! { $owned }.to_string();
}

mod control {
    #[test]
    fn if_expr() {
        for (number, &name) in (1..4).zip(["one", "two", "three"].iter()) {
            let s = html! {
                $if number == 1 {
                    "one"
                } $else if number == 2 {
                    "two"
                } $else if number == 3 {
                    "three"
                } $else {
                    "oh noes"
                }
            }.to_string();
            assert_eq!(s, name);
        }
    }

    #[test]
    fn if_let() {
        for &(input, output) in [(Some("yay"), "yay"), (None, "oh noes")].iter() {
            let s = html! {
                $if let Some(value) = input {
                    $value
                } $else {
                    "oh noes"
                }
            }.to_string();
            assert_eq!(s, output);
        }
    }

    #[test]
    fn for_expr() {
        let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
        let s = html! {
            ul $for pony in &ponies {
                li $pony
            }
        }.to_string();
        assert_eq!(s, concat!(
                "
",
                "
Apple Bloom
",
                "
Scootaloo
",
                "
Sweetie Belle
",
                "
"));
    }
}
<|endoftext|>


<commit_before>//! The element nodes.

#![allow(clippy::new_without_default)]
#![allow(clippy::should_implement_trait)]

use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::Hash;

use crate::node::{Attributes, Children, Node, Value};

pub mod path;
pub mod tag;

#[doc(hidden)]
#[derive(Clone, Debug)]
pub struct Element {
    name: String,
    attributes: Attributes,
    children: Children,
}

impl Element {
    pub fn new<T>(name: T) -> Self
    where
        T: Into<String>,
    {
        Element {
            name: name.into(),
            attributes: Attributes::new(),
            children: Children::new(),
        }
    }

    #[inline]
    pub fn get_name(&self) -> &String {
        &self.name
    }

    #[inline]
    pub fn get_attributes(&self) -> &Attributes {
        &self.attributes
    }

    #[inline]
    pub fn get_children(&self) -> &Children {
        &self.children
    }
}

impl fmt::Display for Element {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "<{}", self.name)?;
        let mut attributes = self.attributes.iter().collect::<Vec<_>>();
        attributes.sort_by_key(|pair| pair.0.as_str());
        for (name, value) in attributes {
            match (value.contains('\''), value.contains('"')) {
                (true, false) | (false, false) => {
                    write!(formatter, r#" {}="{}""#, name, value)?;
                }
                (false, true) => {
                    write!(formatter, r#" {}='{}'"#, name, value)?;
                }
                _ => {}
            }
        }
        if self.children.is_empty() {
            return write!(formatter, "/>");
        }
        write!(formatter, ">")?;
        for child in self.children.iter() {
            write!(formatter, "\n{}", child)?;
        }
        write!(formatter, "\n</{}>", self.name)
    }
}

impl Node for Element {
    #[inline]
    fn append<T>(&mut self, node: T)
    where
        T: Node,
    {
        self.children.push(Box::new(node));
    }

    #[inline]
    fn assign<T, U>(&mut self, name: T, value: U)
    where
        T: Into<String>,
        U: Into<Value>,
    {
        self.attributes.insert(name.into(), value.into());
    }
}

macro_rules! implement {
    ($(#[$doc:meta] struct $struct_name:ident)*) => ($(
        #[$doc]
        #[derive(Clone, Debug)]
        pub struct $struct_name {
            inner: Element,
        }

        impl $struct_name {
            /// Create a node.
            #[inline]
            pub fn new() -> Self {
                $struct_name {
                    inner: Element::new(tag::$struct_name),
                }
            }
        }

        impl Default for $struct_name {
            fn default() -> Self {
                Self::new()
            }
        }

        impl super::NodeDefaultHash for $struct_name {
            #[inline]
            fn default_hash(&self, state: &mut DefaultHasher) {
                self.inner.default_hash(state);
            }
        }

        node! { $struct_name::inner }
    )*);
}

// Implement Hash for def duplicate recognization
impl super::NodeDefaultHash for Element {
    fn default_hash(&self, state: &mut DefaultHasher) {
        self.name.hash(state);
        self.attributes.iter().for_each(|(key, value)| {
            key.hash(state);
            value.hash(state)
        });
        self.children
            .iter()
            .for_each(|child| child.default_hash(state));
    }
}

implement! {
    #[doc = "An [`animate`](https://www.w3.org/TR/SVG/animate.html#AnimateElement) element."]
    struct Animate

    #[doc = "An [`animateColor`](https://www.w3.org/TR/SVG/animate.html#AnimateColorElement) element."]
    struct AnimateColor

    #[doc = "An [`animateMotion`](https://www.w3.org/TR/SVG/animate.html#AnimateMotionElement) element."]
    struct AnimateMotion

    #[doc = "An [`animateTransform`](https://www.w3.org/TR/SVG/animate.html#AnimateTransformElement) element."]
    struct AnimateTransform

    #[doc = "A [`circle`](https://www.w3.org/TR/SVG/shapes.html#CircleElement) element."]
    struct Circle

    #[doc = "A [`clipPath`](https://www.w3.org/TR/SVG/masking.html#ClipPathElement) element."]
    struct ClipPath

    #[doc = "A [`defs`](https://www.w3.org/TR/SVG/struct.html#DefsElement) element."]
    struct Definitions

    #[doc = "A [`desc`](https://www.w3.org/TR/SVG/struct.html#DescElement) element."]
    struct Description

    #[doc = "An [`ellipse`](https://www.w3.org/TR/SVG/shapes.html#EllipseElement) element."]
    struct Ellipse

    #[doc = "A [`filter`](https://www.w3.org/TR/SVG/filters.html#FilterElement) element."]
    struct Filter

    #[doc = "A [`foreignObject`](https://www.w3.org/TR/SVG/embedded.html#ForeignObjectElement) element."]
    struct ForeignObject

    #[doc = "A [`g`](https://www.w3.org/TR/SVG/struct.html#GElement) element."]
    struct Group

    #[doc = "An [`image`](https://www.w3.org/TR/SVG/struct.html#ImageElement) element."]
    struct Image

    #[doc = "A [`line`](https://www.w3.org/TR/SVG/shapes.html#LineElement) element."]
    struct Line

    #[doc = "A [`linearGradient`](https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement) element."]
    struct LinearGradient

    #[doc = "An [`a`](https://www.w3.org/TR/SVG/linking.html#AElement) element."]
    struct Link

    #[doc = "A [`marker`](https://www.w3.org/TR/SVG/painting.html#MarkerElement) element."]
    struct Marker

    #[doc = "A [`mask`](https://www.w3.org/TR/SVG/masking.html#MaskElement) element."]
    struct Mask

    #[doc = "An [`mpath`](https://www.w3.org/TR/SVG/animate.html#MPathElement) element."]
    struct MotionPath

    #[doc = "A [`path`](https://www.w3.org/TR/SVG/paths.html#PathElement) element."]
    struct Path

    #[doc = "A [`pattern`](https://www.w3.org/TR/SVG/pservers.html#PatternElement) element."]
    struct Pattern

    #[doc = "A [`polygon`](https://www.w3.org/TR/SVG/shapes.html#PolygonElement) element."]
    struct Polygon

    #[doc = "A [`polyline`](https://www.w3.org/TR/SVG/shapes.html#PolylineElement) element."]
    struct Polyline

    #[doc = "A [`radialGradient`](https://www.w3.org/TR/SVG/pservers.html#RadialGradientElement) element."]
    struct RadialGradient

    #[doc = "A [`rect`](https://www.w3.org/TR/SVG/shapes.html#RectElement) element."]
    struct Rectangle

    #[doc = "A [`stop`](https://www.w3.org/TR/SVG/pservers.html#StopElement) element."]
    struct Stop

    #[doc = "A [`symbol`](https://www.w3.org/TR/SVG/struct.html#SymbolElement) element."]
    struct Symbol

    #[doc = "A [`text`](https://www.w3.org/TR/SVG/text.html#TextElement) element."]
    struct Text

    #[doc = "A [`textPath`](https://www.w3.org/TR/SVG/text.html#TextPathElement) element."]
    struct TextPath

    #[doc = "A [`title`](https://www.w3.org/TR/SVG/struct.html#TitleElement) element."]
    struct Title

    #[doc = "A [`use`](https://www.w3.org/TR/SVG/struct.html#UseElement) element."]
    struct Use
}

macro_rules! implement {
    (@itemize $i:item) => ($i);
    ($(
        #[$doc:meta]
        struct $struct_name:ident
        [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block
    )*) => ($(
        #[$doc]
        #[derive(Clone, Debug)]
        pub struct $struct_name {
            inner: Element,
        }

        implement! { @itemize
            impl $struct_name {
                /// Create a node.
                #[inline]
                pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self {
                    #[inline(always)]
                    fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body
                    let mut inner = Element::new(tag::$struct_name);
                    initialize(&mut inner $(, $an)*);
                    $struct_name {
                        inner: inner,
                    }
                }
            }
        }

        impl super::NodeDefaultHash for $struct_name {
            fn default_hash(&self, state: &mut DefaultHasher) {
                self.inner.default_hash(state);
            }
        }

        node! { $struct_name::inner }
    )*);
}

implement! {
    #[doc = "An [`svg`](https://www.w3.org/TR/SVG/struct.html#SVGElement) element."]
    struct SVG [] [inner] {
        inner.assign("xmlns", "http://www.w3.org/2000/svg");
    }

    #[doc = "A [`script`](https://www.w3.org/TR/SVG/script.html#ScriptElement) element."]
    struct Script [T: Into<String>] [inner, content: T] {
        inner.append(crate::node::Text::new(content));
    }

    #[doc = "A [`style`](https://www.w3.org/TR/SVG/styling.html#StyleElement) element."]
    struct Style [T: Into<String>] [inner, content: T] {
        inner.append(crate::node::Text::new(content));
    }
}

#[cfg(test)]
mod tests {
    use super::{Element, Style};
    use crate::node::Node;

    #[test]
    fn element_display() {
        let mut element = Element::new("foo");
        element.assign("x", -10);
        element.assign("y", "10px");
        element.assign("s", (12.5, 13.0));
        element.assign("c", "green");
        element.append(Element::new("bar"));

        assert_eq!(
            element.to_string(),
            "<foo c=\"green\" s=\"12.5 13\" x=\"-10\" y=\"10px\">\n\
             <bar/>\n\
             </foo>\
             "
        );
    }

    #[test]
    fn element_display_quotes() {
        let mut element = Element::new("foo");
        element.assign("s", "'single'");
        element.assign("d", r#""double""#);
        element.assign("m", r#""mixed'"#);

        assert_eq!(element.to_string(), r#"<foo d='"double"' s="'single'"/>"#);
    }

    #[test]
    fn style_display() {
        let element = Style::new("* { font-family: foo; }");

        assert_eq!(
            element.to_string(),
            "<style>\n\
             * { font-family: foo; }\n\
             </style>\
             "
        );
    }
}
<commit_msg>Remove a comment<commit_after>//! The element nodes.

#![allow(clippy::new_without_default)]
#![allow(clippy::should_implement_trait)]

use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::Hash;

use crate::node::{Attributes, Children, Node, Value};

pub mod path;
pub mod tag;

#[doc(hidden)]
#[derive(Clone, Debug)]
pub struct Element {
    name: String,
    attributes: Attributes,
    children: Children,
}

impl Element {
    pub fn new<T>(name: T) -> Self
    where
        T: Into<String>,
    {
        Element {
            name: name.into(),
            attributes: Attributes::new(),
            children: Children::new(),
        }
    }

    #[inline]
    pub fn get_name(&self) -> &String {
        &self.name
    }

    #[inline]
    pub fn get_attributes(&self) -> &Attributes {
        &self.attributes
    }

    #[inline]
    pub fn get_children(&self) -> &Children {
        &self.children
    }
}

impl fmt::Display for Element {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "<{}", self.name)?;
        let mut attributes = self.attributes.iter().collect::<Vec<_>>();
        attributes.sort_by_key(|pair| pair.0.as_str());
        for (name, value) in attributes {
            match (value.contains('\''), value.contains('"')) {
                (true, false) | (false, false) => {
                    write!(formatter, r#" {}="{}""#, name, value)?;
                }
                (false, true) => {
                    write!(formatter, r#" {}='{}'"#, name, value)?;
                }
                _ => {}
            }
        }
        if self.children.is_empty() {
            return write!(formatter, "/>");
        }
        write!(formatter, ">")?;
        for child in self.children.iter() {
            write!(formatter, "\n{}", child)?;
        }
        write!(formatter, "\n</{}>", self.name)
    }
}

impl Node for Element {
    #[inline]
    fn append<T>(&mut self, node: T)
    where
        T: Node,
    {
        self.children.push(Box::new(node));
    }

    #[inline]
    fn assign<T, U>(&mut self, name: T, value: U)
    where
        T: Into<String>,
        U: Into<Value>,
    {
        self.attributes.insert(name.into(), value.into());
    }
}

macro_rules! implement {
    ($(#[$doc:meta] struct $struct_name:ident)*) => ($(
        #[$doc]
        #[derive(Clone, Debug)]
        pub struct $struct_name {
            inner: Element,
        }

        impl $struct_name {
            /// Create a node.
            #[inline]
            pub fn new() -> Self {
                $struct_name {
                    inner: Element::new(tag::$struct_name),
                }
            }
        }

        impl Default for $struct_name {
            fn default() -> Self {
                Self::new()
            }
        }

        impl super::NodeDefaultHash for $struct_name {
            #[inline]
            fn default_hash(&self, state: &mut DefaultHasher) {
                self.inner.default_hash(state);
            }
        }

        node! { $struct_name::inner }
    )*);
}

impl super::NodeDefaultHash for Element {
    fn default_hash(&self, state: &mut DefaultHasher) {
        self.name.hash(state);
        self.attributes.iter().for_each(|(key, value)| {
            key.hash(state);
            value.hash(state)
        });
        self.children
            .iter()
            .for_each(|child| child.default_hash(state));
    }
}

implement! {
    #[doc = "An [`animate`](https://www.w3.org/TR/SVG/animate.html#AnimateElement) element."]
    struct Animate

    #[doc = "An [`animateColor`](https://www.w3.org/TR/SVG/animate.html#AnimateColorElement) element."]
    struct AnimateColor

    #[doc = "An [`animateMotion`](https://www.w3.org/TR/SVG/animate.html#AnimateMotionElement) element."]
    struct AnimateMotion

    #[doc = "An [`animateTransform`](https://www.w3.org/TR/SVG/animate.html#AnimateTransformElement) element."]
    struct AnimateTransform

    #[doc = "A [`circle`](https://www.w3.org/TR/SVG/shapes.html#CircleElement) element."]
    struct Circle

    #[doc = "A [`clipPath`](https://www.w3.org/TR/SVG/masking.html#ClipPathElement) element."]
    struct ClipPath

    #[doc = "A [`defs`](https://www.w3.org/TR/SVG/struct.html#DefsElement) element."]
    struct Definitions

    #[doc = "A [`desc`](https://www.w3.org/TR/SVG/struct.html#DescElement) element."]
    struct Description

    #[doc = "An [`ellipse`](https://www.w3.org/TR/SVG/shapes.html#EllipseElement) element."]
    struct Ellipse

    #[doc = "A [`filter`](https://www.w3.org/TR/SVG/filters.html#FilterElement) element."]
    struct Filter

    #[doc = "A [`foreignObject`](https://www.w3.org/TR/SVG/embedded.html#ForeignObjectElement) element."]
    struct ForeignObject

    #[doc = "A [`g`](https://www.w3.org/TR/SVG/struct.html#GElement) element."]
    struct Group

    #[doc = "An [`image`](https://www.w3.org/TR/SVG/struct.html#ImageElement) element."]
    struct Image

    #[doc = "A [`line`](https://www.w3.org/TR/SVG/shapes.html#LineElement) element."]
    struct Line

    #[doc = "A [`linearGradient`](https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement) element."]
    struct LinearGradient

    #[doc = "An [`a`](https://www.w3.org/TR/SVG/linking.html#AElement) element."]
    struct Link

    #[doc = "A [`marker`](https://www.w3.org/TR/SVG/painting.html#MarkerElement) element."]
    struct Marker

    #[doc = "A [`mask`](https://www.w3.org/TR/SVG/masking.html#MaskElement) element."]
    struct Mask

    #[doc = "An [`mpath`](https://www.w3.org/TR/SVG/animate.html#MPathElement) element."]
    struct MotionPath

    #[doc = "A [`path`](https://www.w3.org/TR/SVG/paths.html#PathElement) element."]
    struct Path

    #[doc = "A [`pattern`](https://www.w3.org/TR/SVG/pservers.html#PatternElement) element."]
    struct Pattern

    #[doc = "A [`polygon`](https://www.w3.org/TR/SVG/shapes.html#PolygonElement) element."]
    struct Polygon

    #[doc = "A [`polyline`](https://www.w3.org/TR/SVG/shapes.html#PolylineElement) element."]
    struct Polyline

    #[doc = "A [`radialGradient`](https://www.w3.org/TR/SVG/pservers.html#RadialGradientElement) element."]
    struct RadialGradient

    #[doc = "A [`rect`](https://www.w3.org/TR/SVG/shapes.html#RectElement) element."]
    struct Rectangle

    #[doc = "A [`stop`](https://www.w3.org/TR/SVG/pservers.html#StopElement) element."]
    struct Stop

    #[doc = "A [`symbol`](https://www.w3.org/TR/SVG/struct.html#SymbolElement) element."]
    struct Symbol

    #[doc = "A [`text`](https://www.w3.org/TR/SVG/text.html#TextElement) element."]
    struct Text

    #[doc = "A [`textPath`](https://www.w3.org/TR/SVG/text.html#TextPathElement) element."]
    struct TextPath

    #[doc = "A [`title`](https://www.w3.org/TR/SVG/struct.html#TitleElement) element."]
    struct Title

    #[doc = "A [`use`](https://www.w3.org/TR/SVG/struct.html#UseElement) element."]
    struct Use
}

macro_rules! implement {
    (@itemize $i:item) => ($i);
    ($(
        #[$doc:meta]
        struct $struct_name:ident
        [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block
    )*) => ($(
        #[$doc]
        #[derive(Clone, Debug)]
        pub struct $struct_name {
            inner: Element,
        }

        implement! { @itemize
            impl $struct_name {
                /// Create a node.
                #[inline]
                pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self {
                    #[inline(always)]
                    fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body
                    let mut inner = Element::new(tag::$struct_name);
                    initialize(&mut inner $(, $an)*);
                    $struct_name {
                        inner: inner,
                    }
                }
            }
        }

        impl super::NodeDefaultHash for $struct_name {
            fn default_hash(&self, state: &mut DefaultHasher) {
                self.inner.default_hash(state);
            }
        }

        node! { $struct_name::inner }
    )*);
}

implement! {
    #[doc = "An [`svg`](https://www.w3.org/TR/SVG/struct.html#SVGElement) element."]
    struct SVG [] [inner] {
        inner.assign("xmlns", "http://www.w3.org/2000/svg");
    }

    #[doc = "A [`script`](https://www.w3.org/TR/SVG/script.html#ScriptElement) element."]
    struct Script [T: Into<String>] [inner, content: T] {
        inner.append(crate::node::Text::new(content));
    }

    #[doc = "A [`style`](https://www.w3.org/TR/SVG/styling.html#StyleElement) element."]
    struct Style [T: Into<String>] [inner, content: T] {
        inner.append(crate::node::Text::new(content));
    }
}

#[cfg(test)]
mod tests {
    use super::{Element, Style};
    use crate::node::Node;

    #[test]
    fn element_display() {
        let mut element = Element::new("foo");
        element.assign("x", -10);
        element.assign("y", "10px");
        element.assign("s", (12.5, 13.0));
        element.assign("c", "green");
        element.append(Element::new("bar"));

        assert_eq!(
            element.to_string(),
            "<foo c=\"green\" s=\"12.5 13\" x=\"-10\" y=\"10px\">\n\
             <bar/>\n\
             </foo>\
             "
        );
    }

    #[test]
    fn element_display_quotes() {
        let mut element = Element::new("foo");
        element.assign("s", "'single'");
        element.assign("d", r#""double""#);
        element.assign("m", r#""mixed'"#);

        assert_eq!(element.to_string(), r#"<foo d='"double"' s="'single'"/>"#);
    }

    #[test]
    fn style_display() {
        let element = Style::new("* { font-family: foo; }");

        assert_eq!(
            element.to_string(),
            "<style>\n\
             * { font-family: foo; }\n\
             </style>\
             "
        );
    }
}
<|endoftext|>


<commit_before>use rand::{
    distributions::{Distribution, Standard},
    seq::SliceRandom,
    Rng, SeedableRng,
};
use rand_xorshift::XorShiftRng;
use reduce::Reduce;
use std::fmt;

const TABLE_SIZE: usize = 256;

pub trait NoiseHasher: Send + Sync {
    fn hash(&self, to_hash: &[isize]) -> usize;
}

/// A seed table, required by all noise functions.
///
/// Table creation is expensive, so in most circumstances you'll only want to
/// create one of these per generator.
#[derive(Copy, Clone)]
pub struct PermutationTable {
    values: [u8; TABLE_SIZE],
}

impl Distribution<PermutationTable> for Standard {
    /// Generates a PermutationTable using a random seed.
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PermutationTable {
        let mut seq: Vec<u8> = (0..TABLE_SIZE).map(|x| x as u8).collect();
        seq.shuffle(rng);

        // It's unfortunate that this double-initializes the array, but Rust
        // doesn't currently provide a clean way to do this in one pass. Hopefully
        // it won't matter, as Seed creation will usually be a one-time event.
        let mut perm_table = PermutationTable {
            values: [0; TABLE_SIZE],
        };
        let seq_it = seq.iter();
        for (x, y) in perm_table.values.iter_mut().zip(seq_it) {
            *x = *y
        }
        perm_table
    }
}

impl PermutationTable {
    /// Deterministically generates a new permutation table based on a `u32` seed value.
    ///
    /// Internally this uses a `XorShiftRng`, but we don't really need to worry
    /// about cryptographic security when working with procedural noise.
    pub fn new(seed: u32) -> Self {
        let mut real = [0; 16];
        real[0] = 1;
        for i in 1..4 {
            real[i * 4] = seed as u8;
            real[(i * 4) + 1] = (seed >> 8) as u8;
            real[(i * 4) + 2] = (seed >> 16) as u8;
            real[(i * 4) + 3] = (seed >> 24) as u8;
        }
        let mut rng: XorShiftRng = SeedableRng::from_seed(real);
        rng.gen()
    }

    pub fn get1(&self, x: isize) -> usize {
        let x = (x & 0xff) as usize;
        self.values[x] as usize
    }

    pub fn get2(&self, pos: [isize; 2]) -> usize {
        let y = (pos[1] & 0xff) as usize;
        self.values[self.get1(pos[0]) ^ y] as usize
    }

    pub fn get3(&self, pos: [isize; 3]) -> usize {
        let z = (pos[2] & 0xff) as usize;
        self.values[self.get2([pos[0], pos[1]]) ^ z] as usize
    }

    pub fn get4(&self, pos: [isize; 4]) -> usize {
        let w = (pos[3] & 0xff) as usize;
        self.values[self.get3([pos[0], pos[1], pos[2]]) ^ w] as usize
    }
}

impl NoiseHasher for PermutationTable {
    fn hash(&self, to_hash: &[isize]) -> usize {
        let index: usize = to_hash
            .iter()
            .map(|&a| (a & 0xff) as usize)
            .reduce(|a, b| (self.values[a] as usize ^ b))
            .unwrap();
        self.values[index] as usize
    }
}

impl fmt::Debug for PermutationTable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "PermutationTable {{ .. }}")
    }
}

#[cfg(test)]
mod tests {
    use crate::{NoiseFn, Perlin, Seedable};
    use rand::random;

    #[test]
    fn test_random_seed() {
        let perlin = Perlin::new().set_seed(random());
        let _ = perlin.get([1.0, 2.0, 3.0]);
    }

    #[test]
    fn test_negative_params() {
        let perlin = Perlin::new();
        let _ = perlin.get([-1.0, 2.0, 3.0]);
    }
}
<commit_msg>Remove get#() functions from PermutationTable<commit_after>use rand::{
    distributions::{Distribution, Standard},
    seq::SliceRandom,
    Rng, SeedableRng,
};
use rand_xorshift::XorShiftRng;
use reduce::Reduce;
use std::fmt;

const TABLE_SIZE: usize = 256;

pub trait NoiseHasher: Send + Sync {
    fn hash(&self, to_hash: &[isize]) -> usize;
}

/// A seed table, required by all noise functions.
///
/// Table creation is expensive, so in most circumstances you'll only want to
/// create one of these per generator.
#[derive(Copy, Clone)]
pub struct PermutationTable {
    values: [u8; TABLE_SIZE],
}

impl Distribution<PermutationTable> for Standard {
    /// Generates a PermutationTable using a random seed.
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PermutationTable {
        let mut seq: Vec<u8> = (0..TABLE_SIZE).map(|x| x as u8).collect();
        seq.shuffle(rng);

        // It's unfortunate that this double-initializes the array, but Rust
        // doesn't currently provide a clean way to do this in one pass. Hopefully
        // it won't matter, as Seed creation will usually be a one-time event.
        let mut perm_table = PermutationTable {
            values: [0; TABLE_SIZE],
        };
        let seq_it = seq.iter();
        for (x, y) in perm_table.values.iter_mut().zip(seq_it) {
            *x = *y
        }
        perm_table
    }
}

impl PermutationTable {
    /// Deterministically generates a new permutation table based on a `u32` seed value.
    ///
    /// Internally this uses a `XorShiftRng`, but we don't really need to worry
    /// about cryptographic security when working with procedural noise.
    pub fn new(seed: u32) -> Self {
        let mut real = [0; 16];
        real[0] = 1;
        for i in 1..4 {
            real[i * 4] = seed as u8;
            real[(i * 4) + 1] = (seed >> 8) as u8;
            real[(i * 4) + 2] = (seed >> 16) as u8;
            real[(i * 4) + 3] = (seed >> 24) as u8;
        }
        let mut rng: XorShiftRng = SeedableRng::from_seed(real);
        rng.gen()
    }
}

impl NoiseHasher for PermutationTable {
    fn hash(&self, to_hash: &[isize]) -> usize {
        let index: usize = to_hash
            .iter()
            .map(|&a| (a & 0xff) as usize)
            .reduce(|a, b| (self.values[a] as usize ^ b))
            .unwrap();
        self.values[index] as usize
    }
}

impl fmt::Debug for PermutationTable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "PermutationTable {{ .. }}")
    }
}

#[cfg(test)]
mod tests {
    use crate::{NoiseFn, Perlin, Seedable};
    use rand::random;

    #[test]
    fn test_random_seed() {
        let perlin = Perlin::new().set_seed(random());
        let _ = perlin.get([1.0, 2.0, 3.0]);
    }

    #[test]
    fn test_negative_params() {
        let perlin = Perlin::new();
        let _ = perlin.get([-1.0, 2.0, 3.0]);
    }
}
<|endoftext|>


<commit_before>use crate::io::{AsyncSeek, SeekFrom};
use futures_core::future::Future;
use futures_core::task::{Context, Poll};
use std::io;
use std::pin::Pin;

// TODO: Currently this throws a warning, but it's a false positive as it generates a
// correct link. See: https://github.com/rust-lang/rust/issues/55907
// Verify everything works fine here when that get's resolved.
//
/// Future for the [`seek`](AsyncSeekExt::seek) method.
#[derive(Debug)]
pub struct Seek<'a, S: ?Sized + Unpin> {
    seek: &'a mut S,
    pos: SeekFrom,
}

impl<S: ?Sized + Unpin> Unpin for Seek<'_, S> {}

impl<'a, S: AsyncSeek + ?Sized + Unpin> Seek<'a, S> {
    pub(super) fn new(seek: &'a mut S, pos: SeekFrom) -> Self {
        Self { seek, pos }
    }
}

impl<S: AsyncSeek + ?Sized + Unpin> Future for Seek<'_, S> {
    type Output = io::Result<u64>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = &mut *self;
        Pin::new(&mut this.seek).poll_seek(cx, this.pos)
    }
}
<commit_msg>Fix futures_util::io::Seek<commit_after>use crate::io::{AsyncSeek, SeekFrom};
use futures_core::future::Future;
use futures_core::task::{Context, Poll};
use std::io;
use std::pin::Pin;

/// Future for the [`seek`](crate::io::AsyncSeekExt::seek) method.
#[derive(Debug)]
pub struct Seek<'a, S: ?Sized + Unpin> {
    seek: &'a mut S,
    pos: SeekFrom,
}

impl<S: ?Sized + Unpin> Unpin for Seek<'_, S> {}

impl<'a, S: AsyncSeek + ?Sized + Unpin> Seek<'a, S> {
    pub(super) fn new(seek: &'a mut S, pos: SeekFrom) -> Self {
        Self { seek, pos }
    }
}

impl<S: AsyncSeek + ?Sized + Unpin> Future for Seek<'_, S> {
    type Output = io::Result<u64>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = &mut *self;
        Pin::new(&mut this.seek).poll_seek(cx, this.pos)
    }
}
<|endoftext|>


<commit_before>use libc::{c_char, int32_t};
use std;
use std::ffi::CString;
use std::error::Error;

use backend::Backend;
use provider::error;
use provider::Output;
use provider::service::ServiceProvider;

pub struct Service<'a> {
    name: &'static str,
    backend: &'a Backend,
    provider: &'a ServiceProvider,
    error: Option<error::Error>,
}

impl<'a> Service<'a> {
    pub fn new(n: &'static str, b: &'a Backend, p: &'a ServiceProvider) -> Service<'a> {
        Service {
            name: n,
            backend: b,
            provider: p,
            error: None,
        }
    }

    pub fn is_running(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.is_running(self.name))
            .and_then(Output::to_bool)
    }

    pub fn is_enabled(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.is_enabled(self.name))
            .and_then(Output::to_bool)
    }

    pub fn enable(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.enable(self.name))
            .and_then(Output::to_bool)
    }

    pub fn disable(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.disable(self.name))
            .and_then(Output::to_bool)
    }

    pub fn start(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.start(self.name))
            .and_then(Output::to_bool)
    }

    pub fn stop(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.stop(self.name))
            .and_then(Output::to_bool)
    }

    pub fn reload(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.reload(self.name))
            .and_then(Output::to_bool)
    }

    pub fn restart(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.restart(self.name))
            .and_then(Output::to_bool)
    }
}

// Wrapper functions for FFI

#[no_mangle]
pub extern "C" fn resource_service_free(ptr: *mut Service) {
    if ptr.is_null() {
        return;
    }
    unsafe {
        Box::from_raw(ptr);
    }
}

#[no_mangle]
pub extern "C" fn resource_service_error_description(ptr: *const Service) -> *const c_char {
    let s = unsafe {
        assert!(!ptr.is_null());
        &*ptr
    };

    match s.error {
        Some(ref e) => CString::new(e.description()).unwrap().into_raw(),
        None => std::ptr::null(),
    }
}

#[no_mangle]
pub extern "C" fn resource_service_is_running(ptr: *mut Service) -> int32_t {
    let s = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };

    match s.is_running() {
        Ok(f) => if f { 1 } else { 0 },
        Err(e) => {
            s.error = Some(e);
            return -1;
        }
    }
}

#[no_mangle]
pub extern "C" fn resource_service_is_enabled(ptr: *mut Service) -> int32_t {
    let s = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };

    match s.is_enabled() {
        Ok(f) => if f { 1 } else { 0 },
        Err(e) => {
            s.error = Some(e);
            return -1;
        }
    }
}

#[no_mangle]
pub extern "C" fn resource_service_enable(ptr: *mut Service) -> int32_t {
    let s = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };

    match s.enable() {
        Ok(f) => if f { 1 } else { 0 },
        Err(e) => {
            s.error = Some(e);
            return -1;
        }
    }
}
<commit_msg>Add a wrapper function of service.disable()<commit_after>use libc::{c_char, int32_t};
use std;
use std::ffi::CString;
use std::error::Error;

use backend::Backend;
use provider::error;
use provider::Output;
use provider::service::ServiceProvider;

pub struct Service<'a> {
    name: &'static str,
    backend: &'a Backend,
    provider: &'a ServiceProvider,
    error: Option<error::Error>,
}

impl<'a> Service<'a> {
    pub fn new(n: &'static str, b: &'a Backend, p: &'a ServiceProvider) -> Service<'a> {
        Service {
            name: n,
            backend: b,
            provider: p,
            error: None,
        }
    }

    pub fn is_running(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.is_running(self.name))
            .and_then(Output::to_bool)
    }

    pub fn is_enabled(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.is_enabled(self.name))
            .and_then(Output::to_bool)
    }

    pub fn enable(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.enable(self.name))
            .and_then(Output::to_bool)
    }

    pub fn disable(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.disable(self.name))
            .and_then(Output::to_bool)
    }

    pub fn start(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.start(self.name))
            .and_then(Output::to_bool)
    }

    pub fn stop(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.stop(self.name))
            .and_then(Output::to_bool)
    }

    pub fn reload(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.reload(self.name))
            .and_then(Output::to_bool)
    }

    pub fn restart(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.restart(self.name))
            .and_then(Output::to_bool)
    }
}

// Wrapper functions for FFI

#[no_mangle]
pub extern "C" fn resource_service_free(ptr: *mut Service) {
    if ptr.is_null() {
        return;
    }
    unsafe {
        Box::from_raw(ptr);
    }
}

#[no_mangle]
pub extern "C" fn resource_service_error_description(ptr: *const Service) -> *const c_char {
    let s = unsafe {
        assert!(!ptr.is_null());
        &*ptr
    };

    match s.error {
        Some(ref e) => CString::new(e.description()).unwrap().into_raw(),
        None => std::ptr::null(),
    }
}

#[no_mangle]
pub extern "C" fn resource_service_is_running(ptr: *mut Service) -> int32_t {
    let s = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };

    match s.is_running() {
        Ok(f) => if f { 1 } else { 0 },
        Err(e) => {
            s.error = Some(e);
            return -1;
        }
    }
}

#[no_mangle]
pub extern "C" fn resource_service_is_enabled(ptr: *mut Service) -> int32_t {
    let s = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };

    match s.is_enabled() {
        Ok(f) => if f { 1 } else { 0 },
        Err(e) => {
            s.error = Some(e);
            return -1;
        }
    }
}

#[no_mangle]
pub extern "C" fn resource_service_enable(ptr: *mut Service) -> int32_t {
    let s = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };

    match s.enable() {
        Ok(f) => if f { 1 } else { 0 },
        Err(e) => {
            s.error = Some(e);
            return -1;
        }
    }
}

#[no_mangle]
pub extern "C" fn resource_service_disable(ptr: *mut Service) -> int32_t {
    let s = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };

    match s.disable() {
        Ok(f) => if f { 1 } else { 0 },
        Err(e) => {
            s.error = Some(e);
            return -1;
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::error;
use std::fmt;
use std::os::raw::{c_int, c_long};
use std::path::Path;
use sdl2::get_error;
use sdl2::rwops::RWops;
use sdl2::version::Version;

use font::{
    internal_load_font,
    internal_load_font_at_index,
    internal_load_font_from_ll,
    Font,
};

use ffi;

/// A context manager for `SDL2_TTF` to manage C code initialization and clean-up.
#[must_use]
pub struct Sdl2TtfContext;

// Clean up the context once it goes out of scope
impl Drop for Sdl2TtfContext {
    fn drop(&mut self) {
        unsafe { ffi::TTF_Quit(); }
    }
}

impl Sdl2TtfContext {
    /// Loads a font from the given file with the given size in points.
    pub fn load_font(&self, path: &Path, point_size: u16) -> Result<Font, String> {
        internal_load_font(path, point_size)
    }

    /// Loads the font at the given index of the file, with the given
    /// size in points.
    pub fn load_font_at_index(&self, path: &Path, index: u32, point_size: u16)
            -> Result<Font, String> {
        internal_load_font_at_index(path, index, point_size)
    }

    /// Loads a font from the given SDL2 rwops object with the given size in
    /// points.
    pub fn load_font_from_rwops(&self, rwops: RWops, point_size: u16)
            -> Result<Font, String> {
        let raw = unsafe {
            ffi::TTF_OpenFontRW(rwops.raw(), 0, point_size as c_int)
        };
        if (raw as *mut ()).is_null() {
            Err(get_error())
        } else {
            Ok(internal_load_font_from_ll(raw, true))
        }
    }

    /// Loads the font at the given index of the SDL2 rwops object with
    /// the given size in points.
    pub fn load_font_at_index_from_rwops(&self, rwops: RWops, index: u32,
            point_size: u16) -> Result<Font, String> {
        let raw = unsafe {
            ffi::TTF_OpenFontIndexRW(rwops.raw(), 0, point_size as c_int,
                index as c_long)
        };
        if (raw as *mut ()).is_null() {
            Err(get_error())
        } else {
            Ok(internal_load_font_from_ll(raw, true))
        }
    }
}

/// Returns the version of the dynamically linked `SDL_TTF` library
pub fn get_linked_version() -> Version {
    unsafe {
        Version::from_ll(*ffi::TTF_Linked_Version())
    }
}

/// An error for when `sdl2_ttf` is attempted initialized twice
/// Necessary for context management, unless we find a way to have a singleton
#[derive(Debug)]
pub enum InitError {
    InitializationError(io::Error),
    AlreadyInitializedError,
}

impl error::Error for InitError {
    fn description(&self) -> &str {
        match *self {
            InitError::AlreadyInitializedError => {
                "SDL2_TTF has already been initialized"
            },
            InitError::InitializationError(ref error) => {
                error.description()
            },
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            InitError::AlreadyInitializedError => {
                None
            },
            InitError::InitializationError(ref error) => {
                Some(error)
            },
        }
    }
}

impl fmt::Display for InitError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        formatter.write_str("SDL2_TTF has already been initialized")
    }
}

/// Initializes the truetype font API and returns a context manager which will
/// clean up the library once it goes out of scope.
pub fn init() -> Result<Sdl2TtfContext, InitError> {
    unsafe {
        if ffi::TTF_WasInit() == 1 {
            Err(InitError::AlreadyInitializedError)
        } else if ffi::TTF_Init() == 0 {
            Ok(Sdl2TtfContext)
        } else {
            Err(InitError::InitializationError(
                io::Error::last_os_error()
                    ))
        }
    }
}

/// Returns whether library has been initialized already.
pub fn has_been_initialized() -> bool {
    unsafe {
        ffi::TTF_WasInit() == 1
    }
}
<commit_msg>load_font now borrow rwops instead of consuming it<commit_after>use std::io;
use std::error;
use std::fmt;
use std::os::raw::{c_int, c_long};
use std::path::Path;
use sdl2::get_error;
use sdl2::rwops::RWops;
use sdl2::version::Version;

use font::{
    internal_load_font,
    internal_load_font_at_index,
    internal_load_font_from_ll,
    Font,
};

use ffi;

/// A context manager for `SDL2_TTF` to manage C code initialization and clean-up.
#[must_use]
pub struct Sdl2TtfContext;

// Clean up the context once it goes out of scope
impl Drop for Sdl2TtfContext {
    fn drop(&mut self) {
        unsafe { ffi::TTF_Quit(); }
    }
}

impl Sdl2TtfContext {
    /// Loads a font from the given file with the given size in points.
    pub fn load_font(&self, path: &Path, point_size: u16) -> Result<Font, String> {
        internal_load_font(path, point_size)
    }

    /// Loads the font at the given index of the file, with the given
    /// size in points.
    pub fn load_font_at_index(&self, path: &Path, index: u32, point_size: u16)
            -> Result<Font, String> {
        internal_load_font_at_index(path, index, point_size)
    }

    /// Loads a font from the given SDL2 rwops object with the given size in
    /// points.
    pub fn load_font_from_rwops(&self, rwops: &RWops, point_size: u16)
            -> Result<Font, String> {
        let raw = unsafe {
            ffi::TTF_OpenFontRW(rwops.raw(), 0, point_size as c_int)
        };
        if (raw as *mut ()).is_null() {
            Err(get_error())
        } else {
            Ok(internal_load_font_from_ll(raw, true))
        }
    }

    /// Loads the font at the given index of the SDL2 rwops object with
    /// the given size in points.
    pub fn load_font_at_index_from_rwops(&self, rwops: &RWops, index: u32,
            point_size: u16) -> Result<Font, String> {
        let raw = unsafe {
            ffi::TTF_OpenFontIndexRW(rwops.raw(), 0, point_size as c_int,
                index as c_long)
        };
        if (raw as *mut ()).is_null() {
            Err(get_error())
        } else {
            Ok(internal_load_font_from_ll(raw, true))
        }
    }
}

/// Returns the version of the dynamically linked `SDL_TTF` library
pub fn get_linked_version() -> Version {
    unsafe {
        Version::from_ll(*ffi::TTF_Linked_Version())
    }
}

/// An error for when `sdl2_ttf` is attempted initialized twice
/// Necessary for context management, unless we find a way to have a singleton
#[derive(Debug)]
pub enum InitError {
    InitializationError(io::Error),
    AlreadyInitializedError,
}

impl error::Error for InitError {
    fn description(&self) -> &str {
        match *self {
            InitError::AlreadyInitializedError => {
                "SDL2_TTF has already been initialized"
            },
            InitError::InitializationError(ref error) => {
                error.description()
            },
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            InitError::AlreadyInitializedError => {
                None
            },
            InitError::InitializationError(ref error) => {
                Some(error)
            },
        }
    }
}

impl fmt::Display for InitError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        formatter.write_str("SDL2_TTF has already been initialized")
    }
}

/// Initializes the truetype font API and returns a context manager which will
/// clean up the library once it goes out of scope.
pub fn init() -> Result<Sdl2TtfContext, InitError> {
    unsafe {
        if ffi::TTF_WasInit() == 1 {
            Err(InitError::AlreadyInitializedError)
        } else if ffi::TTF_Init() == 0 {
            Ok(Sdl2TtfContext)
        } else {
            Err(InitError::InitializationError(
                io::Error::last_os_error()
                    ))
        }
    }
}

/// Returns whether library has been initialized already.
pub fn has_been_initialized() -> bool {
    unsafe {
        ffi::TTF_WasInit() == 1
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::thread;
use std::thread::JoinHandle;
use std::net::TcpStream;
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver,
    TryRecvError
};

use super::types::*;
use super::epoll;
use super::epoll::util::*;
use super::epoll::EpollEvent;
use super::socket::Socket;
use super::simple_stream::nbetstream::NbetStream;

#[allow(dead_code)]
pub struct EventLoop {
    /// Handle to event loop process
    prox: JoinHandle<()>,
    /// Sender<T> to proc
    prox_tx: Sender<TcpStream>
}

impl EventLoop {

    /// Returns a new EventLoop
    pub fn new(server_tx: Sender<EventTuple>) -> EventLoop {
        let (tx, rx): (Sender<TcpStream>, Receiver<TcpStream>) = channel();
        let prox = thread::Builder::new()
            .name("EventLoop".to_string())
            .spawn(move || {
                EventLoop::start(rx, server_tx);
            }).unwrap();

        EventLoop {
            prox: prox,
            prox_tx: tx
        }
    }

    /// Returns a clone of this EventLoop's Sender<TcpStream> channel
    pub fn sender(&self) -> Sender<TcpStream> {
        self.prox_tx.clone()
    }

    /// Main event loop
    fn start(rx: Receiver<TcpStream>, uspace_tx: Sender<EventTuple>) {
        // Master socket list
        let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

        // Our error handler for this thread and it's children
        let (err_tx, err_rx): (Sender<()>, Receiver<()>) = channel();

        // Create an epoll instance
        let result = epoll::create1(0);
        if result.is_err() {
            let err = result.unwrap_err();
            panic!("Unable to create epoll instance: {}", err)
        }
        let epoll_instance = result.unwrap();

        // Start the epoll thread
        let c_sockets = sockets.clone();
        let c_epoll_instance = epoll_instance.clone();
        let epoll_prox = thread::Builder::new()
            .name("EpollLoop".to_string())
            .spawn(move || {
                EventLoop::epoll_loop(uspace_tx, c_sockets, c_epoll_instance, err_rx);
            }).unwrap();

        for new_stream in rx.iter() {
            match NbetStream::new(new_stream) {
                Ok(s_stream) => {
                    // Add to master list
                    let socket = Socket::new(s_stream);

                    // TODO - Replace with recoverable version once into_inner() is stable
                    // Unfortunately, this is the only stable way to use mutexes at the moment
                    // Hopefully recovering from poisoning will be in 1.2
                    // let mut s_guard = match sockets.lock() {
                    //     Ok(guard) => guard,
                    //     Err(poisoned) => poisoned.into_inner()
                    // };
                    let mut s_guard = sockets.lock().unwrap();
                    let s_list = s_guard.deref_mut();
                    let s_fd = socket.raw_fd();
                    s_list.push_back(socket);

                    // Add to epoll
                    let event = Box::new(EpollEvent {
                        data: s_fd as u64,
                        events: (event_type::EPOLLIN | event_type::EPOLLET)
                        });
                    match epoll::ctl(epoll_instance, ctl_op::ADD, s_fd, event) {
                        Ok(()) => println!("New socket added to epoll list"),
                        Err(e) => println!("Epoll CtrlError: {}", e)
                    };
                }
                Err(e) => {
                    // TODO - write error to log file
                    println!("Error: {}", e);
                }
            };
        }

        // If we get here, shit is real bad. It means we have lost our
        // channel to the outside world.
        // Kill off event loop, so unwinding can begin
        println!("Rust.EventLoop.start - thread finished");
        let _ = err_tx.send(());
    }

    /// Calls epoll_wait forever waiting for events to be fired up from kernel
    fn epoll_loop(uspace_tx: Sender<EventTuple>,
                  sockets: SocketList,
                  epoll_instance: RawFd,
                  err_rx: Receiver<()>) {

        // This is the maximum number of events we want to be notified of at one time
        let mut events = Vec::<EpollEvent>::with_capacity(100);
        unsafe { events.set_len(100); }

        loop {
            // Wait for epoll events
            match epoll::wait(epoll_instance, &mut events[..], -1) {
                Ok(num_events) => {
                    println!("{} epoll event(s) received", num_events);
                    for x in 0..num_events {
                        let tx_clone = uspace_tx.clone();
                        let s_clone = sockets.clone();
                        EventLoop::handle_epoll_event(tx_clone, &events[x as usize], s_clone);
                    }
                }
                Err(e) => {
                    panic!("Error on epoll::wait(): {}", e)
                }
            }

            // If we receive anything on this end or lose communication, we need to halt,
            // because we have no where to send up events, our "user space" channel is
            // gone
            match err_rx.try_recv() {
                Ok(_) => {
                    println!("Error, terminating epoll_loop");
                    break;
                }
                Err(e) => {
                    match e {
                        TryRecvError::Empty => {}
                        _ => {
                            println!("Error, terminating epoll_loo");
                            break;
                        }
                    }
                }
            }
        }
        println!("Rust.EventLoop.epoll_loop - thread finished");
    }

    /// Processes a read on the socket that is ready for reading
    ///
    /// An epoll event is passed to this function, with the fd that is ready to be read
    /// A traversal through the list of sockets is then performed in order to locate the
    /// NbetStream instance that is wrapping that file descriptor.
    /// After a read is performed on that socket, it's data will be passed back to the
    /// "user-space" section of the Server to process the payload however it needs to.
    ///
    /// TODO - Create a faster way to gain a safe reference to the NbetStream wrapping
    /// the fd instead of an O(n) lookup for every event. Currently lookup time is
    /// O(n) * MAX_EPOLL_EVENTS, where MAX_EPOLL_EVENTS is user defined in this function's
    /// caller.
    fn handle_epoll_event(uspace_tx: Sender<EventTuple>,
                          event: &EpollEvent,
                          sockets: SocketList) {

        println!("Rust.EventLoop.handle_epoll_event");

        // The fd we are traversing the list for
        let fd = event.data;

        // We need a handle before the list gets locked and used
        let s_list_clone = sockets.clone();

        // TODO - Replace with recoverable version once into_inner() is stable
        // Unfortunately, this is the only stable way to use mutexes at the moment
        // Hopefully recovering from poisoning will be in 1.2
        // let mut s_guard = match sockets.lock() {
        //     Ok(guard) => guard,
        //     Err(poisoned) => poisoned.into_inner()
        // };
        let mut s_guard = sockets.lock().unwrap();
        let s_list = s_guard.deref_mut();
        for socket in s_list.iter_mut() {
            if socket.raw_fd() as u64 == fd {
                // We've found the socket for the event passed from epoll
                // Lets attempt to read from it
                match socket.read() {
                    Ok(()) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Ok()");
                        for msg in socket.buffer().iter() {
                            let list_handle = s_list_clone.clone();
                            let socket_clone = socket.clone();
                            let msg_clone = msg.clone();
                            let _ = uspace_tx.send((list_handle, socket_clone, msg_clone));
                        }
                    }
                    Err(e) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Err(e): {}", e);
                    }
                }
            }
        }
    }
}
<commit_msg>Debugging statements<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::thread;
use std::thread::JoinHandle;
use std::net::TcpStream;
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver,
    TryRecvError
};

use super::types::*;
use super::epoll;
use super::epoll::util::*;
use super::epoll::EpollEvent;
use super::socket::Socket;
use super::simple_stream::nbetstream::NbetStream;

#[allow(dead_code)]
pub struct EventLoop {
    /// Handle to event loop process
    prox: JoinHandle<()>,
    /// Sender<T> to proc
    prox_tx: Sender<TcpStream>
}

impl EventLoop {

    /// Returns a new EventLoop
    pub fn new(server_tx: Sender<EventTuple>) -> EventLoop {
        let (tx, rx): (Sender<TcpStream>, Receiver<TcpStream>) = channel();
        let prox = thread::Builder::new()
            .name("EventLoop".to_string())
            .spawn(move || {
                EventLoop::start(rx, server_tx);
            }).unwrap();

        EventLoop {
            prox: prox,
            prox_tx: tx
        }
    }

    /// Returns a clone of this EventLoop's Sender<TcpStream> channel
    pub fn sender(&self) -> Sender<TcpStream> {
        self.prox_tx.clone()
    }

    /// Main event loop
    fn start(rx: Receiver<TcpStream>, uspace_tx: Sender<EventTuple>) {
        // Master socket list
        let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

        // Our error handler for this thread and it's children
        let (err_tx, err_rx): (Sender<()>, Receiver<()>) = channel();

        // Create an epoll instance
        let result = epoll::create1(0);
        if result.is_err() {
            let err = result.unwrap_err();
            panic!("Unable to create epoll instance: {}", err)
        }
        let epoll_instance = result.unwrap();

        // Start the epoll thread
        let c_sockets = sockets.clone();
        let c_epoll_instance = epoll_instance.clone();
        let epoll_prox = thread::Builder::new()
            .name("EpollLoop".to_string())
            .spawn(move || {
                EventLoop::epoll_loop(uspace_tx, c_sockets, c_epoll_instance, err_rx);
            }).unwrap();

        for new_stream in rx.iter() {
            match NbetStream::new(new_stream) {
                Ok(s_stream) => {
                    // Add to master list
                    let socket = Socket::new(s_stream);

                    // TODO - Replace with recoverable version once into_inner() is stable
                    // Unfortunately, this is the only stable way to use mutexes at the moment
                    // Hopefully recovering from poisoning will be in 1.2
                    // let mut s_guard = match sockets.lock() {
                    //     Ok(guard) => guard,
                    //     Err(poisoned) => poisoned.into_inner()
                    // };
                    let mut s_guard = sockets.lock().unwrap();
                    let s_list = s_guard.deref_mut();
                    let s_fd = socket.raw_fd();
                    s_list.push_back(socket);

                    // Add to epoll
                    let event = Box::new(EpollEvent {
                        data: s_fd as u64,
                        events: (event_type::EPOLLIN | event_type::EPOLLET)
                        });
                    match epoll::ctl(epoll_instance, ctl_op::ADD, s_fd, event) {
                        Ok(()) => println!("New socket added to epoll list"),
                        Err(e) => println!("Epoll CtrlError: {}", e)
                    };
                }
                Err(e) => {
                    // TODO - write error to log file
                    println!("Error: {}", e);
                }
            };
        }

        // If we get here, shit is real bad. It means we have lost our
        // channel to the outside world.
        // Kill off event loop, so unwinding can begin
        println!("Rust.EventLoop.start - thread finished");
        let _ = err_tx.send(());
    }

    /// Calls epoll_wait forever waiting for events to be fired up from kernel
    fn epoll_loop(uspace_tx: Sender<EventTuple>,
                  sockets: SocketList,
                  epoll_instance: RawFd,
                  err_rx: Receiver<()>) {

        // This is the maximum number of events we want to be notified of at one time
        let mut events = Vec::<EpollEvent>::with_capacity(100);
        unsafe { events.set_len(100); }

        loop {
            // Wait for epoll events
            match epoll::wait(epoll_instance, &mut events[..], -1) {
                Ok(num_events) => {
                    println!("{} epoll event(s) received", num_events);
                    for x in 0..num_events {
                        let tx_clone = uspace_tx.clone();
                        let s_clone = sockets.clone();
                        EventLoop::handle_epoll_event(tx_clone, &events[x as usize], s_clone);
                    }
                }
                Err(e) => {
                    panic!("Error on epoll::wait(): {}", e)
                }
            }

            // If we receive anything on this end or lose communication, we need to halt,
            // because we have no where to send up events, our "user space" channel is
            // gone
            match err_rx.try_recv() {
                Ok(_) => {
                    println!("Error, terminating epoll_loop");
                    break;
                }
                Err(e) => {
                    match e {
                        TryRecvError::Empty => {}
                        _ => {
                            println!("Error, terminating epoll_loo");
                            break;
                        }
                    }
                }
            }
        }
        println!("Rust.EventLoop.epoll_loop - thread finished");
    }

    /// Processes a read on the socket that is ready for reading
    ///
    /// An epoll event is passed to this function, with the fd that is ready to be read
    /// A traversal through the list of sockets is then performed in order to locate the
    /// NbetStream instance that is wrapping that file descriptor.
    /// After a read is performed on that socket, it's data will be passed back to the
    /// "user-space" section of the Server to process the payload however it needs to.
    ///
    /// TODO - Create a faster way to gain a safe reference to the NbetStream wrapping
    /// the fd instead of an O(n) lookup for every event. Currently lookup time is
    /// O(n) * MAX_EPOLL_EVENTS, where MAX_EPOLL_EVENTS is user defined in this function's
    /// caller.
    fn handle_epoll_event(uspace_tx: Sender<EventTuple>,
                          event: &EpollEvent,
                          sockets: SocketList) {

        println!("Rust.EventLoop.handle_epoll_event");

        // The fd we are traversing the list for
        let fd = event.data;

        // We need a handle before the list gets locked and used
        let s_list_clone = sockets.clone();

        // TODO - Replace with recoverable version once into_inner() is stable
        // Unfortunately, this is the only stable way to use mutexes at the moment
        // Hopefully recovering from poisoning will be in 1.2
        // let mut s_guard = match sockets.lock() {
        //     Ok(guard) => guard,
        //     Err(poisoned) => poisoned.into_inner()
        // };
        let mut s_guard = sockets.lock().unwrap();
        let s_list = s_guard.deref_mut();
        for socket in s_list.iter_mut() {
            if socket.raw_fd() as u64 == fd {
                // We've found the socket for the event passed from epoll
                // Lets attempt to read from it
                match socket.read() {
                    Ok(()) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Ok()");
                        for msg in socket.buffer().iter() {
                            let msg_for_debug = msg.clone();
                            match String::from_utf8() {
                                Ok(msg_str) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string: {}", msg_str);
                                }
                                Err(e) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string.Err: {}", e);
                                }
                            };

                            let list_handle = s_list_clone.clone();
                            let socket_clone = socket.clone();
                            let msg_clone = msg.clone();
                            let _ = uspace_tx.send((list_handle, socket_clone, msg_clone));
                        }
                    }
                    Err(e) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Err(e): {}", e);
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(unsafe_destructor)]

#[macro_use] pub mod base;
pub mod norx6441;
pub mod norx6461;
pub mod norx3241;
pub mod norx3261;
<commit_msg>Disable unstable item warnings<commit_after>#![allow(unstable)]

#![feature(unsafe_destructor)]

#[macro_use] pub mod base;
pub mod norx6441;
pub mod norx6461;
pub mod norx3241;
pub mod norx3261;
<|endoftext|>


<commit_before>use std::error::Error;
use std::fs::File;
use std::io::prelude::*;

pub struct Config {
    pub query: String,
    pub filename: String,
}

impl Config {
    pub fn new(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("not enough arguments");
        }

        let query = args[1].clone();
        let filename = args[2].clone();

        Ok(Config { query, filename })
    }
}

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }

    results
}

pub fn run(config: Config) -> Result<(), Box<Error>> {
    let mut f = File::open(config.filename)?;

    let mut contents = String::new();
    f.read_to_string(&mut contents)?;

    for line in search(&config.query, &contents) {
        println!("{}", line);
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn one_result() {
        let query = "duct";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
    }
}
<commit_msg>add case insensitive search<commit_after>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;

pub struct Config {
    pub query: String,
    pub filename: String,
    pub case_sensitive: bool,
}

impl Config {
    pub fn new(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("not enough arguments");
        }

        let query = args[1].clone();
        let filename = args[2].clone();
        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();

        Ok(Config {
            query,
            filename,
            case_sensitive,
        })
    }
}

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }

    results
}

pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let query = query.to_lowercase();
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.to_lowercase().contains(&query) {
            results.push(line);
        }
    }

    results
}

pub fn run(config: Config) -> Result<(), Box<Error>> {
    let mut f = File::open(config.filename)?;

    let mut contents = String::new();
    f.read_to_string(&mut contents)?;

    let results = if config.case_sensitive {
        search(&config.query, &contents)
    } else {
        search_case_insensitive(&config.query, &contents)
    };

    for line in results {
        println!("{}", line);
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn one_result() {
        let query = "duct";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.
Duct take.";

        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
    }

    #[test]
    fn case_insensitive() {
        let query = "rUsT";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.";

        assert_eq!(
            vec!["Rust:", "Trust me."],
            search_case_insensitive(query, contents)
        );
    }
}
<|endoftext|>