<commit_before>use crate::common::util::*;
#[cfg(not(windows))]
use std::os::unix::fs::PermissionsExt;
extern crate libc;
use self::libc::umask;

static TEST_DIR1: &str = "mkdir_test1";
static TEST_DIR2: &str = "mkdir_test2";
static TEST_DIR3: &str = "mkdir_test3";
static TEST_DIR4: &str = "mkdir_test4/mkdir_test4_1";
static TEST_DIR5: &str = "mkdir_test5/mkdir_test5_1";
static TEST_DIR6: &str = "mkdir_test6";
static TEST_FILE7: &str = "mkdir_test7";
static TEST_DIR8: &str = "mkdir_test8";

#[test]
fn test_mkdir_mkdir() {
        new_ucmd!().arg(TEST_DIR1).succeeds();
}

#[test]
fn test_mkdir_verbose() {
    let expected = "mkdir: created directory 'mkdir_test1'\n";
    new_ucmd!()
        .arg(TEST_DIR1)
        .arg("-v")
        .run()
        .stdout_is(expected);
}

#[test]
fn test_mkdir_dup_dir() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg(TEST_DIR2).succeeds();
    scene.ucmd().arg(TEST_DIR2).fails();
}

#[test]
fn test_mkdir_mode() {
    new_ucmd!().arg("-m").arg("755").arg(TEST_DIR3).succeeds();
}

#[test]
fn test_mkdir_parent() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg("-p").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("-p").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("--parent").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("--parents").arg(TEST_DIR4).succeeds();
}

#[test]
fn test_mkdir_no_parent() {
    new_ucmd!().arg(TEST_DIR5).fails();
}

#[test]
fn test_mkdir_dup_dir_parent() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg(TEST_DIR6).succeeds();
    scene.ucmd().arg("-p").arg(TEST_DIR6).succeeds();
}

#[test]
fn test_mkdir_dup_file() {
    let scene = TestScenario::new(util_name!());
    scene.fixtures.touch(TEST_FILE7);
    scene.ucmd().arg(TEST_FILE7).fails();

    // mkdir should fail for a file even if -p is specified.
    scene.ucmd().arg("-p").arg(TEST_FILE7).fails();
}

#[test]
#[cfg(not(windows))]
fn test_symbolic_mode() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m").arg("a=rwx").arg(TEST_DIR1).succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40777);
}

#[test]
#[cfg(not(windows))]
fn test_symbolic_alteration() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m").arg("-w").arg(TEST_DIR1).succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40555);
}

#[test]
#[cfg(not(windows))]
fn test_multi_symbolic() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m")
        .arg("u=rwx,g=rx,o=")
        .arg(TEST_DIR1)
        .succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40750);
}

#[test]
#[cfg(not(windows))]
fn test_umask_compliance() {
    fn test_single_case(umask_set: u32) {
        let (at, mut ucmd) = at_and_ucmd!();

        let original_umask = unsafe { umask(umask_set) };

        ucmd.arg(TEST_DIR8).succeeds();
        let perms = at.metadata(TEST_DIR8).permissions().mode();

        assert_eq!(perms, (!umask_set & 0o0777) + 0o40000); // before compare, add the setguid, uid bits
        unsafe { umask(original_umask); } // set umask back to original
    }

    for i in 0o0..0o777 { // tests all permission combinations
        test_single_case(i);
    }

}
<commit_msg>test/mkdir: made umask variable mode_t<commit_after>use crate::common::util::*;
#[cfg(not(windows))]
use std::os::unix::fs::PermissionsExt;
extern crate libc;
use self::libc::{umask, mode_t};

static TEST_DIR1: &str = "mkdir_test1";
static TEST_DIR2: &str = "mkdir_test2";
static TEST_DIR3: &str = "mkdir_test3";
static TEST_DIR4: &str = "mkdir_test4/mkdir_test4_1";
static TEST_DIR5: &str = "mkdir_test5/mkdir_test5_1";
static TEST_DIR6: &str = "mkdir_test6";
static TEST_FILE7: &str = "mkdir_test7";
static TEST_DIR8: &str = "mkdir_test8";

#[test]
fn test_mkdir_mkdir() {
        new_ucmd!().arg(TEST_DIR1).succeeds();
}

#[test]
fn test_mkdir_verbose() {
    let expected = "mkdir: created directory 'mkdir_test1'\n";
    new_ucmd!()
        .arg(TEST_DIR1)
        .arg("-v")
        .run()
        .stdout_is(expected);
}

#[test]
fn test_mkdir_dup_dir() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg(TEST_DIR2).succeeds();
    scene.ucmd().arg(TEST_DIR2).fails();
}

#[test]
fn test_mkdir_mode() {
    new_ucmd!().arg("-m").arg("755").arg(TEST_DIR3).succeeds();
}

#[test]
fn test_mkdir_parent() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg("-p").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("-p").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("--parent").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("--parents").arg(TEST_DIR4).succeeds();
}

#[test]
fn test_mkdir_no_parent() {
    new_ucmd!().arg(TEST_DIR5).fails();
}

#[test]
fn test_mkdir_dup_dir_parent() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg(TEST_DIR6).succeeds();
    scene.ucmd().arg("-p").arg(TEST_DIR6).succeeds();
}

#[test]
fn test_mkdir_dup_file() {
    let scene = TestScenario::new(util_name!());
    scene.fixtures.touch(TEST_FILE7);
    scene.ucmd().arg(TEST_FILE7).fails();

    // mkdir should fail for a file even if -p is specified.
    scene.ucmd().arg("-p").arg(TEST_FILE7).fails();
}

#[test]
#[cfg(not(windows))]
fn test_symbolic_mode() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m").arg("a=rwx").arg(TEST_DIR1).succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40777);
}

#[test]
#[cfg(not(windows))]
fn test_symbolic_alteration() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m").arg("-w").arg(TEST_DIR1).succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40555);
}

#[test]
#[cfg(not(windows))]
fn test_multi_symbolic() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m")
        .arg("u=rwx,g=rx,o=")
        .arg(TEST_DIR1)
        .succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40750);
}

#[test]
#[cfg(not(windows))]
fn test_umask_compliance() {
    fn test_single_case(umask_set: mode_t) {
        let (at, mut ucmd) = at_and_ucmd!();

        let original_umask = unsafe { umask(umask_set) };

        ucmd.arg(TEST_DIR8).succeeds();
        let perms = at.metadata(TEST_DIR8).permissions().mode();

        assert_eq!(perms, (!umask_set & 0o0777) + 0o40000); // before compare, add the setguid, uid bits
        unsafe { umask(original_umask); } // set umask back to original
    }

    for i in 0o0..0o777 { // tests all permission combinations
        test_single_case(i);
    }

}
<|endoftext|>


<commit_before>extern mod extra;
extern mod std;
use grid::{Row, Column, alive, dead, Cell, Grid};
mod grid;

/****************************************************************************
 * Something to say Ben??
 ****************************************************************************/

/*
 * Constructs an immutable grid from the contents of an array of strings.
 * The grid is declared mutable, and mutated only inside this fn.
*/
pub fn build_from_file_contents(file_contents: ~[~str]) -> Grid {
  let height = file_contents.len();
  assert!(height > 0u);
  let width = file_contents[0].len();
  let cells = std::vec::from_elem(width, Cell { value: alive } );

  let mut result = Grid {
      inner: std::vec::from_elem(height, cells.clone())
  };
  for row in range(0, height) {
    for column in range(0, width) {
      let file_value: char = file_contents[row][column] as char;
      let cell_value = match file_value {
        'o' => alive,
        '.' => dead,
         _  => fail!("Unexpected cell value found in file.")
      };
      result.inner[row][column] = Cell { value: cell_value };
   }
  }
  return result;
} // fn build_from_file_contents

/*
 Returns a count for how many neighbors of a cell in the grid
 are alive.
 Starts to the cell to the left of the cell/row and sums up cell_alive
 working in clockwise order.
*/
fn count_neighbors(Row(row): Row, Column(col): Column, grid: &Grid) -> uint {
  let left_column  = Column(col - 1);
  let right_column = Column(col + 1);
  let above_row    = Row(row - 1);
  let below_row    = Row(row + 1);

  return grid.cell_alive(Row(row), left_column) + // left
      grid.cell_alive(above_row, left_column)   + // left-above
      grid.cell_alive(above_row, Column(col))   + // above
      grid.cell_alive(above_row, right_column)  + // above-right
      grid.cell_alive(Row(row), right_column)   + // right
      grid.cell_alive(below_row, right_column)  + // below-right
      grid.cell_alive(below_row, Column(col))   + // below
      grid.cell_alive(below_row, left_column);    // below-left
}  // fn count_neighbors

/*pub fn print_neighbor_count(grid: &Grid) {
  let x = grid.inner.len();
  for row in range(0, x) {
    for column in range(0, x) {
      let r = Row(row);
      let c = Column(column);
      let n = count_neighbors(r, c, grid);
      print!("{:u}", n);
    }
    println!("");
  }
}  // fn print_neighbor_count
*/

// 1)Any live cell with fewer than two live neighbours dies, as if caused by
// under-population.
// 2) Any live cell with two or three live neighbours lives on to the next
// generation.
// 3) Any live cell with more than three live neighbours dies, as if by
// overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as
// if by reproduction.
pub fn build_from_grid(prevg: &Grid) -> Grid {
  let cell_value = |row: uint, column: uint| {
    let ncount = count_neighbors(Row(row), Column(column), prevg);
    let cv = match (prevg.inner[row][column].value, ncount) {
      (dead, 3)       => alive,
      (alive, 2..3)   => alive,
      _               => dead
    };
    return Cell { value: cv };
  };
  return Grid {
    inner: std::vec::from_fn(prevg.height(), |row| {
      std::vec::from_fn(prevg.width(), |column| {
        cell_value(row, column)
      })
    })
  };
}  // fn build_from_grid
<commit_msg>Refactored build_grid_from_file.<commit_after>extern mod extra;
extern mod std;
use grid::{Row, Column, alive, dead, Cell, Grid};
mod grid;

/****************************************************************************
 * Something to say Ben??
 ****************************************************************************/

/*
 * Constructs an immutable grid from the contents of an array of strings.
*/
pub fn build_from_file_contents(file_contents: ~[~str]) -> Grid {
  let height = file_contents.len();
  assert!(height > 0u);
  let width = file_contents[0].len();
  assert!(width > 0u);
  let cell_value = |file_value| {
    return match file_value {
      'o' => alive,
      '.' => dead,
       _  => fail!("Unexpected cell value found in file.")
    };
  };
  return Grid {
    inner: std::vec::from_fn(height, |row| {
      std::vec::from_fn(width, |column| {
        assert_eq!(width, file_contents[row].len());
        let file_value = file_contents[row][column];
        return Cell { value: cell_value(file_value as char) };
      })
    })
  };
} // fn build_from_file_contents

