<commit_before>//! Unix-specific extensions to primitives in the `std::process` module.

#![stable(feature = "rust1", since = "1.0.0")]

use crate::ffi::OsStr;
use crate::io;
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::process;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};

/// Unix-specific extensions to the [`process::Command`] builder.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait CommandExt {
    /// Sets the child process's user ID. This translates to a
    /// `setuid` call in the child process. Failure in the `setuid`
    /// call will cause the spawn to fail.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn uid(
        &mut self,
        #[cfg(not(target_os = "vxworks"))] id: u32,
        #[cfg(target_os = "vxworks")] id: u16,
    ) -> &mut process::Command;

    /// Similar to `uid`, but sets the group ID of the child process. This has
    /// the same semantics as the `uid` field.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn gid(
        &mut self,
        #[cfg(not(target_os = "vxworks"))] id: u32,
        #[cfg(target_os = "vxworks")] id: u16,
    ) -> &mut process::Command;

    /// Schedules a closure to be run just before the `exec` function is
    /// invoked.
    ///
    /// The closure is allowed to return an I/O error whose OS error code will
    /// be communicated back to the parent and returned as an error from when
    /// the spawn was requested.
    ///
    /// Multiple closures can be registered and they will be called in order of
    /// their registration. If a closure returns `Err` then no further closures
    /// will be called and the spawn operation will immediately return with a
    /// failure.
    ///
    /// # Notes and Safety
    ///
    /// This closure will be run in the context of the child process after a
    /// `fork`. This primarily means that any modifications made to memory on
    /// behalf of this closure will **not** be visible to the parent process.
    /// This is often a very constrained environment where normal operations
    /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
    /// other threads perhaps still running when the `fork` was run).
    ///
    /// This also means that all resources such as file descriptors and
    /// memory-mapped regions got duplicated. It is your responsibility to make
    /// sure that the closure does not violate library invariants by making
    /// invalid use of these duplicates.
    ///
    /// When this closure is run, aspects such as the stdio file descriptors and
    /// working directory have successfully been changed, so output to these
    /// locations may not appear where intended.
    #[stable(feature = "process_pre_exec", since = "1.34.0")]
    unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
    where
        F: FnMut() -> io::Result<()> + Send + Sync + 'static;

    /// Schedules a closure to be run just before the `exec` function is
    /// invoked.
    ///
    /// This method is stable and usable, but it should be unsafe. To fix
    /// that, it got deprecated in favor of the unsafe [`pre_exec`].
    ///
    /// [`pre_exec`]: CommandExt::pre_exec
    #[stable(feature = "process_exec", since = "1.15.0")]
    #[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")]
    fn before_exec<F>(&mut self, f: F) -> &mut process::Command
    where
        F: FnMut() -> io::Result<()> + Send + Sync + 'static,
    {
        unsafe { self.pre_exec(f) }
    }

    /// Performs all the required setup by this `Command`, followed by calling
    /// the `execvp` syscall.
    ///
    /// On success this function will not return, and otherwise it will return
    /// an error indicating why the exec (or another part of the setup of the
    /// `Command`) failed.
    ///
    /// `exec` not returning has the same implications as calling
    /// [`process::exit`] – no destructors on the current stack or any other
    /// thread’s stack will be run. Therefore, it is recommended to only call
    /// `exec` at a point where it is fine to not run any destructors. Note,
    /// that the `execvp` syscall independently guarantees that all memory is
    /// freed and all file descriptors with the `CLOEXEC` option (set by default
    /// on all file descriptors opened by the standard library) are closed.
    ///
    /// This function, unlike `spawn`, will **not** `fork` the process to create
    /// a new child. Like spawn, however, the default behavior for the stdio
    /// descriptors will be to inherited from the current process.
    ///
    /// # Notes
    ///
    /// The process may be in a "broken state" if this function returns in
    /// error. For example the working directory, environment variables, signal
    /// handling settings, various user/group information, or aspects of stdio
    /// file descriptors may have changed. If a "transactional spawn" is
    /// required to gracefully handle errors it is recommended to use the
    /// cross-platform `spawn` instead.
    #[stable(feature = "process_exec2", since = "1.9.0")]
    fn exec(&mut self) -> io::Error;

    /// Set executable argument
    ///
    /// Set the first process argument, `argv[0]`, to something other than the
    /// default executable path.
    #[stable(feature = "process_set_argv0", since = "1.45.0")]
    fn arg0<S>(&mut self, arg: S) -> &mut process::Command
    where
        S: AsRef<OsStr>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl CommandExt for process::Command {
    fn uid(
        &mut self,
        #[cfg(not(target_os = "vxworks"))] id: u32,
        #[cfg(target_os = "vxworks")] id: u16,
    ) -> &mut process::Command {
        self.as_inner_mut().uid(id);
        self
    }

    fn gid(
        &mut self,
        #[cfg(not(target_os = "vxworks"))] id: u32,
        #[cfg(target_os = "vxworks")] id: u16,
    ) -> &mut process::Command {
        self.as_inner_mut().gid(id);
        self
    }

    unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
    where
        F: FnMut() -> io::Result<()> + Send + Sync + 'static,
    {
        self.as_inner_mut().pre_exec(Box::new(f));
        self
    }

    fn exec(&mut self) -> io::Error {
        self.as_inner_mut().exec(sys::process::Stdio::Inherit)
    }

    fn arg0<S>(&mut self, arg: S) -> &mut process::Command
    where
        S: AsRef<OsStr>,
    {
        self.as_inner_mut().set_arg_0(arg.as_ref());
        self
    }
}

