<commit_before>use crate::{message::BasicReturnMessage, returned_messages::ReturnedMessages, Promise, Result};
use log::trace;
use std::{
    fmt,
    future::Future,
    pin::Pin,
    task::{Context, Poll},
};

pub struct PublisherConfirm {
    inner: Option<Promise<Confirmation>>,
    returned_messages: ReturnedMessages,
    used: bool,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Confirmation {
    Ack(Option<Box<BasicReturnMessage>>),
    Nack(Option<Box<BasicReturnMessage>>),
    NotRequested,
}

impl Confirmation {
    pub fn take_message(self) -> Option<BasicReturnMessage> {
        if let Confirmation::Ack(Some(msg)) | Confirmation::Nack(Some(msg)) = self {
            Some(*msg)
        } else {
            None
        }
    }

    pub fn is_ack(&self) -> bool {
        if let Confirmation::Ack(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_nack(&self) -> bool {
        if let Confirmation::Nack(_) = self {
            true
        } else {
            false
        }
    }
}

impl PublisherConfirm {
    pub(crate) fn new(inner: Promise<Confirmation>, returned_messages: ReturnedMessages) -> Self {
        Self {
            inner: Some(inner),
            returned_messages,
            used: false,
        }
    }

    pub(crate) fn not_requested(returned_messages: ReturnedMessages) -> Self {
        Self {
            inner: Some(Promise::new_with_data(Ok(Confirmation::NotRequested))),
            returned_messages,
            used: false,
        }
    }

    pub fn try_wait(&mut self) -> Option<Result<Confirmation>> {
        let confirmation = self
            .inner
            .as_ref()
            .expect("inner should only be None after Drop")
            .try_wait()?;
        self.used = true;
        Some(confirmation)
    }

    pub fn wait(&mut self) -> Result<Confirmation> {
        self.used = true;
        self.inner
            .as_ref()
            .expect("inner should only be None after Drop")
            .wait()
    }
}

impl fmt::Debug for PublisherConfirm {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("PublisherConfirm").finish()
    }
}

impl Future for PublisherConfirm {
    type Output = Result<Confirmation>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut this = self.as_mut();
        let res = Pin::new(
            &mut this
                .inner
                .as_mut()
                .expect("inner should only be None after Drop"),
        )
        .poll(cx);
        if res.is_ready() {
            this.used = true;
        }
        res
    }
}

impl Drop for PublisherConfirm {
    fn drop(&mut self) {
        if !self.used {
            if let Some(promise) = self.inner.take() {
                trace!(
                    "PublisherConfirm dropped without use, registering it for wait_for_confirms"
                );
                self.returned_messages.register_dropped_confirm(promise);
            }
        }
    }
}
<commit_msg>simplify PUblisherConfirm<commit_after>use crate::{message::BasicReturnMessage, returned_messages::ReturnedMessages, Promise, Result};
use log::trace;
use std::{
    fmt,
    future::Future,
    pin::Pin,
    task::{Context, Poll},
};

pub struct PublisherConfirm {
    inner: Option<Promise<Confirmation>>,
    returned_messages: ReturnedMessages,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Confirmation {
    Ack(Option<Box<BasicReturnMessage>>),
    Nack(Option<Box<BasicReturnMessage>>),
    NotRequested,
}

impl Confirmation {
    pub fn take_message(self) -> Option<BasicReturnMessage> {
        if let Confirmation::Ack(Some(msg)) | Confirmation::Nack(Some(msg)) = self {
            Some(*msg)
        } else {
            None
        }
    }

    pub fn is_ack(&self) -> bool {
        if let Confirmation::Ack(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_nack(&self) -> bool {
        if let Confirmation::Nack(_) = self {
            true
        } else {
            false
        }
    }
}

impl PublisherConfirm {
    pub(crate) fn new(inner: Promise<Confirmation>, returned_messages: ReturnedMessages) -> Self {
        Self {
            inner: Some(inner),
            returned_messages,
        }
    }

    pub(crate) fn not_requested(returned_messages: ReturnedMessages) -> Self {
        Self {
            inner: Some(Promise::new_with_data(Ok(Confirmation::NotRequested))),
            returned_messages,
        }
    }
}

impl fmt::Debug for PublisherConfirm {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("PublisherConfirm").finish()
    }
}

impl Future for PublisherConfirm {
    type Output = Result<Confirmation>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut this = self.as_mut();
        let res = Pin::new(
            &mut this
                .inner
                .as_mut()
                .expect("PublisherConfirm polled after completion"),
        )
        .poll(cx);
        if res.is_ready() {
            this.inner.take();
        }
        res
    }
}

impl Drop for PublisherConfirm {
    fn drop(&mut self) {
        if let Some(promise) = self.inner.take() {
            trace!(
                "PublisherConfirm dropped without use, registering it for wait_for_confirms"
            );
            self.returned_messages.register_dropped_confirm(promise);
        }
    }
}
<|endoftext|>


<commit_before>extern crate elektra_sys;

use elektra_sys::*;
use std::boxed::Box;
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt;

trait KeyBuilder {
    fn new() -> Self;
    fn name<T: Into<Vec<u8>>>(&mut self, name: T) -> Self;
    fn build(self) -> Key;
}

#[derive(Debug)]
enum KeyError {
    InvalidName,
    // TypeMismatch,
    // TypeConversion,
    // NotFoundException
}

impl fmt::Display for KeyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match self {
            KeyError::InvalidName => write!(f, "Key has an invalid name"),
            // _ => unimplemented!(),
        }
    }
}

impl Error for KeyError {}

trait KeyProperties {
    fn new() -> Box<Key>;
    fn set_name(&mut self, name: &str) -> Result<u32, KeyError>;
    fn name(&self) -> &str;
    fn duplicate(&self) -> Box<Key>;
}

impl KeyProperties for Key {
    /// Initializes an empty key object
    fn new() -> Box<Key> {
        unsafe { Box::from_raw(keyNew(0 as *const i8)) }
    }

    /// Set the name of a key
    /// # Examples
    /// ```
    /// let key = Key::new().name("user/test/rust");
    /// assert_eq!(key.get_name(), "user/test/rust");
    /// ```
    fn set_name(&mut self, name: &str) -> Result<u32, KeyError> {
        let cptr = CString::new(name).unwrap();
        let ret_val = unsafe { keySetName(self, cptr.as_ptr()) };

        if ret_val > 0 {
            Ok(ret_val as u32)
        } else {
            Err(KeyError::InvalidName)
        }
    }

    /// Return the name of the key as a borrowed slice
    fn name(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(keyName(self)) };
        c_str.to_str().unwrap()
    }

    /// Return a duplicate of a key
    fn duplicate(&self) -> Box<Key> {
        unsafe { Box::from_raw(keyDup(self)) }
    }
}

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

    #[test]
    fn can_write_read_key() {
        let key_name = "user/test/key";
        let mut key = Key::new();
        key.set_name(key_name).unwrap();
        assert_eq!(key.name(), key_name);
    }

    #[test]
    fn can_duplicate_key() {
        let key_name = "user/test/key";
        let mut key_dup;
        {
            let mut key = Key::new();
            key.set_name(key_name).unwrap();
            key_dup = Some(key.duplicate());
            // key is dropped here
        }
        assert_eq!(key_dup.unwrap().name(), key_name);
    }
}
<commit_msg>Rust: Wrap Key instead of extending it<commit_after>extern crate elektra_sys;

use elektra_sys::{keyDel, keyDup, keyName, keyNew, keySetName};
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt;
use std::ptr::NonNull;

trait KeyBuilder {
    fn new() -> Self;
    fn name<T: Into<Vec<u8>>>(&mut self, name: T) -> Self;
    fn build(self) -> Key;
}

#[derive(Debug)]
pub enum KeyError {
    InvalidName,
    // TypeMismatch,
    // TypeConversion,
    // NotFoundException
}

impl fmt::Display for KeyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match self {
            KeyError::InvalidName => write!(f, "Key has an invalid name"),
            // _ => unimplemented!(),
        }
    }
}

impl Error for KeyError {}

#[derive(Debug)]
pub struct Key {
    ptr: NonNull<elektra_sys::Key>,
}

impl Drop for Key {
    fn drop(&mut self) {
        println!("Drop Key {:?}", self);
        unsafe { keyDel(self.ptr.as_ptr()) };
    }
}

impl Key {
    /// Construct a new empty key
    pub fn new() -> Key {
        let key_ptr = unsafe { keyNew(0 as *const i8) };
        Key::from(key_ptr)
    }

    /// Construct a new key from a raw key pointer
    fn from(ptr: *mut elektra_sys::Key) -> Key {
        Key {
            ptr: NonNull::new(ptr).unwrap(),
        }
    }

    /// Set the name of a key
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let mut key = Key::new();
    /// key.set_name("user/test/rust").unwrap();
    /// assert_eq!(key.name(), "user/test/rust");
    /// ```
    pub fn set_name(&mut self, name: &str) -> Result<u32, KeyError> {
        let cptr = CString::new(name).unwrap();
        let ret_val = unsafe { keySetName(self.ptr.as_ptr(), cptr.as_ptr()) };

        if ret_val > 0 {
            Ok(ret_val as u32)
        } else {
            Err(KeyError::InvalidName)
        }
    }

    /// Return the name of the key as a borrowed slice
    pub fn name(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(keyName(self.ptr.as_ref())) };
        c_str.to_str().unwrap()
    }

    /// Return a duplicate of a key
    pub fn duplicate(&self) -> Key {
        let dup_ptr = unsafe { keyDup(self.ptr.as_ptr()) };
        Key::from(dup_ptr)
    }
}

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

    #[test]
    fn can_write_read_key() {
        let key_name = "user/test/key";
        let mut key = Key::new();
        key.set_name(key_name).unwrap();
        assert_eq!(key.name(), key_name);
    }

    #[test]
    fn can_duplicate_key() {
        let key_name = "user/test/key";
        let mut key_dup;
        {
            let mut key = Key::new();
            key.set_name(key_name).unwrap();
            key_dup = Some(key.duplicate());
            // key is dropped here
        }
        assert_eq!(key_dup.unwrap().name(), key_name);
    }
}
<|endoftext|>


<commit_before>import driver::session::session;
import middle::ty;
import syntax::{ast, visit};
import syntax::attr;
import syntax::codemap::span;
import std::map::{map,hashmap,hash_from_strs};
import io::writer_util;
import syntax::print::pprust::expr_to_str;

export lint, ctypes, unused_imports;
export level, ignore, warn, error;
export lookup_lint, lint_dict, get_lint_dict, check_crate;

#[doc="

A 'lint' check is a kind of miscellaneous constraint that a user _might_ want
to enforce, but might reasonably want to permit as well, on a module-by-module
basis. They contrast with static constraints enforced by other phases of the
compiler, which are generally required to hold in order to compile the program
at all.

"]

enum lint {
    ctypes,
    unused_imports,
    while_true,
    path_statement,
}

enum level {
    ignore, warn, error
}

type lint_spec = @{lint: lint,
                   desc: str,
                   default: level};

type lint_dict = hashmap<str,lint_spec>;

/*
  Pass names should not contain a '-', as the compiler normalizes
  '-' to '_' in command-line flags
 */
fn get_lint_dict() -> lint_dict {
    let v = [
        ("ctypes",
         @{lint: ctypes,
           desc: "proper use of core::libc types in native modules",
           default: warn}),

        ("unused_imports",
         @{lint: unused_imports,
           desc: "imports that are never used",
           default: ignore}),

        ("while_true",
         @{lint: while_true,
           desc: "suggest using loop { } instead of while(true) { }",
           default: warn}),

        ("path_statement",
         @{lint: path_statement,
           desc: "path statements with no effect",
           default: warn})

    ];
    hash_from_strs(v)
}

