<commit_before>mod data;
mod utf_encodings;
mod utils;

use data::IdeographicVariationSequence;

use crate::utils::set_panic_hook;
#[macro_use]
extern crate lazy_static;
use serde::Serialize;
use std::collections::HashMap;
use std::convert::TryFrom;
use wasm_bindgen::prelude::*;

// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet() {
    alert("Hello, unicode-rustwasm!");
}

#[wasm_bindgen]
pub fn init() {
    set_panic_hook();
}

#[wasm_bindgen]
pub fn next_codepoint(codepoint: u32) -> u32 {
    if codepoint != 0x10_ffff {
        codepoint + 1
    } else {
        0
    }
}

#[wasm_bindgen]
pub fn previous_codepoint(codepoint: u32) -> u32 {
    if codepoint != 0 {
        codepoint - 1
    } else {
        0x10_ffff
    }
}

#[wasm_bindgen]
pub fn variation_sequences_for_codepoint(codepoint: u32) -> String {
    let mut result = Vec::<IdeographicVariationSequence>::new();
    for ivd in data::IVD_SEQUENCES.iter() {
        if ivd.base_codepoint == codepoint {
            result.push(ivd.clone());
        }
    }
    serde_json::to_string(&result).unwrap()
}

#[wasm_bindgen]
pub fn u8toc(utf8_bytes: Vec<u8>) -> Option<Vec<u32>> {
    match std::str::from_utf8(utf8_bytes.as_slice()) {
        Err(_) => None,
        Ok(s) => Some(s.chars().map(u32::from).collect()),
    }
}

#[wasm_bindgen]
pub fn ctou8(codepoints: Vec<u32>) -> Option<Vec<u8>> {
    Some(ctos(codepoints)?.bytes().collect())
}

#[wasm_bindgen]
pub fn ctos(codepoints: Vec<u32>) -> Option<String> {
    let maybe_a_string = codepoints
        .iter()
        .map(|num| char::try_from(*num))
        .collect::<Result<String, _>>();
    match maybe_a_string {
        Err(_) => None,
        Ok(s) => Some(s),
    }
}

#[wasm_bindgen]
pub fn stoc(str: &str) -> Vec<u32> {
    str.chars().map(|ch| ch as u32).collect()
}

#[derive(Clone, Serialize)]
pub struct EncodingResult {
    pub success: bool,
    pub encoded_code_units: Option<Vec<u32>>,
    pub first_invalid_codepoint: Option<u32>,
}

// map codepoints -> code units
pub type EncodingTable = HashMap<u32, u32>;

// lazy_static! {
//     static ref ENCODING_TABLES: HashMap<&'static str, EncodingTable> = {
//         let mut encoding_table = HashMap::new();
//         encoding_table.insert("ASCII", [(0, 0), (1, 1)]);
//         encoding_table
//     };
// }

fn encode_str_internal(encoding_name: &str, codepoints: Vec<u32>) -> EncodingResult {
    let code_units: Result<Vec<u32>, u32> = match encoding_name {
        "Unicode UTF-8" => codepoints
            .iter()
            .map(|&cp| char::try_from(cp).map_err(|_| cp).map(|c| c as u32))
            .collect(),
        "Unicode UTF-32 (32-bit code units)" => codepoints
            .iter()
            .map(|&cp| {
                if (cp >= 0xd800 && cp <= 0xdfff) || cp > 0x10_ffff {
                    Err(cp)
                } else {
                    Ok(cp)
                }
            })
            .collect(),
        "UCS-2 (16-bit code units)" => utf_encodings::encode_ucs2_16bit(codepoints.iter()),
        "UCS-2 BE (8-bit code units)" => utf_encodings::encode_ucs2_8bit_be(codepoints.iter()),
        "UCS-2 LE (8-bit code units)" => utf_encodings::encode_ucs2_8bit_le(codepoints.iter()),
        "Unicode UTF-16 (16-bit code units)" => {
            utf_encodings::encode_utf16_16bit(codepoints.iter())
        }
        "Unicode UTF-16 BE (8-bit code units)" => {
            utf_encodings::encode_utf16_8bit_be(codepoints.iter())
        }
        "Unicode UTF-16 LE (8-bit code units)" => {
            utf_encodings::encode_utf16_8bit_le(codepoints.iter())
        }
        "Unicode UTF-32 BE (8-bit code units)" | "Unicode UTF-32 LE (8-bit code units)" => {
            codepoints
                .iter()
                .map(|&cp| {
                    if (cp >= 0xd800 && cp <= 0xdfff) || cp > 0x10_ffff {
                        Err(cp)
                    } else {
                        Ok(cp)
                    }
                })
                .collect::<Result<Vec<u32>, u32>>()
                .map(|v| {
                    v.into_iter()
                        .flat_map(|cp| {
                            (if encoding_name == "Unicode UTF-32 BE (8-bit code units)" {
                                cp.to_be_bytes()
                            } else {
                                cp.to_le_bytes()
                            })
                            .iter()
                            .copied()
                            .map(|u| u as u32)
                            .collect::<Vec<_>>()
                        })
                        .collect()
                })
        }
        _ => {
            let encoding = match data::ENCODING_TABLES.get(encoding_name) {
                Some(encoding) => encoding,
                None => {
                    return EncodingResult {
                        success: false,
                        encoded_code_units: None,
                        first_invalid_codepoint: None,
                    }
                }
            };
            let code_units: Result<Vec<u32>, u32> = codepoints
                .iter()
                .map(|&codepoint| {
                    encoding
                        .get(&codepoint)
                        .ok_or(codepoint)
                        .map(|code_unit| *code_unit)
                })
                .collect();
            return match code_units {
                Ok(code_units) => EncodingResult {
                    success: true,
                    encoded_code_units: Some(
                        code_units
                            .iter()
                            .copied()
                            .flat_map(|cu| {
                                if cu <= 0xff {
                                    vec![cu]
                                } else {
                                    vec![cu >> 8, cu & 0xff]
                                }
                            })
                            .collect(),
                    ),
                    first_invalid_codepoint: None,
                },
                Err(codepoint) => EncodingResult {
                    success: false,
                    encoded_code_units: None,
                    first_invalid_codepoint: Some(codepoint),
                },
            };
        }
    };
    match code_units {
        Ok(code_units) => EncodingResult {
            success: true,
            encoded_code_units: Some(code_units),
            first_invalid_codepoint: None,
        },
        Err(codepoint) => EncodingResult {
            success: false,
            encoded_code_units: None,
            first_invalid_codepoint: Some(codepoint),
        },
    }
}

#[wasm_bindgen]
pub fn encode_str(encoding_name: &str, codepoints: Vec<u32>) -> String {
    let result = encode_str_internal(encoding_name, codepoints);
    serde_json::to_string(&result).unwrap()
}

fn lookup_code_unit(table: &EncodingTable, code_unit: u32) -> Option<u32> {
    for (&k, &v) in table {
        if v == code_unit {
            return Some(k);
        }
    }
    None
}

#[wasm_bindgen]
pub fn decode_str(encoding_name: &str, code_units: Vec<u32>) -> Option<Vec<u32>> {
    if encoding_name == "Unicode UTF-8" {
        return u8toc(
            code_units
                .iter()
                .map(|&u| if u <= 0xff { Some(u as u8) } else { None })
                .collect::<Option<Vec<u8>>>()?,
        );
    } else if encoding_name == "Unicode UTF-32 (32-bit code units)" {
        return code_units
            .iter()
            .map(|&u| {
                if (u >= 0xd800 && u <= 0xdfff) || u > 0x10_ffff {
                    None
                } else {
                    Some(u)
                }
            })
            .collect::<Option<Vec<u32>>>();
    } else if encoding_name == "UCS-2 (16-bit code units)" {
        return utf_encodings::decode_ucs2_16bit(code_units);
    } else if encoding_name == "UCS-2 BE (8-bit code units)" {
        return utf_encodings::decode_ucs2_8bit_be(code_units);
    } else if encoding_name == "UCS-2 LE (8-bit code units)" {
        return utf_encodings::decode_ucs2_8bit_le(code_units);
    } else if encoding_name == "Unicode UTF-16 (16-bit code units)" {
        return utf_encodings::decode_utf16_16bit(code_units);
    } else if encoding_name == "Unicode UTF-16 BE (8-bit code units)" {
        return utf_encodings::decode_utf16_8bit_be(code_units);
    } else if encoding_name == "Unicode UTF-16 LE (8-bit code units)" {
        return utf_encodings::decode_utf16_8bit_le(code_units);
    } else if encoding_name == "Unicode UTF-32 BE (8-bit code units)"
        || encoding_name == "Unicode UTF-32 LE (8-bit code units)"
    {
        if code_units.len() % 4 != 0 {
            return None;
        }
        let mut v: Vec<u32> = vec![];
        for c in code_units.chunks(4) {
            for &code_unit in c {
                if code_unit > 0xff {
                    return None;
                }
            }
            let be_or_le_bytes = [c[0] as u8, c[1] as u8, c[2] as u8, c[3] as u8];
            let cp = if encoding_name == "Unicode UTF-32 BE (8-bit code units)" {
                u32::from_be_bytes(be_or_le_bytes)
            } else {
                u32::from_le_bytes(be_or_le_bytes)
            };
            if (cp >= 0xd800 && cp <= 0xdfff) || cp > 0x10_ffff {
                return None;
            }
            v.push(cp);
        }
        return Some(v);
    }
    let table = data::ENCODING_TABLES.get(encoding_name)?;
    let mut res: Vec<u32> = vec![];
    let mut try_combined = false;
    for (i, cu) in code_units.iter().enumerate() {
        if try_combined {
            match lookup_code_unit(table, code_units[i - 1] << 8 | cu) {
                Some(cp) => {
                    res.push(cp);
                    try_combined = false;
                }
                None => return None,
            }
        } else {
            match lookup_code_unit(table, *cu) {
                Some(cp) => res.push(cp),
                None => try_combined = true,
            }
        }
    }
    Some(res)
}

#[wasm_bindgen]
pub fn long_category_name_for_short_name(short_name: &str) -> Option<String> {
    use std::str::FromStr;
    use unicode_rs::general_category::GeneralCategory;

    Some(
        GeneralCategory::from_str(short_name)
            .ok()?
            .long_name()
            .to_string(),
    )
}

#[wasm_bindgen]
pub fn basic_type_for_codepoint(
    short_general_category_name: &str,
    codepoint: u32,
) -> Option<String> {
    use std::str::FromStr;
    use unicode_rs::general_category::GeneralCategory;

    Some(
        GeneralCategory::from_str(short_general_category_name)
            .ok()?
            .codepoint_type(codepoint)
            .to_string(),
    )
}
<commit_msg>wasm: fix UTF-8 encoder<commit_after>mod data;
mod utf_encodings;
mod utils;

use data::IdeographicVariationSequence;

use crate::utils::set_panic_hook;
#[macro_use]
extern crate lazy_static;
use serde::Serialize;
use std::collections::HashMap;
use std::convert::TryFrom;
use wasm_bindgen::prelude::*;

// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet() {
    alert("Hello, unicode-rustwasm!");
}

