<commit_before>use std::collections::HashMap;
use std::ffi::OsString;
use std::fs::File;
use std::fs;
use std::env;
use std::os::unix::fs::PermissionsExt;
use std::io::{Write,BufReader};
use std::io::BufRead;
use std::process::Command;
use std::path::Path;

const SNAPPY_VERSION: &'static str  = "1.1.2";
const LEVELDB_VERSION: &'static str = "1.18";

fn build_snappy(is_bsd: bool) {
    // Step 1: Build snappy
    // ----------------------------------------------------------------------
    let snappy_path = Path::new("deps")
                           .join(format!("snappy-{}", SNAPPY_VERSION));
    let make = if is_bsd { "gmake" } else { "make" };

    // Clean the build directory first.
    println!("[snappy] Cleaning");
    Command::new(make).args(&["-C", snappy_path.to_str().unwrap()])
                        .arg("distclean")
                        .status().ok().expect("make distclean failed");

    // Configure the build
    println!("[snappy] Configuring");
    Command::new("./configure").current_dir(&snappy_path)
                               .arg("--disable-shared")
                               .status().ok().expect("configure failed");

    // Call "make" to build the C library
    println!("[snappy] Building");
    Command::new(make).args(&["-C", snappy_path.to_str().unwrap()])
                        .status().ok().expect("make failed");

    // Step 2: Copy to output directories
    // ----------------------------------------------------------------------
    let env_var = &env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(env_var);

    println!("[build] Copying output files");
    let res = fs::copy(&snappy_path.join(".libs").join("libsnappy.a"), &out_dir.join("libsnappy.a"));
    res.ok().expect("copy of output files failed");
}

fn build_leveldb(with_snappy: bool, is_bsd: bool) {
    // Step 1: Build LevelDB
    // ----------------------------------------------------------------------
    let leveldb_path = Path::new("deps")
                            .join(format!("leveldb-{}", LEVELDB_VERSION));
    let make = if is_bsd { "gmake" } else { "make" };

    // Clean the build directory first.
    println!("[leveldb] Cleaning");
    Command::new(make).args(&["-C", leveldb_path.to_str().unwrap()])
                        .arg("clean")
                        .status().ok().expect("clean failed");

    // Set up the process environment.  We essentially clone the existing
    // environment, and, if we're including Snappy, also include the appropriate
    // CXXFLAGS and LDFLAGS variables.
    let mut env_map: HashMap<OsString, OsString> = env::vars().map(|(k, v)| {
        (
            k.into(),
            v.into()
        )
    }).collect();

    if with_snappy {
        let linker_path = env::var("OUT_DIR").unwrap();
        env_map.insert(
            "LDFLAGS".into(),
            format!("-L{}", linker_path).into()
        );

        let snappy_path = Path::new("deps")
                               .join(format!("snappy-{}", SNAPPY_VERSION));
        env_map.insert(
            "CXXFLAGS".into(),
            format!("-I{} -fPIC", snappy_path.to_str().unwrap()).into()
        );
    } else {
        env_map.insert(
            "CXXFLAGS".into(),
            format!("-fPIC").into()
        );
    }

    let mut cmd = Command::new(make);

    println!("[leveldb] Building command");

    // Convert to the format that `env_set_all` is expecting.
    for (k,v) in env_map.into_iter() {
        cmd.env(k,v);
    }

    let path_arg = leveldb_path.to_str().expect("leveldb path is not a string");

    // Build the library
    println!("[leveldb] Building");
    cmd.args(&["-C", path_arg])
       .status().ok().expect("leveldb build failed");

    println!("[leveldb] Build finished");
    // Step 2: Copy to output directories
    // ----------------------------------------------------------------------
    let env_var = &env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(env_var);

    println!("[build] Copying output files");
    let res = fs::copy(&leveldb_path.join("libleveldb.a"), &out_dir.join("libleveldb.a"));
    res.ok().expect("copy of output files failed");
}

fn main() {
    println!("[build] Started");

    let have_snappy = env::var("CARGO_FEATURE_SNAPPY").is_ok();
    let is_bsd = env::var("TARGET").unwrap().ends_with("bsd");

    // If we have the appropriate feature, then we build snappy.
    if have_snappy {
        build_snappy(is_bsd);
    }

    // Copy the build_detect_platform file into the appropriate place.
    let template_path = Path::new("deps")
                             .join("build_detect_platform");
    let detect_path = Path::new("deps")
                           .join(format!("leveldb-{}", LEVELDB_VERSION))
                           .join("build_detect_platform");
    if have_snappy {
        println!("[build] Copying the `build_detect_platform` template");
        fs::copy(&template_path, &detect_path).unwrap();
    } else {
        println!("[build] Patching the `build_detect_platform` template");

        // If we aren't using snappy, remove the lines from
        // build_detect_platform that enable Snappy.  This prevents us from
        // picking up a system-local copy of Snappy.
        let new_lines: Vec<String> = {
            let file = File::open(&template_path).unwrap();
            let reader = BufReader::new(file);

            reader.lines().map(|line| {
                let line = line.unwrap();
                if line.contains("-DSNAPPY") || line.contains("-lsnappy") {
                    let mut tmp = String::new();
                    tmp.push_str("true   #");
                    tmp.push_str(line.as_ref());
                    tmp.push_str("\n");
                    tmp
                } else {
                    line
                }
            }).collect()
        };

        let mut f = File::create(&detect_path).unwrap();
        for line in new_lines.iter() {
            f.write_all(line.as_ref()).ok().expect("writing a line failed");
            f.write_all("\n".as_bytes()).ok().expect("writing a line failed");
        }

        println!("[build] Patching complete");
    }

    // Set executable bits on the file

    let mut perms = fs::metadata(&detect_path).ok().expect("metadata missing").permissions();
    let current_mode = perms.mode();
    perms.set_mode(0o100 | current_mode);
    fs::set_permissions(&detect_path, perms).ok().expect("permissions could not be set");

    // Build LevelDB
    build_leveldb(have_snappy, is_bsd);

    // Print the appropriate linker flags
    let out_dir = env::var("OUT_DIR").ok().expect("OUT_DIR missing");
    let linker_flags = if have_snappy {
        "-l static=snappy -l static=leveldb"
    } else {
        "-l static=leveldb"
    };
    println!("cargo:rustc-flags=-L native={} {}", out_dir, linker_flags);

    let target = env::var("TARGET").unwrap();
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=c++");
    } else if target.contains("gnu") {
        println!("cargo:rustc-link-lib=stdc++");
    } else if target.contains("bsd") {
        println!("cargo:rustc-link-lib=c++");
    }

    println!("[build] Finished");
}
<commit_msg>FreeBSD uses libc++ while other BSDs uses libstdc++<commit_after>use std::collections::HashMap;
use std::ffi::OsString;
use std::fs::File;
use std::fs;
use std::env;
use std::os::unix::fs::PermissionsExt;
use std::io::{Write,BufReader};
use std::io::BufRead;
use std::process::Command;
use std::path::Path;

const SNAPPY_VERSION: &'static str  = "1.1.2";
const LEVELDB_VERSION: &'static str = "1.18";

fn build_snappy(is_bsd: bool) {
    // Step 1: Build snappy
    // ----------------------------------------------------------------------
    let snappy_path = Path::new("deps")
                           .join(format!("snappy-{}", SNAPPY_VERSION));
    let make = if is_bsd { "gmake" } else { "make" };

    // Clean the build directory first.
    println!("[snappy] Cleaning");
    Command::new(make).args(&["-C", snappy_path.to_str().unwrap()])
                        .arg("distclean")
                        .status().ok().expect("make distclean failed");

    // Configure the build
    println!("[snappy] Configuring");
    Command::new("./configure").current_dir(&snappy_path)
                               .arg("--disable-shared")
                               .status().ok().expect("configure failed");

    // Call "make" to build the C library
    println!("[snappy] Building");
    Command::new(make).args(&["-C", snappy_path.to_str().unwrap()])
                        .status().ok().expect("make failed");

    // Step 2: Copy to output directories
    // ----------------------------------------------------------------------
    let env_var = &env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(env_var);

    println!("[build] Copying output files");
    let res = fs::copy(&snappy_path.join(".libs").join("libsnappy.a"), &out_dir.join("libsnappy.a"));
    res.ok().expect("copy of output files failed");
}

