<commit_before>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable)]
pub struct Version {
    pub name: String,
    pub vers: String,
    pub deps: Vec<Dependency>,
    pub cksum: String,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable)]
pub struct Dependency {
    pub name: String,
    pub req: String,
    pub features: Vec<String>,
    pub optional: bool,
    pub default_features: bool,
    pub target: Option<String>,
    pub kind: Option<String>
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }

    /// Generates a map of dependencies where the keys are crate names and the values are vectors
    /// of crate names that are its dependencies
    pub fn dependency_map(&self) -> HashMap<String, Vec<String>> {
        let mut map = HashMap::new();
        for crate_ in self.crates() {
            let version = crate_.latest_version();
            let mut deps_names = version.deps.iter().map(|d| d.name.clone()).collect::<Vec<_>>();
            deps_names.sort_by(|a, b| a.cmp(b));
            deps_names.dedup();
            map.insert(version.name.clone(), deps_names);
        }

        map
    }
}

pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len()]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
}
<commit_msg>Fix off-by-one error with latest_version<commit_after>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable)]
pub struct Version {
    pub name: String,
    pub vers: String,
    pub deps: Vec<Dependency>,
    pub cksum: String,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable)]
pub struct Dependency {
    pub name: String,
    pub req: String,
    pub features: Vec<String>,
    pub optional: bool,
    pub default_features: bool,
    pub target: Option<String>,
    pub kind: Option<String>
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }

    /// Generates a map of dependencies where the keys are crate names and the values are vectors
    /// of crate names that are its dependencies
    pub fn dependency_map(&self) -> HashMap<String, Vec<String>> {
        let mut map = HashMap::new();
        for crate_ in self.crates() {
            let version = crate_.latest_version();
            let mut deps_names = version.deps.iter().map(|d| d.name.clone()).collect::<Vec<_>>();
            deps_names.sort_by(|a, b| a.cmp(b));
            deps_names.dedup();
            map.insert(version.name.clone(), deps_names);
        }

        map
    }
}

pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate pad;
extern crate regex;
extern crate colored;

pub mod types;
pub mod parser;

use std::fs;
use std::path::PathBuf;
use regex::Regex;
use types::*;
use colored::*;

fn is_artifact(p: PathBuf, re: Option<Regex>) -> bool {
    let regex = if let Some(r) = re { r }
        else { Regex::new(r"^\S+.a").unwrap() };
    let path_str = &p.into_os_string().into_string().expect("OS String invalid.");
    regex.is_match(path_str)
}

pub fn read_files(in_paths: &PathBuf, depth: u8, min_bytes: Option<u64>) -> FileTree {
    let paths = fs::read_dir(&in_paths).unwrap();
    let mut tree = FileTree::new();
    let mut total_size = FileSize::new(0);

    for p in paths {
        let path = p.unwrap().path(); // TODO no unwraps b/c broken symlinks

        // if this fails, it's probably because `path` is a symlink, so we ignore it.
        if let Ok(metadata) = fs::metadata(&path) {
            // append file size/name for a file
            if metadata.is_file() {
                let file_size = FileSize::new(metadata.len());
                if let Some(b) = min_bytes {
                    if file_size >= FileSize::new(b) {
                        tree.push(path.clone(), file_size, None, depth + 1);
                    }
                }
                else {
                    tree.push(path, file_size, None, depth + 1);
                }
                total_size.add(file_size);
            }

            // otherwise, go deeper
            else if metadata.is_dir() {
                let mut subtree = read_files(&path, depth + 1, min_bytes);
                let dir_size = subtree.file_size;
                if let Some(b) = min_bytes {
                    if dir_size >= FileSize::new(b) {
                        tree.push(path, dir_size, Some(&mut subtree), depth + 1);
                    }
                }
                else {
                    tree.push(path, dir_size, Some(&mut subtree), depth + 1);
                }
                total_size.add(dir_size);
            }
        }
        else {
            println!("{}: ignoring symlink at {}", "Warning".yellow(), path.display());
        }
    }
    tree
}

<commit_msg>permissions fix?<commit_after>extern crate pad;
extern crate regex;
extern crate colored;

pub mod types;
pub mod parser;

use std::fs;
use std::path::PathBuf;
use regex::Regex;
use types::*;
use colored::*;

fn is_artifact(p: PathBuf, re: Option<Regex>) -> bool {
    let regex = if let Some(r) = re { r }
        else { Regex::new(r"^\S+.a").unwrap() };
    let path_str = &p.into_os_string().into_string().expect("OS String invalid.");
    regex.is_match(path_str)
}

pub fn read_files(in_paths: &PathBuf, depth: u8, min_bytes: Option<u64>) -> FileTree {
    let mut tree = FileTree::new();
    let mut total_size = FileSize::new(0);

    if let Some(paths) = fs::read_dir(&in_paths) {
        for p in paths {
            let path = p.unwrap().path(); // TODO no unwraps b/c broken symlinks

            // if this fails, it's probably because `path` is a symlink, so we ignore it.
            if let Ok(metadata) = fs::metadata(&path) {
                // append file size/name for a file
                if metadata.is_file() {
                    let file_size = FileSize::new(metadata.len());
                    if let Some(b) = min_bytes {
                        if file_size >= FileSize::new(b) {
                            tree.push(path.clone(), file_size, None, depth + 1);
                        }
                    }
                    else {
                        tree.push(path, file_size, None, depth + 1);
                    }
                    total_size.add(file_size);
                }

                // otherwise, go deeper
                else if metadata.is_dir() {
                    let mut subtree = read_files(&path, depth + 1, min_bytes);
                    let dir_size = subtree.file_size;
                    if let Some(b) = min_bytes {
                        if dir_size >= FileSize::new(b) {
                            tree.push(path, dir_size, Some(&mut subtree), depth + 1);
                        }
                    }
                    else {
                        tree.push(path, dir_size, Some(&mut subtree), depth + 1);
                    }
                    total_size.add(dir_size);
                }
            }
            else {
                println!("{}: ignoring symlink at {}", "Warning".yellow(), path.display());
            }
        }
    }
    else {
        println!("{}: permission denied for directory", "Warning".yellow());
    }
    tree
}
<|endoftext|>


<commit_before>//! # Endofunctor composition via the Co-Yoneda Lemma
//!
//! ## Functors in Rust
//!
//! Let's implement functors in Rust!
//!
//! Working around the lack of higher-kinded types, our trait for a functor
//! will look something like this:
//!
//! ```
//! pub trait Functor<A, B> {
//!    type Output;
//!    fn fmap<F: Fn(A) -> B>(self, F) -> Self::Output;
//! }
//! ```
//!
//! This works great as long as we write functions that take specific
//! types which are functors, but it is not possible to write a function
//! operating on a generic functor type and using `fmap` more than once.
//! For example, the following will not compile:
//!
//! ```
//! fn add_and_to_string<F: Functor<i32, String>>(x: F) -> F::Output {
//!    x.fmap(|n: i32| n + 1)
//!     .fmap(|n: i32| n.to_string())
//! }
//! ```
//!
//! While functors in general can be encoded to some extend
//! in Rust's trait system, what we usually mean when we
//! say "Functor" is a covariant endofunctor.
//! An endofunctor is a functor that maps back to the same category,
//! e.g. it maps a function between `A` and `B` to a function between
//! `Box<A>` and `Box<B>`, not between `Box<A>` and `Option<B>`.
//!
//! Especially when looking at functor composition, it is useful to
//! be able to encode endofunctors, because it allows us to chain
//! multiple calls to `fmap`, knowing that the result is also a functor,
//! and can be `fmap`'ed further. In Rust this is not possible,
//! because of a lack of higher-kinded types.
//!
//! ## The Co-Yoneda Lemma
//!
//! Let's define a data type called `Coyoneda`:
//!
//! ```
//! Coyoneda :: (b -> a) -> f b -> Coyoneda f a
//! ```
//!
//! This datatype is a functor, which uses function composition
//! to accumulate the mapping function, without changing the captured
//! `f b`. The implementation for `fmap` is trivial:
//!
//! ```
//! fmap f (Coyoneda g a) = Coyoneda (f . g) a
//! ```
//!
//! The co-yoneda lemma states that for a covariant functor `f`,
//! this `Coyoneda f` is naturally isomorphic to `f`.
//! Practically speaking, this means that we can lift any `f a` into a `Coyoneda f a`,
//! and given a function `(a -> b) -> f b`, we can retrieve back a `f b` from a `Coyoneda f b`.
//!
//! ## Composing Coyoneda
//!
//! Now here's the catch: Since we have a parameterized datatype that is isomorphic to any functor,
//! we can lift functors into Coyoneda to compose them safely within Rust's type system!
//!
//! For example, let's implement a function that is generic for any functor:
//!
//! ```
//! fn add_and_to_string<T, A>(y: Coyoneda<T, A, i32>) -> Coyoneda<T, A, String> {
//!    y.map(|n: i32| n + 1)
//!     .map(|n: i32| n.to_string())
//! }!
//! ```
//!
//! Given we implemented a functor for `Option`, we can now do the following:
//!
//! ```
//! let y = add_and_to_string(From::from(Some(42)));
//! assert_eq!(y.unwrap(), Some("43".to_string()))
//! ```
//!
//! ... or for `Box`:
//!
//! ```
//! let y = add_and_to_string(From::from(Box::new(42)));
//! assert_eq!(y.unwrap(), Box::new("43".to_string()))
//! ```
//!
//! ... and for every other functor as well. Yay!

#![feature(box_syntax)]
#![feature(core)]
#![feature(unboxed_closures)]
mod morphism;

use morphism::Morphism;

pub struct Coyoneda<'a, T, A, B> {
    point: T,
    morph: Morphism<'a, A, B>
}

impl<'a, T, A, B> Coyoneda<'a, T, A, B> {

