<commit_before>#![feature(old_io)]
#![feature(old_path)]

extern crate time;

use std::old_io::IoError;
use std::old_io::net::udp::UdpSocket;
use std::old_io::net::ip::{ Ipv4Addr, SocketAddr };
use std::result;
use time::Tm;
use std::old_io::net::pipe::UnixStream;

/// A type alias for `Result<(), IoError>`, the result of writing a log message
pub type Result = result::Result<(), IoError>;

static NIL: &'static str = "-";

/// Syslog Facilites as defined by [rfc5424](https://tools.ietf.org/html/rfc5424#page-10)
#[derive(Copy,Clone)]
pub enum Facility {
  KERN     = 0,
  USER     = 1 << 3,
  MAIL     = 2 << 3,
  DAEMON   = 3 << 3,
  AUTH     = 4 << 3,
  SYSLOG   = 5 << 3,
  LINEPTR  = 6 << 3,
  NEWS     = 7 << 3,
  UUCP     = 8 << 3,
  CLOCK    = 9 << 3,
  AUTHPRIV = 10 << 3,
  FTP      = 11 << 3,
  LOCAL0   = 16 << 3,
  LOCAL1   = 17 << 3,
  LOCAL2   = 18 << 3,
  LOCAL3   = 19 << 3,
  LOCAL4   = 20 << 3,
  LOCAL5   = 21 << 3,
  LOCAL6   = 22 << 3,
  LOCAL7   = 23 << 3
}

/// Syslog Severity as defined by [rfc5424](https://tools.ietf.org/html/rfc5424#page-11)
pub enum Severity {
  EMERGENCY,
  ALERT,
  CRITICAL,
  ERROR,
  WARNING,
  NOTICE,
  INFO,
  DEBUG
}

trait Transport {
  fn send(&mut self, line: &str) -> Result;
}

impl Transport for (UdpSocket, SocketAddr) {
  fn send(&mut self, line: &str) -> Result {
    self.0.send_to(line.as_bytes(), self.1)
  }
}

impl Transport for UnixStream {
  fn send(&mut self, line: &str) -> Result {
    self.write_line(line)
  }
}

/// A rust interface for Syslog, a standard unix system logging service
pub struct Syslog {
  /// A Syslog facility to target when logging
  facility: Facility,
  host: Option<String>,
  /// An optional tag append to Syslog messages as defined by
  /// [rfc5424](https://tools.ietf.org/html/rfc5424#section-6.2.5)
  tag: Option<String>,
  transport: Box<Transport>
}

impl Syslog {
   /// Factory for a Syslog appender that writes to
   /// remote Syslog daemon listening a SocketAddr
   pub fn udp(host: SocketAddr) -> Syslog {
     let socket =
       match UdpSocket::bind(SocketAddr { ip: Ipv4Addr(0,0,0,0), port: 0 }) {
         Err(e) => panic!("error binding to local addr {}", e),
         Ok(s) => s
       };
      let tup = (socket, host);
      Syslog {
        facility: Facility::USER,
        host: None,
        tag: None,
        transport: Box::new(tup)
      }
  }

  /// Same as udp with providing local loopback address with the standard syslog port
  pub fn localudp() -> Syslog {
    Syslog::udp(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 514 })
  }

  /// Factory for a Syslog appender that writes
  /// to a host-local Syslog daemon listening on a unix socket domain
  /// hosted at the given Path
  pub fn unix(path: Path) -> Syslog {
    let stream =
      match UnixStream::connect(&path) {
        Err(_) => panic!("failed to connect to socket"),
        Ok(s)  => s
      };
    Syslog {
      facility: Facility::USER,
      host: None,
      tag: None,
      transport: Box::new(stream)
    }
  }
  /// Returns a new Syslog appender configured to append with
  /// the provided Facility
  pub fn facility(self, facility: Facility) -> Syslog {
    Syslog {
      facility: facility,
      host: None,
      tag: self.tag,
      transport: self.transport
    }
  }

  /// Returns a new Syslog appender configured to append with
  /// the provided host addr
  pub fn host(self, local: &str) -> Syslog {
    Syslog {
      facility: self.facility,
      host: Some(local.to_string()),
      tag: self.tag,
      transport: self.transport
    }
  }

  /// Returns a new Syslog appender, configured to append with
  /// the provided tag
  pub fn tag(self, tag: &str) -> Syslog {
    Syslog {
      facility: self.facility,
      host: None,
      tag: Some(tag.to_string()),
      transport: self.transport
    }
  }

  pub fn debug(&mut self, msg: &str) -> Result {
    self.log(Severity::DEBUG, msg)
  }

  pub fn info(&mut self, msg: &str) -> Result {
    self.log(Severity::INFO, msg)
  }

  pub fn notice(&mut self, msg: &str) -> Result {
    self.log(Severity::NOTICE, msg)
  }

  pub fn warn(&mut self, msg: &str) -> Result {
    self.log(Severity::WARNING, msg)
  }

  pub fn err(&mut self, msg: &str) -> Result {
    self.log(Severity::ERROR, msg)
  }

  pub fn critical(&mut self, msg: &str) -> Result {
    self.log(Severity::CRITICAL, msg)
  }

  pub fn alert(&mut self, msg: &str) -> Result {
    self.log(Severity::ALERT, msg)
  }

  pub fn emergency(&mut self, msg: &str) -> Result {
    self.log(Severity::EMERGENCY, msg)
  }

  fn log(&mut self, severity: Severity,  msg: &str) -> Result {
    let formatted = Syslog::line(self.facility.clone(), severity, time::now(), self.host.clone(), self.tag.clone(), msg);
    self.transport.send(&formatted)
  }

  fn line(facility: Facility, severity: Severity, timestamp: Tm, host: Option<String>, tag: Option<String>, msg: &str) -> String {
    format!(
      "<{:?}> {} {} {} {}",
        Syslog::priority(facility, severity), timestamp.rfc3339(),
        host.unwrap_or(NIL.to_string()), tag.unwrap_or(NIL.to_string()), msg)
  }

  // computes the priority of a message based on a facility and severity
  fn priority(facility: Facility, severity: Severity) -> u8 {
    facility as u8 | severity as u8
  }
}

#[cfg(test)]
mod tests {
  use super::{Syslog, Facility, NIL, Severity};
  use time;
  #[test]
  fn test_syslog_line() {
    let ts = time::now();
    let host = "foo.local";
    let app = "sysly";
    assert_eq!(Syslog::line(
      Facility::LOCAL0, Severity::INFO, ts, Some(host.to_string()), Some(app.to_string()), "yo"),
      format!("<134> {} {} {} yo", ts.rfc3339(), host, app));

    assert_eq!(Syslog::line(
      Facility::LOCAL0, Severity::INFO, ts, None, Some(app.to_string()), "yo"),
      format!("<134> {} {} {} yo", ts.rfc3339(), NIL, app));
  }
}
<commit_msg>few more tests<commit_after>#![feature(old_io)]
#![feature(old_path)]

extern crate time;

use std::old_io::IoError;
use std::old_io::net::udp::UdpSocket;
use std::old_io::net::ip::{ Ipv4Addr, SocketAddr };
use std::result;
use time::Tm;
use std::old_io::net::pipe::UnixStream;

/// A type alias for `Result<(), IoError>`, the result of writing a log message
pub type Result = result::Result<(), IoError>;

static NIL: &'static str = "-";

/// Syslog Facilites as defined by [rfc5424](https://tools.ietf.org/html/rfc5424#page-10)
#[derive(Copy,Clone)]
pub enum Facility {
  KERN     = 0,
  USER     = 1 << 3,
  MAIL     = 2 << 3,
  DAEMON   = 3 << 3,
  AUTH     = 4 << 3,
  SYSLOG   = 5 << 3,
  LINEPTR  = 6 << 3,
  NEWS     = 7 << 3,
  UUCP     = 8 << 3,
  CLOCK    = 9 << 3,
  AUTHPRIV = 10 << 3,
  FTP      = 11 << 3,
  LOCAL0   = 16 << 3,
  LOCAL1   = 17 << 3,
  LOCAL2   = 18 << 3,
  LOCAL3   = 19 << 3,
  LOCAL4   = 20 << 3,
  LOCAL5   = 21 << 3,
  LOCAL6   = 22 << 3,
  LOCAL7   = 23 << 3
}

/// Syslog Severity as defined by [rfc5424](https://tools.ietf.org/html/rfc5424#page-11)
pub enum Severity {
  EMERGENCY,
  ALERT,
  CRITICAL,
  ERROR,
  WARNING,
  NOTICE,
  INFO,
  DEBUG
}

trait Transport {
  fn send(&mut self, line: &str) -> Result;
}

impl Transport for (UdpSocket, SocketAddr) {
  fn send(&mut self, line: &str) -> Result {
    self.0.send_to(line.as_bytes(), self.1)
  }
}

impl Transport for UnixStream {
  fn send(&mut self, line: &str) -> Result {
    self.write_line(line)
  }
}

/// A rust interface for Syslog, a standard unix system logging service
pub struct Syslog {
  /// A Syslog facility to target when logging
  facility: Facility,
  host: Option<String>,
  /// An optional tag append to Syslog messages as defined by
  /// [rfc5424](https://tools.ietf.org/html/rfc5424#section-6.2.5)
  tag: Option<String>,
  transport: Box<Transport>
}

impl Syslog {
   /// Factory for a Syslog appender that writes to
   /// remote Syslog daemon listening a SocketAddr
   pub fn udp(host: SocketAddr) -> Syslog {
     let socket =
       match UdpSocket::bind(SocketAddr { ip: Ipv4Addr(0,0,0,0), port: 0 }) {
         Err(e) => panic!("error binding to local addr {}", e),
         Ok(s) => s
       };
      let tup = (socket, host);
      Syslog {
        facility: Facility::USER,
        host: None,
        tag: None,
        transport: Box::new(tup)
      }
  }