fn build_leveldb(with_snappy: bool, is_bsd: bool) {
    // Step 1: Build LevelDB
    // ----------------------------------------------------------------------
    let leveldb_path = Path::new("deps")
                            .join(format!("leveldb-{}", LEVELDB_VERSION));
    let make = if is_bsd { "gmake" } else { "make" };

    // Clean the build directory first.
    println!("[leveldb] Cleaning");
    Command::new(make).args(&["-C", leveldb_path.to_str().unwrap()])
                        .arg("clean")
                        .status().ok().expect("clean failed");

    // Set up the process environment.  We essentially clone the existing
    // environment, and, if we're including Snappy, also include the appropriate
    // CXXFLAGS and LDFLAGS variables.
    let mut env_map: HashMap<OsString, OsString> = env::vars().map(|(k, v)| {
        (
            k.into(),
            v.into()
        )
    }).collect();

    if with_snappy {
        let linker_path = env::var("OUT_DIR").unwrap();
        env_map.insert(
            "LDFLAGS".into(),
            format!("-L{}", linker_path).into()
        );

        let snappy_path = Path::new("deps")
                               .join(format!("snappy-{}", SNAPPY_VERSION));
        env_map.insert(
            "CXXFLAGS".into(),
            format!("-I{} -fPIC", snappy_path.to_str().unwrap()).into()
        );
    } else {
        env_map.insert(
            "CXXFLAGS".into(),
            format!("-fPIC").into()
        );
    }

    let mut cmd = Command::new(make);

    println!("[leveldb] Building command");

    // Convert to the format that `env_set_all` is expecting.
    for (k,v) in env_map.into_iter() {
        cmd.env(k,v);
    }

    let path_arg = leveldb_path.to_str().expect("leveldb path is not a string");

    // Build the library
    println!("[leveldb] Building");
    cmd.args(&["-C", path_arg])
       .status().ok().expect("leveldb build failed");

    println!("[leveldb] Build finished");
    // Step 2: Copy to output directories
    // ----------------------------------------------------------------------
    let env_var = &env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(env_var);

    println!("[build] Copying output files");
    let res = fs::copy(&leveldb_path.join("libleveldb.a"), &out_dir.join("libleveldb.a"));
    res.ok().expect("copy of output files failed");
}

fn main() {
    println!("[build] Started");

    let have_snappy = env::var("CARGO_FEATURE_SNAPPY").is_ok();
    let target = env::var("TARGET").unwrap();
    let is_bsd = target.ends_with("bsd");

    // If we have the appropriate feature, then we build snappy.
    if have_snappy {
        build_snappy(is_bsd);
    }

    // Copy the build_detect_platform file into the appropriate place.
    let template_path = Path::new("deps")
                             .join("build_detect_platform");
    let detect_path = Path::new("deps")
                           .join(format!("leveldb-{}", LEVELDB_VERSION))
                           .join("build_detect_platform");
    if have_snappy {
        println!("[build] Copying the `build_detect_platform` template");
        fs::copy(&template_path, &detect_path).unwrap();
    } else {
        println!("[build] Patching the `build_detect_platform` template");

        // If we aren't using snappy, remove the lines from
        // build_detect_platform that enable Snappy.  This prevents us from
        // picking up a system-local copy of Snappy.
        let new_lines: Vec<String> = {
            let file = File::open(&template_path).unwrap();
            let reader = BufReader::new(file);

            reader.lines().map(|line| {
                let line = line.unwrap();
                if line.contains("-DSNAPPY") || line.contains("-lsnappy") {
                    let mut tmp = String::new();
                    tmp.push_str("true   #");
                    tmp.push_str(line.as_ref());
                    tmp.push_str("\n");
                    tmp
                } else {
                    line
                }
            }).collect()
        };

        let mut f = File::create(&detect_path).unwrap();
        for line in new_lines.iter() {
            f.write_all(line.as_ref()).ok().expect("writing a line failed");
            f.write_all("\n".as_bytes()).ok().expect("writing a line failed");
        }

        println!("[build] Patching complete");
    }

    // Set executable bits on the file

    let mut perms = fs::metadata(&detect_path).ok().expect("metadata missing").permissions();
    let current_mode = perms.mode();
    perms.set_mode(0o100 | current_mode);
    fs::set_permissions(&detect_path, perms).ok().expect("permissions could not be set");

    // Build LevelDB
    build_leveldb(have_snappy, is_bsd);

    // Print the appropriate linker flags
    let out_dir = env::var("OUT_DIR").ok().expect("OUT_DIR missing");
    let linker_flags = if have_snappy {
        "-l static=snappy -l static=leveldb"
    } else {
        "-l static=leveldb"
    };
    println!("cargo:rustc-flags=-L native={} {}", out_dir, linker_flags);

    if target.contains("apple") || target.contains("freebsd") {
        println!("cargo:rustc-link-lib=c++");
    } else if target.contains("gnu") || target.contains("netbsd") || target.contains("openbsd") {
        println!("cargo:rustc-link-lib=stdc++");
    }

    println!("[build] Finished");
}
<|endoftext|>


<commit_before>use ByteBuf;

use std::cell::UnsafeCell;
use std::sync::Arc;
use std::{cmp, fmt, ops};

/// A reference counted slice of bytes.
///
/// A `Bytes` is an immutable sequence of bytes. Given that it is guaranteed to
/// be immutable, `Bytes` is `Sync`, `Clone` is shallow (ref count increment),
/// and all operations only update views into the underlying data without
/// requiring any copies.
#[derive(Eq)]
pub struct Bytes {
    inner: BytesMut,
}

/// A unique reference to a slice of bytes.
///
/// A `BytesMut` is a unique handle to a slice of bytes allowing mutation of
/// the underlying bytes.
pub struct BytesMut {
    mem: Mem,
    pos: usize,
    len: usize,
    cap: usize,
}

struct Mem {
    inner: Arc<UnsafeCell<Box<[u8]>>>,
}

/*
 *
 * ===== Bytes =====
 *
 */

impl Bytes {
    /// Creates a new `Bytes` and copy the given slice into it.
    pub fn from_slice<T: AsRef<[u8]>>(bytes: T) -> Bytes {
        BytesMut::from_slice(bytes).freeze()
    }

    /// Returns the number of bytes contained in this `Bytes`.
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    /// Returns true if the value contains no bytes
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }

    /// Returns the inner contents of this `Bytes` as a slice.
    pub fn as_slice(&self) -> &[u8] {
        self.as_ref()
    }

    /// Extracts a new `Bytes` referencing the bytes from range [start, end).
    pub fn slice(&self, start: usize, end: usize) -> Bytes {
        let mut ret = self.clone();

        ret.inner
            .set_end(end)
            .set_start(start);

        ret
    }

    /// Extracts a new `Bytes` referencing the bytes from range [start, len).
    pub fn slice_from(&self, start: usize) -> Bytes {
        self.slice(start, self.len())
    }

    /// Extracts a new `Bytes` referencing the bytes from range [0, end).
    pub fn slice_to(&self, end: usize) -> Bytes {
        self.slice(0, end)
    }

    /// Splits the bytes into two at the given index.
    ///
    /// Afterwards `self` contains elements `[0, at)`, and the returned `Bytes`
    /// contains elements `[at, len)`.
    ///
    /// This is an O(1) operation that just increases the reference count and
    /// sets a few indexes.
    ///
    /// # Panics
    ///
    /// Panics if `at > len`
    pub fn split_off(&mut self, at: usize) -> Bytes {
        self.inner.split_off(at).freeze()
    }

    /// Splits the buffer into two at the given index.
    ///
    /// Afterwards `self` contains elements `[at, len)`, and the returned
    /// `Bytes` contains elements `[0, at)`.
    ///
    /// This is an O(1) operation that just increases the reference count and
    /// sets a few indexes.
    ///
    /// # Panics
    ///
    /// Panics if `at > len`
    pub fn drain_to(&mut self, at: usize) -> Bytes {
        self.inner.drain_to(at).freeze()
    }

    /// Attempt to convert into a `BytesMut` handle.
    ///
    /// This will only succeed if there are no other outstanding references to
    /// the underlying chunk of memory.
    pub fn try_mut(mut self) -> Result<BytesMut, Bytes> {
        if self.inner.mem.is_mut_safe() {
            Ok(self.inner)
        } else {
            Err(self)
        }
    }

    /// Consumes handle, returning a new mutable handle
    ///
    /// The function attempts to avoid copying, however if it is unable to
    /// obtain a unique reference to the underlying data, a new buffer is
    /// allocated and the data is copied to it.
    pub fn into_mut(self) -> BytesMut {
        self.try_mut().unwrap_or_else(BytesMut::from_slice)
    }
}

impl Clone for Bytes {
    fn clone(&self) -> Bytes {
        Bytes { inner: self.inner.clone() }
    }
}

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

impl ops::Deref for Bytes {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl From<Vec<u8>> for Bytes {
    fn from(src: Vec<u8>) -> Bytes {
        BytesMut::from(src).freeze()
    }
}

impl<'a> From<&'a [u8]> for Bytes {
    fn from(src: &'a [u8]) -> Bytes {
        BytesMut::from(src).freeze()
    }
}

impl PartialEq for Bytes {
    fn eq(&self, other: &Bytes) -> bool {
        self.inner == other.inner
    }
}

impl fmt::Debug for Bytes {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, fmt)
    }
}

unsafe impl Sync for Bytes {}

/*
 *
 * ===== BytesMut =====
 *
 */

impl BytesMut {
    /// Create a new `BytesMut` with the specified capacity.
    pub fn with_capacity(cap: usize) -> BytesMut {
        BytesMut {
            mem: Mem::with_capacity(cap),
            pos: 0,
            len: 0,
            cap: cap,
        }
    }

    /// Creates a new `BytesMut` and copy the given slice into it.
    pub fn from_slice<T: AsRef<[u8]>>(bytes: T) -> BytesMut {
        let buf = ByteBuf::from_slice(bytes);
        buf.into_inner()
    }

    /// Returns the number of bytes contained in this `BytesMut`.
    pub fn len(&self) -> usize {
        self.len
    }

    /// Returns true if the value contains no bytes
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the total byte capacity of this `BytesMut`
    pub fn capacity(&self) -> usize {
        self.cap
    }

    /// Return an immutable handle to the bytes
    pub fn freeze(self) -> Bytes {
        Bytes { inner: self }
    }