/// Unix-specific extensions to [`process::ExitStatus`].
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ExitStatusExt {
    /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
    /// a process.
    #[stable(feature = "exit_status_from", since = "1.12.0")]
    fn from_raw(raw: i32) -> Self;

    /// If the process was terminated by a signal, returns that signal.
    ///
    /// Ie, if `WIFSIGNALED`, this returns `WTERMSIG`.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn signal(&self) -> Option<i32>;

    /// If the process was terminated by a signal, says whether it dumped core.
    #[unstable(feature = "unix_process_wait_more", issue = "none")]
    fn core_dumped(&self) -> bool;

    /// If the process was stopped by a signal, returns that signal.
    ///
    /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`.  This is only possible if the status came from
    /// a `wait` system call which was passed `WUNTRACED`, was then converted into an `ExitStatus`.
    #[unstable(feature = "unix_process_wait_more", issue = "none")]
    fn stopped_signal(&self) -> Option<i32>;

    /// Whether the process was continued from a stopped status.
    ///
    /// Ie, `WIFCONTINUED`.  This is only possible if the status came from a `wait` system call
    /// which was passed `WCONTINUED`, was then converted into an `ExitStatus`.
    #[unstable(feature = "unix_process_wait_more", issue = "none")]
    fn continued(&self) -> bool;

    /// Returns the underlying raw `wait` status.
    #[unstable(feature = "unix_process_wait_more", issue = "none")]
    fn into_raw(self) -> i32;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl ExitStatusExt for process::ExitStatus {
    fn from_raw(raw: i32) -> Self {
        process::ExitStatus::from_inner(From::from(raw))
    }

    fn signal(&self) -> Option<i32> {
        self.as_inner().signal()
    }

    fn core_dumped(&self) -> bool {
        self.as_inner().core_dumped()
    }

    fn stopped_signal(&self) -> Option<i32> {
        self.as_inner().stopped_signal()
    }

    fn continued(&self) -> bool {
        self.as_inner().continued()
    }

    fn into_raw(self) -> i32 {
        self.as_inner().into_raw().into()
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawFd for process::Stdio {
    unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
        let fd = sys::fd::FileDesc::new(fd);
        let io = sys::process::Stdio::Fd(fd);
        process::Stdio::from_inner(io)
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStdin {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStdout {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStderr {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStdin {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStdout {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStderr {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

/// Returns the OS-assigned process identifier associated with this process's parent.
#[stable(feature = "unix_ppid", since = "1.27.0")]
pub fn parent_id() -> u32 {
    crate::sys::os::getppid()
}
<commit_msg>Replace `Ie` with `In other words`<commit_after>//! Unix-specific extensions to primitives in the `std::process` module.

#![stable(feature = "rust1", since = "1.0.0")]

use crate::ffi::OsStr;
use crate::io;
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::process;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};

/// Unix-specific extensions to the [`process::Command`] builder.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait CommandExt {
    /// Sets the child process's user ID. This translates to a
    /// `setuid` call in the child process. Failure in the `setuid`
    /// call will cause the spawn to fail.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn uid(
        &mut self,
        #[cfg(not(target_os = "vxworks"))] id: u32,
        #[cfg(target_os = "vxworks")] id: u16,
    ) -> &mut process::Command;

    /// Similar to `uid`, but sets the group ID of the child process. This has
    /// the same semantics as the `uid` field.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn gid(
        &mut self,
        #[cfg(not(target_os = "vxworks"))] id: u32,
        #[cfg(target_os = "vxworks")] id: u16,
    ) -> &mut process::Command;

    /// Schedules a closure to be run just before the `exec` function is
    /// invoked.
    ///
    /// The closure is allowed to return an I/O error whose OS error code will
    /// be communicated back to the parent and returned as an error from when
    /// the spawn was requested.
    ///
    /// Multiple closures can be registered and they will be called in order of
    /// their registration. If a closure returns `Err` then no further closures
    /// will be called and the spawn operation will immediately return with a
    /// failure.
    ///
    /// # Notes and Safety
    ///
    /// This closure will be run in the context of the child process after a
    /// `fork`. This primarily means that any modifications made to memory on
    /// behalf of this closure will **not** be visible to the parent process.
    /// This is often a very constrained environment where normal operations
    /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
    /// other threads perhaps still running when the `fork` was run).
    ///
    /// This also means that all resources such as file descriptors and
    /// memory-mapped regions got duplicated. It is your responsibility to make
    /// sure that the closure does not violate library invariants by making
    /// invalid use of these duplicates.
    ///
    /// When this closure is run, aspects such as the stdio file descriptors and
    /// working directory have successfully been changed, so output to these
    /// locations may not appear where intended.
    #[stable(feature = "process_pre_exec", since = "1.34.0")]
    unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
    where
        F: FnMut() -> io::Result<()> + Send + Sync + 'static;

    /// Schedules a closure to be run just before the `exec` function is
    /// invoked.
    ///
    /// This method is stable and usable, but it should be unsafe. To fix
    /// that, it got deprecated in favor of the unsafe [`pre_exec`].
    ///
    /// [`pre_exec`]: CommandExt::pre_exec
    #[stable(feature = "process_exec", since = "1.15.0")]
    #[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")]
    fn before_exec<F>(&mut self, f: F) -> &mut process::Command
    where
        F: FnMut() -> io::Result<()> + Send + Sync + 'static,
    {
        unsafe { self.pre_exec(f) }
    }

    /// Performs all the required setup by this `Command`, followed by calling
    /// the `execvp` syscall.
    ///
    /// On success this function will not return, and otherwise it will return
    /// an error indicating why the exec (or another part of the setup of the
    /// `Command`) failed.
    ///
    /// `exec` not returning has the same implications as calling
    /// [`process::exit`] – no destructors on the current stack or any other
    /// thread’s stack will be run. Therefore, it is recommended to only call
    /// `exec` at a point where it is fine to not run any destructors. Note,
    /// that the `execvp` syscall independently guarantees that all memory is
    /// freed and all file descriptors with the `CLOEXEC` option (set by default
    /// on all file descriptors opened by the standard library) are closed.
    ///
    /// This function, unlike `spawn`, will **not** `fork` the process to create
    /// a new child. Like spawn, however, the default behavior for the stdio
    /// descriptors will be to inherited from the current process.
    ///
    /// # Notes
    ///
    /// The process may be in a "broken state" if this function returns in
    /// error. For example the working directory, environment variables, signal
    /// handling settings, various user/group information, or aspects of stdio
    /// file descriptors may have changed. If a "transactional spawn" is
    /// required to gracefully handle errors it is recommended to use the
    /// cross-platform `spawn` instead.
    #[stable(feature = "process_exec2", since = "1.9.0")]
    fn exec(&mut self) -> io::Error;

    /// Set executable argument
    ///
    /// Set the first process argument, `argv[0]`, to something other than the
    /// default executable path.
    #[stable(feature = "process_set_argv0", since = "1.45.0")]
    fn arg0<S>(&mut self, arg: S) -> &mut process::Command
    where
        S: AsRef<OsStr>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl CommandExt for process::Command {
    fn uid(
        &mut self,
        #[cfg(not(target_os = "vxworks"))] id: u32,
        #[cfg(target_os = "vxworks")] id: u16,
    ) -> &mut process::Command {
        self.as_inner_mut().uid(id);
        self
    }

    fn gid(
        &mut self,
        #[cfg(not(target_os = "vxworks"))] id: u32,
        #[cfg(target_os = "vxworks")] id: u16,
    ) -> &mut process::Command {
        self.as_inner_mut().gid(id);
        self
    }

    unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
    where
        F: FnMut() -> io::Result<()> + Send + Sync + 'static,
    {
        self.as_inner_mut().pre_exec(Box::new(f));
        self
    }

    fn exec(&mut self) -> io::Error {
        self.as_inner_mut().exec(sys::process::Stdio::Inherit)
    }

    fn arg0<S>(&mut self, arg: S) -> &mut process::Command
    where
        S: AsRef<OsStr>,
    {
        self.as_inner_mut().set_arg_0(arg.as_ref());
        self
    }
}

/// Unix-specific extensions to [`process::ExitStatus`].
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ExitStatusExt {
    /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
    /// a process.
    #[stable(feature = "exit_status_from", since = "1.12.0")]
    fn from_raw(raw: i32) -> Self;

    /// If the process was terminated by a signal, returns that signal.
    ///
    /// In other words, if `WIFSIGNALED`, this returns `WTERMSIG`.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn signal(&self) -> Option<i32>;

    /// If the process was terminated by a signal, says whether it dumped core.
    #[unstable(feature = "unix_process_wait_more", issue = "none")]
    fn core_dumped(&self) -> bool;

    /// If the process was stopped by a signal, returns that signal.
    ///
    /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`.  This is only possible if the status came from
    /// a `wait` system call which was passed `WUNTRACED`, was then converted into an `ExitStatus`.
    #[unstable(feature = "unix_process_wait_more", issue = "none")]
    fn stopped_signal(&self) -> Option<i32>;

    /// Whether the process was continued from a stopped status.
    ///
    /// Ie, `WIFCONTINUED`.  This is only possible if the status came from a `wait` system call
    /// which was passed `WCONTINUED`, was then converted into an `ExitStatus`.
    #[unstable(feature = "unix_process_wait_more", issue = "none")]
    fn continued(&self) -> bool;

    /// Returns the underlying raw `wait` status.
    #[unstable(feature = "unix_process_wait_more", issue = "none")]
    fn into_raw(self) -> i32;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl ExitStatusExt for process::ExitStatus {
    fn from_raw(raw: i32) -> Self {
        process::ExitStatus::from_inner(From::from(raw))
    }

    fn signal(&self) -> Option<i32> {
        self.as_inner().signal()
    }

    fn core_dumped(&self) -> bool {
        self.as_inner().core_dumped()
    }

    fn stopped_signal(&self) -> Option<i32> {
        self.as_inner().stopped_signal()
    }

    fn continued(&self) -> bool {
        self.as_inner().continued()
    }

    fn into_raw(self) -> i32 {
        self.as_inner().into_raw().into()
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawFd for process::Stdio {
    unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
        let fd = sys::fd::FileDesc::new(fd);
        let io = sys::process::Stdio::Fd(fd);
        process::Stdio::from_inner(io)
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStdin {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStdout {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStderr {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStdin {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStdout {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStderr {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

/// Returns the OS-assigned process identifier associated with this process's parent.
#[stable(feature = "unix_ppid", since = "1.27.0")]
pub fn parent_id() -> u32 {
    crate::sys::os::getppid()
}
<|endoftext|>


<commit_before>extern crate sha1;

use std::cmp::{Ordering, Ord, Eq, PartialEq, PartialOrd};

struct Node {
    node: String,
    hash: i32
}

impl Eq for Node {
}

#[allow(unused_variables)]
impl PartialOrd for Node {
    fn partial_cmp(&self, other: &Node) -> Option<Ordering> {
        None
    }
}

#[allow(unused_variables)]
impl PartialEq for Node {
    fn eq(&self, other: &Node) -> bool {
        false
    }
}

impl Ord for Node {
    fn cmp(&self, other: &Node) -> Ordering {
        if self.hash >= other.hash {
            Ordering::Equal
        } else {
            Ordering::Less
        }
    }
}

type TickArray = Vec<Node>;

pub struct HashRing {
    default_spots: i32,
    ticks: TickArray,
    length: usize
}

#[allow(exceeding_bitshifts)]
impl HashRing {
    pub fn new(n: i32) -> HashRing {
        let tk = Vec::new();
        let h = HashRing{default_spots: n, ticks: tk, length: 0};
        h
    }

    pub fn add(&mut self, n: String, s: i32) {
        let spots = self.default_spots * s;
        let mut hash = sha1::Sha1::new();

        for i in 0..spots {
            hash.reset();
            let ts: String = i.to_string();

            let b = format!("{}:{}", n, ts);
            hash.update(b.as_bytes());
            let hash_bytes = hash.digest().bytes();
            let _node = Node{node: n.clone(), hash: ((hash_bytes[19] as u32) | (hash_bytes[18] as u32) << 8 | (hash_bytes[17] as u32) << 16 | (hash_bytes[16] as u32) << 24) as i32};
            self.ticks.push(_node);
        }
    }

    pub fn bake(&mut self) {
        self.ticks.sort();
        self.length = self.ticks.len();
    }

    pub fn hash(&self, s: String) -> String {
        let mut h = sha1::Sha1::new();
        h.reset();
        h.update(s.as_bytes());
        let hash_bytes = h.digest().bytes();
//        let v = (hash_bytes[19] | hash_bytes[18] << 8 | hash_bytes[17] << 16 | hash_bytes[16] << 24) as i32;
        let v = ((hash_bytes[19] as u32) | (hash_bytes[18] as u32) << 8 | (hash_bytes[17] as u32) << 16 | (hash_bytes[16] as u32) << 24) as i32;

        let _node = Node{hash: v, node: "".to_string()};
        let nd: &Node;
        match self.ticks.binary_search_by(|v| v.cmp(&_node)) {
            Ok(i) => {
                nd = &self.ticks[i];
            },
            _ => {
                nd = &self.ticks[0];
            }
        }
        nd.node.clone()
    }
}

#[test]
fn test_simple() {
    let mut ring = HashRing::new(255);
    ring.add("node1".to_string(), 1);
    ring.add("node2".to_string(), 1);
    ring.add("node3".to_string(), 1);
    ring.bake();
    let i = ring.hash("liutaihua".to_string());
    println!("======= str: liutaihua, hash res:{:?} ========", i);
}

#[test]
fn bench() {
    let mut ring = HashRing::new(255);
    ring.add("node1".to_string(), 1);
    ring.add("node2".to_string(), 1);
    ring.add("node3".to_string(), 1);
    ring.add("node4".to_string(), 1);
    ring.add("node5".to_string(), 1);

    ring.bake();
    for i in 0..1000 {
        println!("{}", ring.hash(i.to_string()));
    }
}
<commit_msg>add test<commit_after>extern crate sha1;

use std::cmp::{Ordering, Ord, Eq, PartialEq, PartialOrd};

struct Node {
    node: String,
    hash: i32
}

impl Eq for Node {
}

#[allow(unused_variables)]
impl PartialOrd for Node {
    fn partial_cmp(&self, other: &Node) -> Option<Ordering> {
        None
    }
}

#[allow(unused_variables)]
impl PartialEq for Node {
    fn eq(&self, other: &Node) -> bool {
        false
    }
}

impl Ord for Node {
    fn cmp(&self, other: &Node) -> Ordering {
        if self.hash >= other.hash {
            Ordering::Equal
        } else {
            Ordering::Less
        }
    }
}

type TickArray = Vec<Node>;

pub struct HashRing {
    default_spots: i32,
    ticks: TickArray,
    length: usize
}

#[allow(exceeding_bitshifts)]
impl HashRing {
    pub fn new(n: i32) -> HashRing {
        let tk = Vec::new();
        let h = HashRing{default_spots: n, ticks: tk, length: 0};
        h
    }

    pub fn add(&mut self, n: String, s: i32) {
        let spots = self.default_spots * s;
        let mut hash = sha1::Sha1::new();

        for i in 0..spots {
            hash.reset();
            let ts: String = i.to_string();

            let b = format!("{}:{}", n, ts);
            hash.update(b.as_bytes());
            let hash_bytes = hash.digest().bytes();
            let _node = Node{node: n.clone(), hash: ((hash_bytes[19] as u32) | (hash_bytes[18] as u32) << 8 | (hash_bytes[17] as u32) << 16 | (hash_bytes[16] as u32) << 24) as i32};
            self.ticks.push(_node);
        }
    }

    pub fn bake(&mut self) {
        self.ticks.sort();
        self.length = self.ticks.len();
    }

    pub fn hash(&self, s: String) -> String {
        let mut h = sha1::Sha1::new();
        h.reset();
        h.update(s.as_bytes());
        let hash_bytes = h.digest().bytes();
//        let v = (hash_bytes[19] | hash_bytes[18] << 8 | hash_bytes[17] << 16 | hash_bytes[16] << 24) as i32;
        let v = ((hash_bytes[19] as u32) | (hash_bytes[18] as u32) << 8 | (hash_bytes[17] as u32) << 16 | (hash_bytes[16] as u32) << 24) as i32;

        let _node = Node{hash: v, node: "".to_string()};
//        let nd: &Node;
        match self.ticks.binary_search_by(|v| v.cmp(&_node)) {
            Ok(i) => {
                let nd = &self.ticks[i];
                nd.node.clone()
            },
            _ => {
//                nd = &self.ticks[0];
                panic!("failed binary search")
            }
        }
    }
}

#[test]
fn test_simple() {
    let mut ring = HashRing::new(255);
    ring.add("node1".to_string(), 1);
    ring.add("node2".to_string(), 1);
    ring.add("node3".to_string(), 1);
    ring.bake();
    let i = ring.hash("liutaihua".to_string());
    println!("======= str: liutaihua, hash res:{:?} ========", i);
}

#[test]
fn bench() {
    let mut ring = HashRing::new(255);
    ring.add("node1".to_string(), 1);
    ring.add("node2".to_string(), 1);
    ring.add("node3".to_string(), 1);
    ring.add("node4".to_string(), 1);
    ring.add("node5".to_string(), 1);

    ring.bake();
    for i in 0..1000 {
        println!("{}", ring.hash(i.to_string()));
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::fmt;

use base::ast::{Type, Kind};
use typecheck::TcType;
use base::ast;
use base::interner::InternedStr;
use substitution::{Substitution, Substitutable};

#[derive(Debug, PartialEq)]
pub enum Error {
    KindMismatch(Rc<Kind>, Rc<Kind>),
    StringError(&'static str)
}
use self::Error::*;

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            KindMismatch(ref expected, ref actual) => write!(f, "Kind mismatch\nExpected: {}\nFound: {}", expected, actual),
            StringError(s) => write!(f, "{}", s)
        }
    }
}

type Result<T> = ::std::result::Result<T, Error>;

impl Substitutable for Kind {
    fn new(x: u32) -> Kind {
        Kind::Variable(x)
    }
    fn get_var(&self) -> Option<u32> {
        match *self {
            Kind::Variable(var) => Some(var),
            _ => None
        }
    }
}

pub struct KindCheck<'a> {
    variables: &'a mut [TcType],
    info: &'a (Fn(InternedStr) -> Option<&'a TcType> + 'a),
    subs: Substitution<Kind>,
    star: Rc<Kind>
}

fn walk_move_kind<F>(kind: Rc<Kind>, f: &mut F) -> Rc<Kind>
    where F: FnMut(&Kind) -> Option<Rc<Kind>> {
    match walk_move_kind2(&kind, f) {
        Some(kind) => kind,
        None => kind
    }
}
fn walk_move_kind2<F>(kind: &Rc<Kind>, f: &mut F) -> Option<Rc<Kind>>
    where F: FnMut(&Kind) -> Option<Rc<Kind>> {
    let new = f(kind);
    let new2 = {
        let kind = new.as_ref().map(|k| &**k).unwrap_or(kind);
        match *kind {
            Kind::Function(ref a, ref r) => {
                match (walk_move_kind2(a, f), walk_move_kind2(r, f)) {
                    (Some(a), Some(r)) => Some(Rc::new(Kind::Function(a, r))),
                    (Some(a), None) => Some(Rc::new(Kind::Function(a, r.clone()))),
                    (None, Some(r)) => Some(Rc::new(Kind::Function(a.clone(), r))),
                    (None, None) => None
                }
            }
            Kind::Star | Kind::Variable(_) => None
        }
    };
    new2.or(new)
}

impl <'a> KindCheck<'a> {

    pub fn new(info: &'a Fn(InternedStr) -> Option<&'a TcType>, variables: &'a mut [TcType], id: u32) -> KindCheck<'a> {
        let subs = Substitution::new();
        subs.var_id.set(id);
        KindCheck {
            variables: variables,
            info: info,
            subs: subs,
            star: Rc::new(Kind::Star)
        }
    }

    fn find(&mut self, id: InternedStr) -> Result<Rc<Kind>> {
        let kind = self.variables.iter()
            .find(|var| match ***var { Type::Generic(ref other) => other.id == id, _ => false })
            .map(|t| t.kind().clone())
            .or_else(|| {
                (self.info)(id)
                    .and_then(|typ| {
                        match **typ {
                            Type::Data(_, ref args) => {
                                let mut kind = self.star.clone();
                                for arg in args.iter().rev() {
                                    kind = Rc::new(Kind::Function(arg.kind(), kind));
                                }
                                Some(kind)
                            }
                            _ => None
                        }
                    })
            })
            .map(|t| Ok(t))
            .unwrap_or_else(|| Ok(Rc::new(self.subs.variable_for(id))));
        debug!("Find kind: {} => {}", id, kind.as_ref().unwrap());
        kind
    }

    pub fn kindcheck_type(&mut self, typ: &mut TcType) -> Result<Kind> {
        debug!("Kindcheck {}", typ);
        let (kind, t) = try!(self.kindcheck(typ));
        let subs = &mut self.subs;
        let mut f = |typ| ast::walk_move_type(typ, &mut |typ| {
            match *typ {
                Type::Variable(ref var) => {
                    let mut kind = var.kind.clone();
                    kind = subs.update_kind(kind);
                    Some(Type::variable(ast::TypeVariable { id: var.id, kind: kind }))
                }
                Type::Generic(ref var) => {
                    let mut kind = var.kind.clone();
                    kind = subs.update_kind(kind);
                    Some(Type::generic(ast::Generic { id: var.id, kind: kind }))
                }
                _ => None
            }
        });
        *typ  = f(t);
        for typ in self.variables.iter_mut() {
            *typ = f(typ.clone());
        }
        debug!("Done {:?}", typ);
        Ok((*kind).clone())
    }

    fn kindcheck(&mut self, typ: &TcType) -> Result<(Rc<Kind>, TcType)> {
        match **typ {
            Type::Generic(ref gen) => {
                let mut gen = gen.clone();
                gen.kind = try!(self.find(gen.id));
                Ok((gen.kind.clone(), Type::generic(gen)))
            }
            Type::Variable(_) => {
                panic!("kindcheck called on variable")
            }
            Type::Builtin(_) => Ok((self.star.clone(), typ.clone())),
            Type::Array(ref typ) => {
                let (kind, typ) = try!(self.kindcheck(typ));
                let star = self.star.clone();
                try!(self.unify(&star, kind));
                Ok((self.star.clone(), Type::array(typ)))
            }
            Type::App(ref f, ref r) => {
                let (kind, f) = try!(self.kindcheck(f));
                let kind_fn = Rc::new(Kind::Function(self.subs.new_kind(), self.subs.new_kind()));
                let kind = try!(self.unify(&kind_fn, kind));
                match *kind {
                    Kind::Function(ref arg, ref ret) => {
                        let (arg_kind, r) = try!(self.kindcheck(r));
                        try!(self.unify(&arg, arg_kind));
                        Ok((ret.clone(), Type::app(f, r)))
                    }
                    _ => panic!("Expected kind function")
                }
            }
            Type::Data(ast::TypeConstructor::Builtin(_), _) => {
                panic!("Builtin with arguments")
            }
            Type::Data(ast::TypeConstructor::Data(ctor), ref args) => {
                let mut kind = try!(self.find(ctor));
                let mut new_args = Vec::new();
                for arg in args {
                    let f = Rc::new(Kind::Function(self.subs.new_kind(), self.subs.new_kind()));
                    kind = try!(self.unify(&f, kind));
                    kind = match *kind {
                        Kind::Function(ref arg_kind, ref ret) => {
                            let (actual, new_arg) = try!(self.kindcheck(arg));
                            new_args.push(new_arg);
                            try!(self.unify(arg_kind, actual));
                            ret.clone()
                        }
                        _ => return Err(StringError("Expected kind: a -> a"))
                    };
                }
                Ok((kind, Type::data(ast::TypeConstructor::Data(ctor), new_args)))
            }
            Type::Function(ref args, ref ret) => {
                let (kind, arg) = try!(self.kindcheck(&args[0]));
                let star = self.star.clone();
                try!(self.unify(&star, kind));
                let (kind, ret) = try!(self.kindcheck(ret));
                let star = self.star.clone();
                let new_kind = try!(self.unify(&star, kind));
                Ok((new_kind, Type::function(vec![arg], ret)))
            }
            Type::Variants(ref variants) => {
                let variants = try!(variants.iter().map(|variant| {
                    let (kind, typ) = try!(self.kindcheck(&variant.1));
                    let star = self.star.clone();
                    try!(self.unify(&star, kind));
                    Ok((variant.0, typ))
                }).collect());
                Ok((self.star.clone(), Type::variants(variants)))
            }
            Type::Record(ref fields) => {
                let fields = try!(fields.iter().map(|field| {
                    let (kind, typ) = try!(self.kindcheck(&field.typ));
                    let star = self.star.clone();
                    try!(self.unify(&star, kind));
                    Ok(ast::Field { name: field.name, typ: typ })
                }).collect());
                Ok((self.star.clone(), Type::record(fields)))
            }
        }
    }

    fn unify(&mut self, expected: &Rc<Kind>, mut actual: Rc<Kind>) -> Result<Rc<Kind>> {
        debug!("Unify {:?} <=> {:?}", expected, actual);
        if self.unify_(expected, &actual) {
            Ok(self.subs.update_kind(actual))
        }
        else {
            let mut expected = expected.clone();
            expected = self.subs.update_kind(expected);
            actual = self.subs.update_kind(actual);
            Err(KindMismatch(expected, actual))
        }
    }
    fn unify_(&self, expected: &Kind, actual: &Kind) -> bool {
        match (expected, actual) {
            (&Kind::Variable(l), r) => {
                self.union(l, r);
                true
            }
            (l, &Kind::Variable(r)) => {
                self.union(r, l);
                true
            }
            (&Kind::Function(ref l1, ref l2), &Kind::Function(ref r1, ref r2)) => {
                self.unify_(l1, r1) && self.unify_(l2, r2)
            }
            (l, r) => l == r
        }
    }

    fn union(&self, id: u32, typ: &Kind) {
        {
            let id_type = self.subs.find_type_for_var(id);
            let other_type = self.subs.real(typ);
            if id_type.map(|x| x == other_type).unwrap_or(Kind::Variable(id.clone()) == *other_type) {
                return
            }
        }
        let map: &mut _ = unsafe { &mut *self.subs.map.get() };
        //Always make sure the mapping is from a higher variable to a lower
        //This way the resulting variables are always equal to any variables in the globals
        //declaration
        match *typ {
            Kind::Variable(other_id) if id < other_id => map.insert(other_id, Box::new(Kind::Variable(id))),
            _ => map.insert(id, Box::new(typ.clone()))
        };
    }
}

impl Substitution<Kind> {
    fn new_kind(&mut self) -> Rc<ast::Kind> {
        Rc::new(self.new_var())
    }

    fn update_kind(&mut self, kind: Rc<Kind>) -> Rc<Kind> {
        walk_move_kind(kind, &mut |kind| {
            match *kind {
                Kind::Variable(id) => self.find_type_for_var(id).map(|t| Rc::new(t.clone())),
                _ => None
            }
        })
    }
}
<commit_msg>Add occurs check to the kindchecker<commit_after>use std::rc::Rc;
use std::fmt;

use base::ast::{Type, Kind};
use typecheck::TcType;
use base::ast;
use base::interner::InternedStr;
use substitution::{Substitution, Substitutable};

#[derive(Debug, PartialEq)]
pub enum Error {
    KindMismatch(Rc<Kind>, Rc<Kind>),
    StringError(&'static str)
}
use self::Error::*;

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            KindMismatch(ref expected, ref actual) => write!(f, "Kind mismatch\nExpected: {}\nFound: {}", expected, actual),
            StringError(s) => write!(f, "{}", s)
        }
    }
}

type Result<T> = ::std::result::Result<T, Error>;

impl Substitutable for Kind {
    fn new(x: u32) -> Kind {
        Kind::Variable(x)
    }
    fn get_var(&self) -> Option<u32> {
        match *self {
            Kind::Variable(var) => Some(var),
            _ => None
        }
    }
}

pub struct KindCheck<'a> {
    variables: &'a mut [TcType],
    info: &'a (Fn(InternedStr) -> Option<&'a TcType> + 'a),
    subs: Substitution<Kind>,
    star: Rc<Kind>
}

fn walk_move_kind<F>(kind: Rc<Kind>, f: &mut F) -> Rc<Kind>
    where F: FnMut(&Kind) -> Option<Rc<Kind>> {
    match walk_move_kind2(&kind, f) {
        Some(kind) => kind,
        None => kind
    }
}
fn walk_move_kind2<F>(kind: &Rc<Kind>, f: &mut F) -> Option<Rc<Kind>>
    where F: FnMut(&Kind) -> Option<Rc<Kind>> {
    let new = f(kind);
    let new2 = {
        let kind = new.as_ref().map(|k| &**k).unwrap_or(kind);
        match *kind {
            Kind::Function(ref a, ref r) => {
                match (walk_move_kind2(a, f), walk_move_kind2(r, f)) {
                    (Some(a), Some(r)) => Some(Rc::new(Kind::Function(a, r))),
                    (Some(a), None) => Some(Rc::new(Kind::Function(a, r.clone()))),
                    (None, Some(r)) => Some(Rc::new(Kind::Function(a.clone(), r))),
                    (None, None) => None
                }
            }
            Kind::Star | Kind::Variable(_) => None
        }
    };
    new2.or(new)
}

impl <'a> KindCheck<'a> {

    pub fn new(info: &'a Fn(InternedStr) -> Option<&'a TcType>, variables: &'a mut [TcType], id: u32) -> KindCheck<'a> {
        let subs = Substitution::new();
        subs.var_id.set(id);
        KindCheck {
            variables: variables,
            info: info,
            subs: subs,
            star: Rc::new(Kind::Star)
        }
    }

    fn find(&mut self, id: InternedStr) -> Result<Rc<Kind>> {
        let kind = self.variables.iter()
            .find(|var| match ***var { Type::Generic(ref other) => other.id == id, _ => false })
            .map(|t| t.kind().clone())
            .or_else(|| {
                (self.info)(id)
                    .and_then(|typ| {
                        match **typ {
                            Type::Data(_, ref args) => {
                                let mut kind = self.star.clone();
                                for arg in args.iter().rev() {
                                    kind = Rc::new(Kind::Function(arg.kind(), kind));
                                }
                                Some(kind)
                            }
                            _ => None
                        }
                    })
            })
            .map(|t| Ok(t))
            .unwrap_or_else(|| Ok(Rc::new(self.subs.variable_for(id))));
        debug!("Find kind: {} => {}", id, kind.as_ref().unwrap());
        kind
    }

    pub fn kindcheck_type(&mut self, typ: &mut TcType) -> Result<Kind> {
        debug!("Kindcheck {}", typ);
        let (kind, t) = try!(self.kindcheck(typ));
        let subs = &mut self.subs;
        let mut f = |typ| ast::walk_move_type(typ, &mut |typ| {
            match *typ {
                Type::Variable(ref var) => {
                    let mut kind = var.kind.clone();
                    kind = subs.update_kind(kind);
                    Some(Type::variable(ast::TypeVariable { id: var.id, kind: kind }))
                }
                Type::Generic(ref var) => {
                    let mut kind = var.kind.clone();
                    kind = subs.update_kind(kind);
                    Some(Type::generic(ast::Generic { id: var.id, kind: kind }))
                }
                _ => None
            }
        });
        *typ  = f(t);
        for typ in self.variables.iter_mut() {
            *typ = f(typ.clone());
        }
        debug!("Done {:?}", typ);
        Ok((*kind).clone())
    }

    fn kindcheck(&mut self, typ: &TcType) -> Result<(Rc<Kind>, TcType)> {
        match **typ {
            Type::Generic(ref gen) => {
                let mut gen = gen.clone();
                gen.kind = try!(self.find(gen.id));
                Ok((gen.kind.clone(), Type::generic(gen)))
            }
            Type::Variable(_) => {
                panic!("kindcheck called on variable")
            }
            Type::Builtin(_) => Ok((self.star.clone(), typ.clone())),
            Type::Array(ref typ) => {
                let (kind, typ) = try!(self.kindcheck(typ));
                let star = self.star.clone();
                try!(self.unify(&star, kind));
                Ok((self.star.clone(), Type::array(typ)))
            }
            Type::App(ref f, ref r) => {
                let (kind, f) = try!(self.kindcheck(f));
                let kind_fn = Rc::new(Kind::Function(self.subs.new_kind(), self.subs.new_kind()));
                let kind = try!(self.unify(&kind_fn, kind));
                match *kind {
                    Kind::Function(ref arg, ref ret) => {
                        let (arg_kind, r) = try!(self.kindcheck(r));
                        try!(self.unify(&arg, arg_kind));
                        Ok((ret.clone(), Type::app(f, r)))
                    }
                    _ => panic!("Expected kind function")
                }
            }
            Type::Data(ast::TypeConstructor::Builtin(_), _) => {
                panic!("Builtin with arguments")
            }
            Type::Data(ast::TypeConstructor::Data(ctor), ref args) => {
                let mut kind = try!(self.find(ctor));
                let mut new_args = Vec::new();
                for arg in args {
                    let f = Rc::new(Kind::Function(self.subs.new_kind(), self.subs.new_kind()));
                    kind = try!(self.unify(&f, kind));
                    kind = match *kind {
                        Kind::Function(ref arg_kind, ref ret) => {
                            let (actual, new_arg) = try!(self.kindcheck(arg));
                            new_args.push(new_arg);
                            try!(self.unify(arg_kind, actual));
                            ret.clone()
                        }
                        _ => return Err(StringError("Expected kind: a -> a"))
                    };
                }
                Ok((kind, Type::data(ast::TypeConstructor::Data(ctor), new_args)))
            }
            Type::Function(ref args, ref ret) => {
                let (kind, arg) = try!(self.kindcheck(&args[0]));
                let star = self.star.clone();
                try!(self.unify(&star, kind));
                let (kind, ret) = try!(self.kindcheck(ret));
                let star = self.star.clone();
                let new_kind = try!(self.unify(&star, kind));
                Ok((new_kind, Type::function(vec![arg], ret)))
            }
            Type::Variants(ref variants) => {
                let variants = try!(variants.iter().map(|variant| {
                    let (kind, typ) = try!(self.kindcheck(&variant.1));
                    let star = self.star.clone();
                    try!(self.unify(&star, kind));
                    Ok((variant.0, typ))
                }).collect());
                Ok((self.star.clone(), Type::variants(variants)))
            }
            Type::Record(ref fields) => {
                let fields = try!(fields.iter().map(|field| {
                    let (kind, typ) = try!(self.kindcheck(&field.typ));
                    let star = self.star.clone();
                    try!(self.unify(&star, kind));
                    Ok(ast::Field { name: field.name, typ: typ })
                }).collect());
                Ok((self.star.clone(), Type::record(fields)))
            }
        }
    }

    fn unify(&mut self, expected: &Rc<Kind>, mut actual: Rc<Kind>) -> Result<Rc<Kind>> {
        debug!("Unify {:?} <=> {:?}", expected, actual);
        if self.unify_(expected, &actual) {
            Ok(self.subs.update_kind(actual))
        }
        else {
            let mut expected = expected.clone();
            expected = self.subs.update_kind(expected);
            actual = self.subs.update_kind(actual);
            Err(KindMismatch(expected, actual))
        }
    }
    fn unify_(&self, expected: &Kind, actual: &Kind) -> bool {
        match (expected, actual) {
            (&Kind::Variable(l), &Kind::Variable(r)) if l == r => true,
            (&Kind::Variable(l), r) => {
                self.union(l, r)
            }
            (l, &Kind::Variable(r)) => {
                self.union(r, l)
            }
            (&Kind::Function(ref l1, ref l2), &Kind::Function(ref r1, ref r2)) => {
                self.unify_(l1, r1) && self.unify_(l2, r2)
            }
            (l, r) => l == r
        }
    }

    fn union(&self, id: u32, typ: &Kind) -> bool {
        if self.occurs(id, typ) {
            return false
        }
        {
            let id_type = self.subs.find_type_for_var(id);
            let other_type = self.subs.real(typ);
            if id_type.map(|x| x == other_type).unwrap_or(Kind::Variable(id.clone()) == *other_type) {
                return true
            }
        }
        let map: &mut _ = unsafe { &mut *self.subs.map.get() };
        //Always make sure the mapping is from a higher variable to a lower
        //This way the resulting variables are always equal to any variables in the globals
        //declaration
        match *typ {
            Kind::Variable(other_id) if id < other_id => map.insert(other_id, Box::new(Kind::Variable(id))),
            _ => map.insert(id, Box::new(typ.clone()))
        };
        true
    }

    fn occurs(&self, var: u32, kind: &Kind) -> bool {
        let kind = self.subs.real(kind);
        match *kind {
            Kind::Variable(other) => var == other,
            Kind::Function(ref a, ref r) => self.occurs(var, a) || self.occurs(var, r),
            Kind::Star => false
        }
    }
}

impl Substitution<Kind> {
    fn new_kind(&mut self) -> Rc<ast::Kind> {
        Rc::new(self.new_var())
    }

    fn update_kind(&mut self, kind: Rc<Kind>) -> Rc<Kind> {
        walk_move_kind(kind, &mut |kind| {
            match *kind {
                Kind::Variable(id) => self.find_type_for_var(id).map(|t| Rc::new(t.clone())),
                _ => None
            }
        })
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fs::create_dir;
use std::io::ErrorKind;
use std::path::Path;
use std::path::PathBuf;

use devicemapper::DM;
use uuid::Uuid;

use super::super::super::engine::{Engine, Pool, Redundancy, RenameAction};

use super::super::engine::{HasName, HasUuid};
use super::super::errors::{EngineError, EngineResult, ErrorEnum};
use super::super::structures::Table;
use super::super::types::PoolUuid;

use super::pool::StratPool;
use super::setup::find_all;

#[derive(Debug, PartialEq, Eq)]
pub enum DevOwnership {
    Ours(Uuid),
    Unowned,
    Theirs,
}

#[derive(Debug)]
pub struct StratEngine {
    pools: Table<StratPool>,
}

impl StratEngine {
    pub fn initialize() -> EngineResult<StratEngine> {
        if let Err(err) = create_dir("/dev/stratis") {
            if err.kind() != ErrorKind::AlreadyExists {
                return Err(From::from(err));
            }
        }

        Ok(StratEngine { pools: Table::new() })
    }

    /// Teardown Stratis, preparatory to a shutdown.
    pub fn teardown(self) -> EngineResult<()> {
        for pool in self.pools.empty() {
            try!(pool.teardown());
        }
        Ok(())
    }
}

impl Engine for StratEngine {
    fn configure_simulator(&mut self, _denominator: u32) -> EngineResult<()> {
        Ok(()) // we're not the simulator and not configurable, so just say ok
    }

    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   redundancy: Option<u16>,
                   force: bool)
                   -> EngineResult<(PoolUuid, Vec<PathBuf>)> {

        let redundancy = calculate_redundancy!(redundancy);

        if self.pools.contains_name(name) {
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, name.into()));
        }

        let dm = try!(DM::new());
        let pool = try!(StratPool::initialize(name, &dm, blockdev_paths, redundancy, force));
        let bdev_devnodes = pool.block_devs.devnodes();

        let uuid = pool.uuid().clone();
        self.pools.insert(pool);
        Ok((uuid, bdev_devnodes))
    }

    fn destroy_pool(&mut self, uuid: &PoolUuid) -> EngineResult<bool> {
        destroy_pool!{self; uuid}
    }

    fn rename_pool(&mut self, uuid: &PoolUuid, new_name: &str) -> EngineResult<RenameAction> {
        rename_pool!{self; uuid; new_name}
    }

    fn get_pool(&mut self, uuid: &PoolUuid) -> Option<&mut Pool> {
        get_pool!(self; uuid)
    }

    fn check(&mut self) -> () {
        check_engine!(self);
    }

    // TODO: Fix this method so that it actually sets up the engine.
    fn setup(&mut self) -> EngineResult<()> {
        let pools = try!(find_all());
        if !pools.is_empty() {
            let err_msg = "Stratis was already run once, can not yet reconstruct state";
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, err_msg.into()));
        }
        Ok(())
    }
}
<commit_msg>Fix up an over-long import<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fs::create_dir;
use std::io::ErrorKind;
use std::path::Path;
use std::path::PathBuf;

use devicemapper::DM;
use uuid::Uuid;

use super::super::engine::{Engine, HasName, HasUuid, Pool};
use super::super::errors::{EngineError, EngineResult, ErrorEnum};
use super::super::structures::Table;
use super::super::types::{PoolUuid, Redundancy, RenameAction};

use super::pool::StratPool;
use super::setup::find_all;

#[derive(Debug, PartialEq, Eq)]
pub enum DevOwnership {
    Ours(Uuid),
    Unowned,
    Theirs,
}

#[derive(Debug)]
pub struct StratEngine {
    pools: Table<StratPool>,
}

impl StratEngine {
    pub fn initialize() -> EngineResult<StratEngine> {
        if let Err(err) = create_dir("/dev/stratis") {
            if err.kind() != ErrorKind::AlreadyExists {
                return Err(From::from(err));
            }
        }

        Ok(StratEngine { pools: Table::new() })
    }

    /// Teardown Stratis, preparatory to a shutdown.
    pub fn teardown(self) -> EngineResult<()> {
        for pool in self.pools.empty() {
            try!(pool.teardown());
        }
        Ok(())
    }
}

impl Engine for StratEngine {
    fn configure_simulator(&mut self, _denominator: u32) -> EngineResult<()> {
        Ok(()) // we're not the simulator and not configurable, so just say ok
    }

    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   redundancy: Option<u16>,
                   force: bool)
                   -> EngineResult<(PoolUuid, Vec<PathBuf>)> {

        let redundancy = calculate_redundancy!(redundancy);

        if self.pools.contains_name(name) {
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, name.into()));
        }

        let dm = try!(DM::new());
        let pool = try!(StratPool::initialize(name, &dm, blockdev_paths, redundancy, force));
        let bdev_devnodes = pool.block_devs.devnodes();

        let uuid = pool.uuid().clone();
        self.pools.insert(pool);
        Ok((uuid, bdev_devnodes))
    }

    fn destroy_pool(&mut self, uuid: &PoolUuid) -> EngineResult<bool> {
        destroy_pool!{self; uuid}
    }

    fn rename_pool(&mut self, uuid: &PoolUuid, new_name: &str) -> EngineResult<RenameAction> {
        rename_pool!{self; uuid; new_name}
    }

    fn get_pool(&mut self, uuid: &PoolUuid) -> Option<&mut Pool> {
        get_pool!(self; uuid)
    }

    fn check(&mut self) -> () {
        check_engine!(self);
    }

    // TODO: Fix this method so that it actually sets up the engine.
    fn setup(&mut self) -> EngineResult<()> {
        let pools = try!(find_all());
        if !pools.is_empty() {
            let err_msg = "Stratis was already run once, can not yet reconstruct state";
            return Err(EngineError::Engine(ErrorEnum::AlreadyExists, err_msg.into()));
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! # io
//!
//! IO helper functions
//!

#[cfg(test)]
#[path = "io_test.rs"]
mod io_test;

use fsio::file::modify_file;
use fsio::path::from_path::FromPath;
use fsio::path::{canonicalize_or, get_temporary_file_path};
use glob::glob;
use ignore::WalkBuilder;
use std::collections::HashSet;
use std::fs::File;
use std::io;
use std::path::PathBuf;

pub(crate) fn create_text_file(text: &str, extension: &str) -> String {
    let file_path = get_temporary_file_path(extension);

    match fsio::file::write_text_file(&file_path, text) {
        Ok(_) => file_path,
        Err(error) => {
            error!("Unable to create file: {} {:#?}", &file_path, &error);
            panic!("Unable to create file, error: {}", error);
        }
    }
}

pub(crate) fn create_file(
    write_content: &Fn(&mut File) -> io::Result<()>,
    extension: &str,
) -> String {
    let file_path = get_temporary_file_path(extension);

    match modify_file(&file_path, write_content, false) {
        Ok(_) => file_path,
        Err(error) => {
            error!("Unable to write to file: {} {:#?}", &file_path, &error);
            panic!("Unable to write to file, error: {}", error);
        }
    }
}

pub(crate) fn delete_file(file: &str) {
    match fsio::file::delete(file) {
        Ok(_) => debug!("File deleted: {}", &file),
        Err(error) => debug!("Unable to delete file: {} {:#?}", &file, error),
    }
}

pub(crate) fn write_text_file(file_path: &str, text: &str) -> bool {
    match fsio::file::write_text_file(file_path, text) {
        Ok(_) => true,
        Err(_) => false,
    }
}

pub(crate) fn read_text_file(file_path: &PathBuf) -> String {
    debug!("Opening file: {:#?}", &file_path);

    match fsio::file::read_text_file(file_path) {
        Ok(content) => content,
        Err(error) => panic!("Unable to read file: {:?} error: {:#?}", file_path, error),
    }
}

pub(crate) fn get_path_list(
    glob_pattern: &str,
    include_files: bool,
    include_dirs: bool,
    ignore_type: Option<String>,
) -> Vec<String> {
    let mut path_list = vec![];
    match glob(glob_pattern) {
        Ok(paths) => {
            for entry in paths {
                match entry {
                    Ok(path) => {
                        if (include_dirs && path.is_dir()) || (include_files && path.is_file()) {
                            let mut value_string: String = FromPath::from_path(&path);
                            value_string = value_string.replace("\\", "/");
                            if !value_string.starts_with("./") {
                                value_string.insert_str(0, "./");
                            }

                            path_list.push(value_string);
                        }
                    }
                    Err(error) => {
                        error!(
                            "Error while iterating over path entries of glob: {}, error: {:#?}",
                            glob_pattern, error
                        );
                        return vec![];
                    }
                }
            }
        }
        Err(error) => {
            error!(
                "Error while running glob: {}, error: {:#?}",
                glob_pattern, error
            );
            return vec![];
        }
    }

    if !path_list.is_empty() {
        if let Some(ignore_type_value) = ignore_type {
            let mut included_paths = HashSet::new();

            match ignore_type_value.as_str() {
                "git" => {
                    for entry in WalkBuilder::new("./")
                        .hidden(true)
                        .parents(true)
                        .git_ignore(true)
                        .git_exclude(true)
                        .build()
                    {
                        match entry {
                            Ok(path) => {
                                let mut value_string: String = FromPath::from_path(&path.path());
                                value_string = value_string.replace("\\", "/");
                                included_paths.insert(value_string);
                            }
                            Err(error) => error!(
                                "Error while running git ignore path checks, error: {:#?}",
                                error
                            ),
                        }
                    }
                }
                _ => error!("Unsupported ignore type: {}", &ignore_type_value),
            };

            if included_paths.is_empty() {
                path_list.clear();
            } else {
                let org_path_list = path_list;
                path_list = vec![];
                for path in org_path_list {
                    if included_paths.contains(&path) {
                        path_list.push(path);
                    }
                }
            }
        }
    }

    path_list
}

pub(crate) fn canonicalize_to_string(path_string: &str) -> String {
    #[cfg(not(windows))]
    {
        canonicalize_or(path_string, path_string)
    }
    #[cfg(windows)]
    {
        match dunce::canonicalize(path_string) {
            Ok(value) => FromPath::from_path(&value),
            Err(_) => path_string.to_string(),
        }
    }
}
<commit_msg>fix windows build<commit_after>//! # io
//!
//! IO helper functions
//!

#[cfg(test)]
#[path = "io_test.rs"]
mod io_test;

use fsio::file::modify_file;
use fsio::path as fsio_path;
use fsio::path::from_path::FromPath;
use glob::glob;
use ignore::WalkBuilder;
use std::collections::HashSet;
use std::fs::File;
use std::io;
use std::path::PathBuf;

pub(crate) fn create_text_file(text: &str, extension: &str) -> String {
    let file_path = fsio_path::get_temporary_file_path(extension);

    match fsio::file::write_text_file(&file_path, text) {
        Ok(_) => file_path,
        Err(error) => {
            error!("Unable to create file: {} {:#?}", &file_path, &error);
            panic!("Unable to create file, error: {}", error);
        }
    }
}

pub(crate) fn create_file(
    write_content: &Fn(&mut File) -> io::Result<()>,
    extension: &str,
) -> String {
    let file_path = fsio_path::get_temporary_file_path(extension);

    match modify_file(&file_path, write_content, false) {
        Ok(_) => file_path,
        Err(error) => {
            error!("Unable to write to file: {} {:#?}", &file_path, &error);
            panic!("Unable to write to file, error: {}", error);
        }
    }
}

pub(crate) fn delete_file(file: &str) {
    match fsio::file::delete(file) {
        Ok(_) => debug!("File deleted: {}", &file),
        Err(error) => debug!("Unable to delete file: {} {:#?}", &file, error),
    }
}

pub(crate) fn write_text_file(file_path: &str, text: &str) -> bool {
    match fsio::file::write_text_file(file_path, text) {
        Ok(_) => true,
        Err(_) => false,
    }
}

pub(crate) fn read_text_file(file_path: &PathBuf) -> String {
    debug!("Opening file: {:#?}", &file_path);

    match fsio::file::read_text_file(file_path) {
        Ok(content) => content,
        Err(error) => panic!("Unable to read file: {:?} error: {:#?}", file_path, error),
    }
}

pub(crate) fn get_path_list(
    glob_pattern: &str,
    include_files: bool,
    include_dirs: bool,
    ignore_type: Option<String>,
) -> Vec<String> {
    let mut path_list = vec![];
    match glob(glob_pattern) {
        Ok(paths) => {
            for entry in paths {
                match entry {
                    Ok(path) => {
                        if (include_dirs && path.is_dir()) || (include_files && path.is_file()) {
                            let mut value_string: String = FromPath::from_path(&path);
                            value_string = value_string.replace("\\", "/");
                            if !value_string.starts_with("./") {
                                value_string.insert_str(0, "./");
                            }

                            path_list.push(value_string);
                        }
                    }
                    Err(error) => {
                        error!(
                            "Error while iterating over path entries of glob: {}, error: {:#?}",
                            glob_pattern, error
                        );
                        return vec![];
                    }
                }
            }
        }
        Err(error) => {
            error!(
                "Error while running glob: {}, error: {:#?}",
                glob_pattern, error
            );
            return vec![];
        }
    }

    if !path_list.is_empty() {
        if let Some(ignore_type_value) = ignore_type {
            let mut included_paths = HashSet::new();

            match ignore_type_value.as_str() {
                "git" => {
                    for entry in WalkBuilder::new("./")
                        .hidden(true)
                        .parents(true)
                        .git_ignore(true)
                        .git_exclude(true)
                        .build()
                    {
                        match entry {
                            Ok(path) => {
                                let mut value_string: String = FromPath::from_path(&path.path());
                                value_string = value_string.replace("\\", "/");
                                included_paths.insert(value_string);
                            }
                            Err(error) => error!(
                                "Error while running git ignore path checks, error: {:#?}",
                                error
                            ),
                        }
                    }
                }
                _ => error!("Unsupported ignore type: {}", &ignore_type_value),
            };

            if included_paths.is_empty() {
                path_list.clear();
            } else {
                let org_path_list = path_list;
                path_list = vec![];
                for path in org_path_list {
                    if included_paths.contains(&path) {
                        path_list.push(path);
                    }
                }
            }
        }
    }

    path_list
}

pub(crate) fn canonicalize_to_string(path_string: &str) -> String {
    #[cfg(not(windows))]
    {
        fsio_path::canonicalize_or(path_string, path_string)
    }
    #[cfg(windows)]
    {
        match dunce::canonicalize(path_string) {
            Ok(value) => FromPath::from_path(&value),
            Err(_) => path_string.to_string(),
        }
    }
}
<|endoftext|>


<commit_before>
use std::default::Default;
use std::path::{Path, PathBuf};
use std::fs;
use std::fs::File;
use std::io;
use std::io::ErrorKind;
use std::env;
use std::io::Read;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;
use toml;

#[derive(Debug)]
pub enum ConfigError {
    IoError(io::Error),
    TomlParserErrors(Vec<toml::ParserError>),
    InvalidFieldName(String),
    InvalidFieldType(& 'static str, String),
}

impl Error for ConfigError {
    fn description(&self) -> &str {
        match *self {
            ConfigError::IoError(ref e) => e.description(),
            ConfigError::TomlParserErrors(ref v) => v[0].description(),
            ConfigError::InvalidFieldName(_) => "Invalid field name",
            ConfigError::InvalidFieldType(_, _) => "Invalid field type",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            ConfigError::IoError(ref e) => Some(e),
            ConfigError::TomlParserErrors(ref v) => Some(&v[0]),
            _ => None
        }
    }
}

impl Display for ConfigError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            ConfigError::IoError(ref e) => write!(f, "IO Error: {}", e),
            ConfigError::TomlParserErrors(ref v) => write!(f, "Parser Error ({} total): {}",
                    v.len(), v[0]),
            ConfigError::InvalidFieldName(ref s) => write!(f, "Invalid feild name: {}", s),
            ConfigError::InvalidFieldType(expected, ref got) => write!(f, "Expected type {} got {}", expected, got),
        }
    }
}

impl From<io::Error> for ConfigError {
    fn from(e: io::Error) -> ConfigError {
        ConfigError::IoError(e)
    }
}

#[derive(RustcDecodable, Debug)]
pub struct Config {
    pub show_ascii: bool,
    pub show_linenum: bool,
    pub line_width: Option<u32>
}

impl Default for Config {
    fn default() -> Config {
        Config {
            show_ascii: true,
            show_linenum: true,
            line_width: None,
        }
    }
}

macro_rules! try_unwrap_toml {
    ($e:expr, $t:ident) => ({
        match $e {
            toml::Value::$t(v) => v,
            other => {
                return Err(ConfigError::InvalidFieldType(stringify!($t), format!("{}", other)))
            }
        }
    })
}

macro_rules! decode_toml {
    ($obj:expr, $name:ident, $table:expr, $toml_type:ident, $map_func:expr) => ({
        $obj.$name = match $table.remove(stringify!($name)) {
            Some(val) => $map_func(try_unwrap_toml!(val, $toml_type)),
            None => $obj.$name
        };
    });
    ($obj:expr, $name:ident, $table:expr, $toml_type:ident) => ({
        $obj.$name = match $table.remove(stringify!($name)) {
            Some(val) => try_unwrap_toml!(val, $toml_type),
            None => $obj.$name
        };
    });
}

impl Config {
    pub fn get_config_usage() -> &'static str {
        "
The supported configuration options with their default values:
    show_ascii=true        Shows an ascii representation in the right hand side
    show_linenum=true      Shows the byte offset in the left hand side
    line_width=0           The number of bytes per line, 0 meaning auto-wrap

The configuration can be set in the rex.conf file located in the
$XDG_CONFIG_HOME path (usually, ~/.config/rex/rex.conf). Additionally,
properties can be set on the commandline as rex -C show_ascii=false.
"
    }

    fn apply_toml(&mut self, mut t: toml::Table) -> Result<(), ConfigError> {
        decode_toml!(self, show_ascii, t, Boolean);
        decode_toml!(self, show_linenum, t, Boolean);
        decode_toml!(self, line_width, t, Integer, |i| if i > 0 { Some(i as u32) } else { None });
        if let Some((key, _)) = t.into_iter().next() {
            Err(ConfigError::InvalidFieldName(key))
        } else {
            Ok(())
        }
    }

    pub fn set_from_string(&mut self, set_line: &str) -> Result<(), ConfigError> {
        let mut parser = toml::Parser::new(&set_line);
        if let Some(table) = parser.parse() {
            return self.apply_toml(table);
        }
        Err(ConfigError::TomlParserErrors(parser.errors))
    }

    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Config, ConfigError> {
        let mut s = String::new();
        let mut f = try!(File::open(path));
        try!(f.read_to_string(&mut s));
        let mut config: Config = Default::default();
        try!(config.set_from_string(&s));
        Ok(config)
    }

    fn get_config_path() -> PathBuf {
        let mut p = PathBuf::new();
        p.push(env::var("XDG_CONFIG_HOME").unwrap_or_else(
                |_| env::var("HOME").unwrap_or("/".into()) + "/.config"
            ));
        p.join("rex").join("rex.conf")
    }

    pub fn open_default() -> Result<Config, ConfigError> {
        let config_path = Config::get_config_path();
        match fs::metadata(config_path) {
            Ok(_) => Config::from_file(Config::get_config_path()),
            Err(ref err) if err.kind() == ErrorKind::NotFound => Ok(Default::default()),
            Err(err) => Err(err.into()),
        }
    }
}
<commit_msg>Added basic support for serializing the config to toml Values<commit_after>
use std::default::Default;
use std::path::{Path, PathBuf};
use std::fs;
use std::fs::File;
use std::io;
use std::io::ErrorKind;
use std::env;
use std::io::Read;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;
use toml;

#[derive(Debug)]
pub enum ConfigError {
    IoError(io::Error),
    TomlParserErrors(Vec<toml::ParserError>),
    InvalidFieldName(String),
    InvalidFieldType(& 'static str, String),
}

impl Error for ConfigError {
    fn description(&self) -> &str {
        match *self {
            ConfigError::IoError(ref e) => e.description(),
            ConfigError::TomlParserErrors(ref v) => v[0].description(),
            ConfigError::InvalidFieldName(_) => "Invalid field name",
            ConfigError::InvalidFieldType(_, _) => "Invalid field type",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            ConfigError::IoError(ref e) => Some(e),
            ConfigError::TomlParserErrors(ref v) => Some(&v[0]),
            _ => None
        }
    }
}

impl Display for ConfigError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            ConfigError::IoError(ref e) => write!(f, "IO Error: {}", e),
            ConfigError::TomlParserErrors(ref v) => write!(f, "Parser Error ({} total): {}",
                    v.len(), v[0]),
            ConfigError::InvalidFieldName(ref s) => write!(f, "Invalid feild name: {}", s),
            ConfigError::InvalidFieldType(expected, ref got) => write!(f, "Expected type {} got {}", expected, got),
        }
    }
}

