<commit_before>use super::{Attribute, AttrStyle, Body, Crate, Ident, Item, ItemKind, MacroInput, MetaItem};
use quote::Tokens;

use std::collections::BTreeMap as Map;
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;

/// Implementation of a custom derive. Custom derives take a struct or enum and
/// expand it into zero or more items, typically `impl` items.
pub trait CustomDerive {
    /// Expand the given struct or enum. If this custom derive modifies the
    /// input item or preserves it unmodified, it must be returned back in the
    /// `original` field of Expanded. The custom derive may discard the input
    /// item by setting `original` to None.
    fn expand(&self, input: MacroInput) -> Result<Expanded, String>;
}

/// Produced by expanding a custom derive.
pub struct Expanded {
    /// The items (typically `impl` items) constructed by the custom derive.
    pub new_items: Vec<Item>,
    /// The input to the custom derive, whether modified or unmodified. If the
    /// custom derive discards the input item it may do so by setting `original`
    /// to None.
    pub original: Option<MacroInput>,
}

/// Registry of custom derives. Callers add custom derives to a registry, then
/// use the registry to expand those derives in a source file.
#[derive(Default)]
pub struct Registry<'a> {
    derives: Map<String, Box<CustomDerive + 'a>>,
}

impl<T> CustomDerive for T
    where T: Fn(MacroInput) -> Result<Expanded, String>
{
    fn expand(&self, input: MacroInput) -> Result<Expanded, String> {
        self(input)
    }
}

impl<'a> Registry<'a> {
    pub fn new() -> Self {
        Default::default()
    }

    /// Register a custom derive. A `fn(MacroInput) -> Result<Expanded, String>`
    /// may be used as a custom derive.
    ///
    /// ```ignore
    /// registry.add_derive("Serialize", expand_serialize);
    /// ```
    pub fn add_derive<T>(&mut self, name: &str, derive: T)
        where T: CustomDerive + 'a
    {
        self.derives.insert(name.into(), Box::new(derive));
    }