    pub fn map<C, F: Fn(B) -> C + 'a>(self, f: F) -> Coyoneda<'a, T, A, C> {
        Coyoneda{point: self.point, morph: self.morph.tail(f)}
    }

    pub fn unwrap(self) -> <T as Functor<A, B>>::Output where T: Functor<A, B> {
        T::fmap(self.point, self.morph)
    }

}

impl<'a, T, A> From<T> for Coyoneda<'a, T, A, A> {
    fn from(x: T) -> Coyoneda<'a, T, A, A> {
        Coyoneda{point: x, morph: Morphism::new()}
    }
}

pub trait Functor<A, B> {
    type Output;
    fn fmap<F: Fn(A) -> B>(self, F) -> Self::Output;
}

impl<A, B> Functor<A, B> for Box<A> {
    type Output = Box<B>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Box::new(f(*self))
    }
}

impl<A, B> Functor<A, B> for Option<A> {
    type Output = Option<B>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Option::map(self, f)
    }
}

impl<A, B, E> Functor<A, B> for Result<A, E> {
    type Output = Result<B, E>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Result::map(self, f)
    }
}

mod test {
#![cfg(test)]

    use super::*;

    fn add_and_to_string<T, A>(y: Coyoneda<T, A, i32>) -> Coyoneda<T, A, String> {
        y.map(|n: i32| n + 1)
         .map(|n: i32| n.to_string())
         .map(|s| s + "foo")
         .map(|s| s + "bar")
    }

    #[test]
    fn test_box() {
        let x = Box::new(42);
        let y = add_and_to_string(From::from(x)).unwrap();
        assert_eq!(y, Box::new("43foobar".to_string()))
    }

    #[test]
    fn test_option() {
        let x = Some(42);
        let y = add_and_to_string(From::from(x)).unwrap();
        assert_eq!(y, Some("43foobar".to_string()))
    }

    #[test]
    fn test_result() {
        let x: Result<i32, ()> = Ok(42);
        let y = add_and_to_string(From::from(x)).unwrap();
        assert_eq!(y, Ok("43foobar".to_string()))
    }

}
<commit_msg>make functor param existential<commit_after>//! # Endofunctor composition via the Co-Yoneda Lemma
//!
//! ## Functors in Rust
//!
//! Let's implement functors in Rust!
//!
//! Working around the lack of higher-kinded types, our trait for a functor
//! will look something like this:
//!
//! ```
//! pub trait Functor<A, B> {
//!    type Output;
//!    fn fmap<F: Fn(A) -> B>(self, F) -> Self::Output;
//! }
//! ```
//!
//! This works great as long as we write functions that take specific
//! types which are functors, but it is not possible to write a function
//! operating on a generic functor type and using `fmap` more than once.
//! For example, the following will not compile:
//!
//! ```
//! fn add_and_to_string<F: Functor<i32, String>>(x: F) -> F::Output {
//!    x.fmap(|n: i32| n + 1)
//!     .fmap(|n: i32| n.to_string())
//! }
//! ```
//!
//! While functors in general can be encoded to some extend
//! in Rust's trait system, what we usually mean when we
//! say "Functor" is a covariant endofunctor.
//! An endofunctor is a functor that maps back to the same category,
//! e.g. it maps a function between `A` and `B` to a function between
//! `Box<A>` and `Box<B>`, not between `Box<A>` and `Option<B>`.
//!
//! Especially when looking at functor composition, it is useful to
//! be able to encode endofunctors, because it allows us to chain
//! multiple calls to `fmap`, knowing that the result is also a functor,
//! and can be `fmap`'ed further. In Rust this is not possible,
//! because of a lack of higher-kinded types.
//!
//! ## The Co-Yoneda Lemma
//!
//! Let's define a data type called `Coyoneda`:
//!
//! ```
//! Coyoneda :: (b -> a) -> f b -> Coyoneda f a
//! ```
//!
//! This datatype is a functor, which uses function composition
//! to accumulate the mapping function, without changing the captured
//! `f b`. The implementation for `fmap` is trivial:
//!
//! ```
//! fmap f (Coyoneda g a) = Coyoneda (f . g) a
//! ```
//!
//! The co-yoneda lemma states that for a covariant functor `f`,
//! this `Coyoneda f` is naturally isomorphic to `f`.
//! Practically speaking, this means that we can lift any `f a` into a `Coyoneda f a`,
//! and given a function `(a -> b) -> f b`, we can retrieve back a `f b` from a `Coyoneda f b`.
//!
//! ## Composing Coyoneda
//!
//! Now here's the catch: Since we have a parameterized datatype that is isomorphic to any functor,
//! we can lift functors into Coyoneda to compose them safely within Rust's type system!
//!
//! For example, let's implement a function that is generic for any functor:
//!
//! ```
//! fn add_and_to_string<T, A>(y: Coyoneda<T, A, i32>) -> Coyoneda<T, A, String> {
//!    y.map(|n: i32| n + 1)
//!     .map(|n: i32| n.to_string())
//! }!
//! ```
//!
//! Given we implemented a functor for `Option`, we can now do the following:
//!
//! ```
//! let y = add_and_to_string(From::from(Some(42)));
//! assert_eq!(y.unwrap(), Some("43".to_string()))
//! ```
//!
//! ... or for `Box`:
//!
//! ```
//! let y = add_and_to_string(From::from(Box::new(42)));
//! assert_eq!(y.unwrap(), Box::new("43".to_string()))
//! ```
//!
//! ... and for every other functor as well. Yay!

#![feature(box_syntax)]
#![feature(core)]
#![feature(unboxed_closures)]
mod morphism;

use morphism::Morphism;

pub trait Unary {
    type Param;
}

pub trait Functor<B>: Unary {
    type Output;
    fn fmap<F: Fn(Self::Param) -> B>(self, F) -> Self::Output;
}

pub struct Coyoneda<'a, T, B> where T: Unary {
    point: T,
    morph: Morphism<'a, T::Param, B>
}

impl<'a, T: Unary, B> Coyoneda<'a, T, B> {

    pub fn map<C, F: Fn(B) -> C + 'a>(self, f: F) -> Coyoneda<'a, T, C> {
        Coyoneda{point: self.point, morph: self.morph.tail(f)}
    }

    pub fn unwrap(self) -> <T as Functor<B>>::Output where T: Functor<B> {
        T::fmap(self.point, self.morph)
    }

}

impl<'a, T: Unary> From<T> for Coyoneda<'a, T, <T as Unary>::Param> {
    fn from(x: T) -> Coyoneda<'a, T, <T as Unary>::Param> {
        Coyoneda{point: x, morph: Morphism::new()}
    }
}

impl<A> Unary for Box<A> {
    type Param = A;
}

impl<A, B> Functor<B> for Box<A> {
    type Output = Box<B>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Box::new(f(*self))
    }
}

impl<A> Unary for Option<A> {
    type Param = A;
}

impl<A, B> Functor<B> for Option<A> {
    type Output = Option<B>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Option::map(self, f)
    }
}

impl<A, E> Unary for Result<A, E> {
    type Param = A;
}

impl<A, B, E> Functor<B> for Result<A, E> {
    type Output = Result<B, E>;
    fn fmap<F: Fn(A) -> B>(self, f: F) -> Self::Output {
        Result::map(self, f)
    }
}

mod test {
#![cfg(test)]

    use super::*;

    fn add_and_to_string<T: Unary>(y: Coyoneda<T, i32>) -> Coyoneda<T, String> {
        y.map(|n: i32| n + 1)
         .map(|n: i32| n.to_string())
         .map(|s| s + "foo")
         .map(|s| s + "bar")
    }

    #[test]
    fn test_box() {
        let x = Box::new(42);
        let y = add_and_to_string(From::from(x)).unwrap();
        assert_eq!(y, Box::new("43foobar".to_string()))
    }

    #[test]
    fn test_option() {
        let x = Some(42);
        let y = add_and_to_string(From::from(x)).unwrap();
        assert_eq!(y, Some("43foobar".to_string()))
    }

    #[test]
    fn test_result() {
        let x: Result<i32, ()> = Ok(42);
        let y = add_and_to_string(From::from(x)).unwrap();
        assert_eq!(y, Ok("43foobar".to_string()))
    }

}
<|endoftext|>


<commit_before>#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces, unused_qualifications)]
//! compression provides Read adapter implementations for common compression schemes, most notably
//! for Brotli. This allows a consumer to wrap a Brotli-compressed Stream into a Decompressor,
//! allowing the consumer to use the familiar methods provided by the Read trait for consuming
//! the uncompressed stream.

/// bitreader wraps a Read to provide bit-oriented read access to a stream.
pub mod bitreader;
/// brotli provides a Read implementation to wrap a brotli stream, for convenient decompresssion.
pub mod brotli;
/// deflate provides a Read implementation to wrap a deflate stream, for convenient decompresssion.
pub mod deflate;
/// gzip provides a Read implementation to wrap a gzip stream, for convenient decompresssion.
pub mod gzip;
mod huffman;<commit_msg>MOD: removed gzip/deflate modules for now, as they were in no state to go out in public<commit_after>#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces, unused_qualifications)]
//! compression provides Read adapter implementations for common compression schemes, most notably
//! for Brotli. This allows a consumer to wrap a Brotli-compressed Stream into a Decompressor,
//! allowing the consumer to use the familiar methods provided by the Read trait for consuming
//! the uncompressed stream.