/*
 Returns a count for how many neighbors of a cell in the grid
 are alive.
 Starts to the cell to the left of the cell/row and sums up cell_alive
 working in clockwise order.
*/
fn count_neighbors(Row(row): Row, Column(col): Column, grid: &Grid) -> uint {
  let left_column  = Column(col - 1);
  let right_column = Column(col + 1);
  let above_row    = Row(row - 1);
  let below_row    = Row(row + 1);

  return grid.cell_alive(Row(row), left_column) + // left
      grid.cell_alive(above_row, left_column)   + // left-above
      grid.cell_alive(above_row, Column(col))   + // above
      grid.cell_alive(above_row, right_column)  + // above-right
      grid.cell_alive(Row(row), right_column)   + // right
      grid.cell_alive(below_row, right_column)  + // below-right
      grid.cell_alive(below_row, Column(col))   + // below
      grid.cell_alive(below_row, left_column);    // below-left
}  // fn count_neighbors

// 1)Any live cell with fewer than two live neighbours dies, as if caused by
// under-population.
// 2) Any live cell with two or three live neighbours lives on to the next
// generation.
// 3) Any live cell with more than three live neighbours dies, as if by
// overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as
// if by reproduction.
pub fn build_from_grid(prevg: &Grid) -> Grid {
  let cell_value = |row: uint, column: uint| {
    let ncount = count_neighbors(Row(row), Column(column), prevg);
    let cv = match (prevg.inner[row][column].value, ncount) {
      (dead, 3)       => alive,
      (alive, 2..3)   => alive,
      _               => dead
    };
    return Cell { value: cv };
  };
  return Grid {
    inner: std::vec::from_fn(prevg.height(), |row| {
      std::vec::from_fn(prevg.width(), |column| {
        cell_value(row, column)
      })
    })
  };
}  // fn build_from_grid
<|endoftext|>


<commit_before>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::io::net::ip::{SocketAddr, IpAddr};
use std::sync::Arc;

use http::server as http;
use super::{Request, Handler};

use super::response::HttpResponse;
use super::request::HttpRequest;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// The server can be made with a specific `Chain` (using `from_chain`)
/// or with a new `Chain` (using `new`). `Iron` is used to manage the server
/// processes:
/// `Iron.chain.link` is used to add new `Middleware`, and
/// `Iron.listen` is used to kick off a server process.
///
/// `Iron` contains the `Chain` which holds the `Middleware` necessary to run a server.
/// `Iron` is the main interface to adding `Middleware`, and has `Chain` as a
/// public field (for the sake of extensibility).
pub struct Iron<H> {
    /// Add `Middleware` to the `Iron's` `chain` so that requests
    /// are passed through those `Middleware`.
    /// `Middleware` is added to the chain with with `chain.link`.
    pub handler: H,
}

// The struct which actually listens and serves requests.
struct IronListener<H> {
    handler: Arc<H>,
    ip: IpAddr,
    port: u16
}