  /// Same as udp with providing local loopback address with the standard syslog port
  pub fn localudp() -> Syslog {
    Syslog::udp(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 514 })
  }

  /// Factory for a Syslog appender that writes
  /// to a host-local Syslog daemon listening on a unix socket domain
  /// hosted at the given Path
  pub fn unix(path: Path) -> Syslog {
    let stream =
      match UnixStream::connect(&path) {
        Err(_) => panic!("failed to connect to socket"),
        Ok(s)  => s
      };
    Syslog {
      facility: Facility::USER,
      host: None,
      tag: None,
      transport: Box::new(stream)
    }
  }
  /// Returns a new Syslog appender configured to append with
  /// the provided Facility
  pub fn facility(self, facility: Facility) -> Syslog {
    Syslog {
      facility: facility,
      host: None,
      tag: self.tag,
      transport: self.transport
    }
  }

  /// Returns a new Syslog appender configured to append with
  /// the provided host addr
  pub fn host(self, local: &str) -> Syslog {
    Syslog {
      facility: self.facility,
      host: Some(local.to_string()),
      tag: self.tag,
      transport: self.transport
    }
  }

  /// Returns a new Syslog appender, configured to append with
  /// the provided tag
  pub fn tag(self, tag: &str) -> Syslog {
    Syslog {
      facility: self.facility,
      host: None,
      tag: Some(tag.to_string()),
      transport: self.transport
    }
  }

  pub fn debug(&mut self, msg: &str) -> Result {
    self.log(Severity::DEBUG, msg)
  }

  pub fn info(&mut self, msg: &str) -> Result {
    self.log(Severity::INFO, msg)
  }

  pub fn notice(&mut self, msg: &str) -> Result {
    self.log(Severity::NOTICE, msg)
  }

  pub fn warn(&mut self, msg: &str) -> Result {
    self.log(Severity::WARNING, msg)
  }

  pub fn err(&mut self, msg: &str) -> Result {
    self.log(Severity::ERROR, msg)
  }

  pub fn critical(&mut self, msg: &str) -> Result {
    self.log(Severity::CRITICAL, msg)
  }

  pub fn alert(&mut self, msg: &str) -> Result {
    self.log(Severity::ALERT, msg)
  }

  pub fn emergency(&mut self, msg: &str) -> Result {
    self.log(Severity::EMERGENCY, msg)
  }

  fn log(&mut self, severity: Severity,  msg: &str) -> Result {
    let formatted = Syslog::line(self.facility.clone(), severity, time::now(), self.host.clone(), self.tag.clone(), msg);
    self.transport.send(&formatted)
  }

  fn line(facility: Facility, severity: Severity, timestamp: Tm, host: Option<String>, tag: Option<String>, msg: &str) -> String {
    format!(
      "<{:?}> {} {} {} {}",
        Syslog::priority(facility, severity), timestamp.rfc3339(),
        host.unwrap_or(NIL.to_string()), tag.unwrap_or(NIL.to_string()), msg)
  }

  // computes the priority of a message based on a facility and severity
  fn priority(facility: Facility, severity: Severity) -> u8 {
    facility as u8 | severity as u8
  }
}

#[cfg(test)]
mod tests {
  use super::{Syslog, Facility, NIL, Severity};
  use time;
  #[test]
  fn test_syslog_line_defaults() {
    let ts = time::now();
    assert_eq!(Syslog::line(
      Facility::LOCAL0, Severity::INFO, ts, None, None, "yo"),
      format!("<134> {} {} {} yo", ts.rfc3339(), NIL, NIL));
  }

  #[test]
  fn test_syslog_line_host() {
    let ts = time::now();
    let host = "foo.local";
    assert_eq!(Syslog::line(
      Facility::LOCAL0, Severity::INFO, ts, Some(host.to_string()), None, "yo"),
      format!("<134> {} {} {} yo", ts.rfc3339(), host, NIL));
  }

  #[test]
  fn test_syslog_line_tag() {
    let ts = time::now();
    let app = "sysly";
    assert_eq!(Syslog::line(
      Facility::LOCAL0, Severity::INFO, ts, None, Some(app.to_string()), "yo"),
      format!("<134> {} {} {} yo", ts.rfc3339(), NIL, app));
  }
}
<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! A simple interface to the Google URL Shortener API.
#![feature(core, io)]
#![unstable]

extern crate hyper;
extern crate "rustc-serialize" as rustc_serialize;
extern crate url;

use hyper::{HttpError};
use hyper::client::{Request};
use hyper::header::{ContentType};
use hyper::method::{Method};
use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper::status::{StatusCode};
use rustc_serialize::json::{BuilderError, Json};
use std::borrow::{ToOwned};
use std::error::{FromError};
use std::old_io::{IoError};
use url::{Url};
use url::ParseError as UrlError;
use url::form_urlencoded::{serialize};

const BASEURL: &'static str = "https://www.googleapis.com/urlshortener/v1/url";

/// Contains all possible errors you might get while shortening a URL
#[derive(Debug)]
pub enum Error {
    BadStatus(StatusCode, String),
    Http(HttpError),
    Io(IoError),
    Json(BuilderError),
    MissingId(Json),
    Url(UrlError),
}
impl FromError<HttpError> for Error {
    fn from_error(err: HttpError) -> Error {
        Error::Http(err)
    }
}
impl FromError<IoError> for Error {
    fn from_error(err: IoError) -> Error {
        Error::Io(err)
    }
}
impl FromError<BuilderError> for Error {
    fn from_error(err: BuilderError) -> Error {
        Error::Json(err)
    }
}
impl FromError<UrlError> for Error {
    fn from_error(err: UrlError) -> Error {
        Error::Url(err)
    }
}

/// Shortens a URL using the Google URL Shortener API
pub fn shorten(key: &str, longurl: &str) -> Result<String, Error> {
    let query = [("key", key)];
    let query = serialize(query.iter().map(|&x| x));
    let url = format!("{}?{}", BASEURL, query);
    let url = try!(Url::parse(&url[]));
    let mut request = try!(Request::new(Method::Post, url));
    request.headers_mut().set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])));
    let mut request = try!(request.start());
    let body = vec![("longUrl".to_owned(), Json::String(longurl.to_owned()))];
    let body = Json::Object(body.into_iter().collect());
    try!(request.write_str(&*body.to_string()));
    let mut response = try!(request.send());
    let body = try!(response.read_to_string());
    if response.status != StatusCode::Ok {
        return Err(Error::BadStatus(response.status, body))
    }
    let json = try!(Json::from_str(&*body));
    let id = json.find("id").and_then(|x| x.as_string());
    match id {
        Some(id) => Ok(id.to_owned()),
        None => Err(Error::MissingId(json.clone())), //FIXME - nonlexical borrows
    }
}
<commit_msg>Fix some warnings.<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! A simple interface to the Google URL Shortener API.
#![feature(old_io)]
#![unstable]

extern crate hyper;
extern crate "rustc-serialize" as rustc_serialize;
extern crate url;

use hyper::{HttpError};
use hyper::client::{Request};
use hyper::header::{ContentType};
use hyper::method::{Method};
use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper::status::{StatusCode};
use rustc_serialize::json::{BuilderError, Json};
use std::borrow::{ToOwned};
use std::error::{FromError};
use std::old_io::{IoError};
use url::{Url};
use url::ParseError as UrlError;
use url::form_urlencoded::{serialize};

const BASEURL: &'static str = "https://www.googleapis.com/urlshortener/v1/url";

/// Contains all possible errors you might get while shortening a URL
#[derive(Debug)]
pub enum Error {
    BadStatus(StatusCode, String),
    Http(HttpError),
    Io(IoError),
    Json(BuilderError),
    MissingId(Json),
    Url(UrlError),
}
impl FromError<HttpError> for Error {
    fn from_error(err: HttpError) -> Error {
        Error::Http(err)
    }
}
impl FromError<IoError> for Error {
    fn from_error(err: IoError) -> Error {
        Error::Io(err)
    }
}
impl FromError<BuilderError> for Error {
    fn from_error(err: BuilderError) -> Error {
        Error::Json(err)
    }
}
impl FromError<UrlError> for Error {
    fn from_error(err: UrlError) -> Error {
        Error::Url(err)
    }
}

/// Shortens a URL using the Google URL Shortener API
pub fn shorten(key: &str, longurl: &str) -> Result<String, Error> {
    let query = [("key", key)];
    let query = serialize(query.iter().map(|&x| x));
    let url = format!("{}?{}", BASEURL, query);
    let url = try!(Url::parse(&url));
    let mut request = try!(Request::new(Method::Post, url));
    request.headers_mut().set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])));
    let mut request = try!(request.start());
    let body = vec![("longUrl".to_owned(), Json::String(longurl.to_owned()))];
    let body = Json::Object(body.into_iter().collect());
    try!(request.write_str(&*body.to_string()));
    let mut response = try!(request.send());
    let body = try!(response.read_to_string());
    if response.status != StatusCode::Ok {
        return Err(Error::BadStatus(response.status, body))
    }
    let json = try!(Json::from_str(&*body));
    let id = json.find("id").and_then(|x| x.as_string());
    match id {
        Some(id) => Ok(id.to_owned()),
        None => Err(Error::MissingId(json.clone())), //FIXME - nonlexical borrows
    }
}
<|endoftext|>