/// bitreader wraps a Read to provide bit-oriented read access to a stream.
pub mod bitreader;
/// brotli provides a Read implementation to wrap a brotli stream, for convenient decompresssion.
pub mod brotli;
mod huffman;<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A DSL parsing library for human readable text documents
//!
//! Piston-Meta makes it easy to write parsers for human readable text documents.
//! It can be used for language design, custom formats and data driven development.
//!
//! Meta parsing is a development technique that goes back to the first modern computer.
//! The idea is to turn pieces of a computer program into a programmable pipeline,
//! and thereby accelerating development.
//! An important, but surprisingly reusable part across projects, is the concept of generating
//! structured data from text, since text is easy to modify and reason about.
//!
//! Most programs that work with text uses the following pipeline:
//!
//! ```ignore
//! f : text -> data
//! ```
//!
//! The problem with this approach is that `f` changes from project to project,
//! and the task of transforming text into a data structure can get very complex.
//! For example, to create a parser for the syntax of a programming language,
//! one might need several thousands lines of code.
//! This slows down development and increases the chance of making errors.
//!
//! Meta parsing is a technique where `f` gets splitted into two steps:
//!
//! ```ignore
//! f <=> f2 . f1
//! f1 : text -> meta data
//! f2 : meta data -> data
//! ```
//!
//! The first step `f1` takes text and converts it into a meta data.
//! A DSL (Domain Specific Language) is used to describe how this transformation happens.
//! The second step `f2` converts meta data into data, and this is often written as code.
//!
//! ### Rules
//!
//! The meta language is used to describe how to read other documents.
//! First you define some strings to reuse, then some node rules.
//! The last node is used to read the entire document.
//!
//! `20 document = [.l(string:"string") .l(node:"node") .w?]`
//!
//! Strings starts with underscore and can be reused among the rules:
//!
//! `_opt: "optional"`
//!
//! Nodes start with a number that gets multiplied with 1000 and used as debug id.
//! If you get an error `#4003`, then it was caused by a rule in the node starting with 4.
//!
//! |Rule|Description|
//! |----|-----------|
//! |.l(rule)|Separates sub rule with lines.|
//! |.r?(rule)|Repeats sub rule until it fails, allows zero repetitions.|
//! |.r!(rule)|Repeats sub rule until it fails, requires at least one repetition.|
//! |...any_characters?:name|Reads a string until any characters, allows zero characters. Name is optional.|
//! |...any_characters!:name|Reads a string until any characters, requires at least one character. Name is optional.|
//! |..any_characters?:name|Reads a string until any characters or whitespace, allows zero characters. Name is optional.|
//! |..any_characters!:name|Reads a string until any characters or whitespace, requires at least one character. Name is optional.|
//! |.w?|Reads whitespace. The whitespace is optional.|
//! |.w!|Reads whitespace. The whitespace is required.|
//! |?rule|Makes the rule optional.|
//! |"token":name|Expects a token, sets name to `true`. Name is optional.|
//! |"token":!name|Expects a token, sets name to `false`. Name is required.|
//! |!"token":name|Fails if token is read, sets name to `true` if it is not read. Name is optional.|
//! |!"token":!name|Fails if token is read, sets name to `false` if it is not read. Name is required.|
//! |!rule|Fails if rule is read.|
//! |.s?(by_rule rule)|Separates rule by another rule, allows zero repetitions.|
//! |.s!(by_rule rule)|Separates rule by another rule, requires at least one repetition.|
//! |.s?.(by_rule rule)|Separates rule by another rule, allows trailing.|
//! |{rules}|Selects a rule. Tries the first rule, then the second etc. Rules are separated by whitespace.|
//! |[rules]|A sequence of rules. Rules are separated by whitespace.|
//! |node|Uses a node without a name. The read data is put in the current node.|
//! |node:name|Uses a node with a name. The read data is put in a new node with the name.|
//! |.t?:name|Reads a JSON string with a name. The string can be empty. Name is optional.|
//! |.t!:name|Reads a JSON string with a name. The string can not be empty. Name is optional.|
//! |.$:name|Reads a number with a name. The name is optional.|
//! |.$_:name|Reads a number with underscore as visible separator, for example `10_000`. The name is optional.|
//!
//! ### "Hello world" in Piston-Meta
//!
//! ```rust
//! extern crate piston_meta;
//!
//! use piston_meta::*;
//!
//! fn main() {
//!     let text = r#"hi James!"#;
//!     let rules = r#"
//!         1 say_hi = ["hi" .w? {"James":"james" "Peter":"peter"} "!"]
//!         2 document = say_hi
//!     "#;
//!     // Parse rules with meta language and convert to rules for parsing text.
//!     let rules = match syntax_errstr(rules) {
//!         Err(err) => {
//!             println!("{}", err);
//!             return;
//!         }
//!         Ok(rules) => rules
//!     };
//!     let mut data = vec![];
//!     match parse_errstr(&rules, text, &mut data) {
//!         Err(err) => {
//!             println!("{}", err);
//!             return;
//!         }
//!         Ok(()) => {}
//!     };
//!     json::print(&data);
//! }
//! ```
//!
//! ### Bootstrapping
//!
//! When the meta language changes, bootstrapping is used to host old meta syntax in the new meta syntax. Here is how it works:
//!
//! 1. Piston-Meta contains composable rules that can parse many human readable text formats.
//! 2. Piston-Meta knows how to parse and convert to its own rules, known as "bootstrapping".
//! 3. Therefore, you can tell Piston-Meta how to parse other text formats using a meta language!
//! 4. Including the text format describing how to parse its own syntax, which generates equivalent rules to the ones hard coded in Rust.
//! 5. New versions of the meta language can describe older versions to keep backwards compatibility, by changing the self syntax slightly, so it can read an older version of itself.
//!

extern crate read_token;
extern crate range;
#[macro_use]
extern crate lazy_static;

pub use parse_error_handler::{
    stderr_unwrap,
    ParseErrorHandler
};
pub use parse_error::ParseError;
pub use meta_rules::{ parse, parse_errstr, Rule };
pub use bootstrap::Convert;

/// The type of debug id used to track down errors in rules.
pub type DebugId = usize;

use std::sync::Arc;
use std::fs::File;
use std::path::Path;
pub use range::Range;

pub mod bootstrap;
pub mod json;
pub mod meta_rules;
pub mod tokenizer;

mod parse_error;
mod parse_error_handler;
pub mod optimize;

mod all {
    pub use super::*;
}

/// Represents meta data.
#[derive(PartialEq, Clone, Debug)]
pub enum MetaData {
    /// Starts node.
    StartNode(Arc<String>),
    /// Ends node.
    EndNode(Arc<String>),
    /// Sets bool property.
    Bool(Arc<String>, bool),
    /// Sets f64 property.
    F64(Arc<String>, f64),
    /// Sets string property.
    String(Arc<String>, Arc<String>),
}

/// Stores syntax.
#[derive(Clone, Debug, PartialEq)]
pub struct Syntax {
    /// Rule data.
    pub rules: Vec<Rule>,
    /// Name of rules.
    pub names: Vec<Arc<String>>,
}

impl Syntax {
    /// Creates a new syntax.
    pub fn new() -> Syntax {
        Syntax {
            rules: vec![],
            names: vec![]
        }
    }

    /// Adds a new rule.
    pub fn push(&mut self, name: Arc<String>, rule: Rule) {
        self.rules.push(rule);
        self.names.push(name);
    }

    /// Optimizes syntax.
    pub fn optimize(self) -> Syntax {
        let new_rules = self.rules.iter().map(|r| optimize::optimize_rule(&r, &self.rules)).collect();
        Syntax {rules: new_rules, names: self.names}
    }
}

/// Reads syntax from text.
pub fn syntax(rules: &str) -> Result<Syntax, Range<ParseError>> {
    lazy_static! {
        static ref BOOTSTRAP_RULES: Syntax = bootstrap::rules().optimize();
    }

    let mut tokens = vec![];
    parse(&BOOTSTRAP_RULES, rules, &mut tokens)?;
    let mut ignored_meta_data = vec![];
    match bootstrap::convert(&tokens, &mut ignored_meta_data) {
        Ok(res) => Ok(res.optimize()),
        Err(()) => Err(Range::empty(0).wrap(ParseError::Conversion(
            format!("Bootstrapping rules are incorrect"))))
    }
}

/// Reads syntax from text, formatting the error as `String`.
pub fn syntax_errstr(rules: &str) -> Result<Syntax, String> {
    match syntax(rules) {
        Ok(syntax) => Ok(syntax),
        Err(range_err) => {
            let mut w: Vec<u8> = vec![];
            ParseErrorHandler::new(&rules).write(&mut w, range_err).unwrap();
            Err(String::from_utf8(w).unwrap())
        }
    }
}

/// Convenience method for loading data, using the meta language.
/// Panics if there is an error, and writes error message to
/// standard error output.
pub fn load_syntax_data<A, B>(
    syntax_path: A,
    data_path: B
) -> Vec<Range<MetaData>>
    where A: AsRef<Path>, B: AsRef<Path>
{
    use std::io::Read;

    let mut syntax_file = File::open(syntax_path).unwrap();
    let mut s = String::new();
    syntax_file.read_to_string(&mut s).unwrap();
    let rules = stderr_unwrap(&s, syntax(&s));

    let mut data_file = File::open(data_path).unwrap();
    let mut d = String::new();
    data_file.read_to_string(&mut d).unwrap();
    let mut tokens = vec![];
    stderr_unwrap(&d, parse(&rules, &d, &mut tokens));
    tokens
}

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

    fn is_thread_safe<T: Send + Sync>() {}

    #[test]
    fn meta_data_thread_safe() {
        is_thread_safe::<MetaData>();
    }

    #[test]
    fn parse_error_thread_safe() {
        is_thread_safe::<ParseError>();
    }

    #[test]
    fn rule_thread_safe() {
        is_thread_safe::<Rule>();
    }

    #[test]
    fn syntax_thread_safe() {
        is_thread_safe::<Syntax>();
    }
}
<commit_msg>Fixed some typos in docs<commit_after>#![deny(missing_docs)]

