<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/. */

extern crate cc;
extern crate glsl_to_cxx;
extern crate webrender_build;

use std::collections::HashSet;
use std::fmt::Write;
use webrender_build::shader::{ShaderFeatureFlags, get_shader_features};

// Shader key is in "name feature,feature" format.
// File name needs to be formatted as "name_feature_feature".
fn shader_file(shader_key: &str) -> String {
    shader_key.replace(' ', "_").replace(',', "_")
}

fn write_load_shader(shader_keys: &[String]) {
    let mut load_shader = String::new();
    for s in shader_keys {
        let _ = write!(load_shader, "#include \"{}.h\"\n", shader_file(s));
    }
    load_shader.push_str("ProgramLoader load_shader(const char* name) {\n");
    for s in shader_keys {
        let _ = write!(load_shader, "  if (!strcmp(name, \"{}\")) {{ return {}_program::loader; }}\n",
                       s, shader_file(s));
    }
    load_shader.push_str("  return nullptr;\n}\n");
    std::fs::write(std::env::var("OUT_DIR").unwrap() + "/load_shader.h", load_shader).unwrap();
}

fn process_imports(shader_dir: &str, shader: &str, included: &mut HashSet<String>, output: &mut String) {
    if !included.insert(shader.into()) {
        return;
    }
    println!("cargo:rerun-if-changed={}/{}.glsl", shader_dir, shader);
    let source = std::fs::read_to_string(format!("{}/{}.glsl", shader_dir, shader)).unwrap();
    for line in source.lines() {
        if line.starts_with("#include ") {
            let imports = line["#include ".len() ..].split(',');
            for import in imports {
                process_imports(shader_dir, import, included, output);
            }
        } else if line.starts_with("#version ") || line.starts_with("#extension ") {
            // ignore
        } else {
            output.push_str(line);
            output.push('\n');
        }
    }
}

fn translate_shader(shader_key: &str, shader_dir: &str) {
    let mut imported = String::from("#define SWGL 1\n#define __VERSION__ 150\n");
    let _ = write!(imported, "#define WR_MAX_VERTEX_TEXTURE_WIDTH {}U\n",
                   webrender_build::MAX_VERTEX_TEXTURE_WIDTH);

    let (basename, features) =
        shader_key.split_at(shader_key.find(' ').unwrap_or(shader_key.len()));
    if !features.is_empty() {
        for feature in features.trim().split(',') {
            let _ = write!(imported, "#define WR_FEATURE_{}\n", feature);
        }
    }

    process_imports(shader_dir, basename, &mut HashSet::new(), &mut imported);

    let shader = shader_file(shader_key);

    let out_dir = std::env::var("OUT_DIR").unwrap();
    let imp_name = format!("{}/{}.c", out_dir, shader);
    std::fs::write(&imp_name, imported).unwrap();

    let mut build = cc::Build::new();
    build.no_default_flags(true);
    if let Ok(tool) = build.try_get_compiler() {
        if tool.is_like_msvc() {
            build.flag("/EP").flag("/clang:-undef");
        } else {
            build.flag("-xc").flag("-P").flag("-undef");
        }
    }
    // Use SWGLPP target to avoid pulling CFLAGS/CXXFLAGS.
    build.target("SWGLPP");
    build.file(&imp_name);
    let vs = build.clone()
        .define("WR_VERTEX_SHADER", Some("1"))
        .expand();
    let fs = build.clone()
        .define("WR_FRAGMENT_SHADER", Some("1"))
        .expand();
    let vs_name = format!("{}/{}.vert", out_dir, shader);
    let fs_name = format!("{}/{}.frag", out_dir, shader);
    std::fs::write(&vs_name, vs).unwrap();
    std::fs::write(&fs_name, fs).unwrap();

    let args = vec![
        "glsl_to_cxx".to_string(),
        vs_name,
        fs_name,
    ];
    let result = glsl_to_cxx::translate(&mut args.into_iter());
    std::fs::write(format!("{}/{}.h", out_dir, shader), result).unwrap();
}

fn main() {
    let shader_dir = match std::env::var("MOZ_SRC") {
        Ok(dir) => dir + "/gfx/wr/webrender/res",
        Err(_) => std::env::var("CARGO_MANIFEST_DIR").unwrap() + "/../webrender/res",
    };

    let shader_flags =
        ShaderFeatureFlags::GL |
        ShaderFeatureFlags::DUAL_SOURCE_BLENDING |
        ShaderFeatureFlags::ADVANCED_BLEND_EQUATION |
        ShaderFeatureFlags::DEBUG;
    let mut shaders: Vec<String> = Vec::new();
    for (name, features) in get_shader_features(shader_flags) {
        shaders.extend(features.iter().map(|f| {
            if f.is_empty() { name.to_owned() } else { format!("{} {}", name, f) }
        }));
    }

    shaders.sort();

    // We need to ensure that the C preprocessor does not pull compiler flags from
    // the host or target environment. Set up a SWGLPP target with empty flags to
    // work around this.
    if let Ok(target) = std::env::var("TARGET") {
        if let Ok(cc) = std::env::var(format!("CC_{}", target))
                        .or(std::env::var(format!("CC_{}", target.replace("-", "_")))) {
            std::env::set_var("CC_SWGLPP", cc);
        }
    }
    std::env::set_var("CFLAGS_SWGLPP", "");

    for shader in &shaders {
        translate_shader(shader, &shader_dir);
    }

    write_load_shader(&shaders);

    println!("cargo:rerun-if-changed=src/blend.h");
    println!("cargo:rerun-if-changed=src/composite.h");
    println!("cargo:rerun-if-changed=src/gl_defs.h");
    println!("cargo:rerun-if-changed=src/glsl.h");
    println!("cargo:rerun-if-changed=src/program.h");
    println!("cargo:rerun-if-changed=src/rasterize.h");
    println!("cargo:rerun-if-changed=src/swgl_ext.h");
    println!("cargo:rerun-if-changed=src/texture.h");
    println!("cargo:rerun-if-changed=src/vector_type.h");
    println!("cargo:rerun-if-changed=src/gl.cc");
    let mut build = cc::Build::new();
    build.cpp(true);

    // SWGL relies heavily on inlining for performance so override -Oz with -O2
    if build.get_compiler().args().contains(&std::ffi::OsString::from("-Oz")) {
        build.flag("-O2");
    }

    build.file("src/gl.cc")
        .flag("-std=c++17")
        .flag("-UMOZILLA_CONFIG_H")
        .flag("-fno-exceptions")
        .flag("-fno-rtti")
        .flag("-fno-math-errno")
        .define("_GLIBCXX_USE_CXX11_ABI", Some("0"))
        .include(shader_dir)
        .include("src")
        .include(std::env::var("OUT_DIR").unwrap())
        .compile("gl_cc");
}
<commit_msg>Bug 1675395 - Pass in flags for MSVC-like compilers in SWGL build script. r=jrmuizel<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/. */

extern crate cc;
extern crate glsl_to_cxx;
extern crate webrender_build;

use std::collections::HashSet;
use std::fmt::Write;
use webrender_build::shader::{ShaderFeatureFlags, get_shader_features};

// Shader key is in "name feature,feature" format.
// File name needs to be formatted as "name_feature_feature".
fn shader_file(shader_key: &str) -> String {
    shader_key.replace(' ', "_").replace(',', "_")
}

fn write_load_shader(shader_keys: &[String]) {
    let mut load_shader = String::new();
    for s in shader_keys {
        let _ = write!(load_shader, "#include \"{}.h\"\n", shader_file(s));
    }
    load_shader.push_str("ProgramLoader load_shader(const char* name) {\n");
    for s in shader_keys {
        let _ = write!(load_shader, "  if (!strcmp(name, \"{}\")) {{ return {}_program::loader; }}\n",
                       s, shader_file(s));
    }
    load_shader.push_str("  return nullptr;\n}\n");
    std::fs::write(std::env::var("OUT_DIR").unwrap() + "/load_shader.h", load_shader).unwrap();
}

fn process_imports(shader_dir: &str, shader: &str, included: &mut HashSet<String>, output: &mut String) {
    if !included.insert(shader.into()) {
        return;
    }
    println!("cargo:rerun-if-changed={}/{}.glsl", shader_dir, shader);
    let source = std::fs::read_to_string(format!("{}/{}.glsl", shader_dir, shader)).unwrap();
    for line in source.lines() {
        if line.starts_with("#include ") {
            let imports = line["#include ".len() ..].split(',');
            for import in imports {
                process_imports(shader_dir, import, included, output);
            }
        } else if line.starts_with("#version ") || line.starts_with("#extension ") {
            // ignore
        } else {
            output.push_str(line);
            output.push('\n');
        }
    }
}

fn translate_shader(shader_key: &str, shader_dir: &str) {
    let mut imported = String::from("#define SWGL 1\n#define __VERSION__ 150\n");
    let _ = write!(imported, "#define WR_MAX_VERTEX_TEXTURE_WIDTH {}U\n",
                   webrender_build::MAX_VERTEX_TEXTURE_WIDTH);

    let (basename, features) =
        shader_key.split_at(shader_key.find(' ').unwrap_or(shader_key.len()));
    if !features.is_empty() {
        for feature in features.trim().split(',') {
            let _ = write!(imported, "#define WR_FEATURE_{}\n", feature);
        }
    }

    process_imports(shader_dir, basename, &mut HashSet::new(), &mut imported);

    let shader = shader_file(shader_key);

    let out_dir = std::env::var("OUT_DIR").unwrap();
    let imp_name = format!("{}/{}.c", out_dir, shader);
    std::fs::write(&imp_name, imported).unwrap();

    let mut build = cc::Build::new();
    build.no_default_flags(true);
    if let Ok(tool) = build.try_get_compiler() {
        if tool.is_like_msvc() {
            build.flag("/EP");
            if tool.path().to_str().map_or(false, |p| p.contains("clang")) {
                build.flag("/clang:-undef");
            } else {
                build.flag("/u");
            }
        } else {
            build.flag("-xc").flag("-P").flag("-undef");
        }
    }
    // Use SWGLPP target to avoid pulling CFLAGS/CXXFLAGS.
    build.target("SWGLPP");
    build.file(&imp_name);
    let vs = build.clone()
        .define("WR_VERTEX_SHADER", Some("1"))
        .expand();
    let fs = build.clone()
        .define("WR_FRAGMENT_SHADER", Some("1"))
        .expand();
    let vs_name = format!("{}/{}.vert", out_dir, shader);
    let fs_name = format!("{}/{}.frag", out_dir, shader);
    std::fs::write(&vs_name, vs).unwrap();
    std::fs::write(&fs_name, fs).unwrap();

    let args = vec![
        "glsl_to_cxx".to_string(),
        vs_name,
        fs_name,
    ];
    let result = glsl_to_cxx::translate(&mut args.into_iter());
    std::fs::write(format!("{}/{}.h", out_dir, shader), result).unwrap();
}