#[wasm_bindgen]
pub fn init() {
    set_panic_hook();
}

#[wasm_bindgen]
pub fn next_codepoint(codepoint: u32) -> u32 {
    if codepoint != 0x10_ffff {
        codepoint + 1
    } else {
        0
    }
}

#[wasm_bindgen]
pub fn previous_codepoint(codepoint: u32) -> u32 {
    if codepoint != 0 {
        codepoint - 1
    } else {
        0x10_ffff
    }
}

#[wasm_bindgen]
pub fn variation_sequences_for_codepoint(codepoint: u32) -> String {
    let mut result = Vec::<IdeographicVariationSequence>::new();
    for ivd in data::IVD_SEQUENCES.iter() {
        if ivd.base_codepoint == codepoint {
            result.push(ivd.clone());
        }
    }
    serde_json::to_string(&result).unwrap()
}

#[wasm_bindgen]
pub fn u8toc(utf8_bytes: Vec<u8>) -> Option<Vec<u32>> {
    match std::str::from_utf8(utf8_bytes.as_slice()) {
        Err(_) => None,
        Ok(s) => Some(s.chars().map(u32::from).collect()),
    }
}

#[wasm_bindgen]
pub fn ctou8(codepoints: Vec<u32>) -> Option<Vec<u8>> {
    Some(ctos(codepoints)?.bytes().collect())
}

#[wasm_bindgen]
pub fn ctos(codepoints: Vec<u32>) -> Option<String> {
    let maybe_a_string = codepoints
        .iter()
        .map(|num| char::try_from(*num))
        .collect::<Result<String, _>>();
    match maybe_a_string {
        Err(_) => None,
        Ok(s) => Some(s),
    }
}

#[wasm_bindgen]
pub fn stoc(str: &str) -> Vec<u32> {
    str.chars().map(|ch| ch as u32).collect()
}

#[derive(Clone, Serialize)]
pub struct EncodingResult {
    pub success: bool,
    pub encoded_code_units: Option<Vec<u32>>,
    pub first_invalid_codepoint: Option<u32>,
}

// map codepoints -> code units
pub type EncodingTable = HashMap<u32, u32>;

// lazy_static! {
//     static ref ENCODING_TABLES: HashMap<&'static str, EncodingTable> = {
//         let mut encoding_table = HashMap::new();
//         encoding_table.insert("ASCII", [(0, 0), (1, 1)]);
//         encoding_table
//     };
// }

fn encode_str_internal(encoding_name: &str, codepoints: Vec<u32>) -> EncodingResult {
    let code_units: Result<Vec<u32>, u32> = match encoding_name {
        "Unicode UTF-8" => codepoints
            .iter()
            .map(|&cp| char::try_from(cp).map_err(|_| cp).map(|c| c as u32))
            .collect::<Result<Vec<u32>, u32>>()
            .and_then(|cp| {
                ctou8(cp)
                    .ok_or(0u32)
                    .map(|v| v.iter().map(|&cu| cu as u32).collect())
            }),
        "Unicode UTF-32 (32-bit code units)" => codepoints
            .iter()
            .map(|&cp| {
                if (cp >= 0xd800 && cp <= 0xdfff) || cp > 0x10_ffff {
                    Err(cp)
                } else {
                    Ok(cp)
                }
            })
            .collect(),
        "UCS-2 (16-bit code units)" => utf_encodings::encode_ucs2_16bit(codepoints.iter()),
        "UCS-2 BE (8-bit code units)" => utf_encodings::encode_ucs2_8bit_be(codepoints.iter()),
        "UCS-2 LE (8-bit code units)" => utf_encodings::encode_ucs2_8bit_le(codepoints.iter()),
        "Unicode UTF-16 (16-bit code units)" => {
            utf_encodings::encode_utf16_16bit(codepoints.iter())
        }
        "Unicode UTF-16 BE (8-bit code units)" => {
            utf_encodings::encode_utf16_8bit_be(codepoints.iter())
        }
        "Unicode UTF-16 LE (8-bit code units)" => {
            utf_encodings::encode_utf16_8bit_le(codepoints.iter())
        }
        "Unicode UTF-32 BE (8-bit code units)" | "Unicode UTF-32 LE (8-bit code units)" => {
            codepoints
                .iter()
                .map(|&cp| {
                    if (cp >= 0xd800 && cp <= 0xdfff) || cp > 0x10_ffff {
                        Err(cp)
                    } else {
                        Ok(cp)
                    }
                })
                .collect::<Result<Vec<u32>, u32>>()
                .map(|v| {
                    v.into_iter()
                        .flat_map(|cp| {
                            (if encoding_name == "Unicode UTF-32 BE (8-bit code units)" {
                                cp.to_be_bytes()
                            } else {
                                cp.to_le_bytes()
                            })
                            .iter()
                            .copied()
                            .map(|u| u as u32)
                            .collect::<Vec<_>>()
                        })
                        .collect()
                })
        }
        _ => {
            let encoding = match data::ENCODING_TABLES.get(encoding_name) {
                Some(encoding) => encoding,
                None => {
                    return EncodingResult {
                        success: false,
                        encoded_code_units: None,
                        first_invalid_codepoint: None,
                    }
                }
            };
            let code_units: Result<Vec<u32>, u32> = codepoints
                .iter()
                .map(|&codepoint| {
                    encoding
                        .get(&codepoint)
                        .ok_or(codepoint)
                        .map(|code_unit| *code_unit)
                })
                .collect();
            return match code_units {
                Ok(code_units) => EncodingResult {
                    success: true,
                    encoded_code_units: Some(
                        code_units
                            .iter()
                            .copied()
                            .flat_map(|cu| {
                                if cu <= 0xff {
                                    vec![cu]
                                } else {
                                    vec![cu >> 8, cu & 0xff]
                                }
                            })
                            .collect(),
                    ),
                    first_invalid_codepoint: None,
                },
                Err(codepoint) => EncodingResult {
                    success: false,
                    encoded_code_units: None,
                    first_invalid_codepoint: Some(codepoint),
                },
            };
        }
    };
    match code_units {
        Ok(code_units) => EncodingResult {
            success: true,
            encoded_code_units: Some(code_units),
            first_invalid_codepoint: None,
        },
        Err(codepoint) => EncodingResult {
            success: false,
            encoded_code_units: None,
            first_invalid_codepoint: Some(codepoint),
        },
    }
}

#[wasm_bindgen]
pub fn encode_str(encoding_name: &str, codepoints: Vec<u32>) -> String {
    let result = encode_str_internal(encoding_name, codepoints);
    serde_json::to_string(&result).unwrap()
}

fn lookup_code_unit(table: &EncodingTable, code_unit: u32) -> Option<u32> {
    for (&k, &v) in table {
        if v == code_unit {
            return Some(k);
        }
    }
    None
}

#[wasm_bindgen]
pub fn decode_str(encoding_name: &str, code_units: Vec<u32>) -> Option<Vec<u32>> {
    if encoding_name == "Unicode UTF-8" {
        return u8toc(
            code_units
                .iter()
                .map(|&u| if u <= 0xff { Some(u as u8) } else { None })
                .collect::<Option<Vec<u8>>>()?,
        );
    } else if encoding_name == "Unicode UTF-32 (32-bit code units)" {
        return code_units
            .iter()
            .map(|&u| {
                if (u >= 0xd800 && u <= 0xdfff) || u > 0x10_ffff {
                    None
                } else {
                    Some(u)
                }
            })
            .collect::<Option<Vec<u32>>>();
    } else if encoding_name == "UCS-2 (16-bit code units)" {
        return utf_encodings::decode_ucs2_16bit(code_units);
    } else if encoding_name == "UCS-2 BE (8-bit code units)" {
        return utf_encodings::decode_ucs2_8bit_be(code_units);
    } else if encoding_name == "UCS-2 LE (8-bit code units)" {
        return utf_encodings::decode_ucs2_8bit_le(code_units);
    } else if encoding_name == "Unicode UTF-16 (16-bit code units)" {
        return utf_encodings::decode_utf16_16bit(code_units);
    } else if encoding_name == "Unicode UTF-16 BE (8-bit code units)" {
        return utf_encodings::decode_utf16_8bit_be(code_units);
    } else if encoding_name == "Unicode UTF-16 LE (8-bit code units)" {
        return utf_encodings::decode_utf16_8bit_le(code_units);
    } else if encoding_name == "Unicode UTF-32 BE (8-bit code units)"
        || encoding_name == "Unicode UTF-32 LE (8-bit code units)"
    {
        if code_units.len() % 4 != 0 {
            return None;
        }
        let mut v: Vec<u32> = vec![];
        for c in code_units.chunks(4) {
            for &code_unit in c {
                if code_unit > 0xff {
                    return None;
                }
            }
            let be_or_le_bytes = [c[0] as u8, c[1] as u8, c[2] as u8, c[3] as u8];
            let cp = if encoding_name == "Unicode UTF-32 BE (8-bit code units)" {
                u32::from_be_bytes(be_or_le_bytes)
            } else {
                u32::from_le_bytes(be_or_le_bytes)
            };
            if (cp >= 0xd800 && cp <= 0xdfff) || cp > 0x10_ffff {
                return None;
            }
            v.push(cp);
        }
        return Some(v);
    }
    let table = data::ENCODING_TABLES.get(encoding_name)?;
    let mut res: Vec<u32> = vec![];
    let mut try_combined = false;
    for (i, cu) in code_units.iter().enumerate() {
        if try_combined {
            match lookup_code_unit(table, code_units[i - 1] << 8 | cu) {
                Some(cp) => {
                    res.push(cp);
                    try_combined = false;
                }
                None => return None,
            }
        } else {
            match lookup_code_unit(table, *cu) {
                Some(cp) => res.push(cp),
                None => try_combined = true,
            }
        }
    }
    Some(res)
}

#[wasm_bindgen]
pub fn long_category_name_for_short_name(short_name: &str) -> Option<String> {
    use std::str::FromStr;
    use unicode_rs::general_category::GeneralCategory;

    Some(
        GeneralCategory::from_str(short_name)
            .ok()?
            .long_name()
            .to_string(),
    )
}

#[wasm_bindgen]
pub fn basic_type_for_codepoint(
    short_general_category_name: &str,
    codepoint: u32,
) -> Option<String> {
    use std::str::FromStr;
    use unicode_rs::general_category::GeneralCategory;

    Some(
        GeneralCategory::from_str(short_general_category_name)
            .ok()?
            .codepoint_type(codepoint)
            .to_string(),
    )
}
<|endoftext|>


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

use std::env;
use std::fs;
use std::path::PathBuf;

fn main() {
    let target = env::var("TARGET").unwrap();
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let out_dir = PathBuf::from(out_dir);

    if target.contains("windows") {
        let src = PathBuf::from("res/wrench.exe.manifest");
        let mut dst = out_dir.parent().unwrap().parent().unwrap().parent().unwrap().to_owned();
        dst.push("wrench.exe.manifest");
        fs::copy(&src, &dst).unwrap();
    }
}
<commit_msg>Add a cargo:rerun-if-changed directive to wrench's build.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::env;
use std::fs;
use std::path::PathBuf;