type ctxt = @{dict: lint_dict,
              curr: hashmap<lint, level>,
              tcx: ty::ctxt};

impl methods for ctxt {
    fn get_level(lint: lint) -> level {
        alt self.curr.find(lint) {
          some(c) { c }
          none { ignore }
        }
    }

    fn set_level(lint: lint, level: level) {
        if level == ignore {
            self.curr.remove(lint);
        } else {
            self.curr.insert(lint, level);
        }
    }

    fn span_lint(level: level, span: span, msg: str) {
        alt level {
          ignore { }
          warn { self.tcx.sess.span_warn(span, msg); }
          error { self.tcx.sess.span_err(span, msg); }
        }
    }

    #[doc="
          Merge the warnings specified by any `warn(...)` attributes into the
          current lint context, call the provided function, then reset the
          warnings in effect to their previous state.
    "]
    fn with_warn_attrs(attrs: [ast::attribute], f: fn(ctxt)) {

        let mut undo = [];

        let metas = attr::attr_metas(attr::find_attrs_by_name(attrs, "warn"));
        for metas.each {|meta|
            alt meta.node {
              ast::meta_list(_, metas) {
                for metas.each {|meta|
                    alt meta.node {
                      ast::meta_word(lintname) {
                        alt lookup_lint(self.dict, lintname) {
                          none {
                            self.tcx.sess.span_err(
                                meta.span,
                                #fmt("unknown warning: '%s'", lintname));
                          }
                          some((lint, new_level)) {
                            let old_level = self.get_level(lint);
                            self.set_level(lint, new_level);
                            undo += [(lint, old_level)]
                          }
                        }
                      }
                      _ {
                        self.tcx.sess.span_err(
                            meta.span,
                            "malformed warning attribute");
                      }
                    }
                }
              }
              _ {
                self.tcx.sess.span_err(meta.span,
                                       "malformed warning attribute");
              }
            }
        }

        f(self);

        for undo.each {|pair|
            let (lint,old_level) = pair;
            self.set_level(lint, old_level);
        }
    }
}

fn lookup_lint(dict: lint_dict, s: str)
    -> option<(lint, level)> {
    let s = str::replace(s, "-", "_");
    let (name, level) = if s.starts_with("no_") {
        (s.substr(3u, s.len() - 3u), ignore)
    } else if s.starts_with("err_") {
        (s.substr(4u, s.len() - 4u), error)
    } else {
        (s, warn)
    };
    alt dict.find(name) {
      none { none }
      some(spec) { some((spec.lint, level)) }
    }
}

// FIXME: Copied from driver.rs, to work around a bug(#1566)
fn time(do_it: bool, what: str, thunk: fn()) {
    if !do_it{ ret thunk(); }
    let start = std::time::precise_time_s();
    thunk();
    let end = std::time::precise_time_s();
    io::stdout().write_str(#fmt("time: %3.3f s\t%s\n",
                                end - start, what));
}

fn check_item(cx: ctxt, i: @ast::item) {
    cx.with_warn_attrs(i.attrs) {|cx|
        for cx.curr.each {|lint, level|
            alt lint {
              ctypes { check_item_ctypes(cx, level, i); }
              unused_imports { check_item_unused_imports(cx, level, i); }
              while_true { check_item_while_true(cx, level, i); }
              path_statement { check_item_path_statement(cx, level, i); }
            }
        }
    }
}

fn check_item_while_true(cx: ctxt, level: level, it: @ast::item) {
    let visit = visit::mk_simple_visitor(@{
        visit_expr: fn@(e: @ast::expr) {
           alt e.node {
             ast::expr_while(cond, _) {
                alt cond.node {
                    ast::expr_lit(@{node: ast::lit_bool(true),_}) {
                            cx.span_lint(
                              level, e.span,
                              "denote infinite loops with loop { ... }");
                    }
                    _ {}
                }
             }
             _ {}
          }
        }
        with *visit::default_simple_visitor()
    });
    visit::visit_item(it, (), visit);
}

fn check_item_unused_imports(_cx: ctxt, _level: level, _it: @ast::item) {
    // FIXME: Don't know how to check this in lint yet, it's currently being
    // done over in resolve. When resolve is rewritten, do it here instead.
}

fn check_item_ctypes(cx: ctxt, level: level, it: @ast::item) {

    fn check_native_fn(cx: ctxt, level: level, decl: ast::fn_decl) {
        let tys = vec::map(decl.inputs) {|a| a.ty };
        for vec::each(tys + [decl.output]) {|ty|
            alt ty.node {
              ast::ty_path(_, id) {
                alt cx.tcx.def_map.get(id) {
                  ast::def_prim_ty(ast::ty_int(ast::ty_i)) {
                    cx.span_lint(
                        level, ty.span,
                        "found rust type `int` in native module, while \
                         libc::c_int or libc::c_long should be used");
                  }
                  ast::def_prim_ty(ast::ty_uint(ast::ty_u)) {
                    cx.span_lint(
                        level, ty.span,
                        "found rust type `uint` in native module, while \
                         libc::c_uint or libc::c_ulong should be used");
                  }
                  _ { }
                }
              }
              _ { }
            }
        }
    }

    alt it.node {
      ast::item_native_mod(nmod) if attr::native_abi(it.attrs) !=
      either::right(ast::native_abi_rust_intrinsic) {
        for nmod.items.each {|ni|
            alt ni.node {
              ast::native_item_fn(decl, tps) {
                check_native_fn(cx, level, decl);
              }
            }
        }
      }
      _ {/* nothing to do */ }
    }
}

fn check_item_path_statement(cx: ctxt, level: level, it: @ast::item) {
    let visit = visit::mk_simple_visitor(@{
        visit_stmt: fn@(s: @ast::stmt) {
            alt s.node {
              ast::stmt_semi(@{id: _,
                               node: ast::expr_path(@path),
                               span: _}, _) {
                cx.span_lint(
                    level, s.span,
                    "path statement with no effect");
              }
              _ {}
            }
        }
        with *visit::default_simple_visitor()
    });
    visit::visit_item(it, (), visit);
}