impl<H: Send + Sync> Clone for IronListener<H> {
    fn clone(&self) -> IronListener<H> {
        IronListener {
            handler: self.handler.clone(),
            ip: self.ip.clone(),
            port: self.port.clone()
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This is a blocking operation, and is the final op that should be called
    /// on the `Iron` instance. Once `listen` is called, requests will be
    /// handled as defined through the `Iron's` `chain's` `Middleware`.
    pub fn listen(self, ip: IpAddr, port: u16) {
        use http::server::Server;

        IronListener {
            handler: Arc::new(self.handler),
            ip: ip,
            port: port
        }.serve_forever();
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server.
    #[inline]
    pub fn around(handler: H) -> Iron<H> {
        Iron { handler: handler }
    }
}

impl<H: Handler> http::Server for IronListener<H> {
    fn get_config(&self) -> http::Config {
        http::Config {
            bind_address: SocketAddr {
                ip: self.ip,
                port: self.port
            }
        }
    }

    fn handle_request(&self, http_req: HttpRequest, http_res: &mut HttpResponse) {
        // Create wrapper Request and Response
        let mut req = match Request::from_http(http_req) {
            Ok(req) => req,
            Err(e) => {
                error!("Error getting request: {}", e);
                http_res.status = ::http::status::InternalServerError;
                let _ = http_res.write(b"Internal Server Error");
                return;
            }
        };

        // Dispatch the request
        let res = self.handler.call(&mut req);

        match res {
                    // Write the response back to http_res
            Ok(res) => res.write_back(http_res),
            Err(e) => {
                error!("Error handling {}: {}", req, e);
                http_res.status = ::http::status::InternalServerError;
                let _ = http_res.write(b"Internal Server Error");
            }
        }
    }
}
<commit_msg>(doc) Cleanup and docs for Iron.<commit_after>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::io::net::ip::{SocketAddr, IpAddr};
use std::sync::Arc;

use http::server as http;
use super::{Request, Handler};
use super::status;

use super::response::HttpResponse;
use super::request::HttpRequest;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a Handler, which it uses to create responses for client
    /// requests.
    pub handler: H,
}

// The struct which actually listens and serves requests.
struct IronListener<H> {
    handler: Arc<H>,
    ip: IpAddr,
    port: u16
}

impl<H: Send + Sync> Clone for IronListener<H> {
    fn clone(&self) -> IronListener<H> {
        IronListener {
            // Just increment a reference count.
            handler: self.handler.clone(),
            ip: self.ip.clone(),
            port: self.port.clone()
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    pub fn listen(self, ip: IpAddr, port: u16) {
        use http::server::Server;

        spawn(proc() {
            IronListener {
                handler: Arc::new(self.handler),
                ip: ip,
                port: port
            }.serve_forever();
        });
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in Handler.
    pub fn around(handler: H) -> Iron<H> {
        Iron { handler: handler }
    }
}

impl<H: Handler> http::Server for IronListener<H> {
    fn get_config(&self) -> http::Config {
        http::Config {
            bind_address: SocketAddr {
                ip: self.ip,
                port: self.port
            }
        }
    }

    fn handle_request(&self, http_req: HttpRequest, http_res: &mut HttpResponse) {
        // Create wrapper Request
        let mut req = match Request::from_http(http_req) {
            Ok(req) => req,
            Err(e) => {
                error!("Error getting request: {}", e);
                http_res.status = status::InternalServerError;
                let _ = http_res.write(b"Internal Server Error");
                return;
            }
        };

        // Dispatch the request
        let res = self.handler.call(&mut req);

        match res {
            // Write the response back to http_res
            Ok(res) => res.write_back(http_res),
            Err(e) => {
                error!("Error handling {}: {}", req, e);
                http_res.status = status::InternalServerError;
                let _ = http_res.write(b"Internal Server Error");
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(non_ascii_idents)]

extern crate num;

extern crate special_fun;
extern crate roots;

use special_fun::FloatSpecial;
use std::f64::consts::PI;
use roots::SimpleConvergency;
use roots::find_root_brent;

fn jinc(r: f64) -> f64 {
    let π2r = 2.0f64*PI*r;
    2.0f64*π2r.besselj(1.0) / π2r
}

fn find_roots(a: f64, b: f64, f: &Fn(f64)->f64) -> Vec<f64> {
    let mut roots = Vec::new();
    const RANGES : i32 = 100;
    let dx = (b - a) / RANGES as f64;
    let conv = SimpleConvergency{eps:1e-12f64, max_iter:80};
    for r in 0..RANGES {
        let beg = a + (r as f64)*dx;
        let maybe_root = find_root_brent(beg, beg+dx, &f, &conv).ok();
        match maybe_root {
            Some(root) => roots.push(root),
            None => {}
        }
    }

    roots
}

fn main() {
    let v = 0.5f64.besselj(1.0);
    println!("besselj(1.0, 0.5) : {}", v);
    println!("jinc(0.61) : {}", jinc(0.609835));

    let jinc_roots = find_roots(0f64, 5f64, &jinc);
    println!("jinc roots : {:?}", jinc_roots);
}
<commit_msg>simplify a bit `find_roots`.<commit_after>#![feature(non_ascii_idents)]

extern crate num;

extern crate special_fun;
extern crate roots;

use special_fun::FloatSpecial;
use std::f64::consts::PI;
use roots::SimpleConvergency;
use roots::find_root_brent;

fn jinc(r: f64) -> f64 {
    let π2r = 2.0f64*PI*r;
    2.0f64*π2r.besselj(1.0) / π2r
}

fn find_roots(a: f64, b: f64, f: &Fn(f64)->f64) -> Vec<f64> {
    let mut roots = Vec::new();
    const RANGES : i32 = 100;
    let dx = (b - a) / RANGES as f64;
    let conv = SimpleConvergency{eps:1e-12f64, max_iter:80};
    for r in 0..RANGES {
        let beg = a + (r as f64)*dx;
        let maybe_root = find_root_brent(beg, beg+dx, &f, &conv).ok();
        //match maybe_root {
        //    Some(root) => roots.push(root),
        //    None => {}
        //}
        if maybe_root.is_some() {
            roots.push(maybe_root.unwrap());
        }
    }

    roots
}

fn main() {
    let v = 0.5f64.besselj(1.0);
    println!("besselj(1.0, 0.5) : {}", v);
    println!("jinc(0.61) : {}", jinc(0.609835));

    let jinc_roots = find_roots(0f64, 5f64, &jinc);
    println!("jinc roots : {:?}", jinc_roots);
}
<|endoftext|>


<commit_before>//! Generate the site content.

// Standard library
use std::borrow::Cow::{Borrowed, Owned};
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};

// Third party
use glob::{glob, Paths};
use pulldown_cmark as cmark;
use pulldown_cmark::{Event, Parser, Tag};
use syntect::highlighting::ThemeSet;

// First party
use crate::config::{Config, SyntaxOption};

/// Load the `Paths` for all markdown files in the specified content directory.
///
/// If the specified configuration values are wrong, we return a vector of all
/// the errors in the config as far as this is concerned.
///
/// TODO: move that validation elsewhere? Should probably extract a more general
/// site configuration validator.
fn load_markdown_paths(site_directory: &PathBuf, config: &Config) -> Result<Vec<PathBuf>, String> {
    let site = site_directory
        .to_str()
        .ok_or(format!("bad `site`: {:?}", site_directory));

    let directories = config.directories.content.to_str().ok_or(format!(
        "bad content directory: {:?}",
        config.directories.content
    ));

    let (site, directories) = match (site, directories) {
        (Err(s), Err(d)) => Err(s + "\n" + &d),
        (Err(s), Ok(_)) => Err(s),
        (Ok(_), Err(d)) => Err(d),
        (Ok(s), Ok(d)) => Ok((s, d)),
    }?;

    let content_glob = format!("{}/{}/**/*.md", site, directories);

    let paths = glob(&content_glob).map_err(|err| format!("{:?}", err))?;

    let (valid, errors): (Vec<Result<PathBuf, _>>, Vec<Result<_, String>>) = paths
        .map(|glob_result| glob_result.map_err(|err| format!("{:?}", err)))
        .partition(|path| path.is_ok());

    let errors: Vec<String> = errors.into_iter().map(|e| e.unwrap_err()).collect();
    if errors.len() == 0 {
        Ok(valid.into_iter().map(|v| v.unwrap()).collect())
    } else {
        Err(errors.join(",\n"))
    }
}

type LoadTuple<'a> = (&'a PathBuf, Result<String, String>);

fn load_content<'p>(paths: &'p [PathBuf]) -> Result<Vec<(&'p PathBuf, String)>, String> {
    let (contents, errs): (Vec<LoadTuple>, Vec<LoadTuple>) = paths
        .into_iter()
        .map(|path| {
            (
                path,
                std::fs::read_to_string(path).map_err(|e| format!("{:?}", e)),
            )
        })
        .partition(|(_, result)| result.is_ok());

    if errs.len() == 0 {
        Ok(contents
            .into_iter()
            .map(|(path, contents)| (path, contents.unwrap()))
            .collect())
    } else {
        Err(errs
            .into_iter()
            .map(|(_path, err)| err.unwrap_err())
            .collect::<Vec<String>>()
            .join(",\n"))
    }
}

/// Load the templates associated with each taxonomy.
fn load_templates(_site_directory: &PathBuf, _config: &Config) -> Result<Paths, String> {
    unimplemented!()
}

// TODO: put this somewhere else when extracting all the parser logic below into
// its own module.
#[derive(Debug)]
enum ParseState<'s> {
    CodeBlock(&'s syntect::parsing::SyntaxReference),
    PlainTextBlock,
    NonCode,
}

impl<'s> std::default::Default for ParseState<'s> {
    fn default() -> ParseState<'s> {
        ParseState::NonCode
    }
}

/// Generate content from a configuration.
pub fn build(site_directory: PathBuf) -> Result<(), String> {
    // NOTE: this is almost certainly not what we *ultimately* want here, but
    // it'll do as a starting point. There's a lot of `into_iter` and `collect`
    // happening here, which forces us to eagerly materialize a lot of these
    // collections rather than being able to deal with them in a more
    // "streaming" fashion.
    let config = Config::from_file(&PathBuf::from(&site_directory))?;
    let markdown_paths = load_markdown_paths(&site_directory, &config)?;
    let contents = load_content(&markdown_paths)?;

    // TODO: migrate this logic out elsewhere
    // TODO: when doing ^ take into account that we want to be able to avoid a
    // bunch of extra layers of indirection here. If we don't have a theme, that
    // translates to being in `SyntaxOption::Off` or `SyntaxOption::TagOnly`,
    // since the case where we can't *load* the theme is an error. What I want,
    // therefore, is to reflect that in the parsing behavior later.
    let theme = match &config.options.syntax {
        SyntaxOption::Highlight(theme) => {
            let theme_file = PathBuf::from("data").join(theme);
            let theme = ThemeSet::get_theme(theme_file).map_err(|err| format!("{:?}", err))?;
            Some(theme)
        }
        SyntaxOption::Off | SyntaxOption::TagOnly => None,
    };

    // TODO: generate these! Best move: on build, generate a `.packdump`, since
    // that seems to be what Syntect knows how to deal with.
    let syntax_dir = PathBuf::from("data/syntaxes");
    let syntax_set =
        syntect::parsing::SyntaxSet::load_from_folder(syntax_dir).expect("can't load syntaxes");

    let parsed_content: Vec<(&PathBuf, String)> = contents
        .into_iter()
        .map(|(path, content)| {
            let parser = Parser::new_ext(&content, pulldown_cmark::Options::all()).scan(
                ParseState::default(),
                |state, event| match event {
                    Event::Start(Tag::CodeBlock(ref language)) => match state {
                        ParseState::NonCode => {
                            *state = match syntax_set.find_syntax_by_name(&language) {
                                Some(syntax) => ParseState::CodeBlock(syntax),
                                None => ParseState::PlainTextBlock,
                            };

                            // We start every code block with `<pre><code class="...">`
                            // so that we always have semantically correct HTML. However, we
                            // don't add the language class if the language isn't set.
                            let emit_event = if language.len() > 0 {
                                Event::Html(Owned(format!(r#"
"#, language)))
                            } else {
                                Event::Html(Borrowed("
"))
                            };

                            Some(emit_event)
                        }
                        ParseState::CodeBlock(_) | ParseState::PlainTextBlock => {
                            unreachable!("Bad event/state: {:?} with {:?}", event, state);
                        }
                    },

                    Event::End(Tag::CodeBlock(_)) => match state {
                        ParseState::CodeBlock(_) | ParseState::PlainTextBlock => {
                            *state = ParseState::NonCode;
                            Some(Event::Html(Borrowed("
")))
                        }
                        ParseState::NonCode => {
                            unreachable!("Bad event/state: {:?} with {:?}", event, state);
                        }
                    },

                    Event::Text(s) => {
                        match state {
                            ParseState::CodeBlock(syntax) => match &theme {
                                Some(theme) => {
                                    let highlighted = syntect::html::highlighted_html_for_string(
                                        &s,
                                        &syntax_set,
                                        &syntax,
                                        theme,
                                    );

                                    Some(Event::Text(Owned(highlighted)))
                                }
                                None => {
                                    // TODO: implement tag-only parsing with syntect
                                    unimplemented!()
                                }
                            },
                            ParseState::PlainTextBlock => Some(Event::Text(s)),
                            ParseState::NonCode => Some(Event::Text(s)),
                        }
                    }
                    Event::Start(s) => Some(Event::Start(s)),
                    Event::End(e) => Some(Event::End(e)),
                    Event::InlineHtml(s) => Some(Event::InlineHtml(s)),
                    Event::Html(h) => Some(Event::Html(h)),
                    Event::SoftBreak => Some(Event::SoftBreak),
                    Event::HardBreak => Some(Event::HardBreak),
                    Event::FootnoteReference(s) => Some(Event::FootnoteReference(s)),
                },
            );

            // These numbers are derived from a brief survey of content in my
            // own website historically, including both code-heavy and
            // prose-heavy posts. It's probably worth exploring other corpora
            // to see if this is basically right.
            let length_bound_estimate = match &config.options.syntax {
                SyntaxOption::Off | SyntaxOption::TagOnly => 2,
                SyntaxOption::Highlight(_) => 8, // TODO: check other pages
            };

            let mut html = String::with_capacity(content.len() * length_bound_estimate);
            cmark::html::push_html(&mut html, parser);

            (path, html)
        })
        .collect();

    // TODO: extract this as part of the writing it out process.
    let output_dir = site_directory.join(&config.directories.output);

    if output_dir.exists() && !output_dir.is_dir() {
        return Err(format!("Output directory {:?} already exists!", output_dir));
    }

    if !output_dir.exists() {
        std::fs::create_dir(&output_dir).expect(&format!(
            "could not create output directory {:?}",
            &output_dir
        ));
    }

    for (path, content) in parsed_content {
        let file_path = path
            .file_name()
            .ok_or(format!("invalid file: {:?}", path))?;

        let dest = output_dir.join(file_path).with_extension("html");

        let mut fd = match File::create(&dest) {
            Ok(file) => file,
            Err(reason) => {
                return Err(format!(
                    "Could not open {} for write: {}",
                    dest.to_string_lossy(),
                    reason
                ));
            }
        };

        let result = write!(fd, "{}", content);
        if let Err(reason) = result {
            return Err(format!("{:?}", reason.kind()));
        }
    }

    Ok(())
}
<commit_msg>Clarify and document Markdown parsing behavior.<commit_after>//! Generate the site content.

// Standard library
use std::borrow::Cow::{Borrowed, Owned};
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};

// Third party
use glob::{glob, Paths};
use pulldown_cmark as cmark;
use pulldown_cmark::{Event, Parser, Tag};
use syntect::highlighting::ThemeSet;

// First party
use crate::config::{Config, SyntaxOption};

/// Load the `Paths` for all markdown files in the specified content directory.
///
/// If the specified configuration values are wrong, we return a vector of all
/// the errors in the config as far as this is concerned.
///
/// TODO: move that validation elsewhere? Should probably extract a more general
/// site configuration validator.
fn load_markdown_paths(site_directory: &PathBuf, config: &Config) -> Result<Vec<PathBuf>, String> {
    let site = site_directory
        .to_str()
        .ok_or(format!("bad `site`: {:?}", site_directory));

    let directories = config.directories.content.to_str().ok_or(format!(
        "bad content directory: {:?}",
        config.directories.content
    ));

    let (site, directories) = match (site, directories) {
        (Err(s), Err(d)) => Err(s + "\n" + &d),
        (Err(s), Ok(_)) => Err(s),
        (Ok(_), Err(d)) => Err(d),
        (Ok(s), Ok(d)) => Ok((s, d)),
    }?;

    let content_glob = format!("{}/{}/**/*.md", site, directories);

    let paths = glob(&content_glob).map_err(|err| format!("{:?}", err))?;

    let (valid, errors): (Vec<Result<PathBuf, _>>, Vec<Result<_, String>>) = paths
        .map(|glob_result| glob_result.map_err(|err| format!("{:?}", err)))
        .partition(|path| path.is_ok());

    let errors: Vec<String> = errors.into_iter().map(|e| e.unwrap_err()).collect();
    if errors.len() == 0 {
        Ok(valid.into_iter().map(|v| v.unwrap()).collect())
    } else {
        Err(errors.join(",\n"))
    }
}

type LoadTuple<'a> = (&'a PathBuf, Result<String, String>);

fn load_content<'p>(paths: &'p [PathBuf]) -> Result<Vec<(&'p PathBuf, String)>, String> {
    let (contents, errs): (Vec<LoadTuple>, Vec<LoadTuple>) = paths
        .into_iter()
        .map(|path| {
            (
                path,
                std::fs::read_to_string(path).map_err(|e| format!("{:?}", e)),
            )
        })
        .partition(|(_, result)| result.is_ok());

    if errs.len() == 0 {
        Ok(contents
            .into_iter()
            .map(|(path, contents)| (path, contents.unwrap()))
            .collect())
    } else {
        Err(errs
            .into_iter()
            .map(|(_path, err)| err.unwrap_err())
            .collect::<Vec<String>>()
            .join(",\n"))
    }
}

/// Load the templates associated with each taxonomy.
fn load_templates(_site_directory: &PathBuf, _config: &Config) -> Result<Paths, String> {
    unimplemented!()
}

// TODO: put this somewhere else when extracting all the parser logic below into
// its own module.
#[derive(Debug)]
enum ParseState<'s> {
    CodeBlock(&'s syntect::parsing::SyntaxReference),
    PlainTextBlock,
    NonCode,
}

impl<'s> std::default::Default for ParseState<'s> {
    fn default() -> ParseState<'s> {
        ParseState::NonCode
    }
}

/// Generate content from a configuration.
pub fn build(site_directory: PathBuf) -> Result<(), String> {
    // NOTE: this is almost certainly not what we *ultimately* want here, but
    // it'll do as a starting point. There's a lot of `into_iter` and `collect`
    // happening here, which forces us to eagerly materialize a lot of these
    // collections rather than being able to deal with them in a more
    // "streaming" fashion.
    let config = Config::from_file(&PathBuf::from(&site_directory))?;
    let markdown_paths = load_markdown_paths(&site_directory, &config)?;
    let contents = load_content(&markdown_paths)?;

    // TODO: migrate this logic out elsewhere
    // TODO: when doing ^ take into account that we want to be able to avoid a
    // bunch of extra layers of indirection here. If we don't have a theme, that
    // translates to being in `SyntaxOption::Off` or `SyntaxOption::TagOnly`,
    // since the case where we can't *load* the theme is an error. What I want,
    // therefore, is to reflect that in the parsing behavior later.
    let theme = match &config.options.syntax {
        SyntaxOption::Highlight(theme) => {
            let theme_file = PathBuf::from("data").join(theme);
            let theme = ThemeSet::get_theme(theme_file).map_err(|err| format!("{:?}", err))?;
            Some(theme)
        }
        SyntaxOption::Off | SyntaxOption::TagOnly => None,
    };

    // TODO: generate these! Best move: on build, generate a `.packdump`, since
    // that seems to be what Syntect knows how to deal with.
    let syntax_dir = PathBuf::from("data/syntaxes");
    let syntax_set =
        syntect::parsing::SyntaxSet::load_from_folder(syntax_dir).expect("can't load syntaxes");

    let parsed_content: Vec<(&PathBuf, String)> = contents
        .into_iter()
        .map(|(path, content)| {
            let parser = Parser::new_ext(&content, pulldown_cmark::Options::all()).scan(
                ParseState::default(),
                |state, event| match event {
                    Event::Start(Tag::CodeBlock(ref language)) => match state {
                        ParseState::NonCode => {
                            *state = match syntax_set.find_syntax_by_name(&language) {
                                Some(syntax) => ParseState::CodeBlock(syntax),
                                None => ParseState::PlainTextBlock,
                            };

                            // We start every code block with `<pre><code class="...">`
                            // so that we always have semantically correct HTML. However, we
                            // don't add the language class if the language isn't set.
                            let content = if language.len() > 0 {
                                Owned(format!(r#"
"#, language))
                            } else {
                                Borrowed("
")
                            };

                            Some(Event::Html(content))
                        }
                        ParseState::CodeBlock(_) | ParseState::PlainTextBlock => {
                            unreachable!("Bad event/state: {:?} with {:?}", event, state);
                        }
                    },

                    Event::End(Tag::CodeBlock(_)) => match state {
                        ParseState::CodeBlock(_) | ParseState::PlainTextBlock => {
                            *state = ParseState::NonCode;
                            Some(Event::Html(Borrowed("
")))
                        }
                        ParseState::NonCode => {
                            unreachable!("Bad event/state: {:?} with {:?}", event, state);
                        }
                    },

                    // When we are in a text block, we *may* be in a code block,
                    // so we may also need to do whatever highlighting is
                    // specified.
                    Event::Text(s) => {
                        match state {
                            ParseState::CodeBlock(syntax) => match &theme {
                                Some(theme) => {
                                    let highlighted = syntect::html::highlighted_html_for_string(
                                        &s,
                                        &syntax_set,
                                        &syntax,
                                        theme,
                                    );

                                    Some(Event::Text(Owned(highlighted)))
                                }
                                None => {
                                    // TODO: implement tag-only parsing with syntect
                                    unimplemented!()
                                }
                            },
                            ParseState::PlainTextBlock => Some(Event::Text(s)),
                            ParseState::NonCode => Some(Event::Text(s)),
                        }
                    }

                    // TODO: accumulate footnote references and always put them
                    // at the end. Also, generate back-links for them, unless or
                    // until pulldown-cmark does so.
                    Event::FootnoteReference(s) => Some(Event::FootnoteReference(s)),

                    Event::Start(s) => Some(Event::Start(s)),
                    Event::End(e) => Some(Event::End(e)),
                    Event::InlineHtml(s) => Some(Event::InlineHtml(s)),
                    Event::Html(h) => Some(Event::Html(h)),
                    Event::SoftBreak => Some(Event::SoftBreak),
                    Event::HardBreak => Some(Event::HardBreak),
                },
            );

            // These numbers are derived from a brief survey of content in my
            // own website historically, including both code-heavy and
            // prose-heavy posts. It's probably worth exploring other corpora
            // to see if this is basically right.
            let length_bound_estimate = match &config.options.syntax {
                SyntaxOption::Off | SyntaxOption::TagOnly => 2,
                SyntaxOption::Highlight(_) => 8, // TODO: check other pages
            };

            let mut html = String::with_capacity(content.len() * length_bound_estimate);
            cmark::html::push_html(&mut html, parser);

            (path, html)
        })
        .collect();

    // TODO: extract this as part of the writing it out process.
    let output_dir = site_directory.join(&config.directories.output);

    if output_dir.exists() && !output_dir.is_dir() {
        return Err(format!("Output directory {:?} already exists!", output_dir));
    }

    if !output_dir.exists() {
        std::fs::create_dir(&output_dir).expect(&format!(
            "could not create output directory {:?}",
            &output_dir
        ));
    }

    for (path, content) in parsed_content {
        let file_path = path
            .file_name()
            .ok_or(format!("invalid file: {:?}", path))?;

        let dest = output_dir.join(file_path).with_extension("html");

        let mut fd = match File::create(&dest) {
            Ok(file) => file,
            Err(reason) => {
                return Err(format!(
                    "Could not open {} for write: {}",
                    dest.to_string_lossy(),
                    reason
                ));
            }
        };

        let result = write!(fd, "{}", content);
        if let Err(reason) = result {
            return Err(format!("{:?}", reason.kind()));
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate dft;
extern crate test;

use dft::{Operation, Plan, c64};
use test::{Bencher, black_box};

#[bench] fn complex_0004(bencher: &mut Bencher) { complex(   4, bencher); }
#[bench] fn complex_0016(bencher: &mut Bencher) { complex(  16, bencher); }
#[bench] fn complex_0064(bencher: &mut Bencher) { complex(  64, bencher); }
#[bench] fn complex_0256(bencher: &mut Bencher) { complex( 256, bencher); }
#[bench] fn complex_1024(bencher: &mut Bencher) { complex(1024, bencher); }
#[bench] fn complex_4096(bencher: &mut Bencher) { complex(4096, bencher); }
#[bench] fn complex_8192(bencher: &mut Bencher) { complex(8192, bencher); }

#[bench] fn real_0004(bencher: &mut Bencher) { real(   4, bencher); }
#[bench] fn real_0016(bencher: &mut Bencher) { real(  16, bencher); }
#[bench] fn real_0064(bencher: &mut Bencher) { real(  64, bencher); }
#[bench] fn real_0256(bencher: &mut Bencher) { real( 256, bencher); }
#[bench] fn real_1024(bencher: &mut Bencher) { real(1024, bencher); }
#[bench] fn real_4096(bencher: &mut Bencher) { real(4096, bencher); }
#[bench] fn real_8192(bencher: &mut Bencher) { real(8192, bencher); }

fn complex(size: usize, bencher: &mut Bencher) {
    let mut data = vec![c64::new(42.0, 69.0); size];
    let plan = Plan::new(Operation::Forward, size);
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}

fn real(size: usize, bencher: &mut Bencher) {
    let mut data = vec![42.0; 2 * size];
    let plan = Plan::new(Operation::Forward, 2 * size);
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}
<commit_msg>Add some missing tests for powers of two. Add "MB/s"<commit_after>#![feature(test)]

extern crate dft;
extern crate test;

use std::mem;
use dft::{Operation, Plan, c64};
use test::{Bencher, black_box};

#[bench] fn complex_0004(bencher: &mut Bencher) { complex(   4, bencher); }
#[bench] fn complex_0008(bencher: &mut Bencher) { complex(   8, bencher); }
#[bench] fn complex_0016(bencher: &mut Bencher) { complex(  16, bencher); }
#[bench] fn complex_0032(bencher: &mut Bencher) { complex(  32, bencher); }
#[bench] fn complex_0064(bencher: &mut Bencher) { complex(  64, bencher); }
#[bench] fn complex_0128(bencher: &mut Bencher) { complex( 128, bencher); }
#[bench] fn complex_0256(bencher: &mut Bencher) { complex( 256, bencher); }
#[bench] fn complex_0512(bencher: &mut Bencher) { complex( 512, bencher); }
#[bench] fn complex_1024(bencher: &mut Bencher) { complex(1024, bencher); }
#[bench] fn complex_2048(bencher: &mut Bencher) { complex(2048, bencher); }
#[bench] fn complex_4096(bencher: &mut Bencher) { complex(4096, bencher); }
#[bench] fn complex_8192(bencher: &mut Bencher) { complex(8192, bencher); }

#[bench] fn real_0004(bencher: &mut Bencher) { real(   4, bencher); }
#[bench] fn real_0008(bencher: &mut Bencher) { real(   8, bencher); }
#[bench] fn real_0016(bencher: &mut Bencher) { real(  16, bencher); }
#[bench] fn real_0032(bencher: &mut Bencher) { real(  32, bencher); }
#[bench] fn real_0064(bencher: &mut Bencher) { real(  64, bencher); }
#[bench] fn real_0128(bencher: &mut Bencher) { real( 128, bencher); }
#[bench] fn real_0256(bencher: &mut Bencher) { real( 256, bencher); }
#[bench] fn real_0512(bencher: &mut Bencher) { real( 512, bencher); }
#[bench] fn real_1024(bencher: &mut Bencher) { real(1024, bencher); }
#[bench] fn real_2048(bencher: &mut Bencher) { real(2048, bencher); }
#[bench] fn real_4096(bencher: &mut Bencher) { real(4096, bencher); }
#[bench] fn real_8192(bencher: &mut Bencher) { real(8192, bencher); }

fn complex(size: usize, bencher: &mut Bencher) {
    let mut data = vec![c64::new(42.0, 69.0); size];
    let plan = Plan::new(Operation::Forward, size);
    bencher.bytes = (data.len() * mem::size_of_val(&data[0])) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}

fn real(size: usize, bencher: &mut Bencher) {
    let mut data = vec![42.0; 2 * size];
    let plan = Plan::new(Operation::Forward, 2 * size);
    bencher.bytes = (data.len() * mem::size_of_val(&data[0])) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}
<|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};
use serde_json;
use std::collections::HashMap;
use std::iter::FromIterator;
use std::iter::Iterator;

/// Influxdb value, Please look at [this address](https://docs.influxdata.com/influxdb/v1.3/write_protocols/line_protocol_reference/)
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Value {
    /// string
    String(String),
    /// Integer
    Integer(i64),
    /// float
    Float(f64),
    /// Bool
    Boolean(bool),
}

/// influxdb point
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Point {
    /// measurement
    pub measurement: String,
    /// tags
    pub tags: HashMap<String, Value>,
    /// fields
    pub fields: HashMap<String, Value>,
    /// timestamp
    pub timestamp: Option<i64>,
}

impl Point {
    /// Create a new point
    pub fn new(measurement: &str) -> Point {
        Point {
            measurement: String::from(measurement),
            tags: HashMap::new(),
            fields: HashMap::new(),
            timestamp: None,
        }
    }

    /// Add a tag and its value
    pub fn add_tag<T: Into<String>>(mut self, tag: T, value: Value) -> Self {
        self.tags.insert(tag.into(), value);
        self
    }

    /// Add a field and its value
    pub fn add_field<T: Into<String>>(mut self, field: T, value: Value) -> Self {
        self.fields.insert(field.into(), value);
        self
    }

    /// Set the specified timestamp
    pub fn add_timestamp(mut self, timestamp: i64) -> Self {
        self.timestamp = Some(timestamp);
        self
    }
}

/// Points
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Points {
    /// points
    pub point: Vec<Point>,
}

impl Points {
    /// Create a new points
    pub fn new(point: Point) -> Points {
        let mut points = Vec::new();
        points.push(point);
        Points { point: points }
    }

    /// Insert point into already existing points
    pub fn push(mut self, point: Point) -> Self {
        self.point.push(point);
        self
    }

    /// Create a multi Points more directly
    pub fn create_new(points: Vec<Point>) -> Points {
        Points { point: points }
    }
}

impl FromIterator<Point> for Points {
    fn from_iter<T: IntoIterator<Item = Point>>(iter: T) -> Self {
        let mut points = Vec::new();

        for point in iter {
            points.push(point);
        }

        Points { point: points }
    }
}

impl Iterator for Points {
    type Item = Point;

    fn next(&mut self) -> Option<Point> {
        self.point.pop()
    }
}

/// Query data
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Query {
    /// query results
    pub results: Option<Vec<Node>>,
    /// fail message
    pub error: Option<String>,
}

/// Chunked Query data
pub type ChunkedQuery<'de, T> = serde_json::StreamDeserializer<'de, T, Query>;

/// Query data node
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Node {
    /// id
    pub statement_id: Option<u64>,
    /// series
    pub series: Option<Vec<Series>>,
}

/// Query data series
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Series {
    /// measurement
    pub name: String,
    /// tag
    pub tags: Option<HashMap<String, Value>>,
    /// field names and time
    pub columns: Vec<String>,
    /// values
    pub values: Vec<Vec<Value>>,
}

/// Time accuracy
#[derive(Debug, Clone, Copy)]
pub enum Precision {
    /// n
    Nanoseconds,
    /// u
    Microseconds,
    /// ms
    Milliseconds,
    /// s
    Seconds,
    /// m
    Minutes,
    /// h
    Hours,
}

impl Precision {
    /// Convert Precision to &str
    pub fn to_str(&self) -> &str {
        match *self {
            Precision::Nanoseconds => "n",
            Precision::Microseconds => "u",
            Precision::Milliseconds => "ms",
            Precision::Seconds => "s",
            Precision::Minutes => "m",
            Precision::Hours => "h",
        }
    }
}

/// Create Points by macro
#[macro_export]
macro_rules! points {
    ($($x:expr),+) => {
        {
            let mut temp_vec = Vec::new();
            $(temp_vec.push($x);)*
            Points { point: temp_vec }
        }
    };
}

/// Create Point by macro
#[macro_export]
macro_rules! point {
    ($x:expr) => {{
        Point::new($x)
    }};
    ($x:expr, $y:expr, $z:expr) => {{
        Point {
            measurement: String::from($x),
            tags: $y,
            fields: $z,
            timestamp: None,
        }
    }};
    ($x:expr, $y:expr, $z:expr, $a:expr) => {{
        Point {
            measurement: String::from($x),
            tags: $y,
            fields: $z,
            timestamp: Some($a),
        }
    }};
}
<commit_msg>response type may combination all kind of value, should use json value to parse<commit_after>use serde::{Deserialize, Serialize};
use serde_json;
use std::collections::HashMap;
use std::iter::FromIterator;
use std::iter::Iterator;

/// Influxdb value, Please look at [this address](https://docs.influxdata.com/influxdb/v1.3/write_protocols/line_protocol_reference/)
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Value {
    /// string
    String(String),
    /// Integer
    Integer(i64),
    /// float
    Float(f64),
    /// Bool
    Boolean(bool),
}

/// influxdb point
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Point {
    /// measurement
    pub measurement: String,
    /// tags
    pub tags: HashMap<String, Value>,
    /// fields
    pub fields: HashMap<String, Value>,
    /// timestamp
    pub timestamp: Option<i64>,
}

impl Point {
    /// Create a new point
    pub fn new(measurement: &str) -> Point {
        Point {
            measurement: String::from(measurement),
            tags: HashMap::new(),
            fields: HashMap::new(),
            timestamp: None,
        }
    }

    /// Add a tag and its value
    pub fn add_tag<T: Into<String>>(mut self, tag: T, value: Value) -> Self {
        self.tags.insert(tag.into(), value);
        self
    }

    /// Add a field and its value
    pub fn add_field<T: Into<String>>(mut self, field: T, value: Value) -> Self {
        self.fields.insert(field.into(), value);
        self
    }

    /// Set the specified timestamp
    pub fn add_timestamp(mut self, timestamp: i64) -> Self {
        self.timestamp = Some(timestamp);
        self
    }
}

/// Points
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Points {
    /// points
    pub point: Vec<Point>,
}

impl Points {
    /// Create a new points
    pub fn new(point: Point) -> Points {
        let mut points = Vec::new();
        points.push(point);
        Points { point: points }
    }

    /// Insert point into already existing points
    pub fn push(mut self, point: Point) -> Self {
        self.point.push(point);
        self
    }

    /// Create a multi Points more directly
    pub fn create_new(points: Vec<Point>) -> Points {
        Points { point: points }
    }
}

impl FromIterator<Point> for Points {
    fn from_iter<T: IntoIterator<Item = Point>>(iter: T) -> Self {
        let mut points = Vec::new();

        for point in iter {
            points.push(point);
        }

        Points { point: points }
    }
}

impl Iterator for Points {
    type Item = Point;

    fn next(&mut self) -> Option<Point> {
        self.point.pop()
    }
}

/// Query data
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Query {
    /// query results
    pub results: Option<Vec<Node>>,
    /// fail message
    pub error: Option<String>,
}

/// Chunked Query data
pub type ChunkedQuery<'de, T> = serde_json::StreamDeserializer<'de, T, Query>;

/// Query data node
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Node {
    /// id
    pub statement_id: Option<u64>,
    /// series
    pub series: Option<Vec<Series>>,
}

/// Query data series
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Series {
    /// measurement
    pub name: String,
    /// tag
    pub tags: Option<serde_json::Map<String, serde_json::Value>>,
    /// field names and time
    pub columns: Vec<String>,
    /// values
    pub values: Vec<Vec<serde_json::Value>>,
}

/// Time accuracy
#[derive(Debug, Clone, Copy)]
pub enum Precision {
    /// n
    Nanoseconds,
    /// u
    Microseconds,
    /// ms
    Milliseconds,
    /// s
    Seconds,
    /// m
    Minutes,
    /// h
    Hours,
}

impl Precision {
    /// Convert Precision to &str
    pub fn to_str(&self) -> &str {
        match *self {
            Precision::Nanoseconds => "n",
            Precision::Microseconds => "u",
            Precision::Milliseconds => "ms",
            Precision::Seconds => "s",
            Precision::Minutes => "m",
            Precision::Hours => "h",
        }
    }
}

/// Create Points by macro
#[macro_export]
macro_rules! points {
    ($($x:expr),+) => {
        {
            let mut temp_vec = Vec::new();
            $(temp_vec.push($x);)*
            Points { point: temp_vec }
        }
    };
}

/// Create Point by macro
#[macro_export]
macro_rules! point {
    ($x:expr) => {{
        Point::new($x)
    }};
    ($x:expr, $y:expr, $z:expr) => {{
        Point {
            measurement: String::from($x),
            tags: $y,
            fields: $z,
            timestamp: None,
        }
    }};
    ($x:expr, $y:expr, $z:expr, $a:expr) => {{
        Point {
            measurement: String::from($x),
            tags: $y,
            fields: $z,
            timestamp: Some($a),
        }
    }};
}
<|endoftext|>


<commit_before>// `cargo test --benches` and `#[feature(test)]` work only in nightly
#![cfg(rustc_nightly)]
#![feature(test)]

extern crate test;

use protobuf::well_known_types::value;
use protobuf::well_known_types::Struct;
use protobuf::well_known_types::Value;
use protobuf::Message;
use test::Bencher;

#[bench]
fn write_to_bytes(b: &mut Bencher) {
    let mut value = Value::new();
    value.kind = Some(value::Kind::number_value(10.0));
    let mut value2 = Value::new();
    value2.kind = Some(value::Kind::bool_value(true));
    let mut s = Struct::new();
    s.fields.insert("foo".to_owned(), value);
    s.fields.insert("bar".to_owned(), value2);
    b.iter(|| s.write_to_bytes());
}
<commit_msg>Fix compilation on nightly<commit_after>// `cargo test --benches` and `#[feature(test)]` work only in nightly
#![cfg(rustc_nightly)]
#![feature(test)]

extern crate test;

use protobuf::well_known_types::value;
use protobuf::well_known_types::Struct;
use protobuf::well_known_types::Value;
use protobuf::Message;
use test::Bencher;

#[bench]
fn write_to_bytes(b: &mut Bencher) {
    let mut value = Value::new();
    value.kind = Some(value::Kind::NumberValue(10.0));
    let mut value2 = Value::new();
    value2.kind = Some(value::Kind::BoolValue(true));
    let mut s = Struct::new();
    s.fields.insert("foo".to_owned(), value);
    s.fields.insert("bar".to_owned(), value2);
    b.iter(|| s.write_to_bytes());
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::iter::{Iterator, FromIterator, IntoIterator};
use data::{Value, List, Cons, Scope, RuntimeError};

impl List
{
    pub fn cons(car: Value, cdr: List) -> List
    {
        List::Node(Rc::new(Cons{ car: car, cdr: cdr }))
    }

    pub fn from_vec(mut vec: Vec<Value>) -> List
    {
        let mut cdr = List::End;
        while let Some(car) = vec.pop()
        {
            cdr = List::cons(car, cdr);
        }
        cdr
    }

    pub fn iter(&self) -> ListIter
    {
        ListIter(self)
    }

    pub fn eval(&self, env: &mut Scope) -> Result<List, RuntimeError>
    {
        self.iter().map(|val| val.eval(env)).collect()
    }

    pub fn call(&self, env: &mut Scope) -> Result<Value, RuntimeError>
    {
        match *self {
            List::Node(ref cons) => match try!(cons.car.eval(env)) {
                Value::Function(ref func) => func.call(&cons.cdr, env),
                other => Err(RuntimeError::InvalidCall(other.type_name())),
            },
            List::End => Ok(Value::Nil),
        }
    }

    pub fn fold<T, F>(&self, mut acc: T, mut f: F) -> Result<T, RuntimeError>
        where F: FnMut(T, Value) -> Result<T, RuntimeError>
    {
        let mut iter = self.iter();
        while let Some(val) = iter.next()
        {
            acc = try!(f(acc, val))
        }
        Ok(acc)
    }
}

impl FromIterator<Value> for List
{
    fn from_iter<T>(iterator: T) -> Self
        where T: IntoIterator<Item=Value>
    {
        List::from_vec(iterator.into_iter().collect())
    }
}

#[derive(Clone)]
pub struct ListIter<'a>(&'a List);

impl<'a> Iterator for ListIter<'a>
{
    type Item = Value;

    fn next(&mut self) -> Option<Self::Item>
    {
        match *self.0 {
            List::Node(ref cons) => {
                self.0 = &cons.cdr;
                Some(cons.car.clone())
            },
            List::End => None,
        }
    }
}
<commit_msg>more iterator stuff<commit_after>use std::rc::Rc;
use std::iter::{Iterator, FromIterator, IntoIterator};
use data::{Value, List, Cons, Scope, RuntimeError};

impl List
{
    pub fn cons(car: Value, cdr: List) -> List
    {
        List::Node(Rc::new(Cons{ car: car, cdr: cdr }))
    }

    pub fn from_vec(vec: Vec<Value>) -> List
    {
        vec.into_iter().rev().fold(List::End, |cdr, car| List::cons(car, cdr))
    }

    pub fn iter(&self) -> ListIter
    {
        ListIter(self)
    }

    pub fn eval(&self, env: &mut Scope) -> Result<List, RuntimeError>
    {
        self.iter().map(|val| val.eval(env)).collect()
    }

    pub fn call(&self, env: &mut Scope) -> Result<Value, RuntimeError>
    {
        match *self {
            List::Node(ref cons) => match try!(cons.car.eval(env)) {
                Value::Function(ref func) => func.call(&cons.cdr, env),
                other => Err(RuntimeError::InvalidCall(other.type_name())),
            },
            List::End => Ok(Value::Nil),
        }
    }

    pub fn fold<T, F>(&self, mut acc: T, mut f: F) -> Result<T, RuntimeError>
        where F: FnMut(T, Value) -> Result<T, RuntimeError>
    {
        let mut iter = self.iter();
        while let Some(val) = iter.next()
        {
            acc = try!(f(acc, val))
        }
        Ok(acc)
    }
}

impl FromIterator<Value> for List
{
    fn from_iter<T>(iterator: T) -> Self
        where T: IntoIterator<Item=Value>
    {
        List::from_vec(iterator.into_iter().collect())
    }
}

#[derive(Clone)]
pub struct ListIter<'a>(&'a List);

impl<'a> Iterator for ListIter<'a>
{
    type Item = Value;

    fn next(&mut self) -> Option<Self::Item>
    {
        match *self.0 {
            List::Node(ref cons) => {
                self.0 = &cons.cdr;
                Some(cons.car.clone())
            },
            List::End => None,
        }
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use std::ascii::AsciiExt;
use std::io::{self, Write};

use direction::Direction;

#[derive(Debug)]
pub enum PrimaryCommand {
  Go(Direction),
  Look,
  Quit,
}

type HelpInfo = Vec<(char, &'static str)>;

pub trait CommandProcessor<T> {
  fn from_char(c: char) -> Option<T>;

  fn get_help() -> HelpInfo;

  fn get() -> T {
    loop {
      let mut input = String::new();

      io::stdout().write(b"> ").unwrap();
      io::stdout().flush().unwrap();

      match io::stdin().read_line(&mut input) {
        Ok(_) => {
          match input.chars().next() {
            Some(k) => {
              let k = k.to_ascii_lowercase();
              if k == 'h' || k == '?' {
                println!("Available commands:");

                for &(ch, desc) in Self::get_help().iter() {
                  println!("{} - {}", ch, desc);
                }
                continue;
              } else if let Some(cmd) = Self::from_char(k) {
                return cmd;
              }
            },
            None => {}
          }
          println!("I have no idea what you're talking about.");
        },
        Err(error) => {
          println!("Error reading input: {}", error);
        }
      }
    }
  }
}

impl CommandProcessor<PrimaryCommand> for PrimaryCommand {
  fn get_help() -> HelpInfo {
    vec![
      ('n', "go north"),
      ('s', "go south"),
      ('e', "go east"),
      ('w', "go west"),
      ('q', "quit"),
    ]
  }

  fn from_char(c: char) -> Option<PrimaryCommand> {
    match c {
      'q' => { return Some(PrimaryCommand::Quit); },
      'n' => { return Some(PrimaryCommand::Go(Direction::North)); },
      's' => { return Some(PrimaryCommand::Go(Direction::South)); },
      'e' => { return Some(PrimaryCommand::Go(Direction::East)); },
      'w' => { return Some(PrimaryCommand::Go(Direction::West)); },
      'l' => { return Some(PrimaryCommand::Look); },
      _ => { return None; },
    }
  }
}
<commit_msg>Improve help<commit_after>use std::vec::Vec;
use std::ascii::AsciiExt;
use std::io::{self, Write};

use direction::Direction;

#[derive(Debug)]
pub enum PrimaryCommand {
  Go(Direction),
  Look,
  Quit,
}

type HelpInfo = Vec<(char, &'static str)>;

pub trait CommandProcessor<T> {
  fn from_char(c: char) -> Option<T>;

  fn get_help() -> HelpInfo;

  fn get() -> T {
    loop {
      let mut input = String::new();

      io::stdout().write(b"> ").unwrap();
      io::stdout().flush().unwrap();

      match io::stdin().read_line(&mut input) {
        Ok(_) => {
          match input.chars().next() {
            Some(k) => {
              let k = k.to_ascii_lowercase();
              if k == 'h' || k == '?' {
                println!("Available commands:");

                for &(ch, desc) in Self::get_help().iter() {
                  println!("{} - {}", ch, desc);
                }
                continue;
              } else if let Some(cmd) = Self::from_char(k) {
                return cmd;
              }
            },
            None => {}
          }
          println!("I have no idea what you're talking about.");
        },
        Err(error) => {
          println!("Error reading input: {}", error);
        }
      }
    }
  }
}

impl CommandProcessor<PrimaryCommand> for PrimaryCommand {
  fn get_help() -> HelpInfo {
    vec![
      ('n', "go north"),
      ('s', "go south"),
      ('e', "go east"),
      ('w', "go west"),
      ('l', "look around"),
      ('q', "quit"),
    ]
  }

  fn from_char(c: char) -> Option<PrimaryCommand> {
    match c {
      'n' => { return Some(PrimaryCommand::Go(Direction::North)); },
      's' => { return Some(PrimaryCommand::Go(Direction::South)); },
      'e' => { return Some(PrimaryCommand::Go(Direction::East)); },
      'w' => { return Some(PrimaryCommand::Go(Direction::West)); },
      'l' => { return Some(PrimaryCommand::Look); },
      'q' => { return Some(PrimaryCommand::Quit); },
      _ => { return None; },
    }
  }
}
<|endoftext|>


<commit_before>use errors::{self, Error};
use guards::{ReadGuard, WriteGuard};
use methods::Method;
use reflect;

use downcast::Downcast;
//use shared_mutex::{SharedMutex, SharedMutexReadGuard, SharedMutexWriteGuard};

use std::any::Any;
use std::collections::BTreeMap;
use std::sync::{TryLockError, RwLock, RwLockReadGuard, RwLockWriteGuard};

fn type_name<T: Any>() -> &'static str {
    "NOT IMPLEMENTED"
    //unsafe { ::std::intrinsics::type_name::<T>() }
}

// ++++++++++++++++++++ Container ++++++++++++++++++++

pub struct Container<Key, SvcBase: ?Sized> {
    services: BTreeMap<Key, RwLock<Box<SvcBase>>>,
}

impl<Key, SvcBase: ?Sized> Container<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    #[doc(hidden)]
    pub fn new() -> Self {
        Container{ services: BTreeMap::new() }
    }

    #[doc(hidden)]
    pub fn register_service(&mut self, key: Key, svc: Box<SvcBase>) -> &mut Self {
        self.services.insert(key, RwLock::new(svc));
        self
    }

    #[doc(hidden)]
    pub fn register<Svc>(&mut self, svc: Svc) -> &mut Self
    where
        Svc: reflect::Service<Key = Key>,
        Box<Svc>: Into<Box<SvcBase>>,
    {
        self.register_service(Svc::key().clone(), Box::new(svc).into())
    }

    pub fn services(&self) -> &BTreeMap<Key, RwLock<Box<SvcBase>>> {
        &self.services
    }

    pub fn get_service(&self, key: &Key) -> Option<&RwLock<Box<SvcBase>>> {
        self.services.get(key)
    }

    pub fn read_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockReadGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => errors::or_err(key, service.read()),
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn write_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockWriteGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => errors::or_err(key, service.write()),
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn read_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.read_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(ReadGuard::new(base))
    }

    pub fn write_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.write_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(WriteGuard::new(base))
    }

    pub fn read<'a, Svc>(
        &'a self
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.read_service(Svc::key())
    }

    pub fn write<'a, Svc>(
        &'a self
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.write_service(Svc::key())
    }

    pub fn try_read_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockReadGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => errors::or_err(key, service.read()),
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn try_write_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockWriteGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => errors::or_err(key, service.write()),
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn try_read_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.try_read_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(ReadGuard::new(base))
    }

    pub fn try_write_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.try_write_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(WriteGuard::new(base))
    }

    pub fn try_read<'a, Svc>(
        &'a self
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.try_read_service(Svc::key())
    }

    pub fn try_write<'a, Svc>(
        &'a self
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.try_write_service(Svc::key())
    }

    pub fn resolve<'a, M>(&'a self, method: M) -> Result<M::Ret, Error<Key>>
        where M: Method<'a, Key, SvcBase>
    {
        method.resolve(self)
    }
    pub fn try_resolve<'a, M>(&'a self, method: M) -> Result<M::Ret, Error<Key>>
        where M: Method<'a, Key, SvcBase>
    {
        method.try_resolve(self)
    }
}

// ++++++++++++++++++++ ContainerBuilder ++++++++++++++++++++

pub struct ContainerBuilder<Key, SvcBase: ?Sized> {
    cont: Container<Key, SvcBase>
}

impl<Key, SvcBase: ?Sized> ContainerBuilder<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    pub fn new() -> Self {
        ContainerBuilder{ cont: Container::new() }
    }

    pub fn register_service(&mut self, key: Key, svc: Box<SvcBase>) -> &mut Self {
        self.cont.register_service(key, svc);
        self
    }

    /// NOTE: The `Box<Svc>: Into<Box<Base>>`-clause is needed due to rusts lack of
    /// HKT or a `Coercible`-trait (to name two solutions).
    pub fn register<Svc>(&mut self, svc: Svc) -> &mut Self
    where
        Svc: reflect::Service<Key = Key>,
        Box<Svc>: Into<Box<SvcBase>>,
    {
        self.cont.register::<Svc>(svc);
        self
    }

    pub fn build(self) -> Container<Key, SvcBase> {
        self.cont
    }
}

impl<Key, SvcBase: ?Sized> Default for Container<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    fn default() -> Self { Self::new() }
}
<commit_msg>impl Default for ContainerBuilder, not Container<commit_after>use errors::{self, Error};
use guards::{ReadGuard, WriteGuard};
use methods::Method;
use reflect;

use downcast::Downcast;
//use shared_mutex::{SharedMutex, SharedMutexReadGuard, SharedMutexWriteGuard};

use std::any::Any;
use std::collections::BTreeMap;
use std::sync::{TryLockError, RwLock, RwLockReadGuard, RwLockWriteGuard};

fn type_name<T: Any>() -> &'static str {
    "NOT IMPLEMENTED"
    //unsafe { ::std::intrinsics::type_name::<T>() }
}

// ++++++++++++++++++++ Container ++++++++++++++++++++

pub struct Container<Key, SvcBase: ?Sized> {
    services: BTreeMap<Key, RwLock<Box<SvcBase>>>,
}

impl<Key, SvcBase: ?Sized> Container<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    #[doc(hidden)]
    pub fn new() -> Self {
        Container{ services: BTreeMap::new() }
    }

    #[doc(hidden)]
    pub fn register_service(&mut self, key: Key, svc: Box<SvcBase>) -> &mut Self {
        self.services.insert(key, RwLock::new(svc));
        self
    }

    #[doc(hidden)]
    pub fn register<Svc>(&mut self, svc: Svc) -> &mut Self
    where
        Svc: reflect::Service<Key = Key>,
        Box<Svc>: Into<Box<SvcBase>>,
    {
        self.register_service(Svc::key().clone(), Box::new(svc).into())
    }

    pub fn services(&self) -> &BTreeMap<Key, RwLock<Box<SvcBase>>> {
        &self.services
    }

    pub fn get_service(&self, key: &Key) -> Option<&RwLock<Box<SvcBase>>> {
        self.services.get(key)
    }

    pub fn read_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockReadGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => errors::or_err(key, service.read()),
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn write_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockWriteGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => errors::or_err(key, service.write()),
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn read_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.read_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(ReadGuard::new(base))
    }

    pub fn write_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.write_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(WriteGuard::new(base))
    }

    pub fn read<'a, Svc>(
        &'a self
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.read_service(Svc::key())
    }