fn main() {
    let target = env::var("TARGET").unwrap();
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let out_dir = PathBuf::from(out_dir);

    println!("cargo:rerun-if-changed=res/wrench.exe.manifest");
    if target.contains("windows") {
        let src = PathBuf::from("res/wrench.exe.manifest");
        let mut dst = out_dir.parent().unwrap().parent().unwrap().parent().unwrap().to_owned();
        dst.push("wrench.exe.manifest");
        fs::copy(&src, &dst).unwrap();
    }
}
<|endoftext|>


<commit_before>use ast::edit::IndentLevel;
use ide_db::base_db::{AnchoredPathBuf, SourceDatabaseExt};
use syntax::{
    ast::{self, edit::AstNodeEdit, NameOwner},
    AstNode,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: extract_module_to_file
//
// This assist extract module to file.
//
// ```
// mod foo {<|>
//     fn t() {}
// }
// ```
// ->
// ```
// mod foo;
// ```
pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let assist_id = AssistId("extract_module_to_file", AssistKind::RefactorExtract);
    let assist_label = "Extract module to file";
    let db = ctx.db();
    let module_ast = ctx.find_node_at_offset::<ast::Module>()?;
    let module_items = module_ast.item_list()?;
    let dedent_module_items_text = module_items.dedent(IndentLevel(1)).to_string();
    let module_name = module_ast.name()?;
    let target = module_ast.syntax().text_range();
    let anchor_file_id = ctx.frange.file_id;
    let sr = db.file_source_root(anchor_file_id);
    let sr = db.source_root(sr);
    let file_path = sr.path_for_file(&anchor_file_id)?;
    let (file_name, file_ext) = file_path.name_and_extension()?;
    acc.add(assist_id, assist_label, target, |builder| {
        builder.replace(target, format!("mod {};", module_name));
        let path = if is_main_or_lib(file_name) {
            format!("./{}.{}", module_name, file_ext.unwrap())
        } else {
            format!("./{}/{}.{}", file_name, module_name, file_ext.unwrap())
        };
        let dst = AnchoredPathBuf { anchor: anchor_file_id, path };
        let contents = update_module_items_string(dedent_module_items_text);
        builder.create_file(dst, contents);
    })
}
fn is_main_or_lib(file_name: &str) -> bool {
    file_name == "main".to_string() || file_name == "lib".to_string()
}
fn update_module_items_string(items_str: String) -> String {
    let mut items_string_lines: Vec<&str> = items_str.lines().collect();
    items_string_lines.pop(); // Delete last line
    items_string_lines.reverse();
    items_string_lines.pop(); // Delete first line
    items_string_lines.reverse();

    let string = items_string_lines.join("\n");
    format!("{}", string)
}

#[cfg(test)]
mod tests {
    use crate::tests::check_assist;

    use super::*;

    #[test]
    fn extract_module_to_file_with_basic_module() {
        check_assist(
            extract_module_to_file,
            r#"
//- /foo.rs crate:foo
mod tests {<|>
    #[test] fn t() {}
}
"#,
            r#"
//- /foo.rs
mod tests;
//- /foo/tests.rs
#[test] fn t() {}"#,
        )
    }

    #[test]
    fn extract_module_to_file_with_file_path() {
        check_assist(
            extract_module_to_file,
            r#"
//- /src/foo.rs crate:foo
mod bar {<|>
    fn f() {

    }
}
fn main() {
    println!("Hello, world!");
}
"#,
            r#"
//- /src/foo.rs
mod bar;
fn main() {
    println!("Hello, world!");
}
//- /src/foo/bar.rs
fn f() {

}"#,
        )
    }

    #[test]
    fn extract_module_to_file_with_main_filw() {
        check_assist(
            extract_module_to_file,
            r#"
//- /main.rs
mod foo {<|>
    fn f() {

    }
}
fn main() {
    println!("Hello, world!");
}
"#,
            r#"
//- /main.rs
mod foo;
fn main() {
    println!("Hello, world!");
}
//- /foo.rs
fn f() {

}"#,
        )
    }

    #[test]
    fn extract_module_to_file_with_lib_file() {
        check_assist(
            extract_module_to_file,
            r#"
//- /lib.rs
mod foo {<|>
    fn f() {

    }
}
fn main() {
    println!("Hello, world!");
}
"#,
            r#"
//- /lib.rs
mod foo;
fn main() {
    println!("Hello, world!");
}
//- /foo.rs
fn f() {

}"#,
        )
    }
}
<commit_msg>Improve extract_module_to_file assist<commit_after>use ast::edit::IndentLevel;
use ide_db::base_db::AnchoredPathBuf;
use syntax::{
    ast::{self, edit::AstNodeEdit, NameOwner},
    AstNode,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: extract_module_to_file
//
// This assist extract module to file.
//
// ```
// mod foo {<|>
//     fn t() {}
// }
// ```
// ->
// ```
// mod foo;
// ```
pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let module_ast = ctx.find_node_at_offset::<ast::Module>()?;
    let module_name = module_ast.name()?;

    let module_def = ctx.sema.to_def(&module_ast)?;
    let parent_module = module_def.parent(ctx.db())?;

    let module_items = module_ast.item_list()?;
    let target = module_ast.syntax().text_range();
    let anchor_file_id = ctx.frange.file_id;

    acc.add(
        AssistId("extract_module_to_file", AssistKind::RefactorExtract),
        "Extract module to file",
        target,
        |builder| {
            let path = {
                let dir = match parent_module.name(ctx.db()) {
                    Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name),
                    _ => String::new(),
                };
                format!("./{}{}.rs", dir, module_name)
            };
            let contents = {
                let items = module_items.dedent(IndentLevel(1)).to_string();
                let mut items =
                    items.trim_start_matches('{').trim_end_matches('}').trim().to_string();
                if !items.is_empty() {
                    items.push('\n');
                }
                items
            };

            builder.replace(target, format!("mod {};", module_name));

            let dst = AnchoredPathBuf { anchor: anchor_file_id, path };
            builder.create_file(dst, contents);
        },
    )
}

#[cfg(test)]
mod tests {
    use crate::tests::check_assist;

    use super::*;

    #[test]
    fn extract_from_root() {
        check_assist(
            extract_module_to_file,
            r#"
mod tests {<|>
    #[test] fn t() {}
}
"#,
            r#"
//- /main.rs
mod tests;
//- /tests.rs
#[test] fn t() {}
"#,
        );
    }

    #[test]
    fn extract_from_submodule() {
        check_assist(
            extract_module_to_file,
            r#"
//- /main.rs
mod submodule;
//- /submodule.rs
mod inner<|> {
    fn f() {}
}
fn g() {}
"#,
            r#"
//- /submodule.rs
mod inner;
fn g() {}
//- /submodule/inner.rs
fn f() {}
"#,
        );
    }

    #[test]
    fn extract_from_mod_rs() {
        check_assist(
            extract_module_to_file,
            r#"
//- /main.rs
mod submodule;
//- /submodule/mod.rs
mod inner<|> {
    fn f() {}
}
fn g() {}
"#,
            r#"
//- /submodule/mod.rs
mod inner;
fn g() {}
//- /submodule/inner.rs
fn f() {}
"#,
        );
    }
}
<|endoftext|>


<commit_before>include!(concat!(env!("OUT_DIR"), "/colors.rs"));

#[cfg(not(feature = "no_std"))]
use std::fmt;

/// A r g b a color.
#[derive(Copy, Clone, PartialOrd, Default)]
#[repr(packed)]
pub struct Color {
    pub data: u32,
}

impl Color {
    /// Create a new color from RGB
    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
        Color {
            data: 0xFF00_0000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32),
        }
    }

    /// Create a new color from HSV(0.0-360.0, 0.0-1.0, 0.0-1.0)
    pub fn hsv(h: f64, s: f64, v: f64) -> Self {
        Self::hsva(h, s, v, 1.0)
    }

    /// Create a new color from HSL(0.0-360.0, 0.0-1.0, 0.0-1.0)
    pub fn hsl(h: f64, s: f64, l: f64) -> Self {
        Self::hsla(h, s, l, 1.0)
    }

    /// Create a new color from RGB and alpha values
    pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
        Color {
            data: ((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32),
        }
    }

    /// Create a new color from HSV(0.0-360.0, 0.0-1.0, 0.0-1.0) and alpha values(0.0-1.0)
    pub fn hsva(mut hue: f64, mut saturation: f64, mut value: f64, alpha: f64) -> Self {
        hue %= 360.0;
        saturation = saturation.max(0.0).min(1.0);
        value = value.max(0.0).min(1.0);
        let hh = hue / 60.0;
        let idx = hh.floor() as i32;
        let ff = hh.fract();
        let chroma = value * (1.0 - saturation);
        let second_component = value * (1.0 - (saturation * ff));
        let t = value * (1.0 - (saturation * (1.0 - ff)));
        let (r, g, b) = match idx {
            0 => (value, t, chroma),
            1 => (second_component, value, chroma),
            2 => (chroma, value, t),
            3 => (chroma, second_component, value),
            4 => (t, chroma, value),
            5 => (value, chroma, second_component),
            _ => unreachable!(),
        };
        Self::rgba(
            (r * 255.0) as u8,
            (g * 255.0) as u8,
            (b * 255.0) as u8,
            (alpha * 255.0) as u8,
        )
    }

    /// Create a new color from HSL(0.0-360.0, 0.0-1.0, 0.0-1.0) and alpha values(0.0-1.0)
    pub fn hsla(mut hue: f64, mut saturation: f64, mut lightness: f64, alpha: f64) -> Self {
        hue %= 360.0;
        saturation = saturation.max(0.0).min(1.0);
        lightness = lightness.max(0.0).min(1.0);
        let hh = hue / 60.0;
        let idx = hh.floor() as i32;
        let chroma = (1.0 - ((2.0 * lightness) - 1.0).abs()) * saturation;
        let second_component = chroma * (1.0 - (((idx % 2) as f64) - 1.0).abs());
        let (mut r, mut g, mut b) = match idx {
            0 => (chroma, second_component, 0.0),
            1 => (second_component, chroma, 0.0),
            2 => (0.0, chroma, second_component),
            3 => (0.0, second_component, chroma),
            4 => (second_component, 0.0, chroma),
            5 => (chroma, 0.0, second_component),
            _ => unreachable!(),
        };
        let adjustment = lightness - chroma / 2.0;
        r += adjustment;
        g += adjustment;
        b += adjustment;
        Self::rgba(
            (r.min(1.0) * 255.0) as u8,
            (g.min(1.0) * 255.0) as u8,
            (b.min(1.0) * 255.0) as u8,
            (alpha * 255.0) as u8,
        )
    }

    /// Get the r value
    pub fn r(self) -> u8 {
        ((self.data & 0x00FF_0000) >> 16) as u8
    }

    /// Get the g value
    pub fn g(self) -> u8 {
        ((self.data & 0x0000_FF00) >> 8) as u8
    }

    /// Get the b value
    pub fn b(self) -> u8 {
        (self.data & 0x0000_00FF) as u8
    }

    /// Get the alpha value
    pub fn a(self) -> u8 {
        ((self.data & 0xFF00_0000) >> 24) as u8
    }

    /// Attempts to get a color from its name, all the CSS colors are avaible and some other ones also.
    pub fn from_name(name: &str) -> Option<Color> {
        COLORS.get(name).cloned()
    }

    /// Interpolate between two colors
    pub fn interpolate(start_color: Color, end_color: Color, scale: f64) -> Color {
        let r = Color::interp(start_color.r(), end_color.r(), scale);
        let g = Color::interp(start_color.g(), end_color.g(), scale);
        let b = Color::interp(start_color.b(), end_color.b(), scale);
        let a = Color::interp(start_color.a(), end_color.a(), scale);
        Color::rgba(r, g, b, a)
    }

    fn interp(start_color: u8, end_color: u8, scale: f64) -> u8 {
        (end_color as f64 - start_color as f64).mul_add(scale, start_color as f64) as u8
    }
}