fn check_crate(tcx: ty::ctxt, crate: @ast::crate,
               lint_opts: [(lint, level)], time_pass: bool) {

    fn hash_lint(&&lint: lint) -> uint { lint as uint }
    fn eq_lint(&&a: lint, &&b: lint) -> bool { a == b }

    let cx = @{dict: get_lint_dict(),
               curr: hashmap(hash_lint, eq_lint),
               tcx: tcx};

    // Install defaults.
    for cx.dict.each {|_k, spec| cx.set_level(spec.lint, spec.default); }

    // Install command-line options, overriding defaults.
    for lint_opts.each {|pair|
        let (lint,level) = pair;
        cx.set_level(lint, level);
    }

    time(time_pass, "lint checking") {||
        cx.with_warn_attrs(crate.node.attrs) {|cx|
            let visit = visit::mk_simple_visitor(@{
                visit_item: fn@(i: @ast::item) { check_item(cx, i); }
                with *visit::default_simple_visitor()
            });
            visit::visit_crate(*crate, (), visit);
        }
    }

    tcx.sess.abort_if_errors();
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>New lint pass for picking out uses of old-style vecs and str.<commit_after>import driver::session::session;
import middle::ty;
import syntax::{ast, visit};
import syntax::attr;
import syntax::codemap::span;
import std::map::{map,hashmap,int_hash,hash_from_strs};
import io::writer_util;
import syntax::print::pprust::expr_to_str;

export lint, ctypes, unused_imports;
export level, ignore, warn, error;
export lookup_lint, lint_dict, get_lint_dict, check_crate;

#[doc="

A 'lint' check is a kind of miscellaneous constraint that a user _might_ want
to enforce, but might reasonably want to permit as well, on a module-by-module
basis. They contrast with static constraints enforced by other phases of the
compiler, which are generally required to hold in order to compile the program
at all.

"]

enum lint {
    ctypes,
    unused_imports,
    while_true,
    path_statement,
    old_vecs,
}

enum level {
    ignore, warn, error
}

type lint_spec = @{lint: lint,
                   desc: str,
                   default: level};

type lint_dict = hashmap<str,lint_spec>;

/*
  Pass names should not contain a '-', as the compiler normalizes
  '-' to '_' in command-line flags
 */
fn get_lint_dict() -> lint_dict {
    let v = [
        ("ctypes",
         @{lint: ctypes,
           desc: "proper use of core::libc types in native modules",
           default: warn}),

        ("unused_imports",
         @{lint: unused_imports,
           desc: "imports that are never used",
           default: ignore}),

        ("while_true",
         @{lint: while_true,
           desc: "suggest using loop { } instead of while(true) { }",
           default: warn}),

        ("path_statement",
         @{lint: path_statement,
           desc: "path statements with no effect",
           default: warn}),

        ("old_vecs",
         @{lint: old_vecs,
           desc: "old (deprecated) vectors and strings",
           default: ignore})

    ];
    hash_from_strs(v)
}

type ctxt = @{dict: lint_dict,
              curr: hashmap<lint, level>,
              tcx: ty::ctxt};

impl methods for ctxt {
    fn get_level(lint: lint) -> level {
        alt self.curr.find(lint) {
          some(c) { c }
          none { ignore }
        }
    }

    fn set_level(lint: lint, level: level) {
        if level == ignore {
            self.curr.remove(lint);
        } else {
            self.curr.insert(lint, level);
        }
    }

    fn span_lint(level: level, span: span, msg: str) {
        alt level {
          ignore { }
          warn { self.tcx.sess.span_warn(span, msg); }
          error { self.tcx.sess.span_err(span, msg); }
        }
    }

    #[doc="
          Merge the warnings specified by any `warn(...)` attributes into the
          current lint context, call the provided function, then reset the
          warnings in effect to their previous state.
    "]
    fn with_warn_attrs(attrs: [ast::attribute], f: fn(ctxt)) {

        let mut undo = [];

        let metas = attr::attr_metas(attr::find_attrs_by_name(attrs, "warn"));
        for metas.each {|meta|
            alt meta.node {
              ast::meta_list(_, metas) {
                for metas.each {|meta|
                    alt meta.node {
                      ast::meta_word(lintname) {
                        alt lookup_lint(self.dict, lintname) {
                          none {
                            self.tcx.sess.span_err(
                                meta.span,
                                #fmt("unknown warning: '%s'", lintname));
                          }
                          some((lint, new_level)) {
                            let old_level = self.get_level(lint);
                            self.set_level(lint, new_level);
                            undo += [(lint, old_level)]
                          }
                        }
                      }
                      _ {
                        self.tcx.sess.span_err(
                            meta.span,
                            "malformed warning attribute");
                      }
                    }
                }
              }
              _ {
                self.tcx.sess.span_err(meta.span,
                                       "malformed warning attribute");
              }
            }
        }

        f(self);

        for undo.each {|pair|
            let (lint,old_level) = pair;
            self.set_level(lint, old_level);
        }
    }
}

fn lookup_lint(dict: lint_dict, s: str)
    -> option<(lint, level)> {
    let s = str::replace(s, "-", "_");
    let (name, level) = if s.starts_with("no_") {
        (s.substr(3u, s.len() - 3u), ignore)
    } else if s.starts_with("err_") {
        (s.substr(4u, s.len() - 4u), error)
    } else {
        (s, warn)
    };
    alt dict.find(name) {
      none { none }
      some(spec) { some((spec.lint, level)) }
    }
}

// FIXME: Copied from driver.rs, to work around a bug(#1566)
fn time(do_it: bool, what: str, thunk: fn()) {
    if !do_it{ ret thunk(); }
    let start = std::time::precise_time_s();
    thunk();
    let end = std::time::precise_time_s();
    io::stdout().write_str(#fmt("time: %3.3f s\t%s\n",
                                end - start, what));
}

fn check_item(cx: ctxt, i: @ast::item) {
    cx.with_warn_attrs(i.attrs) {|cx|
        for cx.curr.each {|lint, level|
            alt lint {
              ctypes { check_item_ctypes(cx, level, i); }
              unused_imports { check_item_unused_imports(cx, level, i); }
              while_true { check_item_while_true(cx, level, i); }
              path_statement { check_item_path_statement(cx, level, i); }
              old_vecs { check_item_old_vecs(cx, level, i); }
            }
        }
    }
}

fn check_item_while_true(cx: ctxt, level: level, it: @ast::item) {
    let visit = visit::mk_simple_visitor(@{
        visit_expr: fn@(e: @ast::expr) {
           alt e.node {
             ast::expr_while(cond, _) {
                alt cond.node {
                    ast::expr_lit(@{node: ast::lit_bool(true),_}) {
                            cx.span_lint(
                              level, e.span,
                              "denote infinite loops with loop { ... }");
                    }
                    _ {}
                }
             }
             _ {}
          }
        }
        with *visit::default_simple_visitor()
    });
    visit::visit_item(it, (), visit);
}

fn check_item_unused_imports(_cx: ctxt, _level: level, _it: @ast::item) {
    // FIXME: Don't know how to check this in lint yet, it's currently being
    // done over in resolve. When resolve is rewritten, do it here instead.
}

fn check_item_ctypes(cx: ctxt, level: level, it: @ast::item) {

    fn check_native_fn(cx: ctxt, level: level, decl: ast::fn_decl) {
        let tys = vec::map(decl.inputs) {|a| a.ty };
        for vec::each(tys + [decl.output]) {|ty|
            alt ty.node {
              ast::ty_path(_, id) {
                alt cx.tcx.def_map.get(id) {
                  ast::def_prim_ty(ast::ty_int(ast::ty_i)) {
                    cx.span_lint(
                        level, ty.span,
                        "found rust type `int` in native module, while \
                         libc::c_int or libc::c_long should be used");
                  }
                  ast::def_prim_ty(ast::ty_uint(ast::ty_u)) {
                    cx.span_lint(
                        level, ty.span,
                        "found rust type `uint` in native module, while \
                         libc::c_uint or libc::c_ulong should be used");
                  }
                  _ { }
                }
              }
              _ { }
            }
        }
    }

    alt it.node {
      ast::item_native_mod(nmod) if attr::native_abi(it.attrs) !=
      either::right(ast::native_abi_rust_intrinsic) {
        for nmod.items.each {|ni|
            alt ni.node {
              ast::native_item_fn(decl, tps) {
                check_native_fn(cx, level, decl);
              }
            }
        }
      }
      _ {/* nothing to do */ }
    }
}

fn check_item_path_statement(cx: ctxt, level: level, it: @ast::item) {
    let visit = visit::mk_simple_visitor(@{
        visit_stmt: fn@(s: @ast::stmt) {
            alt s.node {
              ast::stmt_semi(@{id: _,
                               node: ast::expr_path(@path),
                               span: _}, _) {
                cx.span_lint(
                    level, s.span,
                    "path statement with no effect");
              }
              _ {}
            }
        }
        with *visit::default_simple_visitor()
    });
    visit::visit_item(it, (), visit);
}

fn check_item_old_vecs(cx: ctxt, level: level, it: @ast::item) {
    let uses_vstore = int_hash();

    let visit = visit::mk_simple_visitor(@{

        visit_expr:fn@(e: @ast::expr) {
            alt e.node {
              ast::expr_vec(_, _) |
              ast::expr_lit(@{node: ast::lit_str(_), span:_})
              if ! uses_vstore.contains_key(e.id) {
                cx.span_lint(level, e.span, "deprecated vec/str expr");
              }
              ast::expr_vstore(@inner, _) {
                uses_vstore.insert(inner.id, true);
              }
              _ { }
            }
        },

        visit_ty: fn@(t: @ast::ty) {
            alt t.node {
              ast::ty_vec(_)
              if ! uses_vstore.contains_key(t.id) {
                cx.span_lint(level, t.span, "deprecated vec type");
              }

              ast::ty_path(@{span: _, global: _, idents: ids,
                             rp: none, types: _}, _)
              if ids == ["str"] && (! uses_vstore.contains_key(t.id)) {
                cx.span_lint(level, t.span, "deprecated str type");
              }

              ast::ty_vstore(inner, _) {
                uses_vstore.insert(inner.id, true);
              }
              _ { }
            }
        }

        with *visit::default_simple_visitor()
    });
    visit::visit_item(it, (), visit);
}

fn check_crate(tcx: ty::ctxt, crate: @ast::crate,
               lint_opts: [(lint, level)], time_pass: bool) {

    fn hash_lint(&&lint: lint) -> uint { lint as uint }
    fn eq_lint(&&a: lint, &&b: lint) -> bool { a == b }

    let cx = @{dict: get_lint_dict(),
               curr: hashmap(hash_lint, eq_lint),
               tcx: tcx};

    // Install defaults.
    for cx.dict.each {|_k, spec| cx.set_level(spec.lint, spec.default); }

    // Install command-line options, overriding defaults.
    for lint_opts.each {|pair|
        let (lint,level) = pair;
        cx.set_level(lint, level);
    }

    time(time_pass, "lint checking") {||
        cx.with_warn_attrs(crate.node.attrs) {|cx|
            let visit = visit::mk_simple_visitor(@{
                visit_item: fn@(i: @ast::item) { check_item(cx, i); }
                with *visit::default_simple_visitor()
            });
            visit::visit_crate(*crate, (), visit);
        }
    }

    tcx.sess.abort_if_errors();
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>


<commit_before>extern crate ggez;
use ggez::conf;
use ggez::event;
use ggez::{GameResult, Context};
use ggez::graphics;
use ggez::graphics::{Color, DrawMode, Point};
use std::time::Duration;

struct MainState {
    pos_x: f32,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let s = MainState { pos_x: 0.0 };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context, _dt: Duration) -> GameResult<()> {
        self.pos_x = self.pos_x % 800.0 + 1.0;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);
        graphics::circle(ctx, DrawMode::Fill, Point { x: self.pos_x, y: 380.0 }, 100.0, 32)?;
        graphics::present(ctx);
        Ok(())
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("super_simple", "ggez", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    event::run(ctx, state).unwrap();
}
<commit_msg>Shave some lines off the super simple example<commit_after>extern crate ggez;
use ggez::*;
use ggez::graphics::{Color, DrawMode, Point};
use std::time::Duration;

struct MainState {
    pos_x: f32,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let s = MainState { pos_x: 0.0 };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context, _dt: Duration) -> GameResult<()> {
        self.pos_x = self.pos_x % 800.0 + 1.0;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);
        graphics::circle(ctx, DrawMode::Fill, Point { x: self.pos_x, y: 380.0 }, 100.0, 32)?;
        graphics::present(ctx);
        Ok(())
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("super_simple", "ggez", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    event::run(ctx, state).unwrap();
}
<|endoftext|>


<commit_before>//! Function names.
//!
//! The name of a function doesn't have any meaning to Cretonne which compiles functions
//! independently.

use std::fmt::{self, Write};
use std::ascii::AsciiExt;

/// The name of a function can be any sequence of bytes.
///
/// Function names are mostly a testing and debugging tool.
/// In particular, `.cton` files use function names to identify functions.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct FunctionName(NameRepr);

impl FunctionName {
    /// Creates a new function name from a sequence of bytes.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use cretonne::ir::FunctionName;
    /// // Create `FunctionName` from a string.
    /// let name = FunctionName::new("hello");
    /// assert_eq!(name.to_string(), "%hello");
    ///
    /// // Create `FunctionName` from a sequence of bytes.
    /// let bytes: &[u8] = &[10, 9, 8];
    /// let name = FunctionName::new(bytes);
    /// assert_eq!(name.to_string(), "#0a0908");
    /// ```
    pub fn new<T>(v: T) -> FunctionName
    where
        T: Into<Vec<u8>>,
    {
        let vec = v.into();
        if vec.len() <= NAME_LENGTH_THRESHOLD {
            let mut bytes = [0u8; NAME_LENGTH_THRESHOLD];
            for (i, &byte) in vec.iter().enumerate() {
                bytes[i] = byte;
            }
            FunctionName(NameRepr::Short {
                length: vec.len() as u8,
                bytes: bytes,
            })
        } else {
            FunctionName(NameRepr::Long(vec))
        }
    }
}

/// Tries to interpret bytes as ASCII alphanumerical characters and `_`.
fn try_as_name(bytes: &[u8]) -> Option<String> {
    let mut name = String::with_capacity(bytes.len());
    for c in bytes.iter().map(|&b| b as char) {
        if c.is_ascii() && c.is_alphanumeric() || c == '_' {
            name.push(c);
        } else {
            return None;
        }
    }
    Some(name)
}

const NAME_LENGTH_THRESHOLD: usize = 22;

#[derive(Debug, Clone, PartialEq, Eq)]
enum NameRepr {
    Short {
        length: u8,
        bytes: [u8; NAME_LENGTH_THRESHOLD],
    },
    Long(Vec<u8>),
}

impl AsRef<[u8]> for NameRepr {
    fn as_ref(&self) -> &[u8] {
        match *self {
            NameRepr::Short { length, ref bytes } => &bytes[0..length as usize],
            NameRepr::Long(ref vec) => vec.as_ref(),
        }
    }
}

impl Default for NameRepr {
    fn default() -> Self {
        NameRepr::Short {
            length: 0,
            bytes: [0; NAME_LENGTH_THRESHOLD],
        }
    }
}

impl fmt::Display for FunctionName {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(name) = try_as_name(self.0.as_ref()) {
            write!(f, "%{}", name)
        } else {
            f.write_char('#')?;
            for byte in self.0.as_ref() {
                write!(f, "{:02x}", byte)?;
            }
            Ok(())
        }
    }
}

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

    #[test]
    fn displaying() {
        assert_eq!(FunctionName::new("").to_string(), "%");
        assert_eq!(FunctionName::new("x").to_string(), "%x");
        assert_eq!(FunctionName::new("x_1").to_string(), "%x_1");
        assert_eq!(FunctionName::new(" ").to_string(), "#20");
        assert_eq!(
            FunctionName::new("кретон").to_string(),
            "#d0bad180d0b5d182d0bed0bd"
        );
        assert_eq!(
            FunctionName::new("印花棉布").to_string(),
            "#e58db0e88ab1e6a389e5b883"
        );
        assert_eq!(
            FunctionName::new(vec![0, 1, 2, 3, 4, 5]).to_string(),
            "#000102030405"
        );
    }
}
<commit_msg>Add an AsRef implementation to FuncName so we can read its contents.<commit_after>//! Function names.
//!
//! The name of a function doesn't have any meaning to Cretonne which compiles functions
//! independently.

use std::fmt::{self, Write};
use std::ascii::AsciiExt;

/// The name of a function can be any sequence of bytes.
///
/// Function names are mostly a testing and debugging tool.
/// In particular, `.cton` files use function names to identify functions.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct FunctionName(NameRepr);