//! # Piston-Meta
//! A DSL parsing library for human readable text documents
//!
//! ### Introduction
//!
//! Piston-Meta makes it easy to write parsers for human readable text documents.
//! It can be used for language design, custom formats and data driven development.
//!
//! Meta parsing is a development technique that goes back to the first modern computer.
//! The idea is to turn pieces of a computer program into a programmable pipeline,
//! and thereby accelerating development.
//! An important, but surprisingly reusable part across projects, is the concept of generating
//! structured data from text, since text is easy to modify and reason about.
//!
//! Most programs that work with text use the following pipeline:
//!
//! ```ignore
//! f : text -> data
//! ```
//!
//! The problem with this approach is that `f` changes from project to project,
//! and the task of transforming text into a data structure can get very complex.
//! For example, to create a parser for the syntax of a programming language,
//! one might need several thousands lines of code.
//! This slows down development and increases the chance of making errors.
//!
//! Meta parsing is a technique where `f` gets splitted into two steps:
//!
//! ```ignore
//! f <=> f2 . f1
//! f1 : text -> meta data
//! f2 : meta data -> data
//! ```
//!
//! The first step `f1` takes text and converts it into meta data.
//! A DSL (Domain Specific Language) is used to describe how this transformation happens.
//! The second step `f2` converts meta data into data, and this is often written as code.
//!
//! ### Rules
//!
//! The meta language is used to describe how to read other documents.
//! First you define some strings to reuse, then some node rules.
//! The last node is used to read the entire document.
//!
//! `20 document = [.l(string:"string") .l(node:"node") .w?]`
//!
//! Strings starts with underscore and can be reused among the rules:
//!
//! `_opt: "optional"`
//!
//! Nodes start with a number that gets multiplied with 1000 and used as debug id.
//! If you get an error `#4003`, then it was caused by a rule in the node starting with 4.
//!
//! |Rule|Description|
//! |----|-----------|
//! |.l(rule)|Separates sub rule with lines.|
//! |.r?(rule)|Repeats sub rule until it fails, allows zero repetitions.|
//! |.r!(rule)|Repeats sub rule until it fails, requires at least one repetition.|
//! |...any_characters?:name|Reads a string until any characters, allows zero characters. Name is optional.|
//! |...any_characters!:name|Reads a string until any characters, requires at least one character. Name is optional.|
//! |..any_characters?:name|Reads a string until any characters or whitespace, allows zero characters. Name is optional.|
//! |..any_characters!:name|Reads a string until any characters or whitespace, requires at least one character. Name is optional.|
//! |.w?|Reads whitespace. The whitespace is optional.|
//! |.w!|Reads whitespace. The whitespace is required.|
//! |?rule|Makes the rule optional.|
//! |"token":name|Expects a token, sets name to `true`. Name is optional.|
//! |"token":!name|Expects a token, sets name to `false`. Name is required.|
//! |!"token":name|Fails if token is read, sets name to `true` if it is not read. Name is optional.|
//! |!"token":!name|Fails if token is read, sets name to `false` if it is not read. Name is required.|
//! |!rule|Fails if rule is read.|
//! |.s?(by_rule rule)|Separates rule by another rule, allows zero repetitions.|
//! |.s!(by_rule rule)|Separates rule by another rule, requires at least one repetition.|
//! |.s?.(by_rule rule)|Separates rule by another rule, allows trailing.|
//! |{rules}|Selects a rule. Tries the first rule, then the second etc. Rules are separated by whitespace.|
//! |[rules]|A sequence of rules. Rules are separated by whitespace.|
//! |node|Uses a node without a name. The read data is put in the current node.|
//! |node:name|Uses a node with a name. The read data is put in a new node with the name.|
//! |.t?:name|Reads a JSON string with a name. The string can be empty. Name is optional.|
//! |.t!:name|Reads a JSON string with a name. The string can not be empty. Name is optional.|
//! |.$:name|Reads a number with a name. The name is optional.|
//! |.$_:name|Reads a number with underscore as visible separator, for example `10_000`. The name is optional.|
//!
//! ### "Hello world" in Piston-Meta
//!
//! ```rust
//! extern crate piston_meta;
//!
//! use piston_meta::*;
//!
//! fn main() {
//!     let text = r#"hi James!"#;
//!     let rules = r#"
//!         1 say_hi = ["hi" .w? {"James":"james" "Peter":"peter"} "!"]
//!         2 document = say_hi
//!     "#;
//!     // Parse rules with meta language and convert to rules for parsing text.
//!     let rules = match syntax_errstr(rules) {
//!         Err(err) => {
//!             println!("{}", err);
//!             return;
//!         }
//!         Ok(rules) => rules
//!     };
//!     let mut data = vec![];
//!     match parse_errstr(&rules, text, &mut data) {
//!         Err(err) => {
//!             println!("{}", err);
//!             return;
//!         }
//!         Ok(()) => {}
//!     };
//!     json::print(&data);
//! }
//! ```
//!
//! ### Bootstrapping
//!
//! When the meta language changes, bootstrapping is used to host old meta syntax in the new meta syntax. Here is how it works:
//!
//! 1. Piston-Meta contains composable rules that can parse many human readable text formats.
//! 2. Piston-Meta knows how to parse and convert to its own rules, known as "bootstrapping".
//! 3. Therefore, you can tell Piston-Meta how to parse other text formats using a meta language!
//! 4. Including the text format describing how to parse its own syntax, which generates equivalent rules to the ones hard coded in Rust.
//! 5. New versions of the meta language can describe older versions to keep backwards compatibility, by changing the self syntax slightly, so it can read an older version of itself.
//!

extern crate read_token;
extern crate range;
#[macro_use]
extern crate lazy_static;

pub use parse_error_handler::{
    stderr_unwrap,
    ParseErrorHandler
};
pub use parse_error::ParseError;
pub use meta_rules::{ parse, parse_errstr, Rule };
pub use bootstrap::Convert;

/// The type of debug id used to track down errors in rules.
pub type DebugId = usize;

use std::sync::Arc;
use std::fs::File;
use std::path::Path;
pub use range::Range;

pub mod bootstrap;
pub mod json;
pub mod meta_rules;
pub mod tokenizer;

mod parse_error;
mod parse_error_handler;
pub mod optimize;

mod all {
    pub use super::*;
}

/// Represents meta data.
#[derive(PartialEq, Clone, Debug)]
pub enum MetaData {
    /// Starts node.
    StartNode(Arc<String>),
    /// Ends node.
    EndNode(Arc<String>),
    /// Sets bool property.
    Bool(Arc<String>, bool),
    /// Sets f64 property.
    F64(Arc<String>, f64),
    /// Sets string property.
    String(Arc<String>, Arc<String>),
}

/// Stores syntax.
#[derive(Clone, Debug, PartialEq)]
pub struct Syntax {
    /// Rule data.
    pub rules: Vec<Rule>,
    /// Name of rules.
    pub names: Vec<Arc<String>>,
}

impl Syntax {
    /// Creates a new syntax.
    pub fn new() -> Syntax {
        Syntax {
            rules: vec![],
            names: vec![]
        }
    }

    /// Adds a new rule.
    pub fn push(&mut self, name: Arc<String>, rule: Rule) {
        self.rules.push(rule);
        self.names.push(name);
    }

    /// Optimizes syntax.
    pub fn optimize(self) -> Syntax {
        let new_rules = self.rules.iter().map(|r| optimize::optimize_rule(&r, &self.rules)).collect();
        Syntax {rules: new_rules, names: self.names}
    }
}

/// Reads syntax from text.
pub fn syntax(rules: &str) -> Result<Syntax, Range<ParseError>> {
    lazy_static! {
        static ref BOOTSTRAP_RULES: Syntax = bootstrap::rules().optimize();
    }

    let mut tokens = vec![];
    parse(&BOOTSTRAP_RULES, rules, &mut tokens)?;
    let mut ignored_meta_data = vec![];
    match bootstrap::convert(&tokens, &mut ignored_meta_data) {
        Ok(res) => Ok(res.optimize()),
        Err(()) => Err(Range::empty(0).wrap(ParseError::Conversion(
            format!("Bootstrapping rules are incorrect"))))
    }
}

/// Reads syntax from text, formatting the error as `String`.
pub fn syntax_errstr(rules: &str) -> Result<Syntax, String> {
    match syntax(rules) {
        Ok(syntax) => Ok(syntax),
        Err(range_err) => {
            let mut w: Vec<u8> = vec![];
            ParseErrorHandler::new(&rules).write(&mut w, range_err).unwrap();
            Err(String::from_utf8(w).unwrap())
        }
    }
}

/// Convenience method for loading data, using the meta language.
/// Panics if there is an error, and writes error message to
/// standard error output.
pub fn load_syntax_data<A, B>(
    syntax_path: A,
    data_path: B
) -> Vec<Range<MetaData>>
    where A: AsRef<Path>, B: AsRef<Path>
{
    use std::io::Read;

    let mut syntax_file = File::open(syntax_path).unwrap();
    let mut s = String::new();
    syntax_file.read_to_string(&mut s).unwrap();
    let rules = stderr_unwrap(&s, syntax(&s));

    let mut data_file = File::open(data_path).unwrap();
    let mut d = String::new();
    data_file.read_to_string(&mut d).unwrap();
    let mut tokens = vec![];
    stderr_unwrap(&d, parse(&rules, &d, &mut tokens));
    tokens
}

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

    fn is_thread_safe<T: Send + Sync>() {}

    #[test]
    fn meta_data_thread_safe() {
        is_thread_safe::<MetaData>();
    }

    #[test]
    fn parse_error_thread_safe() {
        is_thread_safe::<ParseError>();
    }

    #[test]
    fn rule_thread_safe() {
        is_thread_safe::<Rule>();
    }

    #[test]
    fn syntax_thread_safe() {
        is_thread_safe::<Syntax>();
    }
}
<|endoftext|>