impl ToString for Color {
    fn to_string(&self) -> String {
        if self.a() == 0 {
            return String::from("transparent");
        }

        let data = self.data;

        let mut color = format!("#{:x}", data);
        color.remove(1);
        color.remove(1);
        color
    }
}

impl From<&str> for Color {
    fn from(s: &str) -> Color {
        if !s.starts_with('#') {
            if let Some(color) = Color::from_name(s) {
                return color;
            }
        }
        let clean_hex = s.trim_start_matches('#');
        match clean_hex.len() {
            3 | 4 => {
                let num = u32::from_str_radix(&clean_hex, 16).unwrap_or(0);

                let mut blue = (num & 0xF) << 4;
                let mut green = ((num >> 4) & 0xF) << 4;
                let mut red = ((num >> 8) & 0xF) << 4;
                let mut alpha = match clean_hex.len() == 4 {
                    true => ((num >> 12) & 0xF) << 4,
                    false => 0xF,
                };
                red |= red >> 4;
                green |= green >> 4;
                blue |= blue >> 4;
                alpha |= alpha >> 4;

                Color::rgba(red as u8, green as u8, blue as u8, alpha as u8)
            }
            6 | 8 => {
                let mut x = u32::from_str_radix(&clean_hex, 16).unwrap_or(0);

                if clean_hex.len() == 6 {
                    x |= 0xFF00_0000;
                }

                Color { data: x }
            }
            _ => Color { data: 0 },
        }
    }
}

impl From<String> for Color {
    fn from(s: String) -> Color {
        Color::from(s.as_str())
    }
}

/// Compares two colors (the alpha value is ignored)
impl PartialEq for Color {
    fn eq(&self, other: &Color) -> bool {
        self.r() == other.r() && self.g() == other.g() && self.b() == other.b()
    }
}

#[cfg(not(feature = "no_std"))]
impl fmt::Debug for Color {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{:#010X}", { self.data })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn partial_eq() {
        assert_eq!(true, Color::rgb(1, 2, 3) == Color::rgba(1, 2, 3, 200));
        assert_eq!(false, Color::rgb(1, 2, 3) == Color::rgba(11, 2, 3, 200));
        assert_eq!(true, Color::rgba(1, 2, 3, 200) == Color::rgba(1, 2, 3, 200));
    }
}
<commit_msg>utils: update color PartialEq tests<commit_after>include!(concat!(env!("OUT_DIR"), "/colors.rs"));

#[cfg(not(feature = "no_std"))]
use std::fmt;

/// A r g b a color.
#[derive(Copy, Clone, PartialOrd, Default)]
#[repr(packed)]
pub struct Color {
    pub data: u32,
}

impl Color {
    /// Create a new color from RGB
    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
        Color {
            data: 0xFF00_0000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32),
        }
    }

    /// Create a new color from HSV(0.0-360.0, 0.0-1.0, 0.0-1.0)
    pub fn hsv(h: f64, s: f64, v: f64) -> Self {
        Self::hsva(h, s, v, 1.0)
    }

    /// Create a new color from HSL(0.0-360.0, 0.0-1.0, 0.0-1.0)
    pub fn hsl(h: f64, s: f64, l: f64) -> Self {
        Self::hsla(h, s, l, 1.0)
    }

    /// Create a new color from RGB and alpha values
    pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
        Color {
            data: ((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32),
        }
    }

    /// Create a new color from HSV(0.0-360.0, 0.0-1.0, 0.0-1.0) and alpha values(0.0-1.0)
    pub fn hsva(mut hue: f64, mut saturation: f64, mut value: f64, alpha: f64) -> Self {
        hue %= 360.0;
        saturation = saturation.max(0.0).min(1.0);
        value = value.max(0.0).min(1.0);
        let hh = hue / 60.0;
        let idx = hh.floor() as i32;
        let ff = hh.fract();
        let chroma = value * (1.0 - saturation);
        let second_component = value * (1.0 - (saturation * ff));
        let t = value * (1.0 - (saturation * (1.0 - ff)));
        let (r, g, b) = match idx {
            0 => (value, t, chroma),
            1 => (second_component, value, chroma),
            2 => (chroma, value, t),
            3 => (chroma, second_component, value),
            4 => (t, chroma, value),
            5 => (value, chroma, second_component),
            _ => unreachable!(),
        };
        Self::rgba(
            (r * 255.0) as u8,
            (g * 255.0) as u8,
            (b * 255.0) as u8,
            (alpha * 255.0) as u8,
        )
    }

    /// Create a new color from HSL(0.0-360.0, 0.0-1.0, 0.0-1.0) and alpha values(0.0-1.0)
    pub fn hsla(mut hue: f64, mut saturation: f64, mut lightness: f64, alpha: f64) -> Self {
        hue %= 360.0;
        saturation = saturation.max(0.0).min(1.0);
        lightness = lightness.max(0.0).min(1.0);
        let hh = hue / 60.0;
        let idx = hh.floor() as i32;
        let chroma = (1.0 - ((2.0 * lightness) - 1.0).abs()) * saturation;
        let second_component = chroma * (1.0 - (((idx % 2) as f64) - 1.0).abs());
        let (mut r, mut g, mut b) = match idx {
            0 => (chroma, second_component, 0.0),
            1 => (second_component, chroma, 0.0),
            2 => (0.0, chroma, second_component),
            3 => (0.0, second_component, chroma),
            4 => (second_component, 0.0, chroma),
            5 => (chroma, 0.0, second_component),
            _ => unreachable!(),
        };
        let adjustment = lightness - chroma / 2.0;
        r += adjustment;
        g += adjustment;
        b += adjustment;
        Self::rgba(
            (r.min(1.0) * 255.0) as u8,
            (g.min(1.0) * 255.0) as u8,
            (b.min(1.0) * 255.0) as u8,
            (alpha * 255.0) as u8,
        )
    }

    /// Get the r value
    pub fn r(self) -> u8 {
        ((self.data & 0x00FF_0000) >> 16) as u8
    }

    /// Get the g value
    pub fn g(self) -> u8 {
        ((self.data & 0x0000_FF00) >> 8) as u8
    }

    /// Get the b value
    pub fn b(self) -> u8 {
        (self.data & 0x0000_00FF) as u8
    }

    /// Get the alpha value
    pub fn a(self) -> u8 {
        ((self.data & 0xFF00_0000) >> 24) as u8
    }

    /// Attempts to get a color from its name, all the CSS colors are avaible and some other ones also.
    pub fn from_name(name: &str) -> Option<Color> {
        COLORS.get(name).cloned()
    }

    /// Interpolate between two colors
    pub fn interpolate(start_color: Color, end_color: Color, scale: f64) -> Color {
        let r = Color::interp(start_color.r(), end_color.r(), scale);
        let g = Color::interp(start_color.g(), end_color.g(), scale);
        let b = Color::interp(start_color.b(), end_color.b(), scale);
        let a = Color::interp(start_color.a(), end_color.a(), scale);
        Color::rgba(r, g, b, a)
    }

    fn interp(start_color: u8, end_color: u8, scale: f64) -> u8 {
        (end_color as f64 - start_color as f64).mul_add(scale, start_color as f64) as u8
    }
}

impl ToString for Color {
    fn to_string(&self) -> String {
        if self.a() == 0 {
            return String::from("transparent");
        }

        let data = self.data;

        let mut color = format!("#{:x}", data);
        color.remove(1);
        color.remove(1);
        color
    }
}

impl From<&str> for Color {
    fn from(s: &str) -> Color {
        if !s.starts_with('#') {
            if let Some(color) = Color::from_name(s) {
                return color;
            }
        }
        let clean_hex = s.trim_start_matches('#');
        match clean_hex.len() {
            3 | 4 => {
                let num = u32::from_str_radix(&clean_hex, 16).unwrap_or(0);

                let mut blue = (num & 0xF) << 4;
                let mut green = ((num >> 4) & 0xF) << 4;
                let mut red = ((num >> 8) & 0xF) << 4;
                let mut alpha = match clean_hex.len() == 4 {
                    true => ((num >> 12) & 0xF) << 4,
                    false => 0xF,
                };
                red |= red >> 4;
                green |= green >> 4;
                blue |= blue >> 4;
                alpha |= alpha >> 4;

                Color::rgba(red as u8, green as u8, blue as u8, alpha as u8)
            }
            6 | 8 => {
                let mut x = u32::from_str_radix(&clean_hex, 16).unwrap_or(0);

                if clean_hex.len() == 6 {
                    x |= 0xFF00_0000;
                }

                Color { data: x }
            }
            _ => Color { data: 0 },
        }
    }
}

impl From<String> for Color {
    fn from(s: String) -> Color {
        Color::from(s.as_str())
    }
}

/// Compares two colors (the alpha value is ignored)
impl PartialEq for Color {
    fn eq(&self, other: &Color) -> bool {
        self.r() == other.r() && self.g() == other.g() && self.b() == other.b()
    }
}

#[cfg(not(feature = "no_std"))]
impl fmt::Debug for Color {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{:#010X}", { self.data })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn partial_eq() {
        let color_1 = Color::rgb(1, 2, 3);
        let color_2 = Color::rgba(1, 2, 3, 200);
        let color_3 = Color::rgba(11, 2, 3, 200);

        assert!(
            color_1.eq(&color_2),
            "color_1={:?}(, color_2={:?}",
            &color_1,
            &color_2
        );
        assert!(
            color_1.eq(&color_2),
            "color_1={:?}(, color_2={:?}",
            &color_1,
            &color_2
        );
        assert!(
            color_2.ne(&color_3),
            "color_1={:?}(, color_2={:?}",
            &color_2,
            &color_3
        );
    }
}
<|endoftext|>


<commit_before>//  ██████╗  █████╗ ███████╗███████╗██╗███╗   ██╗ ██████╗
//  ██╔══██╗██╔══██╗██╔════╝██╔════╝██║████╗  ██║██╔════╝
//  ██████╔╝███████║███████╗███████╗██║██╔██╗ ██║██║  ███╗
//  ██╔═══╝ ██╔══██║╚════██║╚════██║██║██║╚██╗██║██║   ██║
//  ██║     ██║  ██║███████║███████║██║██║ ╚████║╚██████╔╝
//  ╚═╝     ╚═╝  ╚═╝╚══════╝╚══════╝╚═╝╚═╝  ╚═══╝ ╚═════╝