impl FunctionName {
    /// Creates a new function name from a sequence of bytes.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use cretonne::ir::FunctionName;
    /// // Create `FunctionName` from a string.
    /// let name = FunctionName::new("hello");
    /// assert_eq!(name.to_string(), "%hello");
    ///
    /// // Create `FunctionName` from a sequence of bytes.
    /// let bytes: &[u8] = &[10, 9, 8];
    /// let name = FunctionName::new(bytes);
    /// assert_eq!(name.to_string(), "#0a0908");
    /// ```
    pub fn new<T>(v: T) -> FunctionName
    where
        T: Into<Vec<u8>>,
    {
        let vec = v.into();
        if vec.len() <= NAME_LENGTH_THRESHOLD {
            let mut bytes = [0u8; NAME_LENGTH_THRESHOLD];
            for (i, &byte) in vec.iter().enumerate() {
                bytes[i] = byte;
            }
            FunctionName(NameRepr::Short {
                length: vec.len() as u8,
                bytes: bytes,
            })
        } else {
            FunctionName(NameRepr::Long(vec))
        }
    }
}

/// Tries to interpret bytes as ASCII alphanumerical characters and `_`.
fn try_as_name(bytes: &[u8]) -> Option<String> {
    let mut name = String::with_capacity(bytes.len());
    for c in bytes.iter().map(|&b| b as char) {
        if c.is_ascii() && c.is_alphanumeric() || c == '_' {
            name.push(c);
        } else {
            return None;
        }
    }
    Some(name)
}

const NAME_LENGTH_THRESHOLD: usize = 22;

#[derive(Debug, Clone, PartialEq, Eq)]
enum NameRepr {
    Short {
        length: u8,
        bytes: [u8; NAME_LENGTH_THRESHOLD],
    },
    Long(Vec<u8>),
}

impl AsRef<[u8]> for NameRepr {
    fn as_ref(&self) -> &[u8] {
        match *self {
            NameRepr::Short { length, ref bytes } => &bytes[0..length as usize],
            NameRepr::Long(ref vec) => vec.as_ref(),
        }
    }
}

impl AsRef<[u8]> for FunctionName {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
}

impl Default for NameRepr {
    fn default() -> Self {
        NameRepr::Short {
            length: 0,
            bytes: [0; NAME_LENGTH_THRESHOLD],
        }
    }
}

impl fmt::Display for FunctionName {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(name) = try_as_name(self.0.as_ref()) {
            write!(f, "%{}", name)
        } else {
            f.write_char('#')?;
            for byte in self.0.as_ref() {
                write!(f, "{:02x}", byte)?;
            }
            Ok(())
        }
    }
}

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

    #[test]
    fn displaying() {
        assert_eq!(FunctionName::new("").to_string(), "%");
        assert_eq!(FunctionName::new("x").to_string(), "%x");
        assert_eq!(FunctionName::new("x_1").to_string(), "%x_1");
        assert_eq!(FunctionName::new(" ").to_string(), "#20");
        assert_eq!(
            FunctionName::new("кретон").to_string(),
            "#d0bad180d0b5d182d0bed0bd"
        );
        assert_eq!(
            FunctionName::new("印花棉布").to_string(),
            "#e58db0e88ab1e6a389e5b883"
        );
        assert_eq!(
            FunctionName::new(vec![0, 1, 2, 3, 4, 5]).to_string(),
            "#000102030405"
        );
    }
}
<|endoftext|>


<commit_before>use ::source::{Source, SourceError};

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

use handlebars::Handlebars;
use walkdir::{WalkDir, DirEntry};

pub struct DirectorySource {
    pub prefix: PathBuf,
    pub suffix: String
}

impl DirectorySource {
    pub fn new(prefix: &str, suffix: &str) -> DirectorySource {
        DirectorySource {
            prefix: PathBuf::from(prefix),
            suffix: suffix.to_owned()
        }
    }
}

fn read_file(path: &Path) -> Option<String> {
    if let Ok(mut file) = File::open(path) {
        let mut buf = String::new();
        if file.read_to_string(&mut buf).is_ok() {
            Some(buf)
        } else {
            info!("Failed to read file {}, skipped", path.display());
            None
        }
    } else {
        info!("Failed to open file {}, skipped.", path.display());
        None
    }
}

fn filter_file(entry: &DirEntry, suffix: &str) -> bool {
    entry.file_name().to_str()
        .and_then(|s| Some(s.starts_with(".") || s.starts_with("#") || !s.ends_with(suffix)))
        .unwrap_or(false)
}

impl Source for DirectorySource {
    fn load(&self, reg: &mut Handlebars) -> Result<(), SourceError> {
        let suffix_len = self.suffix.len();

        info!("Loading templates from path {}", self.prefix.display());
        let walker = WalkDir::new(&self.prefix);
        for p in walker.min_depth(1).into_iter().filter(|e| e.is_ok() && !filter_file(e.as_ref().unwrap(), &self.suffix)).map(|e| e.unwrap()) {
            let tpl_file = p.file_name().to_string_lossy();
            let tpl_name = &tpl_file[0 .. tpl_file.len() - suffix_len];
            debug!("getting file {}", tpl_file);
            let tpl_path = p.path();
            if let Some(tpl) = read_file(tpl_path) {
                if let Err(e) = reg.register_template_string(&tpl_name, tpl){
                    warn!("Failed to parse template {}, {}", tpl_name, e);
                } else {
                    info!("Added template {}", tpl_name);
                }
            }
        }
        Ok(())
    }
}
<commit_msg>and_then not needed if map is enough<commit_after>use ::source::{Source, SourceError};

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

use handlebars::Handlebars;
use walkdir::{WalkDir, DirEntry};

pub struct DirectorySource {
    pub prefix: PathBuf,
    pub suffix: String
}

impl DirectorySource {
    pub fn new(prefix: &str, suffix: &str) -> DirectorySource {
        DirectorySource {
            prefix: PathBuf::from(prefix),
            suffix: suffix.to_owned()
        }
    }
}

fn read_file(path: &Path) -> Option<String> {
    if let Ok(mut file) = File::open(path) {
        let mut buf = String::new();
        if file.read_to_string(&mut buf).is_ok() {
            Some(buf)
        } else {
            info!("Failed to read file {}, skipped", path.display());
            None
        }
    } else {
        info!("Failed to open file {}, skipped.", path.display());
        None
    }
}

fn filter_file(entry: &DirEntry, suffix: &str) -> bool {
    entry.file_name().to_str()
        .map(|s| s.starts_with(".") || s.starts_with("#") || !s.ends_with(suffix))
        .unwrap_or(false)
}

impl Source for DirectorySource {
    fn load(&self, reg: &mut Handlebars) -> Result<(), SourceError> {
        let suffix_len = self.suffix.len();

        info!("Loading templates from path {}", self.prefix.display());
        let walker = WalkDir::new(&self.prefix);
        for p in walker.min_depth(1).into_iter().filter(|e| e.is_ok() && !filter_file(e.as_ref().unwrap(), &self.suffix)).map(|e| e.unwrap()) {
            let tpl_file = p.file_name().to_string_lossy();
            let tpl_name = &tpl_file[0 .. tpl_file.len() - suffix_len];
            debug!("getting file {}", tpl_file);
            let tpl_path = p.path();
            if let Some(tpl) = read_file(tpl_path) {
                if let Err(e) = reg.register_template_string(&tpl_name, tpl){
                    warn!("Failed to parse template {}, {}", tpl_name, e);
                } else {
                    info!("Added template {}", tpl_name);
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {println(format!("Received connection from: [{:s}]", pn.to_str()));},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            println(format!("Received request :\n{:s}", request_str));

            let response: ~str =
                ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

                 \r\n";
            stream.write(response.as_bytes());
            println!("Connection terminates.");
        }
    }
}
<commit_msg>updated code to reflect rust 0.12<commit_after>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#![feature(globs)]
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT).as_slice()).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(IP, PORT as u16).listen();

    println!("Listening on [{:s}] ...", addr.to_string());

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        spawn(proc() {
            let mut stream = stream;

            match stream {
                Err(ref e) => { /* connection failed */ }
                Ok(ref mut s) => {
                    match s.peer_name() {
                        Err(ref e) => { /* connection failed */ }
                        Ok(pn) => {println!("Received connection from: [{:s}]", pn.to_string());}
                    }
                }
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            println!("Received request :\n{}", request_str);

            let response: String =
                "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

                 \r\n".to_string();
            stream.write(response.as_bytes());
            println!("Connection terminates.");
        });
    }
}
<|endoftext|>


<commit_before>use yaml_rust::{YamlLoader, Yaml, ScanError};
use std::collections::{HashMap, BTreeMap};

pub type Regex = String;
pub type ScopeElement = String;
pub type CaptureMapping = HashMap<usize, ScopeElement>;

#[derive(Debug)]
pub struct SyntaxDefinition {
    pub name: String,
    pub file_extensions: Vec<String>,
    pub scope: ScopeElement,
    first_line_match: Option<Regex>,
    pub hidden: bool,

    variables: HashMap<String, String>,
    contexts: HashMap<String, Context>,
}

#[derive(Debug)]
pub struct Context {
    meta_scope: Option<ScopeElement>,
    meta_content_scope: Option<ScopeElement>,
    meta_include_prototype: bool,

    patterns: Vec<Pattern>,
}

#[derive(Debug)]
pub enum Pattern {
    Match(MatchPattern),
    Include(ContextReference),
}

#[derive(Debug)]
pub struct MatchPattern {
    regex: Regex,
    scope: Option<ScopeElement>,
    captures: Option<CaptureMapping>,
    operation: MatchOperation,
}

#[derive(Debug)]
pub enum ContextReference {
    Named(String),
    ByScope {
        name: String,
        sub_context: Option<String>,
    },
    File(String),
    Inline(Box<Context>),
}

#[derive(Debug)]
pub enum MatchOperation {
    Push(Vec<ContextReference>),
    Set(Vec<ContextReference>),
    Pop,
    None,
}

#[derive(Debug)]
pub enum ParseError {
    InvalidYaml(ScanError),
    EmptyFile,
    MissingMandatoryKey(&'static str),
    TypeMismatch,
}

fn get_key<'a, R, F: FnOnce(&'a Yaml) -> Option<R>>(map: &'a BTreeMap<Yaml, Yaml>,
                                                    key: &'static str,
                                                    f: F)
                                                    -> Result<R, ParseError> {
    map.get(&Yaml::String(key.to_owned()))
        .ok_or(ParseError::MissingMandatoryKey(key))
        .and_then(|x| f(x).ok_or(ParseError::TypeMismatch))
}

impl SyntaxDefinition {
    pub fn load_from_str(s: &str) -> Result<SyntaxDefinition, ParseError> {
        let docs = match YamlLoader::load_from_str(s) {
            Ok(x) => x,
            Err(e) => return Err(ParseError::InvalidYaml(e)),
        };
        if docs.len() == 0 {
            return Err(ParseError::EmptyFile);
        }
        let doc = &docs[0];
        SyntaxDefinition::parse_top_level(doc)
    }

    fn parse_top_level(doc: &Yaml) -> Result<SyntaxDefinition, ParseError> {
        let h = try!(doc.as_hash().ok_or(ParseError::TypeMismatch));

        let mut variables = HashMap::new();
        if let Ok(map) = get_key(h, "variables", |x| x.as_hash()) {
            for (key, value) in map.iter() {
                if let (Some(key_str), Some(val_str)) = (key.as_str(), value.as_str()) {
                    variables.insert(key_str.to_owned(), val_str.to_owned());
                }
            }
        }

        let contexts_hash = try!(get_key(h, "contexts", |x| x.as_hash()));
        let contexts = try!(SyntaxDefinition::parse_contexts(contexts_hash, &variables));

        let defn = SyntaxDefinition {
            name: try!(get_key(h, "name", |x| x.as_str())).to_owned(),
            scope: try!(get_key(h, "scope", |x| x.as_str())).to_owned(),
            file_extensions: {
                get_key(h, "file_extensions", |x| x.as_vec())
                    .map(|v| v.iter().filter_map(|y| y.as_str()).map(|x| x.to_owned()).collect())
                    .unwrap_or_else(|_| Vec::new())
            },
            first_line_match: get_key(h, "first_line_match", |x| x.as_str())
                .ok()
                .map(|x| x.to_owned()),
            hidden: get_key(h, "hidden", |x| x.as_bool()).unwrap_or(false),

            variables: variables,
            contexts: contexts, // TODO
        };
        Ok(defn)
    }