    pub fn write<'a, Svc>(
        &'a self
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.write_service(Svc::key())
    }

    pub fn try_read_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockReadGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => errors::or_err(key, service.read()),
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn try_write_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockWriteGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => errors::or_err(key, service.write()),
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn try_read_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.try_read_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(ReadGuard::new(base))
    }

    pub fn try_write_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.try_write_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(WriteGuard::new(base))
    }

    pub fn try_read<'a, Svc>(
        &'a self
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.try_read_service(Svc::key())
    }

    pub fn try_write<'a, Svc>(
        &'a self
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.try_write_service(Svc::key())
    }

    pub fn resolve<'a, M>(&'a self, method: M) -> Result<M::Ret, Error<Key>>
        where M: Method<'a, Key, SvcBase>
    {
        method.resolve(self)
    }
    pub fn try_resolve<'a, M>(&'a self, method: M) -> Result<M::Ret, Error<Key>>
        where M: Method<'a, Key, SvcBase>
    {
        method.try_resolve(self)
    }
}

// ++++++++++++++++++++ ContainerBuilder ++++++++++++++++++++

pub struct ContainerBuilder<Key, SvcBase: ?Sized> {
    cont: Container<Key, SvcBase>
}

impl<Key, SvcBase: ?Sized> ContainerBuilder<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    pub fn new() -> Self {
        ContainerBuilder{ cont: Container::new() }
    }

    pub fn register_service(&mut self, key: Key, svc: Box<SvcBase>) -> &mut Self {
        self.cont.register_service(key, svc);
        self
    }

    /// NOTE: The `Box<Svc>: Into<Box<Base>>`-clause is needed due to rusts lack of
    /// HKT or a `Coercible`-trait (to name two solutions).
    pub fn register<Svc>(&mut self, svc: Svc) -> &mut Self
    where
        Svc: reflect::Service<Key = Key>,
        Box<Svc>: Into<Box<SvcBase>>,
    {
        self.cont.register::<Svc>(svc);
        self
    }

    pub fn build(self) -> Container<Key, SvcBase> {
        self.cont
    }
}