fn main() {
    let shader_dir = match std::env::var("MOZ_SRC") {
        Ok(dir) => dir + "/gfx/wr/webrender/res",
        Err(_) => std::env::var("CARGO_MANIFEST_DIR").unwrap() + "/../webrender/res",
    };

    let shader_flags =
        ShaderFeatureFlags::GL |
        ShaderFeatureFlags::DUAL_SOURCE_BLENDING |
        ShaderFeatureFlags::ADVANCED_BLEND_EQUATION |
        ShaderFeatureFlags::DEBUG;
    let mut shaders: Vec<String> = Vec::new();
    for (name, features) in get_shader_features(shader_flags) {
        shaders.extend(features.iter().map(|f| {
            if f.is_empty() { name.to_owned() } else { format!("{} {}", name, f) }
        }));
    }

    shaders.sort();

    // We need to ensure that the C preprocessor does not pull compiler flags from
    // the host or target environment. Set up a SWGLPP target with empty flags to
    // work around this.
    if let Ok(target) = std::env::var("TARGET") {
        if let Ok(cc) = std::env::var(format!("CC_{}", target))
                        .or(std::env::var(format!("CC_{}", target.replace("-", "_")))) {
            std::env::set_var("CC_SWGLPP", cc);
        }
    }
    std::env::set_var("CFLAGS_SWGLPP", "");

    for shader in &shaders {
        translate_shader(shader, &shader_dir);
    }

    write_load_shader(&shaders);

    println!("cargo:rerun-if-changed=src/blend.h");
    println!("cargo:rerun-if-changed=src/composite.h");
    println!("cargo:rerun-if-changed=src/gl_defs.h");
    println!("cargo:rerun-if-changed=src/glsl.h");
    println!("cargo:rerun-if-changed=src/program.h");
    println!("cargo:rerun-if-changed=src/rasterize.h");
    println!("cargo:rerun-if-changed=src/swgl_ext.h");
    println!("cargo:rerun-if-changed=src/texture.h");
    println!("cargo:rerun-if-changed=src/vector_type.h");
    println!("cargo:rerun-if-changed=src/gl.cc");
    let mut build = cc::Build::new();
    build.cpp(true);

    if let Ok(tool) = build.try_get_compiler() {
        if tool.is_like_msvc() {
            build.flag("/std:c++17")
                 .flag("/EHs-")
                 .flag("/GR-")
                 .flag("/UMOZILLA_CONFIG_H");
        } else {
            build.flag("-std=c++17")
                 .flag("-fno-exceptions")
                 .flag("-fno-rtti")
                 .flag("-fno-math-errno")
                 .flag("-UMOZILLA_CONFIG_H");
        }
        // SWGL relies heavily on inlining for performance so override -Oz with -O2
        if tool.args().contains(&"-Oz".into()) {
            build.flag("-O2");
        }
    }

    build.file("src/gl.cc")
        .define("_GLIBCXX_USE_CXX11_ABI", Some("0"))
        .include(shader_dir)
        .include("src")
        .include(std::env::var("OUT_DIR").unwrap())
        .compile("gl_cc");
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::collections::HashSet;
use std::fmt::{self, Debug};
use std::hash::Hash;
use std::slice;

pub struct OrderedSet<T> {
    set: HashSet<T>,
    vec: Vec<T>,
}

impl<'a, T> OrderedSet<&'a T>
where
    T: Hash + Eq,
{
    pub fn new() -> Self {
        OrderedSet {
            set: HashSet::new(),
            vec: Vec::new(),
        }
    }

    pub fn insert(&mut self, value: &'a T) -> bool {
        let new = self.set.insert(value);
        if new {
            self.vec.push(value);
        }
        new
    }

    pub fn contains<Q>(&self, value: &Q) -> bool
    where
        &'a T: Borrow<Q>,
        Q: ?Sized + Hash + Eq,
    {
        self.set.contains(value)
    }

    pub fn get<Q>(&self, value: &Q) -> Option<&'a T>
    where
        &'a T: Borrow<Q>,
        Q: ?Sized + Hash + Eq,
    {
        self.set.get(value).copied()
    }
}

impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
    type Item = &'a T;
    type IntoIter = Iter<'s, 'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        Iter(self.vec.iter())
    }
}

pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);

impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().copied()
    }
}

impl<'a, T> Debug for OrderedSet<&'a T>
where
    T: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_set().entries(self).finish()
    }
}
<commit_msg>Introduce a visibility boundary inside of set module<commit_after>use std::fmt::{self, Debug};
use std::slice;

pub use self::ordered::OrderedSet;

mod ordered {
    use super::Iter;
    use std::borrow::Borrow;
    use std::collections::HashSet;
    use std::hash::Hash;

    pub struct OrderedSet<T> {
        set: HashSet<T>,
        vec: Vec<T>,
    }

    impl<'a, T> OrderedSet<&'a T>
    where
        T: Hash + Eq,
    {
        pub fn new() -> Self {
            OrderedSet {
                set: HashSet::new(),
                vec: Vec::new(),
            }
        }

        pub fn insert(&mut self, value: &'a T) -> bool {
            let new = self.set.insert(value);
            if new {
                self.vec.push(value);
            }
            new
        }

        pub fn contains<Q>(&self, value: &Q) -> bool
        where
            &'a T: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.set.contains(value)
        }

        pub fn get<Q>(&self, value: &Q) -> Option<&'a T>
        where
            &'a T: Borrow<Q>,
            Q: ?Sized + Hash + Eq,
        {
            self.set.get(value).copied()
        }
    }

    impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
        type Item = &'a T;
        type IntoIter = Iter<'s, 'a, T>;
        fn into_iter(self) -> Self::IntoIter {
            Iter(self.vec.iter())
        }
    }
}

pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);

impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().copied()
    }
}

impl<'a, T> Debug for OrderedSet<&'a T>
where
    T: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_set().entries(self).finish()
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

//! Utilities for reading, writing, and transforming data for the LSP service
// We use two crates, lsp_types and lsp_server, for interacting with LSP. This module re-exports
// types from both so that we have a central source-of-truth for all LSP-related utilities.

use crate::lsp_process_error::LSPProcessResult;
use crossbeam::channel::{SendError, Sender};
use lsp_server::{Message, Notification as ServerNotification, Request as ServerRequest};
pub use lsp_types::*;
use lsp_types::{
    notification::{Notification, PublishDiagnostics, ShowMessage},
    request::Request,
};
use serde::{Deserialize, Serialize};

#[derive(Debug)]
pub enum ShowStatus {}

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ShowStatusParams {
    #[serde(rename = "type")]
    pub type_: MessageType,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub progress: Option<Progress>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub uri: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub message: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub short_message: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub actions: Option<Vec<MessageActionItem>>,
}

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct Progress {
    numerator: f32,
    denominator: Option<f32>,
}

impl Request for ShowStatus {
    type Params = ShowStatusParams;
    type Result = ();
    const METHOD: &'static str = "window/showStatus";
}

pub fn set_ready_status(sender: &Sender<Message>) {
    update_status(
        "Relay: ready",
        Some("The Relay extension is ready"),
        MessageType::Info,
        sender,
    );
}

pub fn set_initializing_status(sender: &Sender<Message>) {
    update_in_progress_status(
        "Relay: initializing...",
        Some(
            "The Relay compiler will start when you open a Javascript file containing a graphql literal",
        ),
        sender,
    );
}

pub fn update_in_progress_status(
    short_message: impl Into<String>,
    message: Option<impl Into<String>>,
    sender: &Sender<Message>,
) {
    update_status(short_message, message, MessageType::Warning, sender);
}

pub fn update_status(
    short_message: impl Into<String>,
    message: Option<impl Into<String>>,
    type_: MessageType,
    sender: &Sender<Message>,
) {
    let request = ServerRequest::new(
        ShowStatus::METHOD.to_string().into(),
        ShowStatus::METHOD.into(),
        ShowStatusParams {
            type_,
            progress: None,
            uri: None,
            message: message.map(|s| s.into()),
            short_message: Some(short_message.into()),
            actions: None,
        },
    );
    sender
        .send(Message::Request(request))
        .expect("update_status: failed to send");
}

/// Show a notification in the client
#[allow(dead_code)]
pub fn show_info_message(
    sender: &Sender<Message>,
    message: impl Into<String>,
) -> Result<(), SendError<Message>> {
    let notif = ServerNotification::new(
        ShowMessage::METHOD.into(),
        ShowMessageParams {
            typ: MessageType::Info,
            message: message.into(),
        },
    );

    sender.send(Message::Notification(notif))
}

/// Publish diagnostics to the client
pub fn publish_diagnostic(
    diagnostic_params: PublishDiagnosticsParams,
    sender: &Sender<Message>,
) -> LSPProcessResult<()> {
    let notif = ServerNotification::new(PublishDiagnostics::METHOD.into(), diagnostic_params);
    sender
        .send(Message::Notification(notif))
        .unwrap_or_else(|_| {
            // TODO(brandondail) log here
        });
    Ok(())
}
<commit_msg>Do not export lsp_types::* from lsp.rs<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

//! Utilities for reading, writing, and transforming data for the LSP service
// We use two crates, lsp_types and lsp_server, for interacting with LSP. This module re-exports
// types from both so that we have a central source-of-truth for all LSP-related utilities.

use crate::lsp_process_error::LSPProcessResult;
use crossbeam::channel::{SendError, Sender};
use lsp_server::{Message, Notification as ServerNotification, Request as ServerRequest};
use lsp_types::{
    notification::{Notification, PublishDiagnostics, ShowMessage},
    request::Request,
    MessageActionItem, MessageType, PublishDiagnosticsParams, ShowMessageParams,
};
use serde::{Deserialize, Serialize};

#[derive(Debug)]
pub enum ShowStatus {}

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ShowStatusParams {
    #[serde(rename = "type")]
    pub type_: MessageType,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub progress: Option<Progress>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub uri: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub message: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub short_message: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub actions: Option<Vec<MessageActionItem>>,
}

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct Progress {
    numerator: f32,
    denominator: Option<f32>,
}

impl Request for ShowStatus {
    type Params = ShowStatusParams;
    type Result = ();
    const METHOD: &'static str = "window/showStatus";
}

pub fn set_ready_status(sender: &Sender<Message>) {
    update_status(
        "Relay: ready",
        Some("The Relay extension is ready"),
        MessageType::Info,
        sender,
    );
}

pub fn set_initializing_status(sender: &Sender<Message>) {
    update_in_progress_status(
        "Relay: initializing...",
        Some(
            "The Relay compiler will start when you open a Javascript file containing a graphql literal",
        ),
        sender,
    );
}

pub fn update_in_progress_status(
    short_message: impl Into<String>,
    message: Option<impl Into<String>>,
    sender: &Sender<Message>,
) {
    update_status(short_message, message, MessageType::Warning, sender);
}

pub fn update_status(
    short_message: impl Into<String>,
    message: Option<impl Into<String>>,
    type_: MessageType,
    sender: &Sender<Message>,
) {
    let request = ServerRequest::new(
        ShowStatus::METHOD.to_string().into(),
        ShowStatus::METHOD.into(),
        ShowStatusParams {
            type_,
            progress: None,
            uri: None,
            message: message.map(|s| s.into()),
            short_message: Some(short_message.into()),
            actions: None,
        },
    );
    sender
        .send(Message::Request(request))
        .expect("update_status: failed to send");
}

/// Show a notification in the client
#[allow(dead_code)]
pub fn show_info_message(
    sender: &Sender<Message>,
    message: impl Into<String>,
) -> Result<(), SendError<Message>> {
    let notif = ServerNotification::new(
        ShowMessage::METHOD.into(),
        ShowMessageParams {
            typ: MessageType::Info,
            message: message.into(),
        },
    );

    sender.send(Message::Notification(notif))
}

/// Publish diagnostics to the client
pub fn publish_diagnostic(
    diagnostic_params: PublishDiagnosticsParams,
    sender: &Sender<Message>,
) -> LSPProcessResult<()> {
    let notif = ServerNotification::new(PublishDiagnostics::METHOD.into(), diagnostic_params);
    sender
        .send(Message::Notification(notif))
        .unwrap_or_else(|_| {
            // TODO(brandondail) log here
        });
    Ok(())
}
<|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/. */

extern crate quote;
#[macro_use] extern crate syn;
#[macro_use] extern crate synstructure;

decl_derive!([JSTraceable] => js_traceable_derive);