    fn parse_contexts(map: &BTreeMap<Yaml, Yaml>,
                      variables: &HashMap<String, String>)
                      -> Result<HashMap<String, Context>, ParseError> {
        let mut contexts = HashMap::new();
        for (key, value) in map.iter() {
            if let (Some(name), Some(val_vec)) = (key.as_str(), value.as_vec()) {
                let context = try!(SyntaxDefinition::parse_context(val_vec, variables));
                contexts.insert(name.to_owned(), context);
            }
        }
        return Ok(contexts);
    }

    fn parse_context(vec: &Vec<Yaml>,
                     variables: &HashMap<String, String>)
                     -> Result<Context, ParseError> {
        let mut context = Context {
            meta_scope: None,
            meta_content_scope: None,
            meta_include_prototype: true,
            patterns: Vec::new(),
        };
        for y in vec.iter() {
            let map = try!(y.as_hash().ok_or(ParseError::TypeMismatch));

            if let Some(x) = get_key(map, "meta_scope", |x| x.as_str()).ok() {
                context.meta_scope = Some(x.to_owned());
            } else if let Some(x) = get_key(map, "meta_content_scope", |x| x.as_str()).ok() {
                context.meta_scope = Some(x.to_owned());
            } else if let Some(x) = get_key(map, "meta_include_prototype", |x| x.as_bool()).ok() {
                context.meta_include_prototype = x;
            } else if let Some(x) = get_key(map, "include", |x| Some(x)).ok() {
                let reference = try!(SyntaxDefinition::parse_reference(x, variables));
                context.patterns.push(Pattern::Include(reference));
            } else {
                let pattern = try!(SyntaxDefinition::parse_match_pattern(map, variables));
                context.patterns.push(Pattern::Match(pattern));
            }

        }
        return Ok(context);
    }

    fn parse_reference(y: &Yaml,
                       variables: &HashMap<String, String>)
                       -> Result<ContextReference, ParseError> {
        if let Some(s) = y.as_str() {
            if s.starts_with("scope:") {
                let scope_ref = &s[6..];
                let parts: Vec<&str> = scope_ref.split("#").collect();
                Ok(ContextReference::ByScope {
                    name: parts[0].to_owned(),
                    sub_context: if parts.len() > 0 {
                        Some(parts[1].to_owned())
                    } else {
                        None
                    },
                })
            } else if s.ends_with(".sublime-syntax") {
                Ok(ContextReference::File(s.to_owned()))
            } else {
                Ok(ContextReference::Named(s.to_owned()))
            }
        } else if let Some(v) = y.as_vec() {
            let context = try!(SyntaxDefinition::parse_context(v, variables));
            Ok(ContextReference::Inline(Box::new(context)))
        } else {
            Err(ParseError::TypeMismatch)
        }
    }