impl<Key, SvcBase: ?Sized> Default for ContainerBuilder<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    fn default() -> Self { Self::new() }
}
<|endoftext|>


<commit_before>//! Attributes.

use std::io::Write;

use chrono::{DateTime, UTC};
use uuid::Uuid;

use errors::GerberResult;
use traits::PartialGerberCode;

// FileAttribute

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FileAttribute {
    Part(Part),
    FileFunction(FileFunction),
    FilePolarity(FilePolarity),
    GenerationSoftware(GenerationSoftware),
    CreationDate(DateTime<UTC>),
    ProjectId {
        id: String,
        guid: Uuid,
        revision: String,
    },
    Md5(String),
    UserDefined { name: String, value: Vec<String> },
}

impl<W: Write> PartialGerberCode<W> for FileAttribute {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            FileAttribute::Part(ref part) => {
                write!(writer, "Part,")?;
                part.serialize_partial(writer)?;
            },
            FileAttribute::FileFunction(ref function) => {
                write!(writer, "FileFunction,")?;
                match function {
                    &FileFunction::Copper { ref layer, ref pos, ref copper_type } => {
                        write!(writer, "Copper,L{},", layer)?;
                        pos.serialize_partial(writer)?;
                        if let Some(ref t) = *copper_type {
                            write!(writer, ",")?;
                            t.serialize_partial(writer)?;
                        }
                    },
                    _ => unimplemented!(),
                }
            },
            FileAttribute::GenerationSoftware(ref gs) => {
                write!(writer, "GenerationSoftware,")?;
                gs.serialize_partial(writer)?;
            },
            FileAttribute::Md5(ref hash) => write!(writer, "MD5,{}", hash)?,
            _ => unimplemented!(),
        };
        Ok(())
    }
}