<commit_before>//! # derive_more
//! Rust has lots of builtin traits that are implemented for its basic types, such as [`Add`],
//! [`Not`] or [`From`].
//! However, when wrapping these types inside your own structs or enums you lose the
//! implementations of these traits and are required to recreate them.
//! This is especially annoying when your own structures are very simple, such as when using the
//! commonly advised newtype pattern (e.g. `MyInt(i32)`).
//!
//! This library tries to remove these annoyances and the corresponding boilerplate code.
//! It does this by allowing you to derive lots of commonly used traits for both structs and enums.
//!
//! ## The newly derivable traits
//!
//! Obviously not all traits should be derived to the same code, because they are different
//! different traits after all.
//! However, some of the semantics of the traits overlap a lot, so they have been grouped in the
//! following way:
//!
//! 1. `From`, only contains the [`From`].
//! 2. `Not`-like, contains [`Not`] and [`Neg`].
//! 3. `Add`-like, contains [`Add`], [`Sub`], [`BitAnd`], [`BitOr`] and [`BitXor`].
//! 4. `Mul`-like, contains [`Mul`], [`Div`], [`Rem`], [`Shr`] and [`Shl`].
//! 5. `AddAssign`-like, contains [`AddAssign`], [`SubAssign`], [`BitAndAssign`], [`BitOrAssign`]
//!    and [`BitXorAssign`].
//!
//!
//! ## Generated code
//!
//! It is important to understand what code gets generated when using one of the derives from this
//! crate.
//! That is why the links below explain what code gets generated for a trait for each group from
//! before.
//!
//! 1. [`#[derive(From)]`](from.html)
//! 2. [`#[derive(Not)]`](not.html)
//! 3. [`#[derive(Add)]`](add.html)
//! 4. [`#[derive(Mul)]`](mul.html)
//! 5. [`#[derive(AddAssign)]`](add_assign.html)
//!
//! If you want to be sure what code is generated for your specific trait I recommend using the
//! [`cargo-expand`] utility.
//! This will show you your code with all macros and derives expanded.
//!
//! ## Installation
//!
//! This library heavily uses Macros 1.1, which is to stabilized in Rust 1.15 (the next Rust
//! release).
//! To use it before that time you have to install the nightly or beta channel.
//!
//! After doing this, add this to `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! derive_more = "0.4.0"
//! ```
//!
//! And this to the top of your Rust file:
//!
//! ```
//! #[macro_use]
//! extern crate derive_more;
//! ```
//!
//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
//! [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
//! [`Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
//! [`Neg`]: https://doc.rust-lang.org/std/ops/trait.Neg.html
//! [`Add`]: https://doc.rust-lang.org/std/ops/trait.Add.html
//! [`Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
//! [`BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
//! [`BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
//! [`BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
//! [`Mul`]: https://doc.rust-lang.org/std/ops/trait.Mul.html
//! [`Div`]: https://doc.rust-lang.org/std/ops/trait.Div.html
//! [`Rem`]: https://doc.rust-lang.org/std/ops/trait.Rem.html
//! [`Shr`]: https://doc.rust-lang.org/std/ops/trait.Shr.html
//! [`Shl`]: https://doc.rust-lang.org/std/ops/trait.Shl.html
//! [`AddAssign`]: https://doc.rust-lang.org/std/ops/trait.AddAssign.html
//! [`SubAssign`]: https://doc.rust-lang.org/std/ops/trait.SubAssign.html
//! [`BitAndAssign`]: https://doc.rust-lang.org/std/ops/trait.BitAndAssign.html
//! [`BitOrAssign`]: https://doc.rust-lang.org/std/ops/trait.BitOrAssign.html
//! [`BitXorAssign`]: https://doc.rust-lang.org/std/ops/trait.BitXorAssign.html

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

use proc_macro::TokenStream;

mod utils;

mod from;
mod add_like;
mod add_assign_like;
mod mul_like;
mod not_like;

macro_rules! create_derive(
    ($mod_:ident, $trait_:ident, $fn_name: ident) => {
        #[proc_macro_derive($trait_)]
        #[doc(hidden)]
        pub fn $fn_name(input: TokenStream) -> TokenStream {
            let s = input.to_string();
            let ast = syn::parse_macro_input(&s).unwrap();
            $mod_::expand(&ast, stringify!($trait_)).parse().unwrap()
        }
    }
);

create_derive!(from, From, from_derive);

create_derive!(add_like, Add, add_derive);
create_derive!(add_like, Sub, sub_derive);
create_derive!(add_like, BitAnd, bit_and_derive);
create_derive!(add_like, BitOr, bit_or_derive);
create_derive!(add_like, BitXor, bit_xor_derive);

create_derive!(mul_like, Mul, mul_derive);
create_derive!(mul_like, Div, div_derive);
create_derive!(mul_like, Rem, rem_derive);
create_derive!(mul_like, Shr, shr_derive);
create_derive!(mul_like, Shl, shl_derive);

create_derive!(not_like, Not, not_derive);
create_derive!(not_like, Neg, neg_derive);

create_derive!(add_assign_like, AddAssign,    add_assign_derive);
create_derive!(add_assign_like, SubAssign,    sub_assign_derive);
create_derive!(add_assign_like, BitAndAssign, bit_and_assign_derive);
create_derive!(add_assign_like, BitOrAssign,  bit_or_assign_derive);
create_derive!(add_assign_like, BitXorAssign, bit_xor_assign_derive);
<commit_msg>Docs: Add example to docs<commit_after>//! # derive_more
//! Rust has lots of builtin traits that are implemented for its basic types, such as [`Add`],
//! [`Not`] or [`From`].
//! However, when wrapping these types inside your own structs or enums you lose the
//! implementations of these traits and are required to recreate them.
//! This is especially annoying when your own structures are very simple, such as when using the
//! commonly advised newtype pattern (e.g. `MyInt(i32)`).
//!
//! This library tries to remove these annoyances and the corresponding boilerplate code.
//! It does this by allowing you to derive lots of commonly used traits for both structs and enums.
//!
//! ## Example code
//!
//! By using this library the following code just works:
//!
//! ```rust
//! #[derive(Eq, From, Add)]
//! struct MyInt(i32);
//!
//! #[derive(Eq, Mul)]
//! struct Point2D { x: i32, y: i32 };
//!
//! fn main() {
//!     let my_11 = MyInt(5) + 6.into();
//!     assert_eq!(MyInt(11), MyInt(5) + 6.into())
//!     assert_eq!(Point2D { x: 5, y: 6 } * 10, (50, 60).into());
//! }
//!
//! ```

//! ## The newly derivable traits
//!
//! Obviously not all traits should be derived to the same code, because they are different
//! different traits after all.
//! However, some of the semantics of the traits overlap a lot, so they have been grouped in the
//! following way:
//!
//! 1. `From`, only contains the [`From`].
//! 2. `Not`-like, contains [`Not`] and [`Neg`].
//! 3. `Add`-like, contains [`Add`], [`Sub`], [`BitAnd`], [`BitOr`] and [`BitXor`].
//! 4. `Mul`-like, contains [`Mul`], [`Div`], [`Rem`], [`Shr`] and [`Shl`].
//! 5. `AddAssign`-like, contains [`AddAssign`], [`SubAssign`], [`BitAndAssign`], [`BitOrAssign`]
//!    and [`BitXorAssign`].
//!
//!
//! ## Generated code
//!
//! It is important to understand what code gets generated when using one of the derives from this
//! crate.
//! That is why the links below explain what code gets generated for a trait for each group from
//! before.
//!
//! 1. [`#[derive(From)]`](from.html)
//! 2. [`#[derive(Not)]`](not.html)
//! 3. [`#[derive(Add)]`](add.html)
//! 4. [`#[derive(Mul)]`](mul.html)
//! 5. [`#[derive(AddAssign)]`](add_assign.html)
//!
//! If you want to be sure what code is generated for your specific trait I recommend using the
//! [`cargo-expand`] utility.
//! This will show you your code with all macros and derives expanded.
//!
//! ## Installation
//!
//! This library heavily uses Macros 1.1, which is to stabilized in Rust 1.15 (the next Rust
//! release).
//! To use it before that time you have to install the nightly or beta channel.
//!
//! After doing this, add this to `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! derive_more = "0.4.0"
//! ```
//!
//! And this to the top of your Rust file:
//!
//! ```
//! #[macro_use]
//! extern crate derive_more;
//! ```
//!
//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
//! [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
//! [`Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
//! [`Neg`]: https://doc.rust-lang.org/std/ops/trait.Neg.html
//! [`Add`]: https://doc.rust-lang.org/std/ops/trait.Add.html
//! [`Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
//! [`BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
//! [`BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
//! [`BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
//! [`Mul`]: https://doc.rust-lang.org/std/ops/trait.Mul.html
//! [`Div`]: https://doc.rust-lang.org/std/ops/trait.Div.html
//! [`Rem`]: https://doc.rust-lang.org/std/ops/trait.Rem.html
//! [`Shr`]: https://doc.rust-lang.org/std/ops/trait.Shr.html
//! [`Shl`]: https://doc.rust-lang.org/std/ops/trait.Shl.html
//! [`AddAssign`]: https://doc.rust-lang.org/std/ops/trait.AddAssign.html
//! [`SubAssign`]: https://doc.rust-lang.org/std/ops/trait.SubAssign.html
//! [`BitAndAssign`]: https://doc.rust-lang.org/std/ops/trait.BitAndAssign.html
//! [`BitOrAssign`]: https://doc.rust-lang.org/std/ops/trait.BitOrAssign.html
//! [`BitXorAssign`]: https://doc.rust-lang.org/std/ops/trait.BitXorAssign.html

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

use proc_macro::TokenStream;

mod utils;

mod from;
mod add_like;
mod add_assign_like;
mod mul_like;
mod not_like;

macro_rules! create_derive(
    ($mod_:ident, $trait_:ident, $fn_name: ident) => {
        #[proc_macro_derive($trait_)]
        #[doc(hidden)]
        pub fn $fn_name(input: TokenStream) -> TokenStream {
            let s = input.to_string();
            let ast = syn::parse_macro_input(&s).unwrap();
            $mod_::expand(&ast, stringify!($trait_)).parse().unwrap()
        }
    }
);

create_derive!(from, From, from_derive);

create_derive!(add_like, Add, add_derive);
create_derive!(add_like, Sub, sub_derive);
create_derive!(add_like, BitAnd, bit_and_derive);
create_derive!(add_like, BitOr, bit_or_derive);
create_derive!(add_like, BitXor, bit_xor_derive);

create_derive!(mul_like, Mul, mul_derive);
create_derive!(mul_like, Div, div_derive);
create_derive!(mul_like, Rem, rem_derive);
create_derive!(mul_like, Shr, shr_derive);
create_derive!(mul_like, Shl, shl_derive);

create_derive!(not_like, Not, not_derive);
create_derive!(not_like, Neg, neg_derive);

create_derive!(add_assign_like, AddAssign,    add_assign_derive);
create_derive!(add_assign_like, SubAssign,    sub_assign_derive);
create_derive!(add_assign_like, BitAndAssign, bit_and_assign_derive);
create_derive!(add_assign_like, BitOrAssign,  bit_or_assign_derive);
create_derive!(add_assign_like, BitXorAssign, bit_xor_assign_derive);
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::ops::{
    Deref,
    DerefMut,
};
use std::slice;
use std::convert::From;

/// Make sure the non-nullable pointer optimization does not occur!
enum Flag<T> {
    Alive(T),
    Dropped,
    _Unused,
}