#[cfg(test)]
mod passing {
    use crate::html;
    use crate::opts::Options;

    #[test]
    fn icon() {
        let html = "<link rel=\"icon\" href=\"\" />
text
";
        let dom = html::html_to_dom(&html);
        let res: bool = html::has_favicon(&dom.document);

        assert!(res);
    }

    #[test]
    fn shortcut_icon() {
        let html = "<link rel=\"shortcut icon\" href=\"\" />
text
";
        let dom = html::html_to_dom(&html);
        let res: bool = html::has_favicon(&dom.document);

        assert!(res);
    }
}

//  ███████╗ █████╗ ██╗██╗     ██╗███╗   ██╗ ██████╗
//  ██╔════╝██╔══██╗██║██║     ██║████╗  ██║██╔════╝
//  █████╗  ███████║██║██║     ██║██╔██╗ ██║██║  ███╗
//  ██╔══╝  ██╔══██║██║██║     ██║██║╚██╗██║██║   ██║
//  ██║     ██║  ██║██║███████╗██║██║ ╚████║╚██████╔╝
//  ╚═╝     ╚═╝  ╚═╝╚═╝╚══════╝╚═╝╚═╝  ╚═══╝ ╚═════╝

#[cfg(test)]
mod failing {
    use crate::html;
    use crate::opts::Options;

    #[test]
    fn absent() {
        let html = "
text
";
        let dom = html::html_to_dom(&html);
        let res: bool = html::has_favicon(&dom.document);

        assert!(!res);
    }
}
<commit_msg>remove unused import opts::Options;<commit_after>//  ██████╗  █████╗ ███████╗███████╗██╗███╗   ██╗ ██████╗
//  ██╔══██╗██╔══██╗██╔════╝██╔════╝██║████╗  ██║██╔════╝
//  ██████╔╝███████║███████╗███████╗██║██╔██╗ ██║██║  ███╗
//  ██╔═══╝ ██╔══██║╚════██║╚════██║██║██║╚██╗██║██║   ██║
//  ██║     ██║  ██║███████║███████║██║██║ ╚████║╚██████╔╝
//  ╚═╝     ╚═╝  ╚═╝╚══════╝╚══════╝╚═╝╚═╝  ╚═══╝ ╚═════╝

#[cfg(test)]
mod passing {
    use crate::html;

    #[test]
    fn icon() {
        let html = "<link rel=\"icon\" href=\"\" />
text
";
        let dom = html::html_to_dom(&html);
        let res: bool = html::has_favicon(&dom.document);

        assert!(res);
    }

    #[test]
    fn shortcut_icon() {
        let html = "<link rel=\"shortcut icon\" href=\"\" />
text
";
        let dom = html::html_to_dom(&html);
        let res: bool = html::has_favicon(&dom.document);

        assert!(res);
    }
}

//  ███████╗ █████╗ ██╗██╗     ██╗███╗   ██╗ ██████╗
//  ██╔════╝██╔══██╗██║██║     ██║████╗  ██║██╔════╝
//  █████╗  ███████║██║██║     ██║██╔██╗ ██║██║  ███╗
//  ██╔══╝  ██╔══██║██║██║     ██║██║╚██╗██║██║   ██║
//  ██║     ██║  ██║██║███████╗██║██║ ╚████║╚██████╔╝
//  ╚═╝     ╚═╝  ╚═╝╚═╝╚══════╝╚═╝╚═╝  ╚═══╝ ╚═════╝

#[cfg(test)]
mod failing {
    use crate::html;

    #[test]
    fn absent() {
        let html = "
text
";
        let dom = html::html_to_dom(&html);
        let res: bool = html::has_favicon(&dom.document);

        assert!(!res);
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;

use progress::{Timestamp, Scope};
use progress::nested::Source::ScopeOutput;
use progress::nested::Target::ScopeInput;
use progress::count_map::CountMap;

use communication::Data;
use communication::observer::{Counter, Tee, Extensions};
use communication::pact::Pipeline;

use construction::{Stream, GraphBuilder};
use construction::operators::binary::BinaryStreamExt;

// NOTE : These used to have more exotic implementations that connected observers in a tangle.
// NOTE : It was defective when used with the Observer protocol, because it just forwarded open and
// NOTE : shut messages, without concern for the fact that there would be multiple opens and shuts,
// NOTE : from each of its inputs. This implementation does more staging of data, but should be
// NOTE : less wrong.

pub trait ConcatExt<G: GraphBuilder, D: Data> {
    fn concat(&self, &Stream<G, D>) -> Stream<G, D>;
}

impl<G: GraphBuilder, D: Data> ConcatExt<G, D> for Stream<G, D> {
    fn concat(&self, other: &Stream<G, D>) -> Stream<G, D> {
        self.binary_stream(other, Pipeline, Pipeline, "concat", |input1, input2, output| {
            while let Some((time, data)) = input1.pull() {
                output.give_message_at(time, data);
            }
            while let Some((time, data)) = input2.pull() {
                output.give_message_at(time, data);
            }
        })
    }
}

pub trait ConcatVecExt<G: GraphBuilder, D: Data> {
    fn concatenate(&self, Vec<Stream<G, D>>) -> Stream<G, D>;
}

impl<G: GraphBuilder, D: Data> ConcatVecExt<G, D> for G {
    fn concatenate(&self, mut sources: Vec<Stream<G, D>>) -> Stream<G, D> {
        if let Some(mut result) = sources.pop() {
            while let Some(next) = sources.pop() {
                result = result.concat(&next);
            }
            result
        }
        else {
            panic!("must pass at least one stream to concatenate");
        }
    }
}
<commit_msg>tieding up use statements<commit_after>use communication::Data;
use communication::observer::Extensions;
use communication::pact::Pipeline;

use construction::{Stream, GraphBuilder};
use construction::operators::binary::BinaryStreamExt;

// NOTE : These used to have more exotic implementations that connected observers in a tangle.
// NOTE : It was defective when used with the Observer protocol, because it just forwarded open and
// NOTE : shut messages, without concern for the fact that there would be multiple opens and shuts,
// NOTE : from each of its inputs. This implementation does more staging of data, but should be
// NOTE : less wrong.

pub trait ConcatExt<G: GraphBuilder, D: Data> {
    fn concat(&self, &Stream<G, D>) -> Stream<G, D>;
}

impl<G: GraphBuilder, D: Data> ConcatExt<G, D> for Stream<G, D> {
    fn concat(&self, other: &Stream<G, D>) -> Stream<G, D> {
        self.binary_stream(other, Pipeline, Pipeline, "concat", |input1, input2, output| {
            while let Some((time, data)) = input1.pull() {
                output.give_message_at(time, data);
            }
            while let Some((time, data)) = input2.pull() {
                output.give_message_at(time, data);
            }
        })
    }
}

pub trait ConcatVecExt<G: GraphBuilder, D: Data> {
    fn concatenate(&self, Vec<Stream<G, D>>) -> Stream<G, D>;
}

impl<G: GraphBuilder, D: Data> ConcatVecExt<G, D> for G {
    fn concatenate(&self, mut sources: Vec<Stream<G, D>>) -> Stream<G, D> {
        if let Some(mut result) = sources.pop() {
            while let Some(next) = sources.pop() {
                result = result.concat(&next);
            }
            result
        }
        else {
            panic!("must pass at least one stream to concatenate");
        }
    }
}
<|endoftext|>


<commit_before>use super::util::*;
<commit_msg>Clarified the bad line by splitting up statements<commit_after>use super::util::*;

#[test]
fn ensure_workspace_switch_when_fullscreen() {
    let mut tree = basic_tree();
    let active_id = tree.active_id().unwrap();
    tree.set_fullscreen(active_id, true).unwrap();
    tree = tree.add_view().unwrap();
    tree = tree.switch_to_workspace("2").unwrap();
    tree.switch_to_workspace("1").unwrap();
}
<|endoftext|>


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

use cell::UnsafeCell;
use libc;
use sys::mutex::{self, Mutex};
use time::Duration;

pub struct Condvar { inner: UnsafeCell<libc::pthread_cond_t> }

unsafe impl Send for Condvar {}
unsafe impl Sync for Condvar {}

const TIMESPEC_MAX: libc::timespec = libc::timespec {
    tv_sec: <libc::time_t>::max_value(),
    tv_nsec: 1_000_000_000 - 1,
};

impl Condvar {
    pub const fn new() -> Condvar {
        // Might be moved and address is changing it is better to avoid
        // initialization of potentially opaque OS data before it landed
        Condvar { inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER) }
    }

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub unsafe fn init(&mut self) {}

    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
    pub unsafe fn init(&mut self) {
        use mem;
        let mut attr: libc::pthread_condattr_t = mem::uninitialized();
        let r = libc::pthread_condattr_init(&mut attr);
        assert_eq!(r, 0);
        let r = libc::pthread_condattr_setclock(&mut attr, libc::CLOCK_MONOTONIC);
        assert_eq!(r, 0);
        let r = libc::pthread_cond_init(self.inner.get(), &attr);
        assert_eq!(r, 0);
        let r = libc::pthread_condattr_destroy(&mut attr);
        assert_eq!(r, 0);
    }

    #[inline]
    pub unsafe fn notify_one(&self) {
        let r = libc::pthread_cond_signal(self.inner.get());
        debug_assert_eq!(r, 0);
    }

    #[inline]
    pub unsafe fn notify_all(&self) {
        let r = libc::pthread_cond_broadcast(self.inner.get());
        debug_assert_eq!(r, 0);
    }

    #[inline]
    pub unsafe fn wait(&self, mutex: &Mutex) {
        let r = libc::pthread_cond_wait(self.inner.get(), mutex::raw(mutex));
        debug_assert_eq!(r, 0);
    }

    // This implementation is used on systems that support pthread_condattr_setclock
    // where we configure condition variable to use monotonic clock (instead of
    // default system clock). This approach avoids all problems that result
    // from changes made to the system time.
    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
        use mem;

        let mut now: libc::timespec = mem::zeroed();
        let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
        assert_eq!(r, 0);

        // Nanosecond calculations can't overflow because both values are below 1e9.
        let nsec = dur.subsec_nanos() as libc::c_long + now.tv_nsec as libc::c_long;
        // FIXME: Casting u64 into time_t could truncate the value.
        let sec = (dur.as_secs() as libc::time_t)
            .checked_add((nsec / 1_000_000_000) as libc::time_t)
            .and_then(|s| s.checked_add(now.tv_sec));
        let nsec = nsec % 1_000_000_000;

        let timeout = sec.map(|s| {
            libc::timespec { tv_sec: s, tv_nsec: nsec }
        }).unwrap_or(TIMESPEC_MAX);

        let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
                                            &timeout);
        assert!(r == libc::ETIMEDOUT || r == 0);
        r == 0
    }

    // This implementation is modeled after libcxx's condition_variable
    // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
    // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
        use ptr;
        use time::Instant;

        // First, figure out what time it currently is, in both system and
        // stable time.  pthread_cond_timedwait uses system time, but we want to
        // report timeout based on stable time.
        let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
        let stable_now = Instant::now();
        let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());
        debug_assert_eq!(r, 0);

        let nsec = dur.subsec_nanos() as libc::c_long +
                   (sys_now.tv_usec * 1000) as libc::c_long;
        let extra = (nsec / 1_000_000_000) as libc::time_t;
        let nsec = nsec % 1_000_000_000;
        let seconds = dur.as_secs() as libc::time_t;

        let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| {
            s.checked_add(seconds)
        }).map(|s| {
            libc::timespec { tv_sec: s, tv_nsec: nsec }
        }).unwrap_or(TIMESPEC_MAX);

        // And wait!
        let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
                                            &timeout);
        debug_assert!(r == libc::ETIMEDOUT || r == 0);

        // ETIMEDOUT is not a totally reliable method of determining timeout due
        // to clock shifts, so do the check ourselves
        stable_now.elapsed() < dur
    }

    #[inline]
    #[cfg(not(target_os = "dragonfly"))]
    pub unsafe fn destroy(&self) {
        let r = libc::pthread_cond_destroy(self.inner.get());
        debug_assert_eq!(r, 0);
    }

    #[inline]
    #[cfg(target_os = "dragonfly")]
    pub unsafe fn destroy(&self) {
        let r = libc::pthread_cond_destroy(self.inner.get());
        // On DragonFly pthread_cond_destroy() returns EINVAL if called on
        // a condvar that was just initialized with
        // libc::PTHREAD_COND_INITIALIZER. Once it is used or
        // pthread_cond_init() is called, this behaviour no longer occurs.
        debug_assert!(r == 0 || r == libc::EINVAL);
    }
}
<commit_msg>Avoid using pthread_condattr_setclock on Android.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use cell::UnsafeCell;
use libc;
use sys::mutex::{self, Mutex};
use time::Duration;

