<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.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn signal(&self) -> Option<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()
    }
}

#[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>unix ExitStatus: Clarify docs for .signal()<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.
    ///
    /// Ie, if `WIFSIGNALED`, this returns `WTERMSIG`.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn signal(&self) -> Option<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()
    }
}

#[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>use std::collections::{BTreeMap, BTreeSet};

#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum Foo {
    A(&'static str),
    _B,
    _C,
}

// Gather all references from a mutable iterator and make sure Miri notices if
// using them is dangerous.
fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
    // Gather all those references.
    let mut refs: Vec<&mut T> = iter.collect();
    // Use them all. Twice, to be sure we got all interleavings.
    for r in refs.iter_mut() {
        std::mem::swap(dummy, r);
    }
    for r in refs {
        std::mem::swap(dummy, r);
    }
}

pub fn main() {
    let mut b = BTreeSet::new();
    b.insert(Foo::A("\'"));
    b.insert(Foo::A("/="));
    b.insert(Foo::A("#"));
    b.insert(Foo::A("0o"));
    assert!(b.remove(&Foo::A("/=")));
    assert!(!b.remove(&Foo::A("/=")));

    // Also test a lower-alignment type, where the NodeHeader overlaps with
    // the keys.
    let mut b = BTreeSet::new();
    b.insert(1024u16);
    b.insert(7u16);

    let mut b = BTreeMap::new();
    b.insert(format!("bar"), 1024);
    b.insert(format!("baz"), 7);
    for i in 0..60 {
        b.insert(format!("key{}", i), i);
    }
    test_all_refs(&mut 13, b.values_mut());
}
<commit_msg>test BTreeMap::drain_filter for leaks<commit_after>#![feature(btree_drain_filter)]
use std::collections::{BTreeMap, BTreeSet};
use std::mem;

#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum Foo {
    A(&'static str),
    _B,
    _C,
}

// Gather all references from a mutable iterator and make sure Miri notices if
// using them is dangerous.
fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
    // Gather all those references.
    let mut refs: Vec<&mut T> = iter.collect();
    // Use them all. Twice, to be sure we got all interleavings.
    for r in refs.iter_mut() {
        std::mem::swap(dummy, r);
    }
    for r in refs {
        std::mem::swap(dummy, r);
    }
}

pub fn main() {
    let mut b = BTreeSet::new();
    b.insert(Foo::A("\'"));
    b.insert(Foo::A("/="));
    b.insert(Foo::A("#"));
    b.insert(Foo::A("0o"));
    assert!(b.remove(&Foo::A("/=")));
    assert!(!b.remove(&Foo::A("/=")));

    // Also test a lower-alignment type, where the NodeHeader overlaps with
    // the keys.
    let mut b = BTreeSet::new();
    b.insert(1024u16);
    b.insert(7u16);

    let mut b = BTreeMap::new();
    b.insert(format!("bar"), 1024);
    b.insert(format!("baz"), 7);
    for i in 0..60 {
        b.insert(format!("key{}", i), i);
    }
    test_all_refs(&mut 13, b.values_mut());

    // Test forgetting the drain.
    let mut d = b.drain_filter(|_, i| *i < 30);
    d.next().unwrap();
    mem::forget(d);
}
<|endoftext|>


<commit_before>#![cfg(feature = "postgresql")]

extern crate postgres;
extern crate crypto;

use self::crypto::scrypt::{scrypt_simple,scrypt_check,ScryptParams};

use self::postgres::{Connection, TlsMode, Result as SQLResult};
use self::postgres::rows::Row;

pub struct Db(Connection);

use super::{Image,Tag,AnyWith,ImageBuilder,parse_tag};

impl Default for Db { // Чтобы Clippy не жаловался
    fn default() -> Self {
        Self::new()
    }
}

static POSTGRES_LOGIN : &'static str = "easy";
static POSTGRES_PASS : &'static str = "";

lazy_static! {
    static ref SCRYPT_PARAMS: ScryptParams = ScryptParams::new(10, 8, 1); // 10 сильно быстрее чем 14
}

impl Db {
    pub fn new() -> Self {
        let conn = Connection::connect(format!("postgres://{}:{}@localhost", POSTGRES_LOGIN, POSTGRES_PASS), TlsMode::None).unwrap();
        conn.batch_execute("CREATE EXTENSION IF NOT EXISTS citext;
                            CREATE TABLE IF NOT EXISTS images(
                                id SERIAL PRIMARY KEY,
                                name TEXT NOT NULL UNIQUE,
                                tags TEXT[] NOT NULL,
                                uploader TEXT,
                                score INT NOT NULL DEFAULT 0,

                                got_from TEXT,
                                original_link TEXT,
                                rating CHAR
                            );

                            CREATE TABLE IF NOT EXISTS users(
                                id SERIAL PRIMARY KEY,
                                name CITEXT UNIQUE NOT NULL,
                                pass TEXT NOT NULL
                            );").unwrap();
        Db(conn)
    }

    /// Сохранить картинку, сгенерировава имя из тэгов
    pub fn add_with_tags_name(&self, tags: &[String], ext: &str, uploader: &str) -> SQLResult<String> {
        let lastnum = self.0.query("SELECT id FROM images ORDER BY id DESC LIMIT 1", &[])?.get(0).get::<_, i32>("id");

        let name = format!("{}_{}.{}", lastnum + 1  , tags.join("_").replace("'","''"),ext);
        self.add_image(&ImageBuilder::new(&name, tags).uploader(uploader).finalize())?;
        Ok(name)
    }

    pub fn add_image(&self, image: &ImageBuilder) -> SQLResult<()> {
        self.0.execute("INSERT into images (name,
                                            tags,
                                            got_from,
                                            original_link,
                                            rating,
                                            uploader,
                                            score)
                       VALUES ($1,
                               $2,
                               $3,
                               $4,
                               $5,
                               $6,
                               $7) ON CONFLICT (name) DO UPDATE SET tags = $2, score = $7",
        &[&image.name,&image.tags,&image.got_from, &image.original_link,&image.rating.map(|x| x.to_string()), &image.uploader, &image.score]).unwrap();
        Ok(())
    }

    pub fn get_image(&self, id: i32) -> SQLResult<Image> {
        let row = self.0.query("SELECT * FROM images WHERE id = $1", &[&id])?;
        Ok(Db::extract_image(row.get(0)))
    }

    pub fn get_images<T: Into<Option<i32>>>(&self, take: T, skip: usize) -> SQLResult<Vec<Image>>{
        let take = match take.into() {
            Some(x) => x.to_string(),
            None    => "ALL".to_string()
        };

        Ok(self.0.query(&format!("SELECT * FROM images ORDER BY id DESC LIMIT {} OFFSET {}", take, skip as i32),&[])?
           .iter().fold(Vec::new(), |mut acc, row| {
               acc.push(Db::extract_image(row));
               acc
           }))
    }