/// Trait for fixed size arrays.
pub unsafe trait Array {
    /// The array's element type
    type Item;
    #[doc(hidden)]
    unsafe fn new() -> Self;
    #[doc(hidden)]
    fn as_ptr(&self) -> *const Self::Item;
    #[doc(hidden)]
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    #[doc(hidden)]
    fn capacity() -> usize;
}

macro_rules! fix_array_impl {
    ($len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            /// Note: Returnin an uninitialized value here only works
            /// if we can be sure the data is never used. The nullable pointer
            /// inside enum optimization conflicts with this this for example,
            /// so we need to be extra careful. See `Flag` enum.
            unsafe fn new() -> [T; $len] { mem::uninitialized() }
            #[inline]
            fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
            fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
            #[inline]
            fn capacity() -> usize { $len }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    () => ();
    ($len:expr, $($more:expr,)*) => (
        fix_array_impl!($len);
        fix_array_impl_recursive!($($more,)*);
    );
}

fix_array_impl_recursive!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                          16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
                          32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,);

/// A vector with a fixed capacity.
///
/// The **ArrayVec** is a vector backed by a fixed size array and keeps track of
/// the number of initialized elements.
///
/// The vector is a contiguous value that you can store directly on the stack
/// if needed.
///
/// It offers a simple API of *.push()* and *.pop()* but also dereferences to a slice, so
/// that the full slice API is available.
///
/// The vector also implements a by value iterator.
pub struct ArrayVec<A: Array> {
    len: u8,
    xs: Flag<A>,
}

impl<A: Array> Drop for ArrayVec<A> {
    fn drop(&mut self) {
        // clear all elements, then inhibit drop of inner array
        while let Some(_) = self.pop() { }
        unsafe {
            ptr::write(&mut self.xs, Flag::Dropped);
        }
    }
}

impl<A: Array> ArrayVec<A> {
    /// Create a new empty **ArrayVec**.
    ///
    /// Capacity is inferred from the type parameter.
    ///
    /// ## Examples
    ///
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 16]>::new();
    /// array.push(1);
    /// array.push(2);
    /// assert_eq!(&array[..], &[1, 2]);
    /// assert_eq!(array.capacity(), 16);
    /// ```
    pub fn new() -> ArrayVec<A> {
        unsafe {
            ArrayVec { xs: Flag::Alive(Array::new()), len: 0 }
        }
    }

    #[inline]
    fn inner_ref(&self) -> &A {
        match self.xs {
            Flag::Alive(ref xs) => xs,
            _ => unreachable!(),
            //_ => std::intrinsics::unreachable(),
        }
    }

    #[inline]
    fn inner_mut(&mut self) -> &mut A {
        // FIXME: Optimize this, we know it's always Some.
        match self.xs {
            Flag::Alive(ref mut xs) => xs,
            _ => unreachable!(),
            //_ => std::intrinsics::unreachable(),
        }
    }

    /// Return the number of elements in the **ArrayVec**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::from([1, 2, 3]);
    /// array.pop();
    /// assert_eq!(array.len(), 2);
    /// ```
    #[inline]
    pub fn len(&self) -> usize { self.len as usize }

    /// Return the capacity of the **ArrayVec**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let array = ArrayVec::from([1, 2, 3]);
    /// assert_eq!(array.capacity(), 3);
    /// ```
    #[inline]
    pub fn capacity(&self) -> usize { A::capacity() }

    /// Push **element** to the end of the vector.
    ///
    /// Return **None** if the push succeeds, or and return **Some(** *element* **)**
    /// if the vector is full.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 2]>::new();
    ///
    /// array.push(1);
    /// array.push(2);
    /// let overflow = array.push(3);
    ///
    /// assert_eq!(&array[..], &[1, 2]);
    /// assert_eq!(overflow, Some(3));
    /// ```
    pub fn push(&mut self, element: A::Item) -> Option<A::Item> {
        if self.len() < A::capacity() {
            unsafe {
                let len = self.len();
                ptr::write(self.get_unchecked_mut(len), element);
            }
            self.len += 1;
            None
        } else {
            Some(element)
        }
    }

    /// Remove the last element in the vector.
    ///
    /// Return **Some(** *element* **)** if the vector is non-empty, else **None**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 2]>::new();
    ///
    /// array.push(1);
    ///
    /// assert_eq!(array.pop(), Some(1));
    /// assert_eq!(array.pop(), None);
    /// ```
    pub fn pop(&mut self) -> Option<A::Item> {
        if self.len == 0 {
            return None
        }
        unsafe {
            self.len -= 1;
            let len = self.len();
            Some(ptr::read(self.get_unchecked_mut(len)))
        }
    }
}

impl<A: Array> Deref for ArrayVec<A> {
    type Target = [A::Item];
    #[inline]
    fn deref(&self) -> &[A::Item] {
        unsafe {
            slice::from_raw_parts(self.inner_ref().as_ptr(), self.len())
        }
    }
}

impl<A: Array> DerefMut for ArrayVec<A> {
    #[inline]
    fn deref_mut(&mut self) -> &mut [A::Item] {
        let len = self.len();
        unsafe {
            slice::from_raw_parts_mut(self.inner_mut().as_mut_ptr(), len)
        }
    }
}

/// Create an **ArrayVec** from an array.
///
/// ## Examples
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::from([1, 2, 3]);
/// assert_eq!(array.len(), 3);
/// assert_eq!(array.capacity(), 3);
/// ```
impl<A: Array> From<A> for ArrayVec<A> {
    fn from(array: A) -> Self {
        ArrayVec { xs: Flag::Alive(array), len: A::capacity() as u8 }
    }
}

/// Iterate the **ArrayVec** with references to each element.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let array = ArrayVec::from([1, 2, 3]);
///
/// for elt in &array {
///     // ...
/// }
/// ```
impl<'a, A: Array> IntoIterator for &'a ArrayVec<A> {
    type Item = &'a A::Item;
    type IntoIter = slice::Iter<'a, A::Item>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

/// Iterate the **ArrayVec** with mutable references to each element.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::from([1, 2, 3]);
///
/// for elt in &mut array {
///     // ...
/// }
/// ```
impl<'a, A: Array> IntoIterator for &'a mut ArrayVec<A> {
    type Item = &'a mut A::Item;
    type IntoIter = slice::IterMut<'a, A::Item>;
    fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
}

/// Iterate the **ArrayVec** with each element by value.
///
/// The vector is consumed by this operation.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// for elt in ArrayVec::from([1, 2, 3]) {
///     // ...
/// }
/// ```
impl<A: Array> IntoIterator for ArrayVec<A> {
    type Item = A::Item;
    type IntoIter = IntoIter<A>;
    fn into_iter(self) -> IntoIter<A> {
        IntoIter { index: 0, v: self, }
    }
}

/// By-value iterator for ArrayVec.
pub struct IntoIter<A: Array> {
    index: u8,
    v: ArrayVec<A>,
}

impl<A: Array> Iterator for IntoIter<A> {
    type Item = A::Item;

    fn next(&mut self) -> Option<A::Item> {
        if self.index == self.v.len {
            None
        } else {
            unsafe {
                let ptr = self.v.get_unchecked_mut(self.index as usize);
                let elt = ptr::read(ptr);
                self.index += 1;
                Some(elt)
            }
        }
    }
}

impl<A: Array> Drop for IntoIter<A> {
    fn drop(&mut self) {
        // exhaust iterator and clear the vector
        while let Some(_) = self.next() { }
        self.v.len = 0;
    }
}

#[test]
fn test_simple() {
    use std::ops::Add;

    let mut vec: ArrayVec<[Vec<i32>; 3]> = ArrayVec::new();

    vec.push(vec![1,2,3,4]);
    vec.push(vec![3]);
    vec.push(vec![-1, 90, -2]);

    for elt in &vec {
        println!("{:?}", elt);
    }

    let sum = vec.iter().map(|x| x.iter().fold(0, Add::add)).fold(0, Add::add);
    assert_eq!(sum, 13 + 87);
    let sum_len = vec.into_iter().map(|x| x.len()).fold(0, Add::add);
    assert_eq!(sum_len, 8);
}

#[test]
fn test_drop() {
    use std::rc::Rc;
    use std::cell::Cell;

    let flag = Rc::new(Cell::new(0));

    struct Foo(Rc<Cell<i32>>);

    impl Drop for Foo {
        fn drop(&mut self) {
            let n = self.0.get();
            self.0.set(n + 1);
        }
    }

    {
        let mut array = ArrayVec::<[Foo; 128]>::new();
        array.push(Foo(flag.clone()));
        array.push(Foo(flag.clone()));
    }
    assert_eq!(flag.get(), 2);

    // test something with the nullable pointer optimization
    flag.set(0);

    {
        let mut array = ArrayVec::<[_; 3]>::new();
        array.push(vec![Foo(flag.clone())]);
        array.push(vec![Foo(flag.clone()), Foo(flag.clone())]);
        array.push(vec![]);
        array.push(vec![Foo(flag.clone())]);
        assert_eq!(flag.get(), 1);
        drop(array.pop());
        assert_eq!(flag.get(), 1);
        drop(array.pop());
        assert_eq!(flag.get(), 3);
    }

    assert_eq!(flag.get(), 4);
}
<commit_msg>Implement Extend and FromIterator<commit_after>use std::iter;
use std::mem;
use std::ptr;
use std::ops::{
    Deref,
    DerefMut,
};
use std::slice;
use std::convert::From;

/// Make sure the non-nullable pointer optimization does not occur!
enum Flag<T> {
    Alive(T),
    Dropped,
    _Unused,
}

/// Trait for fixed size arrays.
pub unsafe trait Array {
    /// The array's element type
    type Item;
    #[doc(hidden)]
    unsafe fn new() -> Self;
    #[doc(hidden)]
    fn as_ptr(&self) -> *const Self::Item;
    #[doc(hidden)]
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    #[doc(hidden)]
    fn capacity() -> usize;
}

macro_rules! fix_array_impl {
    ($len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            /// Note: Returnin an uninitialized value here only works
            /// if we can be sure the data is never used. The nullable pointer
            /// inside enum optimization conflicts with this this for example,
            /// so we need to be extra careful. See `Flag` enum.
            unsafe fn new() -> [T; $len] { mem::uninitialized() }
            #[inline]
            fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
            fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
            #[inline]
            fn capacity() -> usize { $len }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    () => ();
    ($len:expr, $($more:expr,)*) => (
        fix_array_impl!($len);
        fix_array_impl_recursive!($($more,)*);
    );
}

fix_array_impl_recursive!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                          16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
                          32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,);

/// A vector with a fixed capacity.
///
/// The **ArrayVec** is a vector backed by a fixed size array and keeps track of
/// the number of initialized elements.
///
/// The vector is a contiguous value that you can store directly on the stack
/// if needed.
///
/// It offers a simple API of *.push()* and *.pop()* but also dereferences to a slice, so
/// that the full slice API is available.
///
/// The vector also implements a by value iterator.
pub struct ArrayVec<A: Array> {
    len: u8,
    xs: Flag<A>,
}

impl<A: Array> Drop for ArrayVec<A> {
    fn drop(&mut self) {
        // clear all elements, then inhibit drop of inner array
        while let Some(_) = self.pop() { }
        unsafe {
            ptr::write(&mut self.xs, Flag::Dropped);
        }
    }
}

impl<A: Array> ArrayVec<A> {
    /// Create a new empty **ArrayVec**.
    ///
    /// Capacity is inferred from the type parameter.
    ///
    /// ## Examples
    ///
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 16]>::new();
    /// array.push(1);
    /// array.push(2);
    /// assert_eq!(&array[..], &[1, 2]);
    /// assert_eq!(array.capacity(), 16);
    /// ```
    pub fn new() -> ArrayVec<A> {
        unsafe {
            ArrayVec { xs: Flag::Alive(Array::new()), len: 0 }
        }
    }