    fn parse_match_pattern(map: &BTreeMap<Yaml, Yaml>,
                           variables: &HashMap<String, String>)
                           -> Result<MatchPattern, ParseError> {
        let raw_regex = try!(get_key(map, "match", |x| x.as_str()));
        let regex = raw_regex.to_owned(); // TODO substitute variables, compile with Onigurama
        let scope = get_key(map, "scope", |x| x.as_str()).ok().map(|s| s.to_owned());
        let pattern = MatchPattern {
            regex: regex,
            scope: scope,
            captures: None, // TODO
            operation: MatchOperation::None, // TODO
        };
        return Ok(pattern);
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn can_parse() {
        use syntax_definition::SyntaxDefinition;
        let defn: SyntaxDefinition =
            SyntaxDefinition::load_from_str("name: C\nscope: source.c\ncontexts: {}").unwrap();
        assert_eq!(defn.name, "C");
        assert_eq!(defn.scope, "source.c");
        let exts_empty: Vec<String> = Vec::new();
        assert_eq!(defn.file_extensions, exts_empty);
        assert_eq!(defn.hidden, false);
        assert!(defn.variables.is_empty());
        let defn2: SyntaxDefinition =
            SyntaxDefinition::load_from_str("
        name: C
        scope: source.c
        file_extensions: [c, h]
        hidden: true
        variables:
          ident: '[A-Za-z_][A-Za-z_0-9]*'
        contexts:
          main:
            - match: \\b(if|else|for|while)\\b
              scope: keyword.control.c
            - match: '\"'
              push: string
          string:
            - meta_scope: string.quoted.double.c
            - match: \\\\.
              scope: constant.character.escape.c
            - match: '\"'
              pop: true
        ")
                .unwrap();
        assert_eq!(defn2.name, "C");
        assert_eq!(defn2.scope, "source.c");
        let exts: Vec<String> = vec![String::from("c"), String::from("h")];
        assert_eq!(defn2.file_extensions, exts);
        assert_eq!(defn2.hidden, true);
        assert_eq!(defn2.variables.get("ident").unwrap(),
                   "[A-Za-z_][A-Za-z_0-9]*");

        let n: Option<String> = None;
        println!("{:?}", defn2);
        assert!(false);
        assert_eq!(defn2.contexts["main"].meta_scope, n);
        assert_eq!(defn2.contexts["main"].meta_include_prototype, true);
        assert_eq!(defn2.contexts["string"].meta_scope,
                   Some(String::from("string.quoted.double.c")));
    }
}
<commit_msg>Implement captures and some operations.<commit_after>use yaml_rust::{YamlLoader, Yaml, ScanError};
use std::collections::{HashMap, BTreeMap};

pub type Regex = String;
pub type ScopeElement = String;
pub type CaptureMapping = HashMap<usize, ScopeElement>;

#[derive(Debug)]
pub struct SyntaxDefinition {
    pub name: String,
    pub file_extensions: Vec<String>,
    pub scope: ScopeElement,
    first_line_match: Option<Regex>,
    pub hidden: bool,

    variables: HashMap<String, String>,
    contexts: HashMap<String, Context>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct Context {
    meta_scope: Option<ScopeElement>,
    meta_content_scope: Option<ScopeElement>,
    meta_include_prototype: bool,

    patterns: Vec<Pattern>,
}

#[derive(Debug, PartialEq, Eq)]
pub enum Pattern {
    Match(MatchPattern),
    Include(ContextReference),
}

#[derive(Debug, PartialEq, Eq)]
pub struct MatchPattern {
    regex: Regex,
    scope: Option<ScopeElement>,
    captures: Option<CaptureMapping>,
    operation: MatchOperation,
}

#[derive(Debug, PartialEq, Eq)]
pub enum ContextReference {
    Named(String),
    ByScope {
        name: String,
        sub_context: Option<String>,
    },
    File(String),
    Inline(Box<Context>),
}

#[derive(Debug, PartialEq, Eq)]
pub enum MatchOperation {
    Push(Vec<ContextReference>),
    Set(Vec<ContextReference>),
    Pop,
    None,
}

#[derive(Debug)]
pub enum ParseError {
    InvalidYaml(ScanError),
    EmptyFile,
    MissingMandatoryKey(&'static str),
    TypeMismatch,
}

fn get_key<'a, R, F: FnOnce(&'a Yaml) -> Option<R>>(map: &'a BTreeMap<Yaml, Yaml>,
                                                    key: &'static str,
                                                    f: F)
                                                    -> Result<R, ParseError> {
    map.get(&Yaml::String(key.to_owned()))
        .ok_or(ParseError::MissingMandatoryKey(key))
        .and_then(|x| f(x).ok_or(ParseError::TypeMismatch))
}

impl SyntaxDefinition {
    pub fn load_from_str(s: &str) -> Result<SyntaxDefinition, ParseError> {
        let docs = match YamlLoader::load_from_str(s) {
            Ok(x) => x,
            Err(e) => return Err(ParseError::InvalidYaml(e)),
        };
        if docs.len() == 0 {
            return Err(ParseError::EmptyFile);
        }
        let doc = &docs[0];
        SyntaxDefinition::parse_top_level(doc)
    }

    fn parse_top_level(doc: &Yaml) -> Result<SyntaxDefinition, ParseError> {
        let h = try!(doc.as_hash().ok_or(ParseError::TypeMismatch));

        let mut variables = HashMap::new();
        if let Ok(map) = get_key(h, "variables", |x| x.as_hash()) {
            for (key, value) in map.iter() {
                if let (Some(key_str), Some(val_str)) = (key.as_str(), value.as_str()) {
                    variables.insert(key_str.to_owned(), val_str.to_owned());
                }
            }
        }

        let contexts_hash = try!(get_key(h, "contexts", |x| x.as_hash()));
        let contexts = try!(SyntaxDefinition::parse_contexts(contexts_hash, &variables));

        let defn = SyntaxDefinition {
            name: try!(get_key(h, "name", |x| x.as_str())).to_owned(),
            scope: try!(get_key(h, "scope", |x| x.as_str())).to_owned(),
            file_extensions: {
                get_key(h, "file_extensions", |x| x.as_vec())
                    .map(|v| v.iter().filter_map(|y| y.as_str()).map(|x| x.to_owned()).collect())
                    .unwrap_or_else(|_| Vec::new())
            },
            first_line_match: get_key(h, "first_line_match", |x| x.as_str())
                .ok()
                .map(|x| x.to_owned()),
            hidden: get_key(h, "hidden", |x| x.as_bool()).unwrap_or(false),

            variables: variables,
            contexts: contexts,
        };
        Ok(defn)
    }

    fn parse_contexts(map: &BTreeMap<Yaml, Yaml>,
                      variables: &HashMap<String, String>)
                      -> Result<HashMap<String, Context>, ParseError> {
        let mut contexts = HashMap::new();
        for (key, value) in map.iter() {
            if let (Some(name), Some(val_vec)) = (key.as_str(), value.as_vec()) {
                let context = try!(SyntaxDefinition::parse_context(val_vec, variables));
                contexts.insert(name.to_owned(), context);
            }
        }
        return Ok(contexts);
    }

    fn parse_context(vec: &Vec<Yaml>,
                     variables: &HashMap<String, String>)
                     -> Result<Context, ParseError> {
        let mut context = Context {
            meta_scope: None,
            meta_content_scope: None,
            meta_include_prototype: true,
            patterns: Vec::new(),
        };
        for y in vec.iter() {
            let map = try!(y.as_hash().ok_or(ParseError::TypeMismatch));

            if let Some(x) = get_key(map, "meta_scope", |x| x.as_str()).ok() {
                context.meta_scope = Some(x.to_owned());
            } else if let Some(x) = get_key(map, "meta_content_scope", |x| x.as_str()).ok() {
                context.meta_scope = Some(x.to_owned());
            } else if let Some(x) = get_key(map, "meta_include_prototype", |x| x.as_bool()).ok() {
                context.meta_include_prototype = x;
            } else if let Some(x) = get_key(map, "include", |x| Some(x)).ok() {
                let reference = try!(SyntaxDefinition::parse_reference(x, variables));
                context.patterns.push(Pattern::Include(reference));
            } else {
                let pattern = try!(SyntaxDefinition::parse_match_pattern(map, variables));
                context.patterns.push(Pattern::Match(pattern));
            }

        }
        return Ok(context);
    }

    fn parse_reference(y: &Yaml,
                       variables: &HashMap<String, String>)
                       -> Result<ContextReference, ParseError> {
        if let Some(s) = y.as_str() {
            if s.starts_with("scope:") {
                let scope_ref = &s[6..];
                let parts: Vec<&str> = scope_ref.split("#").collect();
                Ok(ContextReference::ByScope {
                    name: parts[0].to_owned(),
                    sub_context: if parts.len() > 0 {
                        Some(parts[1].to_owned())
                    } else {
                        None
                    },
                })
            } else if s.ends_with(".sublime-syntax") {
                Ok(ContextReference::File(s.to_owned()))
            } else {
                Ok(ContextReference::Named(s.to_owned()))
            }
        } else if let Some(v) = y.as_vec() {
            let context = try!(SyntaxDefinition::parse_context(v, variables));
            Ok(ContextReference::Inline(Box::new(context)))
        } else {
            Err(ParseError::TypeMismatch)
        }
    }

    fn parse_match_pattern(map: &BTreeMap<Yaml, Yaml>,
                           variables: &HashMap<String, String>)
                           -> Result<MatchPattern, ParseError> {
        let raw_regex = try!(get_key(map, "match", |x| x.as_str()));
        let regex = raw_regex.to_owned(); // TODO substitute variables, compile with Onigurama
        let scope = get_key(map, "scope", |x| x.as_str()).ok().map(|s| s.to_owned());

        let captures = if let Ok(map) = get_key(map, "captures", |x| x.as_hash()) {
            let mut res_map = HashMap::new();
            for (key, value) in map.iter() {
                if let (Some(key_int), Some(val_str)) = (key.as_i64(), value.as_str()) {
                    res_map.insert(key_int as usize, val_str.to_owned());
                }
            }
            Some(res_map)
        } else {
            None
        };

        let operation = if let Ok(map) = get_key(map, "pop", |x| x.as_bool()) {
            MatchOperation::Pop
        } else if let Ok(y) = get_key(map, "push", |x| Some(x)) {
            MatchOperation::Push(vec![try!(SyntaxDefinition::parse_reference(y, variables))])
        } else if let Ok(y) = get_key(map, "set", |x| Some(x)) {
            MatchOperation::Set(vec![try!(SyntaxDefinition::parse_reference(y, variables))])
            // TODO multi-push and multi-pop
        } else {
            MatchOperation::None
        };

        let pattern = MatchPattern {
            regex: regex,
            scope: scope,
            captures: captures,
            operation: operation, // TODO
        };
        return Ok(pattern);
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn can_parse() {
        use syntax_definition::{SyntaxDefinition, Pattern, CaptureMapping, MatchPattern, MatchOperation, ContextReference};
        let defn: SyntaxDefinition =
            SyntaxDefinition::load_from_str("name: C\nscope: source.c\ncontexts: {}").unwrap();
        assert_eq!(defn.name, "C");
        assert_eq!(defn.scope, "source.c");
        let exts_empty: Vec<String> = Vec::new();
        assert_eq!(defn.file_extensions, exts_empty);
        assert_eq!(defn.hidden, false);
        assert!(defn.variables.is_empty());
        let defn2: SyntaxDefinition =
            SyntaxDefinition::load_from_str("
        name: C
        scope: source.c
        file_extensions: [c, h]
        hidden: true
        variables:
          ident: '[A-Za-z_][A-Za-z_0-9]*'
        contexts:
          main:
            - match: \\b(if|else|for|while)\\b
              scope: keyword.control.c
              captures:
                  1: meta.preprocessor.c++
                  2: keyword.control.include.c++
              push: scope:source.c#main
            - match: '\"'
              push: string
          string:
            - meta_scope: string.quoted.double.c
            - match: \\\\.
              scope: constant.character.escape.c
            - match: '\"'
              pop: true
        ")
                .unwrap();
        assert_eq!(defn2.name, "C");
        assert_eq!(defn2.scope, "source.c");
        let exts: Vec<String> = vec![String::from("c"), String::from("h")];
        assert_eq!(defn2.file_extensions, exts);
        assert_eq!(defn2.hidden, true);
        assert_eq!(defn2.variables.get("ident").unwrap(),
                   "[A-Za-z_][A-Za-z_0-9]*");

        let n: Option<String> = None;
        println!("{:?}", defn2);
        // assert!(false);
        assert_eq!(defn2.contexts["main"].meta_scope, n);
        assert_eq!(defn2.contexts["main"].meta_include_prototype, true);
        assert_eq!(defn2.contexts["string"].meta_scope,
                   Some(String::from("string.quoted.double.c")));
        let first_pattern: &Pattern = &defn2.contexts["main"].patterns[0];
        match first_pattern {
            &Pattern::Match(ref match_pat) => {
                let m : &CaptureMapping = match_pat.captures.as_ref().expect("test failed");
                let x : &String = &m[&1];
                assert_eq!(x, "meta.preprocessor.c++");
                assert_eq!(match_pat.operation, MatchOperation::Push(vec![
                    ContextReference::ByScope {
                        name: String::from("source.c"),
                        sub_context: Some(String::from("main"))
                    }]));
            },
            _ => assert!(false)
        }
    }
}
<|endoftext|>


<commit_before>use libc::{self, c_int};
pub use self::os::*;

pub const IPV6_ADD_MEMBERSHIP: c_int = libc::IPV6_ADD_MEMBERSHIP;
pub const IPV6_DROP_MEMBERSHIP: c_int = libc::IPV6_DROP_MEMBERSHIP;

#[cfg(any(target_os = "linux", target_os = "android"))]
mod os {
    use libc::{self, c_int, uint8_t};

    pub const AF_UNIX: c_int  = 1;
    pub const AF_LOCAL: c_int = AF_UNIX;
    pub const AF_INET: c_int  = 2;
    pub const AF_INET6: c_int = 10;

    pub const SOCK_STREAM: c_int = 1;
    pub const SOCK_DGRAM: c_int = 2;
    pub const SOCK_SEQPACKET: c_int = 5;
    pub const SOCK_RAW: c_int = 3;
    pub const SOCK_RDM: c_int = 4;

    pub const SOL_IP: c_int     = 0;
    pub const SOL_SOCKET: c_int = 1;
    pub const SOL_TCP: c_int    = 6;
    pub const SOL_UDP: c_int    = 17;
    pub const SOL_IPV6: c_int   = 41;
    pub const IPPROTO_IP: c_int = SOL_IP;
    pub const IPPROTO_IPV6: c_int = SOL_IPV6;
    pub const IPPROTO_TCP: c_int = SOL_TCP;
    pub const IPPROTO_UDP: c_int = SOL_UDP;

    pub const SO_ACCEPTCONN: c_int = 30;
    pub const SO_BINDTODEVICE: c_int = 25;
    pub const SO_BROADCAST: c_int = 6;
    pub const SO_BSDCOMPAT: c_int = 14;
    pub const SO_DEBUG: c_int = 1;
    pub const SO_DOMAIN: c_int = 39;
    pub const SO_ERROR: c_int = 4;
    pub const SO_DONTROUTE: c_int = 5;
    pub const SO_KEEPALIVE: c_int = 9;
    pub const SO_LINGER: c_int = 13;
    pub const SO_MARK: c_int = 36;
    pub const SO_OOBINLINE: c_int = 10;
    pub const SO_PASSCRED: c_int = 16;
    pub const SO_PEEK_OFF: c_int = 42;
    pub const SO_PEERCRED: c_int = 17;
    pub const SO_PRIORITY: c_int = 12;
    pub const SO_PROTOCOL: c_int = 38;
    pub const SO_RCVBUF: c_int = 8;
    pub const SO_RCVBUFFORCE: c_int = 33;
    pub const SO_RCVLOWAT: c_int = 18;
    pub const SO_SNDLOWAT: c_int = 19;
    pub const SO_RCVTIMEO: c_int = 20;
    pub const SO_SNDTIMEO: c_int = 21;
    pub const SO_REUSEADDR: c_int = 2;
    pub const SO_REUSEPORT: c_int = 15;
    pub const SO_RXQ_OVFL: c_int = 40;
    pub const SO_SNDBUF: c_int = 7;
    pub const SO_SNDBUFFORCE: c_int = 32;
    pub const SO_TIMESTAMP: c_int = 29;
    pub const SO_TYPE: c_int = 3;
    pub const SO_BUSY_POLL: c_int = 46;

    // Socket options for TCP sockets
    pub const TCP_NODELAY: c_int = 1;
    pub const TCP_MAXSEG: c_int = 2;
    pub const TCP_CORK: c_int = 3;
    pub const TCP_KEEPIDLE: c_int = libc::TCP_KEEPIDLE;

    // Socket options for the IP layer of the socket
    pub const IP_MULTICAST_IF: c_int = 32;

    pub type IpMulticastTtl = uint8_t;

    pub const IP_MULTICAST_TTL: c_int = 33;
    pub const IP_MULTICAST_LOOP: c_int = 34;
    pub const IP_ADD_MEMBERSHIP: c_int = 35;
    pub const IP_DROP_MEMBERSHIP: c_int = 36;

    pub type InAddrT = u32;

    // Declarations of special addresses
    pub const INADDR_ANY: InAddrT = 0;
    pub const INADDR_NONE: InAddrT = 0xffffffff;
    pub const INADDR_BROADCAST: InAddrT = 0xffffffff;

    pub type SockMessageFlags = i32;
    // Flags for send/recv and their relatives
    pub const MSG_OOB: SockMessageFlags = 0x1;
    pub const MSG_PEEK: SockMessageFlags = 0x2;
    pub const MSG_DONTWAIT: SockMessageFlags = 0x40;

    // shutdown flags
    pub const SHUT_RD: c_int   = 0;
    pub const SHUT_WR: c_int   = 1;
    pub const SHUT_RDWR: c_int = 2;
}

// Not all of these constants exist on freebsd
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "ios", target_os = "openbsd"))]
mod os {
    use libc::{self, c_int, uint8_t};

    pub const AF_UNIX: c_int  = 1;
    pub const AF_LOCAL: c_int = AF_UNIX;
    pub const AF_INET: c_int  = 2;
    pub const AF_INET6: c_int = 30;

    pub const SOCK_STREAM: c_int = 1;
    pub const SOCK_DGRAM: c_int = 2;
    pub const SOCK_SEQPACKET: c_int = 5;
    pub const SOCK_RAW: c_int = 3;
    pub const SOCK_RDM: c_int = 4;

    pub const SOL_SOCKET: c_int = 0xffff;
    pub const IPPROTO_IP: c_int = 0;
    pub const IPPROTO_IPV6: c_int = 41;
    pub const IPPROTO_TCP: c_int = 6;
    pub const IPPROTO_UDP: c_int = 17;

    pub const SO_ACCEPTCONN: c_int          = 0x0002;
    pub const SO_BROADCAST: c_int           = 0x0020;
    pub const SO_DEBUG: c_int               = 0x0001;
    pub const SO_DONTTRUNC: c_int           = 0x2000;
    pub const SO_ERROR: c_int               = 0x1007;
    pub const SO_DONTROUTE: c_int           = 0x0010;
    pub const SO_KEEPALIVE: c_int           = 0x0008;
    pub const SO_LABEL: c_int               = 0x1010;
    pub const SO_LINGER: c_int              = 0x0080;
    pub const SO_NREAD: c_int               = 0x1020;
    pub const SO_NKE: c_int                 = 0x1021;
    pub const SO_NOSIGPIPE: c_int           = 0x1022;
    pub const SO_NOADDRERR: c_int           = 0x1023;
    pub const SO_NOTIFYCONFLICT: c_int      = 0x1026;
    pub const SO_NP_EXTENSIONS: c_int       = 0x1083;
    pub const SO_NWRITE: c_int              = 0x1024;
    pub const SO_OOBINLINE: c_int           = 0x0100;
    pub const SO_PEERLABEL: c_int           = 0x1011;
    pub const SO_RCVBUF: c_int              = 0x1002;
    pub const SO_RCVLOWAT: c_int            = 0x1004;
    pub const SO_SNDLOWAT: c_int            = 0x1003;
    pub const SO_RCVTIMEO: c_int            = 0x1006;
    pub const SO_SNDTIMEO: c_int            = 0x1005;
    pub const SO_RANDOMPORT: c_int          = 0x1082;
    pub const SO_RESTRICTIONS: c_int        = 0x1081;
    pub const SO_RESTRICT_DENYIN: c_int     = 0x00000001;
    pub const SO_RESTRICT_DENYOUT: c_int    = 0x00000002;
    pub const SO_REUSEADDR: c_int           = 0x0004;
    pub const SO_REUSEPORT: c_int           = 0x0200;
    pub const SO_REUSESHAREUID: c_int       = 0x1025;
    pub const SO_SNDBUF: c_int              = 0x1001;
    pub const SO_TIMESTAMP: c_int           = 0x0400;
    pub const SO_TIMESTAMP_MONOTONIC: c_int = 0x0800;
    pub const SO_TYPE: c_int                = 0x1008;
    pub const SO_WANTMORE: c_int            = 0x4000;
    pub const SO_WANTOOBFLAG: c_int         = 0x8000;
    #[allow(overflowing_literals)]
    pub const SO_RESTRICT_DENYSET: c_int    = 0x80000000;

    // Socket options for TCP sockets
    pub const TCP_NODELAY: c_int = 1;
    pub const TCP_MAXSEG: c_int = 2;
    #[cfg(any(target_os = "macos",
              target_os = "ios"))]
    pub const TCP_KEEPALIVE: c_int = libc::TCP_KEEPALIVE;
    #[cfg(target_os = "freebsd")]
    pub const TCP_KEEPIDLE: c_int = libc::TCP_KEEPIDLE;

    // Socket options for the IP layer of the socket
    pub const IP_MULTICAST_IF: c_int = 9;

    pub type IpMulticastTtl = uint8_t;

    pub const IP_MULTICAST_TTL: c_int = 10;
    pub const IP_MULTICAST_LOOP: c_int = 11;
    pub const IP_ADD_MEMBERSHIP: c_int = 12;
    pub const IP_DROP_MEMBERSHIP: c_int = 13;

    pub type InAddrT = u32;

    // Declarations of special addresses
    pub const INADDR_ANY: InAddrT = 0;
    pub const INADDR_NONE: InAddrT = 0xffffffff;
    pub const INADDR_BROADCAST: InAddrT = 0xffffffff;

    pub type SockMessageFlags = i32;
    // Flags for send/recv and their relatives
    pub const MSG_OOB: SockMessageFlags = 0x1;
    pub const MSG_PEEK: SockMessageFlags = 0x2;
    pub const MSG_DONTWAIT: SockMessageFlags = 0x80;

    // shutdown flags
    pub const SHUT_RD: c_int   = 0;
    pub const SHUT_WR: c_int   = 1;
    pub const SHUT_RDWR: c_int = 2;
}