pub struct Condvar { inner: UnsafeCell<libc::pthread_cond_t> }

unsafe impl Send for Condvar {}
unsafe impl Sync for Condvar {}

const TIMESPEC_MAX: libc::timespec = libc::timespec {
    tv_sec: <libc::time_t>::max_value(),
    tv_nsec: 1_000_000_000 - 1,
};

impl Condvar {
    pub const fn new() -> Condvar {
        // Might be moved and address is changing it is better to avoid
        // initialization of potentially opaque OS data before it landed
        Condvar { inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER) }
    }

    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
    pub unsafe fn init(&mut self) {}

    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
    pub unsafe fn init(&mut self) {
        use mem;
        let mut attr: libc::pthread_condattr_t = mem::uninitialized();
        let r = libc::pthread_condattr_init(&mut attr);
        assert_eq!(r, 0);
        let r = libc::pthread_condattr_setclock(&mut attr, libc::CLOCK_MONOTONIC);
        assert_eq!(r, 0);
        let r = libc::pthread_cond_init(self.inner.get(), &attr);
        assert_eq!(r, 0);
        let r = libc::pthread_condattr_destroy(&mut attr);
        assert_eq!(r, 0);
    }

    #[inline]
    pub unsafe fn notify_one(&self) {
        let r = libc::pthread_cond_signal(self.inner.get());
        debug_assert_eq!(r, 0);
    }

    #[inline]
    pub unsafe fn notify_all(&self) {
        let r = libc::pthread_cond_broadcast(self.inner.get());
        debug_assert_eq!(r, 0);
    }

    #[inline]
    pub unsafe fn wait(&self, mutex: &Mutex) {
        let r = libc::pthread_cond_wait(self.inner.get(), mutex::raw(mutex));
        debug_assert_eq!(r, 0);
    }

    // This implementation is used on systems that support pthread_condattr_setclock
    // where we configure condition variable to use monotonic clock (instead of
    // default system clock). This approach avoids all problems that result
    // from changes made to the system time.
    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
        use mem;

        let mut now: libc::timespec = mem::zeroed();
        let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
        assert_eq!(r, 0);

        // Nanosecond calculations can't overflow because both values are below 1e9.
        let nsec = dur.subsec_nanos() as libc::c_long + now.tv_nsec as libc::c_long;
        // FIXME: Casting u64 into time_t could truncate the value.
        let sec = (dur.as_secs() as libc::time_t)
            .checked_add((nsec / 1_000_000_000) as libc::time_t)
            .and_then(|s| s.checked_add(now.tv_sec));
        let nsec = nsec % 1_000_000_000;

        let timeout = sec.map(|s| {
            libc::timespec { tv_sec: s, tv_nsec: nsec }
        }).unwrap_or(TIMESPEC_MAX);

        let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
                                            &timeout);
        assert!(r == libc::ETIMEDOUT || r == 0);
        r == 0
    }

    // This implementation is modeled after libcxx's condition_variable
    // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
    // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
        use ptr;
        use time::Instant;

        // First, figure out what time it currently is, in both system and
        // stable time.  pthread_cond_timedwait uses system time, but we want to
        // report timeout based on stable time.
        let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
        let stable_now = Instant::now();
        let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());
        debug_assert_eq!(r, 0);

        let nsec = dur.subsec_nanos() as libc::c_long +
                   (sys_now.tv_usec * 1000) as libc::c_long;
        let extra = (nsec / 1_000_000_000) as libc::time_t;
        let nsec = nsec % 1_000_000_000;
        let seconds = dur.as_secs() as libc::time_t;

        let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| {
            s.checked_add(seconds)
        }).map(|s| {
            libc::timespec { tv_sec: s, tv_nsec: nsec }
        }).unwrap_or(TIMESPEC_MAX);

        // And wait!
        let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
                                            &timeout);
        debug_assert!(r == libc::ETIMEDOUT || r == 0);

        // ETIMEDOUT is not a totally reliable method of determining timeout due
        // to clock shifts, so do the check ourselves
        stable_now.elapsed() < dur
    }

    #[inline]
    #[cfg(not(target_os = "dragonfly"))]
    pub unsafe fn destroy(&self) {
        let r = libc::pthread_cond_destroy(self.inner.get());
        debug_assert_eq!(r, 0);
    }

    #[inline]
    #[cfg(target_os = "dragonfly")]
    pub unsafe fn destroy(&self) {
        let r = libc::pthread_cond_destroy(self.inner.get());
        // On DragonFly pthread_cond_destroy() returns EINVAL if called on
        // a condvar that was just initialized with
        // libc::PTHREAD_COND_INITIALIZER. Once it is used or
        // pthread_cond_init() is called, this behaviour no longer occurs.
        debug_assert!(r == 0 || r == libc::EINVAL);
    }
}
<|endoftext|>


<commit_before>extern crate jpeg_decoder as jpeg;
extern crate png;

use png::HasParameters;
use std::env;
use std::fs::File;
use std::io::{self, BufReader, Write};
use std::process;

fn usage() -> ! {
    write!(io::stderr(), "usage: decode image.jpg image.png").unwrap();
    process::exit(1)
}

fn main() {
    let mut args = env::args().skip(1);
    let input_path = args.next().unwrap_or_else(|| usage());
    let output_path = args.next().unwrap_or_else(|| usage());

    let input_file = File::open(input_path).expect("The specified input file could not be opened");
    let mut decoder = jpeg::Decoder::new(BufReader::new(input_file));
    let mut data = decoder.decode().expect("Decoding failed. If other software can successfully decode the specified JPEG image, then it's likely that there is a bug in jpeg-decoder");
    let info = decoder.info().unwrap();

    let output_file = File::create(output_path).unwrap();
    let mut encoder = png::Encoder::new(output_file, info.width as u32, info.height as u32);
    encoder.set_depth(png::BitDepth::Eight);

    match info.pixel_format {
        jpeg::PixelFormat::L8     => encoder.set_color(png::ColorType::Grayscale),
        jpeg::PixelFormat::RGB24  => encoder.set_color(png::ColorType::RGB),
        jpeg::PixelFormat::CMYK32 => {
            data = cmyk_to_rgb(&mut data);
            encoder.set_color(png::ColorType::RGB)
        },
    };

    encoder.write_header()
           .expect("writing png header failed")
           .write_image_data(&data)
           .expect("png encoding failed");
}

fn cmyk_to_rgb(input: &[u8]) -> Vec<u8> {
    let size = input.len() - input.len() / 4;
    let mut output = Vec::with_capacity(size);

    for pixel in input.chunks(4) {
        let c = pixel[0] as f32 / 255.0;
        let m = pixel[1] as f32 / 255.0;
        let y = pixel[2] as f32 / 255.0;
        let k = pixel[3] as f32 / 255.0;

        // CMYK -> CMY
        let c = c * (1.0 - k) + k;
        let m = m * (1.0 - k) + k;
        let y = y * (1.0 - k) + k;

        // CMY -> RGB
        let r = (1.0 - c) * 255.0;
        let g = (1.0 - m) * 255.0;
        let b = (1.0 - y) * 255.0;

        output.push(r as u8);
        output.push(g as u8);
        output.push(b as u8);
    }

    output
}
<commit_msg>remove unused import<commit_after>extern crate jpeg_decoder as jpeg;
extern crate png;

use std::env;
use std::fs::File;
use std::io::{self, BufReader, Write};
use std::process;

fn usage() -> ! {
    write!(io::stderr(), "usage: decode image.jpg image.png").unwrap();
    process::exit(1)
}

fn main() {
    let mut args = env::args().skip(1);
    let input_path = args.next().unwrap_or_else(|| usage());
    let output_path = args.next().unwrap_or_else(|| usage());

    let input_file = File::open(input_path).expect("The specified input file could not be opened");
    let mut decoder = jpeg::Decoder::new(BufReader::new(input_file));
    let mut data = decoder.decode().expect("Decoding failed. If other software can successfully decode the specified JPEG image, then it's likely that there is a bug in jpeg-decoder");
    let info = decoder.info().unwrap();

    let output_file = File::create(output_path).unwrap();
    let mut encoder = png::Encoder::new(output_file, info.width as u32, info.height as u32);
    encoder.set_depth(png::BitDepth::Eight);

    match info.pixel_format {
        jpeg::PixelFormat::L8     => encoder.set_color(png::ColorType::Grayscale),
        jpeg::PixelFormat::RGB24  => encoder.set_color(png::ColorType::RGB),
        jpeg::PixelFormat::CMYK32 => {
            data = cmyk_to_rgb(&mut data);
            encoder.set_color(png::ColorType::RGB)
        },
    };

    encoder.write_header()
           .expect("writing png header failed")
           .write_image_data(&data)
           .expect("png encoding failed");
}

fn cmyk_to_rgb(input: &[u8]) -> Vec<u8> {
    let size = input.len() - input.len() / 4;
    let mut output = Vec::with_capacity(size);

    for pixel in input.chunks(4) {
        let c = pixel[0] as f32 / 255.0;
        let m = pixel[1] as f32 / 255.0;
        let y = pixel[2] as f32 / 255.0;
        let k = pixel[3] as f32 / 255.0;

        // CMYK -> CMY
        let c = c * (1.0 - k) + k;
        let m = m * (1.0 - k) + k;
        let y = y * (1.0 - k) + k;

        // CMY -> RGB
        let r = (1.0 - c) * 255.0;
        let g = (1.0 - m) * 255.0;
        let b = (1.0 - y) * 255.0;

        output.push(r as u8);
        output.push(g as u8);
        output.push(b as u8);
    }

    output
}
<|endoftext|>