    #[inline]
    fn inner_ref(&self) -> &A {
        match self.xs {
            Flag::Alive(ref xs) => xs,
            _ => unreachable!(),
            //_ => std::intrinsics::unreachable(),
        }
    }

    #[inline]
    fn inner_mut(&mut self) -> &mut A {
        // FIXME: Optimize this, we know it's always Some.
        match self.xs {
            Flag::Alive(ref mut xs) => xs,
            _ => unreachable!(),
            //_ => std::intrinsics::unreachable(),
        }
    }

    /// Return the number of elements in the **ArrayVec**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::from([1, 2, 3]);
    /// array.pop();
    /// assert_eq!(array.len(), 2);
    /// ```
    #[inline]
    pub fn len(&self) -> usize { self.len as usize }

    /// Return the capacity of the **ArrayVec**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let array = ArrayVec::from([1, 2, 3]);
    /// assert_eq!(array.capacity(), 3);
    /// ```
    #[inline]
    pub fn capacity(&self) -> usize { A::capacity() }

    /// Push **element** to the end of the vector.
    ///
    /// Return **None** if the push succeeds, or and return **Some(** *element* **)**
    /// if the vector is full.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 2]>::new();
    ///
    /// array.push(1);
    /// array.push(2);
    /// let overflow = array.push(3);
    ///
    /// assert_eq!(&array[..], &[1, 2]);
    /// assert_eq!(overflow, Some(3));
    /// ```
    pub fn push(&mut self, element: A::Item) -> Option<A::Item> {
        if self.len() < A::capacity() {
            unsafe {
                let len = self.len();
                ptr::write(self.get_unchecked_mut(len), element);
            }
            self.len += 1;
            None
        } else {
            Some(element)
        }
    }

    /// Remove the last element in the vector.
    ///
    /// Return **Some(** *element* **)** if the vector is non-empty, else **None**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 2]>::new();
    ///
    /// array.push(1);
    ///
    /// assert_eq!(array.pop(), Some(1));
    /// assert_eq!(array.pop(), None);
    /// ```
    pub fn pop(&mut self) -> Option<A::Item> {
        if self.len == 0 {
            return None
        }
        unsafe {
            self.len -= 1;
            let len = self.len();
            Some(ptr::read(self.get_unchecked_mut(len)))
        }
    }
}

impl<A: Array> Deref for ArrayVec<A> {
    type Target = [A::Item];
    #[inline]
    fn deref(&self) -> &[A::Item] {
        unsafe {
            slice::from_raw_parts(self.inner_ref().as_ptr(), self.len())
        }
    }
}

impl<A: Array> DerefMut for ArrayVec<A> {
    #[inline]
    fn deref_mut(&mut self) -> &mut [A::Item] {
        let len = self.len();
        unsafe {
            slice::from_raw_parts_mut(self.inner_mut().as_mut_ptr(), len)
        }
    }
}

/// Create an **ArrayVec** from an array.
///
/// ## Examples
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::from([1, 2, 3]);
/// assert_eq!(array.len(), 3);
/// assert_eq!(array.capacity(), 3);
/// ```
impl<A: Array> From<A> for ArrayVec<A> {
    fn from(array: A) -> Self {
        ArrayVec { xs: Flag::Alive(array), len: A::capacity() as u8 }
    }
}

/// Iterate the **ArrayVec** with references to each element.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let array = ArrayVec::from([1, 2, 3]);
///
/// for elt in &array {
///     // ...
/// }
/// ```
impl<'a, A: Array> IntoIterator for &'a ArrayVec<A> {
    type Item = &'a A::Item;
    type IntoIter = slice::Iter<'a, A::Item>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

/// Iterate the **ArrayVec** with mutable references to each element.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::from([1, 2, 3]);
///
/// for elt in &mut array {
///     // ...
/// }
/// ```
impl<'a, A: Array> IntoIterator for &'a mut ArrayVec<A> {
    type Item = &'a mut A::Item;
    type IntoIter = slice::IterMut<'a, A::Item>;
    fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
}

/// Iterate the **ArrayVec** with each element by value.
///
/// The vector is consumed by this operation.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// for elt in ArrayVec::from([1, 2, 3]) {
///     // ...
/// }
/// ```
impl<A: Array> IntoIterator for ArrayVec<A> {
    type Item = A::Item;
    type IntoIter = IntoIter<A>;
    fn into_iter(self) -> IntoIter<A> {
        IntoIter { index: 0, v: self, }
    }
}

/// By-value iterator for ArrayVec.
pub struct IntoIter<A: Array> {
    index: u8,
    v: ArrayVec<A>,
}

impl<A: Array> Iterator for IntoIter<A> {
    type Item = A::Item;

    fn next(&mut self) -> Option<A::Item> {
        if self.index == self.v.len {
            None
        } else {
            unsafe {
                let ptr = self.v.get_unchecked_mut(self.index as usize);
                let elt = ptr::read(ptr);
                self.index += 1;
                Some(elt)
            }
        }
    }
}

impl<A: Array> Drop for IntoIter<A> {
    fn drop(&mut self) {
        // exhaust iterator and clear the vector
        while let Some(_) = self.next() { }
        self.v.len = 0;
    }
}

/// Extend the **ArrayVec** with an iterator.
///
/// Does not extract more items than there is space for. No error
/// occurs if there are more iterator elements.
impl<A: Array> Extend<A::Item> for ArrayVec<A> {
    fn extend<T: IntoIterator<Item=A::Item>>(&mut self, iter: T) {
        let take = self.capacity() - self.len();
        for elt in iter.into_iter().take(take) {
            self.push(elt);
        }
    }
}

/// Create an **ArrayVec** from an iterator.
///
/// Does not extract more items than there is space for. No error
/// occurs if there are more iterator elements.
impl<A: Array> iter::FromIterator<A::Item> for ArrayVec<A> {
    fn from_iter<T: IntoIterator<Item=A::Item>>(iter: T) -> Self {
        let mut array = ArrayVec::new();
        array.extend(iter);
        array
    }
}

#[test]
fn test_simple() {
    use std::ops::Add;

    let mut vec: ArrayVec<[Vec<i32>; 3]> = ArrayVec::new();

    vec.push(vec![1,2,3,4]);
    vec.push(vec![3]);
    vec.push(vec![-1, 90, -2]);

    for elt in &vec {
        println!("{:?}", elt);
    }

    let sum = vec.iter().map(|x| x.iter().fold(0, Add::add)).fold(0, Add::add);
    assert_eq!(sum, 13 + 87);
    let sum_len = vec.into_iter().map(|x| x.len()).fold(0, Add::add);
    assert_eq!(sum_len, 8);
}

#[test]
fn test_drop() {
    use std::rc::Rc;
    use std::cell::Cell;

    let flag = Rc::new(Cell::new(0));

    struct Foo(Rc<Cell<i32>>);

    impl Drop for Foo {
        fn drop(&mut self) {
            let n = self.0.get();
            self.0.set(n + 1);
        }
    }

    {
        let mut array = ArrayVec::<[Foo; 128]>::new();
        array.push(Foo(flag.clone()));
        array.push(Foo(flag.clone()));
    }
    assert_eq!(flag.get(), 2);

    // test something with the nullable pointer optimization
    flag.set(0);

    {
        let mut array = ArrayVec::<[_; 3]>::new();
        array.push(vec![Foo(flag.clone())]);
        array.push(vec![Foo(flag.clone()), Foo(flag.clone())]);
        array.push(vec![]);
        array.push(vec![Foo(flag.clone())]);
        assert_eq!(flag.get(), 1);
        drop(array.pop());
        assert_eq!(flag.get(), 1);
        drop(array.pop());
        assert_eq!(flag.get(), 3);
    }

    assert_eq!(flag.get(), 4);
}

#[test]
fn test_extend() {
    let mut range = 0..10;

    let mut array: ArrayVec<[_; 5]> = range.by_ref().collect();
    assert_eq!(&array[..], &[0, 1, 2, 3, 4]);
    assert_eq!(range.next(), Some(5));

    array.extend(range.by_ref());
    assert_eq!(range.next(), Some(6));

    let mut array: ArrayVec<[_; 10]> = (0..3).collect();
    assert_eq!(&array[..], &[0, 1, 2]);
    array.extend(3..5);
    assert_eq!(&array[..], &[0, 1, 2, 3, 4]);
}
<|endoftext|>


<commit_before><commit_msg>format > to_string<commit_after><|endoftext|>


<commit_before>use std::io::BufRead;
use std::io;
use std::str::SplitWhitespace;
use std::str::FromStr;

#[derive(Debug)]
pub enum LoadingError {
    InvalidLine(usize),
    WrongNumberOfArguments(usize),
    Parse(usize),
    Io(io::Error),
}

/// A struct containing all data store by wavefront
pub struct ObjData {
    vertices : Vec<(f32,f32,f32,f32)>,
    normals : Vec<(f32,f32,f32)>,
    texcoords : Vec<(f32,f32,f32)>,
    faces : Vec<Vec<(usize,Option<usize>,Option<usize>)>>
}

impl From<io::Error> for LoadingError {
    fn from(err : io::Error) -> LoadingError {
        LoadingError::Io(err)
    }
}

fn parse<T : FromStr>(it : SplitWhitespace, nb : usize) -> Result<Vec<T>, LoadingError> {
    let mut vec : Vec<T> = Vec::new();
    for s in it {
        let val = match s.parse::<T>() {
            Ok(v) => v,
            Err(_) => return Err(LoadingError::Parse(nb)),
        };
        vec.push(val);
    }
    return Ok(vec);
}

impl ObjData {