<commit_before>//! A macro for defining `#[cfg]` if-else statements.
//!
//! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
//! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
//! emitting the implementation which matches first.
//!
//! This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
//! without having to rewrite each clause multiple times.
//!
//! # Example
//!
//! ```
//! cfg_if::cfg_if! {
//!     if #[cfg(unix)] {
//!         fn foo() { /* unix specific functionality */ }
//!     } else if #[cfg(target_pointer_width = "32")] {
//!         fn foo() { /* non-unix, 32-bit functionality */ }
//!     } else {
//!         fn foo() { /* fallback implementation */ }
//!     }
//! }
//!
//! # fn main() {}
//! ```

#![no_std]
#![doc(html_root_url = "https://docs.rs/cfg-if")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

/// The main macro provided by this crate. See crate documentation for more
/// information.
#[macro_export]
macro_rules! cfg_if {
    // match if/else chains with a final `else`
    ($(
        if #[cfg($meta:meta)] { $($tokens:tt)* }
    ) else * else {
        $($tokens2:tt)*
    }) => {
        $crate::cfg_if! {
            @__items
            () ;
            $( ( ($meta) ($($tokens)*) ), )*
            ( () ($($tokens2)*) ),
        }
    };

    // match if/else chains lacking a final `else`
    (
        if #[cfg($i_met:meta)] { $($i_tokens:tt)* }
        $(
            else if #[cfg($e_met:meta)] { $($e_tokens:tt)* }
        )*
    ) => {
        $crate::cfg_if! {
            @__items
            () ;
            ( ($i_met) ($($i_tokens)*) ),
            $( ( ($e_met) ($($e_tokens)*) ), )*
            ( () () ),
        }
    };

    // Internal and recursive macro to emit all the items
    //
    // Collects all the negated cfgs in a list at the beginning and after the
    // semicolon is all the remaining items
    (@__items ($($not:meta,)*) ; ) => {};
    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($tokens:tt)*) ), $($rest:tt)*) => {
        // Emit all items within one block, applying an appropriate #[cfg]. The
        // #[cfg] will require all `$m` matchers specified and must also negate
        // all previous matchers.
        #[cfg(all($($m,)* not(any($($not),*))))] $crate::cfg_if! { @__identity $($tokens)* }

        // Recurse to emit all other items in `$rest`, and when we do so add all
        // our `$m` matchers to the list of `$not` matchers as future emissions
        // will have to negate everything we just matched as well.
        $crate::cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
    };

    // Internal macro to make __apply work out right for different match types,
    // because of how macros matching/expand stuff.
    (@__identity $($tokens:tt)*) => {
        $($tokens)*
    };
}

#[cfg(test)]
mod tests {
    cfg_if! {
        if #[cfg(test)] {
            use core::option::Option as Option2;
            fn works1() -> Option2<u32> { Some(1) }
        } else {
            fn works1() -> Option<u32> { None }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works2() -> bool { false }
        } else if #[cfg(test)] {
            fn works2() -> bool { true }
        } else {
            fn works2() -> bool { false }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works3() -> bool { false }
        } else {
            fn works3() -> bool { true }
        }
    }

    cfg_if! {
        if #[cfg(test)] {
            use core::option::Option as Option3;
            fn works4() -> Option3<u32> { Some(1) }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works5() -> bool { false }
        } else if #[cfg(test)] {
            fn works5() -> bool { true }
        }
    }

    #[test]
    fn it_works() {
        assert!(works1().is_some());
        assert!(works2());
        assert!(works3());
        assert!(works4().is_some());
        assert!(works5());
    }

    #[test]
    #[allow(clippy::assertions_on_constants)]
    fn test_usage_within_a_function() {
        cfg_if! {if #[cfg(debug_assertions)] {
            // we want to put more than one thing here to make sure that they
            // all get configured properly.
            assert!(cfg!(debug_assertions));
            assert_eq!(4, 2+2);
        } else {
            assert!(works1().is_some());
            assert_eq!(10, 5+5);
        }}
    }

    trait Trait {
        fn blah(&self);
    }

    #[allow(dead_code)]
    struct Struct;

    impl Trait for Struct {
        cfg_if! {
            if #[cfg(feature = "blah")] {
                fn blah(&self) {
                    unimplemented!();
                }
            } else {
                fn blah(&self) {
                    unimplemented!();
                }
            }
        }
    }
}
<commit_msg>More readable formatting and identifier names. (#39)<commit_after>//! A macro for defining `#[cfg]` if-else statements.
//!
//! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
//! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
//! emitting the implementation which matches first.
//!
//! This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
//! without having to rewrite each clause multiple times.
//!
//! # Example
//!
//! ```
//! cfg_if::cfg_if! {
//!     if #[cfg(unix)] {
//!         fn foo() { /* unix specific functionality */ }
//!     } else if #[cfg(target_pointer_width = "32")] {
//!         fn foo() { /* non-unix, 32-bit functionality */ }
//!     } else {
//!         fn foo() { /* fallback implementation */ }
//!     }
//! }
//!
//! # fn main() {}
//! ```

#![no_std]
#![doc(html_root_url = "https://docs.rs/cfg-if")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

/// The main macro provided by this crate. See crate documentation for more
/// information.
#[macro_export]
macro_rules! cfg_if {
    // match if/else chains with a final `else`
    (
        $(
            if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
        ) else+
        else { $( $e_tokens:tt )* }
    ) => {
        $crate::cfg_if! {
            @__items () ;
            $(
                (( $i_meta ) ( $( $i_tokens )* )) ,
            )+
            (() ( $( $e_tokens )* )) ,
        }
    };

    // match if/else chains lacking a final `else`
    (
        if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
        $(
            else if #[cfg( $e_meta:meta )] { $( $e_tokens:tt )* }
        )*
    ) => {
        $crate::cfg_if! {
            @__items () ;
            (( $i_meta ) ( $( $i_tokens )* )) ,
            $(
                (( $e_meta ) ( $( $e_tokens )* )) ,
            )*
        }
    };

    // Internal and recursive macro to emit all the items
    //
    // Collects all the previous cfgs in a list at the beginning, so they can be
    // negated. After the semicolon is all the remaining items.
    (@__items ( $( $_:meta , )* ) ; ) => {};
    (
        @__items ( $( $no:meta , )* ) ;
        (( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
        $( $rest:tt , )*
    ) => {
        // Emit all items within one block, applying an appropriate #[cfg]. The
        // #[cfg] will require all `$yes` matchers specified and must also negate
        // all previous matchers.
        #[cfg(all(
            $( $yes , )?
            not(any( $( $no ),* ))
        ))]
        $crate::cfg_if! { @__identity $( $tokens )* }

        // Recurse to emit all other items in `$rest`, and when we do so add all
        // our `$yes` matchers to the list of `$no` matchers as future emissions
        // will have to negate everything we just matched as well.
        $crate::cfg_if! {
            @__items ( $( $no , )* $( $yes , )? ) ;
            $( $rest , )*
        }
    };

    // Internal macro to make __apply work out right for different match types,
    // because of how macros match/expand stuff.
    (@__identity $( $tokens:tt )* ) => {
        $( $tokens )*
    };
}

#[cfg(test)]
mod tests {
    cfg_if! {
        if #[cfg(test)] {
            use core::option::Option as Option2;
            fn works1() -> Option2<u32> { Some(1) }
        } else {
            fn works1() -> Option<u32> { None }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works2() -> bool { false }
        } else if #[cfg(test)] {
            fn works2() -> bool { true }
        } else {
            fn works2() -> bool { false }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works3() -> bool { false }
        } else {
            fn works3() -> bool { true }
        }
    }

    cfg_if! {
        if #[cfg(test)] {
            use core::option::Option as Option3;
            fn works4() -> Option3<u32> { Some(1) }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works5() -> bool { false }
        } else if #[cfg(test)] {
            fn works5() -> bool { true }
        }
    }

    #[test]
    fn it_works() {
        assert!(works1().is_some());
        assert!(works2());
        assert!(works3());
        assert!(works4().is_some());
        assert!(works5());
    }

    #[test]
    #[allow(clippy::assertions_on_constants)]
    fn test_usage_within_a_function() {
        cfg_if! {if #[cfg(debug_assertions)] {
            // we want to put more than one thing here to make sure that they
            // all get configured properly.
            assert!(cfg!(debug_assertions));
            assert_eq!(4, 2+2);
        } else {
            assert!(works1().is_some());
            assert_eq!(10, 5+5);
        }}
    }

    trait Trait {
        fn blah(&self);
    }

    #[allow(dead_code)]
    struct Struct;

    impl Trait for Struct {
        cfg_if! {
            if #[cfg(feature = "blah")] {
                fn blah(&self) {
                    unimplemented!();
                }
            } else {
                fn blah(&self) {
                    unimplemented!();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! # probe-c-api
//!
//! The `probe-c-api` library creates and runs short test scripts to examine the
//! representation of types and the representations and values of constants in a
//! C library's API. The main goal is to assist Rust-based build systems,
//! especially Cargo build scripts, in producing bindings to C libraries
//! automatically. Nonetheless, this approach may be extended in the nebulous
//! future, e.g. by probing other aspects of a C API, by probing features in
//! other C-like languages (especially C++), or by adding features to aid in
//! writing bindings for other languages.

#![warn(missing_copy_implementations, missing_debug_implementations)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces, unused_qualifications)]
#![warn(variant_size_differences)]
#![deny(missing_docs)]

extern crate rand;

use std::boxed::Box;
use std::default::Default;
use std::env;
use std::fmt;
use std::fs;
use std::io::{self, Write};
use std::path;
use std::process::{self, Command};

use rand::random;

// FIXME? It's not clear whether simply aliasing the standard library types will
// provide the functionality we want from `CommandResult`, so we could hedge our
// bets by making `CommandResult` an opaque wrapper, leaving us the freedom to
// change the representation later.
//
// On the other hand, we definitely want it to be easy to construct a
// `CommandResult` from an `io::Result<process::Output>`, even if they aren't
// identical types. Also, the standard library types are actually quite good for
// this purpose, and it's not clear what more we could want!

/// Result of compilation and run commands. Currently just an alias for the
/// standard library types used by `std::process`, since in most cases we only
/// want to know:
///
///  1. Were we able to run the command at all? (If not, we'll have
///     `io::Result::Err(..)`, probably of kind `NotFound` or
///     `PermissionDenied`.)
///
///  2. If so, did the command exit with an error? (Check `status` on
///     `process::Output`.)
///
///  3. And what did the command report? (Check `stdout` and `stderr` on
///     `process::Output`.)
pub type CommandResult = io::Result<process::Output>;

/// A struct that stores information about how to compile and run test programs.
///
/// The main functionality of `probe_c_api` is implemented using the methods on
/// `Probe`. The lifetime parameter is provided in order to allow closures to be
/// used for the compiler and run commands. If `'static` types implementing `Fn`
/// are used (e.g. function pointers), the lifetime may be `'static`.
pub struct Probe<'a> {
    work_dir: path::PathBuf,
    compile_to: Box<Fn(&path::Path, &path::Path) -> CommandResult + 'a>,
    run: Box<Fn(&path::Path) -> CommandResult + 'a>,
}

impl<'a> fmt::Debug for Probe<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        f.write_fmt(format_args!("probe_c_api::Probe in \"{:?}\"",
                                 self.work_dir))
    }
}