// ApertureAttribute

#[derive(Debug, Clone, PartialEq)]
pub enum ApertureAttribute {
    ApertureFunction(ApertureFunction),
    DrillTolerance {
        plus: f64,
        minus: f64,
    },
}

// Part

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Part {
    /// Single PCB
    Single,
    /// A.k.a. customer panel, assembly panel, shipping panel, biscuit
    Array,
    /// A.k.a. working panel, production panel
    FabricationPanel,
    /// A test coupon
    Coupon,
    /// None of the above
    Other(String),
}

impl<W: Write> PartialGerberCode<W> for Part {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            Part::Single => write!(writer, "Single")?,
            Part::Array => write!(writer, "Array")?,
            Part::FabricationPanel => write!(writer, "FabricationPanel")?,
            Part::Coupon => write!(writer, "Coupon")?,
            Part::Other(ref description) => write!(writer, "Other,{}", description)?,
        };
        Ok(())
    }
}

// Position

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Position {
    Top,
    Bottom,
}

impl<W: Write> PartialGerberCode<W> for Position {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            Position::Top => write!(writer, "Top")?,
            Position::Bottom => write!(writer, "Bot")?,
        };
        Ok(())
    }
}

// ExtendedPosition

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExtendedPosition {
    Top,
    Inner,
    Bottom,
}