    /// Splits the bytes into two at the given index.
    ///
    /// Afterwards `self` contains elements `[0, at)`, and the returned
    /// `BytesMut` contains elements `[at, capacity)`.
    ///
    /// This is an O(1) operation that just increases the reference count and
    /// sets a few indexes.
    ///
    /// # Panics
    ///
    /// Panics if `at > capacity`
    pub fn split_off(&mut self, at: usize) -> BytesMut {
        let mut other = self.clone();

        other.set_start(at);
        self.set_end(at);

        return other
    }

    /// Splits the buffer into two at the given index.
    ///
    /// Afterwards `self` contains elements `[at, len)`, and the returned `BytesMut`
    /// contains elements `[0, at)`.
    ///
    /// This is an O(1) operation that just increases the reference count and
    /// sets a few indexes.
    ///
    /// # Panics
    ///
    /// Panics if `at > len`
    pub fn drain_to(&mut self, at: usize) -> BytesMut {
        let mut other = self.clone();

        other.set_end(at);
        self.set_start(at);

        return other
    }

    /// Returns the inner contents of this `BytesMut` as a slice.
    pub fn as_slice(&self) -> &[u8] {
        self.as_ref()
    }

    /// Returns the inner contents of this `BytesMut` as a mutable slice
    ///
    /// This a slice of bytes that have been initialized
    pub fn as_mut(&mut self) -> &mut [u8] {
        let end = self.pos + self.len;
        &mut self.mem.as_mut()[self.pos..end]
    }

    /// Sets the length of the buffer
    ///
    /// This will explicitly set the size of the buffer without actually
    /// modifying the data, so it is up to the caller to ensure that the data
    /// has been initialized.
    ///
    /// # Panics
    ///
    /// This method will panic if `len` is out of bounds for the underlying
    /// slice or if it comes after the `end` of the configured window.
    pub unsafe fn set_len(&mut self, len: usize) {
        assert!(len <= self.cap);
        self.len = len;
    }

    /// Returns the inner contents of this `BytesMut` as a mutable slice
    ///
    /// This a slice of all bytes, including uninitialized memory
    pub unsafe fn as_raw(&mut self) -> &mut [u8] {
        let end = self.pos + self.cap;
        &mut self.mem.as_mut()[self.pos..end]
    }

    /// Changes the starting index of this window to the index specified.
    ///
    /// Returns the windows back to chain multiple calls to this method.
    ///
    /// # Panics
    ///
    /// This method will panic if `start` is out of bounds for the underlying
    /// slice.
    fn set_start(&mut self, start: usize) -> &mut BytesMut {
        assert!(start <= self.cap);
        self.pos += start;

        if self.len >= start {
            self.len -= start;
        } else {
            self.len = 0;
        }

        self.cap -= start;
        self
    }

    /// Changes the end index of this window to the index specified.
    ///
    /// Returns the windows back to chain multiple calls to this method.
    ///
    /// # Panics
    ///
    /// This method will panic if `start` is out of bounds for the underlying
    /// slice.
    fn set_end(&mut self, end: usize) -> &mut BytesMut {
        assert!(end <= self.cap);
        self.cap = end;
        self.len = cmp::min(self.len, end);
        self
    }

    /// Increments the ref count. This should only be done if it is known that
    /// it can be done safely. As such, this fn is not public, instead other
    /// fns will use this one while maintaining the guarantees.
    fn clone(&self) -> BytesMut {
         BytesMut {
            mem: self.mem.clone(),
            .. *self
        }
    }
}

impl AsRef<[u8]> for BytesMut {
    fn as_ref(&self) -> &[u8] {
        let end = self.pos + self.len;
        &self.mem.as_ref()[self.pos..end]
    }
}

impl ops::Deref for BytesMut {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl ops::DerefMut for BytesMut {
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl From<Vec<u8>> for BytesMut {
    fn from(src: Vec<u8>) -> BytesMut {
        let len = src.len();
        let cap = src.capacity();

        BytesMut {
            mem: Mem::from_vec(src),
            pos: 0,
            len: len,
            cap: cap,
        }
    }
}

impl<'a> From<&'a [u8]> for BytesMut {
    fn from(src: &'a [u8]) -> BytesMut {
        BytesMut::from_slice(src)
    }
}

impl PartialEq for BytesMut {
    fn eq(&self, other: &BytesMut) -> bool {
        **self == **other
    }
}

impl Eq for BytesMut {
}

impl fmt::Debug for BytesMut {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.as_ref(), fmt)
    }
}

unsafe impl Send for BytesMut {}

/*
 *
 * ===== Mem =====
 *
 */

impl Mem {
    fn with_capacity(cap: usize) -> Mem {
        let mut vec = Vec::with_capacity(cap);
        unsafe { vec.set_len(cap); }

        Mem { inner: Arc::new(UnsafeCell::new(vec.into_boxed_slice())) }
    }

    fn from_vec(mut vec: Vec<u8>) -> Mem {
        let cap = vec.capacity();
        unsafe { vec.set_len(cap); }

        Mem { inner: Arc::new(UnsafeCell::new(vec.into_boxed_slice())) }
    }

    fn as_ref(&self) -> &[u8] {
        unsafe { &*self.inner.get() }
    }

    fn as_mut(&mut self) -> &mut [u8] {
        unsafe { &mut *self.inner.get() }
    }

    fn is_mut_safe(&mut self) -> bool {
        Arc::get_mut(&mut self.inner).is_some()
    }

    fn clone(&self) -> Mem {
        Mem { inner: self.inner.clone() }
    }
}

/*
 *
 * ===== PartialEq =====
 *
 */

impl PartialEq<[u8]> for BytesMut {
    fn eq(&self, other: &[u8]) -> bool {
        &**self == other
    }
}

impl PartialEq<BytesMut> for [u8] {
    fn eq(&self, other: &BytesMut) -> bool {
        *other == *self
    }
}

impl PartialEq<Vec<u8>> for BytesMut {
    fn eq(&self, other: &Vec<u8>) -> bool {
        *self == &other[..]
    }
}

impl PartialEq<BytesMut> for Vec<u8> {
    fn eq(&self, other: &BytesMut) -> bool {
        *other == *self
    }
}

impl<'a, T: ?Sized> PartialEq<&'a T> for BytesMut
    where BytesMut: PartialEq<T>
{
    fn eq(&self, other: &&'a T) -> bool {
        *self == **other
    }
}

impl<'a> PartialEq<BytesMut> for &'a [u8] {
    fn eq(&self, other: &BytesMut) -> bool {
        *other == *self
    }
}

impl PartialEq<[u8]> for Bytes {
    fn eq(&self, other: &[u8]) -> bool {
        self.inner == *other
    }
}

impl PartialEq<Bytes> for [u8] {
    fn eq(&self, other: &Bytes) -> bool {
        *other == *self
    }
}

impl PartialEq<Vec<u8>> for Bytes {
    fn eq(&self, other: &Vec<u8>) -> bool {
        *self == &other[..]
    }
}

impl PartialEq<Bytes> for Vec<u8> {
    fn eq(&self, other: &Bytes) -> bool {
        *other == *self
    }
}

impl<'a> PartialEq<Bytes> for &'a [u8] {
    fn eq(&self, other: &Bytes) -> bool {
        *other == *self
    }
}

impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes
    where Bytes: PartialEq<T>
{
    fn eq(&self, other: &&'a T) -> bool {
        *self == **other
    }
}
<commit_msg>Impl IntoBuf for Bytes and BytesMut<commit_after>use {IntoBuf, ByteBuf, SliceBuf};

use std::cell::UnsafeCell;
use std::sync::Arc;
use std::{cmp, fmt, ops};

/// A reference counted slice of bytes.
///
/// A `Bytes` is an immutable sequence of bytes. Given that it is guaranteed to
/// be immutable, `Bytes` is `Sync`, `Clone` is shallow (ref count increment),
/// and all operations only update views into the underlying data without
/// requiring any copies.
#[derive(Eq)]
pub struct Bytes {
    inner: BytesMut,
}

/// A unique reference to a slice of bytes.
///
/// A `BytesMut` is a unique handle to a slice of bytes allowing mutation of
/// the underlying bytes.
pub struct BytesMut {
    mem: Mem,
    pos: usize,
    len: usize,
    cap: usize,
}

struct Mem {
    inner: Arc<UnsafeCell<Box<[u8]>>>,
}

/*
 *
 * ===== Bytes =====
 *
 */

impl Bytes {
    /// Creates a new `Bytes` and copy the given slice into it.
    pub fn from_slice<T: AsRef<[u8]>>(bytes: T) -> Bytes {
        BytesMut::from_slice(bytes).freeze()
    }