impl<'a> Probe<'a> {
    /// Construct a `Probe` by specifying a work directory, a method to compile
    /// a C program, and a method to run a C program.
    ///
    /// The `work_dir` argument should be a path to a directory where the probe
    /// can read, write, and execute files. We could attempt to verify this, but
    /// in practice there are too many platforms and security measures out
    /// there. So it is up to the user to figure out the difference between a
    /// failure of a test and an inability to run the test due to security
    /// measures.
    ///
    /// Files in the `work_dir` are kept from colliding via random number
    /// generator, which makes it possible to execute tests in parallel, in
    /// practice.
    ///
    /// The `compile_to` argument is responsible for taking a source file
    /// `&Path` (the first argument) and producing a runnable program at another
    /// `&Path` (the second argument). This is roughly equivalent to the shell
    /// script:
    ///
    /// ```sh
    /// gcc -c $1 -o $2
    /// ```
    ///
    /// `compile_to` should yield a `CommandResult`, which allows the exit
    /// status to be checked, and provides the standard output and error for
    /// debugging purposes.
    ///
    /// The `run` argument is responsible for running the process and yielding
    /// its status and output, again as a `CommandResult`.
    ///
    /// FIXME! Suggestions for equivalent non-POSIX examples, especially
    /// anything relevant for Windows, are welcomed.
    pub fn new<C: 'a, R: 'a>(work_dir: &path::Path,
                             compile_to: C,
                             run: R) -> Probe<'a>
        where C: Fn(&path::Path, &path::Path) -> CommandResult,
              R: Fn(&path::Path) -> CommandResult {
        // FIXME! Check that work_dir is a directory.
        Probe {
            work_dir: work_dir.to_path_buf(),
            compile_to: Box::new(compile_to),
            run: Box::new(run),
        }
    }
    /// Write a byte stream to a file, then attempt to compile it.
    ///
    /// This is not terribly useful, and is provided mostly for users who simply
    /// want to reuse a closure that was used to construct the `Probe`, as well
    /// as for convenience and testing of `probe-c-api` itself.
    pub fn try_compile(&self, source: &[u8]) -> CommandResult {
        let random_suffix = random::<u64>();
        let source_path = self.work_dir.join(&format!("source-{}.c",
                                                      random_suffix));
        // FIXME! Check the error from these `try!`'s when there's a problem,
        // e.g. a permissions issue.
        {
            let mut file = try!(fs::File::create(&source_path));
            try!(file.write_all(source));
        }
        let program_path = self.work_dir.join("program")
                               .with_extension(env::consts::EXE_EXTENSION);
        (*self.compile_to)(&source_path, &program_path)
    }
}

/// We provide a default `Probe<'static>` that runs in an OS-specific temporary
/// directory, uses gcc, and simply runs each test.
///
/// FIXME? Can we do better than the gcc command on Windows?
impl Default for Probe<'static> {
    fn default() -> Self {
        Probe::new(
            &env::temp_dir(),
            |source_path, program_path| {
                Command::new("gcc").arg("-c").arg(source_path)
                                   .arg("-o").arg(program_path)
                                   .output()
            },
            |program_path| {
                Command::new(program_path).output()
            },
        )
    }
}
<commit_msg>Add copyright header to lib.rs.<commit_after>// Copyright 2015 Sean Patrick Santos
//
// Licensed under the Apache License, Version 2.0.
// License available at:
// http://www.apache.org/licenses/LICENSE-2.0
//
// Copyright and license information should be present in the top
// level directory of this package.

//! # probe-c-api
//!
//! The `probe-c-api` library creates and runs short test scripts to examine the
//! representation of types and the representations and values of constants in a
//! C library's API. The main goal is to assist Rust-based build systems,
//! especially Cargo build scripts, in producing bindings to C libraries
//! automatically. Nonetheless, this approach may be extended in the nebulous
//! future, e.g. by probing other aspects of a C API, by probing features in
//! other C-like languages (especially C++), or by adding features to aid in
//! writing bindings for other languages.

#![warn(missing_copy_implementations, missing_debug_implementations)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces, unused_qualifications)]
#![warn(variant_size_differences)]
#![deny(missing_docs)]

extern crate rand;

use std::boxed::Box;
use std::default::Default;
use std::env;
use std::fmt;
use std::fs;
use std::io::{self, Write};
use std::path;
use std::process::{self, Command};

use rand::random;

// FIXME? It's not clear whether simply aliasing the standard library types will
// provide the functionality we want from `CommandResult`, so we could hedge our
// bets by making `CommandResult` an opaque wrapper, leaving us the freedom to
// change the representation later.
//
// On the other hand, we definitely want it to be easy to construct a
// `CommandResult` from an `io::Result<process::Output>`, even if they aren't
// identical types. Also, the standard library types are actually quite good for
// this purpose, and it's not clear what more we could want!

/// Result of compilation and run commands. Currently just an alias for the
/// standard library types used by `std::process`, since in most cases we only
/// want to know:
///
///  1. Were we able to run the command at all? (If not, we'll have
///     `io::Result::Err(..)`, probably of kind `NotFound` or
///     `PermissionDenied`.)
///
///  2. If so, did the command exit with an error? (Check `status` on
///     `process::Output`.)
///
///  3. And what did the command report? (Check `stdout` and `stderr` on
///     `process::Output`.)
pub type CommandResult = io::Result<process::Output>;

/// A struct that stores information about how to compile and run test programs.
///
/// The main functionality of `probe_c_api` is implemented using the methods on
/// `Probe`. The lifetime parameter is provided in order to allow closures to be
/// used for the compiler and run commands. If `'static` types implementing `Fn`
/// are used (e.g. function pointers), the lifetime may be `'static`.
pub struct Probe<'a> {
    work_dir: path::PathBuf,
    compile_to: Box<Fn(&path::Path, &path::Path) -> CommandResult + 'a>,
    run: Box<Fn(&path::Path) -> CommandResult + 'a>,
}

impl<'a> fmt::Debug for Probe<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        f.write_fmt(format_args!("probe_c_api::Probe in \"{:?}\"",
                                 self.work_dir))
    }
}

impl<'a> Probe<'a> {
    /// Construct a `Probe` by specifying a work directory, a method to compile
    /// a C program, and a method to run a C program.
    ///
    /// The `work_dir` argument should be a path to a directory where the probe
    /// can read, write, and execute files. We could attempt to verify this, but
    /// in practice there are too many platforms and security measures out
    /// there. So it is up to the user to figure out the difference between a
    /// failure of a test and an inability to run the test due to security
    /// measures.
    ///
    /// Files in the `work_dir` are kept from colliding via random number
    /// generator, which makes it possible to execute tests in parallel, in
    /// practice.
    ///
    /// The `compile_to` argument is responsible for taking a source file
    /// `&Path` (the first argument) and producing a runnable program at another
    /// `&Path` (the second argument). This is roughly equivalent to the shell
    /// script:
    ///
    /// ```sh
    /// gcc -c $1 -o $2
    /// ```
    ///
    /// `compile_to` should yield a `CommandResult`, which allows the exit
    /// status to be checked, and provides the standard output and error for
    /// debugging purposes.
    ///
    /// The `run` argument is responsible for running the process and yielding
    /// its status and output, again as a `CommandResult`.
    ///
    /// FIXME! Suggestions for equivalent non-POSIX examples, especially
    /// anything relevant for Windows, are welcomed.
    pub fn new<C: 'a, R: 'a>(work_dir: &path::Path,
                             compile_to: C,
                             run: R) -> Probe<'a>
        where C: Fn(&path::Path, &path::Path) -> CommandResult,
              R: Fn(&path::Path) -> CommandResult {
        // FIXME! Check that work_dir is a directory.
        Probe {
            work_dir: work_dir.to_path_buf(),
            compile_to: Box::new(compile_to),
            run: Box::new(run),
        }
    }
    /// Write a byte stream to a file, then attempt to compile it.
    ///
    /// This is not terribly useful, and is provided mostly for users who simply
    /// want to reuse a closure that was used to construct the `Probe`, as well
    /// as for convenience and testing of `probe-c-api` itself.
    pub fn try_compile(&self, source: &[u8]) -> CommandResult {
        let random_suffix = random::<u64>();
        let source_path = self.work_dir.join(&format!("source-{}.c",
                                                      random_suffix));
        // FIXME! Check the error from these `try!`'s when there's a problem,
        // e.g. a permissions issue.
        {
            let mut file = try!(fs::File::create(&source_path));
            try!(file.write_all(source));
        }
        let program_path = self.work_dir.join("program")
                               .with_extension(env::consts::EXE_EXTENSION);
        (*self.compile_to)(&source_path, &program_path)
    }
}