#[cfg(test)]
mod test {
    use super::*;
    use nixtest::assert_const_eq;
    use libc::c_int;

    macro_rules! check_const {
        ($($konst:ident),+) => {{
            $(assert_const_eq(stringify!($konst), $konst as c_int);)+
        }};
    }

    #[test]
    pub fn test_const_values() {
        check_const!(
            AF_UNIX,
            AF_LOCAL,
            AF_INET,
            AF_INET6,
            SOCK_STREAM,
            SOCK_DGRAM,
            SOCK_SEQPACKET,
            SOCK_RAW,
            SOCK_RDM,
            SOL_SOCKET,
            IPPROTO_IP,
            IPPROTO_IPV6,
            IPPROTO_TCP,
            IPPROTO_UDP,
            SO_ACCEPTCONN,
            SO_BROADCAST,
            SO_DEBUG,
            SO_ERROR,
            SO_DONTROUTE,
            SO_KEEPALIVE,
            SO_LINGER,
            SO_OOBINLINE,
            SO_RCVBUF,
            SO_RCVLOWAT,
            SO_SNDLOWAT,
            SO_RCVTIMEO,
            SO_SNDTIMEO,
            SO_REUSEADDR,
            // SO_REUSEPORT,
            SO_SNDBUF,
            SO_TIMESTAMP,
            SO_TYPE,
            TCP_NODELAY,
            TCP_MAXSEG,
            IP_MULTICAST_IF,
            IP_MULTICAST_TTL,
            IP_MULTICAST_LOOP,
            IP_ADD_MEMBERSHIP,
            IP_DROP_MEMBERSHIP,
            INADDR_ANY,
            INADDR_NONE,
            INADDR_BROADCAST,
            MSG_OOB,
            MSG_PEEK,
            MSG_DONTWAIT,
            SHUT_RD,
            SHUT_WR,
            SHUT_RDWR
            );

    }

    #[cfg(target_os = "linux")]
    #[test]
    pub fn test_linux_consts() {
        // TODO Figure out how to test new constants
        check_const!(
            SOL_IP,
            SOL_TCP,
            SOL_UDP,
            SOL_IPV6,
            SO_BINDTODEVICE,
            SO_BSDCOMPAT,
            // SO_DOMAIN,
            // SO_MARK,
            TCP_CORK,
            // SO_BUSY_POLL,
            // SO_RXQ_OVFL,
            SO_PASSCRED,
            SO_PRIORITY,
            // SO_PROTOCOL,
            SO_RCVBUFFORCE,
            // SO_PEEK_OFF,
            SO_PEERCRED,
            SO_SNDBUFFORCE);
    }
}
<commit_msg>Remove import on those platforms where it is unused.<commit_after>use libc::{self, c_int};
pub use self::os::*;

pub const IPV6_ADD_MEMBERSHIP: c_int = libc::IPV6_ADD_MEMBERSHIP;
pub const IPV6_DROP_MEMBERSHIP: c_int = libc::IPV6_DROP_MEMBERSHIP;

#[cfg(any(target_os = "linux", target_os = "android"))]
mod os {
    use libc::{self, c_int, uint8_t};

    pub const AF_UNIX: c_int  = 1;
    pub const AF_LOCAL: c_int = AF_UNIX;
    pub const AF_INET: c_int  = 2;
    pub const AF_INET6: c_int = 10;

    pub const SOCK_STREAM: c_int = 1;
    pub const SOCK_DGRAM: c_int = 2;
    pub const SOCK_SEQPACKET: c_int = 5;
    pub const SOCK_RAW: c_int = 3;
    pub const SOCK_RDM: c_int = 4;

    pub const SOL_IP: c_int     = 0;
    pub const SOL_SOCKET: c_int = 1;
    pub const SOL_TCP: c_int    = 6;
    pub const SOL_UDP: c_int    = 17;
    pub const SOL_IPV6: c_int   = 41;
    pub const IPPROTO_IP: c_int = SOL_IP;
    pub const IPPROTO_IPV6: c_int = SOL_IPV6;
    pub const IPPROTO_TCP: c_int = SOL_TCP;
    pub const IPPROTO_UDP: c_int = SOL_UDP;

    pub const SO_ACCEPTCONN: c_int = 30;
    pub const SO_BINDTODEVICE: c_int = 25;
    pub const SO_BROADCAST: c_int = 6;
    pub const SO_BSDCOMPAT: c_int = 14;
    pub const SO_DEBUG: c_int = 1;
    pub const SO_DOMAIN: c_int = 39;
    pub const SO_ERROR: c_int = 4;
    pub const SO_DONTROUTE: c_int = 5;
    pub const SO_KEEPALIVE: c_int = 9;
    pub const SO_LINGER: c_int = 13;
    pub const SO_MARK: c_int = 36;
    pub const SO_OOBINLINE: c_int = 10;
    pub const SO_PASSCRED: c_int = 16;
    pub const SO_PEEK_OFF: c_int = 42;
    pub const SO_PEERCRED: c_int = 17;
    pub const SO_PRIORITY: c_int = 12;
    pub const SO_PROTOCOL: c_int = 38;
    pub const SO_RCVBUF: c_int = 8;
    pub const SO_RCVBUFFORCE: c_int = 33;
    pub const SO_RCVLOWAT: c_int = 18;
    pub const SO_SNDLOWAT: c_int = 19;
    pub const SO_RCVTIMEO: c_int = 20;
    pub const SO_SNDTIMEO: c_int = 21;
    pub const SO_REUSEADDR: c_int = 2;
    pub const SO_REUSEPORT: c_int = 15;
    pub const SO_RXQ_OVFL: c_int = 40;
    pub const SO_SNDBUF: c_int = 7;
    pub const SO_SNDBUFFORCE: c_int = 32;
    pub const SO_TIMESTAMP: c_int = 29;
    pub const SO_TYPE: c_int = 3;
    pub const SO_BUSY_POLL: c_int = 46;

    // Socket options for TCP sockets
    pub const TCP_NODELAY: c_int = 1;
    pub const TCP_MAXSEG: c_int = 2;
    pub const TCP_CORK: c_int = 3;
    pub const TCP_KEEPIDLE: c_int = libc::TCP_KEEPIDLE;

    // Socket options for the IP layer of the socket
    pub const IP_MULTICAST_IF: c_int = 32;

    pub type IpMulticastTtl = uint8_t;

    pub const IP_MULTICAST_TTL: c_int = 33;
    pub const IP_MULTICAST_LOOP: c_int = 34;
    pub const IP_ADD_MEMBERSHIP: c_int = 35;
    pub const IP_DROP_MEMBERSHIP: c_int = 36;

    pub type InAddrT = u32;

    // Declarations of special addresses
    pub const INADDR_ANY: InAddrT = 0;
    pub const INADDR_NONE: InAddrT = 0xffffffff;
    pub const INADDR_BROADCAST: InAddrT = 0xffffffff;

    pub type SockMessageFlags = i32;
    // Flags for send/recv and their relatives
    pub const MSG_OOB: SockMessageFlags = 0x1;
    pub const MSG_PEEK: SockMessageFlags = 0x2;
    pub const MSG_DONTWAIT: SockMessageFlags = 0x40;

    // shutdown flags
    pub const SHUT_RD: c_int   = 0;
    pub const SHUT_WR: c_int   = 1;
    pub const SHUT_RDWR: c_int = 2;
}