    /// Returns the number of bytes contained in this `Bytes`.
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    /// Returns true if the value contains no bytes
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }

    /// Returns the inner contents of this `Bytes` as a slice.
    pub fn as_slice(&self) -> &[u8] {
        self.as_ref()
    }

    /// Extracts a new `Bytes` referencing the bytes from range [start, end).
    pub fn slice(&self, start: usize, end: usize) -> Bytes {
        let mut ret = self.clone();

        ret.inner
            .set_end(end)
            .set_start(start);

        ret
    }

    /// Extracts a new `Bytes` referencing the bytes from range [start, len).
    pub fn slice_from(&self, start: usize) -> Bytes {
        self.slice(start, self.len())
    }

    /// Extracts a new `Bytes` referencing the bytes from range [0, end).
    pub fn slice_to(&self, end: usize) -> Bytes {
        self.slice(0, end)
    }

    /// Splits the bytes into two at the given index.
    ///
    /// Afterwards `self` contains elements `[0, at)`, and the returned `Bytes`
    /// contains elements `[at, len)`.
    ///
    /// This is an O(1) operation that just increases the reference count and
    /// sets a few indexes.
    ///
    /// # Panics
    ///
    /// Panics if `at > len`
    pub fn split_off(&mut self, at: usize) -> Bytes {
        self.inner.split_off(at).freeze()
    }

    /// Splits the buffer into two at the given index.
    ///
    /// Afterwards `self` contains elements `[at, len)`, and the returned
    /// `Bytes` contains elements `[0, at)`.
    ///
    /// This is an O(1) operation that just increases the reference count and
    /// sets a few indexes.
    ///
    /// # Panics
    ///
    /// Panics if `at > len`
    pub fn drain_to(&mut self, at: usize) -> Bytes {
        self.inner.drain_to(at).freeze()
    }

    /// Attempt to convert into a `BytesMut` handle.
    ///
    /// This will only succeed if there are no other outstanding references to
    /// the underlying chunk of memory.
    pub fn try_mut(mut self) -> Result<BytesMut, Bytes> {
        if self.inner.mem.is_mut_safe() {
            Ok(self.inner)
        } else {
            Err(self)
        }
    }

    /// Consumes handle, returning a new mutable handle
    ///
    /// The function attempts to avoid copying, however if it is unable to
    /// obtain a unique reference to the underlying data, a new buffer is
    /// allocated and the data is copied to it.
    pub fn into_mut(self) -> BytesMut {
        self.try_mut().unwrap_or_else(BytesMut::from_slice)
    }
}

impl IntoBuf for Bytes {
    type Buf = SliceBuf<Self>;

    fn into_buf(self) -> Self::Buf {
        SliceBuf::new(self)
    }
}

impl<'a> IntoBuf for &'a Bytes {
    type Buf = SliceBuf<Self>;

    fn into_buf(self) -> Self::Buf {
        SliceBuf::new(self)
    }
}

impl Clone for Bytes {
    fn clone(&self) -> Bytes {
        Bytes { inner: self.inner.clone() }
    }
}

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

impl ops::Deref for Bytes {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl From<Vec<u8>> for Bytes {
    fn from(src: Vec<u8>) -> Bytes {
        BytesMut::from(src).freeze()
    }
}

impl<'a> From<&'a [u8]> for Bytes {
    fn from(src: &'a [u8]) -> Bytes {
        BytesMut::from(src).freeze()
    }
}

impl PartialEq for Bytes {
    fn eq(&self, other: &Bytes) -> bool {
        self.inner == other.inner
    }
}

impl fmt::Debug for Bytes {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, fmt)
    }
}

unsafe impl Sync for Bytes {}

/*
 *
 * ===== BytesMut =====
 *
 */

impl BytesMut {
    /// Create a new `BytesMut` with the specified capacity.
    pub fn with_capacity(cap: usize) -> BytesMut {
        BytesMut {
            mem: Mem::with_capacity(cap),
            pos: 0,
            len: 0,
            cap: cap,
        }
    }

    /// Creates a new `BytesMut` and copy the given slice into it.
    pub fn from_slice<T: AsRef<[u8]>>(bytes: T) -> BytesMut {
        let buf = ByteBuf::from_slice(bytes);
        buf.into_inner()
    }

    /// Returns the number of bytes contained in this `BytesMut`.
    pub fn len(&self) -> usize {
        self.len
    }

    /// Returns true if the value contains no bytes
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the total byte capacity of this `BytesMut`
    pub fn capacity(&self) -> usize {
        self.cap
    }

    /// Return an immutable handle to the bytes
    pub fn freeze(self) -> Bytes {
        Bytes { inner: self }
    }

    /// Splits the bytes into two at the given index.
    ///
    /// Afterwards `self` contains elements `[0, at)`, and the returned
    /// `BytesMut` contains elements `[at, capacity)`.
    ///
    /// This is an O(1) operation that just increases the reference count and
    /// sets a few indexes.
    ///
    /// # Panics
    ///
    /// Panics if `at > capacity`
    pub fn split_off(&mut self, at: usize) -> BytesMut {
        let mut other = self.clone();

        other.set_start(at);
        self.set_end(at);

        return other
    }

    /// Splits the buffer into two at the given index.
    ///
    /// Afterwards `self` contains elements `[at, len)`, and the returned `BytesMut`
    /// contains elements `[0, at)`.
    ///
    /// This is an O(1) operation that just increases the reference count and
    /// sets a few indexes.
    ///
    /// # Panics
    ///
    /// Panics if `at > len`
    pub fn drain_to(&mut self, at: usize) -> BytesMut {
        let mut other = self.clone();

        other.set_end(at);
        self.set_start(at);

        return other
    }

    /// Returns the inner contents of this `BytesMut` as a slice.
    pub fn as_slice(&self) -> &[u8] {
        self.as_ref()
    }

    /// Returns the inner contents of this `BytesMut` as a mutable slice
    ///
    /// This a slice of bytes that have been initialized
    pub fn as_mut(&mut self) -> &mut [u8] {
        let end = self.pos + self.len;
        &mut self.mem.as_mut()[self.pos..end]
    }

    /// Sets the length of the buffer
    ///
    /// This will explicitly set the size of the buffer without actually
    /// modifying the data, so it is up to the caller to ensure that the data
    /// has been initialized.
    ///
    /// # Panics
    ///
    /// This method will panic if `len` is out of bounds for the underlying
    /// slice or if it comes after the `end` of the configured window.
    pub unsafe fn set_len(&mut self, len: usize) {
        assert!(len <= self.cap);
        self.len = len;
    }

    /// Returns the inner contents of this `BytesMut` as a mutable slice
    ///
    /// This a slice of all bytes, including uninitialized memory
    pub unsafe fn as_raw(&mut self) -> &mut [u8] {
        let end = self.pos + self.cap;
        &mut self.mem.as_mut()[self.pos..end]
    }

    /// Changes the starting index of this window to the index specified.
    ///
    /// Returns the windows back to chain multiple calls to this method.
    ///
    /// # Panics
    ///
    /// This method will panic if `start` is out of bounds for the underlying
    /// slice.
    fn set_start(&mut self, start: usize) -> &mut BytesMut {
        assert!(start <= self.cap);
        self.pos += start;

        if self.len >= start {
            self.len -= start;
        } else {
            self.len = 0;
        }

        self.cap -= start;
        self
    }

    /// Changes the end index of this window to the index specified.
    ///
    /// Returns the windows back to chain multiple calls to this method.
    ///
    /// # Panics
    ///
    /// This method will panic if `start` is out of bounds for the underlying
    /// slice.
    fn set_end(&mut self, end: usize) -> &mut BytesMut {
        assert!(end <= self.cap);
        self.cap = end;
        self.len = cmp::min(self.len, end);
        self
    }

    /// Increments the ref count. This should only be done if it is known that
    /// it can be done safely. As such, this fn is not public, instead other
    /// fns will use this one while maintaining the guarantees.
    fn clone(&self) -> BytesMut {
         BytesMut {
            mem: self.mem.clone(),
            .. *self
        }
    }
}

impl IntoBuf for BytesMut {
    type Buf = SliceBuf<Self>;

    fn into_buf(self) -> Self::Buf {
        SliceBuf::new(self)
    }
}

impl<'a> IntoBuf for &'a BytesMut {
    type Buf = SliceBuf<&'a BytesMut>;

    fn into_buf(self) -> Self::Buf {
        SliceBuf::new(self)
    }
}

impl AsRef<[u8]> for BytesMut {
    fn as_ref(&self) -> &[u8] {
        let end = self.pos + self.len;
        &self.mem.as_ref()[self.pos..end]
    }
}

impl ops::Deref for BytesMut {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl ops::DerefMut for BytesMut {
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl From<Vec<u8>> for BytesMut {
    fn from(src: Vec<u8>) -> BytesMut {
        let len = src.len();
        let cap = src.capacity();

        BytesMut {
            mem: Mem::from_vec(src),
            pos: 0,
            len: len,
            cap: cap,
        }
    }
}

impl<'a> From<&'a [u8]> for BytesMut {
    fn from(src: &'a [u8]) -> BytesMut {
        BytesMut::from_slice(src)
    }
}

impl PartialEq for BytesMut {
    fn eq(&self, other: &BytesMut) -> bool {
        **self == **other
    }
}

impl Eq for BytesMut {
}

impl fmt::Debug for BytesMut {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.as_ref(), fmt)
    }
}

unsafe impl Send for BytesMut {}

/*
 *
 * ===== Mem =====
 *
 */

impl Mem {
    fn with_capacity(cap: usize) -> Mem {
        let mut vec = Vec::with_capacity(cap);
        unsafe { vec.set_len(cap); }

        Mem { inner: Arc::new(UnsafeCell::new(vec.into_boxed_slice())) }
    }

    fn from_vec(mut vec: Vec<u8>) -> Mem {
        let cap = vec.capacity();
        unsafe { vec.set_len(cap); }

        Mem { inner: Arc::new(UnsafeCell::new(vec.into_boxed_slice())) }
    }

    fn as_ref(&self) -> &[u8] {
        unsafe { &*self.inner.get() }
    }

    fn as_mut(&mut self) -> &mut [u8] {
        unsafe { &mut *self.inner.get() }
    }