    /// Constructs a new empty `ObjData`.
    ///
    /// # Examples
    ///
    /// ```
    /// use lwobj::ObjData;
    ///
    /// let data = ObjData::new();
    /// ```
    pub fn new() -> ObjData {
        ObjData {
            vertices : Vec::new(),
            normals : Vec::new(),
            texcoords : Vec::new(),
            faces : Vec::new(),
        }
    }

    /// Load an `ObjData` from a `BufReader`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::File;
    /// use std::io::BufReader;
    /// use lwobj::ObjData;
    ///
    /// let f = File::open("cube.obj").unwrap();
    /// let mut input = BufReader::new(f);
    /// let data = ObjData::load(&mut input).ok().unwrap();
    /// ```
    pub fn load<R : io::Read>(input : &mut io::BufReader<R>) -> Result<ObjData,LoadingError> {
        let mut data = ObjData::new();
        let mut buf = String::new();
        let mut nb : usize = 0;
        while try!(input.read_line(&mut buf)) > 0 {
            // Skip comment
            if buf.chars().next().unwrap() != '#' {
                let mut iter = buf.split_whitespace();
                match iter.next() {
                    Some("v") => {
                        let args = try!(parse::<f32>(iter,nb));
                        if args.len() == 4 {
                            data.vertices.push((args[0],args[1],args[2],args[3]));
                        } else if args.len() == 3 {
                            data.vertices.push((args[0],args[1],args[2],1.0));
                        } else {
                            return Err(LoadingError::WrongNumberOfArguments(nb));
                        }
                    },
                    Some("vn") => {
                        let args = try!(parse::<f32>(iter,nb));
                        if args.len() == 3 {
                            data.normals.push((args[0],args[1],args[2]));
                        } else {
                            return Err(LoadingError::WrongNumberOfArguments(nb));
                        }
                    },
                    Some("vt") => {
                        let args = try!(parse::<f32>(iter,nb));
                        if args.len() == 3 {
                            data.texcoords.push((args[0],args[1],args[2]));
                        } else if args.len() == 2 {
                            data.texcoords.push((args[0],args[1],0.));
                        } else {
                            return Err(LoadingError::WrongNumberOfArguments(nb));
                        }
                    },
                    Some("s") => {
                        // Not supported
                    },
                    Some("f") => {
                        let mut vec : Vec<(usize,Option<usize>,Option<usize>)> = Vec::new();
                        for arg in iter {
                            let index : Vec<_> = arg.split('/').collect();
                            if index.len() != 3 {
                                return Err(LoadingError::WrongNumberOfArguments(nb));
                            }
                            let v = match index[0].parse::<usize>() {
                                Ok(val) => val,
                                Err(_) => return Err(LoadingError::Parse(nb)),
                            };
                            let vt = index[1].parse::<usize>().ok();
                            let vn = index[2].parse::<usize>().ok();
                            vec.push((v,vt,vn));
                        }
                        data.faces.push(vec);
                    },
                    Some("o") => {
                        // Not supported
                    },
                    _ => return Err(LoadingError::InvalidLine(nb)),
                }
            }
            nb += 1;
            buf.clear();
        }
        return Ok(data);
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::io::BufReader;
    use obj::*;

    #[test]
    fn load() {
        let mut expected = ObjData::new();
        expected.vertices = vec![(1.,-1.,-1.,1.),
        (1.,-1.,1.,1.),
        (-1.,-1.,1.,1.),
        (-1.,-1.,-1.,1.),
        (1.,1.,-1.,1.),
        (1.,1.,1.,1.),
        (-1.,1.,1.,1.),
        (-1.,1.,-1.,1.)];
        expected.normals = vec![(0.,-1.,0.),
        (0.,1.,0.),
        (1.,0.,0.),
        (0.,0.,1.),
        (-1.,0.,0.),
        (0.,0.,-1.)];
        expected.faces = vec![ vec![(2,None,Some(1)), (4,None,Some(1)), (1,None,Some(1))],
        vec![(8,None,Some(2)), (6,None,Some(2)), (5,None,Some(2))],
        vec![(5,None,Some(3)), (2,None,Some(3)), (1,None,Some(3))],
        vec![(6,None,Some(4)), (3,None,Some(4)), (2,None,Some(4))],
        vec![(3,None,Some(5)), (8,None,Some(5)), (4,None,Some(5))],
        vec![(1,None,Some(6)), (8,None,Some(6)), (5,None,Some(6))],
        vec![(2,None,Some(1)), (3,None,Some(1)), (4,None,Some(1))],
        vec![(8,None,Some(2)), (7,None,Some(2)), (6,None,Some(2))],
        vec![(5,None,Some(3)), (6,None,Some(3)), (2,None,Some(3))],
        vec![(6,None,Some(4)), (7,None,Some(4)), (3,None,Some(4))],
        vec![(3,None,Some(5)), (7,None,Some(5)), (8,None,Some(5))],
        vec![(1,None,Some(6)), (4,None,Some(6)), (8,None,Some(6))],
        ];
        let f = File::open("cube.obj").unwrap();
        let mut input = BufReader::new(f);
        let data = ObjData::load(&mut input).ok().unwrap();
        assert_eq!(expected.vertices,data.vertices);
        assert_eq!(expected.normals,data.normals);
        assert_eq!(expected.texcoords,data.texcoords);
        assert_eq!(expected.faces,data.faces);
    }
}
<commit_msg>Adds documentation + Changes indexes starting value to 0<commit_after>use std::io::BufRead;
use std::io;
use std::str::SplitWhitespace;
use std::str::FromStr;

#[derive(Debug)]
pub enum LoadingError {
    InvalidLine(usize),
    WrongNumberOfArguments(usize),
    Parse(usize),
    Io(io::Error),
}

/// A struct containing all data store by wavefront.
pub struct ObjData {
    /// List of vertices `(x,y,z,w)`.
    /// Its coordinates are (x,y,z) and w is the weight for rational curves and surfaces.
    pub vertices : Vec<(f32,f32,f32,f32)>,
    /// List of normal vector with componetns `(x,y,z)`.
    pub normals : Vec<(f32,f32,f32)>,
    /// List of texture coordinates `(u,v,w)`.
    /// u and v are the value for the horizontal and vertical direction.
    /// w is the value for the depth of the texture.
    pub texcoords : Vec<(f32,f32,f32)>,
    /// List of faces.
    /// Each Face is a list of `(v,vt,vn)`.
    /// v is the index of vertex.
    /// vt is the index of its texture coordinate if it has one.
    /// vn is the index of its normal vector if it has one.
    pub faces : Vec<Vec<(usize,Option<usize>,Option<usize>)>>
}

impl From<io::Error> for LoadingError {
    fn from(err : io::Error) -> LoadingError {
        LoadingError::Io(err)
    }
}

fn parse<T : FromStr>(it : SplitWhitespace, nb : usize) -> Result<Vec<T>, LoadingError> {
    let mut vec : Vec<T> = Vec::new();
    for s in it {
        let val = match s.parse::<T>() {
            Ok(v) => v,
            Err(_) => return Err(LoadingError::Parse(nb)),
        };
        vec.push(val);
    }
    return Ok(vec);
}

impl ObjData {
    /// Constructs a new empty `ObjData`.
    ///
    /// # Examples
    ///
    /// ```
    /// use lwobj::ObjData;
    ///
    /// let data = ObjData::new();
    /// ```
    pub fn new() -> ObjData {
        ObjData {
            vertices : Vec::new(),
            normals : Vec::new(),
            texcoords : Vec::new(),
            faces : Vec::new(),
        }
    }