<commit_before>extern crate skim;
use skim::{Skim, SkimOptions};
use std::default::Default;

pub fn main() {
    let options = SkimOptions::default();

    let selected_items = Skim::run_with(&options, None)
        .map(|out| out.selected_items)
        .unwrap_or_else(|| Vec::new());

    for item in selected_items.iter() {
        print!("{}{}", item.get_output_text(), "\n");
    }
}
<commit_msg>sample.rs: remove extraneous line.<commit_after>extern crate skim;
use skim::{Skim, SkimOptions};

pub fn main() {
    let options = SkimOptions::default();

    let selected_items = Skim::run_with(&options, None)
        .map(|out| out.selected_items)
        .unwrap_or_else(|| Vec::new());

    for item in selected_items.iter() {
        print!("{}{}", item.get_output_text(), "\n");
    }
}
<|endoftext|>


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

#![unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear")]

use clone::Clone;
use default::Default;
use hash;
use marker;

/// A trait representing stateful hashes which can be used to hash keys in a
/// `HashMap`.
///
/// A HashState is used as a factory for instances of `Hasher` which a `HashMap`
/// can then use to hash keys independently. A `HashMap` by default uses a state
/// which will create instances of a `SipHasher`, but a custom state factory can
/// be provided to the `with_hash_state` function.
///
/// If a hashing algorithm has no initial state, then the `Hasher` type for that
/// algorithm can implement the `Default` trait and create hash maps with the
/// `DefaultState` structure. This state is 0-sized and will simply delegate
/// to `Default` when asked to create a hasher.
pub trait HashState {
    /// Type of the hasher that will be created.
    type Hasher: hash::Hasher;

    /// Creates a new hasher based on the given state of this object.
    fn hasher(&self) -> Self::Hasher;
}

/// A structure which is a factory for instances of `Hasher` which implement the
/// default trait.
///
/// This struct has is 0-sized and does not need construction.
pub struct DefaultState<H>(marker::PhantomData<H>);

impl<H: Default + hash::Hasher> HashState for DefaultState<H> {
    type Hasher = H;
    fn hasher(&self) -> H { Default::default() }
}

impl<H> Clone for DefaultState<H> {
    fn clone(&self) -> DefaultState<H> { DefaultState(marker::PhantomData) }
}

impl<H> Default for DefaultState<H> {
    fn default() -> DefaultState<H> { DefaultState(marker::PhantomData) }
}
<commit_msg>typo "struct has is 0-sized"<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear")]

use clone::Clone;
use default::Default;
use hash;
use marker;

/// A trait representing stateful hashes which can be used to hash keys in a
/// `HashMap`.
///
/// A HashState is used as a factory for instances of `Hasher` which a `HashMap`
/// can then use to hash keys independently. A `HashMap` by default uses a state
/// which will create instances of a `SipHasher`, but a custom state factory can
/// be provided to the `with_hash_state` function.
///
/// If a hashing algorithm has no initial state, then the `Hasher` type for that
/// algorithm can implement the `Default` trait and create hash maps with the
/// `DefaultState` structure. This state is 0-sized and will simply delegate
/// to `Default` when asked to create a hasher.
pub trait HashState {
    /// Type of the hasher that will be created.
    type Hasher: hash::Hasher;

    /// Creates a new hasher based on the given state of this object.
    fn hasher(&self) -> Self::Hasher;
}

/// A structure which is a factory for instances of `Hasher` which implement the
/// default trait.
///
/// This struct is 0-sized and does not need construction.
pub struct DefaultState<H>(marker::PhantomData<H>);

impl<H: Default + hash::Hasher> HashState for DefaultState<H> {
    type Hasher = H;
    fn hasher(&self) -> H { Default::default() }
}

impl<H> Clone for DefaultState<H> {
    fn clone(&self) -> DefaultState<H> { DefaultState(marker::PhantomData) }
}

impl<H> Default for DefaultState<H> {
    fn default() -> DefaultState<H> { DefaultState(marker::PhantomData) }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;
extern crate mio;
extern crate rand;
extern crate docopt;
extern crate quiche;
extern crate env_logger;

use std::fs;
use std::io;
use std::net;
use std::path;

use std::collections::hash_map;
use std::collections::HashMap;

use docopt::Docopt;

use rand::Rng;

const LOCAL_CONN_ID_LEN: usize = 16;

const TRANSPORT_PARAMS: quiche::TransportParams = quiche::TransportParams {
    idle_timeout: 30,
    initial_max_data: 10_000_000,
    initial_max_bidi_streams: 100,
    initial_max_uni_streams: 100,
    max_packet_size: 1500,
    ack_delay_exponent: 3,
    disable_migration: true,
    max_ack_delay: 25,
    initial_max_stream_data_bidi_local: 1_000_000,
    initial_max_stream_data_bidi_remote: 1_000_000,
    initial_max_stream_data_uni: 1_000_000,
    stateless_reset_token_present: true,
    stateless_reset_token: [0xba; 16],
};

const USAGE: &str = "Usage: server [options]

Options:
  -h --help         Show this screen.
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
";

fn main() {
    let mut buf = [0; TRANSPORT_PARAMS.max_packet_size as usize];
    let mut out = [0; TRANSPORT_PARAMS.max_packet_size as usize];

    env_logger::init();

    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen")).unwrap();

    let poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket).unwrap();
    poll.register(&socket, mio::Token(0),
                  mio::Ready::readable(),
                  mio::PollOpt::edge()).unwrap();

    let mut connections: HashMap<net::SocketAddr, Box<quiche::Connection>> =
        HashMap::new();