    fn is_mut_safe(&mut self) -> bool {
        Arc::get_mut(&mut self.inner).is_some()
    }

    fn clone(&self) -> Mem {
        Mem { inner: self.inner.clone() }
    }
}

/*
 *
 * ===== PartialEq =====
 *
 */

impl PartialEq<[u8]> for BytesMut {
    fn eq(&self, other: &[u8]) -> bool {
        &**self == other
    }
}

impl PartialEq<BytesMut> for [u8] {
    fn eq(&self, other: &BytesMut) -> bool {
        *other == *self
    }
}

impl PartialEq<Vec<u8>> for BytesMut {
    fn eq(&self, other: &Vec<u8>) -> bool {
        *self == &other[..]
    }
}

impl PartialEq<BytesMut> for Vec<u8> {
    fn eq(&self, other: &BytesMut) -> bool {
        *other == *self
    }
}

impl<'a, T: ?Sized> PartialEq<&'a T> for BytesMut
    where BytesMut: PartialEq<T>
{
    fn eq(&self, other: &&'a T) -> bool {
        *self == **other
    }
}

impl<'a> PartialEq<BytesMut> for &'a [u8] {
    fn eq(&self, other: &BytesMut) -> bool {
        *other == *self
    }
}

impl PartialEq<[u8]> for Bytes {
    fn eq(&self, other: &[u8]) -> bool {
        self.inner == *other
    }
}

impl PartialEq<Bytes> for [u8] {
    fn eq(&self, other: &Bytes) -> bool {
        *other == *self
    }
}

impl PartialEq<Vec<u8>> for Bytes {
    fn eq(&self, other: &Vec<u8>) -> bool {
        *self == &other[..]
    }
}

impl PartialEq<Bytes> for Vec<u8> {
    fn eq(&self, other: &Bytes) -> bool {
        *other == *self
    }
}

impl<'a> PartialEq<Bytes> for &'a [u8] {
    fn eq(&self, other: &Bytes) -> bool {
        *other == *self
    }
}

impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes
    where Bytes: PartialEq<T>
{
    fn eq(&self, other: &&'a T) -> bool {
        *self == **other
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;
use syntax::{Expr, ExprF};
use typed_arena::Arena;

pub type Error = &'static str;

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ID(usize);

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Ty<'ty> {
  Deferred(ID),
  Func(&'ty Ty<'ty>, &'ty Ty<'ty>),
  Bool,
  Int,
  Str,
}

pub static TY_BOOL: Ty<'static> = Ty::Bool;
pub static TY_INT:  Ty<'static> = Ty::Int;
pub static TY_STR:  Ty<'static> = Ty::Str;

impl<'ty> Ty<'ty> {
  pub fn pretty<Purge, W>(&'ty self, purge: &Purge, into: &mut W) -> fmt::Result
    where
      Purge: Fn(&'ty Ty<'ty>) -> &'ty Ty<'ty>,
      W: fmt::Write {
    match *purge(self) {
      Ty::Deferred(ID(id)) =>
        write!(into, "t{}", id),
      Ty::Func(a, b) => {
        try!(write!(into, "("));
        try!(a.pretty(purge, into));
        try!(write!(into, " -> "));
        try!(b.pretty(purge, into));
        try!(write!(into, ")"));
        Ok(())
      },
      Ty::Bool =>
        write!(into, "bool"),
      Ty::Int =>
        write!(into, "int"),
      Ty::Str =>
        write!(into, "str"),
    }
  }
}

pub struct Check<'ty> {
  arena: &'ty Arena<Ty<'ty>>,
  next_id: usize,
  solved: HashMap<ID, &'ty Ty<'ty>>,
}

impl<'ty> Check<'ty> {
  pub fn new(arena: &'ty Arena<Ty<'ty>>) -> Self {
    Check{
      arena: arena,
      next_id: 0,
      solved: HashMap::new(),
    }
  }

  pub fn fresh(&mut self) -> &'ty Ty<'ty> {
    let ty = self.arena.alloc(Ty::Deferred(ID(self.next_id)));
    self.next_id += 1;
    ty
  }

  fn solve(&mut self, id: ID, ty: &'ty Ty<'ty>) {
    self.solved.insert(id, ty);
  }

  pub fn purge(&self, ty: &'ty Ty<'ty>) -> &'ty Ty<'ty> {
    match ty {
      &Ty::Deferred(id) =>
        match self.solved.get(&id) {
          Some(uy) => self.purge(uy),
          None => ty,
        },
      _ => ty,
    }
  }

  pub fn unify(&mut self, ty: &'ty Ty<'ty>, uy: &'ty Ty<'ty>) -> Result<(), Error> {
    match (self.purge(ty), self.purge(uy)) {
      (&Ty::Deferred(ty_id), &Ty::Deferred(uy_id))
        if ty_id == uy_id =>
        Ok(()),
      (&Ty::Deferred(ty_id), uy_p) => {
        self.solve(ty_id, uy_p);
        Ok(())
      },
      (ty_p, &Ty::Deferred(uy_id)) => {
        self.solve(uy_id, ty_p);
        Ok(())
      },
      (&Ty::Func(ty_a, ty_b), &Ty::Func(uy_a, uy_b)) => {
        try!(self.unify(ty_a, uy_a));
        try!(self.unify(ty_b, uy_b));
        Ok(())
      },
      (&Ty::Bool, &Ty::Bool) =>
        Ok(()),
      (&Ty::Int, &Ty::Int) =>
        Ok(()),
      (&Ty::Str, &Ty::Str) =>
        Ok(()),
      (_, _) => {
        Err("cannot unify types")
      },
    }
  }

  pub fn infer<T>(
    &mut self,
    env: &HashMap<&str, &'ty Ty<'ty>>,
    expr: &Expr<T>,
  ) -> Result<&'ty Ty<'ty>, Error> {
    match expr.1 {
      ExprF::Lit(_) =>
        // FIXME: Non-Boolean literals.
        Ok(&TY_BOOL),
      ExprF::Var(name) =>
        match env.get(&name) {
          Some(ty) => Ok(ty),
          None => {
            Err("cannot find variable")
          },
        },
      ExprF::Abs(param, body) => {
        let param_ty = self.fresh();

        let mut body_env = env.clone();
        body_env.insert(param, param_ty);
        let result_ty = try!(self.infer(&body_env, body));

        let func_ty = self.arena.alloc(Ty::Func(param_ty, result_ty));
        Ok(func_ty)
      },
      ExprF::App(callee, argument) => {
        let callee_ty = try!(self.infer(env, callee));
        let argument_ty = try!(self.infer(env, argument));

        let result_ty = self.fresh();
        let func_ty = self.arena.alloc(Ty::Func(argument_ty, result_ty));
        try!(self.unify(callee_ty, func_ty));

        Ok(result_ty)
      },
    }
  }
}

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

  #[test]
  fn test_unify() {
    let arena = Arena::new();
    let mut check = Check::new(&arena);

    let ty1 = &TY_BOOL;
    let ty2 = arena.alloc(Ty::Func(ty1, ty1));
    let ty3 = check.fresh();
    let ty4 = check.fresh();
    let ty5 = check.fresh();
    let ty6 = check.fresh();

    assert_eq!(check.unify(ty1, ty1), Ok(()));

    assert_eq!(check.unify(ty2, ty2), Ok(()));

    assert_eq!(check.unify(ty1, ty2), Err("cannot unify types"));

    assert_eq!(check.unify(ty3, ty3), Ok(()));
    assert_eq!(check.unify(ty3, ty4), Ok(()));
    assert_eq!(check.unify(ty4, ty1), Ok(()));
    assert_eq!(check.purge(ty3),      ty1);
    assert_eq!(check.unify(ty5, ty1), Ok(()));
    assert_eq!(check.unify(ty5, ty3), Ok(()));
    assert_eq!(check.unify(ty6, ty2), Ok(()));
    assert_eq!(check.unify(ty5, ty6), Err("cannot unify types"));
  }

  #[test]
  fn test_infer() {
    let expr_arena = Arena::new();
    let ty_arena = Arena::new();

    let mut check = Check::new(&ty_arena);

    let mut env = HashMap::new();
    env.insert("vari", &TY_INT);
    env.insert("even", ty_arena.alloc(Ty::Func(&TY_INT, &TY_BOOL)));

    let expr = Expr(
      (),
      ExprF::App(
        expr_arena.alloc(Expr((), ExprF::Var("even"))),
        expr_arena.alloc(Expr((), ExprF::Var("vari"))),
      ),
    );
    let ty = check.infer(&env, &expr);
    assert_eq!(ty.map(|t| check.purge(t)), Ok(&TY_BOOL));
  }
}
<commit_msg>Type check literals properly<commit_after>use std::collections::HashMap;
use std::fmt;
use syntax::{Expr, ExprF, Literal};
use typed_arena::Arena;

pub type Error = &'static str;

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ID(usize);

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Ty<'ty> {
  Deferred(ID),
  Func(&'ty Ty<'ty>, &'ty Ty<'ty>),
  Bool,
  Int,
  Str,
}

pub static TY_BOOL: Ty<'static> = Ty::Bool;
pub static TY_INT:  Ty<'static> = Ty::Int;
pub static TY_STR:  Ty<'static> = Ty::Str;