    /// Load an `ObjData` from a `BufReader`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::File;
    /// use std::io::BufReader;
    /// use lwobj::ObjData;
    ///
    /// let f = File::open("cube.obj").unwrap();
    /// let mut input = BufReader::new(f);
    /// let data = ObjData::load(&mut input).ok().unwrap();
    /// ```
    pub fn load<R : io::Read>(input : &mut io::BufReader<R>) -> Result<ObjData,LoadingError> {
        let mut data = ObjData::new();
        let mut buf = String::new();
        let mut nb : usize = 0;
        while try!(input.read_line(&mut buf)) > 0 {
            // Skip comment
            if buf.chars().next().unwrap() != '#' {
                let mut iter = buf.split_whitespace();
                match iter.next() {
                    Some("v") => {
                        let args = try!(parse::<f32>(iter,nb));
                        if args.len() == 4 {
                            data.vertices.push((args[0],args[1],args[2],args[3]));
                        } else if args.len() == 3 {
                            data.vertices.push((args[0],args[1],args[2],1.0));
                        } else {
                            return Err(LoadingError::WrongNumberOfArguments(nb));
                        }
                    },
                    Some("vn") => {
                        let args = try!(parse::<f32>(iter,nb));
                        if args.len() == 3 {
                            data.normals.push((args[0],args[1],args[2]));
                        } else {
                            return Err(LoadingError::WrongNumberOfArguments(nb));
                        }
                    },
                    Some("vt") => {
                        let args = try!(parse::<f32>(iter,nb));
                        if args.len() == 3 {
                            data.texcoords.push((args[0],args[1],args[2]));
                        } else if args.len() == 2 {
                            data.texcoords.push((args[0],args[1],0.));
                        } else if args.len() == 1 {
                            data.texcoords.push((args[0],0.,0.));
                        } else {
                            return Err(LoadingError::WrongNumberOfArguments(nb));
                        }
                    },
                    Some("s") => {
                        // Not supported
                    },
                    Some("f") => {
                        let mut vec : Vec<(usize,Option<usize>,Option<usize>)> = Vec::new();
                        for arg in iter {
                            let index : Vec<_> = arg.split('/').collect();
                            if index.len() != 3 {
                                return Err(LoadingError::WrongNumberOfArguments(nb));
                            }
                            let v = match index[0].parse::<usize>() {
                                Ok(val) => val-1,
                                Err(_) => return Err(LoadingError::Parse(nb)),
                            };
                            let vt = match index[1].parse::<usize>().ok() {
                                    Some(val) => Some(val-1),
                                    None => None,
                            };
                            let vn = match index[2].parse::<usize>().ok() {
                                    Some(val) => Some(val-1),
                                    None => None,
                            };
                            vec.push((v,vt,vn));
                        }
                        data.faces.push(vec);
                    },
                    Some("o") => {
                        // Not supported
                    },
                    _ => return Err(LoadingError::InvalidLine(nb)),
                }
            }
            nb += 1;
            buf.clear();
        }
        return Ok(data);
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::io::BufReader;
    use obj::*;

    #[test]
    fn load() {
        let mut expected = ObjData::new();
        expected.vertices = vec![(1.,-1.,-1.,1.),
        (1.,-1.,1.,1.),
        (-1.,-1.,1.,1.),
        (-1.,-1.,-1.,1.),
        (1.,1.,-1.,1.),
        (1.,1.,1.,1.),
        (-1.,1.,1.,1.),
        (-1.,1.,-1.,1.)];
        expected.normals = vec![(0.,-1.,0.),
        (0.,1.,0.),
        (1.,0.,0.),
        (0.,0.,1.),
        (-1.,0.,0.),
        (0.,0.,-1.)];
        expected.faces = vec![ vec![(1,None,Some(0)), (3,None,Some(0)), (0,None,Some(0))],
        vec![(7,None,Some(1)), (5,None,Some(1)), (4,None,Some(1))],
        vec![(4,None,Some(2)), (1,None,Some(2)), (0,None,Some(2))],
        vec![(5,None,Some(3)), (2,None,Some(3)), (1,None,Some(3))],
        vec![(2,None,Some(4)), (7,None,Some(4)), (3,None,Some(4))],
        vec![(0,None,Some(5)), (7,None,Some(5)), (4,None,Some(5))],
        vec![(1,None,Some(0)), (2,None,Some(0)), (3,None,Some(0))],
        vec![(7,None,Some(1)), (6,None,Some(1)), (5,None,Some(1))],
        vec![(4,None,Some(2)), (5,None,Some(2)), (1,None,Some(2))],
        vec![(5,None,Some(3)), (6,None,Some(3)), (2,None,Some(3))],
        vec![(2,None,Some(4)), (6,None,Some(4)), (7,None,Some(4))],
        vec![(0,None,Some(5)), (3,None,Some(5)), (7,None,Some(5))],
        ];
        let f = File::open("cube.obj").unwrap();
        let mut input = BufReader::new(f);
        let data = ObjData::load(&mut input).ok().unwrap();
        assert_eq!(expected.vertices,data.vertices);
        assert_eq!(expected.normals,data.normals);
        assert_eq!(expected.texcoords,data.texcoords);
        assert_eq!(expected.faces,data.faces);
    }
}
<|endoftext|>


<commit_before>//! This module has various option flags and configs we can pass to ISPC,
//! located here for convience and clutter reduction.

/// Different math libraries that ISPC can use for computations.
pub enum MathLib {
    /// Use ispc's built-in math functions (the default).
    ISPCDefault,
    /// Use high-performance but lower-accuracy math functions.
    Fast,
    /// Use the Intel(r) SVML math libraries.
    SVML,
    /// Use the system's math library (**may be quite slow**).
    System,
}

impl ToString for MathLib {
    fn to_string(&self) -> String {
        match *self {
            MathLib::ISPCDefault => String::from("--math-lib=default"),
            MathLib::Fast => String::from("--math-lib=fast"),
            MathLib::SVML => String::from("--math-lib=svml"),
            MathLib::System => String::from("--math-lib=system"),
        }
    }
}

/// Select 32 or 64 bit addressing to be used by ISPC. Note: 32-bit
/// addressing calculations are done by default, even on 64 bit target
/// architectures.
pub enum Addressing {
    /// Select 32 bit addressing calculations.
    A32,
    /// Select 64 bit addressing calculations.
    A64,
}

impl ToString for Addressing {
    fn to_string(&self) -> String {
        match *self {
            Addressing::A32 => String::from("--addressing=32"),
            Addressing::A64 => String::from("--addressing=64"),
        }
    }
}

/// ISPC target CPU type options, if none is set ISPC will
/// target the machine being compile on.
#[derive(Eq, PartialEq)]
pub enum CPU {
    Generic,
    /// Synonym for Atom target
    Bonnell,
    Core2,
    Penryn,
    /// Synonym for corei7 target
    Nehalem,
    /// Synonym for corei7-avx
    SandyBridge,
    /// Synonym for core-avx-i target
    IvyBridge,
    /// Synonym for core-avx2 target
    Haswell,
    Broadwell,
    Knl,
    Skx,
    /// Synonym for slm target
    Silvermont,
}

impl ToString for CPU {
    fn to_string(&self) -> String {
        match *self {
            CPU::Generic => String::from("--cpu=generic"),
            CPU::Bonnell => String::from("--cpu=bonnell"),
            CPU::Core2 => String::from("--cpu=core2"),
            CPU::Penryn => String::from("--cpu=penryn"),
            CPU::Nehalem => String::from("--cpu=nehalem"),
            CPU::SandyBridge => String::from("--cpu=sandybridge"),
            CPU::IvyBridge => String::from("--cpu=ivybridge"),
            CPU::Haswell => String::from("--cpu=haswell"),
            CPU::Broadwell => String::from("--cpu=broadwell"),
            CPU::Knl => String::from("--cpu=knl"),
            CPU::Skx => String::from("--cpu=skx"),
            CPU::Silvermont => String::from("--cpu=silvermont"),
        }
    }
}

/// ISPC optimization options.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub enum OptimizationOpt {
    /// Remove assertion statements from final code.
    DisableAssertions,
    /// Disable 'fused multiply-add' instructions (on targets that support them).
    DisableFMA,
    /// Disable loop unrolling.
    DisableLoopUnroll,
    /// Faster masked vector loads on SSE (may go past end of array).
    FastMaskedVload,
    /// Perform non-IEEE-compliant optimizations of numeric expressions.
    FastMath,
    /// Always issue aligned vector load and store instructions.
    ForceAlignedMemory,
}

impl ToString for OptimizationOpt {
    fn to_string(&self) -> String {
        match *self {
            OptimizationOpt::DisableAssertions => String::from("--opt=disable-assertions"),
            OptimizationOpt::DisableFMA => String::from("--opt=disable-fma"),
            OptimizationOpt::DisableLoopUnroll => String::from("--opt=disable-loop-unroll"),
            OptimizationOpt::FastMaskedVload => String::from("--opt=fast-masked-vload"),
            OptimizationOpt::FastMath => String::from("--opt=fast-math"),
            OptimizationOpt::ForceAlignedMemory => String::from("--opt=force-aligned-memory"),
        }
    }
}

/// Target instruction sets and vector widths available to specialize for. The
/// default if none is set will be the host CPU's ISA and vector width.
pub enum TargetISA {
    Host,
    SSE2i32x4,
    SSE2i32x8,
    SSE4i32x4,
    SSE4i32x8,
    SSE4i16x8,
    SSE4i8x16,
    AVX1i32x4,
    AVX1i32x8,
    AVX1i32x16,
    AVX1i64x4,
    AVX11i32x8,
    AVX11i32x16,
    AVX11i64x4,
    AVX2i32x8,
    AVX2i32x16,
    AVX2i64x4,
    AVX512KNLi32x16,
}

impl TargetISA {
    pub fn lib_suffix(&self) -> String {
        match *self {
            TargetISA::Host => String::from("host"),
            TargetISA::SSE2i32x4 => String::from("sse2"),
            TargetISA::SSE2i32x8 => String::from("sse2"),
            TargetISA::SSE4i32x4 => String::from("sse4"),
            TargetISA::SSE4i32x8 => String::from("sse4"),
            TargetISA::SSE4i16x8 => String::from("sse4"),
            TargetISA::SSE4i8x16 => String::from("sse4"),
            TargetISA::AVX1i32x4 => String::from("avx1"),
            TargetISA::AVX1i32x8 => String::from("avx1"),
            TargetISA::AVX1i32x16 => String::from("avx1"),
            TargetISA::AVX1i64x4 => String::from("avx1"),
            TargetISA::AVX11i32x8 => String::from("avx11"),
            TargetISA::AVX11i32x16 => String::from("avx11"),
            TargetISA::AVX11i64x4 => String::from("avx11"),
            TargetISA::AVX2i32x8 => String::from("avx2"),
            TargetISA::AVX2i32x16 => String::from("avx2"),
            TargetISA::AVX2i64x4 => String::from("avx2"),
            TargetISA::AVX512KNLi32x16 => String::from("avx512knl"),
        }
    }
}

impl ToString for TargetISA {
    fn to_string(&self) -> String {
        match *self {
            TargetISA::Host => String::from("host"),
            TargetISA::SSE2i32x4 => String::from("sse2-i32x4"),
            TargetISA::SSE2i32x8 => String::from("sse2-i32x8"),
            TargetISA::SSE4i32x4 => String::from("sse4-i32x4"),
            TargetISA::SSE4i32x8 => String::from("sse4-i32x8"),
            TargetISA::SSE4i16x8 => String::from("sse4-i16x8"),
            TargetISA::SSE4i8x16 => String::from("sse4-i8x16"),
            TargetISA::AVX1i32x4 => String::from("avx1-i32x4"),
            TargetISA::AVX1i32x8 => String::from("avx1-i32x8"),
            TargetISA::AVX1i32x16 => String::from("avx1-i32x16"),
            TargetISA::AVX1i64x4 => String::from("avx1-i64x4"),
            TargetISA::AVX11i32x8 => String::from("avx1.1-i32x8"),
            TargetISA::AVX11i32x16 => String::from("avx1.1-i32x16"),
            TargetISA::AVX11i64x4 => String::from("avx1.1-i64x4"),
            TargetISA::AVX2i32x8 => String::from("avx2-i32x8"),
            TargetISA::AVX2i32x16 => String::from("avx2-i32x16"),
            TargetISA::AVX2i64x4 => String::from("avx2-i64x4"),
            TargetISA::AVX512KNLi32x16 => String::from("avx512knl-i32x16"),
        }
    }
}

<commit_msg>fix lib suffixes for AVX1<commit_after>//! This module has various option flags and configs we can pass to ISPC,
//! located here for convience and clutter reduction.

/// Different math libraries that ISPC can use for computations.
pub enum MathLib {
    /// Use ispc's built-in math functions (the default).
    ISPCDefault,
    /// Use high-performance but lower-accuracy math functions.
    Fast,
    /// Use the Intel(r) SVML math libraries.
    SVML,
    /// Use the system's math library (**may be quite slow**).
    System,
}

impl ToString for MathLib {
    fn to_string(&self) -> String {
        match *self {
            MathLib::ISPCDefault => String::from("--math-lib=default"),
            MathLib::Fast => String::from("--math-lib=fast"),
            MathLib::SVML => String::from("--math-lib=svml"),
            MathLib::System => String::from("--math-lib=system"),
        }
    }
}

/// Select 32 or 64 bit addressing to be used by ISPC. Note: 32-bit
/// addressing calculations are done by default, even on 64 bit target
/// architectures.
pub enum Addressing {
    /// Select 32 bit addressing calculations.
    A32,
    /// Select 64 bit addressing calculations.
    A64,
}

impl ToString for Addressing {
    fn to_string(&self) -> String {
        match *self {
            Addressing::A32 => String::from("--addressing=32"),
            Addressing::A64 => String::from("--addressing=64"),
        }
    }
}

/// ISPC target CPU type options, if none is set ISPC will
/// target the machine being compile on.
#[derive(Eq, PartialEq)]
pub enum CPU {
    Generic,
    /// Synonym for Atom target
    Bonnell,
    Core2,
    Penryn,
    /// Synonym for corei7 target
    Nehalem,
    /// Synonym for corei7-avx
    SandyBridge,
    /// Synonym for core-avx-i target
    IvyBridge,
    /// Synonym for core-avx2 target
    Haswell,
    Broadwell,
    Knl,
    Skx,
    /// Synonym for slm target
    Silvermont,
}

impl ToString for CPU {
    fn to_string(&self) -> String {
        match *self {
            CPU::Generic => String::from("--cpu=generic"),
            CPU::Bonnell => String::from("--cpu=bonnell"),
            CPU::Core2 => String::from("--cpu=core2"),
            CPU::Penryn => String::from("--cpu=penryn"),
            CPU::Nehalem => String::from("--cpu=nehalem"),
            CPU::SandyBridge => String::from("--cpu=sandybridge"),
            CPU::IvyBridge => String::from("--cpu=ivybridge"),
            CPU::Haswell => String::from("--cpu=haswell"),
            CPU::Broadwell => String::from("--cpu=broadwell"),
            CPU::Knl => String::from("--cpu=knl"),
            CPU::Skx => String::from("--cpu=skx"),
            CPU::Silvermont => String::from("--cpu=silvermont"),
        }
    }
}

/// ISPC optimization options.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub enum OptimizationOpt {
    /// Remove assertion statements from final code.
    DisableAssertions,
    /// Disable 'fused multiply-add' instructions (on targets that support them).
    DisableFMA,
    /// Disable loop unrolling.
    DisableLoopUnroll,
    /// Faster masked vector loads on SSE (may go past end of array).
    FastMaskedVload,
    /// Perform non-IEEE-compliant optimizations of numeric expressions.
    FastMath,
    /// Always issue aligned vector load and store instructions.
    ForceAlignedMemory,
}

impl ToString for OptimizationOpt {
    fn to_string(&self) -> String {
        match *self {
            OptimizationOpt::DisableAssertions => String::from("--opt=disable-assertions"),
            OptimizationOpt::DisableFMA => String::from("--opt=disable-fma"),
            OptimizationOpt::DisableLoopUnroll => String::from("--opt=disable-loop-unroll"),
            OptimizationOpt::FastMaskedVload => String::from("--opt=fast-masked-vload"),
            OptimizationOpt::FastMath => String::from("--opt=fast-math"),
            OptimizationOpt::ForceAlignedMemory => String::from("--opt=force-aligned-memory"),
        }
    }
}

/// Target instruction sets and vector widths available to specialize for. The
/// default if none is set will be the host CPU's ISA and vector width.
pub enum TargetISA {
    Host,
    SSE2i32x4,
    SSE2i32x8,
    SSE4i32x4,
    SSE4i32x8,
    SSE4i16x8,
    SSE4i8x16,
    AVX1i32x4,
    AVX1i32x8,
    AVX1i32x16,
    AVX1i64x4,
    AVX11i32x8,
    AVX11i32x16,
    AVX11i64x4,
    AVX2i32x8,
    AVX2i32x16,
    AVX2i64x4,
    AVX512KNLi32x16,
}

impl TargetISA {
    pub fn lib_suffix(&self) -> String {
        match *self {
            TargetISA::Host => String::from("host"),
            TargetISA::SSE2i32x4 => String::from("sse2"),
            TargetISA::SSE2i32x8 => String::from("sse2"),
            TargetISA::SSE4i32x4 => String::from("sse4"),
            TargetISA::SSE4i32x8 => String::from("sse4"),
            TargetISA::SSE4i16x8 => String::from("sse4"),
            TargetISA::SSE4i8x16 => String::from("sse4"),
            TargetISA::AVX1i32x4 => String::from("avx"),
            TargetISA::AVX1i32x8 => String::from("avx"),
            TargetISA::AVX1i32x16 => String::from("avx"),
            TargetISA::AVX1i64x4 => String::from("avx"),
            TargetISA::AVX11i32x8 => String::from("avx11"),
            TargetISA::AVX11i32x16 => String::from("avx11"),
            TargetISA::AVX11i64x4 => String::from("avx11"),
            TargetISA::AVX2i32x8 => String::from("avx2"),
            TargetISA::AVX2i32x16 => String::from("avx2"),
            TargetISA::AVX2i64x4 => String::from("avx2"),
            TargetISA::AVX512KNLi32x16 => String::from("avx512knl"),
        }
    }
}

impl ToString for TargetISA {
    fn to_string(&self) -> String {
        match *self {
            TargetISA::Host => String::from("host"),
            TargetISA::SSE2i32x4 => String::from("sse2-i32x4"),
            TargetISA::SSE2i32x8 => String::from("sse2-i32x8"),
            TargetISA::SSE4i32x4 => String::from("sse4-i32x4"),
            TargetISA::SSE4i32x8 => String::from("sse4-i32x8"),
            TargetISA::SSE4i16x8 => String::from("sse4-i16x8"),
            TargetISA::SSE4i8x16 => String::from("sse4-i8x16"),
            TargetISA::AVX1i32x4 => String::from("avx1-i32x4"),
            TargetISA::AVX1i32x8 => String::from("avx1-i32x8"),
            TargetISA::AVX1i32x16 => String::from("avx1-i32x16"),
            TargetISA::AVX1i64x4 => String::from("avx1-i64x4"),
            TargetISA::AVX11i32x8 => String::from("avx1.1-i32x8"),
            TargetISA::AVX11i32x16 => String::from("avx1.1-i32x16"),
            TargetISA::AVX11i64x4 => String::from("avx1.1-i64x4"),
            TargetISA::AVX2i32x8 => String::from("avx2-i32x8"),
            TargetISA::AVX2i32x16 => String::from("avx2-i32x16"),
            TargetISA::AVX2i64x4 => String::from("avx2-i64x4"),
            TargetISA::AVX512KNLi32x16 => String::from("avx512knl-i32x16"),
        }
    }
}

<|endoftext|>


<commit_before>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_mut(self) -> PmemMutVirtualPtr<T> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &PersistentMap) -> PmemConstPtr<T> {
        let new_virt = PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemConstPtr { virt: new_virt, pool: pool.as_ptr() }
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_const(self) -> PmemConstVirtualPtr<T> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        let new_virt = PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemMutPtr { virt: new_virt, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T: ?Sized> PmemConstPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_mut(self) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self.virt.as_mut(), pool: self.pool as *mut T }
    }
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        if self.is_null() {
            ::std::ptr::null()
        } else {
            self.pool.offset(self.virt.offset as isize) as *const T
        }
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T: ?Sized> PmemMutPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_const(self) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self.virt.as_const(), pool: self.pool as *const T }
    }
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        if self.is_null() {
            ::std::ptr::null_mut()
        } else {
            self.pool.offset(self.virt.offset as isize) as *mut T
        }
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