/// We provide a default `Probe<'static>` that runs in an OS-specific temporary
/// directory, uses gcc, and simply runs each test.
///
/// FIXME? Can we do better than the gcc command on Windows?
impl Default for Probe<'static> {
    fn default() -> Self {
        Probe::new(
            &env::temp_dir(),
            |source_path, program_path| {
                Command::new("gcc").arg("-c").arg(source_path)
                                   .arg("-o").arg(program_path)
                                   .output()
            },
            |program_path| {
                Command::new(program_path).output()
            },
        )
    }
}
<|endoftext|>


<commit_before>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! # Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** — Clone impls for all syntax tree types.
//!
//! [`syn_mid::ItemFn`]: struct.ItemFn.html
//! [`syn_mid::Block`]: struct.Block.html
//! [syn]: https://github.com/dtolnay/syn

#![doc(html_root_url = "https://docs.rs/syn-mid/0.5.0")]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
))]
#![forbid(unsafe_code)]
#![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all, clippy::default_trait_access)]
// mem::take and #[non_exhaustive] requires Rust 1.40, matches! requires Rust 1.42
#![allow(
    clippy::mem_replace_with_default,
    clippy::manual_non_exhaustive,
    clippy::match_like_matches_macro
)]
#![allow(clippy::eval_order_dependence, clippy::large_enum_variant)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;

pub use crate::{
    arg::{FnArg, Receiver},
    pat::{
        FieldPat, Pat, PatIdent, PatPath, PatReference, PatStruct, PatTuple, PatTupleStruct,
        PatType, PatWild,
    },
};

use proc_macro2::TokenStream;
use syn::{
    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Variadic,
    Visibility,
};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub sig: Signature,
        pub block: Box<Block>,
    }
}

ast_struct! {
    /// A function signature in a trait or implementation: `unsafe fn
    /// initialize(&self)`.
    pub struct Signature {
        pub constness: Option<Token![const]>,
        pub asyncness: Option<Token![async]>,
        pub unsafety: Option<Token![unsafe]>,
        pub abi: Option<Abi>,
        pub fn_token: Token![fn],
        pub ident: Ident,
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub variadic: Option<Variadic>,
        pub output: ReturnType,
    }
}

mod parsing {
    use syn::{
        braced, parenthesized,
        parse::{Parse, ParseStream, Result},
        parse2, Abi, Attribute, Generics, Ident, ReturnType, Token, Type, Variadic, Visibility,
        WhereClause,
    };

    use super::{Block, FnArg, ItemFn, PatType, Signature};

    impl Parse for Block {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let content;
            Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
        }
    }

    fn parse_signature(input: ParseStream<'_>) -> Result<Signature> {
        let constness: Option<Token![const]> = input.parse()?;
        let asyncness: Option<Token![async]> = input.parse()?;
        let unsafety: Option<Token![unsafe]> = input.parse()?;
        let abi: Option<Abi> = input.parse()?;
        let fn_token: Token![fn] = input.parse()?;
        let ident: Ident = input.parse()?;
        let generics: Generics = input.parse()?;

        let content;
        let paren_token = parenthesized!(content in input);
        let inputs = content.parse_terminated(FnArg::parse)?;
        let variadic = inputs.last().as_ref().and_then(get_variadic);

        fn get_variadic(input: &&FnArg) -> Option<Variadic> {
            if let FnArg::Typed(PatType { ty, .. }) = input {
                if let Type::Verbatim(tokens) = &**ty {
                    if let Ok(dots) = parse2(tokens.clone()) {
                        return Some(Variadic { attrs: Vec::new(), dots });
                    }
                }
            }
            None
        }

        let output: ReturnType = input.parse()?;
        let where_clause: Option<WhereClause> = input.parse()?;

        Ok(Signature {
            constness,
            asyncness,
            unsafety,
            abi,
            fn_token,
            ident,
            paren_token,
            inputs,
            output,
            variadic,
            generics: Generics { where_clause, ..generics },
        })
    }

    impl Parse for ItemFn {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let sig = parse_signature(input)?;
            let block = input.parse()?;
            Ok(Self { attrs, vis, sig, block: Box::new(block) })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};
    use syn::{punctuated::Punctuated, Token, Type};

    use super::{Block, FnArg, ItemFn, Signature};

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    fn has_variadic(inputs: &Punctuated<FnArg, Token![,]>) -> bool {
        let last = match inputs.last() {
            Some(last) => last,
            None => return false,
        };

        let pat = match last {
            FnArg::Typed(pat) => pat,
            FnArg::Receiver(_) => return false,
        };

        let tokens = match pat.ty.as_ref() {
            Type::Verbatim(tokens) => tokens,
            _ => return false,
        };

        tokens.to_string() == "..."
    }

    impl ToTokens for Signature {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.constness.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
                if self.variadic.is_some() && !has_variadic(&self.inputs) {
                    if !self.inputs.empty_or_trailing() {
                        <Token![,]>::default().to_tokens(tokens);
                    }
                    self.variadic.to_tokens(tokens);
                }
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.sig.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<commit_msg>Use intra-doc links<commit_after>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! # Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** — Clone impls for all syntax tree types.
//!
//! [`syn_mid::ItemFn`]: ItemFn
//! [`syn_mid::Block`]: Block
//! [syn]: https://github.com/dtolnay/syn

#![doc(html_root_url = "https://docs.rs/syn-mid/0.5.0")]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
))]
#![forbid(unsafe_code)]
#![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all, clippy::default_trait_access)]
// mem::take and #[non_exhaustive] requires Rust 1.40, matches! requires Rust 1.42
#![allow(
    clippy::mem_replace_with_default,
    clippy::manual_non_exhaustive,
    clippy::match_like_matches_macro
)]
#![allow(clippy::eval_order_dependence, clippy::large_enum_variant)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;

pub use crate::{
    arg::{FnArg, Receiver},
    pat::{
        FieldPat, Pat, PatIdent, PatPath, PatReference, PatStruct, PatTuple, PatTupleStruct,
        PatType, PatWild,
    },
};

use proc_macro2::TokenStream;
use syn::{
    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Variadic,
    Visibility,
};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub sig: Signature,
        pub block: Box<Block>,
    }
}

ast_struct! {
    /// A function signature in a trait or implementation: `unsafe fn
    /// initialize(&self)`.
    pub struct Signature {
        pub constness: Option<Token![const]>,
        pub asyncness: Option<Token![async]>,
        pub unsafety: Option<Token![unsafe]>,
        pub abi: Option<Abi>,
        pub fn_token: Token![fn],
        pub ident: Ident,
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub variadic: Option<Variadic>,
        pub output: ReturnType,
    }
}

mod parsing {
    use syn::{
        braced, parenthesized,
        parse::{Parse, ParseStream, Result},
        parse2, Abi, Attribute, Generics, Ident, ReturnType, Token, Type, Variadic, Visibility,
        WhereClause,
    };

    use super::{Block, FnArg, ItemFn, PatType, Signature};

    impl Parse for Block {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let content;
            Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
        }
    }

    fn parse_signature(input: ParseStream<'_>) -> Result<Signature> {
        let constness: Option<Token![const]> = input.parse()?;
        let asyncness: Option<Token![async]> = input.parse()?;
        let unsafety: Option<Token![unsafe]> = input.parse()?;
        let abi: Option<Abi> = input.parse()?;
        let fn_token: Token![fn] = input.parse()?;
        let ident: Ident = input.parse()?;
        let generics: Generics = input.parse()?;

        let content;
        let paren_token = parenthesized!(content in input);
        let inputs = content.parse_terminated(FnArg::parse)?;
        let variadic = inputs.last().as_ref().and_then(get_variadic);

        fn get_variadic(input: &&FnArg) -> Option<Variadic> {
            if let FnArg::Typed(PatType { ty, .. }) = input {
                if let Type::Verbatim(tokens) = &**ty {
                    if let Ok(dots) = parse2(tokens.clone()) {
                        return Some(Variadic { attrs: Vec::new(), dots });
                    }
                }
            }
            None
        }

        let output: ReturnType = input.parse()?;
        let where_clause: Option<WhereClause> = input.parse()?;

        Ok(Signature {
            constness,
            asyncness,
            unsafety,
            abi,
            fn_token,
            ident,
            paren_token,
            inputs,
            output,
            variadic,
            generics: Generics { where_clause, ..generics },
        })
    }

    impl Parse for ItemFn {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let sig = parse_signature(input)?;
            let block = input.parse()?;
            Ok(Self { attrs, vis, sig, block: Box::new(block) })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};
    use syn::{punctuated::Punctuated, Token, Type};

    use super::{Block, FnArg, ItemFn, Signature};

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    fn has_variadic(inputs: &Punctuated<FnArg, Token![,]>) -> bool {
        let last = match inputs.last() {
            Some(last) => last,
            None => return false,
        };

        let pat = match last {
            FnArg::Typed(pat) => pat,
            FnArg::Receiver(_) => return false,
        };

        let tokens = match pat.ty.as_ref() {
            Type::Verbatim(tokens) => tokens,
            _ => return false,
        };

        tokens.to_string() == "..."
    }

    impl ToTokens for Signature {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.constness.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
                if self.variadic.is_some() && !has_variadic(&self.inputs) {
                    if !self.inputs.empty_or_trailing() {
                        <Token![,]>::default().to_tokens(tokens);
                    }
                    self.variadic.to_tokens(tokens);
                }
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.sig.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<|endoftext|>


<commit_before>#![allow(clippy::missing_safety_doc)] // FIXME

//! `rust-numpy` provides Rust interfaces for [NumPy C APIs](https://numpy.org/doc/stable/reference/c-api),
//! especially for [ndarray](https://numpy.org/doc/stable/reference/arrays.ndarray.html) class.
//!
//! It uses [pyo3](https://github.com/PyO3/pyo3) for rust bindings to cpython, and uses
//! [ndarray](https://github.com/bluss/ndarray) for rust side matrix library.
//!
//! For numpy dependency, it calls `import numpy.core` internally. So you just need numpy
//! installed by `pip install numpy` or other ways in your python environment.
//! You can use both system environment and `virtualenv`.
//!
//! This library loads numpy module automatically. So if numpy is not installed, it simply panics,
//! instead of returing a result.
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate ndarray;
//! use numpy::{ToPyArray, PyArray};
//! fn main() {
//!     pyo3::Python::with_gil(|py| {
//!         let py_array = array![[1i64, 2], [3, 4]].to_pyarray(py);
//!         assert_eq!(
//!             py_array.readonly().as_array(),
//!             array![[1i64, 2], [3, 4]]
//!         );
//!     })
//! }
//! ```
pub mod array;
pub mod convert;
mod dtype;
mod error;
pub mod npyffi;
pub mod npyiter;
mod readonly;
mod slice_container;
mod sum_products;

pub use ndarray;

pub use crate::array::{
    get_array_module, PyArray, PyArray0, PyArray1, PyArray2, PyArray3, PyArray4, PyArray5,
    PyArray6, PyArrayDyn,
};
pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
pub use crate::dtype::{c32, c64, DataType, Element, PyArrayDescr};
pub use crate::error::{FromVecError, NotContiguousError, ShapeError};
pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API};
pub use crate::npyiter::{
    IterMode, NpyIterFlag, NpyMultiIter, NpyMultiIterBuilder, NpySingleIter, NpySingleIterBuilder,
};
pub use crate::readonly::{
    PyReadonlyArray, PyReadonlyArray1, PyReadonlyArray2, PyReadonlyArray3, PyReadonlyArray4,
    PyReadonlyArray5, PyReadonlyArray6, PyReadonlyArrayDyn,
};
pub use crate::sum_products::{dot, einsum_impl, inner};
pub use ndarray::{array, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn};