    pub fn by_tags<T: Into<Option<i32>>>(&self, take: T, skip: usize, tags: &[String]) -> SQLResult<Vec<Image>> {
        let tags = tags.iter().map(|x| parse_tag(x)).collect::<Vec<_>>();
        let order = tags.iter().filter_map(|x| {
            match *x {
                Tag::OrderBy(ref by, ref ascdesc) => {
                    Some(format!("{:?}", by).to_lowercase() + " " + &format!("{:?}", ascdesc).to_uppercase())
                },
                _   => None
            }
        }).collect::<Vec<_>>();
        let order = match order.last() {
            Some(t) => t,
            None    => "id DESC"
        };

        let q = tags.clone().iter().map(|t| {
            match *t {
                Tag::Include(ref incl) => format!(r"tags @> ARRAY['{}']", incl),
                Tag::Exclude(ref excl) => format!(r"NOT tags @> ARRAY['{}']", excl),
                Tag::AnyWith(ref x) => match *x {
                    AnyWith::Before(ref bef) => format!(r"(SELECT bool_or(tag ~ '^{}') FROM unnest(tags) t (tag))", bef),
                    AnyWith::After(ref aft) => format!(r"(SELECT bool_or(tag ~ '{}$') FROM unnest(tags) t (tag))", aft),
                },
                Tag::Rating(ref r) => {
                    let mut s = "(".to_string();
                    for tg in r {
                        s.push_str(&format!("rating = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::From(ref f) => {
                    let mut s = "(".to_string();
                    for tg in f {
                        s.push_str(&format!("got_from = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::Uploader(ref u) => {
                    let mut s = "(".to_string();
                    for tg in u {
                        s.push_str(&format!("uploader = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },
                Tag::OrderBy(_,_) => {String::new()}
            }
        }).filter(|x| !x.is_empty()).collect::<Vec<_>>().join(" AND ");
        let q = if !q.is_empty() {
            format!("WHERE {}", q)
        } else {
            String::new()
        };

        let take = match take.into() {
            Some(x) => x.to_string(),
            None    => "ALL".to_string()
        };

        Ok(self.0.query(&format!("SELECT * FROM images {} ORDER BY {} LIMIT {} OFFSET {}", q, order, take, skip),&[])?
           .iter().fold(Vec::new(), |mut acc, row| {
               acc.push(Db::extract_image(row));
               acc
           }))
    }

    pub fn delete_image(&self, id: i32) -> SQLResult<String> {
        let name = self.0.query("SELECT * FROM images WHERE id = $1", &[&id])?.get(0).get::<_,String>("name");
        self.0.execute("DELETE FROM images WHERE id = $1", &[&id])?;
        Ok(name)
    }

    // true - всё хорошо, false - пользователь уже существует
    pub fn add_user(&self, login: &str, pass: &str) -> SQLResult<bool> {
        if self.0.query("SELECT * FROM users WHERE name = $1", &[&login])?.is_empty() && login.to_lowercase() != "sync" {
            let pass = scrypt_simple(pass, &SCRYPT_PARAMS).unwrap();

            self.0.execute("INSERT INTO users (name,pass) VALUES ($1,$2)", &[&login, &pass])?;
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Result показывает ошибки в базе, Option - существует пользователь или нет
    pub fn check_user(&self, login: &str, pass: &str) -> SQLResult<Option<bool>> {
        let pass_hash = self.0.query("SELECT * FROM USERS WHERE name = $1", &[&login])?;
        if pass_hash.is_empty() {
            Ok(None)
        } else {
            let pass_hash = pass_hash.get(0).get::<_, String>("pass");
            Ok(Some(scrypt_check(pass, &pass_hash).unwrap()))
        }
    }

    fn extract_image(row: Row) -> Image {
        Image{
            id: row.get("id"),
            name: row.get("name"),
            tags: row.get("tags"),
            got_from: row.get::<_, Option<String>>("got_from"),
            original_link: row.get::<_, Option<String>>("original_link"),
            rating: row.get::<_,Option<String>>("rating").map(|x| x.to_string().chars().collect::<Vec<_>>()[0]),
            uploader: row.get::<_,Option<String>>("uploader"),
            score: row.get::<_,i32>("score")
        }
    }
}
<commit_msg>Не ломается, если картинки с ID не существует<commit_after>#![cfg(feature = "postgresql")]

extern crate postgres;
extern crate crypto;

use self::crypto::scrypt::{scrypt_simple,scrypt_check,ScryptParams};

use self::postgres::{Connection, TlsMode, Result as SQLResult};
use self::postgres::rows::Row;

pub struct Db(Connection);

use super::{Image,Tag,AnyWith,ImageBuilder,parse_tag};

impl Default for Db { // Чтобы Clippy не жаловался
    fn default() -> Self {
        Self::new()
    }
}

static POSTGRES_LOGIN : &'static str = "easy";
static POSTGRES_PASS : &'static str = "";

lazy_static! {
    static ref SCRYPT_PARAMS: ScryptParams = ScryptParams::new(10, 8, 1); // 10 сильно быстрее чем 14
}

impl Db {
    pub fn new() -> Self {
        let conn = Connection::connect(format!("postgres://{}:{}@localhost", POSTGRES_LOGIN, POSTGRES_PASS), TlsMode::None).unwrap();
        conn.batch_execute("CREATE EXTENSION IF NOT EXISTS citext;
                            CREATE TABLE IF NOT EXISTS images(
                                id SERIAL PRIMARY KEY,
                                name TEXT NOT NULL UNIQUE,
                                tags TEXT[] NOT NULL,
                                uploader TEXT,
                                score INT NOT NULL DEFAULT 0,

                                got_from TEXT,
                                original_link TEXT,
                                rating CHAR
                            );

                            CREATE TABLE IF NOT EXISTS users(
                                id SERIAL PRIMARY KEY,
                                name CITEXT UNIQUE NOT NULL,
                                pass TEXT NOT NULL
                            );").unwrap();
        Db(conn)
    }

    /// Сохранить картинку, сгенерировава имя из тэгов
    pub fn add_with_tags_name(&self, tags: &[String], ext: &str, uploader: &str) -> SQLResult<String> {
        let lastnum = self.0.query("SELECT id FROM images ORDER BY id DESC LIMIT 1", &[])?.get(0).get::<_, i32>("id");

        let name = format!("{}_{}.{}", lastnum + 1  , tags.join("_").replace("'","''"),ext);
        self.add_image(&ImageBuilder::new(&name, tags).uploader(uploader).finalize())?;
        Ok(name)
    }

    pub fn add_image(&self, image: &ImageBuilder) -> SQLResult<()> {
        self.0.execute("INSERT into images (name,
                                            tags,
                                            got_from,
                                            original_link,
                                            rating,
                                            uploader,
                                            score)
                       VALUES ($1,
                               $2,
                               $3,
                               $4,
                               $5,
                               $6,
                               $7) ON CONFLICT (name) DO UPDATE SET tags = $2, score = $7",
        &[&image.name,&image.tags,&image.got_from, &image.original_link,&image.rating.map(|x| x.to_string()), &image.uploader, &image.score]).unwrap();
        Ok(())
    }

    pub fn get_image(&self, id: i32) -> SQLResult<Option<Image>> {
        let rows = self.0.query("SELECT * FROM images WHERE id = $1", &[&id])?;
        Ok(if !rows.is_empty() {
            Some(Db::extract_image(rows.get(0)))
        } else {
            None
        })
    }

    pub fn get_images<T: Into<Option<i32>>>(&self, take: T, skip: usize) -> SQLResult<Vec<Image>>{
        let take = match take.into() {
            Some(x) => x.to_string(),
            None    => "ALL".to_string()
        };

        Ok(self.0.query(&format!("SELECT * FROM images ORDER BY id DESC LIMIT {} OFFSET {}", take, skip as i32),&[])?
           .iter().fold(Vec::new(), |mut acc, row| {
               acc.push(Db::extract_image(row));
               acc
           }))
    }

    pub fn by_tags<T: Into<Option<i32>>>(&self, take: T, skip: usize, tags: &[String]) -> SQLResult<Vec<Image>> {
        let tags = tags.iter().map(|x| parse_tag(x)).collect::<Vec<_>>();
        let order = tags.iter().filter_map(|x| {
            match *x {
                Tag::OrderBy(ref by, ref ascdesc) => {
                    Some(format!("{:?}", by).to_lowercase() + " " + &format!("{:?}", ascdesc).to_uppercase())
                },
                _   => None
            }
        }).collect::<Vec<_>>();
        let order = match order.last() {
            Some(t) => t,
            None    => "id DESC"
        };

        let q = tags.clone().iter().map(|t| {
            match *t {
                Tag::Include(ref incl) => format!(r"tags @> ARRAY['{}']", incl),
                Tag::Exclude(ref excl) => format!(r"NOT tags @> ARRAY['{}']", excl),
                Tag::AnyWith(ref x) => match *x {
                    AnyWith::Before(ref bef) => format!(r"(SELECT bool_or(tag ~ '^{}') FROM unnest(tags) t (tag))", bef),
                    AnyWith::After(ref aft) => format!(r"(SELECT bool_or(tag ~ '{}$') FROM unnest(tags) t (tag))", aft),
                },
                Tag::Rating(ref r) => {
                    let mut s = "(".to_string();
                    for tg in r {
                        s.push_str(&format!("rating = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::From(ref f) => {
                    let mut s = "(".to_string();
                    for tg in f {
                        s.push_str(&format!("got_from = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::Uploader(ref u) => {
                    let mut s = "(".to_string();
                    for tg in u {
                        s.push_str(&format!("uploader = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },
                Tag::OrderBy(_,_) => {String::new()}
            }
        }).filter(|x| !x.is_empty()).collect::<Vec<_>>().join(" AND ");
        let q = if !q.is_empty() {
            format!("WHERE {}", q)
        } else {
            String::new()
        };

        let take = match take.into() {
            Some(x) => x.to_string(),
            None    => "ALL".to_string()
        };

        Ok(self.0.query(&format!("SELECT * FROM images {} ORDER BY {} LIMIT {} OFFSET {}", q, order, take, skip),&[])?
           .iter().fold(Vec::new(), |mut acc, row| {
               acc.push(Db::extract_image(row));
               acc
           }))
    }

    pub fn delete_image(&self, id: i32) -> SQLResult<String> {
        let name = self.0.query("SELECT * FROM images WHERE id = $1", &[&id])?.get(0).get::<_,String>("name");
        self.0.execute("DELETE FROM images WHERE id = $1", &[&id])?;
        Ok(name)
    }

    // true - всё хорошо, false - пользователь уже существует
    pub fn add_user(&self, login: &str, pass: &str) -> SQLResult<bool> {
        if self.0.query("SELECT * FROM users WHERE name = $1", &[&login])?.is_empty() && login.to_lowercase() != "sync" {
            let pass = scrypt_simple(pass, &SCRYPT_PARAMS).unwrap();

            self.0.execute("INSERT INTO users (name,pass) VALUES ($1,$2)", &[&login, &pass])?;
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Result показывает ошибки в базе, Option - существует пользователь или нет
    pub fn check_user(&self, login: &str, pass: &str) -> SQLResult<Option<bool>> {
        let pass_hash = self.0.query("SELECT * FROM USERS WHERE name = $1", &[&login])?;
        if pass_hash.is_empty() {
            Ok(None)
        } else {
            let pass_hash = pass_hash.get(0).get::<_, String>("pass");
            Ok(Some(scrypt_check(pass, &pass_hash).unwrap()))
        }
    }

    fn extract_image(row: Row) -> Image {
        Image{
            id: row.get("id"),
            name: row.get("name"),
            tags: row.get("tags"),
            got_from: row.get::<_, Option<String>>("got_from"),
            original_link: row.get::<_, Option<String>>("original_link"),
            rating: row.get::<_,Option<String>>("rating").map(|x| x.to_string().chars().collect::<Vec<_>>()[0]),
            uploader: row.get::<_,Option<String>>("uploader"),
            score: row.get::<_,i32>("score")
        }
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::fmt;

use log::trace;

use rustc_span::DUMMY_SP;

use crate::*;

/// Details of premature program termination.
pub enum TerminationInfo {
    Exit(i64),
    Abort(Option<String>),
    UnsupportedInIsolation(String),
    ExperimentalUb { msg: String, url: String },
    Deadlock,
}

impl fmt::Debug for TerminationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use TerminationInfo::*;
        match self {
            Exit(code) =>
                write!(f, "the evaluated program completed with exit code {}", code),
            Abort(None) =>
                write!(f, "the evaluated program aborted execution"),
            Abort(Some(msg)) =>
                write!(f, "the evaluated program aborted execution: {}", msg),
            UnsupportedInIsolation(msg) =>
                write!(f, "{}", msg),
            ExperimentalUb { msg, .. } =>
                write!(f, "{}", msg),
            Deadlock =>
                write!(f, "the evaluated program deadlocked"),
        }
    }
}

impl MachineStopType for TerminationInfo {}

/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
    PoppedTrackedPointerTag(Item),
    CreatedAlloc(AllocId),
    FreedAlloc(AllocId),
}

/// Emit a custom diagnostic without going through the miri-engine machinery
pub fn report_error<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
    mut e: InterpErrorInfo<'tcx>,
) -> Option<i64> {
    use InterpError::*;

    let (title, helps) = match &e.kind {
        MachineStop(info) => {
            let info = info.downcast_ref::<TerminationInfo>().expect("invalid MachineStop payload");
            use TerminationInfo::*;
            let title = match info {
                Exit(code) => return Some(*code),
                Abort(_) =>
                    "abnormal termination",
                UnsupportedInIsolation(_) =>
                    "unsupported operation",
                ExperimentalUb { .. } =>
                    "Undefined Behavior",
                Deadlock => "deadlock",
            };
            let helps = match info {
                UnsupportedInIsolation(_) =>
                    vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
                ExperimentalUb { url, .. } =>
                    vec![
                        format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
                        format!("see {} for further information", url),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
        _ => {
            let title = match e.kind {
                Unsupported(_) =>
                    "unsupported operation",
                UndefinedBehavior(_) =>
                    "Undefined Behavior",
                ResourceExhaustion(_) =>
                    "resource exhaustion",
                _ =>
                    bug!("This error should be impossible in Miri: {}", e),
            };
            let helps = match e.kind {
                Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
                    vec![format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`")],
                Unsupported(UnsupportedOpInfo::ReadBytesAsPointer) =>
                    panic!("`ReadBytesAsPointer` cannot be raised by Miri"),
                Unsupported(_) =>
                    vec![format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support")],
                UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. }) =>
                    vec![
                        format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
                        format!("but alignment errors can also be false positives, see https://github.com/rust-lang/miri/issues/1074"),
                        format!("you can disable the alignment check with `-Zmiri-disable-alignment-check`, but that could hide true bugs")
                    ],
                UndefinedBehavior(_) =>
                    vec![
                        format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
                        format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
    };

    e.print_backtrace();
    let msg = e.to_string();
    let result = report_msg(ecx, &format!("{}: {}", title, msg), msg, helps, true);

    if let UndefinedBehavior(UndefinedBehaviorInfo::InvalidUndefBytes(Some(ptr))) = e.kind {
        eprintln!(
            "Uninitialized read occurred at offset 0x{:x} into this allocation:",
            ptr.offset.bytes(),
        );
        ecx.memory.dump_alloc(ptr.alloc_id);
        eprintln!();
    }

    result
}

/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
/// Also emits a full stacktrace of the interpreter stack.
fn report_msg<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
    title: &str,
    span_msg: String,
    mut helps: Vec<String>,
    error: bool,
) -> Option<i64> {
    let span = if let Some(frame) = ecx.machine.stack.last() {
        frame.current_source_info().unwrap().span
    } else {
        DUMMY_SP
    };
    let mut err = if error {
        ecx.tcx.sess.struct_span_err(span, title)
    } else {
        ecx.tcx.sess.diagnostic().span_note_diag(span, title)
    };
    err.span_label(span, span_msg);
    if !helps.is_empty() {
        // Add visual separator before backtrace.
        helps.last_mut().unwrap().push_str("\n");
        for help in helps {
            err.help(&help);
        }
    }
    // Add backtrace
    let frames = ecx.generate_stacktrace();
    for (idx, frame_info) in frames.iter().enumerate() {
        let is_local = frame_info.instance.def_id().is_local();
        // No span for non-local frames and the first frame (which is the error site).
        if is_local && idx > 0 {
            err.span_note(frame_info.span, &frame_info.to_string());
        } else {
            err.note(&frame_info.to_string());
        }
    }

    err.emit();

    for (i, frame) in ecx.machine.stack.iter().enumerate() {
        trace!("-------------------");
        trace!("Frame {}", i);
        trace!("    return: {:?}", frame.return_place.map(|p| *p));
        for (i, local) in frame.locals.iter().enumerate() {
            trace!("    local {}: {:?}", i, local.value);
        }
    }
    // Let the reported error determine the return code.
    return None;
}

thread_local! {
    static DIAGNOSTICS: RefCell<Vec<NonHaltingDiagnostic>> = RefCell::new(Vec::new());
}

/// Schedule a diagnostic for emitting. This function works even if you have no `InterpCx` available.
/// The diagnostic will be emitted after the current interpreter step is finished.
pub fn register_diagnostic(e: NonHaltingDiagnostic) {
    DIAGNOSTICS.with(|diagnostics| diagnostics.borrow_mut().push(e));
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Emit all diagnostics that were registed with `register_diagnostics`
    fn process_diagnostics(&self) {
        let this = self.eval_context_ref();
        DIAGNOSTICS.with(|diagnostics| {
            for e in diagnostics.borrow_mut().drain(..) {
                use NonHaltingDiagnostic::*;
                let msg = match e {
                    PoppedTrackedPointerTag(item) =>
                        format!("popped tracked tag for item {:?}", item),
                    CreatedAlloc(AllocId(id)) =>
                        format!("created allocation with id {}", id),
                    FreedAlloc(AllocId(id)) =>
                        format!("freed allocation with id {}", id),
                };
                report_msg(this, "tracking was triggered", msg, vec![], false);
            }
        });
    }
}
<commit_msg>Review comments<commit_after>use std::cell::RefCell;
use std::fmt;

use log::trace;

use rustc_span::DUMMY_SP;

use crate::*;

/// Details of premature program termination.
pub enum TerminationInfo {
    Exit(i64),
    Abort(Option<String>),
    UnsupportedInIsolation(String),
    ExperimentalUb { msg: String, url: String },
    Deadlock,
}

impl fmt::Debug for TerminationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use TerminationInfo::*;
        match self {
            Exit(code) =>
                write!(f, "the evaluated program completed with exit code {}", code),
            Abort(None) =>
                write!(f, "the evaluated program aborted execution"),
            Abort(Some(msg)) =>
                write!(f, "the evaluated program aborted execution: {}", msg),
            UnsupportedInIsolation(msg) =>
                write!(f, "{}", msg),
            ExperimentalUb { msg, .. } =>
                write!(f, "{}", msg),
            Deadlock =>
                write!(f, "the evaluated program deadlocked"),
        }
    }
}

impl MachineStopType for TerminationInfo {}

/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
    PoppedTrackedPointerTag(Item),
    CreatedAlloc(AllocId),
    FreedAlloc(AllocId),
}

/// Emit a custom diagnostic without going through the miri-engine machinery
pub fn report_error<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
    mut e: InterpErrorInfo<'tcx>,
) -> Option<i64> {
    use InterpError::*;

    let (title, helps) = match &e.kind {
        MachineStop(info) => {
            let info = info.downcast_ref::<TerminationInfo>().expect("invalid MachineStop payload");
            use TerminationInfo::*;
            let title = match info {
                Exit(code) => return Some(*code),
                Abort(_) =>
                    "abnormal termination",
                UnsupportedInIsolation(_) =>
                    "unsupported operation",
                ExperimentalUb { .. } =>
                    "Undefined Behavior",
                Deadlock => "deadlock",
            };
            let helps = match info {
                UnsupportedInIsolation(_) =>
                    vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
                ExperimentalUb { url, .. } =>
                    vec![
                        format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
                        format!("see {} for further information", url),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
        _ => {
            let title = match e.kind {
                Unsupported(_) =>
                    "unsupported operation",
                UndefinedBehavior(_) =>
                    "Undefined Behavior",
                ResourceExhaustion(_) =>
                    "resource exhaustion",
                _ =>
                    bug!("This error should be impossible in Miri: {}", e),
            };
            let helps = match e.kind {
                Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
                    vec![format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`")],
                Unsupported(UnsupportedOpInfo::ReadBytesAsPointer) =>
                    panic!("`ReadBytesAsPointer` cannot be raised by Miri"),
                Unsupported(_) =>
                    vec![format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support")],
                UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. }) =>
                    vec![
                        format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
                        format!("but alignment errors can also be false positives, see https://github.com/rust-lang/miri/issues/1074"),
                        format!("you can disable the alignment check with `-Zmiri-disable-alignment-check`, but that could hide true bugs")
                    ],
                UndefinedBehavior(_) =>
                    vec![
                        format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
                        format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
    };

    e.print_backtrace();
    let msg = e.to_string();
    report_msg(ecx, &format!("{}: {}", title, msg), msg, helps, true);

    // Extra output to help debug specific issues.
    if let UndefinedBehavior(UndefinedBehaviorInfo::InvalidUndefBytes(Some(ptr))) = e.kind {
        eprintln!(
            "Uninitialized read occurred at offset 0x{:x} into this allocation:",
            ptr.offset.bytes(),
        );
        ecx.memory.dump_alloc(ptr.alloc_id);
        eprintln!();
    }

    None
}

/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
/// Also emits a full stacktrace of the interpreter stack.
fn report_msg<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
    title: &str,
    span_msg: String,
    mut helps: Vec<String>,
    error: bool,
) {
    let span = if let Some(frame) = ecx.machine.stack.last() {
        frame.current_source_info().unwrap().span
    } else {
        DUMMY_SP
    };
    let mut err = if error {
        ecx.tcx.sess.struct_span_err(span, title)
    } else {
        ecx.tcx.sess.diagnostic().span_note_diag(span, title)
    };
    err.span_label(span, span_msg);
    if !helps.is_empty() {
        // Add visual separator before backtrace.
        helps.last_mut().unwrap().push_str("\n");
        for help in helps {
            err.help(&help);
        }
    }
    // Add backtrace
    let frames = ecx.generate_stacktrace();
    for (idx, frame_info) in frames.iter().enumerate() {
        let is_local = frame_info.instance.def_id().is_local();
        // No span for non-local frames and the first frame (which is the error site).
        if is_local && idx > 0 {
            err.span_note(frame_info.span, &frame_info.to_string());
        } else {
            err.note(&frame_info.to_string());
        }
    }

    err.emit();

    for (i, frame) in ecx.machine.stack.iter().enumerate() {
        trace!("-------------------");
        trace!("Frame {}", i);
        trace!("    return: {:?}", frame.return_place.map(|p| *p));
        for (i, local) in frame.locals.iter().enumerate() {
            trace!("    local {}: {:?}", i, local.value);
        }
    }
}

thread_local! {
    static DIAGNOSTICS: RefCell<Vec<NonHaltingDiagnostic>> = RefCell::new(Vec::new());
}

/// Schedule a diagnostic for emitting. This function works even if you have no `InterpCx` available.
/// The diagnostic will be emitted after the current interpreter step is finished.
pub fn register_diagnostic(e: NonHaltingDiagnostic) {
    DIAGNOSTICS.with(|diagnostics| diagnostics.borrow_mut().push(e));
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Emit all diagnostics that were registed with `register_diagnostics`
    fn process_diagnostics(&self) {
        let this = self.eval_context_ref();
        DIAGNOSTICS.with(|diagnostics| {
            for e in diagnostics.borrow_mut().drain(..) {
                use NonHaltingDiagnostic::*;
                let msg = match e {
                    PoppedTrackedPointerTag(item) =>
                        format!("popped tracked tag for item {:?}", item),
                    CreatedAlloc(AllocId(id)) =>
                        format!("created allocation with id {}", id),
                    FreedAlloc(AllocId(id)) =>
                        format!("freed allocation with id {}", id),
                };
                report_msg(this, "tracking was triggered", msg, vec![], false);
            }
        });
    }
}
<|endoftext|>


<commit_before>//! Engineering related constants
//
// http://www.engineeringtoolbox.com/physical-constants-SI-d_1662.html
// http://www.engineering.com/Library/ArticlesPage/tabid/85/ArticleID/115/Constants.aspx

<commit_msg>Add new constants for engineering<commit_after>//! Engineering related constants
//
// http://www.engineeringtoolbox.com/physical-constants-SI-d_1662.html
// http://www.engineering.com/Library/ArticlesPage/tabid/85/ArticleID/115/Constants.aspx

pub const gravitational_acceleration: f64 = 9.807; // [m/s²]
pub const plancks_constant: f64 = 6.625e-34; // [J · s/molecule]
pub const speed_of_light_vac: f64 = 2.998e8; // [m/s]
pub const avogadros_number: f64 = 6.024e23; // [molecules/mol]
pub const boltzmanns_constant: f64 = 1.380e-23; // [J/K * molecule]
pub const steffan_boltzmann_constant: f64 = 5.670e-8 ; // [W/m² * K⁴]
pub const universal_gas_constant: f64 = 8.31434e3; // [J/kmol * K]
pub const normal_atmospheric_pressure: f64 = 101325.0; // [N/m²]
pub const bohr_radius: f64 = 0.529167e-10; // [m]
pub const electronic_charge: f64 = 1.60210e-19; // [C]
pub const electron_rest_mass: f64 = 9.10908e-31; // [kg]
pub const fine_structure_constant: f64 = 7.29720e-3; // []
pub const proton_rest_mass: f64 = 1.67252e-27; // [Kg]
pub const neutron_rest_mass: f64 = 1.67482e-27; // [Kg]
<|endoftext|>


<commit_before>
#[derive(PartialEq)]
#[derive(Debug)]
pub enum PrizeType {
    SPECIAL,
    GRAND,
    FIRST,
    SECOND,
    THIRD,
    FOURTH,
    FIFTH,
    SIXTH,
    ADDITIONAL,
    NONE
}

#[derive(Debug)]
pub struct WinningNumbers {
    pub special_prize: String,
    pub grand_prize: String,
    pub regular_prizes: [String; 3],
    pub additional_prizes: [String; 3],
}

fn check_ticket(winning_number: &str, ticket_number: &str) -> usize {
    let mut max_length = 0;

    for length in (3..9).rev() {
        let winning_reverse: String = winning_number.chars().rev().collect();
        let ticket_reverse: String = ticket_number.chars().rev().collect();
        if winning_reverse[0..length] == ticket_reverse[0..length] {
            max_length = length;
            break;
        }
    }

    max_length
}

fn convert_number_to_prize(number: usize) -> PrizeType {
    match number {
        8 => PrizeType::FIRST,
        7 => PrizeType::SECOND,
        6 => PrizeType::THIRD,
        5 => PrizeType::FOURTH,
        4 => PrizeType::FIFTH,
        3 => PrizeType::SIXTH,
        _ => PrizeType::NONE,
    }
}

fn check_ticket_regular(regular_prizes: &[String; 3], ticket_number: &str) -> PrizeType {
    let regular1 = check_ticket(&regular_prizes[0], ticket_number);
    let regular2 = check_ticket(&regular_prizes[1], ticket_number);
    let regular3 = check_ticket(&regular_prizes[2], ticket_number);

    let results = [regular1, regular2, regular3];
    let best_result = results.iter().max();

    match best_result {
        Some(number) => convert_number_to_prize(*number),
        None => PrizeType::NONE,
    }
}

pub fn check_ticket_all(winning_numbers: &WinningNumbers, ticket_number: &str) -> PrizeType
{
    let special_rev = winning_numbers.special_prize.chars().rev();
    let grand_rev = winning_numbers.grand_prize.chars().rev();
    let ticket_rev : String = ticket_number.chars().rev().collect();

    let regular_prize_result = check_ticket_regular(&winning_numbers.regular_prizes, ticket_number);

    if ticket_rev.chars().take(8).eq(special_rev) {
        PrizeType::SPECIAL
    }
    else if ticket_rev.chars().take(8).eq(grand_rev) {
        PrizeType::GRAND
    }
    else if regular_prize_result != PrizeType::NONE {
        regular_prize_result
    }
    else if ticket_rev.chars().take(3).eq(winning_numbers.additional_prizes[0].chars().rev()) {
        PrizeType::ADDITIONAL
    }
    else if ticket_rev.chars().take(3).eq(winning_numbers.additional_prizes[1].chars().rev()) {
        PrizeType::ADDITIONAL
    }
    else if ticket_rev.chars().take(3).eq(winning_numbers.additional_prizes[2].chars().rev()) {
        PrizeType::ADDITIONAL
    }
    else
    {
        PrizeType::NONE
    }
}

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

    #[test]
    fn test_last_digit_off() {
        assert_eq!(0, check_ticket("AB-87654320","AB-87654321"));
    }

    #[test]
    fn test_full_match() {
        assert_eq!(8, check_ticket("AB-87654321","AB-87654321"));
    }

    #[test]
    fn test_last_three() {
        assert_eq!(3, check_ticket("AB-87654321","AB-00000321"));
    }

    #[test]
    fn test_last_two_no_match() {
        assert_eq!(0, check_ticket("AB-87654321","AB-00000021"));
    }
/////////////////////// Convert number to prize
    #[test]
    fn test_convert_number_to_prize() {
        assert_eq!(PrizeType::FIRST, convert_number_to_prize(8));
        assert_eq!(PrizeType::SECOND, convert_number_to_prize(7));
        assert_eq!(PrizeType::THIRD, convert_number_to_prize(6));
        assert_eq!(PrizeType::FOURTH, convert_number_to_prize(5));
        assert_eq!(PrizeType::FIFTH, convert_number_to_prize(4));
        assert_eq!(PrizeType::SIXTH, convert_number_to_prize(3));
        assert_eq!(PrizeType::NONE, convert_number_to_prize(2));
        assert_eq!(PrizeType::NONE, convert_number_to_prize(1));
        assert_eq!(PrizeType::NONE, convert_number_to_prize(0));
        assert_eq!(PrizeType::NONE, convert_number_to_prize(9));
    }
/////////////////////// check_ticket_regular
    #[test]
    fn test_check_regular() {
        let regular_numbers = [String::from("98765432"),
                               String::from("87654321"),
                               String::from("76543210")];

        assert_eq!(PrizeType::FIRST, check_ticket_regular(&regular_numbers,  "98765432"));
        assert_eq!(PrizeType::FIRST, check_ticket_regular(&regular_numbers,  "87654321"));
        assert_eq!(PrizeType::FIRST, check_ticket_regular(&regular_numbers,  "76543210"));
        assert_eq!(PrizeType::SECOND, check_ticket_regular(&regular_numbers, "08765432"));
        assert_eq!(PrizeType::THIRD, check_ticket_regular(&regular_numbers,  "00765432"));
        assert_eq!(PrizeType::FOURTH, check_ticket_regular(&regular_numbers, "00065432"));
        assert_eq!(PrizeType::FIFTH, check_ticket_regular(&regular_numbers,  "00005432"));
        assert_eq!(PrizeType::SIXTH, check_ticket_regular(&regular_numbers,  "00000432"));
        assert_eq!(PrizeType::NONE, check_ticket_regular(&regular_numbers,   "00000032"));

        // Double check that smaller, non-first prizes are checked on the other winning numbers
        assert_eq!(PrizeType::FIFTH, check_ticket_regular(&regular_numbers,  "00004321"));
        assert_eq!(PrizeType::SIXTH, check_ticket_regular(&regular_numbers,  "00000210"));
    }

///////////////////// check_ticket_all
    #[test]
    fn test_full_ticket() {
        let winning_numbers = WinningNumbers {
            special_prize: String::from("01234567"),
            grand_prize: String::from("12345678"),
            regular_prizes: [String::from("98765432"),
                             String::from("87654321"),
                             String::from("76543210")],
            additional_prizes: [String::from("765"),
                                String::from("654"),
                                String::from("543")]
        };

        assert_eq!(PrizeType::NONE, check_ticket_all(&winning_numbers, "AZ-39842818"));
        assert_eq!(PrizeType::SPECIAL, check_ticket_all(&winning_numbers, "AD-01234567"));
        assert_eq!(PrizeType::GRAND, check_ticket_all(&winning_numbers, "AD-12345678"));
        assert_eq!(PrizeType::FIRST, check_ticket_all(&winning_numbers, "AD-98765432"));
        assert_eq!(PrizeType::SIXTH, check_ticket_all(&winning_numbers, "BB-00000210"));
        assert_eq!(PrizeType::ADDITIONAL, check_ticket_all(&winning_numbers, "XX-00000543"));
        assert_eq!(PrizeType::ADDITIONAL, check_ticket_all(&winning_numbers, "YY-00000654"));
        assert_eq!(PrizeType::ADDITIONAL, check_ticket_all(&winning_numbers, "ZZ-00000765"));
    }

    #[test]
    fn test_largest_prize_returned() {
        let winning_numbers = WinningNumbers {
            special_prize: String::from("98765432"),
            grand_prize: String::from("87654321"),
            regular_prizes: [String::from("08765432"), // Almost same as special
                             String::from("07654321"), // Almost same as grand
                             String::from("76543210")],
            additional_prizes: [String::from("321"), //Same as last 3 of both grand and reguar
                                String::from("432"), //Same as last 3 of both special and reguar
                                String::from("314")]
        };

        assert_eq!(PrizeType::SPECIAL, check_ticket_all(&winning_numbers, "AZ-98765432"));
        assert_eq!(PrizeType::GRAND, check_ticket_all(&winning_numbers, "AD-87654321"));
        assert_eq!(PrizeType::FOURTH, check_ticket_all(&winning_numbers, "AF-00054321"));
    }

    #[test]
    fn test_no_preceding_letters() {
        let winning_numbers = WinningNumbers {
            special_prize: String::from("01234567"),
            grand_prize: String::from("12345678"),
            regular_prizes: [String::from("98765432"),
                             String::from("87654321"),
                             String::from("76543210")],
            additional_prizes: [String::from("765"),
                                String::from("654"),
                                String::from("543")]
        };

        assert_eq!(PrizeType::FIRST, check_ticket_all(&winning_numbers, "98765432"));
    }
}
<commit_msg>small improvement to iterator code<commit_after>
#[derive(PartialEq)]
#[derive(Debug)]
pub enum PrizeType {
    SPECIAL,
    GRAND,
    FIRST,
    SECOND,
    THIRD,
    FOURTH,
    FIFTH,
    SIXTH,
    ADDITIONAL,
    NONE
}

#[derive(Debug)]
pub struct WinningNumbers {
    pub special_prize: String,
    pub grand_prize: String,
    pub regular_prizes: [String; 3],
    pub additional_prizes: [String; 3],
}

fn check_ticket(winning_number: &str, ticket_number: &str) -> usize {
    let mut max_length = 0;

    for length in (3..9).rev() {
        let winning_reverse = winning_number.chars().rev().take(length);
        let ticket_reverse = ticket_number.chars().rev().take(length);
        if winning_reverse.eq(ticket_reverse){
            max_length = length;
            break;
        }
    }

    max_length
}

fn convert_number_to_prize(number: usize) -> PrizeType {
    match number {
        8 => PrizeType::FIRST,
        7 => PrizeType::SECOND,
        6 => PrizeType::THIRD,
        5 => PrizeType::FOURTH,
        4 => PrizeType::FIFTH,
        3 => PrizeType::SIXTH,
        _ => PrizeType::NONE,
    }
}

fn check_ticket_regular(regular_prizes: &[String; 3], ticket_number: &str) -> PrizeType {
    let regular1 = check_ticket(&regular_prizes[0], ticket_number);
    let regular2 = check_ticket(&regular_prizes[1], ticket_number);
    let regular3 = check_ticket(&regular_prizes[2], ticket_number);

    let results = [regular1, regular2, regular3];
    let best_result = results.iter().max();

    match best_result {
        Some(number) => convert_number_to_prize(*number),
        None => PrizeType::NONE,
    }
}

pub fn check_ticket_all(winning_numbers: &WinningNumbers, ticket_number: &str) -> PrizeType
{
    let special_rev = winning_numbers.special_prize.chars().rev();
    let grand_rev = winning_numbers.grand_prize.chars().rev();
    let ticket_rev : String = ticket_number.chars().rev().collect();

    let regular_prize_result = check_ticket_regular(&winning_numbers.regular_prizes, ticket_number);

    if ticket_rev.chars().take(8).eq(special_rev) {
        PrizeType::SPECIAL
    }
    else if ticket_rev.chars().take(8).eq(grand_rev) {
        PrizeType::GRAND
    }
    else if regular_prize_result != PrizeType::NONE {
        regular_prize_result
    }
    else if ticket_rev.chars().take(3).eq(winning_numbers.additional_prizes[0].chars().rev()) {
        PrizeType::ADDITIONAL
    }
    else if ticket_rev.chars().take(3).eq(winning_numbers.additional_prizes[1].chars().rev()) {
        PrizeType::ADDITIONAL
    }
    else if ticket_rev.chars().take(3).eq(winning_numbers.additional_prizes[2].chars().rev()) {
        PrizeType::ADDITIONAL
    }
    else
    {
        PrizeType::NONE
    }
}

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

    #[test]
    fn test_last_digit_off() {
        assert_eq!(0, check_ticket("AB-87654320","AB-87654321"));
    }

    #[test]
    fn test_full_match() {
        assert_eq!(8, check_ticket("AB-87654321","AB-87654321"));
    }

    #[test]
    fn test_last_three() {
        assert_eq!(3, check_ticket("AB-87654321","AB-00000321"));
    }

    #[test]
    fn test_last_two_no_match() {
        assert_eq!(0, check_ticket("AB-87654321","AB-00000021"));
    }
/////////////////////// Convert number to prize
    #[test]
    fn test_convert_number_to_prize() {
        assert_eq!(PrizeType::FIRST, convert_number_to_prize(8));
        assert_eq!(PrizeType::SECOND, convert_number_to_prize(7));
        assert_eq!(PrizeType::THIRD, convert_number_to_prize(6));
        assert_eq!(PrizeType::FOURTH, convert_number_to_prize(5));
        assert_eq!(PrizeType::FIFTH, convert_number_to_prize(4));
        assert_eq!(PrizeType::SIXTH, convert_number_to_prize(3));
        assert_eq!(PrizeType::NONE, convert_number_to_prize(2));
        assert_eq!(PrizeType::NONE, convert_number_to_prize(1));
        assert_eq!(PrizeType::NONE, convert_number_to_prize(0));
        assert_eq!(PrizeType::NONE, convert_number_to_prize(9));
    }
/////////////////////// check_ticket_regular
    #[test]
    fn test_check_regular() {
        let regular_numbers = [String::from("98765432"),
                               String::from("87654321"),
                               String::from("76543210")];

        assert_eq!(PrizeType::FIRST, check_ticket_regular(&regular_numbers,  "98765432"));
        assert_eq!(PrizeType::FIRST, check_ticket_regular(&regular_numbers,  "87654321"));
        assert_eq!(PrizeType::FIRST, check_ticket_regular(&regular_numbers,  "76543210"));
        assert_eq!(PrizeType::SECOND, check_ticket_regular(&regular_numbers, "08765432"));
        assert_eq!(PrizeType::THIRD, check_ticket_regular(&regular_numbers,  "00765432"));
        assert_eq!(PrizeType::FOURTH, check_ticket_regular(&regular_numbers, "00065432"));
        assert_eq!(PrizeType::FIFTH, check_ticket_regular(&regular_numbers,  "00005432"));
        assert_eq!(PrizeType::SIXTH, check_ticket_regular(&regular_numbers,  "00000432"));
        assert_eq!(PrizeType::NONE, check_ticket_regular(&regular_numbers,   "00000032"));

        // Double check that smaller, non-first prizes are checked on the other winning numbers
        assert_eq!(PrizeType::FIFTH, check_ticket_regular(&regular_numbers,  "00004321"));
        assert_eq!(PrizeType::SIXTH, check_ticket_regular(&regular_numbers,  "00000210"));
    }

///////////////////// check_ticket_all
    #[test]
    fn test_full_ticket() {
        let winning_numbers = WinningNumbers {
            special_prize: String::from("01234567"),
            grand_prize: String::from("12345678"),
            regular_prizes: [String::from("98765432"),
                             String::from("87654321"),
                             String::from("76543210")],
            additional_prizes: [String::from("765"),
                                String::from("654"),
                                String::from("543")]
        };

        assert_eq!(PrizeType::NONE, check_ticket_all(&winning_numbers, "AZ-39842818"));
        assert_eq!(PrizeType::SPECIAL, check_ticket_all(&winning_numbers, "AD-01234567"));
        assert_eq!(PrizeType::GRAND, check_ticket_all(&winning_numbers, "AD-12345678"));
        assert_eq!(PrizeType::FIRST, check_ticket_all(&winning_numbers, "AD-98765432"));
        assert_eq!(PrizeType::SIXTH, check_ticket_all(&winning_numbers, "BB-00000210"));
        assert_eq!(PrizeType::ADDITIONAL, check_ticket_all(&winning_numbers, "XX-00000543"));
        assert_eq!(PrizeType::ADDITIONAL, check_ticket_all(&winning_numbers, "YY-00000654"));
        assert_eq!(PrizeType::ADDITIONAL, check_ticket_all(&winning_numbers, "ZZ-00000765"));
    }

    #[test]
    fn test_largest_prize_returned() {
        let winning_numbers = WinningNumbers {
            special_prize: String::from("98765432"),
            grand_prize: String::from("87654321"),
            regular_prizes: [String::from("08765432"), // Almost same as special
                             String::from("07654321"), // Almost same as grand
                             String::from("76543210")],
            additional_prizes: [String::from("321"), //Same as last 3 of both grand and reguar
                                String::from("432"), //Same as last 3 of both special and reguar
                                String::from("314")]
        };

        assert_eq!(PrizeType::SPECIAL, check_ticket_all(&winning_numbers, "AZ-98765432"));
        assert_eq!(PrizeType::GRAND, check_ticket_all(&winning_numbers, "AD-87654321"));
        assert_eq!(PrizeType::FOURTH, check_ticket_all(&winning_numbers, "AF-00054321"));
    }

    #[test]
    fn test_no_preceding_letters() {
        let winning_numbers = WinningNumbers {
            special_prize: String::from("01234567"),
            grand_prize: String::from("12345678"),
            regular_prizes: [String::from("98765432"),
                             String::from("87654321"),
                             String::from("76543210")],
            additional_prizes: [String::from("765"),
                                String::from("654"),
                                String::from("543")]
        };

        assert_eq!(PrizeType::FIRST, check_ticket_all(&winning_numbers, "98765432"));
    }
}
<|endoftext|>


<commit_before>//! Formatting helpers for a `Date`.

#![allow(non_snake_case)]

use crate::format::{Language, Padding};
use crate::Date;
use crate::Weekday::{Friday, Monday, Saturday, Sunday, Thursday, Tuesday, Wednesday};
use core::fmt::{self, Formatter};

macro_rules! nonexhaustive_locale {
    () => {
        unreachable!(
            "This is needed due to the explicit nonexhaustiveness of locales. \
             Once rust-lang/rust#44109 is resolved and `#[non_exhaustive]` is \
             stabilized, this will no longer be necessary."
        )
    };
}

/// Short day of the week
pub(crate) fn fmt_a(f: &mut Formatter<'_>, date: Date, locale: Language) -> fmt::Result {
    use Language::*;
    match (locale, date.weekday()) {
        (en, Monday) => f.write_str("Mon"),
        (en, Tuesday) => f.write_str("Tue"),
        (en, Wednesday) => f.write_str("Wed"),
        (en, Thursday) => f.write_str("Thu"),
        (en, Friday) => f.write_str("Fri"),
        (en, Saturday) => f.write_str("Sat"),
        (en, Sunday) => f.write_str("Sun"),

        (es, Monday) => f.write_str("Lu"),
        (es, Tuesday) => f.write_str("Ma"),
        (es, Wednesday) => f.write_str("Mi"),
        (es, Thursday) => f.write_str("Ju"),
        (es, Friday) => f.write_str("Vi"),
        (es, Saturday) => f.write_str("Sa"),
        (es, Sunday) => f.write_str("Do"),

        _ => nonexhaustive_locale!(),
    }
}

/// Day of the week
pub(crate) fn fmt_A(f: &mut Formatter<'_>, date: Date, locale: Language) -> fmt::Result {
    use Language::*;
    match (locale, date.weekday()) {
        (en, Monday) => f.write_str("Monday"),
        (en, Tuesday) => f.write_str("Tuesday"),
        (en, Wednesday) => f.write_str("Wednesday"),
        (en, Thursday) => f.write_str("Thursday"),
        (en, Friday) => f.write_str("Friday"),
        (en, Saturday) => f.write_str("Saturday"),
        (en, Sunday) => f.write_str("Sunday"),

        (es, Monday) => f.write_str("lunes"),
        (es, Tuesday) => f.write_str("martes"),
        (es, Wednesday) => f.write_str("miércoles"),
        (es, Thursday) => f.write_str("jueves"),
        (es, Friday) => f.write_str("viernes"),
        (es, Saturday) => f.write_str("sábado"),
        (es, Sunday) => f.write_str("domingo"),

        _ => nonexhaustive_locale!(),
    }
}

/// Short month name
///
/// References on localization
/// - [Yale](https://web.library.yale.edu/cataloging/months)
/// - [Princeton](https://library.princeton.edu/departments/tsd/katmandu/reference/months.html)
pub(crate) fn fmt_b(f: &mut Formatter<'_>, date: Date, locale: Language) -> fmt::Result {
    use Language::*;
    match (locale, date.month()) {
        (en, 1) => f.write_str("Jan"),
        (en, 2) => f.write_str("Feb"),
        (en, 3) => f.write_str("Mar"),
        (en, 4) => f.write_str("Apr"),
        (en, 5) => f.write_str("May"),
        (en, 6) => f.write_str("June"),
        (en, 7) => f.write_str("July"),
        (en, 8) => f.write_str("Aug"),
        (en, 9) => f.write_str("Sept"),
        (en, 10) => f.write_str("Oct"),
        (en, 11) => f.write_str("Nov"),
        (en, 12) => f.write_str("Dec"),

        (es, 1) => f.write_str("enero"),
        (es, 2) => f.write_str("feb"),
        (es, 3) => f.write_str("marzo"),
        (es, 4) => f.write_str("abr"),
        (es, 5) => f.write_str("mayo"),
        (es, 6) => f.write_str("jun"),
        (es, 7) => f.write_str("jul"),
        (es, 8) => f.write_str("agosto"),
        (es, 9) => f.write_str("set"),
        (es, 10) => f.write_str("oct"),
        (es, 11) => f.write_str("nov"),
        (es, 12) => f.write_str("dic"),

        _ => unreachable!("There are only 12 months in a year."),
    }
}

/// Month name
pub(crate) fn fmt_B(f: &mut Formatter<'_>, date: Date, locale: Language) -> fmt::Result {
    use Language::*;
    match (locale, date.month()) {
        (en, 1) => f.write_str("January"),
        (en, 2) => f.write_str("February"),
        (en, 3) => f.write_str("March"),
        (en, 4) => f.write_str("April"),
        (en, 5) => f.write_str("May"),
        (en, 6) => f.write_str("June"),
        (en, 7) => f.write_str("July"),
        (en, 8) => f.write_str("August"),
        (en, 9) => f.write_str("September"),
        (en, 10) => f.write_str("October"),
        (en, 11) => f.write_str("November"),
        (en, 12) => f.write_str("December"),

        (es, 1) => f.write_str("enero"),
        (es, 2) => f.write_str("febrero"),
        (es, 3) => f.write_str("marzo"),
        (es, 4) => f.write_str("abril"),
        (es, 5) => f.write_str("mayo"),
        (es, 6) => f.write_str("junio"),
        (es, 7) => f.write_str("julio"),
        (es, 8) => f.write_str("agosto"),
        (es, 9) => f.write_str("septiembre"),
        (es, 10) => f.write_str("octubre"),
        (es, 11) => f.write_str("noviembre"),
        (es, 12) => f.write_str("diciembre"),

        _ => unreachable!("There are only 12 months in a year."),
    }
}

/// Year divided by 100 and truncated to integer (`00`-`99`)
pub(crate) fn fmt_C(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.year() / 100)
}

/// Day of the month, zero-padded (`01`-`31`)
pub(crate) fn fmt_d(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.day())
}

/// Day of the month, space-padded (` 1`-`31`)
pub(crate) fn fmt_e(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Space, 2, date.day())
}

/// Week-based year, last two digits (`00`-`99`)
pub(crate) fn fmt_g(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.iso_year_week().0.rem_euclid(100))
}

/// Week-based year
pub(crate) fn fmt_G(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.iso_year_week().0)
}

/// Day of the year, zero-padded to width 3 (`000`-`366`)
pub(crate) fn fmt_j(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 3, date.ordinal())
}

/// Month of the year, zero-padded (`01`-`12`)
pub(crate) fn fmt_m(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.month())
}

/// ISO weekday (Monday = 1, Sunday = 7)
pub(crate) fn fmt_u(f: &mut Formatter<'_>, date: Date) -> fmt::Result {
    write!(f, "{}", date.weekday().iso_weekday_number())
}

/// ISO week number, zero-padded (`00`-`53`)
pub(crate) fn fmt_V(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.week())
}

/// Weekday number (Sunday = 0, Saturday = 6)
pub(crate) fn fmt_w(f: &mut Formatter<'_>, date: Date) -> fmt::Result {
    write!(f, "{}", date.weekday().number_days_from_sunday())
}

/// Last two digits of year (`00`-`99`)
pub(crate) fn fmt_y(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.year().rem_euclid(100))
}

/// Full year
pub(crate) fn fmt_Y(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 4, date.year())
}
<commit_msg>Display sign on years >= 10_000<commit_after>//! Formatting helpers for a `Date`.

#![allow(non_snake_case)]

use crate::format::{Language, Padding};
use crate::Date;
use crate::Weekday::{Friday, Monday, Saturday, Sunday, Thursday, Tuesday, Wednesday};
use core::fmt::{self, Formatter};

macro_rules! nonexhaustive_locale {
    () => {
        unreachable!(
            "This is needed due to the explicit nonexhaustiveness of locales. \
             Once rust-lang/rust#44109 is resolved and `#[non_exhaustive]` is \
             stabilized, this will no longer be necessary."
        )
    };
}

/// Short day of the week
pub(crate) fn fmt_a(f: &mut Formatter<'_>, date: Date, locale: Language) -> fmt::Result {
    use Language::*;
    match (locale, date.weekday()) {
        (en, Monday) => f.write_str("Mon"),
        (en, Tuesday) => f.write_str("Tue"),
        (en, Wednesday) => f.write_str("Wed"),
        (en, Thursday) => f.write_str("Thu"),
        (en, Friday) => f.write_str("Fri"),
        (en, Saturday) => f.write_str("Sat"),
        (en, Sunday) => f.write_str("Sun"),

        (es, Monday) => f.write_str("Lu"),
        (es, Tuesday) => f.write_str("Ma"),
        (es, Wednesday) => f.write_str("Mi"),
        (es, Thursday) => f.write_str("Ju"),
        (es, Friday) => f.write_str("Vi"),
        (es, Saturday) => f.write_str("Sa"),
        (es, Sunday) => f.write_str("Do"),

        _ => nonexhaustive_locale!(),
    }
}

/// Day of the week
pub(crate) fn fmt_A(f: &mut Formatter<'_>, date: Date, locale: Language) -> fmt::Result {
    use Language::*;
    match (locale, date.weekday()) {
        (en, Monday) => f.write_str("Monday"),
        (en, Tuesday) => f.write_str("Tuesday"),
        (en, Wednesday) => f.write_str("Wednesday"),
        (en, Thursday) => f.write_str("Thursday"),
        (en, Friday) => f.write_str("Friday"),
        (en, Saturday) => f.write_str("Saturday"),
        (en, Sunday) => f.write_str("Sunday"),

        (es, Monday) => f.write_str("lunes"),
        (es, Tuesday) => f.write_str("martes"),
        (es, Wednesday) => f.write_str("miércoles"),
        (es, Thursday) => f.write_str("jueves"),
        (es, Friday) => f.write_str("viernes"),
        (es, Saturday) => f.write_str("sábado"),
        (es, Sunday) => f.write_str("domingo"),

        _ => nonexhaustive_locale!(),
    }
}

/// Short month name
///
/// References on localization
/// - [Yale](https://web.library.yale.edu/cataloging/months)
/// - [Princeton](https://library.princeton.edu/departments/tsd/katmandu/reference/months.html)
pub(crate) fn fmt_b(f: &mut Formatter<'_>, date: Date, locale: Language) -> fmt::Result {
    use Language::*;
    match (locale, date.month()) {
        (en, 1) => f.write_str("Jan"),
        (en, 2) => f.write_str("Feb"),
        (en, 3) => f.write_str("Mar"),
        (en, 4) => f.write_str("Apr"),
        (en, 5) => f.write_str("May"),
        (en, 6) => f.write_str("June"),
        (en, 7) => f.write_str("July"),
        (en, 8) => f.write_str("Aug"),
        (en, 9) => f.write_str("Sept"),
        (en, 10) => f.write_str("Oct"),
        (en, 11) => f.write_str("Nov"),
        (en, 12) => f.write_str("Dec"),

        (es, 1) => f.write_str("enero"),
        (es, 2) => f.write_str("feb"),
        (es, 3) => f.write_str("marzo"),
        (es, 4) => f.write_str("abr"),
        (es, 5) => f.write_str("mayo"),
        (es, 6) => f.write_str("jun"),
        (es, 7) => f.write_str("jul"),
        (es, 8) => f.write_str("agosto"),
        (es, 9) => f.write_str("set"),
        (es, 10) => f.write_str("oct"),
        (es, 11) => f.write_str("nov"),
        (es, 12) => f.write_str("dic"),

        _ => unreachable!("There are only 12 months in a year."),
    }
}

/// Month name
pub(crate) fn fmt_B(f: &mut Formatter<'_>, date: Date, locale: Language) -> fmt::Result {
    use Language::*;
    match (locale, date.month()) {
        (en, 1) => f.write_str("January"),
        (en, 2) => f.write_str("February"),
        (en, 3) => f.write_str("March"),
        (en, 4) => f.write_str("April"),
        (en, 5) => f.write_str("May"),
        (en, 6) => f.write_str("June"),
        (en, 7) => f.write_str("July"),
        (en, 8) => f.write_str("August"),
        (en, 9) => f.write_str("September"),
        (en, 10) => f.write_str("October"),
        (en, 11) => f.write_str("November"),
        (en, 12) => f.write_str("December"),

        (es, 1) => f.write_str("enero"),
        (es, 2) => f.write_str("febrero"),
        (es, 3) => f.write_str("marzo"),
        (es, 4) => f.write_str("abril"),
        (es, 5) => f.write_str("mayo"),
        (es, 6) => f.write_str("junio"),
        (es, 7) => f.write_str("julio"),
        (es, 8) => f.write_str("agosto"),
        (es, 9) => f.write_str("septiembre"),
        (es, 10) => f.write_str("octubre"),
        (es, 11) => f.write_str("noviembre"),
        (es, 12) => f.write_str("diciembre"),

        _ => unreachable!("There are only 12 months in a year."),
    }
}

/// Year divided by 100 and truncated to integer (`00`-`99`)
pub(crate) fn fmt_C(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.year() / 100)
}

/// Day of the month, zero-padded (`01`-`31`)
pub(crate) fn fmt_d(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.day())
}

/// Day of the month, space-padded (` 1`-`31`)
pub(crate) fn fmt_e(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Space, 2, date.day())
}

/// Week-based year, last two digits (`00`-`99`)
pub(crate) fn fmt_g(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.iso_year_week().0.rem_euclid(100))
}

/// Week-based year
pub(crate) fn fmt_G(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.iso_year_week().0)
}

/// Day of the year, zero-padded to width 3 (`000`-`366`)
pub(crate) fn fmt_j(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 3, date.ordinal())
}

/// Month of the year, zero-padded (`01`-`12`)
pub(crate) fn fmt_m(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.month())
}

/// ISO weekday (Monday = 1, Sunday = 7)
pub(crate) fn fmt_u(f: &mut Formatter<'_>, date: Date) -> fmt::Result {
    write!(f, "{}", date.weekday().iso_weekday_number())
}

/// ISO week number, zero-padded (`00`-`53`)
pub(crate) fn fmt_V(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.week())
}

/// Weekday number (Sunday = 0, Saturday = 6)
pub(crate) fn fmt_w(f: &mut Formatter<'_>, date: Date) -> fmt::Result {
    write!(f, "{}", date.weekday().number_days_from_sunday())
}

/// Last two digits of year (`00`-`99`)
pub(crate) fn fmt_y(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    pad!(Zero, 2, date.year().rem_euclid(100))
}

/// Full year
pub(crate) fn fmt_Y(f: &mut Formatter<'_>, date: Date, padding: Padding) -> fmt::Result {
    let year = date.year();

    if year >= 10_000 {
        f.write_str("+")?;
    }

    pad!(Zero, 4, year)
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use gl;
use gl::types::*;
use context::Context;
use renderbuffer::Renderbuffer;
use texture::{Texture, TextureType, ImageTargetType};
use types::GLError;

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl Context {
    pub fn gen_framebuffer(&self) -> Framebuffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenFramebuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Framebuffer {
                gl_id: id
            }
        }
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> GLenum {
        gl::FRAMEBUFFER
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        unsafe {
            gl::FramebufferRenderbuffer(self.target(),
                                        attachment.gl_enum(),
                                        gl::RENDERBUFFER,
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture2d<T: TextureType>(&mut self,
                                     attachment: FramebufferAttachment,
                                     tex_target: T::ImageTargetType,
                                     texture: &mut Texture<T>,
                                     level: i32)
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target(),
                                     attachment.gl_enum(),
                                     tex_target.gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub fn bind<'a>(&'a mut self, fbo: &mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<commit_msg>FIXUP buffer bits<commit_after>use std::marker::PhantomData;
use gl;
use gl::types::*;
use context::Context;
use renderbuffer::Renderbuffer;
use texture::{Texture, TextureType, ImageTargetType};
use types::{BufferBits, GLError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl Context {
    pub fn gen_framebuffer(&self) -> Framebuffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenFramebuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Framebuffer {
                gl_id: id
            }
        }
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> GLenum {
        gl::FRAMEBUFFER
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        unsafe {
            gl::FramebufferRenderbuffer(self.target(),
                                        attachment.gl_enum(),
                                        gl::RENDERBUFFER,
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture2d<T: TextureType>(&mut self,
                                     attachment: FramebufferAttachment,
                                     tex_target: T::ImageTargetType,
                                     texture: &mut Texture<T>,
                                     level: i32)
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target(),
                                     attachment.gl_enum(),
                                     tex_target.gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub fn bind<'a>(&'a mut self, fbo: &mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<|endoftext|>