// Not all of these constants exist on freebsd
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "ios", target_os = "openbsd"))]
mod os {
    #[cfg(any(target_os = "macos",
              target_os = "ios",
              target_os = "freebsd"))]
    use libc::{self, c_int, uint8_t};
    #[cfg(any(target_os = "openbsd"))]
    use libc::{c_int, uint8_t};

    pub const AF_UNIX: c_int  = 1;
    pub const AF_LOCAL: c_int = AF_UNIX;
    pub const AF_INET: c_int  = 2;
    pub const AF_INET6: c_int = 30;

    pub const SOCK_STREAM: c_int = 1;
    pub const SOCK_DGRAM: c_int = 2;
    pub const SOCK_SEQPACKET: c_int = 5;
    pub const SOCK_RAW: c_int = 3;
    pub const SOCK_RDM: c_int = 4;

    pub const SOL_SOCKET: c_int = 0xffff;
    pub const IPPROTO_IP: c_int = 0;
    pub const IPPROTO_IPV6: c_int = 41;
    pub const IPPROTO_TCP: c_int = 6;
    pub const IPPROTO_UDP: c_int = 17;

    pub const SO_ACCEPTCONN: c_int          = 0x0002;
    pub const SO_BROADCAST: c_int           = 0x0020;
    pub const SO_DEBUG: c_int               = 0x0001;
    pub const SO_DONTTRUNC: c_int           = 0x2000;
    pub const SO_ERROR: c_int               = 0x1007;
    pub const SO_DONTROUTE: c_int           = 0x0010;
    pub const SO_KEEPALIVE: c_int           = 0x0008;
    pub const SO_LABEL: c_int               = 0x1010;
    pub const SO_LINGER: c_int              = 0x0080;
    pub const SO_NREAD: c_int               = 0x1020;
    pub const SO_NKE: c_int                 = 0x1021;
    pub const SO_NOSIGPIPE: c_int           = 0x1022;
    pub const SO_NOADDRERR: c_int           = 0x1023;
    pub const SO_NOTIFYCONFLICT: c_int      = 0x1026;
    pub const SO_NP_EXTENSIONS: c_int       = 0x1083;
    pub const SO_NWRITE: c_int              = 0x1024;
    pub const SO_OOBINLINE: c_int           = 0x0100;
    pub const SO_PEERLABEL: c_int           = 0x1011;
    pub const SO_RCVBUF: c_int              = 0x1002;
    pub const SO_RCVLOWAT: c_int            = 0x1004;
    pub const SO_SNDLOWAT: c_int            = 0x1003;
    pub const SO_RCVTIMEO: c_int            = 0x1006;
    pub const SO_SNDTIMEO: c_int            = 0x1005;
    pub const SO_RANDOMPORT: c_int          = 0x1082;
    pub const SO_RESTRICTIONS: c_int        = 0x1081;
    pub const SO_RESTRICT_DENYIN: c_int     = 0x00000001;
    pub const SO_RESTRICT_DENYOUT: c_int    = 0x00000002;
    pub const SO_REUSEADDR: c_int           = 0x0004;
    pub const SO_REUSEPORT: c_int           = 0x0200;
    pub const SO_REUSESHAREUID: c_int       = 0x1025;
    pub const SO_SNDBUF: c_int              = 0x1001;
    pub const SO_TIMESTAMP: c_int           = 0x0400;
    pub const SO_TIMESTAMP_MONOTONIC: c_int = 0x0800;
    pub const SO_TYPE: c_int                = 0x1008;
    pub const SO_WANTMORE: c_int            = 0x4000;
    pub const SO_WANTOOBFLAG: c_int         = 0x8000;
    #[allow(overflowing_literals)]
    pub const SO_RESTRICT_DENYSET: c_int    = 0x80000000;

    // Socket options for TCP sockets
    pub const TCP_NODELAY: c_int = 1;
    pub const TCP_MAXSEG: c_int = 2;
    #[cfg(any(target_os = "macos",
              target_os = "ios"))]
    pub const TCP_KEEPALIVE: c_int = libc::TCP_KEEPALIVE;
    #[cfg(target_os = "freebsd")]
    pub const TCP_KEEPIDLE: c_int = libc::TCP_KEEPIDLE;

    // Socket options for the IP layer of the socket
    pub const IP_MULTICAST_IF: c_int = 9;

    pub type IpMulticastTtl = uint8_t;

    pub const IP_MULTICAST_TTL: c_int = 10;
    pub const IP_MULTICAST_LOOP: c_int = 11;
    pub const IP_ADD_MEMBERSHIP: c_int = 12;
    pub const IP_DROP_MEMBERSHIP: c_int = 13;

    pub type InAddrT = u32;

    // Declarations of special addresses
    pub const INADDR_ANY: InAddrT = 0;
    pub const INADDR_NONE: InAddrT = 0xffffffff;
    pub const INADDR_BROADCAST: InAddrT = 0xffffffff;

    pub type SockMessageFlags = i32;
    // Flags for send/recv and their relatives
    pub const MSG_OOB: SockMessageFlags = 0x1;
    pub const MSG_PEEK: SockMessageFlags = 0x2;
    pub const MSG_DONTWAIT: SockMessageFlags = 0x80;

    // shutdown flags
    pub const SHUT_RD: c_int   = 0;
    pub const SHUT_WR: c_int   = 1;
    pub const SHUT_RDWR: c_int = 2;
}

#[cfg(test)]
mod test {
    use super::*;
    use nixtest::assert_const_eq;
    use libc::c_int;

    macro_rules! check_const {
        ($($konst:ident),+) => {{
            $(assert_const_eq(stringify!($konst), $konst as c_int);)+
        }};
    }

    #[test]
    pub fn test_const_values() {
        check_const!(
            AF_UNIX,
            AF_LOCAL,
            AF_INET,
            AF_INET6,
            SOCK_STREAM,
            SOCK_DGRAM,
            SOCK_SEQPACKET,
            SOCK_RAW,
            SOCK_RDM,
            SOL_SOCKET,
            IPPROTO_IP,
            IPPROTO_IPV6,
            IPPROTO_TCP,
            IPPROTO_UDP,
            SO_ACCEPTCONN,
            SO_BROADCAST,
            SO_DEBUG,
            SO_ERROR,
            SO_DONTROUTE,
            SO_KEEPALIVE,
            SO_LINGER,
            SO_OOBINLINE,
            SO_RCVBUF,
            SO_RCVLOWAT,
            SO_SNDLOWAT,
            SO_RCVTIMEO,
            SO_SNDTIMEO,
            SO_REUSEADDR,
            // SO_REUSEPORT,
            SO_SNDBUF,
            SO_TIMESTAMP,
            SO_TYPE,
            TCP_NODELAY,
            TCP_MAXSEG,
            IP_MULTICAST_IF,
            IP_MULTICAST_TTL,
            IP_MULTICAST_LOOP,
            IP_ADD_MEMBERSHIP,
            IP_DROP_MEMBERSHIP,
            INADDR_ANY,
            INADDR_NONE,
            INADDR_BROADCAST,
            MSG_OOB,
            MSG_PEEK,
            MSG_DONTWAIT,
            SHUT_RD,
            SHUT_WR,
            SHUT_RDWR
            );

    }

    #[cfg(target_os = "linux")]
    #[test]
    pub fn test_linux_consts() {
        // TODO Figure out how to test new constants
        check_const!(
            SOL_IP,
            SOL_TCP,
            SOL_UDP,
            SOL_IPV6,
            SO_BINDTODEVICE,
            SO_BSDCOMPAT,
            // SO_DOMAIN,
            // SO_MARK,
            TCP_CORK,
            // SO_BUSY_POLL,
            // SO_RXQ_OVFL,
            SO_PASSCRED,
            SO_PRIORITY,
            // SO_PROTOCOL,
            SO_RCVBUFFORCE,
            // SO_PEEK_OFF,
            SO_PEERCRED,
            SO_SNDBUFFORCE);
    }
}
<|endoftext|>


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

#![allow(non_snake_case)]

register_long_diagnostics! {

E0381: r##"
It is not allowed to use or capture an uninitialized variable. For example:

```
fn main() {
    let x: i32;
    let y = x; // error, use of possibly uninitialized variable
```

To fix this, ensure that any declared variables are initialized before being
used.
"##

}

register_diagnostics! {
    E0373, // closure may outlive current fn, but it borrows {}, which is owned by current fn
    E0382, // use of partially/collaterally moved value
    E0383, // partial reinitialization of uninitialized structure
    E0384, // reassignment of immutable variable
    E0385, // {} in an aliasable location
    E0386, // {} in an immutable container
    E0387, // {} in a captured outer variable in an `Fn` closure
    E0388, // {} in a static location
    E0389  // {} in a `&` reference
}
<commit_msg>Add long diagnostics for E0373<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_snake_case)]

register_long_diagnostics! {

E0373: r##"
This error occurs when an attempt is made to use data captured by a closure,
when that data may no longer exist. It's most commonly seen when attempting to
return a closure:

```
fn foo() -> Box<Fn(u32) -> u32> {
    let x = 0u32;
    Box::new(|y| x + y)
}
```

Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
closed-over data by reference. This means that once `foo()` returns, `x` no
longer exists. An attempt to access `x` within the closure would thus be unsafe.

Another situation where this might be encountered is when spawning threads:

```
fn foo() {
    let x = 0u32;
    let y = 1u32;

    let thr = std::thread::spawn(|| {
        x + y
    });
}
```

Since our new thread runs in parallel, the stack frame containing `x` and `y`
may well have disappeared by the time we try to use them. Even if we call
`thr.join()` within foo (which blocks until `thr` has completed, ensuring the
stack frame won't disappear), we will not succeed: the compiler cannot prove
that this behaviour is safe, and so won't let us do it.

The solution to this problem is usually to switch to using a `move` closure.
This approach moves (or copies, where possible) data into the closure, rather
than taking references to it. For example:

```
fn foo() -> Box<Fn(u32) -> u32> {
    let x = 0u32;
    Box::new(move |y| x + y)
}
```

Now that the closure has its own copy of the data, there's no need to worry
about safety.
"##,

E0381: r##"
It is not allowed to use or capture an uninitialized variable. For example:

```
fn main() {
    let x: i32;
    let y = x; // error, use of possibly uninitialized variable
```

To fix this, ensure that any declared variables are initialized before being
used.
"##

}

register_diagnostics! {
    E0382, // use of partially/collaterally moved value
    E0383, // partial reinitialization of uninitialized structure
    E0384, // reassignment of immutable variable
    E0385, // {} in an aliasable location
    E0386, // {} in an immutable container
    E0387, // {} in a captured outer variable in an `Fn` closure
    E0388, // {} in a static location
    E0389  // {} in a `&` reference
}
<|endoftext|>


<commit_before>use magazine_cutout::*;

#[test]
fn test_example_works() {
    let magazine = "two times three is not four"
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "two times two is four"
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(!can_construct_note(&magazine, &note));
}

#[test]
#[ignore]
fn test_fn_returns_true_for_good_input() {
    let magazine = "The metro orchestra unveiled its new grand piano today. Its donor paraphrased Nathn Hale: \"I only regret that I have but one to give \"".split_whitespace().collect::<Vec<&str>>();
    let note = "give one grand today."
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(can_construct_note(&magazine, &note));
}

#[test]
#[ignore]
fn test_fn_returns_false_for_bad_input() {
    let magazine = "I've got a lovely bunch of coconuts."
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "I've got som coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(!can_construct_note(&magazine, &note));
}

#[test]
#[ignore]
fn test_case_sensitivity() {
    let magazine = "i've got some lovely coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "I've got some coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(!can_construct_note(&magazine, &note));

    let magazine = "I've got some lovely coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "i've got some coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(!can_construct_note(&magazine, &note));
}
<commit_msg>Update Magazine Cutout (#1321)<commit_after>use magazine_cutout::*;

#[test]
fn test_example_works() {
    let magazine = "two times three is not four"
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "two times two is four"
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(!can_construct_note(&magazine, &note));
}

#[test]
#[ignore]
fn test_fn_returns_true_for_good_input() {
    let magazine = "The metro orchestra unveiled its new grand piano today. Its donor paraphrased Nathn Hale: \"I only regret that I have but one to give \"".split_whitespace().collect::<Vec<&str>>();
    let note = "give one grand today."
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(can_construct_note(&magazine, &note));
}

#[test]
#[ignore]
fn test_fn_returns_false_for_bad_input() {
    let magazine = "I've got a lovely bunch of coconuts."
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "I've got som coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(!can_construct_note(&magazine, &note));
}

#[test]
#[ignore]
fn test_case_sensitivity() {
    let magazine = "i've got some lovely coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "I've got some coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(!can_construct_note(&magazine, &note));

    let magazine = "I've got some lovely coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "i've got some coconuts"
        .split_whitespace()
        .collect::<Vec<&str>>();
    assert!(!can_construct_note(&magazine, &note));
}

#[test]
#[ignore]
fn test_magzine_has_more_than_words_available_than_needed() {
    let magazine = "Enough is enough when enough is enough"
        .split_whitespace()
        .collect::<Vec<&str>>();
    let note = "enough is enough".split_whitespace().collect::<Vec<&str>>();
    assert!(can_construct_note(&magazine, &note));
}
<|endoftext|>