/// Test readme
#[doc(hidden)]
pub mod doc_test {
    macro_rules! doc_comment {
        ($x: expr, $modname: ident) => {
            #[doc = $x]
            mod $modname {}
        };
    }
    doc_comment!(include_str!("../README.md"), readme);
}

/// Create a [PyArray](./array/struct.PyArray.html) with one, two or three dimensions.
/// This macro is backed by
/// [`ndarray::array`](https://docs.rs/ndarray/latest/ndarray/macro.array.html).
///
/// # Example
/// ```
/// pyo3::Python::with_gil(|py| {
///     let array = numpy::pyarray![py, [1, 2], [3, 4]];
///     assert_eq!(
///         array.readonly().as_array(),
///         ndarray::array![[1, 2], [3, 4]]
///     );
/// });
#[macro_export]
macro_rules! pyarray {
    ($py: ident, $([$([$($x:expr),* $(,)*]),+ $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$([$($x,)*],)*],)*], $py)
    }};
    ($py: ident, $([$($x:expr),* $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$($x,)*],)*], $py)
    }};
    ($py: ident, $($x:expr),* $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$($x,)*], $py)
    }};
}
<commit_msg>Only inlcude the examples from the README for doctesting.<commit_after>#![allow(clippy::missing_safety_doc)] // FIXME

//! `rust-numpy` provides Rust interfaces for [NumPy C APIs](https://numpy.org/doc/stable/reference/c-api),
//! especially for [ndarray](https://numpy.org/doc/stable/reference/arrays.ndarray.html) class.
//!
//! It uses [pyo3](https://github.com/PyO3/pyo3) for rust bindings to cpython, and uses
//! [ndarray](https://github.com/bluss/ndarray) for rust side matrix library.
//!
//! For numpy dependency, it calls `import numpy.core` internally. So you just need numpy
//! installed by `pip install numpy` or other ways in your python environment.
//! You can use both system environment and `virtualenv`.
//!
//! This library loads numpy module automatically. So if numpy is not installed, it simply panics,
//! instead of returing a result.
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate ndarray;
//! use numpy::{ToPyArray, PyArray};
//! fn main() {
//!     pyo3::Python::with_gil(|py| {
//!         let py_array = array![[1i64, 2], [3, 4]].to_pyarray(py);
//!         assert_eq!(
//!             py_array.readonly().as_array(),
//!             array![[1i64, 2], [3, 4]]
//!         );
//!     })
//! }
//! ```
pub mod array;
pub mod convert;
mod dtype;
mod error;
pub mod npyffi;
pub mod npyiter;
mod readonly;
mod slice_container;
mod sum_products;

pub use ndarray;

pub use crate::array::{
    get_array_module, PyArray, PyArray0, PyArray1, PyArray2, PyArray3, PyArray4, PyArray5,
    PyArray6, PyArrayDyn,
};
pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
pub use crate::dtype::{c32, c64, DataType, Element, PyArrayDescr};
pub use crate::error::{FromVecError, NotContiguousError, ShapeError};
pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API};
pub use crate::npyiter::{
    IterMode, NpyIterFlag, NpyMultiIter, NpyMultiIterBuilder, NpySingleIter, NpySingleIterBuilder,
};
pub use crate::readonly::{
    PyReadonlyArray, PyReadonlyArray1, PyReadonlyArray2, PyReadonlyArray3, PyReadonlyArray4,
    PyReadonlyArray5, PyReadonlyArray6, PyReadonlyArrayDyn,
};
pub use crate::sum_products::{dot, einsum_impl, inner};
pub use ndarray::{array, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn};

#[cfg(doctest)]
mod doctest {
    macro_rules! doc_comment {
        ($x: expr, $modname: ident) => {
            #[doc = $x]
            mod $modname {}
        };
    }
    doc_comment!(include_str!("../README.md"), readme);
}

/// Create a [PyArray](./array/struct.PyArray.html) with one, two or three dimensions.
/// This macro is backed by
/// [`ndarray::array`](https://docs.rs/ndarray/latest/ndarray/macro.array.html).
///
/// # Example
/// ```
/// pyo3::Python::with_gil(|py| {
///     let array = numpy::pyarray![py, [1, 2], [3, 4]];
///     assert_eq!(
///         array.readonly().as_array(),
///         ndarray::array![[1, 2], [3, 4]]
///     );
/// });
#[macro_export]
macro_rules! pyarray {
    ($py: ident, $([$([$($x:expr),* $(,)*]),+ $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$([$($x,)*],)*],)*], $py)
    }};
    ($py: ident, $([$($x:expr),* $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$($x,)*],)*], $py)
    }};
    ($py: ident, $($x:expr),* $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$($x,)*], $py)
    }};
}
<|endoftext|>


<commit_before>extern crate regex;

use regex::Regex;

pub fn puzzle(input: &str) -> u32 {
    0
}

pub struct Room {
    name: String,
    sector_id: u32,
    checksum: String,
}

impl Room {
    fn new(description: &str) -> Room {
        let regex = Regex::new(r"(?x)
(?P<name>[a-z-]+)
-
(?P<sector_id>[0-9]+)
\[(?P<checksum>[a-z]{5})\]
").expect("Regex is invalid");

        let caps = regex.captures(description).expect("Can't capture");

        Room {
            name: caps.name("name").expect("No name").to_string(),
            sector_id: 3, //caps.name("sector_id").expect("No sector id").parse().expect("Can't parse"),
            checksum: String::from("hi"), //caps.name("checksum").expect("No checksum").to_string(),
        }
    }
}

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

    #[test]
    fn test_extraction() {
        let description = "aaaaa-bbb-z-y-x-123[abxyz]";
        let room = Room::new(description);

        assert_eq!(room.name, "aaaaa-bbb-z-y-x");
        assert_eq!(room.sector_id, 123);
        assert_eq!(room.checksum, "abxyz");
    }
}
<commit_msg>Set up tests for checking if a room is real<commit_after>extern crate regex;

use regex::Regex;

pub fn puzzle(input: &str) -> u32 {
    0
}

pub struct Room {
    name: String,
    sector_id: u32,
    checksum: String,
}

impl Room {
    fn new(description: &str) -> Room {
        let regex = Regex::new(r"(?x)
            (?P<name>[a-z-]+)
            -
            (?P<sector_id>[0-9]+)
            \[(?P<checksum>[a-z]{5})\]").expect("Regex is invalid");

        let caps = regex.captures(description).expect("Can't capture");

        Room {
            name: caps.name("name").expect("No name").to_string(),
            sector_id: caps.name("sector_id").expect("No sector id").parse().expect("Can't parse"),
            checksum: caps.name("checksum").expect("No checksum").to_string(),
        }
    }

    fn is_real(&self) -> bool {
        true
    }
}

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

    #[test]
    fn test_extraction() {
        let description = "aaaaa-bbb-z-y-x-123[abxyz]";
        let room = Room::new(description);

        assert_eq!(room.name, "aaaaa-bbb-z-y-x");
        assert_eq!(room.sector_id, 123);
        assert_eq!(room.checksum, "abxyz");
    }

    #[test]
    fn real_rooms() {
        assert!(Room::new("aaaaa-bbb-z-y-x-123[abxyz]").is_real());
        assert!(Room::new("a-b-c-d-e-f-g-h-987[abcde]").is_real());
        assert!(Room::new("not-a-real-room-404[oarel]").is_real());
    }

    #[test]
    fn decoy_rooms() {
        assert!( ! Room::new("totally-real-room-200[decoy]").is_real() );
    }
}
<|endoftext|>