impl<'ty> Ty<'ty> {
  pub fn pretty<Purge, W>(&'ty self, purge: &Purge, into: &mut W) -> fmt::Result
    where
      Purge: Fn(&'ty Ty<'ty>) -> &'ty Ty<'ty>,
      W: fmt::Write {
    match *purge(self) {
      Ty::Deferred(ID(id)) =>
        write!(into, "t{}", id),
      Ty::Func(a, b) => {
        try!(write!(into, "("));
        try!(a.pretty(purge, into));
        try!(write!(into, " -> "));
        try!(b.pretty(purge, into));
        try!(write!(into, ")"));
        Ok(())
      },
      Ty::Bool =>
        write!(into, "bool"),
      Ty::Int =>
        write!(into, "int"),
      Ty::Str =>
        write!(into, "str"),
    }
  }
}

pub struct Check<'ty> {
  arena: &'ty Arena<Ty<'ty>>,
  next_id: usize,
  solved: HashMap<ID, &'ty Ty<'ty>>,
}

impl<'ty> Check<'ty> {
  pub fn new(arena: &'ty Arena<Ty<'ty>>) -> Self {
    Check{
      arena: arena,
      next_id: 0,
      solved: HashMap::new(),
    }
  }

  pub fn fresh(&mut self) -> &'ty Ty<'ty> {
    let ty = self.arena.alloc(Ty::Deferred(ID(self.next_id)));
    self.next_id += 1;
    ty
  }

  fn solve(&mut self, id: ID, ty: &'ty Ty<'ty>) {
    self.solved.insert(id, ty);
  }

  pub fn purge(&self, ty: &'ty Ty<'ty>) -> &'ty Ty<'ty> {
    match ty {
      &Ty::Deferred(id) =>
        match self.solved.get(&id) {
          Some(uy) => self.purge(uy),
          None => ty,
        },
      _ => ty,
    }
  }

  pub fn unify(&mut self, ty: &'ty Ty<'ty>, uy: &'ty Ty<'ty>) -> Result<(), Error> {
    match (self.purge(ty), self.purge(uy)) {
      (&Ty::Deferred(ty_id), &Ty::Deferred(uy_id))
        if ty_id == uy_id =>
        Ok(()),
      (&Ty::Deferred(ty_id), uy_p) => {
        self.solve(ty_id, uy_p);
        Ok(())
      },
      (ty_p, &Ty::Deferred(uy_id)) => {
        self.solve(uy_id, ty_p);
        Ok(())
      },
      (&Ty::Func(ty_a, ty_b), &Ty::Func(uy_a, uy_b)) => {
        try!(self.unify(ty_a, uy_a));
        try!(self.unify(ty_b, uy_b));
        Ok(())
      },
      (&Ty::Bool, &Ty::Bool) =>
        Ok(()),
      (&Ty::Int, &Ty::Int) =>
        Ok(()),
      (&Ty::Str, &Ty::Str) =>
        Ok(()),
      (_, _) => {
        Err("cannot unify types")
      },
    }
  }

  pub fn infer<T>(
    &mut self,
    env: &HashMap<&str, &'ty Ty<'ty>>,
    expr: &Expr<T>,
  ) -> Result<&'ty Ty<'ty>, Error> {
    match expr.1 {
      ExprF::Lit(Literal::Bool(_)) =>
        Ok(&TY_BOOL),
      ExprF::Lit(Literal::Int(_)) =>
        Ok(&TY_INT),
      ExprF::Lit(Literal::Str(_)) =>
        Ok(&TY_STR),
      ExprF::Var(name) =>
        match env.get(&name) {
          Some(ty) => Ok(ty),
          None => {
            Err("cannot find variable")
          },
        },
      ExprF::Abs(param, body) => {
        let param_ty = self.fresh();

        let mut body_env = env.clone();
        body_env.insert(param, param_ty);
        let result_ty = try!(self.infer(&body_env, body));

        let func_ty = self.arena.alloc(Ty::Func(param_ty, result_ty));
        Ok(func_ty)
      },
      ExprF::App(callee, argument) => {
        let callee_ty = try!(self.infer(env, callee));
        let argument_ty = try!(self.infer(env, argument));

        let result_ty = self.fresh();
        let func_ty = self.arena.alloc(Ty::Func(argument_ty, result_ty));
        try!(self.unify(callee_ty, func_ty));

        Ok(result_ty)
      },
    }
  }
}

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

  #[test]
  fn test_unify() {
    let arena = Arena::new();
    let mut check = Check::new(&arena);

    let ty1 = &TY_BOOL;
    let ty2 = arena.alloc(Ty::Func(ty1, ty1));
    let ty3 = check.fresh();
    let ty4 = check.fresh();
    let ty5 = check.fresh();
    let ty6 = check.fresh();

    assert_eq!(check.unify(ty1, ty1), Ok(()));

    assert_eq!(check.unify(ty2, ty2), Ok(()));

    assert_eq!(check.unify(ty1, ty2), Err("cannot unify types"));

    assert_eq!(check.unify(ty3, ty3), Ok(()));
    assert_eq!(check.unify(ty3, ty4), Ok(()));
    assert_eq!(check.unify(ty4, ty1), Ok(()));
    assert_eq!(check.purge(ty3),      ty1);
    assert_eq!(check.unify(ty5, ty1), Ok(()));
    assert_eq!(check.unify(ty5, ty3), Ok(()));
    assert_eq!(check.unify(ty6, ty2), Ok(()));
    assert_eq!(check.unify(ty5, ty6), Err("cannot unify types"));
  }

  #[test]
  fn test_infer() {
    let expr_arena = Arena::new();
    let ty_arena = Arena::new();

    let mut check = Check::new(&ty_arena);

    let mut env = HashMap::new();
    env.insert("vari", &TY_INT);
    env.insert("even", ty_arena.alloc(Ty::Func(&TY_INT, &TY_BOOL)));

    let expr = Expr(
      (),
      ExprF::App(
        expr_arena.alloc(Expr((), ExprF::Var("even"))),
        expr_arena.alloc(Expr((), ExprF::Var("vari"))),
      ),
    );
    let ty = check.infer(&env, &expr);
    assert_eq!(ty.map(|t| check.purge(t)), Ok(&TY_BOOL));
  }
}
<|endoftext|>


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

//! Cloud API.

#[allow(unused_imports)]
use fallible_iterator::FallibleIterator;

#[allow(unused_imports)]
use super::{Error, ErrorKind, Result};
use super::auth::AuthMethod;
#[cfg(feature = "compute")]
use super::compute::{Flavor, FlavorQuery, FlavorSummary,
                     Server, ServerQuery, ServerSummary};
#[cfg(feature = "image")]
use super::image::{Image, ImageQuery};
use super::session::Session;
#[allow(unused_imports)]
use super::utils::ResultExt;

/// OpenStack cloud API.
///
/// Provides high-level API for working with OpenStack clouds.
#[derive(Debug, Clone)]
pub struct Cloud {
    session: Session
}