    loop {
        // Garbage collect closed connections.
        connections.retain(|_, ref mut c| {
            debug!("Collecting garbage");

            if c.is_closed() {
                debug!("{} connection collected", c.trace_id());
            }

            !c.is_closed()
        });

        poll.poll(&mut events, None).unwrap();

        'read: loop {
            let (len, src) = match socket.recv_from(&mut buf) {
                Ok(v) => v,

                 Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            let buf = &mut buf[..len];

            let hdr = match quiche::Header::from_slice(buf, LOCAL_CONN_ID_LEN) {
                Ok(v) => v,

                Err(e) => {
                    error!("Parsing packet header failed: {:?}", e);
                    continue
                }
            };

            if hdr.ty == quiche::Type::VersionNegotiation {
                error!("Version negotiation invalid on the server");
                continue;
            }

            let conn = match connections.entry(src) {
                hash_map::Entry::Vacant(v) => {
                    if hdr.version != quiche::VERSION_DRAFT15 {
                        warn!("Doing version negotiation");

                        let len = quiche::Connection::negotiate_version(&hdr, &mut out)
                                               .unwrap();
                        let out = &out[..len];

                        socket.send_to(out, &src).unwrap();
                        continue;
                    }

                    if hdr.ty != quiche::Type::Initial {
                        error!("Packet is not Initial");
                        continue;
                    }

                    let mut scid: [u8; LOCAL_CONN_ID_LEN] = [0; LOCAL_CONN_ID_LEN];
                    rand::thread_rng().fill(&mut scid[..]);

                    let config = quiche::Config {
                        version: quiche::VERSION_DRAFT15,

                        local_conn_id: &scid,

                        local_transport_params: &TRANSPORT_PARAMS,

                        tls_server_name: args.get_str("--name"),
                        tls_certificate: args.get_str("--cert"),
                        tls_certificate_key: args.get_str("--key"),
                    };

                    debug!("New connection: dcid={} scid={} lcid={}",
                           hex_dump(&hdr.dcid),
                           hex_dump(&hdr.scid),
                           hex_dump(&scid));

                    let conn = quiche::Connection::new(config, true).unwrap();

                    v.insert(conn)
                },

                hash_map::Entry::Occupied(v) => v.into_mut(),
            };

            let mut left = len;

            // Process potentially coalesced packets.
            while left > 0 {
                let read = match conn.recv(&mut buf[len - left..len]) {
                    Ok(v)  => v,

                    Err(e) => {
                        error!("{} recv failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break 'read;
                    },
                };

                left -= read;

                debug!("{} read {} bytes", conn.trace_id(), read);
            }

            let streams: Vec<u64> = conn.stream_iter().collect();
            for s in streams {
                info!("{} stream {} is readable", conn.trace_id(), s);
                handle_stream(conn, s, &args);
            }
        }

        for (src, conn) in &mut connections {
            loop {
                let write = match conn.send(&mut out) {
                    Ok(v) => v,

                    Err(quiche::Error::NothingToDo) => {
                        debug!("{} done writing", conn.trace_id());
                        break;
                    },

                    Err(e) => {
                        error!("{} send failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break;
                    },
                };

                // TODO: coalesce packets.
                socket.send_to(&out[..write], &src).unwrap();

                debug!("{} written {} bytes", conn.trace_id(), write);
            }
        }
    }
}

fn handle_stream(conn: &mut quiche::Connection, stream: u64, args: &docopt::ArgvMap) {
    let stream_data = match conn.stream_recv(stream) {
        Ok(v) => v,

        Err(quiche::Error::NothingToDo) => return,

        Err(e) => panic!("{} stream recv failed {:?}",
                         conn.trace_id(), e),
    };

    info!("{} stream {} has {} bytes (fin? {})", conn.trace_id(),
          stream, stream_data.len(), stream_data.fin());

    if stream_data.len() > 4 && &stream_data[..4] == b"GET " {
        let uri = &stream_data[4..stream_data.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = path::Path::new(&uri);
        let mut path = path::PathBuf::from(args.get_str("--root"));

        for c in uri.components() {
            if let path::Component::Normal(v) = c {
                path.push(v)
            }
        }

        info!("{} got GET request for {:?} on stream {}",
              conn.trace_id(), path, stream);

        let data = fs::read(path.as_path())
                      .unwrap_or_else(|_| Vec::from(String::from("Not Found!\r\n")));

        info!("{} sending response of size {} on stream {}",
              conn.trace_id(), data.len(), stream);

        if let Err(e) = conn.stream_send(stream, &data, true) {
            error!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter()
                              .map(|b| format!("{:02x}", b))
                              .collect();

    vec.join("")
}
<commit_msg>server: collect closed connection at the end of the loop, not the start<commit_after>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;
extern crate mio;
extern crate rand;
extern crate docopt;
extern crate quiche;
extern crate env_logger;

use std::fs;
use std::io;
use std::net;
use std::path;

use std::collections::hash_map;
use std::collections::HashMap;

use docopt::Docopt;

use rand::Rng;

const LOCAL_CONN_ID_LEN: usize = 16;

const TRANSPORT_PARAMS: quiche::TransportParams = quiche::TransportParams {
    idle_timeout: 30,
    initial_max_data: 10_000_000,
    initial_max_bidi_streams: 100,
    initial_max_uni_streams: 100,
    max_packet_size: 1500,
    ack_delay_exponent: 3,
    disable_migration: true,
    max_ack_delay: 25,
    initial_max_stream_data_bidi_local: 1_000_000,
    initial_max_stream_data_bidi_remote: 1_000_000,
    initial_max_stream_data_uni: 1_000_000,
    stateless_reset_token_present: true,
    stateless_reset_token: [0xba; 16],
};

const USAGE: &str = "Usage: server [options]

Options:
  -h --help         Show this screen.
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
";

fn main() {
    let mut buf = [0; TRANSPORT_PARAMS.max_packet_size as usize];
    let mut out = [0; TRANSPORT_PARAMS.max_packet_size as usize];

    env_logger::init();

    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen")).unwrap();

    let poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket).unwrap();
    poll.register(&socket, mio::Token(0),
                  mio::Ready::readable(),
                  mio::PollOpt::edge()).unwrap();

    let mut connections: HashMap<net::SocketAddr, Box<quiche::Connection>> =
        HashMap::new();

    loop {
        poll.poll(&mut events, None).unwrap();

        'read: loop {
            let (len, src) = match socket.recv_from(&mut buf) {
                Ok(v) => v,

                 Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            let buf = &mut buf[..len];

            let hdr = match quiche::Header::from_slice(buf, LOCAL_CONN_ID_LEN) {
                Ok(v) => v,

                Err(e) => {
                    error!("Parsing packet header failed: {:?}", e);
                    continue
                }
            };

            if hdr.ty == quiche::Type::VersionNegotiation {
                error!("Version negotiation invalid on the server");
                continue;
            }

            let conn = match connections.entry(src) {
                hash_map::Entry::Vacant(v) => {
                    if hdr.version != quiche::VERSION_DRAFT15 {
                        warn!("Doing version negotiation");

                        let len = quiche::Connection::negotiate_version(&hdr, &mut out)
                                               .unwrap();
                        let out = &out[..len];

                        socket.send_to(out, &src).unwrap();
                        continue;
                    }

                    if hdr.ty != quiche::Type::Initial {
                        error!("Packet is not Initial");
                        continue;
                    }

                    let mut scid: [u8; LOCAL_CONN_ID_LEN] = [0; LOCAL_CONN_ID_LEN];
                    rand::thread_rng().fill(&mut scid[..]);

                    let config = quiche::Config {
                        version: quiche::VERSION_DRAFT15,

                        local_conn_id: &scid,

                        local_transport_params: &TRANSPORT_PARAMS,

                        tls_server_name: args.get_str("--name"),
                        tls_certificate: args.get_str("--cert"),
                        tls_certificate_key: args.get_str("--key"),
                    };

                    debug!("New connection: dcid={} scid={} lcid={}",
                           hex_dump(&hdr.dcid),
                           hex_dump(&hdr.scid),
                           hex_dump(&scid));

                    let conn = quiche::Connection::new(config, true).unwrap();

                    v.insert(conn)
                },

                hash_map::Entry::Occupied(v) => v.into_mut(),
            };

            let mut left = len;

            // Process potentially coalesced packets.
            while left > 0 {
                let read = match conn.recv(&mut buf[len - left..len]) {
                    Ok(v)  => v,

                    Err(e) => {
                        error!("{} recv failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break 'read;
                    },
                };

                left -= read;

                debug!("{} read {} bytes", conn.trace_id(), read);
            }

            let streams: Vec<u64> = conn.stream_iter().collect();
            for s in streams {
                info!("{} stream {} is readable", conn.trace_id(), s);
                handle_stream(conn, s, &args);
            }
        }

        for (src, conn) in &mut connections {
            loop {
                let write = match conn.send(&mut out) {
                    Ok(v) => v,

                    Err(quiche::Error::NothingToDo) => {
                        debug!("{} done writing", conn.trace_id());
                        break;
                    },

                    Err(e) => {
                        error!("{} send failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break;
                    },
                };

                // TODO: coalesce packets.
                socket.send_to(&out[..write], &src).unwrap();

                debug!("{} written {} bytes", conn.trace_id(), write);
            }
        }

        // Garbage collect closed connections.
        connections.retain(|_, ref mut c| {
            debug!("Collecting garbage");

            if c.is_closed() {
                debug!("{} connection collected", c.trace_id());
            }

            !c.is_closed()
        });
    }
}

fn handle_stream(conn: &mut quiche::Connection, stream: u64, args: &docopt::ArgvMap) {
    let stream_data = match conn.stream_recv(stream) {
        Ok(v) => v,

        Err(quiche::Error::NothingToDo) => return,

        Err(e) => panic!("{} stream recv failed {:?}",
                         conn.trace_id(), e),
    };

    info!("{} stream {} has {} bytes (fin? {})", conn.trace_id(),
          stream, stream_data.len(), stream_data.fin());

    if stream_data.len() > 4 && &stream_data[..4] == b"GET " {
        let uri = &stream_data[4..stream_data.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = path::Path::new(&uri);
        let mut path = path::PathBuf::from(args.get_str("--root"));

        for c in uri.components() {
            if let path::Component::Normal(v) = c {
                path.push(v)
            }
        }

        info!("{} got GET request for {:?} on stream {}",
              conn.trace_id(), path, stream);

        let data = fs::read(path.as_path())
                      .unwrap_or_else(|_| Vec::from(String::from("Not Found!\r\n")));

        info!("{} sending response of size {} on stream {}",
              conn.trace_id(), data.len(), stream);

        if let Err(e) = conn.stream_send(stream, &data, true) {
            error!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter()
                              .map(|b| format!("{:02x}", b))
                              .collect();

    vec.join("")
}
<|endoftext|>


<commit_before>extern crate rusttype;

use rusttype::{FontCollection, PixelsXY, point, PositionedGlyph};
use std::io::Write;

fn main() {
    let font_data = include_bytes!("Gudea-Regular.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap(); // only succeeds if collection consists of one font
    {
        // Desired font pixel height
        let height: f32 = 20.1; // to get 80 chars across (fits most terminals); adjust as desired
        let pixel_height = height.ceil() as usize;

        // 2x scale in x direction to counter the aspect ratio of monospace characters.
        let scale = PixelsXY(height*2.0, height);

        // The origin of a line of text is at the baseline (roughly where non-descending letters sit).
        // We don't want to clip the text, so we shift it down with an offset when laying it out.
        // v_metrics.ascent is the distance between the baseline and the highest edge of any glyph in
        // the font. That's enough to guarantee that there's no clipping.
        let v_metrics = font.v_metrics(scale);
        let offset = point(0.0, v_metrics.ascent);

        // Glyphs to draw for "Hello!". Feel free to try other strings.
        let glyphs: Vec<PositionedGlyph> = font.layout("Hello!", scale, offset).collect();

        // Find the most visually pleasing width to display
        let width = glyphs.iter().map(|g| g.h_metrics().advance_width)
            .fold(0.0, |x, y| x + y).ceil() as usize;

        println!("width: {}, height: {}", width, pixel_height);

        // Rasterise directly into ASCII art.
        let mut pixel_data = vec![b'@'; width * pixel_height];
        let mapping = b"@%#x+=:-. "; // The approximation of greyscale
        let mapping_scale = (mapping.len()-1) as f32;
        for g in glyphs {
            if let Some(bb) = g.pixel_bounding_box() {
                g.draw(|x, y, v| {
                    // v should be in the range 0.0 to 1.0
                    let i = (v*mapping_scale + 0.5) as usize;
                    // so something's wrong if you get $ in the output.
                    let c = mapping.get(i).cloned().unwrap_or(b'$');
                    let x = (x as i32 + bb.min.x) as usize;
                    let y = (y as i32 + bb.min.y) as usize;
                    pixel_data[(x + y * width)] = c;
                })
            }
        }

        // Print it out
        let stdout = ::std::io::stdout();
        let mut handle = stdout.lock();
        for j in 0..pixel_height {
            handle.write(&pixel_data[j*width..(j+1)*width]).unwrap();
            handle.write(b"\n").unwrap();
        }
    }
}
<commit_msg>Made the default text in the example more appropriate.<commit_after>extern crate rusttype;

use rusttype::{FontCollection, PixelsXY, point, PositionedGlyph};
use std::io::Write;

fn main() {
    let font_data = include_bytes!("Gudea-Regular.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap(); // only succeeds if collection consists of one font
    {
        // Desired font pixel height
        let height: f32 = 12.5; // to get 80 chars across (fits most terminals); adjust as desired
        let pixel_height = height.ceil() as usize;

        // 2x scale in x direction to counter the aspect ratio of monospace characters.
        let scale = PixelsXY(height*2.0, height);

        // The origin of a line of text is at the baseline (roughly where non-descending letters sit).
        // We don't want to clip the text, so we shift it down with an offset when laying it out.
        // v_metrics.ascent is the distance between the baseline and the highest edge of any glyph in
        // the font. That's enough to guarantee that there's no clipping.
        let v_metrics = font.v_metrics(scale);
        let offset = point(0.0, v_metrics.ascent);

        // Glyphs to draw for "Hello!". Feel free to try other strings.
        let glyphs: Vec<PositionedGlyph> = font.layout("RustType", scale, offset).collect();

        // Find the most visually pleasing width to display
        let width = glyphs.iter().map(|g| g.h_metrics().advance_width)
            .fold(0.0, |x, y| x + y).ceil() as usize;

        println!("width: {}, height: {}", width, pixel_height);

        // Rasterise directly into ASCII art.
        let mut pixel_data = vec![b'@'; width * pixel_height];
        let mapping = b"@%#x+=:-. "; // The approximation of greyscale
        let mapping_scale = (mapping.len()-1) as f32;
        for g in glyphs {
            if let Some(bb) = g.pixel_bounding_box() {
                g.draw(|x, y, v| {
                    // v should be in the range 0.0 to 1.0
                    let i = (v*mapping_scale + 0.5) as usize;
                    // so something's wrong if you get $ in the output.
                    let c = mapping.get(i).cloned().unwrap_or(b'$');
                    let x = (x as i32 + bb.min.x) as usize;
                    let y = (y as i32 + bb.min.y) as usize;
                    pixel_data[(x + y * width)] = c;
                })
            }
        }

        // Print it out
        let stdout = ::std::io::stdout();
        let mut handle = stdout.lock();
        for j in 0..pixel_height {
            handle.write(&pixel_data[j*width..(j+1)*width]).unwrap();
            handle.write(b"\n").unwrap();
        }
    }
}
<|endoftext|>


<commit_before>extern crate tutil;

use tutil::crayon::Style;
use tutil::crayon::Color::*;

use tutil::screen;

fn main() {
    println!("{}", Red.on(Black).blink().paint("Hello world!"));
    println!("{:?}", screen::size());
}
<commit_msg>Improve the example<commit_after>extern crate tutil;

use tutil::crayon::Style;
use tutil::crayon::Color::*;

use tutil::screen;

fn main() {
    println!("{}", Red.on(Black).blink().paint("Hello world!"));

    let size = screen::size().unwrap();
    println!("The screen size is {}x{}.", size.0, size.1);
}
<|endoftext|>