impl From<io::Error> for ConfigError {
    fn from(e: io::Error) -> ConfigError {
        ConfigError::IoError(e)
    }
}

#[derive(RustcDecodable, Debug)]
pub struct Config {
    pub show_ascii: bool,
    pub show_linenum: bool,
    pub line_width: Option<u32>
}

impl Default for Config {
    fn default() -> Config {
        Config {
            show_ascii: true,
            show_linenum: true,
            line_width: None,
        }
    }
}

macro_rules! try_unwrap_toml {
    ($e:expr, $t:ident) => ({
        match $e {
            toml::Value::$t(v) => v,
            other => {
                return Err(ConfigError::InvalidFieldType(stringify!($t), format!("{}", other)))
            }
        }
    })
}

macro_rules! decode_toml {
    ($obj:expr, $name:ident, $table:expr, $toml_type:ident, $map_func:expr) => ({
        $obj.$name = match $table.remove(stringify!($name)) {
            Some(val) => $map_func(try_unwrap_toml!(val, $toml_type)),
            None => $obj.$name
        };
    });
    ($obj:expr, $name:ident, $table:expr, $toml_type:ident) => ({
        $obj.$name = match $table.remove(stringify!($name)) {
            Some(val) => try_unwrap_toml!(val, $toml_type),
            None => $obj.$name
        };
    });
}