impl Cloud {
    /// Create a new cloud object with a given authentication plugin.
    ///
    /// See (auth module)[auth/index.html) for details on how to authenticate
    /// against OpenStack clouds.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// ```
    pub fn new<Auth: AuthMethod + 'static>(auth_method: Auth) -> Cloud {
        Cloud::new_with_session(Session::new(auth_method))
    }

    /// Create a new cloud object with a given session.
    ///
    /// This constructor can be used to modify `Session` parameters before
    /// using it in the `Cloud` object. This is an advanced feature and
    /// should generally be avoided.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let session = openstack::session::Session::new(auth);
    /// let os = openstack::Cloud::new_with_session(session);
    pub fn new_with_session(session: Session) -> Cloud {
        Cloud {
            session: session
        }
    }

    /// Convert this cloud into one using the given endpoint interface.
    pub fn with_endpoint_interface<S>(self, endpoint_interface: S)
            -> Cloud where S: Into<String> {
        Cloud {
            session: self.session.with_endpoint_interface(endpoint_interface)
        }
    }

    /// `Session` used with this `Cloud` object.
    pub fn session(&self) -> &Session {
        &self.session
    }

    /// Refresh this `Cloud` object (renew token, refetch service catalog, etc).
    pub fn refresh(&mut self) -> Result<()> {
        self.session.auth_method_mut().refresh()
    }

    /// Extract the `Session` object, destroying this `Cloud`.
    pub fn into_session(self) -> Session {
        self.session
    }

    /// Find a server by its name or ID.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server = os.get_server("8a1c355b-2e1e-440a-8aa8-f272df72bc32")
    ///     .expect("Unable to get a server");
    /// ```
    #[cfg(feature = "compute")]
    pub fn get_server<Id: Into<String>>(&self, id_or_name: Id) -> Result<Server> {
        let s = id_or_name.into();
        Server::new(&self.session, &s).if_not_found_then(|| {
            self.find_servers().with_name(s.clone()).into_iter()
                .filter(|srv| srv.name() == &s).take(2)
                .collect::<Vec<ServerSummary>>().and_then(|mut srvs| {
                    if srvs.len() > 1 {
                        Err(Error::new(ErrorKind::TooManyItems,
                                       "Too many servers with this name"))
                    } else {
                        match srvs.pop() {
                            Some(srv) => srv.details(),
                            None => Err(Error::new(
                                ErrorKind::ResourceNotFound,
                                "No servers with this name or ID"))
                        }
                    }
                })
        })
    }

    /// Build a query against server list.
    ///
    /// The returned object is a builder that should be used to construct
    /// the query.
    ///
    /// # Example
    ///
    /// Sorting servers by `access_ip_v4` and getting first 5 results:
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let sorting = openstack::compute::ServerSortKey::AccessIpv4;
    /// let server_list = os.find_servers()
    ///     .sort_by(openstack::Sort::Asc(sorting)).with_limit(5)
    ///     .all().expect("Unable to fetch servers");
    /// ```
    #[cfg(feature = "compute")]
    pub fn find_servers(&self) -> ServerQuery {
        ServerQuery::new(&self.session)
    }

    /// List all servers.
    ///
    /// This call can yield a lot of results, use the
    /// [find_servers](#method.find_servers) call to limit the number of
    /// servers to receive.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server_list = os.list_servers().expect("Unable to fetch servers");
    /// ```
    #[cfg(feature = "compute")]
    pub fn list_servers(&self) -> Result<Vec<ServerSummary>> {
        self.find_servers().all()
    }

    /// Find a flavor by its name or ID.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server = os.get_flavor("m1.medium").expect("Unable to get a flavor");
    /// ```
    #[cfg(feature = "compute")]
    pub fn get_flavor<Id: Into<String>>(&self, id_or_name: Id) -> Result<Flavor> {
        let s = id_or_name.into();
        Flavor::new(&self.session, &s).if_not_found_then(|| {
            self.find_flavors().into_iter()
                .filter(|item| item.name() == &s).take(2)
                .collect::<Vec<FlavorSummary>>().and_then(|mut items| {
                    if items.len() > 1 {
                        Err(Error::new(ErrorKind::TooManyItems,
                                       "Too many flavors with this name"))
                    } else {
                        match items.pop() {
                            Some(item) => item.details(),
                            None => Err(Error::new(
                                ErrorKind::ResourceNotFound,
                                "No flavors with this name or ID"))
                        }
                    }
                })
        })
    }

    /// Build a query against flavor list.
    ///
    /// The returned object is a builder that should be used to construct
    /// the query.
    #[cfg(feature = "compute")]
    pub fn find_flavors(&self) -> FlavorQuery {
        FlavorQuery::new(&self.session)
    }

    /// List all flavors.
    ///
    /// This call can yield a lot of results, use the
    /// [find_flavors](#method.find_flavors) call to limit the number of
    /// flavors to receive.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server_list = os.list_flavors().expect("Unable to fetch flavors");
    /// ```
    #[cfg(feature = "compute")]
    pub fn list_flavors(&self) -> Result<Vec<FlavorSummary>> {
        self.find_flavors().all()
    }

    /// Find an image by its name or ID.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server = os.get_image("centos7").expect("Unable to get a image");
    /// ```
    #[cfg(feature = "image")]
    pub fn get_image<Id: Into<String>>(&self, id_or_name: Id) -> Result<Image> {
        let s = id_or_name.into();
        Image::new(&self.session, &s).if_not_found_then(|| {
            self.find_images().with_name(s).one()
        })
    }

    /// Build a query against image list.
    ///
    /// The returned object is a builder that should be used to construct
    /// the query.
    #[cfg(feature = "image")]
    pub fn find_images(&self) -> ImageQuery {
        ImageQuery::new(&self.session)
    }

    /// List all images.
    ///
    /// This call can yield a lot of results, use the
    /// [find_images](#method.find_images) call to limit the number of
    /// images to receive.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server_list = os.list_images().expect("Unable to fetch images");
    /// ```
    #[cfg(feature = "image")]
    pub fn list_images(&self) -> Result<Vec<Image>> {
        self.find_images().all()
    }
}

impl From<Session> for Cloud {
    fn from(value: Session) -> Cloud {
        Cloud::new_with_session(value)
    }
}
<commit_msg>chore: sort feature methods of Cloud<commit_after>// Copyright 2018 Dmitry Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Cloud API.

#[allow(unused_imports)]
use fallible_iterator::FallibleIterator;

#[allow(unused_imports)]
use super::{Error, ErrorKind, Result};
use super::auth::AuthMethod;
#[cfg(feature = "compute")]
use super::compute::{Flavor, FlavorQuery, FlavorSummary,
                     Server, ServerQuery, ServerSummary};
#[cfg(feature = "image")]
use super::image::{Image, ImageQuery};
use super::session::Session;
#[allow(unused_imports)]
use super::utils::ResultExt;

/// OpenStack cloud API.
///
/// Provides high-level API for working with OpenStack clouds.
#[derive(Debug, Clone)]
pub struct Cloud {
    session: Session
}

impl Cloud {
    /// Create a new cloud object with a given authentication plugin.
    ///
    /// See (auth module)[auth/index.html) for details on how to authenticate
    /// against OpenStack clouds.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// ```
    pub fn new<Auth: AuthMethod + 'static>(auth_method: Auth) -> Cloud {
        Cloud::new_with_session(Session::new(auth_method))
    }

    /// Create a new cloud object with a given session.
    ///
    /// This constructor can be used to modify `Session` parameters before
    /// using it in the `Cloud` object. This is an advanced feature and
    /// should generally be avoided.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let session = openstack::session::Session::new(auth);
    /// let os = openstack::Cloud::new_with_session(session);
    pub fn new_with_session(session: Session) -> Cloud {
        Cloud {
            session: session
        }
    }

    /// Convert this cloud into one using the given endpoint interface.
    pub fn with_endpoint_interface<S>(self, endpoint_interface: S)
            -> Cloud where S: Into<String> {
        Cloud {
            session: self.session.with_endpoint_interface(endpoint_interface)
        }
    }

    /// `Session` used with this `Cloud` object.
    pub fn session(&self) -> &Session {
        &self.session
    }

    /// Extract the `Session` object, destroying this `Cloud`.
    pub fn into_session(self) -> Session {
        self.session
    }

    /// Refresh this `Cloud` object (renew token, refetch service catalog, etc).
    pub fn refresh(&mut self) -> Result<()> {
        self.session.auth_method_mut().refresh()
    }

    /// Build a query against flavor list.
    ///
    /// The returned object is a builder that should be used to construct
    /// the query.
    #[cfg(feature = "compute")]
    pub fn find_flavors(&self) -> FlavorQuery {
        FlavorQuery::new(&self.session)
    }

    /// Build a query against image list.
    ///
    /// The returned object is a builder that should be used to construct
    /// the query.
    #[cfg(feature = "image")]
    pub fn find_images(&self) -> ImageQuery {
        ImageQuery::new(&self.session)
    }

    /// Build a query against server list.
    ///
    /// The returned object is a builder that should be used to construct
    /// the query.
    ///
    /// # Example
    ///
    /// Sorting servers by `access_ip_v4` and getting first 5 results:
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let sorting = openstack::compute::ServerSortKey::AccessIpv4;
    /// let server_list = os.find_servers()
    ///     .sort_by(openstack::Sort::Asc(sorting)).with_limit(5)
    ///     .all().expect("Unable to fetch servers");
    /// ```
    #[cfg(feature = "compute")]
    pub fn find_servers(&self) -> ServerQuery {
        ServerQuery::new(&self.session)
    }

    /// Find a flavor by its name or ID.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server = os.get_flavor("m1.medium").expect("Unable to get a flavor");
    /// ```
    #[cfg(feature = "compute")]
    pub fn get_flavor<Id: Into<String>>(&self, id_or_name: Id) -> Result<Flavor> {
        let s = id_or_name.into();
        Flavor::new(&self.session, &s).if_not_found_then(|| {
            self.find_flavors().into_iter()
                .filter(|item| item.name() == &s).take(2)
                .collect::<Vec<FlavorSummary>>().and_then(|mut items| {
                    if items.len() > 1 {
                        Err(Error::new(ErrorKind::TooManyItems,
                                       "Too many flavors with this name"))
                    } else {
                        match items.pop() {
                            Some(item) => item.details(),
                            None => Err(Error::new(
                                ErrorKind::ResourceNotFound,
                                "No flavors with this name or ID"))
                        }
                    }
                })
        })
    }

    /// Find an image by its name or ID.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server = os.get_image("centos7").expect("Unable to get a image");
    /// ```
    #[cfg(feature = "image")]
    pub fn get_image<Id: Into<String>>(&self, id_or_name: Id) -> Result<Image> {
        let s = id_or_name.into();
        Image::new(&self.session, &s).if_not_found_then(|| {
            self.find_images().with_name(s).one()
        })
    }

    /// Find a server by its name or ID.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server = os.get_server("8a1c355b-2e1e-440a-8aa8-f272df72bc32")
    ///     .expect("Unable to get a server");
    /// ```
    #[cfg(feature = "compute")]
    pub fn get_server<Id: Into<String>>(&self, id_or_name: Id) -> Result<Server> {
        let s = id_or_name.into();
        Server::new(&self.session, &s).if_not_found_then(|| {
            self.find_servers().with_name(s.clone()).into_iter()
                .filter(|srv| srv.name() == &s).take(2)
                .collect::<Vec<ServerSummary>>().and_then(|mut srvs| {
                    if srvs.len() > 1 {
                        Err(Error::new(ErrorKind::TooManyItems,
                                       "Too many servers with this name"))
                    } else {
                        match srvs.pop() {
                            Some(srv) => srv.details(),
                            None => Err(Error::new(
                                ErrorKind::ResourceNotFound,
                                "No servers with this name or ID"))
                        }
                    }
                })
        })
    }

    /// List all flavors.
    ///
    /// This call can yield a lot of results, use the
    /// [find_flavors](#method.find_flavors) call to limit the number of
    /// flavors to receive.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server_list = os.list_flavors().expect("Unable to fetch flavors");
    /// ```
    #[cfg(feature = "compute")]
    pub fn list_flavors(&self) -> Result<Vec<FlavorSummary>> {
        self.find_flavors().all()
    }

    /// List all images.
    ///
    /// This call can yield a lot of results, use the
    /// [find_images](#method.find_images) call to limit the number of
    /// images to receive.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server_list = os.list_images().expect("Unable to fetch images");
    /// ```
    #[cfg(feature = "image")]
    pub fn list_images(&self) -> Result<Vec<Image>> {
        self.find_images().all()
    }

    /// List all servers.
    ///
    /// This call can yield a lot of results, use the
    /// [find_servers](#method.find_servers) call to limit the number of
    /// servers to receive.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use openstack;
    ///
    /// let auth = openstack::auth::from_env().expect("Unable to authenticate");
    /// let os = openstack::Cloud::new(auth);
    /// let server_list = os.list_servers().expect("Unable to fetch servers");
    /// ```
    #[cfg(feature = "compute")]
    pub fn list_servers(&self) -> Result<Vec<ServerSummary>> {
        self.find_servers().all()
    }
}