    /// Read Rust source code from the `src` file, expand the custom derives
    /// that have been registered, and write the result to the `dst` file.
    pub fn expand_file<S, D>(&self, src: S, dst: D) -> Result<(), String>
        where S: AsRef<Path>,
              D: AsRef<Path>
    {
        // Open the src file
        let mut src = match File::open(src) {
            Ok(open) => open,
            Err(err) => return Err(err.to_string()),
        };

        // Read the contents of the src file to a String
        let mut content = String::new();
        if let Err(err) = src.read_to_string(&mut content) {
            return Err(err.to_string());
        }

        // Parse the contents
        let krate = try!(super::parse_crate(&content));

        // Expand
        let expanded = try!(expand_crate(self, krate));

        // Print the expanded code to a String
        let out = try!(pretty(quote!(#expanded)));

        // Create or truncate the dst file, opening in write-only mode
        let mut dst = match File::create(dst) {
            Ok(create) => create,
            Err(err) => return Err(err.to_string()),
        };

        // Write expanded code to the dst file
        if let Err(err) = dst.write_all(out.as_bytes()) {
            return Err(err.to_string());
        }

        Ok(())
    }
}

fn expand_crate(reg: &Registry, krate: Crate) -> Result<Crate, String> {
    let mut items = Vec::new();
    for item in krate.items {
        try!(expand_item(reg, item, Vec::new(), &mut items));
    }
    Ok(Crate { items: items, ..krate })
}

fn expand_item(reg: &Registry, mut item: Item, cfg: Vec<MetaItem>, out: &mut Vec<Item>) -> Result<(), String> {
    let (body, generics) = match item.node {
        ItemKind::Enum(variants, generics) => (Body::Enum(variants), generics),
        ItemKind::Struct(variant_data, generics) => (Body::Struct(variant_data), generics),
        _ => {
            // Custom derives cannot apply to this item, preserve it unmodified
            item.attrs.extend(combine_cfgs(cfg));
            out.push(item);
            return Ok(());
        }
    };
    let macro_input = MacroInput {
        ident: item.ident,
        vis: item.vis,
        attrs: item.attrs,
        generics: generics,
        body: body,
    };
    expand_macro_input(reg, macro_input, cfg, out)
}

fn expand_macro_input(reg: &Registry,
                      mut input: MacroInput,
                      inherited_cfg: Vec<MetaItem>,
                      out: &mut Vec<Item>)
                      -> Result<(), String> {
    let mut derives = Vec::new();
    let mut all_cfg = inherited_cfg;

    // Find custom derives on this item, removing them from the input
    input.attrs = input.attrs
        .into_iter()
        .flat_map(|attr| {
            let (new_derives, cfg, attr) = parse_attr(reg, attr);
            derives.extend(new_derives);
            all_cfg.extend(cfg);
            attr
        })
        .collect();

    // Expand each custom derive
    for derive in derives {
        let expanded = try!(reg.derives[derive.name.as_ref()].expand(input));

        for new_item in expanded.new_items {
            let mut extended_cfg = all_cfg.clone();
            extended_cfg.extend(derive.cfg.clone());
            try!(expand_item(reg, new_item, extended_cfg, out));
        }

        input = match expanded.original {
            Some(input) => input,
            None => return Ok(()),
        };
    }

    input.attrs.extend(combine_cfgs(all_cfg));
    out.push(input.into());
    Ok(())
}

struct Derive {
    name: Ident,
    /// If the custom derive was behind a cfg_attr
    cfg: Option<MetaItem>,
}

/// Pull custom derives and cfgs out of the given Attribute.
fn parse_attr(reg: &Registry, attr: Attribute) -> (Vec<Derive>, Vec<MetaItem>, Option<Attribute>) {
    if attr.style != AttrStyle::Outer || attr.is_sugared_doc {
        return (Vec::new(), Vec::new(), Some(attr));
    }

    let (name, nested) = match attr.value {
        MetaItem::List(name, nested) => (name, nested),
        _ => return (Vec::new(), Vec::new(), Some(attr)),
    };

    match name.as_ref() {
        "derive" => {
            let (derives, attr) = parse_derive_attr(reg, nested);
            let derives = derives.into_iter()
                .map(|d| {
                    Derive {
                        name: d,
                        cfg: None,
                    }
                })
                .collect();
            (derives, Vec::new(), attr)
        }
        "cfg_attr" => {
            let (derives, attr) = parse_cfg_attr(reg, nested);
            (derives, Vec::new(), attr)
        }
        "cfg" => (Vec::new(), nested, None),
        _ => {
            // Rebuild the original attribute because it was destructured above
            let attr = Attribute {
                style: AttrStyle::Outer,
                value: MetaItem::List(name, nested),
                is_sugared_doc: false,
            };
            (Vec::new(), Vec::new(), Some(attr))
        }
    }
}

/// Assuming the given nested meta-items came from a #[derive(...)] attribute,
/// pull out the ones that are custom derives.
fn parse_derive_attr(reg: &Registry, nested: Vec<MetaItem>) -> (Vec<Ident>, Option<Attribute>) {
    let mut derives = Vec::new();

    let remaining: Vec<_> = nested.into_iter()
        .flat_map(|meta| {
            let word = match meta {
                MetaItem::Word(word) => word,
                _ => return Some(meta),
            };
            if reg.derives.contains_key(word.as_ref()) {
                derives.push(word);
                None
            } else {
                Some(MetaItem::Word(word))
            }
        })
        .collect();

    let attr = if remaining.is_empty() {
        // Elide an empty #[derive()]
        None
    } else {
        Some(Attribute {
            style: AttrStyle::Outer,
            value: MetaItem::List("derive".into(), remaining),
            is_sugared_doc: false,
        })
    };

    (derives, attr)
}

/// Assuming the given nested meta-items came from a #[cfg_attr(...)] attribute,
/// pull out any custom derives contained within.
fn parse_cfg_attr(reg: &Registry, nested: Vec<MetaItem>) -> (Vec<Derive>, Option<Attribute>) {
    if nested.len() != 2 {
        let attr = Attribute {
            style: AttrStyle::Outer,
            value: MetaItem::List("cfg_attr".into(), nested),
            is_sugared_doc: false,
        };
        return (Vec::new(), Some(attr));
    }

    let mut iter = nested.into_iter();
    let cfg = iter.next().unwrap();
    let arg = iter.next().unwrap();

    let (name, nested) = match arg {
        MetaItem::List(name, nested) => (name, nested),
        _ => {
            let attr = Attribute {
                style: AttrStyle::Outer,
                value: MetaItem::List("cfg_attr".into(), vec![cfg, arg]),
                is_sugared_doc: false,
            };
            return (Vec::new(), Some(attr));
        }
    };

    if name == "derive" {
        let (derives, attr) = parse_derive_attr(reg, nested);
        let derives = derives.into_iter()
            .map(|d| {
                Derive {
                    name: d,
                    cfg: Some(cfg.clone()),
                }
            })
            .collect();
        let attr = attr.map(|attr| {
            Attribute {
                style: AttrStyle::Outer,
                value: MetaItem::List("cfg_attr".into(), vec![cfg, attr.value]),
                is_sugared_doc: false,
            }
        });
        (derives, attr)
    } else {
        let attr = Attribute {
            style: AttrStyle::Outer,
            value: MetaItem::List("cfg_attr".into(), vec![cfg, MetaItem::List(name, nested)]),
            is_sugared_doc: false,
        };
        (Vec::new(), Some(attr))
    }
}

/// Combine a list of cfg expressions into an attribute like `#[cfg(a)]` or
/// `#[cfg(all(a, b, c))]`, or nothing if there are no cfg expressions.
fn combine_cfgs(cfg: Vec<MetaItem>) -> Option<Attribute> {
    // Flatten `all` cfgs so we don't nest `all` inside of `all`.
    let cfg: Vec<_> = cfg.into_iter().flat_map(|cfg| {
        let (name, nested) = match cfg {
            MetaItem::List(name, nested) => (name, nested),
            _ => return vec![cfg],
        };
        if name == "all" {
            nested
        } else {
            vec![MetaItem::List(name, nested)]
        }
    }).collect();

    let value = match cfg.len() {
        0 => return None,
        1 => cfg,
        _ => vec![MetaItem::List("all".into(), cfg)],
    };

    Some(Attribute {
        style: AttrStyle::Outer,
        value: MetaItem::List("cfg".into(), value),
        is_sugared_doc: false,
    })
}

#[cfg(not(feature = "pretty"))]
fn pretty(tokens: Tokens) -> Result<String, String> {
    Ok(tokens.to_string())
}

#[cfg(feature = "pretty")]
fn pretty(tokens: Tokens) -> Result<String, String> {
    use syntax::parse::{self, ParseSess};
    use syntax::print::pprust;

    let name = "syn".to_string();
    let source = tokens.to_string();
    let cfg = Vec::new();
    let sess = ParseSess::new();
    let krate = match parse::parse_crate_from_source_str(name, source, cfg, &sess) {
        Ok(krate) => krate,
        Err(mut err) => {
            err.emit();
            return Err("pretty printer failed to parse expanded code".into());
        }
    };

    if sess.span_diagnostic.has_errors() {
        return Err("pretty printer failed to parse expanded code".into());
    }

    let mut reader = &tokens.to_string().into_bytes()[..];
    let mut writer = Vec::new();
    let ann = pprust::NoAnn;

    try!(pprust::print_crate(
        sess.codemap(),
        &sess.span_diagnostic,
        &krate,
        "".to_string(),
        &mut reader,
        Box::new(&mut writer),
        &ann,
        false).map_err(|err| err.to_string()));

    String::from_utf8(writer).map_err(|err| err.to_string())
}
<commit_msg>Cargo fmt<commit_after>use super::{Attribute, AttrStyle, Body, Crate, Ident, Item, ItemKind, MacroInput, MetaItem};
use quote::Tokens;

use std::collections::BTreeMap as Map;
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;

/// Implementation of a custom derive. Custom derives take a struct or enum and
/// expand it into zero or more items, typically `impl` items.
pub trait CustomDerive {
    /// Expand the given struct or enum. If this custom derive modifies the
    /// input item or preserves it unmodified, it must be returned back in the
    /// `original` field of Expanded. The custom derive may discard the input
    /// item by setting `original` to None.
    fn expand(&self, input: MacroInput) -> Result<Expanded, String>;
}

/// Produced by expanding a custom derive.
pub struct Expanded {
    /// The items (typically `impl` items) constructed by the custom derive.
    pub new_items: Vec<Item>,
    /// The input to the custom derive, whether modified or unmodified. If the
    /// custom derive discards the input item it may do so by setting `original`
    /// to None.
    pub original: Option<MacroInput>,
}

/// Registry of custom derives. Callers add custom derives to a registry, then
/// use the registry to expand those derives in a source file.
#[derive(Default)]
pub struct Registry<'a> {
    derives: Map<String, Box<CustomDerive + 'a>>,
}

impl<T> CustomDerive for T
    where T: Fn(MacroInput) -> Result<Expanded, String>
{
    fn expand(&self, input: MacroInput) -> Result<Expanded, String> {
        self(input)
    }
}

impl<'a> Registry<'a> {
    pub fn new() -> Self {
        Default::default()
    }

    /// Register a custom derive. A `fn(MacroInput) -> Result<Expanded, String>`
    /// may be used as a custom derive.
    ///
    /// ```ignore
    /// registry.add_derive("Serialize", expand_serialize);
    /// ```
    pub fn add_derive<T>(&mut self, name: &str, derive: T)
        where T: CustomDerive + 'a
    {
        self.derives.insert(name.into(), Box::new(derive));
    }

    /// Read Rust source code from the `src` file, expand the custom derives
    /// that have been registered, and write the result to the `dst` file.
    pub fn expand_file<S, D>(&self, src: S, dst: D) -> Result<(), String>
        where S: AsRef<Path>,
              D: AsRef<Path>
    {
        // Open the src file
        let mut src = match File::open(src) {
            Ok(open) => open,
            Err(err) => return Err(err.to_string()),
        };

        // Read the contents of the src file to a String
        let mut content = String::new();
        if let Err(err) = src.read_to_string(&mut content) {
            return Err(err.to_string());
        }

        // Parse the contents
        let krate = try!(super::parse_crate(&content));

        // Expand
        let expanded = try!(expand_crate(self, krate));

        // Print the expanded code to a String
        let out = try!(pretty(quote!(#expanded)));

        // Create or truncate the dst file, opening in write-only mode
        let mut dst = match File::create(dst) {
            Ok(create) => create,
            Err(err) => return Err(err.to_string()),
        };

        // Write expanded code to the dst file
        if let Err(err) = dst.write_all(out.as_bytes()) {
            return Err(err.to_string());
        }

        Ok(())
    }
}

fn expand_crate(reg: &Registry, krate: Crate) -> Result<Crate, String> {
    let mut items = Vec::new();
    for item in krate.items {
        try!(expand_item(reg, item, Vec::new(), &mut items));
    }
    Ok(Crate { items: items, ..krate })
}

fn expand_item(reg: &Registry,
               mut item: Item,
               cfg: Vec<MetaItem>,
               out: &mut Vec<Item>)
               -> Result<(), String> {
    let (body, generics) = match item.node {
        ItemKind::Enum(variants, generics) => (Body::Enum(variants), generics),
        ItemKind::Struct(variant_data, generics) => (Body::Struct(variant_data), generics),
        _ => {
            // Custom derives cannot apply to this item, preserve it unmodified
            item.attrs.extend(combine_cfgs(cfg));
            out.push(item);
            return Ok(());
        }
    };
    let macro_input = MacroInput {
        ident: item.ident,
        vis: item.vis,
        attrs: item.attrs,
        generics: generics,
        body: body,
    };
    expand_macro_input(reg, macro_input, cfg, out)
}

fn expand_macro_input(reg: &Registry,
                      mut input: MacroInput,
                      inherited_cfg: Vec<MetaItem>,
                      out: &mut Vec<Item>)
                      -> Result<(), String> {
    let mut derives = Vec::new();
    let mut all_cfg = inherited_cfg;

    // Find custom derives on this item, removing them from the input
    input.attrs = input.attrs
        .into_iter()
        .flat_map(|attr| {
            let (new_derives, cfg, attr) = parse_attr(reg, attr);
            derives.extend(new_derives);
            all_cfg.extend(cfg);
            attr
        })
        .collect();

    // Expand each custom derive
    for derive in derives {
        let expanded = try!(reg.derives[derive.name.as_ref()].expand(input));

        for new_item in expanded.new_items {
            let mut extended_cfg = all_cfg.clone();
            extended_cfg.extend(derive.cfg.clone());
            try!(expand_item(reg, new_item, extended_cfg, out));
        }

        input = match expanded.original {
            Some(input) => input,
            None => return Ok(()),
        };
    }

    input.attrs.extend(combine_cfgs(all_cfg));
    out.push(input.into());
    Ok(())
}

struct Derive {
    name: Ident,
    /// If the custom derive was behind a cfg_attr
    cfg: Option<MetaItem>,
}

/// Pull custom derives and cfgs out of the given Attribute.
fn parse_attr(reg: &Registry, attr: Attribute) -> (Vec<Derive>, Vec<MetaItem>, Option<Attribute>) {
    if attr.style != AttrStyle::Outer || attr.is_sugared_doc {
        return (Vec::new(), Vec::new(), Some(attr));
    }

    let (name, nested) = match attr.value {
        MetaItem::List(name, nested) => (name, nested),
        _ => return (Vec::new(), Vec::new(), Some(attr)),
    };

    match name.as_ref() {
        "derive" => {
            let (derives, attr) = parse_derive_attr(reg, nested);
            let derives = derives.into_iter()
                .map(|d| {
                    Derive {
                        name: d,
                        cfg: None,
                    }
                })
                .collect();
            (derives, Vec::new(), attr)
        }
        "cfg_attr" => {
            let (derives, attr) = parse_cfg_attr(reg, nested);
            (derives, Vec::new(), attr)
        }
        "cfg" => (Vec::new(), nested, None),
        _ => {
            // Rebuild the original attribute because it was destructured above
            let attr = Attribute {
                style: AttrStyle::Outer,
                value: MetaItem::List(name, nested),
                is_sugared_doc: false,
            };
            (Vec::new(), Vec::new(), Some(attr))
        }
    }
}

/// Assuming the given nested meta-items came from a #[derive(...)] attribute,
/// pull out the ones that are custom derives.
fn parse_derive_attr(reg: &Registry, nested: Vec<MetaItem>) -> (Vec<Ident>, Option<Attribute>) {
    let mut derives = Vec::new();

    let remaining: Vec<_> = nested.into_iter()
        .flat_map(|meta| {
            let word = match meta {
                MetaItem::Word(word) => word,
                _ => return Some(meta),
            };
            if reg.derives.contains_key(word.as_ref()) {
                derives.push(word);
                None
            } else {
                Some(MetaItem::Word(word))
            }
        })
        .collect();

    let attr = if remaining.is_empty() {
        // Elide an empty #[derive()]
        None
    } else {
        Some(Attribute {
            style: AttrStyle::Outer,
            value: MetaItem::List("derive".into(), remaining),
            is_sugared_doc: false,
        })
    };

    (derives, attr)
}

/// Assuming the given nested meta-items came from a #[cfg_attr(...)] attribute,
/// pull out any custom derives contained within.
fn parse_cfg_attr(reg: &Registry, nested: Vec<MetaItem>) -> (Vec<Derive>, Option<Attribute>) {
    if nested.len() != 2 {
        let attr = Attribute {
            style: AttrStyle::Outer,
            value: MetaItem::List("cfg_attr".into(), nested),
            is_sugared_doc: false,
        };
        return (Vec::new(), Some(attr));
    }

    let mut iter = nested.into_iter();
    let cfg = iter.next().unwrap();
    let arg = iter.next().unwrap();

    let (name, nested) = match arg {
        MetaItem::List(name, nested) => (name, nested),
        _ => {
            let attr = Attribute {
                style: AttrStyle::Outer,
                value: MetaItem::List("cfg_attr".into(), vec![cfg, arg]),
                is_sugared_doc: false,
            };
            return (Vec::new(), Some(attr));
        }
    };

    if name == "derive" {
        let (derives, attr) = parse_derive_attr(reg, nested);
        let derives = derives.into_iter()
            .map(|d| {
                Derive {
                    name: d,
                    cfg: Some(cfg.clone()),
                }
            })
            .collect();
        let attr = attr.map(|attr| {
            Attribute {
                style: AttrStyle::Outer,
                value: MetaItem::List("cfg_attr".into(), vec![cfg, attr.value]),
                is_sugared_doc: false,
            }
        });
        (derives, attr)
    } else {
        let attr = Attribute {
            style: AttrStyle::Outer,
            value: MetaItem::List("cfg_attr".into(), vec![cfg, MetaItem::List(name, nested)]),
            is_sugared_doc: false,
        };
        (Vec::new(), Some(attr))
    }
}

/// Combine a list of cfg expressions into an attribute like `#[cfg(a)]` or
/// `#[cfg(all(a, b, c))]`, or nothing if there are no cfg expressions.
fn combine_cfgs(cfg: Vec<MetaItem>) -> Option<Attribute> {
    // Flatten `all` cfgs so we don't nest `all` inside of `all`.
    let cfg: Vec<_> = cfg.into_iter()
        .flat_map(|cfg| {
            let (name, nested) = match cfg {
                MetaItem::List(name, nested) => (name, nested),
                _ => return vec![cfg],
            };
            if name == "all" {
                nested
            } else {
                vec![MetaItem::List(name, nested)]
            }
        })
        .collect();

    let value = match cfg.len() {
        0 => return None,
        1 => cfg,
        _ => vec![MetaItem::List("all".into(), cfg)],
    };

    Some(Attribute {
        style: AttrStyle::Outer,
        value: MetaItem::List("cfg".into(), value),
        is_sugared_doc: false,
    })
}

#[cfg(not(feature = "pretty"))]
fn pretty(tokens: Tokens) -> Result<String, String> {
    Ok(tokens.to_string())
}

#[cfg(feature = "pretty")]
fn pretty(tokens: Tokens) -> Result<String, String> {
    use syntax::parse::{self, ParseSess};
    use syntax::print::pprust;

    let name = "syn".to_string();
    let source = tokens.to_string();
    let cfg = Vec::new();
    let sess = ParseSess::new();
    let krate = match parse::parse_crate_from_source_str(name, source, cfg, &sess) {
        Ok(krate) => krate,
        Err(mut err) => {
            err.emit();
            return Err("pretty printer failed to parse expanded code".into());
        }
    };

    if sess.span_diagnostic.has_errors() {
        return Err("pretty printer failed to parse expanded code".into());
    }

    let mut reader = &tokens.to_string().into_bytes()[..];
    let mut writer = Vec::new();
    let ann = pprust::NoAnn;

    try!(pprust::print_crate(
        sess.codemap(),
        &sess.span_diagnostic,
        &krate,
        "".to_string(),
        &mut reader,
        Box::new(&mut writer),
        &ann,
        false).map_err(|err| err.to_string()));

    String::from_utf8(writer).map_err(|err| err.to_string())
}
<|endoftext|>


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

use eutil::slice_to_str;
use libc::{size_t, c_int, c_ushort,c_void};
use libc::types::os::arch::c95::wchar_t;
use mem::{new0,newarray0,delete,deletearray};
use std::char;
use std::mem;
use std::ptr;
use std::slice;
use std::string;
use types::{cef_string_utf16_t, cef_string_utf8_t, cef_string_wide_t};
use types::{cef_string_userfree_utf16_t, cef_string_userfree_utf8_t, cef_string_userfree_wide_t};

//cef_string

#[no_mangle]
extern "C" fn string_wide_dtor(str: *mut wchar_t) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
extern "C" fn string_utf8_dtor(str: *mut u8) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
extern "C" fn string_utf16_dtor(str: *mut c_ushort) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_free(cs: *mut cef_string_userfree_wide_t) {
   cef_string_wide_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf8_t) {
   cef_string_utf8_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_free(cs: *mut cef_string_userfree_utf16_t) {
   cef_string_utf16_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_clear(cs: *mut cef_string_utf8_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut u8;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_alloc() -> *mut cef_string_utf8_t {
    #![inline(never)]
    new0::<cef_string_utf8_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_set(src: *const u8, src_len: size_t, output: *mut cef_string_utf8_t, copy: c_int) -> c_int {
    cef_string_utf8_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<u8>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf8_dtor);
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_cmp(a: *const cef_string_utf8_t, b: *const cef_string_utf8_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice((*a).str as *const u8, (*a).length as uint, |astr:&[u8]| {
            slice::raw::buf_as_slice((*b).str as *const u8, (*b).length as uint, |bstr:&[u8]| {
                  match astr.cmp(bstr) {
                       Less => -1,
                       Equal => 0,
                       Greater => 1
                  }
            })
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as uint, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1);
        1
    })
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_to_utf8(src: *const u16, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(src, src_len as uint, |ustr| {
            match string::String::from_utf16(ustr) {
                Some(str) => {
                    cef_string_utf8_set(str.as_bytes().as_ptr(), str.len() as size_t, output, 1);
                    1 as c_int
                },
                None =>  0 as c_int
            }
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_clear(cs: *mut cef_string_utf16_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut c_ushort;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_alloc() -> *mut cef_string_utf16_t {
    #![inline(never)]
    new0::<cef_string_utf16_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_set(src: *const c_ushort, src_len: size_t, output: *mut cef_string_utf16_t, copy: c_int) -> c_int {
    cef_string_utf16_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<c_ushort>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf16_dtor);
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_cmp(a: *const cef_string_utf16_t, b: *const cef_string_utf16_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(mem::transmute((*a).str), (*a).length as uint, |astr:&[u16]| {
            slice::raw::buf_as_slice(mem::transmute((*b).str), (*b).length as uint, |bstr:&[u16]| {
                  match astr.cmp(bstr) {
                       Less => -1,
                       Equal => 0,
                       Greater => 1
                  }
            })
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_clear(cs: *mut cef_string_wide_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut wchar_t;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_alloc() -> *mut cef_string_wide_t {
    #![inline(never)]
    new0::<cef_string_wide_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_wide_set(src: *const wchar_t, src_len: size_t, output: *mut cef_string_wide_t, copy: c_int) -> c_int {
    cef_string_wide_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<wchar_t>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = Some(string_wide_dtor);
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_wide_cmp(a: *const cef_string_wide_t, b: *const cef_string_wide_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice((*a).str as *const wchar_t, (*a).length as uint, |astr:&[wchar_t]| {
            slice::raw::buf_as_slice((*b).str as *const wchar_t, (*b).length as uint, |bstr:&[wchar_t]| {
                  match astr.cmp(bstr) {
                       Less => -1,
                       Equal => 0,
                       Greater => 1
                  }
            })
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf8_to_utf16(src, src_len, output as *mut cef_string_utf16_t);
    }
    slice_to_str(src, src_len as uint, |result| {
        let conv = result.chars().map(|c| c as u32).collect::<Vec<u32>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_wide_to_utf8(src: *const wchar_t, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf16_to_utf8(src as *const u16, src_len, output);
    }
    unsafe {
       slice::raw::buf_as_slice(src, src_len as uint, |ustr| {
            let conv = ustr.iter().map(|&c| char::from_u32(c as u32).unwrap_or('\uFFFD')).collect::<String>();
            cef_string_utf8_set(conv.as_bytes().as_ptr(), conv.len() as size_t, output, 1)
       })
    }
}
<commit_msg>embedding: cef_string_ascii_to_utf16()<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::slice_to_str;
use libc::{size_t, c_int, c_ushort,c_void};
use libc::types::os::arch::c95::wchar_t;
use mem::{new0,newarray0,delete,deletearray};
use std::char;
use std::mem;
use std::ptr;
use std::slice;
use std::string;
use types::{cef_string_utf16_t, cef_string_utf8_t, cef_string_wide_t};
use types::{cef_string_userfree_utf16_t, cef_string_userfree_utf8_t, cef_string_userfree_wide_t};

//cef_string

#[no_mangle]
extern "C" fn string_wide_dtor(str: *mut wchar_t) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
extern "C" fn string_utf8_dtor(str: *mut u8) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
extern "C" fn string_utf16_dtor(str: *mut c_ushort) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_free(cs: *mut cef_string_userfree_wide_t) {
   cef_string_wide_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf8_t) {
   cef_string_utf8_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_free(cs: *mut cef_string_userfree_utf16_t) {
   cef_string_utf16_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_clear(cs: *mut cef_string_utf8_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut u8;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_alloc() -> *mut cef_string_utf8_t {
    #![inline(never)]
    new0::<cef_string_utf8_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_set(src: *const u8, src_len: size_t, output: *mut cef_string_utf8_t, copy: c_int) -> c_int {
    cef_string_utf8_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<u8>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf8_dtor);
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_cmp(a: *const cef_string_utf8_t, b: *const cef_string_utf8_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice((*a).str as *const u8, (*a).length as uint, |astr:&[u8]| {
            slice::raw::buf_as_slice((*b).str as *const u8, (*b).length as uint, |bstr:&[u8]| {
                  match astr.cmp(bstr) {
                       Less => -1,
                       Equal => 0,
                       Greater => 1
                  }
            })
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as uint, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1);
        1
    })
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_to_utf8(src: *const u16, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(src, src_len as uint, |ustr| {
            match string::String::from_utf16(ustr) {
                Some(str) => {
                    cef_string_utf8_set(str.as_bytes().as_ptr(), str.len() as size_t, output, 1);
                    1 as c_int
                },
                None =>  0 as c_int
            }
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_clear(cs: *mut cef_string_utf16_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut c_ushort;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_alloc() -> *mut cef_string_utf16_t {
    #![inline(never)]
    new0::<cef_string_utf16_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_set(src: *const c_ushort, src_len: size_t, output: *mut cef_string_utf16_t, copy: c_int) -> c_int {
    cef_string_utf16_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<c_ushort>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf16_dtor);
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_cmp(a: *const cef_string_utf16_t, b: *const cef_string_utf16_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(mem::transmute((*a).str), (*a).length as uint, |astr:&[u16]| {
            slice::raw::buf_as_slice(mem::transmute((*b).str), (*b).length as uint, |bstr:&[u16]| {
                  match astr.cmp(bstr) {
                       Less => -1,
                       Equal => 0,
                       Greater => 1
                  }
            })
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_clear(cs: *mut cef_string_wide_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut wchar_t;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_alloc() -> *mut cef_string_wide_t {
    #![inline(never)]
    new0::<cef_string_wide_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_wide_set(src: *const wchar_t, src_len: size_t, output: *mut cef_string_wide_t, copy: c_int) -> c_int {
    cef_string_wide_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<wchar_t>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = Some(string_wide_dtor);
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_wide_cmp(a: *const cef_string_wide_t, b: *const cef_string_wide_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice((*a).str as *const wchar_t, (*a).length as uint, |astr:&[wchar_t]| {
            slice::raw::buf_as_slice((*b).str as *const wchar_t, (*b).length as uint, |bstr:&[wchar_t]| {
                  match astr.cmp(bstr) {
                       Less => -1,
                       Equal => 0,
                       Greater => 1
                  }
            })
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf8_to_utf16(src, src_len, output as *mut cef_string_utf16_t);
    }
    slice_to_str(src, src_len as uint, |result| {
        let conv = result.chars().map(|c| c as u32).collect::<Vec<u32>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_wide_to_utf8(src: *const wchar_t, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf16_to_utf8(src as *const u16, src_len, output);
    }
    unsafe {
       slice::raw::buf_as_slice(src, src_len as uint, |ustr| {
            let conv = ustr.iter().map(|&c| char::from_u32(c as u32).unwrap_or('\uFFFD')).collect::<String>();
            cef_string_utf8_set(conv.as_bytes().as_ptr(), conv.len() as size_t, output, 1)
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as uint, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1)
    })
}
<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};

use turtle::random;

use cell::Cell;
use wall::Wall;

const GRID_SIZE: usize = 8;

/// A row or column of cells
pub type Cells = [Cell; GRID_SIZE];

/// Used to determine whether to iterate over rows or columns
#[derive(Clone, Copy)]
enum GridIterTarget {
    Rows,
    Columns,
}

pub struct GridIter<'a> {
    grid: &'a [Cells; GRID_SIZE],
    target: GridIterTarget,
    current: usize,
    end: usize,
}

impl<'a> GridIter<'a> {
    fn new(grid: &'a [Cells; GRID_SIZE], target: GridIterTarget) -> Self {
        Self {
            grid,
            target,
            current: 0,
            end: match target {
                GridIterTarget::Rows => grid.len(),
                GridIterTarget::Columns => grid[0].len(),
            },
        }
    }
}

impl<'a> Iterator for GridIter<'a> {
    type Item = GridCellIter<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current >= self.end {
            return None;
        }

        let iter = GridCellIter::new(
            self.grid,
            self.target,
            self.current
        );

        self.current += 1;
        Some(iter)
    }
}

impl<'a> DoubleEndedIterator for GridIter<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.current >= self.end {
            return None;
        }

        let iter = GridCellIter::new(
            self.grid,
            self.target,
            self.end - 1
        );

        self.end -= 1;
        Some(iter)
    }
}

pub struct GridCellIter<'a> {
    grid: &'a [Cells; GRID_SIZE],
    target: GridIterTarget,
    /// The row or column being iterated over
    index: usize,
    /// The current position in the row or column being iterated over
    current: usize,
    // Index of the item just after the last item in the row or column being iterated over
    end: usize,
}

impl<'a> GridCellIter<'a> {
    fn new(grid: &'a [Cells; GRID_SIZE], target: GridIterTarget, index: usize) -> Self {
        Self {
            grid,
            target,
            index,
            current: 0,
            end: match target {
                GridIterTarget::Rows => grid[0].len(),
                GridIterTarget::Columns => grid.len(),
            },
        }
    }

    fn get(&self, current: usize) -> &'a Cell {
        match self.target {
            GridIterTarget::Rows => {
                &self.grid[self.index][current]
            },
            GridIterTarget::Columns => {
                &self.grid[current][self.index]
            },
        }
    }
}

impl<'a> Iterator for GridCellIter<'a> {
    type Item = &'a Cell;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current >= self.end {
            return None;
        }

        let cell = self.get(self.current);

        self.current += 1;
        Some(cell)
    }
}

impl<'a> DoubleEndedIterator for GridCellIter<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.current >= self.end {
            return None;
        }

        let cell = self.get(self.end - 1);

        self.end -= 1;
        Some(cell)
    }
}

#[derive(Debug)]
pub struct Grid([Cells; GRID_SIZE]);

impl Index<usize> for Grid {
    type Output = Cells;

    fn index(&self, index: usize) -> &Self::Output {
        self.0.index(index)
    }
}

impl IndexMut<usize> for Grid {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        self.0.index_mut(index)
    }
}

impl Grid {
    pub fn new() -> Grid {
        Grid([Cells::default(); GRID_SIZE])
    }

    pub fn random_walls() -> Grid {
        let mut grid = [Cells::default(); GRID_SIZE];
        for row in &mut grid {
            for cell in row {
                *cell = random();
            }
        }
        Grid(grid)
    }

    /// Removes the wall between two adjacent cells
    pub fn open_between(&mut self, (row1, col1): (usize, usize), (row2, col2): (usize, usize)) {
        match (row2 as isize - row1 as isize, col2 as isize - col1 as isize) {
            (-1, 0) => {
                self[row1][col1].north = Wall::Open;
                self[row2][col2].south = Wall::Open;
            },
            (0, 1) => {
                self[row1][col1].east = Wall::Open;
                self[row2][col2].west = Wall::Open;
            },
            (1, 0) => {
                self[row1][col1].south = Wall::Open;
                self[row2][col2].north = Wall::Open;
            },
            (0, -1) => {
                self[row1][col1].west = Wall::Open;
                self[row2][col2].east = Wall::Open;
            },
            _ => unreachable!("Cells were not adjacent"),
        }
    }

    /// Returns the cell positions adjacent in the four cardinal directions to the given cell
    /// position. Only returns valid cell positions.
    pub fn adjacent_cells(&self, (row, col): (usize, usize)) -> Vec<(usize, usize)> {
        let mut positions = Vec::new();
        if row > 0 {
            // north
            positions.push((row - 1, col));
        }
        if col < self.row_size()-1 {
            // east
            positions.push((row, col + 1));
        }
        if row < self.col_size()-1 {
            // south
            positions.push((row + 1, col));
        }
        if col > 0 {
            // west
            positions.push((row, col - 1));
        }
        positions
    }

    /// Gets the cell at the given position
    pub fn get(&self, (row, col): (usize, usize)) -> &Cell {
        &self[row][col]
    }

    /// Returns the size of each row
    pub fn row_size(&self) -> usize {
        self.0[0].len()
    }

    /// Returns the size of each column
    pub fn col_size(&self) -> usize {
        self.0.len()
    }

    /// Returns the first row
    pub fn first_row(&self) -> GridCellIter {
        self.rows().next().unwrap()
    }

    /// Returns the last row
    pub fn last_row(&self) -> GridCellIter {
        self.rows().next_back().unwrap()
    }

    /// Returns the first column
    pub fn first_col(&self) -> GridCellIter {
        self.cols().next().unwrap()
    }

    /// Returns the last column
    pub fn last_col(&self) -> GridCellIter {
        self.cols().next_back().unwrap()
    }

    /// Returns an iterator over each row
    pub fn rows(&self) -> GridIter {
        GridIter::new(&self.0, GridIterTarget::Rows)
    }

    /// Returns an iterator over each row
    pub fn cols(&self) -> GridIter {
        GridIter::new(&self.0, GridIterTarget::Columns)
    }
}
<commit_msg>Increasing grid size to 12<commit_after>use std::ops::{Index, IndexMut};

use turtle::random;

use cell::Cell;
use wall::Wall;

const GRID_SIZE: usize = 12;

/// A row or column of cells
pub type Cells = [Cell; GRID_SIZE];

/// Used to determine whether to iterate over rows or columns
#[derive(Clone, Copy)]
enum GridIterTarget {
    Rows,
    Columns,
}

pub struct GridIter<'a> {
    grid: &'a [Cells; GRID_SIZE],
    target: GridIterTarget,
    current: usize,
    end: usize,
}

impl<'a> GridIter<'a> {
    fn new(grid: &'a [Cells; GRID_SIZE], target: GridIterTarget) -> Self {
        Self {
            grid,
            target,
            current: 0,
            end: match target {
                GridIterTarget::Rows => grid.len(),
                GridIterTarget::Columns => grid[0].len(),
            },
        }
    }
}

impl<'a> Iterator for GridIter<'a> {
    type Item = GridCellIter<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current >= self.end {
            return None;
        }

        let iter = GridCellIter::new(
            self.grid,
            self.target,
            self.current
        );

        self.current += 1;
        Some(iter)
    }
}

impl<'a> DoubleEndedIterator for GridIter<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.current >= self.end {
            return None;
        }

        let iter = GridCellIter::new(
            self.grid,
            self.target,
            self.end - 1
        );

        self.end -= 1;
        Some(iter)
    }
}

pub struct GridCellIter<'a> {
    grid: &'a [Cells; GRID_SIZE],
    target: GridIterTarget,
    /// The row or column being iterated over
    index: usize,
    /// The current position in the row or column being iterated over
    current: usize,
    // Index of the item just after the last item in the row or column being iterated over
    end: usize,
}

impl<'a> GridCellIter<'a> {
    fn new(grid: &'a [Cells; GRID_SIZE], target: GridIterTarget, index: usize) -> Self {
        Self {
            grid,
            target,
            index,
            current: 0,
            end: match target {
                GridIterTarget::Rows => grid[0].len(),
                GridIterTarget::Columns => grid.len(),
            },
        }
    }

    fn get(&self, current: usize) -> &'a Cell {
        match self.target {
            GridIterTarget::Rows => {
                &self.grid[self.index][current]
            },
            GridIterTarget::Columns => {
                &self.grid[current][self.index]
            },
        }
    }
}

impl<'a> Iterator for GridCellIter<'a> {
    type Item = &'a Cell;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current >= self.end {
            return None;
        }

        let cell = self.get(self.current);

        self.current += 1;
        Some(cell)
    }
}

impl<'a> DoubleEndedIterator for GridCellIter<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.current >= self.end {
            return None;
        }

        let cell = self.get(self.end - 1);

        self.end -= 1;
        Some(cell)
    }
}

#[derive(Debug)]
pub struct Grid([Cells; GRID_SIZE]);

impl Index<usize> for Grid {
    type Output = Cells;

    fn index(&self, index: usize) -> &Self::Output {
        self.0.index(index)
    }
}

impl IndexMut<usize> for Grid {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        self.0.index_mut(index)
    }
}

impl Grid {
    pub fn new() -> Grid {
        Grid([Cells::default(); GRID_SIZE])
    }

    pub fn random_walls() -> Grid {
        let mut grid = [Cells::default(); GRID_SIZE];
        for row in &mut grid {
            for cell in row {
                *cell = random();
            }
        }
        Grid(grid)
    }

    /// Removes the wall between two adjacent cells
    pub fn open_between(&mut self, (row1, col1): (usize, usize), (row2, col2): (usize, usize)) {
        match (row2 as isize - row1 as isize, col2 as isize - col1 as isize) {
            (-1, 0) => {
                self[row1][col1].north = Wall::Open;
                self[row2][col2].south = Wall::Open;
            },
            (0, 1) => {
                self[row1][col1].east = Wall::Open;
                self[row2][col2].west = Wall::Open;
            },
            (1, 0) => {
                self[row1][col1].south = Wall::Open;
                self[row2][col2].north = Wall::Open;
            },
            (0, -1) => {
                self[row1][col1].west = Wall::Open;
                self[row2][col2].east = Wall::Open;
            },
            _ => unreachable!("Cells were not adjacent"),
        }
    }

    /// Returns the cell positions adjacent in the four cardinal directions to the given cell
    /// position. Only returns valid cell positions.
    pub fn adjacent_cells(&self, (row, col): (usize, usize)) -> Vec<(usize, usize)> {
        let mut positions = Vec::new();
        if row > 0 {
            // north
            positions.push((row - 1, col));
        }
        if col < self.row_size()-1 {
            // east
            positions.push((row, col + 1));
        }
        if row < self.col_size()-1 {
            // south
            positions.push((row + 1, col));
        }
        if col > 0 {
            // west
            positions.push((row, col - 1));
        }
        positions
    }

    /// Gets the cell at the given position
    pub fn get(&self, (row, col): (usize, usize)) -> &Cell {
        &self[row][col]
    }

    /// Returns the size of each row
    pub fn row_size(&self) -> usize {
        self.0[0].len()
    }

    /// Returns the size of each column
    pub fn col_size(&self) -> usize {
        self.0.len()
    }

    /// Returns the first row
    pub fn first_row(&self) -> GridCellIter {
        self.rows().next().unwrap()
    }

    /// Returns the last row
    pub fn last_row(&self) -> GridCellIter {
        self.rows().next_back().unwrap()
    }

    /// Returns the first column
    pub fn first_col(&self) -> GridCellIter {
        self.cols().next().unwrap()
    }

    /// Returns the last column
    pub fn last_col(&self) -> GridCellIter {
        self.cols().next_back().unwrap()
    }

    /// Returns an iterator over each row
    pub fn rows(&self) -> GridIter {
        GridIter::new(&self.0, GridIterTarget::Rows)
    }

    /// Returns an iterator over each row
    pub fn cols(&self) -> GridIter {
        GridIter::new(&self.0, GridIterTarget::Columns)
    }
}
<|endoftext|>


<commit_before>use rustc_serialize::json;

use common::{Nullable, Date};
use cookie;
use time;

#[derive(Debug)]
pub enum WebDriverResponse {
    CloseWindow(CloseWindowResponse),
    Cookie(CookieResponse),
    DeleteSession,
    ElementRect(ElementRectResponse),
    Generic(ValueResponse),
    NewSession(NewSessionResponse),
    Timeouts(TimeoutsResponse),
    Void,
    WindowPosition(WindowPositionResponse),
    WindowSize(WindowSizeResponse),
}

impl WebDriverResponse {
    pub fn to_json_string(self) -> String {
        match self {
            WebDriverResponse::CloseWindow(x) => json::encode(&x),
            WebDriverResponse::Cookie(x) => json::encode(&x),
            WebDriverResponse::DeleteSession => Ok("{}".to_string()),
            WebDriverResponse::ElementRect(x) => json::encode(&x),
            WebDriverResponse::Generic(x) => json::encode(&x),
            WebDriverResponse::NewSession(x) => json::encode(&x),
            WebDriverResponse::Timeouts(x) => json::encode(&x),
            WebDriverResponse::Void => Ok("{}".to_string()),
            WebDriverResponse::WindowPosition(x) => json::encode(&x),
            WebDriverResponse::WindowSize(x) => json::encode(&x),
        }.unwrap()
    }
}

#[derive(RustcEncodable, Debug)]
pub struct CloseWindowResponse {
    pub window_handles: Vec<String>,
}

impl CloseWindowResponse {
    pub fn new(handles: Vec<String>) -> CloseWindowResponse {
        CloseWindowResponse { window_handles: handles }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct NewSessionResponse {
    pub sessionId: String,
    pub value: json::Json
}

impl NewSessionResponse {
    pub fn new(session_id: String, value: json::Json) -> NewSessionResponse {
        NewSessionResponse {
            value: value,
            sessionId: session_id
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct TimeoutsResponse {
    pub script: u64,
    pub pageLoad: u64,
    pub implicit: u64,
}

#[derive(RustcEncodable, Debug)]
pub struct ValueResponse {
    pub value: json::Json
}

impl ValueResponse {
    pub fn new(value: json::Json) -> ValueResponse {
        ValueResponse {
            value: value
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct WindowSizeResponse {
    pub width: u64,
    pub height: u64
}

impl WindowSizeResponse {
    pub fn new(width: u64, height: u64) -> WindowSizeResponse {
        WindowSizeResponse {
            width: width,
            height: height
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct WindowPositionResponse {
    pub x: i64,
    pub y: i64,
}

impl WindowPositionResponse {
    pub fn new(x: i64, y: i64) -> WindowPositionResponse {
        WindowPositionResponse { x: x, y: y }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct ElementRectResponse {
    pub x: f64,
    pub y: f64,
    pub width: f64,
    pub height: f64
}

impl ElementRectResponse {
    pub fn new(x: f64, y: f64, width: f64, height: f64) -> ElementRectResponse {
        ElementRectResponse {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

//TODO: some of these fields are probably supposed to be optional
#[derive(RustcEncodable, PartialEq, Debug, Clone)]
pub struct Cookie {
    pub name: String,
    pub value: String,
    pub path: Nullable<String>,
    pub domain: Nullable<String>,
    pub expiry: Nullable<Date>,
    pub secure: bool,
    pub httpOnly: bool
}

impl Cookie {
    pub fn new(name: String, value: String, path: Nullable<String>, domain: Nullable<String>,
               expiry: Nullable<Date>, secure: bool, http_only: bool) -> Cookie {
        Cookie {
            name: name,
            value: value,
            path: path,
            domain: domain,
            expiry: expiry,
            secure: secure,
            httpOnly: http_only
        }
    }
}

impl Into<cookie::Cookie<'static>> for Cookie {
    fn into(self) -> cookie::Cookie<'static> {
        let cookie = cookie::Cookie::build(self.name, self.value)
            .secure(self.secure)
            .http_only(self.httpOnly);
        let cookie = match self.domain {
            Nullable::Value(domain) => cookie.domain(domain),
            Nullable::Null => cookie,
        };
        let cookie = match self.path {
            Nullable::Value(path) => cookie.path(path),
            Nullable::Null => cookie,
        };
        let cookie = match self.expiry {
            Nullable::Value(Date(expiry)) => {
                cookie.expires(time::at(time::Timespec::new(expiry as i64, 0)))
            },
            Nullable::Null => cookie,
        };
        cookie.finish()
    }
}

#[derive(RustcEncodable, Debug)]
pub struct CookieResponse {
    pub value: Vec<Cookie>
}

impl CookieResponse {
    pub fn new(value: Vec<Cookie>) -> CookieResponse {
        CookieResponse {
            value: value
        }
    }
}
<commit_msg>Wrap responses in a 'value' key.<commit_after>use rustc_serialize::json;

use common::{Nullable, Date};
use cookie;
use time;

#[derive(Debug)]
pub enum WebDriverResponse {
    CloseWindow(CloseWindowResponse),
    Cookie(CookieResponse),
    DeleteSession,
    ElementRect(ElementRectResponse),
    Generic(ValueResponse),
    NewSession(NewSessionResponse),
    Timeouts(TimeoutsResponse),
    Void,
    WindowPosition(WindowPositionResponse),
    WindowSize(WindowSizeResponse),
}

impl WebDriverResponse {
    pub fn to_json_string(self) -> String {
        let obj = match self {
            WebDriverResponse::CloseWindow(ref x) => json::encode(x),
            WebDriverResponse::Cookie(ref x) => json::encode(x),
            WebDriverResponse::DeleteSession => Ok("{}".to_string()),
            WebDriverResponse::ElementRect(ref x) => json::encode(x),
            WebDriverResponse::Generic(ref x) => json::encode(x),
            WebDriverResponse::NewSession(ref x) => json::encode(x),
            WebDriverResponse::Timeouts(ref x) => json::encode(x),
            WebDriverResponse::Void => Ok("{}".to_string()),
            WebDriverResponse::WindowPosition(ref x) => json::encode(x),
            WebDriverResponse::WindowSize(ref x) => json::encode(x),
        }.unwrap();

        match self {
            WebDriverResponse::Generic(_) => obj,
            _ => {
                let mut data = String::with_capacity(11 + obj.len());
                data.push_str("{\"value\": ");
                data.push_str(&*obj);
                data.push_str("}");
                data
            }
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct CloseWindowResponse {
    pub window_handles: Vec<String>,
}

impl CloseWindowResponse {
    pub fn new(handles: Vec<String>) -> CloseWindowResponse {
        CloseWindowResponse { window_handles: handles }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct NewSessionResponse {
    pub sessionId: String,
    pub value: json::Json
}

impl NewSessionResponse {
    pub fn new(session_id: String, value: json::Json) -> NewSessionResponse {
        NewSessionResponse {
            value: value,
            sessionId: session_id
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct TimeoutsResponse {
    pub script: u64,
    pub pageLoad: u64,
    pub implicit: u64,
}

#[derive(RustcEncodable, Debug)]
pub struct ValueResponse {
    pub value: json::Json
}

impl ValueResponse {
    pub fn new(value: json::Json) -> ValueResponse {
        ValueResponse {
            value: value
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct WindowSizeResponse {
    pub width: u64,
    pub height: u64
}

impl WindowSizeResponse {
    pub fn new(width: u64, height: u64) -> WindowSizeResponse {
        WindowSizeResponse {
            width: width,
            height: height
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct WindowPositionResponse {
    pub x: i64,
    pub y: i64,
}

impl WindowPositionResponse {
    pub fn new(x: i64, y: i64) -> WindowPositionResponse {
        WindowPositionResponse { x: x, y: y }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct ElementRectResponse {
    pub x: f64,
    pub y: f64,
    pub width: f64,
    pub height: f64
}

impl ElementRectResponse {
    pub fn new(x: f64, y: f64, width: f64, height: f64) -> ElementRectResponse {
        ElementRectResponse {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

//TODO: some of these fields are probably supposed to be optional
#[derive(RustcEncodable, PartialEq, Debug, Clone)]
pub struct Cookie {
    pub name: String,
    pub value: String,
    pub path: Nullable<String>,
    pub domain: Nullable<String>,
    pub expiry: Nullable<Date>,
    pub secure: bool,
    pub httpOnly: bool
}

impl Cookie {
    pub fn new(name: String, value: String, path: Nullable<String>, domain: Nullable<String>,
               expiry: Nullable<Date>, secure: bool, http_only: bool) -> Cookie {
        Cookie {
            name: name,
            value: value,
            path: path,
            domain: domain,
            expiry: expiry,
            secure: secure,
            httpOnly: http_only
        }
    }
}

impl Into<cookie::Cookie<'static>> for Cookie {
    fn into(self) -> cookie::Cookie<'static> {
        let cookie = cookie::Cookie::build(self.name, self.value)
            .secure(self.secure)
            .http_only(self.httpOnly);
        let cookie = match self.domain {
            Nullable::Value(domain) => cookie.domain(domain),
            Nullable::Null => cookie,
        };
        let cookie = match self.path {
            Nullable::Value(path) => cookie.path(path),
            Nullable::Null => cookie,
        };
        let cookie = match self.expiry {
            Nullable::Value(Date(expiry)) => {
                cookie.expires(time::at(time::Timespec::new(expiry as i64, 0)))
            },
            Nullable::Null => cookie,
        };
        cookie.finish()
    }
}

#[derive(RustcEncodable, Debug)]
pub struct CookieResponse {
    pub value: Vec<Cookie>
}

impl CookieResponse {
    pub fn new(value: Vec<Cookie>) -> CookieResponse {
        CookieResponse {
            value: value
        }
    }
}
<|endoftext|>


<commit_before>//! Actix web diesel example
//!
//! Diesel does not support tokio, so we have to run it in separate threads.
//! Actix supports sync actors by default, so we going to create sync actor that will
//! use diesel. Technically sync actors are worker style actors, multiple of them
//! can run in parallele and process messages from same queue.
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate diesel;
extern crate uuid;
extern crate futures;
extern crate actix;
extern crate actix_web;
extern crate env_logger;

use actix::prelude::*;
use actix_web::*;
use futures::future::{Future, ok};
use diesel::Connection;
use diesel::sqlite::SqliteConnection;
use diesel::prelude::*;

mod models;
mod schema;

/// State with DbExecutor address
struct State {
    db: SyncAddress<DbExecutor>,
}

/// Async request handler
fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>> {
    let name = &req.match_info()["name"];

    Box::new(
        req.state().db.call_fut(CreatePerson{name: name.to_owned()})
            .and_then(|res| {
                match res {
                    Ok(person) => ok(httpcodes::HTTPOk.build().json(person).unwrap()),
                    Err(_) => ok(httpcodes::HTTPInternalServerError.response())
                }
            })
            .map_err(|e| error::ErrorInternalServerError(e).into()))
}

/// This is db executor actor. We are going to run 3 of them in parallele.
struct DbExecutor(SqliteConnection);

/// This is only message that this actor can handle, but it is easy to extend number of
/// messages.
struct CreatePerson {
    name: String,
}

impl ResponseType for CreatePerson {
    type Item = models::User;
    type Error = Error;
}

impl Actor for DbExecutor {
    type Context = SyncContext<Self>;
}

impl Handler<CreatePerson> for DbExecutor {
    fn handle(&mut self, msg: CreatePerson, _: &mut Self::Context)
              -> Response<Self, CreatePerson>
    {
        use self::schema::users::dsl::*;

        let uuid = format!("{}", uuid::Uuid::new_v4());
        let new_user = models::NewUser {
            id: &uuid,
            name: &msg.name,
        };

        diesel::insert_into(users)
            .values(&new_user)
            .execute(&self.0)
            .expect("Error inserting person");

        let mut items = users
            .filter(id.eq(&uuid))
            .load::<models::User>(&self.0)
            .expect("Error loading person");

        Self::reply(items.pop().unwrap())
    }
}

fn main() {
    ::std::env::set_var("RUST_LOG", "actix_web=info");
    let _ = env_logger::init();
    let sys = actix::System::new("diesel-example");

    // Start db executor actors
    let addr = SyncArbiter::start(3, || {
        DbExecutor(SqliteConnection::establish("test.db").unwrap())
    });

    // Start http server
    HttpServer::new(move || {
        Application::with_state(State{db: addr.clone()})
            // enable logger
            .middleware(middlewares::Logger::default())
            .resource("/{name}", |r| r.method(Method::GET).a(index))})
        .bind("127.0.0.1:8080").unwrap()
        .start().unwrap();

    println!("Started http server: 127.0.0.1:8080");
    let _ = sys.run();
}
<commit_msg>better name<commit_after>//! Actix web diesel example
//!
//! Diesel does not support tokio, so we have to run it in separate threads.
//! Actix supports sync actors by default, so we going to create sync actor that will
//! use diesel. Technically sync actors are worker style actors, multiple of them
//! can run in parallele and process messages from same queue.
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate diesel;
extern crate uuid;
extern crate futures;
extern crate actix;
extern crate actix_web;
extern crate env_logger;

use actix_web::*;
use actix::prelude::*;
use diesel::prelude::*;
use futures::future::{Future, ok};

mod models;
mod schema;

/// State with DbExecutor address
struct State {
    db: SyncAddress<DbExecutor>,
}

/// Async request handler
fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>> {
    let name = &req.match_info()["name"];

    Box::new(
        req.state().db.call_fut(CreateUser{name: name.to_owned()})
            .and_then(|res| {
                match res {
                    Ok(person) => ok(httpcodes::HTTPOk.build().json(person).unwrap()),
                    Err(_) => ok(httpcodes::HTTPInternalServerError.response())
                }
            })
            .map_err(|e| error::ErrorInternalServerError(e).into()))
}

/// This is db executor actor. We are going to run 3 of them in parallele.
struct DbExecutor(SqliteConnection);

/// This is only message that this actor can handle, but it is easy to extend number of
/// messages.
struct CreateUser {
    name: String,
}

impl ResponseType for CreateUser {
    type Item = models::User;
    type Error = Error;
}

impl Actor for DbExecutor {
    type Context = SyncContext<Self>;
}

impl Handler<CreateUser> for DbExecutor {
    fn handle(&mut self, msg: CreateUser, _: &mut Self::Context)
              -> Response<Self, CreateUser>
    {
        use self::schema::users::dsl::*;

        let uuid = format!("{}", uuid::Uuid::new_v4());
        let new_user = models::NewUser {
            id: &uuid,
            name: &msg.name,
        };

        diesel::insert_into(users)
            .values(&new_user)
            .execute(&self.0)
            .expect("Error inserting person");

        let mut items = users
            .filter(id.eq(&uuid))
            .load::<models::User>(&self.0)
            .expect("Error loading person");

        Self::reply(items.pop().unwrap())
    }
}

fn main() {
    ::std::env::set_var("RUST_LOG", "actix_web=info");
    let _ = env_logger::init();
    let sys = actix::System::new("diesel-example");

    // Start db executor actors
    let addr = SyncArbiter::start(3, || {
        DbExecutor(SqliteConnection::establish("test.db").unwrap())
    });

    // Start http server
    HttpServer::new(move || {
        Application::with_state(State{db: addr.clone()})
            // enable logger
            .middleware(middlewares::Logger::default())
            .resource("/{name}", |r| r.method(Method::GET).a(index))})
        .bind("127.0.0.1:8080").unwrap()
        .start().unwrap();

    println!("Started http server: 127.0.0.1:8080");
    let _ = sys.run();
}
<|endoftext|>


<commit_before>extern crate gcc;
extern crate pkg_config;

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

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    // Use the installed libcares if it is available.
    if pkg_config::Config::new()
        .atleast_version("1.11.0")
            .find("libcares")
            .is_ok() {
        return
    }

    // MSVC builds are different.
    let target = env::var("TARGET").unwrap();
    if target.contains("msvc") {
        build_msvc(&target);
        return
    }

    // Set up compiler options.
    let mut cflags = env::var("CFLAGS").unwrap_or(String::new());
    if target.contains("i686") {
        cflags.push_str(" -m32");
    } else if target.contains("x86_64") {
        cflags.push_str(" -m64");
    }
    if !target.contains("i686") {
        cflags.push_str(" -fPIC");
    }

    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let _ = fs::create_dir(&build);

    let mut config_opts = Vec::new();
    config_opts.push("--enable-static=yes".to_string());
    config_opts.push("--enable-shared=no".to_string());
    config_opts.push("--enable-optimize".to_string());
    config_opts.push(format!("--prefix={}", dst.display()));

    // Prepare.
    let src = env::current_dir().unwrap();
    run(Command::new("sh")
                .current_dir(&src.join("c-ares"))
                .arg("buildconf"));
    run(Command::new("sh")
                .env("CFLAGS", &cflags)
                .current_dir(&build)
                .arg("-c")
                .arg(&format!("{} {}", src.join("c-ares/configure").display(),
                              config_opts.join(" "))));

    // Compile.
    run(Command::new(make())
                .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap()))
                .current_dir(&build));

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/.libs", build.display());
    println!("cargo:rustc-link-lib=static=cares");
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(t!(cmd.status()).success());
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn build_msvc(target: &str) {
    // Prepare.
    let src = env::current_dir().unwrap();
    let c_ares_dir = &src.join("c-ares");
    run(Command::new("cmd")
                .current_dir(c_ares_dir)
                .arg("/c")
                .arg("buildconf.bat"));

    // Compile.
    let mut cmd = gcc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "CFG=lib-release", "c-ares"]);
    run(&mut cmd);

    // Install library.
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let mut cmd = gcc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "/a", "CFG=lib-release", "install"]);
    cmd.env("INSTALL_DIR", format!("{}", build.display()));
    run(&mut cmd);

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/lib", build.display());
    println!("cargo:rustc-link-lib=static=libcares");
}
<commit_msg>Avoid requiring a C++11 compiler<commit_after>extern crate gcc;
extern crate pkg_config;

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

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    // Use the installed libcares if it is available.
    if pkg_config::Config::new()
        .atleast_version("1.11.0")
            .find("libcares")
            .is_ok() {
        return
    }

    // MSVC builds are different.
    let target = env::var("TARGET").unwrap();
    if target.contains("msvc") {
        build_msvc(&target);
        return
    }

    // Set up compiler options.
    let mut cflags = env::var("CFLAGS").unwrap_or(String::new());
    if target.contains("i686") {
        cflags.push_str(" -m32");
    } else if target.contains("x86_64") {
        cflags.push_str(" -m64");
    }
    if !target.contains("i686") {
        cflags.push_str(" -fPIC");
    }

    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let _ = fs::create_dir(&build);

    let mut config_opts = Vec::new();
    config_opts.push("--disable-tests".to_string());
    config_opts.push("--enable-static=yes".to_string());
    config_opts.push("--enable-shared=no".to_string());
    config_opts.push("--enable-optimize".to_string());
    config_opts.push(format!("--prefix={}", dst.display()));

    // Prepare.
    let src = env::current_dir().unwrap();
    run(Command::new("sh")
                .current_dir(&src.join("c-ares"))
                .arg("buildconf"));
    run(Command::new("sh")
                .env("CFLAGS", &cflags)
                .current_dir(&build)
                .arg("-c")
                .arg(&format!("{} {}", src.join("c-ares/configure").display(),
                              config_opts.join(" "))));

    // Compile.
    run(Command::new(make())
                .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap()))
                .current_dir(&build));

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/.libs", build.display());
    println!("cargo:rustc-link-lib=static=cares");
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(t!(cmd.status()).success());
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn build_msvc(target: &str) {
    // Prepare.
    let src = env::current_dir().unwrap();
    let c_ares_dir = &src.join("c-ares");
    run(Command::new("cmd")
                .current_dir(c_ares_dir)
                .arg("/c")
                .arg("buildconf.bat"));

    // Compile.
    let mut cmd = gcc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "CFG=lib-release", "c-ares"]);
    run(&mut cmd);

    // Install library.
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let mut cmd = gcc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "/a", "CFG=lib-release", "install"]);
    cmd.env("INSTALL_DIR", format!("{}", build.display()));
    run(&mut cmd);

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/lib", build.display());
    println!("cargo:rustc-link-lib=static=libcares");
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate serde_json;
extern crate jmespath;

use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::process::exit;

use clap::{Arg, App};
use jmespath::RcVar;
use jmespath::{Variable, Expression};

macro_rules! die(
    ($msg:expr) => (
        match writeln!(&mut ::std::io::stderr(), "{}", $msg) {
            Ok(_) => exit(1),
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
);

fn main() {
    let matches = App::new("jp")
        .version("1.0")
        .author("Michael Dowling <mtdowling@gmail.com>")
        .about("JMESPath command line interface")
        .arg(Arg::with_name("filename")
            .help("Read input JSON from a file instead of stdin.")
            .short("f")
            .takes_value(true)
            .long("filename"))
        .arg(Arg::with_name("unquoted")
            .help("If the final result is a string, it will be printed without quotes.")
            .short("u")
            .long("unquoted")
            .multiple(false))
        .arg(Arg::with_name("ast")
            .help("Only print the AST of the parsed expression.  Do not rely on this output, \
                  only useful for debugging purposes.")
            .long("ast")
            .multiple(false))
        .arg(Arg::with_name("expr-file")
            .help("Read JMESPath expression from the specified file.")
            .short("e")
            .takes_value(true)
            .long("expr-file")
            .conflicts_with("expression")
            .required(true))
        .arg(Arg::with_name("expression")
            .help("JMESPath expression to evaluate")
            .index(1)
            .conflicts_with("expr-file")
            .required(true))
        .get_matches();

    let file_expression = matches.value_of("expr-file")
        .map(|f| read_file("expression", f));

    let expr = if let Some(ref e) = file_expression {
        Expression::new(e)
    } else {
        Expression::new(matches.value_of("expression").unwrap())
    }.map_err(|e| die!(e.to_string())).unwrap();

    if matches.is_present("ast") {
        println!("{:#?}", expr.as_ast());
        exit(0);
    }

    let json = get_json(matches.value_of("filename"));

    match expr.search(json) {
        Err(e) => die!(e.to_string()),
        Ok(result) => show_result(result, matches.is_present("unquoted"))
    }
}

fn show_result(result: RcVar, unquoted: bool) {
    if unquoted && result.is_string() {
        println!("{}", result.as_string().unwrap());
    } else {
        let mut out = io::stdout();
        serde_json::to_writer_pretty(&mut out, &result)
            .map(|_| out.write(&['\n' as u8]))
            .map_err(|e| die!(format!("Error converting result to string: {}", e)))
            .ok();
    }
}

fn read_file(label: &str, filename: &str) -> String {
    match File::open(filename) {
        Err(e) => die!(format!("Error opening {} file at {}: {}", label, filename, e)),
        Ok(mut file) => {
            let mut buffer = String::new();
            file.read_to_string(&mut buffer)
                .map_err(|e| die!(format!("Error reading {} from {}: {}", label, filename, e)))
                .map(|_| buffer)
                .unwrap()
        }
    }
}

fn get_json(filename: Option<&str>) -> Variable {
    let buffer = match filename {
        Some(f) => read_file("JSON", f),
        None => {
            let mut buffer = String::new();
            match io::stdin().read_to_string(&mut buffer) {
                Ok(_) => buffer,
                Err(e) => die!(format!("Error reading JSON from stdin: {}", e))
            }
        }
    };
    Variable::from_json(&buffer)
        .map_err(|e| die!(format!("Error parsing JSON: {}", e)))
        .unwrap()
}
<commit_msg>Using faster search in CLI<commit_after>extern crate clap;
extern crate serde_json;
extern crate jmespath;

use std::rc::Rc;
use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::process::exit;

use clap::{Arg, App};
use jmespath::RcVar;
use jmespath::{Variable, Expression};

macro_rules! die(
    ($msg:expr) => (
        match writeln!(&mut ::std::io::stderr(), "{}", $msg) {
            Ok(_) => exit(1),
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
);

fn main() {
    let matches = App::new("jp")
        .version("1.0")
        .author("Michael Dowling <mtdowling@gmail.com>")
        .about("JMESPath command line interface")
        .arg(Arg::with_name("filename")
            .help("Read input JSON from a file instead of stdin.")
            .short("f")
            .takes_value(true)
            .long("filename"))
        .arg(Arg::with_name("unquoted")
            .help("If the final result is a string, it will be printed without quotes.")
            .short("u")
            .long("unquoted")
            .multiple(false))
        .arg(Arg::with_name("ast")
            .help("Only print the AST of the parsed expression.  Do not rely on this output, \
                  only useful for debugging purposes.")
            .long("ast")
            .multiple(false))
        .arg(Arg::with_name("expr-file")
            .help("Read JMESPath expression from the specified file.")
            .short("e")
            .takes_value(true)
            .long("expr-file")
            .conflicts_with("expression")
            .required(true))
        .arg(Arg::with_name("expression")
            .help("JMESPath expression to evaluate")
            .index(1)
            .conflicts_with("expr-file")
            .required(true))
        .get_matches();

    let file_expression = matches.value_of("expr-file")
        .map(|f| read_file("expression", f));

    let expr = if let Some(ref e) = file_expression {
        Expression::new(e)
    } else {
        Expression::new(matches.value_of("expression").unwrap())
    }.map_err(|e| die!(e.to_string())).unwrap();

    if matches.is_present("ast") {
        println!("{:#?}", expr.as_ast());
        exit(0);
    }

    let json = Rc::new(get_json(matches.value_of("filename")));

    match expr.search_variable(&json) {
        Err(e) => die!(e.to_string()),
        Ok(result) => show_result(result, matches.is_present("unquoted"))
    }
}

fn show_result(result: RcVar, unquoted: bool) {
    if unquoted && result.is_string() {
        println!("{}", result.as_string().unwrap());
    } else {
        let mut out = io::stdout();
        serde_json::to_writer_pretty(&mut out, &result)
            .map(|_| out.write(&['\n' as u8]))
            .map_err(|e| die!(format!("Error converting result to string: {}", e)))
            .ok();
    }
}

fn read_file(label: &str, filename: &str) -> String {
    match File::open(filename) {
        Err(e) => die!(format!("Error opening {} file at {}: {}", label, filename, e)),
        Ok(mut file) => {
            let mut buffer = String::new();
            file.read_to_string(&mut buffer)
                .map_err(|e| die!(format!("Error reading {} from {}: {}", label, filename, e)))
                .map(|_| buffer)
                .unwrap()
        }
    }
}

fn get_json(filename: Option<&str>) -> Variable {
    let buffer = match filename {
        Some(f) => read_file("JSON", f),
        None => {
            let mut buffer = String::new();
            match io::stdin().read_to_string(&mut buffer) {
                Ok(_) => buffer,
                Err(e) => die!(format!("Error reading JSON from stdin: {}", e))
            }
        }
    };
    Variable::from_json(&buffer)
        .map_err(|e| die!(format!("Error parsing JSON: {}", e)))
        .unwrap()
}
<|endoftext|>


<commit_before>use super::error::{Error, Result};
use super::generate::parse_grammar::GrammarJSON;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use which::which;

pub fn get_grammar_name(src_dir: &Path) -> Result<String> {
    let grammar_json_path = src_dir.join("grammar.json");
    let grammar_json = fs::read_to_string(&grammar_json_path).map_err(Error::wrap(|| {
        format!("Failed to read grammar file {:?}", grammar_json_path)
    }))?;
    let grammar: GrammarJSON = serde_json::from_str(&grammar_json).map_err(Error::wrap(|| {
        format!("Failed to parse grammar file {:?}", grammar_json_path)
    }))?;
    Ok(grammar.name)
}

pub fn compile_language_to_wasm(language_dir: &Path, force_docker: bool) -> Result<()> {
    let src_dir = language_dir.join("src");
    let grammar_name = get_grammar_name(&src_dir)?;
    let output_filename = format!("tree-sitter-{}.wasm", grammar_name);

    let mut command;
    if !force_docker {
        let emcc_path = get_emcc_path();
        if emcc_path.is_ok() {
            command = Command::new(emcc_path.unwrap());
            command.current_dir(&language_dir);
        } else {
            return Err(emcc_path.unwrap_err());
        }
    } else if Command::new("docker").output().is_ok() {
        command = Command::new("docker");
        command.args(&["run", "--rm"]);

        // Mount the parser directory as a volume
        let mut volume_string;
        if let (Some(parent), Some(filename)) = (language_dir.parent(), language_dir.file_name()) {
            volume_string = OsString::from(parent);
            volume_string.push(":/src:Z");
            command.arg("--workdir");
            command.arg(&Path::new("/src").join(filename));
        } else {
            volume_string = OsString::from(language_dir);
            volume_string.push(":/src:Z");
            command.args(&["--workdir", "/src"]);
        }

        command.args(&[OsStr::new("--volume"), &volume_string]);

        // Get the current user id so that files created in the docker container will have
        // the same owner.
        if cfg!(unix) {
            let user_id_output = Command::new("id")
                .arg("-u")
                .output()
                .map_err(Error::wrap(|| "Failed to get get current user id"))?;
            let user_id = String::from_utf8_lossy(&user_id_output.stdout);
            let user_id = user_id.trim();
            command.args(&["--user", user_id]);
        }

        // Run `emcc` in a container using the `emscripten-slim` image
        command.args(&["emscripten/emsdk", "emcc"]);
    } else {
        return Error::err(
            "You must have either emcc or docker on your PATH to run this command".to_string(),
        );
    }

    command.args(&[
        "-o",
        &output_filename,
        "-Os",
        "-s",
        "WASM=1",
        "-s",
        "SIDE_MODULE=1",
        "-s",
        "TOTAL_MEMORY=33554432",
        "-s",
        "NODEJS_CATCH_EXIT=0",
        "-s",
        &format!("EXPORTED_FUNCTIONS=[\"_tree_sitter_{}\"]", grammar_name),
        "-fno-exceptions",
        "-I",
        "src",
    ]);

    let src = Path::new("src");
    let parser_c_path = src.join("parser.c");
    let scanner_c_path = src.join("scanner.c");
    let scanner_cc_path = src.join("scanner.cc");
    let scanner_cpp_path = src.join("scanner.cpp");

    if language_dir.join(&scanner_cc_path).exists() {
        command.arg("-xc++").arg(&scanner_cc_path);
    } else if language_dir.join(&scanner_cpp_path).exists() {
        command.arg("-xc++").arg(&scanner_cpp_path);
    } else if language_dir.join(&scanner_c_path).exists() {
        command.arg(&scanner_c_path);
    }

    command.arg(&parser_c_path);

    let output = command
        .output()
        .map_err(Error::wrap(|| "Failed to run emcc command"))?;
    if !output.status.success() {
        return Err(Error::from(format!(
            "emcc command failed - {}",
            String::from_utf8_lossy(&output.stderr)
        )));
    }

    // Move the created `.wasm` file into the current working directory.
    fs::rename(&language_dir.join(&output_filename), &output_filename).map_err(Error::wrap(
        || format!("Couldn't find output file {:?}", output_filename),
    ))?;

    Ok(())
}

fn get_emcc_path() -> Result<PathBuf> {
    let emcc_bin;
    if cfg!(windows) {
        emcc_bin = "emcc.bat";
    } else {
        emcc_bin = "emcc";
    };
    let emcc_which = which(emcc_bin);
    let emcc_path;
    if emcc_which.is_ok() {
        emcc_path = emcc_which.unwrap();
    } else {
        return Error::err("emcc was not found on PATH".to_string());
    }
    if Command::new(&emcc_path).output().is_ok() {
        return Ok(emcc_path);
    }
    return Error::err("emcc binary doesn't work properly".to_string());
}
<commit_msg>fix(cli): Correct fallback on docker compilation for all platforms, fixes #1124<commit_after>use super::error::{Error, Result};
use super::generate::parse_grammar::GrammarJSON;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::Path;
use std::process::Command;
use which::which;

pub fn get_grammar_name(src_dir: &Path) -> Result<String> {
    let grammar_json_path = src_dir.join("grammar.json");
    let grammar_json = fs::read_to_string(&grammar_json_path).map_err(Error::wrap(|| {
        format!("Failed to read grammar file {:?}", grammar_json_path)
    }))?;
    let grammar: GrammarJSON = serde_json::from_str(&grammar_json).map_err(Error::wrap(|| {
        format!("Failed to parse grammar file {:?}", grammar_json_path)
    }))?;
    Ok(grammar.name)
}

pub fn compile_language_to_wasm(language_dir: &Path, force_docker: bool) -> Result<()> {
    let src_dir = language_dir.join("src");
    let grammar_name = get_grammar_name(&src_dir)?;
    let output_filename = format!("tree-sitter-{}.wasm", grammar_name);

    let emcc_bin = if cfg!(windows) { "emcc.bat" } else { "emcc" };
    let emcc_path = which(emcc_bin)
        .ok()
        .and_then(|p| Command::new(&p).output().and(Ok(p)).ok());

    let mut command;
    if !force_docker && emcc_path.is_some() {
        command = Command::new(emcc_path.unwrap());
        command.current_dir(&language_dir);
    } else if Command::new("docker").output().is_ok() {
        command = Command::new("docker");
        command.args(&["run", "--rm"]);

        // Mount the parser directory as a volume
        let mut volume_string;
        if let (Some(parent), Some(filename)) = (language_dir.parent(), language_dir.file_name()) {
            volume_string = OsString::from(parent);
            volume_string.push(":/src:Z");
            command.arg("--workdir");
            command.arg(&Path::new("/src").join(filename));
        } else {
            volume_string = OsString::from(language_dir);
            volume_string.push(":/src:Z");
            command.args(&["--workdir", "/src"]);
        }

        command.args(&[OsStr::new("--volume"), &volume_string]);

        // Get the current user id so that files created in the docker container will have
        // the same owner.
        if cfg!(unix) {
            let user_id_output = Command::new("id")
                .arg("-u")
                .output()
                .map_err(Error::wrap(|| "Failed to get get current user id"))?;
            let user_id = String::from_utf8_lossy(&user_id_output.stdout);
            let user_id = user_id.trim();
            command.args(&["--user", user_id]);
        }

        // Run `emcc` in a container using the `emscripten-slim` image
        command.args(&["emscripten/emsdk", "emcc"]);
    } else {
        return Error::err(
            "You must have either emcc or docker on your PATH to run this command".to_string(),
        );
    }

    command.args(&[
        "-o",
        &output_filename,
        "-Os",
        "-s",
        "WASM=1",
        "-s",
        "SIDE_MODULE=1",
        "-s",
        "TOTAL_MEMORY=33554432",
        "-s",
        "NODEJS_CATCH_EXIT=0",
        "-s",
        &format!("EXPORTED_FUNCTIONS=[\"_tree_sitter_{}\"]", grammar_name),
        "-fno-exceptions",
        "-I",
        "src",
    ]);

    let src = Path::new("src");
    let parser_c_path = src.join("parser.c");
    let scanner_c_path = src.join("scanner.c");
    let scanner_cc_path = src.join("scanner.cc");
    let scanner_cpp_path = src.join("scanner.cpp");

    if language_dir.join(&scanner_cc_path).exists() {
        command.arg("-xc++").arg(&scanner_cc_path);
    } else if language_dir.join(&scanner_cpp_path).exists() {
        command.arg("-xc++").arg(&scanner_cpp_path);
    } else if language_dir.join(&scanner_c_path).exists() {
        command.arg(&scanner_c_path);
    }

    command.arg(&parser_c_path);

    let output = command
        .output()
        .map_err(Error::wrap(|| "Failed to run emcc command"))?;
    if !output.status.success() {
        return Err(Error::from(format!(
            "emcc command failed - {}",
            String::from_utf8_lossy(&output.stderr)
        )));
    }

    // Move the created `.wasm` file into the current working directory.
    fs::rename(&language_dir.join(&output_filename), &output_filename).map_err(Error::wrap(
        || format!("Couldn't find output file {:?}", output_filename),
    ))?;

    Ok(())
}
<|endoftext|>