pub fn null<T>() -> PmemConstVirtualPtr<T> {
    PmemConstVirtualPtr::null()
}

pub fn null_mut<T>() -> PmemMutVirtualPtr<T> {
    PmemMutVirtualPtr::null()
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<commit_msg>feat: take refs on transitions between ptr types<commit_after>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_mut(&self) -> PmemMutVirtualPtr<T> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &PersistentMap) -> PmemConstPtr<T> {
        let new_virt = PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemConstPtr { virt: new_virt, pool: pool.as_ptr() }
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_const(&self) -> PmemConstVirtualPtr<T> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        let new_virt = PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemMutPtr { virt: new_virt, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T: ?Sized> PmemConstPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_mut(&self) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self.virt.as_mut(), pool: self.pool as *mut T }
    }
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        if self.is_null() {
            ::std::ptr::null()
        } else {
            self.pool.offset(self.virt.offset as isize) as *const T
        }
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T: ?Sized> PmemMutPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_const(&self) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self.virt.as_const(), pool: self.pool as *const T }
    }
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        if self.is_null() {
            ::std::ptr::null_mut()
        } else {
            self.pool.offset(self.virt.offset as isize) as *mut T
        }
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

pub fn null<T>() -> PmemConstVirtualPtr<T> {
    PmemConstVirtualPtr::null()
}

pub fn null_mut<T>() -> PmemMutVirtualPtr<T> {
    PmemMutVirtualPtr::null()
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<|endoftext|>