impl<W: Write> PartialGerberCode<W> for ExtendedPosition {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            ExtendedPosition::Top => write!(writer, "Top")?,
            ExtendedPosition::Inner => write!(writer, "Inr")?,
            ExtendedPosition::Bottom => write!(writer, "Bot")?,
        };
        Ok(())
    }
}

// CopperType

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CopperType {
    Plane,
    Signal,
    Mixed,
    Hatched,
}

impl<W: Write> PartialGerberCode<W> for CopperType {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            CopperType::Plane => write!(writer, "Plane")?,
            CopperType::Signal => write!(writer, "Signal")?,
            CopperType::Mixed => write!(writer, "Mixed")?,
            CopperType::Hatched => write!(writer, "Hatched")?,
        };
        Ok(())
    }
}

// Drill

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Drill {
    ThroughHole,
    Blind,
    Buried,
}

// DrillRouteType

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DrillRouteType {
    Drill,
    Route,
    Mixed,
}

// Profile

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Profile {
    Plated,
    NonPlated,
}

// FileFunction

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FileFunction {
    Copper { layer: i32, pos: ExtendedPosition, copper_type: Option<CopperType> },
    Soldermask { pos: Position, index: Option<i32> },
    Legend { pos: Position, index: Option<i32> },
    Goldmask { pos: Position, index: Option<i32> },
    Silvermask { pos: Position, index: Option<i32> },
    Tinmask { pos: Position, index: Option<i32> },
    Carbonmask { pos: Position, index: Option<i32> },
    Peelablesoldermask { pos: Position, index: Option<i32> },
    Glue { pos: Position, index: Option<i32> },
    Viatenting(Position),
    Viafill,
    Heatsink(Position),
    Paste(Position),
    KeepOut(Position),
    Pads(Position),
    Scoring(Position),
    Plated { from_layer: i32, to_layer: i32, drill: Drill, label: Option<DrillRouteType> },
    NonPlated { from_layer: i32, to_layer: i32, drill: Drill, label: Option<DrillRouteType> },
    Profile(Profile),
    Drillmap,
    FabricationDrawing,
    ArrayDrawing,
    AssemblyDrawing(Position),
    Drawing(String),
    Other(String),
}