impl From<Session> for Cloud {
    fn from(value: Session) -> Cloud {
        Cloud::new_with_session(value)
    }
}
<|endoftext|>


<commit_before>pub struct Crc64 {
    table: [u64; 256],
    value: u64,
    count: u32,
}

fn table_maker(polynomial: u64) -> [u64; 256] {
    let mut table: [u64; 256] = [0; 256];
    for i in 0..256 {
        let mut v = i as u64;
        for _ in 0..8 {
            v = if v & 1 != 0 {
                polynomial ^ (v >> 1)
            } else {
                v >> 1
            }
        }
        table[i] = v;
    }
    table
}

impl Crc64 {
    pub fn new() -> Crc64 {
        let polynomial = 0xC96C5795D7870F42;
        let c64 = Crc64 {
            table: table_maker(polynomial),
            value: 0xffffffffffffffff,
            count: 0,
        };
        c64
    }

    pub fn reset(&mut self) {
        self.value = 0xffffffffffffffff;
    }

    pub fn update(&mut self, buf: &[u8]) {
        for &i in buf {
            self.value = self.table[((self.value as u8) ^ i) as usize] ^ (self.value >> 8);
            self.count += 1;
        }
    }

    pub fn finalize(&mut self){
        self.value = self.value ^ 0xffffffffffffffffu64;
    }

    pub fn checksum(&mut self, buf: &[u8]) -> u64 {
        self.reset();
        self.update(buf);
        self.finalize();
        self.getsum()
    }

    pub fn getsum(&self) -> u64 {
        self.value
    }

    pub fn bytecount(&self) -> u32{
        self.count
    }
}

#[test]
fn crc32_test() {
    let mut crc64 = Crc64::new();
    crc64.checksum(b"0000");
    assert_eq!(crc64.getsum(),0x2B5C866A7CBEF446);
}
<commit_msg>Corrected the reset method to reset the byte count<commit_after>pub struct Crc64 {
    table: [u64; 256],
    value: u64,
    count: u32,
}

fn table_maker(polynomial: u64) -> [u64; 256] {
    let mut table: [u64; 256] = [0; 256];
    for i in 0..256 {
        let mut v = i as u64;
        for _ in 0..8 {
            v = if v & 1 != 0 {
                polynomial ^ (v >> 1)
            } else {
                v >> 1
            }
        }
        table[i] = v;
    }
    table
}

impl Crc64 {
    pub fn new() -> Crc64 {
        let polynomial = 0xC96C5795D7870F42;
        let c64 = Crc64 {
            table: table_maker(polynomial),
            value: 0xffffffffffffffff,
            count: 0,
        };
        c64
    }

    pub fn reset(&mut self) {
        self.value = 0xffffffffffffffff;
        self.count = 0;
    }

    pub fn update(&mut self, buf: &[u8]) {
        for &i in buf {
            self.value = self.table[((self.value as u8) ^ i) as usize] ^ (self.value >> 8);
            self.count += 1;
        }
    }

    pub fn finalize(&mut self){
        self.value = self.value ^ 0xffffffffffffffffu64;
    }

    pub fn checksum(&mut self, buf: &[u8]) -> u64 {
        self.reset();
        self.update(buf);
        self.finalize();
        self.getsum()
    }

    pub fn getsum(&self) -> u64 {
        self.value
    }

    pub fn bytecount(&self) -> u32{
        self.count
    }
}

#[test]
fn crc32_test() {
    let mut crc64 = Crc64::new();
    crc64.checksum(b"0000");
    assert_eq!(crc64.getsum(),0x2B5C866A7CBEF446);
}
<|endoftext|>


<commit_before>extern crate image;
extern crate nalgebra;

use std::f64::consts::FRAC_PI_2;
use std::io::File;
use std::num::FloatMath;
use image::{GenericImage, Pixel};
use nalgebra::{DVec, Mat2, Pnt2, Rot2, Vec1, Vec2, Vec3};

fn draw(v: &DVec<f64>, path: &Path) {
    let width = v.len() as u32;
    let height = 128u32;
    let white = Pixel::from_channels(255, 255, 255, 255);
    let buffer = image::ImageBuffer::from_fn(width, height, |_, _| white);
    let mut img = image::DynamicImage::ImageRgba8(buffer);
    let red = Pixel::from_channels(255, 0, 0, 255);
    for i in range(0u32, width) {
        let half = (height / 2) as f64;
        let y = half * (1.0 + v[i as uint]);
        let y = nalgebra::clamp(y as u32, 0u32, height - 1);
        img.put_pixel(i, y, red);
    }
    let out = File::create(path).unwrap();
    let _ = img.save(out, image::PNG);
}

fn main() {
    println!("24 days of Rust - nalgebra (day 14)");
    let v = Vec2::new(0.0f64, 1.0);
    // 90 degrees clockwise
    //  0, 1
    // -1, 0
    let rot = Mat2::new(0.0f64, -1.0, 1.0, 0.0);
    println!("{}", rot * v);
    let angle = FRAC_PI_2;
    let rot = Rot2::new(Vec1::new(angle));
    println!("{}", rot * v);
    let point = Pnt2::new(4.0f64, 4.0);
    println!("Translate from {} to {}", point, nalgebra::translate(&v, &point));

    let v1 = Vec3::new(2.0f64, 2.0, 0.0);
    let v2 = Vec3::new(2.0f64, -2.0, 0.0);
    if nalgebra::approx_eq(&0.0f64, &nalgebra::dot(&v1, &v2)) {
        println!("v1 is orthogonal to v2");
    }

    println!("{}", nalgebra::cross(&v1, &v2));
    println!("{}", nalgebra::cross(&v2, &v1));

    let sine = DVec::from_fn(512, |i: uint| {
        let t = i as f64 / 16.0f64;
        t.sin()
    });
    draw(&sine, &Path::new("out_sine.png"));
}
<commit_msg>Reverse plot.<commit_after>extern crate image;
extern crate nalgebra;

use std::f64::consts::FRAC_PI_2;
use std::io::File;
use std::num::FloatMath;
use image::{GenericImage, Pixel};
use nalgebra::{DVec, Mat2, Pnt2, Rot2, Vec1, Vec2, Vec3};

fn draw(v: &DVec<f64>, path: &Path) {
    let width = v.len() as u32;
    let height = 128u32;
    let white = Pixel::from_channels(255, 255, 255, 255);
    let buffer = image::ImageBuffer::from_fn(width, height, |_, _| white);
    let mut img = image::DynamicImage::ImageRgba8(buffer);
    let red = Pixel::from_channels(255, 0, 0, 255);
    for i in range(0u32, width) {
        let half = (height / 2) as f64;
        let y = half * (1.0 + v[i as uint]);
        let y = nalgebra::clamp(y as u32, 1u32, height);
        img.put_pixel(i, height - y, red);
    }
    let out = File::create(path).unwrap();
    let _ = img.save(out, image::PNG);
}

fn main() {
    println!("24 days of Rust - nalgebra (day 14)");
    let v = Vec2::new(0.0f64, 1.0);
    // 90 degrees clockwise
    //  0, 1
    // -1, 0
    let rot = Mat2::new(0.0f64, -1.0, 1.0, 0.0);
    println!("{}", rot * v);
    let angle = FRAC_PI_2;
    let rot = Rot2::new(Vec1::new(angle));
    println!("{}", rot * v);
    let point = Pnt2::new(4.0f64, 4.0);
    println!("Translate from {} to {}", point, nalgebra::translate(&v, &point));

    let v1 = Vec3::new(2.0f64, 2.0, 0.0);
    let v2 = Vec3::new(2.0f64, -2.0, 0.0);
    if nalgebra::approx_eq(&0.0f64, &nalgebra::dot(&v1, &v2)) {
        println!("v1 is orthogonal to v2");
    }

    println!("{}", nalgebra::cross(&v1, &v2));
    println!("{}", nalgebra::cross(&v2, &v1));

    let sine = DVec::from_fn(512, |i: uint| {
        let t = i as f64 / 16.0f64;
        t.sin()
    });
    draw(&sine, &Path::new("out_sine.png"));
}
<|endoftext|>