fn js_traceable_derive(s: synstructure::Structure) -> quote::Tokens {
    let match_body = s.each(|binding| {
        Some(quote!(#binding.trace(tracer);))
    });

    let ast = s.ast();
    let name = ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
    let mut where_clause = where_clause.unwrap_or(&parse_quote!(where)).clone();
    for param in ast.generics.type_params() {
        let ident = param.ident;
        where_clause.predicates.push(parse_quote!(#ident: ::dom::bindings::trace::JSTraceable))
    }

    let tokens = quote! {
        #[allow(unsafe_code)]
        unsafe impl #impl_generics ::dom::bindings::trace::JSTraceable for #name #ty_generics #where_clause {
            #[inline]
            #[allow(unused_variables, unused_imports)]
            unsafe fn trace(&self, tracer: *mut ::js::jsapi::JSTracer) {
                use ::dom::bindings::trace::JSTraceable;
                match *self {
                    #match_body
                }
            }
        }
    };

    tokens
}
<commit_msg>Auto merge of #21655 - kingdido999:master, r=jdm<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/. */

extern crate quote;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate synstructure;

decl_derive!([JSTraceable] => js_traceable_derive);

fn js_traceable_derive(s: synstructure::Structure) -> quote::Tokens {
    let match_body = s.each(|binding| Some(quote!(#binding.trace(tracer);)));

    let ast = s.ast();
    let name = ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
    let mut where_clause = where_clause.unwrap_or(&parse_quote!(where)).clone();
    for param in ast.generics.type_params() {
        let ident = param.ident;
        where_clause
            .predicates
            .push(parse_quote!(#ident: ::dom::bindings::trace::JSTraceable))
    }

    let tokens = quote! {
        #[allow(unsafe_code)]
        unsafe impl #impl_generics ::dom::bindings::trace::JSTraceable for #name #ty_generics #where_clause {
            #[inline]
            #[allow(unused_variables, unused_imports)]
            unsafe fn trace(&self, tracer: *mut ::js::jsapi::JSTracer) {
                use ::dom::bindings::trace::JSTraceable;
                match *self {
                    #match_body
                }
            }
        }
    };

    tokens
}
<|endoftext|>


<commit_before>pub mod ffi;

use std::mem;
use std::ptr;

use super::utils::fn_ptr::FnPtrLoader;

#[inline]
pub fn load<T: FnPtrLoader>(loader: &T) {
   unsafe {
      ffi::load_functions(loader)
   };
}

#[inline]
pub fn clear_color(red: f32, green: f32, blue: f32, alpha: f32) {
   unsafe {
      ffi::glClearColor(red, green, blue, alpha);
   }
}

#[inline]
pub fn clear() {
   unsafe {
      ffi::glClear(ffi::GL_COLOR_BUFFER_BIT);
   }
}

#[inline]
pub fn flush() {
   unsafe {
      ffi::glFlush();
   }
}

#[inline]
pub fn finish() {
   unsafe {
      ffi::glFinish();
   }
}

#[inline]
pub fn reset_pixelstore_alignment() {
   unsafe {
      ffi::glPixelStorei(ffi::GL_UNPACK_ALIGNMENT, 1);
   }
}

#[inline]
pub fn enable_framebuffer_srgb() {
   unsafe {
      ffi::glEnable(ffi::GL_FRAMEBUFFER_SRGB);
   }
}

#[inline]
pub fn disable_all() {
   unsafe {
      ffi::glDisable(ffi::GL_SCISSOR_TEST);
      ffi::glDisable(ffi::GL_BLEND);
      ffi::glDisable(ffi::GL_CULL_FACE);
      ffi::glDisable(ffi::GL_DEPTH_TEST);
      ffi::glDisable(ffi::GL_DITHER);
      ffi::glDisable(ffi::GL_POLYGON_OFFSET_FILL);
      ffi::glDisable(ffi::GL_SAMPLE_ALPHA_TO_COVERAGE);
      ffi::glDisable(ffi::GL_SAMPLE_COVERAGE);
      ffi::glDisable(ffi::GL_STENCIL_TEST);
   };
}

pub struct Texture {
   pub name: ffi::GLuint,
}

impl Texture {
   pub fn new(width: u32, height: u32) -> Self {
      let mut name: ffi::GLuint = unsafe { mem::uninitialized() };

      unsafe {
         ffi::glGenTextures(1, &mut name);

         ffi::glBindTexture(ffi::GL_TEXTURE_2D, name);

         ffi::glTexParameteri(
            ffi::GL_TEXTURE_2D,
            ffi::GL_TEXTURE_WRAP_S,
            ffi::GL_CLAMP_TO_EDGE as ffi::GLint
         );

         ffi::glTexParameteri(
            ffi::GL_TEXTURE_2D,
            ffi::GL_TEXTURE_WRAP_T,
            ffi::GL_CLAMP_TO_EDGE as ffi::GLint
         );

         ffi::glTexParameteri(
            ffi::GL_TEXTURE_2D,
            ffi::GL_TEXTURE_MIN_FILTER,
            ffi::GL_NEAREST as ffi::GLint
         );

         ffi::glTexParameteri(
            ffi::GL_TEXTURE_2D,
            ffi::GL_TEXTURE_MAG_FILTER,
            ffi::GL_NEAREST as ffi::GLint
         );

         ffi::glTexImage2D(
            ffi::GL_TEXTURE_2D,
            0,
            ffi::GL_RGBA8 as ffi::GLint,
            width as ffi::GLsizei,
            height as ffi::GLsizei,
            0,
            ffi::GL_RGBA,
            ffi::GL_UNSIGNED_BYTE,
            ptr::null()
         );
      }

      Texture {
         name: name,
      }
   }

   #[inline]
   pub fn bind(&self) {
      unsafe {
         ffi::glBindTexture(ffi::GL_TEXTURE_2D, self.name);
      }
   }

   #[inline]
   pub fn resize(&self, width: u32, height: u32) {
      unsafe {
         ffi::glTexImage2D(
            ffi::GL_TEXTURE_2D,
            0,
            ffi::GL_RGBA8 as ffi::GLint,
            width as ffi::GLsizei,
            height as ffi::GLsizei,
            0,
            ffi::GL_RGBA,
            ffi::GL_UNSIGNED_BYTE,
            ptr::null()
         );
      }
   }

   #[inline]
   pub fn update(&self, width: u32, height: u32) {
      unsafe {
         ffi::glTexSubImage2D(
            ffi::GL_TEXTURE_2D,
            0,
            0, 0, width as ffi::GLsizei, height as ffi::GLsizei,
            ffi::GL_RGBA,
            ffi::GL_UNSIGNED_BYTE,
            ptr::null()
         );
      }
   }
}

impl Drop for Texture {
   fn drop (&mut self) {
      unsafe {
         ffi::glDeleteTextures(1, &self.name)
      };
   }
}

pub struct Framebuffer {
   pub name: ffi::GLuint,
}

impl Framebuffer {
   pub fn new(texture: &Texture) -> Self {
      let mut name: ffi::GLuint = unsafe { mem::uninitialized() };

      unsafe {
         ffi::glGenFramebuffers(1, &mut name)
      };

      let framebuffer = Framebuffer {
         name: name,
      };

      framebuffer.bind();
      framebuffer.attach_texture(texture);
      framebuffer.unbind();

      framebuffer
   }

   #[inline]
   pub fn bind(&self) {
      unsafe {
         ffi::glBindFramebuffer(ffi::GL_READ_FRAMEBUFFER, self.name)
      };
   }

   #[inline]
   pub fn unbind(&self) {
      unsafe {
         ffi::glBindFramebuffer(ffi::GL_READ_FRAMEBUFFER, 0)
      };
   }

   #[inline]
   pub fn attach_texture(&self, texture: &Texture) {
      unsafe {
         ffi::glFramebufferTexture2D(
            ffi::GL_READ_FRAMEBUFFER,
            ffi::GL_COLOR_ATTACHMENT0,
            ffi::GL_TEXTURE_2D,
            texture.name,
            0
         )
      };
   }

   #[inline]
   pub fn blit(&self, width: u32, height: u32) {
      unsafe {
         ffi::glBlitFramebuffer(
            0, 0, width as ffi::GLint, height as ffi::GLint,
            0, 0, width as ffi::GLint, height as ffi::GLint,
            ffi::GL_COLOR_BUFFER_BIT,
            ffi::GL_NEAREST
         )
      };
   }
}

impl Drop for Framebuffer {
   fn drop (&mut self) {
      unsafe {
         ffi::glDeleteFramebuffers(1, &self.name)
      };
   }
}

pub struct Buffer {
   pub name: ffi::GLuint,
   pub ptr: *mut ffi::c_void,
   pub size: ffi::GLsizeiptr,
}

impl Buffer {
   pub fn new() -> Self {
      let mut name: ffi::GLuint = unsafe { mem::uninitialized() };

      unsafe {
         ffi::glGenBuffers(1, &mut name)
      };

      Buffer {
         name: name,
         ptr: ptr::null_mut(),
         size: 0,
      }
   }

   #[inline]
   pub fn bind(&self) {
      unsafe {
         ffi::glBindBuffer(ffi::GL_PIXEL_UNPACK_BUFFER, self.name)
      };
   }

   #[inline]
   pub fn unbind(&self) {
      unsafe {
         ffi::glBindBuffer(ffi::GL_PIXEL_UNPACK_BUFFER, 0)
      };
   }

   #[inline]
   pub fn init_data(&mut self, size: usize) {
      self.size = size as ffi::GLsizeiptr;
      unsafe {
         ffi::glBufferData(
            ffi::GL_PIXEL_UNPACK_BUFFER,
            self.size,
            ptr::null(),
            ffi::GL_STREAM_DRAW
         )
      };
   }

   #[inline]
   pub fn map(&mut self) {
      self.ptr = unsafe {
         ffi::glMapBuffer(ffi::GL_PIXEL_UNPACK_BUFFER, ffi::GL_WRITE_ONLY)
      };
   }

   #[inline]
   pub fn map_range(&mut self) {
      self.ptr = unsafe {
         ffi::glMapBufferRange(
            ffi::GL_PIXEL_UNPACK_BUFFER, 0, self.size,
            ffi::GL_MAP_WRITE_BIT// | ffi::GL_MAP_UNSYNCHRONIZED_BIT
         )
      };
   }

   #[inline]
   pub fn unmap(&self) {
      unsafe {
         ffi::glUnmapBuffer(ffi::GL_PIXEL_UNPACK_BUFFER)
      };
   }
}

impl Drop for Buffer {
   fn drop (&mut self) {
      unsafe {
         ffi::glDeleteBuffers(1, &self.name)
      };
   }
}

pub struct Shader {
   pub name: ffi::GLuint,
}

impl Shader {
   pub fn new(shader_type: ffi::GLenum) -> Self {
      let name = unsafe {
         ffi::glCreateShader(shader_type)
      };

      Shader {
         name: name,
      }
   }
}

impl Drop for Shader {
   fn drop (&mut self) {
      unsafe {
         ffi::glDeleteShader(self.name)
      };
   }
}
<commit_msg>Wrappers for GL shaders compilation<commit_after>pub mod ffi;

use std::mem;
use std::ptr;
use std::ffi::CString;

use super::utils::fn_ptr::FnPtrLoader;

#[inline]
pub fn load<T: FnPtrLoader>(loader: &T) {
   unsafe {
      ffi::load_functions(loader)
   };
}

#[inline]
pub fn clear_color(red: f32, green: f32, blue: f32, alpha: f32) {
   unsafe {
      ffi::glClearColor(red, green, blue, alpha);
   }
}

#[inline]
pub fn clear() {
   unsafe {
      ffi::glClear(ffi::GL_COLOR_BUFFER_BIT);
   }
}

#[inline]
pub fn flush() {
   unsafe {
      ffi::glFlush();
   }
}

#[inline]
pub fn finish() {
   unsafe {
      ffi::glFinish();
   }
}

#[inline]
pub fn reset_pixelstore_alignment() {
   unsafe {
      ffi::glPixelStorei(ffi::GL_UNPACK_ALIGNMENT, 1);
   }
}

#[inline]
pub fn enable_framebuffer_srgb() {
   unsafe {
      ffi::glEnable(ffi::GL_FRAMEBUFFER_SRGB);
   }
}

#[inline]
pub fn disable_all() {
   unsafe {
      ffi::glDisable(ffi::GL_SCISSOR_TEST);
      ffi::glDisable(ffi::GL_BLEND);
      ffi::glDisable(ffi::GL_CULL_FACE);
      ffi::glDisable(ffi::GL_DEPTH_TEST);
      ffi::glDisable(ffi::GL_DITHER);
      ffi::glDisable(ffi::GL_POLYGON_OFFSET_FILL);
      ffi::glDisable(ffi::GL_SAMPLE_ALPHA_TO_COVERAGE);
      ffi::glDisable(ffi::GL_SAMPLE_COVERAGE);
      ffi::glDisable(ffi::GL_STENCIL_TEST);
   };
}

pub struct Texture {
   pub name: ffi::GLuint,
}

impl Texture {
   pub fn new(width: u32, height: u32) -> Self {
      let mut name: ffi::GLuint = unsafe { mem::uninitialized() };

      unsafe {
         ffi::glGenTextures(1, &mut name);

         ffi::glBindTexture(ffi::GL_TEXTURE_2D, name);

         ffi::glTexParameteri(
            ffi::GL_TEXTURE_2D,
            ffi::GL_TEXTURE_WRAP_S,
            ffi::GL_CLAMP_TO_EDGE as ffi::GLint
         );

         ffi::glTexParameteri(
            ffi::GL_TEXTURE_2D,
            ffi::GL_TEXTURE_WRAP_T,
            ffi::GL_CLAMP_TO_EDGE as ffi::GLint
         );

         ffi::glTexParameteri(
            ffi::GL_TEXTURE_2D,
            ffi::GL_TEXTURE_MIN_FILTER,
            ffi::GL_NEAREST as ffi::GLint
         );

         ffi::glTexParameteri(
            ffi::GL_TEXTURE_2D,
            ffi::GL_TEXTURE_MAG_FILTER,
            ffi::GL_NEAREST as ffi::GLint
         );

         ffi::glTexImage2D(
            ffi::GL_TEXTURE_2D,
            0,
            ffi::GL_RGBA8 as ffi::GLint,
            width as ffi::GLsizei,
            height as ffi::GLsizei,
            0,
            ffi::GL_RGBA,
            ffi::GL_UNSIGNED_BYTE,
            ptr::null()
         );
      }

      Texture {
         name: name,
      }
   }

   #[inline]
   pub fn bind(&self) {
      unsafe {
         ffi::glBindTexture(ffi::GL_TEXTURE_2D, self.name);
      }
   }

   #[inline]
   pub fn resize(&self, width: u32, height: u32) {
      unsafe {
         ffi::glTexImage2D(
            ffi::GL_TEXTURE_2D,
            0,
            ffi::GL_RGBA8 as ffi::GLint,
            width as ffi::GLsizei,
            height as ffi::GLsizei,
            0,
            ffi::GL_RGBA,
            ffi::GL_UNSIGNED_BYTE,
            ptr::null()
         );
      }
   }

   #[inline]
   pub fn update(&self, width: u32, height: u32) {
      unsafe {
         ffi::glTexSubImage2D(
            ffi::GL_TEXTURE_2D,
            0,
            0, 0, width as ffi::GLsizei, height as ffi::GLsizei,
            ffi::GL_RGBA,
            ffi::GL_UNSIGNED_BYTE,
            ptr::null()
         );
      }
   }
}

impl Drop for Texture {
   fn drop (&mut self) {
      unsafe {
         ffi::glDeleteTextures(1, &self.name)
      };
   }
}

pub struct Framebuffer {
   pub name: ffi::GLuint,
}

impl Framebuffer {
   pub fn new(texture: &Texture) -> Self {
      let mut name: ffi::GLuint = unsafe { mem::uninitialized() };

      unsafe {
         ffi::glGenFramebuffers(1, &mut name)
      };

      let framebuffer = Framebuffer {
         name: name,
      };

      framebuffer.bind();
      framebuffer.attach_texture(texture);
      framebuffer.unbind();

      framebuffer
   }

   #[inline]
   pub fn bind(&self) {
      unsafe {
         ffi::glBindFramebuffer(ffi::GL_READ_FRAMEBUFFER, self.name)
      };
   }

   #[inline]
   pub fn unbind(&self) {
      unsafe {
         ffi::glBindFramebuffer(ffi::GL_READ_FRAMEBUFFER, 0)
      };
   }

   #[inline]
   pub fn attach_texture(&self, texture: &Texture) {
      unsafe {
         ffi::glFramebufferTexture2D(
            ffi::GL_READ_FRAMEBUFFER,
            ffi::GL_COLOR_ATTACHMENT0,
            ffi::GL_TEXTURE_2D,
            texture.name,
            0
         )
      };
   }

   #[inline]
   pub fn blit(&self, width: u32, height: u32) {
      unsafe {
         ffi::glBlitFramebuffer(
            0, 0, width as ffi::GLint, height as ffi::GLint,
            0, 0, width as ffi::GLint, height as ffi::GLint,
            ffi::GL_COLOR_BUFFER_BIT,
            ffi::GL_NEAREST
         )
      };
   }
}

impl Drop for Framebuffer {
   fn drop (&mut self) {
      unsafe {
         ffi::glDeleteFramebuffers(1, &self.name)
      };
   }
}

pub struct Buffer {
   pub name: ffi::GLuint,
   pub ptr: *mut ffi::c_void,
   pub size: ffi::GLsizeiptr,
}

impl Buffer {
   pub fn new() -> Self {
      let mut name: ffi::GLuint = unsafe { mem::uninitialized() };

      unsafe {
         ffi::glGenBuffers(1, &mut name)
      };

      Buffer {
         name: name,
         ptr: ptr::null_mut(),
         size: 0,
      }
   }

   #[inline]
   pub fn bind(&self) {
      unsafe {
         ffi::glBindBuffer(ffi::GL_PIXEL_UNPACK_BUFFER, self.name)
      };
   }

   #[inline]
   pub fn unbind(&self) {
      unsafe {
         ffi::glBindBuffer(ffi::GL_PIXEL_UNPACK_BUFFER, 0)
      };
   }

   #[inline]
   pub fn init_data(&mut self, size: usize) {
      self.size = size as ffi::GLsizeiptr;
      unsafe {
         ffi::glBufferData(
            ffi::GL_PIXEL_UNPACK_BUFFER,
            self.size,
            ptr::null(),
            ffi::GL_STREAM_DRAW
         )
      };
   }

   #[inline]
   pub fn map(&mut self) {
      self.ptr = unsafe {
         ffi::glMapBuffer(ffi::GL_PIXEL_UNPACK_BUFFER, ffi::GL_WRITE_ONLY)
      };
   }

   #[inline]
   pub fn map_range(&mut self) {
      self.ptr = unsafe {
         ffi::glMapBufferRange(
            ffi::GL_PIXEL_UNPACK_BUFFER, 0, self.size,
            ffi::GL_MAP_WRITE_BIT// | ffi::GL_MAP_UNSYNCHRONIZED_BIT
         )
      };
   }

   #[inline]
   pub fn unmap(&self) {
      unsafe {
         ffi::glUnmapBuffer(ffi::GL_PIXEL_UNPACK_BUFFER)
      };
   }
}

impl Drop for Buffer {
   fn drop (&mut self) {
      unsafe {
         ffi::glDeleteBuffers(1, &self.name)
      };
   }
}

pub struct Shader {
   pub name: ffi::GLuint,
}

impl Shader {
   pub fn new(shader_type: ffi::GLenum) -> Self {
      let name = unsafe {
         ffi::glCreateShader(shader_type)
      };

      Shader {
         name: name,
      }
   }

   #[inline]
   pub fn shader_source(&self, string: &str) {
      let cstring = CString::new(string).unwrap().as_ptr();

      unsafe {
         ffi::glShaderSource(self.name, 1, &cstring, ptr::null())
      };
   }

   #[inline]
   pub fn compile(&self) {
      unsafe {
         ffi::glCompileShader(self.name)
      };
   }

   #[inline]
   pub fn is_compiled(&self) -> bool {
      let mut compiled: ffi::GLint = unsafe { mem::uninitialized() };

      unsafe {
         ffi::glGetShaderiv(self.name, ffi::GL_COMPILE_STATUS, &mut compiled);
      };

      compiled == 1
   }
}

impl Drop for Shader {
   fn drop (&mut self) {
      unsafe {
         ffi::glDeleteShader(self.name)
      };
   }
}
<|endoftext|>


<commit_before>extern crate serialize;

use std::num::strconv;
use std::collections::TreeMap;
use self::serialize::json;

use {Parser, Value};
use Value::{Table, Integer, Float, Boolean, Datetime, Array};

fn to_json(toml: Value) -> json::Json {
    fn doit(s: &str, json: json::Json) -> json::Json {
        let mut map = TreeMap::new();
        map.insert("type".to_string(), json::String(s.to_string()));
        map.insert("value".to_string(), json);
        json::Object(map)
    }
    match toml {
        Value::String(s) => doit("string", json::String(s)),
        Integer(i) => doit("integer", json::String(i.to_string())),
        Float(f) => doit("float", json::String({
            let (bytes, _) =
                strconv::float_to_str_bytes_common(f, 10, true,
                                                   strconv::SignNeg,
                                                   strconv::DigMax(15),
                                                   strconv::ExpNone,
                                                   false);
            let s = String::from_utf8(bytes).unwrap();
            if s.as_slice().contains(".") {s} else {format!("{}.0", s)}
        })),
        Boolean(b) => doit("bool", json::String(b.to_string())),
        Datetime(s) => doit("datetime", json::String(s)),
        Array(arr) => {
            let is_table = match arr.as_slice().head() {
                Some(&Table(..)) => true,
                _ => false,
            };
            let json = json::Array(arr.into_iter().map(to_json).collect());
            if is_table {json} else {doit("array", json)}
        }
        Table(table) => json::Object(table.into_iter().map(|(k, v)| {
            (k, to_json(v))
        }).collect()),
    }
}

fn run(toml: &str, json: &str) {
    let mut p = Parser::new(toml);
    let table = p.parse();
    assert!(p.errors.len() == 0, "had_errors: {}",
            p.errors.iter().map(|e| {
                (e.desc.clone(), toml.slice(e.lo - 5, e.hi + 5))
            }).collect::<Vec<(String, &str)>>());
    assert!(table.is_some());
    let table = table.unwrap();

    let json = json::from_str(json).unwrap();
    let toml_json = to_json(Table(table));
    assert!(json == toml_json,
            "expected\n{}\ngot\n{}\n",
            json.to_pretty_str(),
            toml_json.to_pretty_str());
}

macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (
    #[test]
    fn $name() { run($toml, $json); }
) )

test!(array_empty,
       include_str!("valid/array-empty.toml"),
       include_str!("valid/array-empty.json"))
test!(array_nospaces,
       include_str!("valid/array-nospaces.toml"),
       include_str!("valid/array-nospaces.json"))
test!(arrays_hetergeneous,
       include_str!("valid/arrays-hetergeneous.toml"),
       include_str!("valid/arrays-hetergeneous.json"))
test!(arrays,
       include_str!("valid/arrays.toml"),
       include_str!("valid/arrays.json"))
test!(arrays_nested,
       include_str!("valid/arrays-nested.toml"),
       include_str!("valid/arrays-nested.json"))
test!(empty,
       include_str!("valid/empty.toml"),
       include_str!("valid/empty.json"))
test!(bool,
       include_str!("valid/bool.toml"),
       include_str!("valid/bool.json"))
test!(datetime,
       include_str!("valid/datetime.toml"),
       include_str!("valid/datetime.json"))
test!(example,
       include_str!("valid/example.toml"),
       include_str!("valid/example.json"))
test!(float,
       include_str!("valid/float.toml"),
       include_str!("valid/float.json"))
test!(implicit_and_explicit_after,
       include_str!("valid/implicit-and-explicit-after.toml"),
       include_str!("valid/implicit-and-explicit-after.json"))
test!(implicit_and_explicit_before,
       include_str!("valid/implicit-and-explicit-before.toml"),
       include_str!("valid/implicit-and-explicit-before.json"))
test!(implicit_groups,
       include_str!("valid/implicit-groups.toml"),
       include_str!("valid/implicit-groups.json"))
test!(integer,
       include_str!("valid/integer.toml"),
       include_str!("valid/integer.json"))
test!(key_equals_nospace,
       include_str!("valid/key-equals-nospace.toml"),
       include_str!("valid/key-equals-nospace.json"))
test!(key_special_chars,
       include_str!("valid/key-special-chars.toml"),
       include_str!("valid/key-special-chars.json"))
test!(key_with_pound,
       include_str!("valid/key-with-pound.toml"),
       include_str!("valid/key-with-pound.json"))
test!(long_float,
       include_str!("valid/long-float.toml"),
       include_str!("valid/long-float.json"))
test!(long_integer,
       include_str!("valid/long-integer.toml"),
       include_str!("valid/long-integer.json"))
test!(string_empty,
       include_str!("valid/string-empty.toml"),
       include_str!("valid/string-empty.json"))
test!(string_escapes,
       include_str!("valid/string-escapes.toml"),
       include_str!("valid/string-escapes.json"))
test!(string_simple,
       include_str!("valid/string-simple.toml"),
       include_str!("valid/string-simple.json"))
test!(string_with_pound,
       include_str!("valid/string-with-pound.toml"),
       include_str!("valid/string-with-pound.json"))
test!(table_array_implicit,
       include_str!("valid/table-array-implicit.toml"),
       include_str!("valid/table-array-implicit.json"))
test!(table_array_many,
       include_str!("valid/table-array-many.toml"),
       include_str!("valid/table-array-many.json"))
test!(table_array_nest,
       include_str!("valid/table-array-nest.toml"),
       include_str!("valid/table-array-nest.json"))
test!(table_array_one,
       include_str!("valid/table-array-one.toml"),
       include_str!("valid/table-array-one.json"))
test!(table_empty,
       include_str!("valid/table-empty.toml"),
       include_str!("valid/table-empty.json"))
test!(table_sub_empty,
       include_str!("valid/table-sub-empty.toml"),
       include_str!("valid/table-sub-empty.json"))
test!(table_whitespace,
       include_str!("valid/table-whitespace.toml"),
       include_str!("valid/table-whitespace.json"))
test!(table_with_pound,
       include_str!("valid/table-with-pound.toml"),
       include_str!("valid/table-with-pound.json"))
test!(unicode_escape,
       include_str!("valid/unicode-escape.toml"),
       include_str!("valid/unicode-escape.json"))
test!(unicode_literal,
       include_str!("valid/unicode-literal.toml"),
       include_str!("valid/unicode-literal.json"))
<commit_msg>Update to rust master<commit_after>extern crate serialize;

use std::num::strconv;
use std::collections::TreeMap;
use self::serialize::json::{mod, Json};

use {Parser, Value};
use Value::{Table, Integer, Float, Boolean, Datetime, Array};

fn to_json(toml: Value) -> Json {
    fn doit(s: &str, json: Json) -> Json {
        let mut map = TreeMap::new();
        map.insert("type".to_string(), Json::String(s.to_string()));
        map.insert("value".to_string(), json);
        Json::Object(map)
    }
    match toml {
        Value::String(s) => doit("string", Json::String(s)),
        Integer(i) => doit("integer", Json::String(i.to_string())),
        Float(f) => doit("float", Json::String({
            let (bytes, _) =
                strconv::float_to_str_bytes_common(f, 10, true,
                                                   strconv::SignNeg,
                                                   strconv::DigMax(15),
                                                   strconv::ExpNone,
                                                   false);
            let s = String::from_utf8(bytes).unwrap();
            if s.as_slice().contains(".") {s} else {format!("{}.0", s)}
        })),
        Boolean(b) => doit("bool", Json::String(b.to_string())),
        Datetime(s) => doit("datetime", Json::String(s)),
        Array(arr) => {
            let is_table = match arr.as_slice().head() {
                Some(&Table(..)) => true,
                _ => false,
            };
            let json = Json::Array(arr.into_iter().map(to_json).collect());
            if is_table {json} else {doit("array", json)}
        }
        Table(table) => Json::Object(table.into_iter().map(|(k, v)| {
            (k, to_json(v))
        }).collect()),
    }
}

fn run(toml: &str, json: &str) {
    let mut p = Parser::new(toml);
    let table = p.parse();
    assert!(p.errors.len() == 0, "had_errors: {}",
            p.errors.iter().map(|e| {
                (e.desc.clone(), toml.slice(e.lo - 5, e.hi + 5))
            }).collect::<Vec<(String, &str)>>());
    assert!(table.is_some());
    let table = table.unwrap();

    let json = json::from_str(json).unwrap();
    let toml_json = to_json(Table(table));
    assert!(json == toml_json,
            "expected\n{}\ngot\n{}\n",
            json.to_pretty_str(),
            toml_json.to_pretty_str());
}

macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (
    #[test]
    fn $name() { run($toml, $json); }
) )

test!(array_empty,
       include_str!("valid/array-empty.toml"),
       include_str!("valid/array-empty.json"))
test!(array_nospaces,
       include_str!("valid/array-nospaces.toml"),
       include_str!("valid/array-nospaces.json"))
test!(arrays_hetergeneous,
       include_str!("valid/arrays-hetergeneous.toml"),
       include_str!("valid/arrays-hetergeneous.json"))
test!(arrays,
       include_str!("valid/arrays.toml"),
       include_str!("valid/arrays.json"))
test!(arrays_nested,
       include_str!("valid/arrays-nested.toml"),
       include_str!("valid/arrays-nested.json"))
test!(empty,
       include_str!("valid/empty.toml"),
       include_str!("valid/empty.json"))
test!(bool,
       include_str!("valid/bool.toml"),
       include_str!("valid/bool.json"))
test!(datetime,
       include_str!("valid/datetime.toml"),
       include_str!("valid/datetime.json"))
test!(example,
       include_str!("valid/example.toml"),
       include_str!("valid/example.json"))
test!(float,
       include_str!("valid/float.toml"),
       include_str!("valid/float.json"))
test!(implicit_and_explicit_after,
       include_str!("valid/implicit-and-explicit-after.toml"),
       include_str!("valid/implicit-and-explicit-after.json"))
test!(implicit_and_explicit_before,
       include_str!("valid/implicit-and-explicit-before.toml"),
       include_str!("valid/implicit-and-explicit-before.json"))
test!(implicit_groups,
       include_str!("valid/implicit-groups.toml"),
       include_str!("valid/implicit-groups.json"))
test!(integer,
       include_str!("valid/integer.toml"),
       include_str!("valid/integer.json"))
test!(key_equals_nospace,
       include_str!("valid/key-equals-nospace.toml"),
       include_str!("valid/key-equals-nospace.json"))
test!(key_special_chars,
       include_str!("valid/key-special-chars.toml"),
       include_str!("valid/key-special-chars.json"))
test!(key_with_pound,
       include_str!("valid/key-with-pound.toml"),
       include_str!("valid/key-with-pound.json"))
test!(long_float,
       include_str!("valid/long-float.toml"),
       include_str!("valid/long-float.json"))
test!(long_integer,
       include_str!("valid/long-integer.toml"),
       include_str!("valid/long-integer.json"))
test!(string_empty,
       include_str!("valid/string-empty.toml"),
       include_str!("valid/string-empty.json"))
test!(string_escapes,
       include_str!("valid/string-escapes.toml"),
       include_str!("valid/string-escapes.json"))
test!(string_simple,
       include_str!("valid/string-simple.toml"),
       include_str!("valid/string-simple.json"))
test!(string_with_pound,
       include_str!("valid/string-with-pound.toml"),
       include_str!("valid/string-with-pound.json"))
test!(table_array_implicit,
       include_str!("valid/table-array-implicit.toml"),
       include_str!("valid/table-array-implicit.json"))
test!(table_array_many,
       include_str!("valid/table-array-many.toml"),
       include_str!("valid/table-array-many.json"))
test!(table_array_nest,
       include_str!("valid/table-array-nest.toml"),
       include_str!("valid/table-array-nest.json"))
test!(table_array_one,
       include_str!("valid/table-array-one.toml"),
       include_str!("valid/table-array-one.json"))
test!(table_empty,
       include_str!("valid/table-empty.toml"),
       include_str!("valid/table-empty.json"))
test!(table_sub_empty,
       include_str!("valid/table-sub-empty.toml"),
       include_str!("valid/table-sub-empty.json"))
test!(table_whitespace,
       include_str!("valid/table-whitespace.toml"),
       include_str!("valid/table-whitespace.json"))
test!(table_with_pound,
       include_str!("valid/table-with-pound.toml"),
       include_str!("valid/table-with-pound.json"))
test!(unicode_escape,
       include_str!("valid/unicode-escape.toml"),
       include_str!("valid/unicode-escape.json"))
test!(unicode_literal,
       include_str!("valid/unicode-literal.toml"),
       include_str!("valid/unicode-literal.json"))
<|endoftext|>


<commit_before>extern crate translator;

#[test]
fn empty() {
	let translator = translator::Translator::new();

	assert_eq!("", translator.translate(""));
	assert_eq!(" ", translator.translate(" "));
	assert_eq!("  ", translator.translate("  "));
	assert_eq!("   ", translator.translate("   "));
}

#[test]
fn letters() {
	let translator = translator::Translator::new();

	assert_eq!("а", translator.translate("a"));
	assert_eq!("б", translator.translate("b"));
	assert_eq!("в", translator.translate("v"));
	assert_eq!("г", translator.translate("g"));
	assert_eq!("д", translator.translate("d"));
	assert_eq!("е", translator.translate("e"));
	assert_eq!("ё", translator.translate("jo"));
	assert_eq!("ж", translator.translate("zh"));
	assert_eq!("з", translator.translate("z"));
	assert_eq!("и", translator.translate("i"));
	assert_eq!("й", translator.translate("j"));
	assert_eq!("к", translator.translate("k"));
	assert_eq!("л", translator.translate("l"));
	assert_eq!("м", translator.translate("m"));
	assert_eq!("н", translator.translate("n"));
	assert_eq!("о", translator.translate("o"));
	assert_eq!("п", translator.translate("p"));
	assert_eq!("р", translator.translate("r"));
	assert_eq!("с", translator.translate("s"));
	assert_eq!("т", translator.translate("t"));
	assert_eq!("у", translator.translate("u"));
	assert_eq!("ф", translator.translate("f"));
	assert_eq!("х", translator.translate("h"));
	assert_eq!("ц", translator.translate("c"));
	assert_eq!("ч", translator.translate("ch"));
	assert_eq!("ш", translator.translate("sh"));
	assert_eq!("щ", translator.translate("shh"));
	assert_eq!("ъ", translator.translate("#"));
	assert_eq!("ы", translator.translate("y"));
	assert_eq!("ь", translator.translate("'"));
	assert_eq!("э", translator.translate("je"));
	assert_eq!("ю", translator.translate("ju"));
	assert_eq!("я", translator.translate("ja"));
}

#[test]
fn capital_letters()
{
	let translator = translator::Translator::new();

	assert_eq!("А", translator.translate("A"));
	assert_eq!("Б", translator.translate("B"));
	assert_eq!("В", translator.translate("V"));
	assert_eq!("Г", translator.translate("G"));
	assert_eq!("Д", translator.translate("D"));
	assert_eq!("Е", translator.translate("E"));
	assert_eq!("Ё", translator.translate("JO"));
	assert_eq!("Ж", translator.translate("ZH"));
	assert_eq!("З", translator.translate("Z"));
	assert_eq!("И", translator.translate("I"));
	assert_eq!("Й", translator.translate("J"));
	assert_eq!("К", translator.translate("K"));
	assert_eq!("Л", translator.translate("L"));
	assert_eq!("М", translator.translate("M"));
	assert_eq!("Н", translator.translate("N"));
	assert_eq!("О", translator.translate("O"));
	assert_eq!("П", translator.translate("P"));
	assert_eq!("Р", translator.translate("R"));
	assert_eq!("С", translator.translate("S"));
	assert_eq!("Т", translator.translate("T"));
	assert_eq!("У", translator.translate("U"));
	assert_eq!("Ф", translator.translate("F"));
	assert_eq!("Х", translator.translate("X"));
	assert_eq!("Х", translator.translate("H"));
	assert_eq!("Ц", translator.translate("C"));
	assert_eq!("Ч", translator.translate("CH"));
	assert_eq!("Ш", translator.translate("SH"));
	assert_eq!("Щ", translator.translate("SHH"));
	assert_eq!("Ъ", translator.translate("##"));
	assert_eq!("Ы", translator.translate("Y"));
	assert_eq!("Ь", translator.translate("''"));
	assert_eq!("Э", translator.translate("JE"));
	assert_eq!("Ю", translator.translate("JU"));
	assert_eq!("Я", translator.translate("JA"));
}

#[test]
fn words() {
	let translator = translator::Translator::new();

	assert_eq!("Привет", translator.translate("Privet"));
}

#[test]
fn sentences() {
	let translator = translator::Translator::new();

	assert_eq!("Привет нуб", translator.translate("Privet nub"));
}
<commit_msg>TODO note<commit_after>extern crate translator;

#[test]
fn empty() {
	let translator = translator::Translator::new();

	assert_eq!("", translator.translate(""));
	assert_eq!(" ", translator.translate(" "));
	assert_eq!("  ", translator.translate("  "));
	assert_eq!("   ", translator.translate("   "));
}

#[test]
fn letters() {
	let translator = translator::Translator::new();

	assert_eq!("а", translator.translate("a"));
	assert_eq!("б", translator.translate("b"));
	assert_eq!("в", translator.translate("v"));
	assert_eq!("г", translator.translate("g"));
	assert_eq!("д", translator.translate("d"));
	assert_eq!("е", translator.translate("e"));
	assert_eq!("ё", translator.translate("jo"));
	assert_eq!("ж", translator.translate("zh"));
	assert_eq!("з", translator.translate("z"));
	assert_eq!("и", translator.translate("i"));
	assert_eq!("й", translator.translate("j"));
	assert_eq!("к", translator.translate("k"));
	assert_eq!("л", translator.translate("l"));
	assert_eq!("м", translator.translate("m"));
	assert_eq!("н", translator.translate("n"));
	assert_eq!("о", translator.translate("o"));
	assert_eq!("п", translator.translate("p"));
	assert_eq!("р", translator.translate("r"));
	assert_eq!("с", translator.translate("s"));
	assert_eq!("т", translator.translate("t"));
	assert_eq!("у", translator.translate("u"));
	assert_eq!("ф", translator.translate("f"));
	assert_eq!("х", translator.translate("h"));
	assert_eq!("ц", translator.translate("c"));
	assert_eq!("ч", translator.translate("ch"));
	assert_eq!("ш", translator.translate("sh"));
	assert_eq!("щ", translator.translate("shh"));
	assert_eq!("ъ", translator.translate("#"));
	assert_eq!("ы", translator.translate("y"));
	assert_eq!("ь", translator.translate("'"));
	assert_eq!("э", translator.translate("je"));
	assert_eq!("ю", translator.translate("ju"));
	assert_eq!("я", translator.translate("ja"));
}

#[test]
fn capital_letters()
{
	let translator = translator::Translator::new();

    // TODO: Use to_uppercase in order to remove duplication.
	assert_eq!("А", translator.translate("A"));
	assert_eq!("Б", translator.translate("B"));
	assert_eq!("В", translator.translate("V"));
	assert_eq!("Г", translator.translate("G"));
	assert_eq!("Д", translator.translate("D"));
	assert_eq!("Е", translator.translate("E"));
	assert_eq!("Ё", translator.translate("JO"));
	assert_eq!("Ж", translator.translate("ZH"));
	assert_eq!("З", translator.translate("Z"));
	assert_eq!("И", translator.translate("I"));
	assert_eq!("Й", translator.translate("J"));
	assert_eq!("К", translator.translate("K"));
	assert_eq!("Л", translator.translate("L"));
	assert_eq!("М", translator.translate("M"));
	assert_eq!("Н", translator.translate("N"));
	assert_eq!("О", translator.translate("O"));
	assert_eq!("П", translator.translate("P"));
	assert_eq!("Р", translator.translate("R"));
	assert_eq!("С", translator.translate("S"));
	assert_eq!("Т", translator.translate("T"));
	assert_eq!("У", translator.translate("U"));
	assert_eq!("Ф", translator.translate("F"));
	assert_eq!("Х", translator.translate("X"));
	assert_eq!("Х", translator.translate("H"));
	assert_eq!("Ц", translator.translate("C"));
	assert_eq!("Ч", translator.translate("CH"));
	assert_eq!("Ш", translator.translate("SH"));
	assert_eq!("Щ", translator.translate("SHH"));
	assert_eq!("Ъ", translator.translate("##"));
	assert_eq!("Ы", translator.translate("Y"));
	assert_eq!("Ь", translator.translate("''"));
	assert_eq!("Э", translator.translate("JE"));
	assert_eq!("Ю", translator.translate("JU"));
	assert_eq!("Я", translator.translate("JA"));
}

#[test]
fn words() {
	let translator = translator::Translator::new();

	assert_eq!("Привет", translator.translate("Privet"));
}

#[test]
fn sentences() {
	let translator = translator::Translator::new();

	assert_eq!("Привет нуб", translator.translate("Privet nub"));
}
<|endoftext|>


<commit_before><commit_msg>test hash validation in client/server tests<commit_after><|endoftext|>


<commit_before>
// FIXME: There is so many PathBuf's in this module
//        Conver them to Path

use std::io::prelude::*;
use std::io;
use std::path::{Path, PathBuf};
use std::fs;
use error::Result;

use regex::Regex;

/// Copies files from source directory to destination directory.
pub fn copy_dir<P: AsRef<Path>>(source: P, destination: P) -> Result<()> {
    copy_files_and_handle_html(source.as_ref().to_path_buf(),
                               destination.as_ref().to_path_buf(),
                               false,
                               "",
                               false)
}

/// Copies documentation from a crate's target directory to destination.
///
/// Target directory must have doc directory.
///
/// This function is designed to avoid file duplications. It is using rustc version string
/// to rename common files (css files, jquery.js, playpen.js, main.js etc.) in a standard rustdoc.
pub fn copy_doc_dir<P: AsRef<Path>>(target: P,
                                    destination: P,
                                    rustc_version: &str,
                                    target_platform: bool)
                                    -> Result<()> {
    let source = PathBuf::from(target.as_ref()).join("doc");
    copy_files_and_handle_html(source,
                               destination.as_ref().to_path_buf(),
                               true,
                               rustc_version,
                               target_platform)
}

fn copy_files_and_handle_html(source: PathBuf,
                              destination: PathBuf,
                              handle_html: bool,
                              rustc_version: &str,
                              target: bool)
                              -> Result<()> {

    // Make sure destination directory is exists
    if !destination.exists() {
        try!(fs::create_dir_all(&destination));
    }

    // Avoid copying duplicated files
    let dup_regex = Regex::new(r"(\.lock|\.txt|\.woff|jquery\.js|playpen\.js|main\.js|\.css)$")
        .unwrap();

    for file in try!(source.read_dir()) {

        let file = try!(file);
        let mut destination_full_path = PathBuf::from(&destination);
        destination_full_path.push(file.file_name());

        let metadata = try!(file.metadata());

        if metadata.is_dir() {
            try!(fs::create_dir_all(&destination_full_path));
            try!(copy_files_and_handle_html(file.path(),
                                            destination_full_path,
                                            handle_html,
                                            &rustc_version,
                                            target));
        } else if handle_html && file.file_name().into_string().unwrap().ends_with(".html") {
            try!(copy_html(&file.path(), &destination_full_path, rustc_version, target));
        } else if handle_html && dup_regex.is_match(&file.file_name().into_string().unwrap()[..]) {
            continue;
        } else {
            try!(fs::copy(&file.path(), &destination_full_path));
        }

    }
    Ok(())
}

fn copy_html(source: &PathBuf,
             destination: &PathBuf,
             rustc_version: &str,
             target: bool)
             -> Result<()> {

    let source_file = try!(fs::File::open(source));
    let mut destination_file = try!(fs::OpenOptions::new()
        .write(true)
        .create(true)
        .open(destination));

    let reader = io::BufReader::new(source_file);

    // FIXME: We don't need to store common libraries (jquery and normalize) for the each version
    //        of rustc. I believe storing only one version of this files should work in every
    //        documentation page.
    let replace_regex =
        Regex::new(r#"(href|src)="(.*)(main|jquery|rustdoc|playpen|normalize)\.(css|js)""#)
            .unwrap();
    let replace_str = format!("$1=\"{}../../$2$3-{}.$4\"",
                              if target { "../" } else { "" },
                              rustc_version);

    for line in reader.lines() {
        let mut line = try!(line);

        // replace css links
        line = replace_regex.replace_all(&line[..], &replace_str[..]).into_owned();

        try!(destination_file.write(line.as_bytes()));
        // need to write consumed newline
        try!(destination_file.write(&['\n' as u8]));
    }

    Ok(())
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    extern crate tempdir;
    use std::fs;
    use std::path::Path;
    use super::*;

    #[test]
    #[ignore]
    fn test_copy_dir() {
        let destination = tempdir::TempDir::new("cratesfyi").unwrap();

        // lets try to copy a src directory to tempdir
        let res = copy_dir(Path::new("src"), destination.path());
        // remove temp dir
        fs::remove_dir_all(destination.path()).unwrap();

        assert!(res.is_ok());
    }

    #[test]
    #[ignore]
    fn test_copy_doc_dir() {
        // lets build documentation of rand crate
        use utils::build_doc;
        let pkg = build_doc("rand", None, None).unwrap();

        let pkg_dir = format!("rand-{}", pkg.manifest().version());
        let target = Path::new(&pkg_dir);
        let destination = tempdir::TempDir::new("cratesfyi").unwrap();
        let res = copy_doc_dir(target, destination.path(), "UNKNOWN", false);

        // remove build and temp dir
        fs::remove_dir_all(target).unwrap();
        fs::remove_dir_all(destination.path()).unwrap();

        assert!(res.is_ok());
    }
}
<commit_msg>Stop editing html files generated by rustdoc<commit_after>
// FIXME: There is so many PathBuf's in this module
//        Conver them to Path

use std::io::prelude::*;
use std::io;
use std::path::{Path, PathBuf};
use std::fs;
use error::Result;

use regex::Regex;

/// Copies files from source directory to destination directory.
pub fn copy_dir<P: AsRef<Path>>(source: P, destination: P) -> Result<()> {
    copy_files_and_handle_html(source.as_ref().to_path_buf(),
                               destination.as_ref().to_path_buf(),
                               false,
                               "",
                               false)
}

/// Copies documentation from a crate's target directory to destination.
///
/// Target directory must have doc directory.
///
/// This function is designed to avoid file duplications. It is using rustc version string
/// to rename common files (css files, jquery.js, playpen.js, main.js etc.) in a standard rustdoc.
pub fn copy_doc_dir<P: AsRef<Path>>(target: P,
                                    destination: P,
                                    rustc_version: &str,
                                    target_platform: bool)
                                    -> Result<()> {
    let source = PathBuf::from(target.as_ref()).join("doc");
    copy_files_and_handle_html(source,
                               destination.as_ref().to_path_buf(),
                               true,
                               rustc_version,
                               target_platform)
}

fn copy_files_and_handle_html(source: PathBuf,
                              destination: PathBuf,
                              handle_html: bool,
                              rustc_version: &str,
                              target: bool)
                              -> Result<()> {

    // FIXME: handle_html is useless since we started using --resource-suffix
    //        argument with rustdoc

    // Make sure destination directory is exists
    if !destination.exists() {
        try!(fs::create_dir_all(&destination));
    }

    // Avoid copying common files
    let dup_regex = Regex::new(
        r"(\.lock|\.txt|\.woff|\.svg|\.css|main-.*\.css|main-.*\.js|normalize-.*\.js|rustdoc-.*\.css|storage-.*\.js|theme-.*\.js)$")
        .unwrap();

    for file in try!(source.read_dir()) {

        let file = try!(file);
        let mut destination_full_path = PathBuf::from(&destination);
        destination_full_path.push(file.file_name());

        let metadata = try!(file.metadata());

        if metadata.is_dir() {
            try!(fs::create_dir_all(&destination_full_path));
            try!(copy_files_and_handle_html(file.path(),
                                            destination_full_path,
                                            handle_html,
                                            &rustc_version,
                                            target));
        } else if handle_html && dup_regex.is_match(&file.file_name().into_string().unwrap()[..]) {
            continue;
        } else {
            try!(fs::copy(&file.path(), &destination_full_path));
        }

    }
    Ok(())
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    extern crate tempdir;
    use std::fs;
    use std::path::Path;
    use super::*;

    #[test]
    #[ignore]
    fn test_copy_dir() {
        let destination = tempdir::TempDir::new("cratesfyi").unwrap();

        // lets try to copy a src directory to tempdir
        let res = copy_dir(Path::new("src"), destination.path());
        // remove temp dir
        fs::remove_dir_all(destination.path()).unwrap();

        assert!(res.is_ok());
    }

    #[test]
    #[ignore]
    fn test_copy_doc_dir() {
        // lets build documentation of rand crate
        use utils::build_doc;
        let pkg = build_doc("rand", None, None).unwrap();

        let pkg_dir = format!("rand-{}", pkg.manifest().version());
        let target = Path::new(&pkg_dir);
        let destination = tempdir::TempDir::new("cratesfyi").unwrap();
        let res = copy_doc_dir(target, destination.path(), "UNKNOWN", false);

        // remove build and temp dir
        fs::remove_dir_all(target).unwrap();
        fs::remove_dir_all(destination.path()).unwrap();

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


<commit_before>use bytes::{BufMut, BytesMut};
use serde_1::{Deserialize, Serialize};
use serde_json_1::Value;
use std::error::Error;
use std::fmt::Debug;
use std::io::Read;

use crate::{FromSql, IsNull, ToSql, Type};

// https://github.com/tokio-rs/bytes/issues/170
struct B<'a>(&'a mut BytesMut);

impl<'a> BufMut for B<'a> {
    #[inline]
    fn remaining_mut(&self) -> usize {
        usize::max_value() - self.0.len()
    }

    #[inline]
    unsafe fn advance_mut(&mut self, cnt: usize) {
        self.0.advance_mut(cnt);
    }

    #[inline]
    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        if !self.0.has_remaining_mut() {
            self.0.reserve(64);
        }

        self.0.bytes_mut()
    }
}

/// A wrapper type to allow arbitrary `Serialize`/`Deserialize` types to convert to Postgres JSON values.
#[derive(Debug)]
pub struct Json<T>(pub T);

impl<'a, T> FromSql<'a> for Json<T>
where
    T: Deserialize<'a>,
{
    fn from_sql(ty: &Type, mut raw: &'a [u8]) -> Result<Json<T>, Box<dyn Error + Sync + Send>> {
        if *ty == Type::JSONB {
            let mut b = [0; 1];
            raw.read_exact(&mut b)?;
            // We only support version 1 of the jsonb binary format
            if b[0] != 1 {
                return Err("unsupported JSONB encoding version".into());
            }
        }
        serde_json_1::de::from_slice(raw)
            .map(Json)
            .map_err(Into::into)
    }

    accepts!(JSON, JSONB);
}

impl<T> ToSql for Json<T>
where
    T: Serialize + Debug,
{
    fn to_sql(
        &self,
        ty: &Type,
        out: &mut BytesMut,
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        if *ty == Type::JSONB {
            B(out).put_u8(1);
        }
        serde_json_1::ser::to_writer(B(out).writer(), &self.0)?;
        Ok(IsNull::No)
    }

    accepts!(JSON, JSONB);
    to_sql_checked!();
}

impl<'a> FromSql<'a> for Value {
    fn from_sql(ty: &Type, raw: &[u8]) -> Result<Value, Box<dyn Error + Sync + Send>> {
        Json::<Value>::from_sql(ty, raw).map(|json| json.0)
    }

    accepts!(JSON, JSONB);
}

impl ToSql for Value {
    fn to_sql(
        &self,
        ty: &Type,
        out: &mut BytesMut,
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        Json(self).to_sql(ty, out)
    }

    accepts!(JSON, JSONB);
    to_sql_checked!();
}
<commit_msg>Fix serde-json<commit_after>use crate::{FromSql, IsNull, ToSql, Type};
use bytes::buf::BufMutExt;
use bytes::{BufMut, BytesMut};
use serde_1::{Deserialize, Serialize};
use serde_json_1::Value;
use std::error::Error;
use std::fmt::Debug;
use std::io::Read;

/// A wrapper type to allow arbitrary `Serialize`/`Deserialize` types to convert to Postgres JSON values.
#[derive(Debug)]
pub struct Json<T>(pub T);

impl<'a, T> FromSql<'a> for Json<T>
where
    T: Deserialize<'a>,
{
    fn from_sql(ty: &Type, mut raw: &'a [u8]) -> Result<Json<T>, Box<dyn Error + Sync + Send>> {
        if *ty == Type::JSONB {
            let mut b = [0; 1];
            raw.read_exact(&mut b)?;
            // We only support version 1 of the jsonb binary format
            if b[0] != 1 {
                return Err("unsupported JSONB encoding version".into());
            }
        }
        serde_json_1::de::from_slice(raw)
            .map(Json)
            .map_err(Into::into)
    }

    accepts!(JSON, JSONB);
}

impl<T> ToSql for Json<T>
where
    T: Serialize + Debug,
{
    fn to_sql(
        &self,
        ty: &Type,
        out: &mut BytesMut,
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        if *ty == Type::JSONB {
            out.put_u8(1);
        }
        serde_json_1::ser::to_writer(out.writer(), &self.0)?;
        Ok(IsNull::No)
    }

    accepts!(JSON, JSONB);
    to_sql_checked!();
}

impl<'a> FromSql<'a> for Value {
    fn from_sql(ty: &Type, raw: &[u8]) -> Result<Value, Box<dyn Error + Sync + Send>> {
        Json::<Value>::from_sql(ty, raw).map(|json| json.0)
    }

    accepts!(JSON, JSONB);
}

impl ToSql for Value {
    fn to_sql(
        &self,
        ty: &Type,
        out: &mut BytesMut,
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        Json(self).to_sql(ty, out)
    }

    accepts!(JSON, JSONB);
    to_sql_checked!();
}
<|endoftext|>


<commit_before>extern crate serialize;
use std::io::net::udp::UdpSocket;
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::comm::TryRecvError;

enum PacketType {
    PacketConnect = 0,
    PacketDisconnect,
    PacketMessage
}

struct Packet {
    protocol_id: u32,
    packet_type: PacketType,
    packet_content: Vec<u8>
}

enum Command {
    Disconnect
}

impl Packet {
    fn deserialize(raw: &[u8]) -> Packet {
        Packet {
            protocol_id: 0,
            packet_type: PacketMessage,
            packet_content: vec![]
        }
    }

    fn serialize(&self) -> Vec<u8> {
        vec![]
    }
}

struct Connection {
    addr: SocketAddr,
    reader_comms: Option<(Sender<Command>, Receiver<Packet>)>,
    writer_comms: Option<(Sender<Packet>, Receiver<Command>)>
}

fn reader_process(mut reader: UdpSocket, reader_sub_out: Sender<Packet>, reader_sub_in: Receiver<Command>) {
    let mut buf = [0, ..255];
    loop {
        match reader.recv_from(buf) {
            Ok((amt, src)) => {
                reader_sub_out.send(Packet::deserialize(buf));
            }
            Err(e) => println!("couldn't receive a datagram: {}", e)
        }
    }
}

fn writer_process(mut writer: UdpSocket, writer_sub_out: Sender<Command>, writer_sub_in: Receiver<Packet>, target_addr: SocketAddr) {
    for msg in writer_sub_in.iter() {
        writer.send_to(msg.serialize().as_slice(), target_addr);
    }
}

impl Connection {
    pub fn new(addr: SocketAddr) -> Connection {
        Connection {
            addr: addr,
            reader_comms: None,
            writer_comms: None
        }
    }

    pub fn connect(&mut self, target_addr: SocketAddr) {
         match UdpSocket::bind(self.addr) {
            Ok(reader) => {
                let writer = reader.clone();

                let (reader_out, reader_sub_in) = channel();
                let (reader_sub_out, reader_in) = channel();

                spawn(proc() {
                    reader_process(reader, reader_sub_out, reader_sub_in);
                });

                let (writer_out, writer_sub_in) = channel();
                let (writer_sub_out, writer_in) = channel();
                spawn(proc() {
                    writer_process(writer, writer_sub_out, writer_sub_in, target_addr);
                });

                self.reader_comms = Some((reader_out, reader_in));
                self.writer_comms = Some((writer_out, writer_in));
            }
            Err(e) => fail!("couldn't bind socket: {}", e)
        };
    }

    pub fn poll(&mut self) -> Option<Packet> {
        match self.reader_comms {
            Some((_, ref mut reader_in)) => {
                match reader_in.try_recv() {
                    Ok(value) => Some(value),
                    _ => None
                }
            },
            None => None
        }
    }
}

fn main () {
    Connection::new(SocketAddr{ip: Ipv4Addr(127, 0, 0, 1), port: 0});
}
<commit_msg>Continuing with experimental packet handling<commit_after>extern crate serialize;
use std::io::net::udp::UdpSocket;
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::MemReader;
use std::io::{IoResult, IoError, IoErrorKind, OtherIoError};
use std::comm::TryRecvError;

#[deriving(FromPrimitive)]
enum PacketType {
    PacketConnect = 0,
    PacketDisconnect,
    PacketMessage
}

struct Packet {
    protocol_id: u32,
    packet_type: PacketType,
    packet_content: Vec<u8>
}

enum Command {
    Disconnect
}

impl Packet {
    fn deserialize(raw: &[u8]) -> IoResult<Packet> {
        let mut r = MemReader::new(Vec::from_slice(raw));
        let protocol_id = try!(r.read_be_u32());
        let packet_type = try!(r.read_byte());
        let content = try!(r.read_to_end());

        match FromPrimitive::from_u8(packet_type) {
            Some(packet_type) => {
                Ok(Packet {
                    protocol_id: protocol_id,
                    packet_type: packet_type,
                    packet_content: content
                })
            },
            None => Err(IoError{
                kind: OtherIoError,
                desc: "Invalid packet type",
                detail: None
            })
        }

    }

    fn serialize(&self) -> Vec<u8> {
        vec![]
    }
}

struct Connection {
    addr: SocketAddr,
    reader_comms: Option<(Sender<Command>, Receiver<Packet>)>,
    writer_comms: Option<(Sender<Packet>, Receiver<Command>)>
}

fn reader_process(mut reader: UdpSocket, reader_sub_out: Sender<Packet>, reader_sub_in: Receiver<Command>) {
    let mut buf = [0, ..255];
    loop {
        match reader.recv_from(buf) {
            Ok((amt, src)) => {
                match Packet::deserialize(buf) {
                    Ok(packet) => {
                        //TODO: Validate this packet is actually for us
                        //Packet type, sender
                        reader_sub_out.send(packet);
                    },
                    Err(_) => ()
                }
            }
            Err(e) => println!("couldn't receive a datagram: {}", e)
        }
    }
}

fn writer_process(mut writer: UdpSocket, writer_sub_out: Sender<Command>, writer_sub_in: Receiver<Packet>, target_addr: SocketAddr) {
    for msg in writer_sub_in.iter() {
        writer.send_to(msg.serialize().as_slice(), target_addr);
    }
}

impl Connection {
    pub fn new(addr: SocketAddr) -> Connection {
        Connection {
            addr: addr,
            reader_comms: None,
            writer_comms: None
        }
    }

    pub fn connect(&mut self, target_addr: SocketAddr) {
         match UdpSocket::bind(self.addr) {
            Ok(reader) => {
                let writer = reader.clone();

                let (reader_out, reader_sub_in) = channel();
                let (reader_sub_out, reader_in) = channel();

                spawn(proc() {
                    reader_process(reader, reader_sub_out, reader_sub_in);
                });

                let (writer_out, writer_sub_in) = channel();
                let (writer_sub_out, writer_in) = channel();
                spawn(proc() {
                    writer_process(writer, writer_sub_out, writer_sub_in, target_addr);
                });

                self.reader_comms = Some((reader_out, reader_in));
                self.writer_comms = Some((writer_out, writer_in));
            }
            Err(e) => fail!("couldn't bind socket: {}", e)
        };
    }

    pub fn poll(&mut self) -> Option<Packet> {
        match self.reader_comms {
            Some((_, ref mut reader_in)) => {
                match reader_in.try_recv() {
                    Ok(value) => Some(value),
                    _ => None
                }
            },
            None => None
        }
    }
}

fn main () {
    Connection::new(SocketAddr{ip: Ipv4Addr(127, 0, 0, 1), port: 0});
}
<|endoftext|>


<commit_before>// Higher level OpenCL wrappers.

use CL::*;
use CL::ll::*;

struct Platform {
    id: cl_platform_id
}

pub fn get_platforms() -> ~[Platform] {
    let mut num_platforms = 0;

    // TODO: Check result status
    clGetPlatformIDs(0, ptr::null(), ptr::addr_of(&num_platforms));

    let ids = vec::to_mut(vec::from_elem(num_platforms as uint,
                                         0 as cl_platform_id));

    do vec::as_imm_buf(ids) |ids, len| {
        clGetPlatformIDs(len as cl_uint,
                         ids, ptr::addr_of(&num_platforms))
    };

    do ids.map |id| { Platform { id: *id } }
}

struct Device {
    id: cl_device_id
}

pub fn get_devices(platform: Platform) -> ~[Device] {
    let mut num_devices = 0;

    clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, 0, ptr::null(),
                   ptr::addr_of(&num_devices));

    let ids = vec::to_mut(vec::from_elem(num_devices as uint,
                                         0 as cl_device_id));
    do vec::as_imm_buf(ids) |ids, len| {
        clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, len as cl_uint,
                       ids, ptr::addr_of(&num_devices));
    };

    do ids.map |id| { Device {id: *id }}
}

struct Context {
    ctx: cl_context,

    drop {
        clReleaseContext(self.ctx);
    }
}

pub fn create_context(device: Device) -> Context {
    // TODO: Support for multiple devices
    let mut errcode = 0;

    // TODO: Proper error messages
    let ctx = clCreateContext(ptr::null(), 1, ptr::addr_of(&device.id),
                              ptr::nul(), ptr::addr_of(&errcode));

    if errcode != CL_SUCCESS {
        fail ~"Failed to create opencl context!";
    }

    Context { ctx: ctx };
}

struct CommandQueue {
    cqueue: cl_command_queue,

    drop {
        clReleaseCommandQueue(self.cqueue);
    }
}

pub fn create_commandqueue(ctx: Context, device: Device) -> CommandQueue {
    let mut errcode = 0;

    let cqueue = clCreateCommandQueue(ctx.ctx, device.id, 0, ptr::addr_of(&errcode));

    if errcode != CL_SUCCESS {
        fail ~"Failed to create command queue!";
    }

    CommandQueue { cqueue: cqueue };
}
<commit_msg>Fixed syntax error.<commit_after>// Higher level OpenCL wrappers.

use CL::*;
use CL::ll::*;

struct Platform {
    id: cl_platform_id
}

pub fn get_platforms() -> ~[Platform] {
    let mut num_platforms = 0;

    // TODO: Check result status
    clGetPlatformIDs(0, ptr::null(), ptr::addr_of(&num_platforms));

    let ids = vec::to_mut(vec::from_elem(num_platforms as uint,
                                         0 as cl_platform_id));

    do vec::as_imm_buf(ids) |ids, len| {
        clGetPlatformIDs(len as cl_uint,
                         ids, ptr::addr_of(&num_platforms))
    };

    do ids.map |id| { Platform { id: *id } }
}

struct Device {
    id: cl_device_id
}

pub fn get_devices(platform: Platform) -> ~[Device] {
    let mut num_devices = 0;

    clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, 0, ptr::null(),
                   ptr::addr_of(&num_devices));

    let ids = vec::to_mut(vec::from_elem(num_devices as uint,
                                         0 as cl_device_id));
    do vec::as_imm_buf(ids) |ids, len| {
        clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, len as cl_uint,
                       ids, ptr::addr_of(&num_devices));
    };

    do ids.map |id| { Device {id: *id }}
}

struct Context {
    ctx: cl_context,

    drop {
        clReleaseContext(self.ctx);
    }
}

pub fn create_context(device: Device) -> Context {
    // TODO: Support for multiple devices
    let mut errcode = 0;

    // TODO: Proper error messages
    let ctx = clCreateContext(ptr::null(), 1, ptr::addr_of(&device.id),
                              ptr::null(), ptr::addr_of(&errcode));

    if errcode != CL_SUCCESS {
        fail ~"Failed to create opencl context!";
    }

    Context { ctx: ctx };
}

struct CommandQueue {
    cqueue: cl_command_queue,

    drop {
        clReleaseCommandQueue(self.cqueue);
    }
}

pub fn create_commandqueue(ctx: Context, device: Device) -> CommandQueue {
    let mut errcode = 0;

    let cqueue = clCreateCommandQueue(ctx.ctx, device.id, 0, ptr::addr_of(&errcode));

    if errcode != CL_SUCCESS {
        fail ~"Failed to create command queue!";
    }

    CommandQueue { cqueue: cqueue };
}
<|endoftext|>


<commit_before>use core::libc::{c_void, size_t};
use ll::*;
use ptr::{null, to_unsafe_ptr, to_mut_unsafe_ptr};
use cast::transmute;

pub type CssStylesheet = c_void;

pub enum CssError {
    CssOk = 0,
    CssNomem = 1,
    CssBadParm = 2,
    CssInvalid = 3,
    CssFileNotFound = 4,
    CssNeedData = 5,
    CssBadCharset = 6,
    CssEof = 7,
    CssImportsPending = 8,
    CssPropertyNotSet = 9
}

pub enum CssLanguageLevel {
    CssLevel1 = 0,
    CssLevel2 = 1,
    CssLevel21 = 2,
    CssLevel3 = 3,
    CssLevelDefault = 99 // NB: This is not the same as the ll value
}

pub struct CssStylesheetParams {
    params_version: CssStylesheetParamsVersion,
    level: CssLanguageLevel,
    charset: ~str,
    url: ~str,
    title: ~str,
    allow_quirks: bool,
    inline_style: bool,
    resolve: Option<CssUrlResolutionFn>,
    import: Option<CssImportNotificationFn>,
    color: Option<CssColorResolutionFn>,
    font: Option<CssFontResolutionFn>,
}

pub enum CssStylesheetParamsVersion {
    CssStylesheetParamsVersion1 = 1
}

// FIXME: Need hl reprs of lwc_string
pub type CssUrlResolutionFn = @fn(base: &str, rel: &lwc_string, abs: & &lwc_string) -> CssError;
pub type CssImportNotificationFn = @fn(parent: &CssStylesheet, url: &lwc_string, media: &uint64_t) -> CssError;
pub type CssColorResolutionFn = @fn(name: &lwc_string, color: &CssColor) -> CssError;
pub type CssFontResolutionFn = @fn(name: &lwc_string, system_font: &CssSystemFont) -> CssError;

pub struct CssColor { r: u8, g: u8, b: u8, a: u8 }

pub struct CssSystemFont {
    style: CssFontStyle,
    variant: CssFontVariant,
    weight: CssFontWeight,
    size: CssSize,
    line_height: CssSize,
    family: ~str
}

pub struct CssSize {
    size: CssFixed,
    unit: CssUnit
}

pub enum CssFontStyle {
    CssFontStyleInherit = 0,
    CssFontStyleNormal = 1,
    CssFontStyleItalic = 2,
    CssFontStyleOblique = 3
}

pub enum CssFontVariant {
    CssFontVariantInherit = 0,
    CssFontVariantNormal = 1,
    CssFontVariantSmallCaps = 2
}

pub enum CssFontWeight {
    CssFontWeightInherit = 0x0,
    CssFontWeightNormal = 0x1,
    CssFontWeightBold = 0x2,
    CssFontWeightBolder = 0x3,
    CssFontWeightLighter = 0x4,
    CssFontWeight100 = 0x5,
    CssFontWeight200 = 0x6,
    CssFontWeight300 = 0x7,
    CssFontWeight400 = 0x8,
    CssFontWeight500 = 0x9,
    CssFontWeight600 = 0xa,
    CssFontWeight700 = 0xb,
    CssFontWeight800 = 0xc,
    CssFontWeight900 = 0xd,
}

pub type CssFixed = int32_t;

pub enum CssUnit {
    CssUnitPx = 0x0,
    CssUnitEx = 0x1,
    CssUnitEm = 0x2,
    CssUnitIn = 0x3,
    CssUnitCm = 0x4,
    CssUnitMm = 0x5,
    CssUnitPt = 0x6,
    CssUnitPc = 0x7,
    CssUnitPct = 0x8,
    CssUnitDeg = 0x9,
    CssUnitGrad = 0xa,
    CssUnitRad = 0xb,
    CssUnitMs = 0xc,
    CssUnitS = 0xd,
    CssUnitHz = 0xe,
    CssUnitKhz = 0xf
}

fn ll_result_to_rust_result<T>(code: css_error, val: T) -> CssResult<T> {
    match code {
        CSS_OK => Ok(move val),
        _ => Err(unsafe { transmute(code) })
    }
}

type CssResult<T> = Result<T, CssError>;

pub struct CssStylesheetRef {
    priv sheet: *css_stylesheet,

    drop {
        css_stylesheet_destroy(self.sheet);
    }
}

fn css_stylesheet_create(params: &CssStylesheetParams) -> CssStylesheetRef {
    do params.as_ll |ll_params| {
        let mut sheet: *css_stylesheet = null();
        let code = ll::css_stylesheet_create(
            to_unsafe_ptr(ll_params), realloc, null(), to_mut_unsafe_ptr(&mut sheet));
        require_ok(code, "creating stylesheet");
        CssStylesheetRef {
            sheet: sheet
        }
    }
}

fn require_ok(code: css_error, what: &str) {
    match code {
        CSS_OK => (),
        e => fail fmt!("CSS parsing failed while %s. code: %?", what, e)
    }
}

impl CssStylesheetRef {
    fn size() -> uint {
        let mut size = 0;
        let code = css_stylesheet_size(self.sheet, to_mut_unsafe_ptr(&mut size));
        require_ok(code, "getting stylesheet size");
        return size as uint;
    }

    fn append_data(data: &[u8]) {
        // FIXME: For some reason to_const_ptr isn't accessible
        let code = css_stylesheet_append_data(self.sheet, unsafe { transmute(vec::raw::to_ptr(data)) }, data.len() as size_t);
        match code {
            CSS_NEEDDATA => { /* fine */ },
            _ => require_ok(code, "appending styleshet data")
        }
    }

    fn data_done() {
        let code = css_stylesheet_data_done(self.sheet);
        require_ok(code, "finishing parsing");
    }
}

extern fn realloc(ptr: *c_void, len: size_t, _pw: *c_void) -> *c_void {
    libc::realloc(ptr, len)
}<commit_msg>Use owned closures<commit_after>use core::libc::{c_void, size_t};
use ll::*;
use ptr::{null, to_unsafe_ptr, to_mut_unsafe_ptr};
use cast::transmute;

pub type CssStylesheet = c_void;

pub enum CssError {
    CssOk = 0,
    CssNomem = 1,
    CssBadParm = 2,
    CssInvalid = 3,
    CssFileNotFound = 4,
    CssNeedData = 5,
    CssBadCharset = 6,
    CssEof = 7,
    CssImportsPending = 8,
    CssPropertyNotSet = 9
}

pub enum CssLanguageLevel {
    CssLevel1 = 0,
    CssLevel2 = 1,
    CssLevel21 = 2,
    CssLevel3 = 3,
    CssLevelDefault = 99 // NB: This is not the same as the ll value
}

pub struct CssStylesheetParams {
    params_version: CssStylesheetParamsVersion,
    level: CssLanguageLevel,
    charset: ~str,
    url: ~str,
    title: ~str,
    allow_quirks: bool,
    inline_style: bool,
    resolve: Option<CssUrlResolutionFn>,
    import: Option<CssImportNotificationFn>,
    color: Option<CssColorResolutionFn>,
    font: Option<CssFontResolutionFn>,
}

pub enum CssStylesheetParamsVersion {
    CssStylesheetParamsVersion1 = 1
}

// FIXME: Need hl reprs of lwc_string
pub type CssUrlResolutionFn = ~fn(base: &str, rel: &lwc_string, abs: & &lwc_string) -> CssError;
pub type CssImportNotificationFn = ~fn(parent: &CssStylesheet, url: &lwc_string, media: &uint64_t) -> CssError;
pub type CssColorResolutionFn = ~fn(name: &lwc_string, color: &CssColor) -> CssError;
pub type CssFontResolutionFn = ~fn(name: &lwc_string, system_font: &CssSystemFont) -> CssError;

pub struct CssColor { r: u8, g: u8, b: u8, a: u8 }

pub struct CssSystemFont {
    style: CssFontStyle,
    variant: CssFontVariant,
    weight: CssFontWeight,
    size: CssSize,
    line_height: CssSize,
    family: ~str
}

pub struct CssSize {
    size: CssFixed,
    unit: CssUnit
}

pub enum CssFontStyle {
    CssFontStyleInherit = 0,
    CssFontStyleNormal = 1,
    CssFontStyleItalic = 2,
    CssFontStyleOblique = 3
}

pub enum CssFontVariant {
    CssFontVariantInherit = 0,
    CssFontVariantNormal = 1,
    CssFontVariantSmallCaps = 2
}

pub enum CssFontWeight {
    CssFontWeightInherit = 0x0,
    CssFontWeightNormal = 0x1,
    CssFontWeightBold = 0x2,
    CssFontWeightBolder = 0x3,
    CssFontWeightLighter = 0x4,
    CssFontWeight100 = 0x5,
    CssFontWeight200 = 0x6,
    CssFontWeight300 = 0x7,
    CssFontWeight400 = 0x8,
    CssFontWeight500 = 0x9,
    CssFontWeight600 = 0xa,
    CssFontWeight700 = 0xb,
    CssFontWeight800 = 0xc,
    CssFontWeight900 = 0xd,
}

pub type CssFixed = int32_t;

pub enum CssUnit {
    CssUnitPx = 0x0,
    CssUnitEx = 0x1,
    CssUnitEm = 0x2,
    CssUnitIn = 0x3,
    CssUnitCm = 0x4,
    CssUnitMm = 0x5,
    CssUnitPt = 0x6,
    CssUnitPc = 0x7,
    CssUnitPct = 0x8,
    CssUnitDeg = 0x9,
    CssUnitGrad = 0xa,
    CssUnitRad = 0xb,
    CssUnitMs = 0xc,
    CssUnitS = 0xd,
    CssUnitHz = 0xe,
    CssUnitKhz = 0xf
}

fn ll_result_to_rust_result<T>(code: css_error, val: T) -> CssResult<T> {
    match code {
        CSS_OK => Ok(move val),
        _ => Err(unsafe { transmute(code) })
    }
}

type CssResult<T> = Result<T, CssError>;

pub struct CssStylesheetRef {
    priv sheet: *css_stylesheet,

    drop {
        css_stylesheet_destroy(self.sheet);
    }
}

fn css_stylesheet_create(params: &CssStylesheetParams) -> CssStylesheetRef {
    do params.as_ll |ll_params| {
        let mut sheet: *css_stylesheet = null();
        let code = ll::css_stylesheet_create(
            to_unsafe_ptr(ll_params), realloc, null(), to_mut_unsafe_ptr(&mut sheet));
        require_ok(code, "creating stylesheet");
        CssStylesheetRef {
            sheet: sheet
        }
    }
}

fn require_ok(code: css_error, what: &str) {
    match code {
        CSS_OK => (),
        e => fail fmt!("CSS parsing failed while %s. code: %?", what, e)
    }
}

impl CssStylesheetRef {
    fn size() -> uint {
        let mut size = 0;
        let code = css_stylesheet_size(self.sheet, to_mut_unsafe_ptr(&mut size));
        require_ok(code, "getting stylesheet size");
        return size as uint;
    }

    fn append_data(data: &[u8]) {
        // FIXME: For some reason to_const_ptr isn't accessible
        let code = css_stylesheet_append_data(self.sheet, unsafe { transmute(vec::raw::to_ptr(data)) }, data.len() as size_t);
        match code {
            CSS_NEEDDATA => { /* fine */ },
            _ => require_ok(code, "appending styleshet data")
        }
    }

    fn data_done() {
        let code = css_stylesheet_data_done(self.sheet);
        require_ok(code, "finishing parsing");
    }
}

extern fn realloc(ptr: *c_void, len: size_t, _pw: *c_void) -> *c_void {
    libc::realloc(ptr, len)
}<|endoftext|>