// FilePolarity

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FilePolarity {
    Positive,
    Negative,
}

// GenerationSoftware

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GenerationSoftware {
    pub vendor: String,
    pub application: String,
    pub version: Option<String>,
}

impl GenerationSoftware {
    pub fn new<S: Into<String>>(vendor: S, application: S, version: Option<S>) -> Self {
        GenerationSoftware {
            vendor: vendor.into(),
            application: application.into(),
            version: version.map(|s| s.into()),
        }
    }
}

impl<W: Write> PartialGerberCode<W> for GenerationSoftware {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match self.version {
            Some(ref v) => write!(writer, "{},{},{}", self.vendor, self.application, v)?,
            None => write!(writer, "{},{}", self.vendor, self.application)?,
        };
        Ok(())
    }
}

// ApertureFunction

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ApertureFunction {
    // Only valid for layers with file function plated or non-plated
    ViaDrill,
    BackDrill,
    ComponentDrill {
        press_fit: Option<bool>, // TODO is this bool?
    },
    CastellatedDrill,
    MechanicalDrill {
        function: Option<DrillFunction>,
    },
    Slot,
    CutOut,
    Cavity,
    OtherDrill(String),

    // Only valid for layers with file function copper
    ComponentPad {
        press_fit: Option<bool>, // TODO is this bool?
    },
    SmdPad(SmdPadType),
    BgaPad(SmdPadType),
    ConnectorPad,
    HeatsinkPad,
    ViaPad,
    TestPad,
    CastellatedPad,
    FiducialPad(FiducialScope),
    ThermalReliefPad,
    WasherPad,
    AntiPad,
    OtherPad(String),
    Conductor,
    NonConductor,
    CopperBalancing,
    Border,
    OtherCopper(String),

    // All layers
    Profile,
    NonMaterial,
    Material,
    Other(String),
}

// DrillFunction

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DrillFunction {
    BreakOut,
    Tooling,
    Other,
}

// SmdPadType

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SmdPadType {
    CopperDefined,
    SoldermaskDefined,
}

// FiducialScope

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FiducialScope {
    Global,
    Local,
}
<commit_msg>Add support for profile + soldermask FileFunction values (#26)<commit_after>//! Attributes.

use std::io::Write;

use chrono::{DateTime, UTC};
use uuid::Uuid;

use errors::GerberResult;
use traits::PartialGerberCode;

// FileAttribute

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FileAttribute {
    Part(Part),
    FileFunction(FileFunction),
    FilePolarity(FilePolarity),
    GenerationSoftware(GenerationSoftware),
    CreationDate(DateTime<UTC>),
    ProjectId {
        id: String,
        guid: Uuid,
        revision: String,
    },
    Md5(String),
    UserDefined { name: String, value: Vec<String> },
}

impl<W: Write> PartialGerberCode<W> for FileAttribute {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            FileAttribute::Part(ref part) => {
                write!(writer, "Part,")?;
                part.serialize_partial(writer)?;
            },
            FileAttribute::FileFunction(ref function) => {
                write!(writer, "FileFunction,")?;
                match function {
                    &FileFunction::Copper { ref layer, ref pos, ref copper_type } => {
                        write!(writer, "Copper,L{},", layer)?;
                        pos.serialize_partial(writer)?;
                        if let Some(ref t) = *copper_type {
                            write!(writer, ",")?;
                            t.serialize_partial(writer)?;
                        }
                    },
                    &FileFunction::Profile(ref plating) => {
                        write!(writer, "Profile,")?;
                        plating.serialize_partial(writer)?;
                    },
                    &FileFunction::Soldermask { ref pos, ref index } => {
                        write!(writer, "Soldermask,")?;
                        pos.serialize_partial(writer)?;
                        if let Some(ref i) = index {
                            write!(writer, ",{}", *i)?;
                        }
                    },
                    _ => unimplemented!(),
                }
            },
            FileAttribute::GenerationSoftware(ref gs) => {
                write!(writer, "GenerationSoftware,")?;
                gs.serialize_partial(writer)?;
            },
            FileAttribute::Md5(ref hash) => write!(writer, "MD5,{}", hash)?,
            _ => unimplemented!(),
        };
        Ok(())
    }
}

// ApertureAttribute

#[derive(Debug, Clone, PartialEq)]
pub enum ApertureAttribute {
    ApertureFunction(ApertureFunction),
    DrillTolerance {
        plus: f64,
        minus: f64,
    },
}

// Part

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Part {
    /// Single PCB
    Single,
    /// A.k.a. customer panel, assembly panel, shipping panel, biscuit
    Array,
    /// A.k.a. working panel, production panel
    FabricationPanel,
    /// A test coupon
    Coupon,
    /// None of the above
    Other(String),
}

impl<W: Write> PartialGerberCode<W> for Part {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            Part::Single => write!(writer, "Single")?,
            Part::Array => write!(writer, "Array")?,
            Part::FabricationPanel => write!(writer, "FabricationPanel")?,
            Part::Coupon => write!(writer, "Coupon")?,
            Part::Other(ref description) => write!(writer, "Other,{}", description)?,
        };
        Ok(())
    }
}

// Position

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Position {
    Top,
    Bottom,
}

impl<W: Write> PartialGerberCode<W> for Position {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            Position::Top => write!(writer, "Top")?,
            Position::Bottom => write!(writer, "Bot")?,
        };
        Ok(())
    }
}

// ExtendedPosition

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExtendedPosition {
    Top,
    Inner,
    Bottom,
}

impl<W: Write> PartialGerberCode<W> for ExtendedPosition {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            ExtendedPosition::Top => write!(writer, "Top")?,
            ExtendedPosition::Inner => write!(writer, "Inr")?,
            ExtendedPosition::Bottom => write!(writer, "Bot")?,
        };
        Ok(())
    }
}

// CopperType

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CopperType {
    Plane,
    Signal,
    Mixed,
    Hatched,
}

impl<W: Write> PartialGerberCode<W> for CopperType {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            CopperType::Plane => write!(writer, "Plane")?,
            CopperType::Signal => write!(writer, "Signal")?,
            CopperType::Mixed => write!(writer, "Mixed")?,
            CopperType::Hatched => write!(writer, "Hatched")?,
        };
        Ok(())
    }
}

// Drill

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Drill {
    ThroughHole,
    Blind,
    Buried,
}

// DrillRouteType

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DrillRouteType {
    Drill,
    Route,
    Mixed,
}

// Profile

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Profile {
    Plated,
    NonPlated,
}

impl<W: Write> PartialGerberCode<W> for Profile {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match *self {
            Profile::Plated => write!(writer, "P")?,
            Profile::NonPlated => write!(writer, "NP")?,
        };
        Ok(())
    }
}

// FileFunction

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FileFunction {
    Copper { layer: i32, pos: ExtendedPosition, copper_type: Option<CopperType> },
    Soldermask { pos: Position, index: Option<i32> },
    Legend { pos: Position, index: Option<i32> },
    Goldmask { pos: Position, index: Option<i32> },
    Silvermask { pos: Position, index: Option<i32> },
    Tinmask { pos: Position, index: Option<i32> },
    Carbonmask { pos: Position, index: Option<i32> },
    Peelablesoldermask { pos: Position, index: Option<i32> },
    Glue { pos: Position, index: Option<i32> },
    Viatenting(Position),
    Viafill,
    Heatsink(Position),
    Paste(Position),
    KeepOut(Position),
    Pads(Position),
    Scoring(Position),
    Plated { from_layer: i32, to_layer: i32, drill: Drill, label: Option<DrillRouteType> },
    NonPlated { from_layer: i32, to_layer: i32, drill: Drill, label: Option<DrillRouteType> },
    Profile(Profile),
    Drillmap,
    FabricationDrawing,
    ArrayDrawing,
    AssemblyDrawing(Position),
    Drawing(String),
    Other(String),
}

// FilePolarity

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FilePolarity {
    Positive,
    Negative,
}

// GenerationSoftware

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GenerationSoftware {
    pub vendor: String,
    pub application: String,
    pub version: Option<String>,
}

impl GenerationSoftware {
    pub fn new<S: Into<String>>(vendor: S, application: S, version: Option<S>) -> Self {
        GenerationSoftware {
            vendor: vendor.into(),
            application: application.into(),
            version: version.map(|s| s.into()),
        }
    }
}

impl<W: Write> PartialGerberCode<W> for GenerationSoftware {
    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
        match self.version {
            Some(ref v) => write!(writer, "{},{},{}", self.vendor, self.application, v)?,
            None => write!(writer, "{},{}", self.vendor, self.application)?,
        };
        Ok(())
    }
}

// ApertureFunction

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ApertureFunction {
    // Only valid for layers with file function plated or non-plated
    ViaDrill,
    BackDrill,
    ComponentDrill {
        press_fit: Option<bool>, // TODO is this bool?
    },
    CastellatedDrill,
    MechanicalDrill {
        function: Option<DrillFunction>,
    },
    Slot,
    CutOut,
    Cavity,
    OtherDrill(String),

    // Only valid for layers with file function copper
    ComponentPad {
        press_fit: Option<bool>, // TODO is this bool?
    },
    SmdPad(SmdPadType),
    BgaPad(SmdPadType),
    ConnectorPad,
    HeatsinkPad,
    ViaPad,
    TestPad,
    CastellatedPad,
    FiducialPad(FiducialScope),
    ThermalReliefPad,
    WasherPad,
    AntiPad,
    OtherPad(String),
    Conductor,
    NonConductor,
    CopperBalancing,
    Border,
    OtherCopper(String),

    // All layers
    Profile,
    NonMaterial,
    Material,
    Other(String),
}

// DrillFunction

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DrillFunction {
    BreakOut,
    Tooling,
    Other,
}

// SmdPadType

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SmdPadType {
    CopperDefined,
    SoldermaskDefined,
}

// FiducialScope

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FiducialScope {
    Global,
    Local,
}
<|endoftext|>