macro_rules! create_toml {
    ($obj:expr, $pos:ident, $name:ident, $toml_type:ident, $map_func:expr) => ({
        if ($pos == 0) {
            return Some((stringify!($name), toml::Value::$toml_type($map_func($obj.$name))))
        } else {
            $pos -= 1;
        }
    });
    ($obj:expr, $pos:ident, $name:ident, $toml_type:ident) => ({
        if ($pos == 0) {
            return Some((stringify!($name), toml::Value::$toml_type($obj.$name)))
        } else {
            $pos -= 1;
        }
    });
}

impl Config {
    pub fn get_config_usage() -> &'static str {
        "
The supported configuration options with their default values:
    show_ascii=true        Shows an ascii representation in the right hand side
    show_linenum=true      Shows the byte offset in the left hand side
    line_width=0           The number of bytes per line, 0 meaning auto-wrap

The configuration can be set in the rex.conf file located in the
$XDG_CONFIG_HOME path (usually, ~/.config/rex/rex.conf). Additionally,
properties can be set on the commandline as rex -C show_ascii=false.
"
    }

    fn apply_toml(&mut self, mut t: toml::Table) -> Result<(), ConfigError> {
        decode_toml!(self, show_ascii, t, Boolean);
        decode_toml!(self, show_linenum, t, Boolean);
        decode_toml!(self, line_width, t, Integer, |i| if i > 0 { Some(i as u32) } else { None });
        if let Some((key, _)) = t.into_iter().next() {
            Err(ConfigError::InvalidFieldName(key))
        } else {
            Ok(())
        }
    }

    fn read_toml(&self, mut p: usize) -> Option<(&'static str, toml::Value)> {
        create_toml!(self, p, show_ascii, Boolean);
        create_toml!(self, p, show_linenum, Boolean);
        create_toml!(self, p, line_width, Integer, |opt_i| if let Some(i) = opt_i { i as i64 } else { 0 });
        None
    }

    pub fn values<'a>(&'a self) -> Values<'a> {
        Values {
            config: self,
            pos: 0,
        }
    }

    pub fn set_from_string(&mut self, set_line: &str) -> Result<(), ConfigError> {
        let mut parser = toml::Parser::new(&set_line);
        if let Some(table) = parser.parse() {
            return self.apply_toml(table);
        }
        Err(ConfigError::TomlParserErrors(parser.errors))
    }

    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Config, ConfigError> {
        let mut s = String::new();
        let mut f = try!(File::open(path));
        try!(f.read_to_string(&mut s));
        let mut config: Config = Default::default();
        try!(config.set_from_string(&s));
        Ok(config)
    }

    fn get_config_path() -> PathBuf {
        let mut p = PathBuf::new();
        p.push(env::var("XDG_CONFIG_HOME").unwrap_or_else(
                |_| env::var("HOME").unwrap_or("/".into()) + "/.config"
            ));
        p.join("rex").join("rex.conf")
    }

    pub fn open_default() -> Result<Config, ConfigError> {
        let config_path = Config::get_config_path();
        match fs::metadata(config_path) {
            Ok(_) => Config::from_file(Config::get_config_path()),
            Err(ref err) if err.kind() == ErrorKind::NotFound => Ok(Default::default()),
            Err(err) => Err(err.into()),
        }
    }
}

pub struct Values<'a> {
    config: &'a Config,
    pos: usize,
}

impl<'a> Iterator for Values<'a> {
    type Item = (&'static str, toml::Value);

    fn next(&mut self) -> Option<(&'static str, toml::Value)> {
        let pos = self.pos;
        self.pos += 1;
        self.config.read_toml(pos)
    }
}
<|endoftext|>