<commit_before>//! Online SQLite backup API.
//!
//! To create a `Backup`, you must have two distinct `SqliteConnection`s - one
//! for the source (which can be used while the backup is running) and one for
//! the destination (which cannot).  A `Backup` handle exposes three methods:
//! `step` will attempt to back up a specified number of pages, `progress` gets
//! the current progress of the backup as of the last call to `step`, and
//! `run_to_completion` will attempt to back up the entire source database,
//! allowing you to specify how many pages are backed up at a time and how long
//! the thread should sleep between chunks of pages.
//!
//! The following example is equivalent to "Example 2: Online Backup of a
//! Running Database" from [SQLite's Online Backup API
//! documentation](https://www.sqlite.org/backup.html).
//!
//! ```rust,no_run
//! # use rusqlite::{backup, SqliteConnection, SqliteResult};
//! # use std::path::Path;
//! # use std::time;
//!
//! fn backupDb<P: AsRef<Path>>(src: &SqliteConnection, dst: P, progress: fn(backup::Progress))
//!     -> SqliteResult<()> {
//!     let mut dst = try!(SqliteConnection::open(dst));
//!     let backup = try!(backup::Backup::new(src, &mut dst));
//!     backup.run_to_completion(5, time::Duration::from_millis(250), Some(progress))
//! }
//! ```

use std::ffi::CString;
use std::marker::PhantomData;

use libc::c_int;
use std::thread;
use std::time::Duration;

use ffi;

use {SqliteConnection, SqliteError, SqliteResult, str_to_cstring};

/// Possible successful results of calling `Backup::step`.
pub enum StepResult {
    /// The backup is complete.
    Done,

    /// The step was successful but there are still more pages that need to be backed up.
    More,

    /// The step failed because appropriate locks could not be aquired. This is
    /// not a fatal error - the step can be retried.
    Busy,

    /// The step failed because the source connection was writing to the
    /// database. This is not a fatal error - the step can be retried.
    Locked,
}

/// Name for the database to back up. Can be specified for both the source and
/// destination.
pub enum BackupName {
    /// The main database. This is typically what you want.
    Main,
    /// Back up the temporary database (e.g., any "CREATE TEMPORARY TABLE" tables).
    Temp,
    /// Backup a database that has been attached via "ATTACH DATABASE ...".
    Attached(String),
}

impl BackupName {
    fn to_cstring(self) -> SqliteResult<CString> {
        match self {
            BackupName::Main => str_to_cstring("main"),
            BackupName::Temp => str_to_cstring("temp"),
            BackupName::Attached(s) => str_to_cstring(&s),
        }
    }
}

/// Struct specifying the progress of a backup. The percentage completion can
/// be calculated as `(pagecount - remaining) / pagecount`. The progress of a
/// backup is as of the last call to `step` - if the source database is
/// modified after a call to `step`, the progress value will become outdated
/// and potentially incorrect.
#[derive(Copy,Clone,Debug)]
pub struct Progress {
    /// Number of pages in the source database that still need to be backed up.
    pub remaining: c_int,
    /// Total number of pages in the source database.
    pub pagecount: c_int,
}

/// A handle to an online backup.
pub struct Backup<'a, 'b> {
    phantom_from: PhantomData<&'a ()>,
    phantom_to: PhantomData<&'b ()>,
    b: *mut ffi::sqlite3_backup,
}

impl<'a, 'b> Backup<'a, 'b> {
    /// Attempt to create a new handle that will allow backups from `from` to
    /// `to`. Note that `to` is a `&mut` - this is because SQLite forbids any
    /// API calls on the destination of a backup while the backup is taking
    /// place.
    ///
    /// # Failure
    ///
    /// Will return `Err` if the underlying `sqlite3_backup_init` call returns
    /// `NULL`.
    pub fn new(from: &'a SqliteConnection,
               to: &'b mut SqliteConnection) -> SqliteResult<Backup<'a, 'b>> {
        Backup::new_with_names(from, BackupName::Main, to, BackupName::Main)
    }

    /// Attempt to create a new handle that will allow backups from the
    /// `from_name` database of `from` to the `to_name` database of `to`. Note
    /// that `to` is a `&mut` - this is because SQLite forbids any API calls on
    /// the destination of a backup while the backup is taking place.
    ///
    /// # Failure
    ///
    /// Will return `Err` if the underlying `sqlite3_backup_init` call returns
    /// `NULL`.
    pub fn new_with_names(from: &'a SqliteConnection, from_name: BackupName,
                          to: &'b mut SqliteConnection, to_name: BackupName)
        -> SqliteResult<Backup<'a, 'b>>
    {
        let to_name = try!(to_name.to_cstring());
        let from_name = try!(from_name.to_cstring());

        let to_db = to.db.borrow_mut().db;

        let b = unsafe {
            let b = ffi::sqlite3_backup_init(to_db, to_name.as_ptr(),
                                             from.db.borrow_mut().db, from_name.as_ptr());
            if b.is_null() {
                return Err(SqliteError::from_handle(to_db, ffi::sqlite3_errcode(to_db)));
            }
            b
        };

        Ok(Backup{
            phantom_from: PhantomData,
            phantom_to: PhantomData,
            b: b,
        })
    }

    /// Gets the progress of the backup as of the last call to `step`.
    pub fn progress(&self) -> Progress {
        unsafe {
            Progress{
                remaining: ffi::sqlite3_backup_remaining(self.b),
                pagecount: ffi::sqlite3_backup_pagecount(self.b),
            }
        }
    }

    /// Attempts to back up the given number of pages. If `num_pages` is
    /// negative, will attempt to back up all remaining pages. This will hold a
    /// lock on the source database for the duration, so it is probably not
    /// what you want for databases that are currently active (see
    /// `run_to_completion` for a better alternative).
    ///
    /// # Failure
    ///
    /// Will return `Err` if the underlying `sqlite3_backup_step` call returns
    /// an error code other than `DONE`, `OK`, `BUSY`, or `LOCKED`. `BUSY` and
    /// `LOCKED` are transient errors and are therefore returned as possible
    /// `Ok` values.
    pub fn step(&self, num_pages: c_int) -> SqliteResult<StepResult> {
        use self::StepResult::{Done, More, Busy, Locked};

        let rc = unsafe {
            ffi::sqlite3_backup_step(self.b, num_pages)
        };
        match rc {
            ffi::SQLITE_DONE   => Ok(Done),
            ffi::SQLITE_OK     => Ok(More),
            ffi::SQLITE_BUSY   => Ok(Busy),
            ffi::SQLITE_LOCKED => Ok(Locked),
            rc =>
                Err(SqliteError{ code: rc, message: ffi::code_to_str(rc).into() })
        }
    }

    /// Attempts to run the entire backup. Will call `step(pages_per_step)` as
    /// many times as necessary, sleeping for `pause_between_pages` between
    /// each call to give the source database time to process any pending
    /// queries. This is a direct implementation of "Example 2: Online Backup
    /// of a Running Database" from [SQLite's Online Backup API
    /// documentation](https://www.sqlite.org/backup.html).
    ///
    /// If `progress` is not `None`, it will be called after each step with the
    /// current progress of the backup. Note that is possible the progress may
    /// not change if the step returns `Busy` or `Locked` even though the
    /// backup is still running.
    ///
    /// # Failure
    ///
    /// Will return `Err` if any of the calls to `step` return `Err`.
    pub fn run_to_completion(&self, pages_per_step: c_int, pause_between_pages: Duration,
                             progress: Option<fn(Progress)>) -> SqliteResult<()> {
        use self::StepResult::{Done, More, Busy, Locked};

        assert!(pages_per_step > 0, "pages_per_step must be positive");

        loop {
            let r = try!(self.step(pages_per_step));
            if let Some(progress) = progress {
                progress(self.progress())
            }
            match r {
                More | Busy | Locked => thread::sleep(pause_between_pages),
                Done => return Ok(()),
            }
        }
    }
}

impl<'a, 'b> Drop for Backup<'a, 'b> {
    fn drop(&mut self) {
        unsafe { ffi::sqlite3_backup_finish(self.b) };
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;
    use std::time::Duration;
    use super::{Backup, BackupName};

    #[test]
    fn test_backup() {
        let src = SqliteConnection::open_in_memory().unwrap();
        let sql = "BEGIN;
                   CREATE TABLE foo(x INTEGER);
                   INSERT INTO foo VALUES(42);
                   END;";
        src.execute_batch(sql).unwrap();

        let mut dst = SqliteConnection::open_in_memory().unwrap();

        {
            let backup = Backup::new(&src, &mut dst).unwrap();
            backup.step(-1).unwrap();
        }

        let the_answer = dst.query_row("SELECT x FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42, the_answer);

        src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();

        {
            let backup = Backup::new(&src, &mut dst).unwrap();
            backup.run_to_completion(5, Duration::from_millis(250), None).unwrap();
        }

        let the_answer = dst.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42 + 43, the_answer);
    }

    #[test]
    fn test_backup_temp() {
        let src = SqliteConnection::open_in_memory().unwrap();
        let sql = "BEGIN;
                   CREATE TEMPORARY TABLE foo(x INTEGER);
                   INSERT INTO foo VALUES(42);
                   END;";
        src.execute_batch(sql).unwrap();

        let mut dst = SqliteConnection::open_in_memory().unwrap();

        {
            let backup = Backup::new_with_names(&src, BackupName::Temp, &mut dst, BackupName::Main)
                .unwrap();
            backup.step(-1).unwrap();
        }

        let the_answer = dst.query_row("SELECT x FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42, the_answer);

        src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();

        {
            let backup = Backup::new_with_names(&src, BackupName::Temp, &mut dst, BackupName::Main)
                .unwrap();
            backup.run_to_completion(5, Duration::from_millis(250), None).unwrap();
        }

        let the_answer = dst.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42 + 43, the_answer);
    }

    #[test]
    fn test_backup_attached() {
        let src = SqliteConnection::open_in_memory().unwrap();
        let sql = "ATTACH DATABASE ':memory:' AS my_attached;
                   BEGIN;
                   CREATE TABLE my_attached.foo(x INTEGER);
                   INSERT INTO my_attached.foo VALUES(42);
                   END;";
        src.execute_batch(sql).unwrap();

        let mut dst = SqliteConnection::open_in_memory().unwrap();

        {
            let backup = Backup::new_with_names(&src, BackupName::Attached("my_attached".into()),
                                                &mut dst, BackupName::Main).unwrap();
            backup.step(-1).unwrap();
        }

        let the_answer = dst.query_row("SELECT x FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42, the_answer);

        src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();

        {
            let backup = Backup::new_with_names(&src, BackupName::Attached("my_attached".into()),
                                                &mut dst, BackupName::Main).unwrap();
            backup.run_to_completion(5, Duration::from_millis(250), None).unwrap();
        }

        let the_answer = dst.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42 + 43, the_answer);
    }
}
<commit_msg>Use &str instead of String inside BackupName<commit_after>//! Online SQLite backup API.
//!
//! To create a `Backup`, you must have two distinct `SqliteConnection`s - one
//! for the source (which can be used while the backup is running) and one for
//! the destination (which cannot).  A `Backup` handle exposes three methods:
//! `step` will attempt to back up a specified number of pages, `progress` gets
//! the current progress of the backup as of the last call to `step`, and
//! `run_to_completion` will attempt to back up the entire source database,
//! allowing you to specify how many pages are backed up at a time and how long
//! the thread should sleep between chunks of pages.
//!
//! The following example is equivalent to "Example 2: Online Backup of a
//! Running Database" from [SQLite's Online Backup API
//! documentation](https://www.sqlite.org/backup.html).
//!
//! ```rust,no_run
//! # use rusqlite::{backup, SqliteConnection, SqliteResult};
//! # use std::path::Path;
//! # use std::time;
//!
//! fn backupDb<P: AsRef<Path>>(src: &SqliteConnection, dst: P, progress: fn(backup::Progress))
//!     -> SqliteResult<()> {
//!     let mut dst = try!(SqliteConnection::open(dst));
//!     let backup = try!(backup::Backup::new(src, &mut dst));
//!     backup.run_to_completion(5, time::Duration::from_millis(250), Some(progress))
//! }
//! ```

use std::ffi::CString;
use std::marker::PhantomData;

use libc::c_int;
use std::thread;
use std::time::Duration;

use ffi;

use {SqliteConnection, SqliteError, SqliteResult, str_to_cstring};

/// Possible successful results of calling `Backup::step`.
pub enum StepResult {
    /// The backup is complete.
    Done,

    /// The step was successful but there are still more pages that need to be backed up.
    More,

    /// The step failed because appropriate locks could not be aquired. This is
    /// not a fatal error - the step can be retried.
    Busy,

    /// The step failed because the source connection was writing to the
    /// database. This is not a fatal error - the step can be retried.
    Locked,
}

/// Name for the database to back up. Can be specified for both the source and
/// destination.
pub enum BackupName<'a> {
    /// The main database. This is typically what you want.
    Main,
    /// Back up the temporary database (e.g., any "CREATE TEMPORARY TABLE" tables).
    Temp,
    /// Backup a database that has been attached via "ATTACH DATABASE ...".
    Attached(&'a str),
}

impl<'a> BackupName<'a> {
    fn to_cstring(self) -> SqliteResult<CString> {
        match self {
            BackupName::Main => str_to_cstring("main"),
            BackupName::Temp => str_to_cstring("temp"),
            BackupName::Attached(s) => str_to_cstring(s),
        }
    }
}

/// Struct specifying the progress of a backup. The percentage completion can
/// be calculated as `(pagecount - remaining) / pagecount`. The progress of a
/// backup is as of the last call to `step` - if the source database is
/// modified after a call to `step`, the progress value will become outdated
/// and potentially incorrect.
#[derive(Copy,Clone,Debug)]
pub struct Progress {
    /// Number of pages in the source database that still need to be backed up.
    pub remaining: c_int,
    /// Total number of pages in the source database.
    pub pagecount: c_int,
}

/// A handle to an online backup.
pub struct Backup<'a, 'b> {
    phantom_from: PhantomData<&'a ()>,
    phantom_to: PhantomData<&'b ()>,
    b: *mut ffi::sqlite3_backup,
}

impl<'a, 'b> Backup<'a, 'b> {
    /// Attempt to create a new handle that will allow backups from `from` to
    /// `to`. Note that `to` is a `&mut` - this is because SQLite forbids any
    /// API calls on the destination of a backup while the backup is taking
    /// place.
    ///
    /// # Failure
    ///
    /// Will return `Err` if the underlying `sqlite3_backup_init` call returns
    /// `NULL`.
    pub fn new(from: &'a SqliteConnection,
               to: &'b mut SqliteConnection) -> SqliteResult<Backup<'a, 'b>> {
        Backup::new_with_names(from, BackupName::Main, to, BackupName::Main)
    }

    /// Attempt to create a new handle that will allow backups from the
    /// `from_name` database of `from` to the `to_name` database of `to`. Note
    /// that `to` is a `&mut` - this is because SQLite forbids any API calls on
    /// the destination of a backup while the backup is taking place.
    ///
    /// # Failure
    ///
    /// Will return `Err` if the underlying `sqlite3_backup_init` call returns
    /// `NULL`.
    pub fn new_with_names(from: &'a SqliteConnection, from_name: BackupName,
                          to: &'b mut SqliteConnection, to_name: BackupName)
        -> SqliteResult<Backup<'a, 'b>>
    {
        let to_name = try!(to_name.to_cstring());
        let from_name = try!(from_name.to_cstring());

        let to_db = to.db.borrow_mut().db;

        let b = unsafe {
            let b = ffi::sqlite3_backup_init(to_db, to_name.as_ptr(),
                                             from.db.borrow_mut().db, from_name.as_ptr());
            if b.is_null() {
                return Err(SqliteError::from_handle(to_db, ffi::sqlite3_errcode(to_db)));
            }
            b
        };

        Ok(Backup{
            phantom_from: PhantomData,
            phantom_to: PhantomData,
            b: b,
        })
    }

    /// Gets the progress of the backup as of the last call to `step`.
    pub fn progress(&self) -> Progress {
        unsafe {
            Progress{
                remaining: ffi::sqlite3_backup_remaining(self.b),
                pagecount: ffi::sqlite3_backup_pagecount(self.b),
            }
        }
    }

    /// Attempts to back up the given number of pages. If `num_pages` is
    /// negative, will attempt to back up all remaining pages. This will hold a
    /// lock on the source database for the duration, so it is probably not
    /// what you want for databases that are currently active (see
    /// `run_to_completion` for a better alternative).
    ///
    /// # Failure
    ///
    /// Will return `Err` if the underlying `sqlite3_backup_step` call returns
    /// an error code other than `DONE`, `OK`, `BUSY`, or `LOCKED`. `BUSY` and
    /// `LOCKED` are transient errors and are therefore returned as possible
    /// `Ok` values.
    pub fn step(&self, num_pages: c_int) -> SqliteResult<StepResult> {
        use self::StepResult::{Done, More, Busy, Locked};

        let rc = unsafe {
            ffi::sqlite3_backup_step(self.b, num_pages)
        };
        match rc {
            ffi::SQLITE_DONE   => Ok(Done),
            ffi::SQLITE_OK     => Ok(More),
            ffi::SQLITE_BUSY   => Ok(Busy),
            ffi::SQLITE_LOCKED => Ok(Locked),
            rc =>
                Err(SqliteError{ code: rc, message: ffi::code_to_str(rc).into() })
        }
    }

    /// Attempts to run the entire backup. Will call `step(pages_per_step)` as
    /// many times as necessary, sleeping for `pause_between_pages` between
    /// each call to give the source database time to process any pending
    /// queries. This is a direct implementation of "Example 2: Online Backup
    /// of a Running Database" from [SQLite's Online Backup API
    /// documentation](https://www.sqlite.org/backup.html).
    ///
    /// If `progress` is not `None`, it will be called after each step with the
    /// current progress of the backup. Note that is possible the progress may
    /// not change if the step returns `Busy` or `Locked` even though the
    /// backup is still running.
    ///
    /// # Failure
    ///
    /// Will return `Err` if any of the calls to `step` return `Err`.
    pub fn run_to_completion(&self, pages_per_step: c_int, pause_between_pages: Duration,
                             progress: Option<fn(Progress)>) -> SqliteResult<()> {
        use self::StepResult::{Done, More, Busy, Locked};

        assert!(pages_per_step > 0, "pages_per_step must be positive");

        loop {
            let r = try!(self.step(pages_per_step));
            if let Some(progress) = progress {
                progress(self.progress())
            }
            match r {
                More | Busy | Locked => thread::sleep(pause_between_pages),
                Done => return Ok(()),
            }
        }
    }
}

impl<'a, 'b> Drop for Backup<'a, 'b> {
    fn drop(&mut self) {
        unsafe { ffi::sqlite3_backup_finish(self.b) };
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;
    use std::time::Duration;
    use super::{Backup, BackupName};

    #[test]
    fn test_backup() {
        let src = SqliteConnection::open_in_memory().unwrap();
        let sql = "BEGIN;
                   CREATE TABLE foo(x INTEGER);
                   INSERT INTO foo VALUES(42);
                   END;";
        src.execute_batch(sql).unwrap();

        let mut dst = SqliteConnection::open_in_memory().unwrap();

        {
            let backup = Backup::new(&src, &mut dst).unwrap();
            backup.step(-1).unwrap();
        }

        let the_answer = dst.query_row("SELECT x FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42, the_answer);

        src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();

        {
            let backup = Backup::new(&src, &mut dst).unwrap();
            backup.run_to_completion(5, Duration::from_millis(250), None).unwrap();
        }

        let the_answer = dst.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42 + 43, the_answer);
    }

    #[test]
    fn test_backup_temp() {
        let src = SqliteConnection::open_in_memory().unwrap();
        let sql = "BEGIN;
                   CREATE TEMPORARY TABLE foo(x INTEGER);
                   INSERT INTO foo VALUES(42);
                   END;";
        src.execute_batch(sql).unwrap();

        let mut dst = SqliteConnection::open_in_memory().unwrap();

        {
            let backup = Backup::new_with_names(&src, BackupName::Temp, &mut dst, BackupName::Main)
                .unwrap();
            backup.step(-1).unwrap();
        }

        let the_answer = dst.query_row("SELECT x FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42, the_answer);

        src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();

        {
            let backup = Backup::new_with_names(&src, BackupName::Temp, &mut dst, BackupName::Main)
                .unwrap();
            backup.run_to_completion(5, Duration::from_millis(250), None).unwrap();
        }

        let the_answer = dst.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42 + 43, the_answer);
    }

    #[test]
    fn test_backup_attached() {
        let src = SqliteConnection::open_in_memory().unwrap();
        let sql = "ATTACH DATABASE ':memory:' AS my_attached;
                   BEGIN;
                   CREATE TABLE my_attached.foo(x INTEGER);
                   INSERT INTO my_attached.foo VALUES(42);
                   END;";
        src.execute_batch(sql).unwrap();

        let mut dst = SqliteConnection::open_in_memory().unwrap();

        {
            let backup = Backup::new_with_names(&src, BackupName::Attached("my_attached"),
                                                &mut dst, BackupName::Main).unwrap();
            backup.step(-1).unwrap();
        }

        let the_answer = dst.query_row("SELECT x FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42, the_answer);

        src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();

        {
            let backup = Backup::new_with_names(&src, BackupName::Attached("my_attached"),
                                                &mut dst, BackupName::Main).unwrap();
            backup.run_to_completion(5, Duration::from_millis(250), None).unwrap();
        }

        let the_answer = dst.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get::<i64>(0)).unwrap();
        assert_eq!(42 + 43, the_answer);
    }
}
<|endoftext|>


<commit_before>use crate::ast::{Enum, Field, Input, Struct, Variant};
use crate::attr::Attrs;
use syn::{Error, Result};

pub(crate) const CHECKED: &str = "checked in validation";

impl Input<'_> {
    pub(crate) fn validate(&self) -> Result<()> {
        match self {
            Input::Struct(input) => input.validate(),
            Input::Enum(input) => input.validate(),
        }
    }
}

impl Struct<'_> {
    fn validate(&self) -> Result<()> {
        check_no_source_or_backtrace(&self.attrs)?;
        check_no_duplicate_source_or_backtrace(&self.fields)?;
        for field in &self.fields {
            field.validate()?;
        }
        Ok(())
    }
}

impl Enum<'_> {
    fn validate(&self) -> Result<()> {
        check_no_source_or_backtrace(&self.attrs)?;
        let has_display = self.has_display();
        for variant in &self.variants {
            variant.validate()?;
            if has_display && variant.attrs.display.is_none() {
                return Err(Error::new_spanned(
                    variant.original,
                    "missing #[error(\"...\")] display attribute",
                ));
            }
        }
        Ok(())
    }
}

impl Variant<'_> {
    fn validate(&self) -> Result<()> {
        check_no_source_or_backtrace(&self.attrs)?;
        check_no_duplicate_source_or_backtrace(&self.fields)?;
        for field in &self.fields {
            field.validate()?;
        }
        Ok(())
    }
}

impl Field<'_> {
    fn validate(&self) -> Result<()> {
        if let Some(display) = &self.attrs.display {
            return Err(Error::new_spanned(
                display.original,
                "not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant",
            ));
        }
        Ok(())
    }
}

fn check_no_source_or_backtrace(attrs: &Attrs) -> Result<()> {
    if let Some(source) = &attrs.source {
        return Err(Error::new_spanned(
            source,
            "not expected here; the #[source] attribute belongs on a specific field",
        ));
    }
    if let Some(backtrace) = &attrs.backtrace {
        return Err(Error::new_spanned(
            backtrace,
            "not expected here; the #[backtrace] attribute belongs on a specific field",
        ));
    }
    Ok(())
}

fn check_no_duplicate_source_or_backtrace(fields: &[Field]) -> Result<()> {
    let mut has_source = false;
    let mut has_backtrace = false;
    for field in fields {
        if let Some(source) = &field.attrs.source {
            if has_source {
                return Err(Error::new_spanned(source, "duplicate #[source] attribute"));
            }
            has_source = true;
        }
        if let Some(backtrace) = &field.attrs.backtrace {
            if has_backtrace {
                return Err(Error::new_spanned(
                    backtrace,
                    "duplicate #[backtrace] attribute",
                ));
            }
            has_backtrace = true;
        }
    }
    Ok(())
}
<commit_msg>Rename attr validation methods<commit_after>use crate::ast::{Enum, Field, Input, Struct, Variant};
use crate::attr::Attrs;
use syn::{Error, Result};

pub(crate) const CHECKED: &str = "checked in validation";

impl Input<'_> {
    pub(crate) fn validate(&self) -> Result<()> {
        match self {
            Input::Struct(input) => input.validate(),
            Input::Enum(input) => input.validate(),
        }
    }
}

impl Struct<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        check_field_attrs(&self.fields)?;
        for field in &self.fields {
            field.validate()?;
        }
        Ok(())
    }
}

impl Enum<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        let has_display = self.has_display();
        for variant in &self.variants {
            variant.validate()?;
            if has_display && variant.attrs.display.is_none() {
                return Err(Error::new_spanned(
                    variant.original,
                    "missing #[error(\"...\")] display attribute",
                ));
            }
        }
        Ok(())
    }
}

impl Variant<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        check_field_attrs(&self.fields)?;
        for field in &self.fields {
            field.validate()?;
        }
        Ok(())
    }
}

impl Field<'_> {
    fn validate(&self) -> Result<()> {
        if let Some(display) = &self.attrs.display {
            return Err(Error::new_spanned(
                display.original,
                "not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant",
            ));
        }
        Ok(())
    }
}

fn check_non_field_attrs(attrs: &Attrs) -> Result<()> {
    if let Some(source) = &attrs.source {
        return Err(Error::new_spanned(
            source,
            "not expected here; the #[source] attribute belongs on a specific field",
        ));
    }
    if let Some(backtrace) = &attrs.backtrace {
        return Err(Error::new_spanned(
            backtrace,
            "not expected here; the #[backtrace] attribute belongs on a specific field",
        ));
    }
    Ok(())
}

fn check_field_attrs(fields: &[Field]) -> Result<()> {
    let mut has_source = false;
    let mut has_backtrace = false;
    for field in fields {
        if let Some(source) = &field.attrs.source {
            if has_source {
                return Err(Error::new_spanned(source, "duplicate #[source] attribute"));
            }
            has_source = true;
        }
        if let Some(backtrace) = &field.attrs.backtrace {
            if has_backtrace {
                return Err(Error::new_spanned(
                    backtrace,
                    "duplicate #[backtrace] attribute",
                ));
            }
            has_backtrace = true;
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;

use std::default::Default;
use std::sync::{Arc, Future};
use std::comm;

use postgres::SslMode;
use r2d2_postgres::PostgresPoolManager;
use r2d2_postgres::GenericConnection;

#[test]
fn test_basic() {
    let manager = PostgresPoolManager::new("postgres://postgres@localhost", SslMode::None);
    let config = r2d2::Config {
        pool_size: 2,
        ..Default::default()
    };
    let handler = r2d2::NoopErrorHandler;
    let pool = Arc::new(r2d2::Pool::new(config, manager, handler).unwrap());

    let (s1, r1) = comm::channel();
    let (s2, r2) = comm::channel();

    let pool1 = pool.clone();
    let mut fut1 = Future::spawn(proc() {
        let conn = pool1.get().unwrap();
        s1.send(());
        r2.recv();
        drop(conn);
    });

    let pool2 = pool.clone();
    let mut fut2 = Future::spawn(proc() {
        let conn = pool2.get().unwrap();
        s2.send(());
        r1.recv();
        drop(conn);
    });

    fut1.get();
    fut2.get();

    pool.get().unwrap();
}

#[test]
fn test_is_valid() {
    let manager = PostgresPoolManager::new("postgres://postgres@localhost", SslMode::None);
    let config = r2d2::Config {
        pool_size: 1,
        test_on_check_out: true,
        ..Default::default()
    };
    let handler = r2d2::NoopErrorHandler;
    let pool = r2d2::Pool::new(config, manager, handler).unwrap();

    pool.get().unwrap();
}

#[test]
fn test_statement_pool() {
    let config = r2d2_postgres::Config { statement_pool_size: 1 };
    let manager = r2d2_postgres::StatementCachingManager::new(
        "postgres://postgres@localhost", SslMode::None, config);
    let pool = r2d2::Pool::new(Default::default(), manager, r2d2::NoopErrorHandler).unwrap();

    let conn = pool.get().unwrap();
    let stmt = conn.prepare("SELECT 1::INT").unwrap();
    let stmt2 = conn.prepare("SELECT 1::INT").unwrap();
    assert_eq!(&*stmt as *const _, &*stmt2 as *const _);
    assert_eq!(stmt.query([]).unwrap().next().unwrap().get::<_, i32>(0), 1i32);

    let stmt3 = conn.prepare("SELECT 2::INT").unwrap();
    assert_eq!(stmt3.query([]).unwrap().next().unwrap().get::<_, i32>(0), 2i32);
    let stmt4 = conn.prepare("SELECT 1::INT").unwrap();
    let a = &*stmt as *const _;
    let b = &*stmt4 as *const _;
    assert!(a != b);
    assert_eq!(stmt4.query([]).unwrap().next().unwrap().get::<_, i32>(0), 1i32);
}
<commit_msg>Fix test builds<commit_after>extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;

use std::default::Default;
use std::sync::{Arc, Future};
use std::comm;

use postgres::SslMode;
use r2d2_postgres::PostgresPoolManager;
use r2d2_postgres::GenericConnection;

#[test]
fn test_basic() {
    let manager = PostgresPoolManager::new("postgres://postgres@localhost", SslMode::None);
    let config = r2d2::Config {
        pool_size: 2,
        ..Default::default()
    };
    let handler = r2d2::NoopErrorHandler;
    let pool = Arc::new(r2d2::Pool::new(config, manager, handler).unwrap());

    let (s1, r1) = comm::channel();
    let (s2, r2) = comm::channel();

    let pool1 = pool.clone();
    let mut fut1 = Future::spawn(proc() {
        let conn = pool1.get().unwrap();
        s1.send(());
        r2.recv();
        drop(conn);
    });

    let pool2 = pool.clone();
    let mut fut2 = Future::spawn(proc() {
        let conn = pool2.get().unwrap();
        s2.send(());
        r1.recv();
        drop(conn);
    });

    fut1.get();
    fut2.get();

    pool.get().unwrap();
}

#[test]
fn test_is_valid() {
    let manager = PostgresPoolManager::new("postgres://postgres@localhost", SslMode::None);
    let config = r2d2::Config {
        pool_size: 1,
        test_on_check_out: true,
        ..Default::default()
    };
    let handler = r2d2::NoopErrorHandler;
    let pool = r2d2::Pool::new(config, manager, handler).unwrap();

    pool.get().unwrap();
}

#[test]
fn test_statement_pool() {
    let config = r2d2_postgres::Config { statement_pool_size: 1 };
    let manager = r2d2_postgres::StatementCachingManager::new(
        "postgres://postgres@localhost", SslMode::None, config);
    let pool = r2d2::Pool::new(Default::default(), manager, r2d2::NoopErrorHandler).unwrap();

    let conn = pool.get().unwrap();
    let stmt = conn.prepare("SELECT 1::INT").unwrap();
    let stmt2 = conn.prepare("SELECT 1::INT").unwrap();
    assert_eq!(&*stmt as *const _, &*stmt2 as *const _);
    assert_eq!(stmt.query(&[]).unwrap().next().unwrap().get::<_, i32>(0), 1i32);

    let stmt3 = conn.prepare("SELECT 2::INT").unwrap();
    assert_eq!(stmt3.query(&[]).unwrap().next().unwrap().get::<_, i32>(0), 2i32);
    let stmt4 = conn.prepare("SELECT 1::INT").unwrap();
    let a = &*stmt as *const _;
    let b = &*stmt4 as *const _;
    assert!(a != b);
    assert_eq!(stmt4.query(&[]).unwrap().next().unwrap().get::<_, i32>(0), 1i32);
}
<|endoftext|>


<commit_before>extern crate r2d2;

use std::default::Default;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::sync::mpsc::{self, SyncSender, Receiver};
use std::sync::{Mutex, Arc};
use std::time::Duration;
use std::thread;

mod config;

#[derive(Debug, PartialEq)]
struct FakeConnection;

struct OkManager;

impl r2d2::ManageConnection for OkManager {
    type Connection = FakeConnection;
    type Error = ();

    fn connect(&self) -> Result<FakeConnection, ()> {
        Ok(FakeConnection)
    }

    fn is_valid(&self, _: &mut FakeConnection) -> Result<(), ()> {
        Ok(())
    }

    fn has_broken(&self, _: &mut FakeConnection) -> bool {
        false
    }
}

struct NthConnectFailManager {
    n: Mutex<u32>,
}

impl r2d2::ManageConnection for NthConnectFailManager {
    type Connection = FakeConnection;
    type Error = ();

    fn connect(&self) -> Result<FakeConnection, ()> {
        let mut n = self.n.lock().unwrap();
        if *n > 0 {
            *n -= 1;
            Ok(FakeConnection)
        } else {
            Err(())
        }
    }

    fn is_valid(&self, _: &mut FakeConnection) -> Result<(), ()> {
        Ok(())
    }

    fn has_broken(&self, _: &mut FakeConnection) -> bool {
        false
    }
}

#[test]
fn test_pool_size_ok() {
    let config = r2d2::Config::builder().pool_size(5).build();
    let manager = NthConnectFailManager { n: Mutex::new(5) };
    let pool = r2d2::Pool::new(config, manager).unwrap();
    let mut conns = vec![];
    for _ in 0..5 {
        conns.push(pool.get().ok().unwrap());
    }
}

#[test]
fn test_acquire_release() {
    let config = r2d2::Config::builder().pool_size(2).build();
    let pool = r2d2::Pool::new(config, OkManager).unwrap();

    let conn1 = pool.get().ok().unwrap();
    let conn2 = pool.get().ok().unwrap();
    drop(conn1);
    let conn3 = pool.get().ok().unwrap();
    drop(conn2);
    drop(conn3);
}

#[test]
fn test_is_send_sync() {
    fn is_send_sync<T: Send+Sync>() {}
    is_send_sync::<r2d2::Pool<OkManager>>();
}

#[test]
fn test_issue_2_unlocked_during_is_valid() {
    struct BlockingChecker {
        first: AtomicBool,
        s: Mutex<SyncSender<()>>,
        r: Mutex<Receiver<()>>,
    }

    impl r2d2::ManageConnection for BlockingChecker {
        type Connection = FakeConnection;
        type Error = ();

        fn connect(&self) -> Result<FakeConnection, ()> {
            Ok(FakeConnection)
        }

        fn is_valid(&self, _: &mut FakeConnection) -> Result<(), ()> {
            if self.first.compare_and_swap(true, false, Ordering::SeqCst) {
                self.s.lock().unwrap().send(()).unwrap();
                self.r.lock().unwrap().recv().unwrap();
            }
            Ok(())
        }

        fn has_broken(&self, _: &mut FakeConnection) -> bool {
            false
        }
    }

    let (s1, r1) = mpsc::sync_channel(0);
    let (s2, r2) = mpsc::sync_channel(0);

    let config = r2d2::Config::builder()
        .test_on_check_out(true)
        .pool_size(2)
        .build();
    let manager = BlockingChecker {
        first: AtomicBool::new(true),
        s: Mutex::new(s1),
        r: Mutex::new(r2),
    };
    let pool = Arc::new(r2d2::Pool::new(config, manager).unwrap());

    let p2 = pool.clone();
    let t = thread::spawn(move || {
        p2.get().ok().unwrap();
    });

    r1.recv().unwrap();
    // get call by other task has triggered the health check
    pool.get().ok().unwrap();
    s2.send(()).ok().unwrap();

    t.join().ok().unwrap();
}

#[test]
fn test_drop_on_broken() {
    static DROPPED: AtomicBool = ATOMIC_BOOL_INIT;
    DROPPED.store(false, Ordering::SeqCst);

    struct Connection;

    impl Drop for Connection {
        fn drop(&mut self) {
            DROPPED.store(true, Ordering::SeqCst);
        }
    }

    struct Handler;

    impl r2d2::ManageConnection for Handler {
        type Connection = Connection;
        type Error = ();

        fn connect(&self) -> Result<Connection, ()> {
            Ok(Connection)
        }

        fn is_valid(&self, _: &mut Connection) -> Result<(), ()> {
            Ok(())
        }

        fn has_broken(&self, _: &mut Connection) -> bool {
            true
        }
    }

    let pool = r2d2::Pool::new(Default::default(), Handler).unwrap();

    drop(pool.get().ok().unwrap());

    assert!(DROPPED.load(Ordering::SeqCst));
}

#[test]
fn test_initialization_failure() {
    let config = r2d2::Config::builder()
        .connection_timeout_ms(1000)
        .build();
    let manager = NthConnectFailManager {
        n: Mutex::new(0),
    };
    r2d2::Pool::new(config, manager).err().unwrap();
}

#[test]
fn test_get_timeout() {
    let config = r2d2::Config::builder()
        .pool_size(1)
        .connection_timeout(Duration::from_secs(1))
        .build();
    let pool = r2d2::Pool::new(config, OkManager).unwrap();
    let _c = pool.get().unwrap();
    pool.get().err().unwrap();
}

#[test]
fn test_connection_customizer() {
    static DROPPED: AtomicBool = ATOMIC_BOOL_INIT;
    DROPPED.store(false, Ordering::SeqCst);

    struct Connection(i32);

    impl Drop for Connection {
        fn drop(&mut self) {
            DROPPED.store(true, Ordering::SeqCst);
        }
    }

    struct Handler;

    impl r2d2::ManageConnection for Handler {
        type Connection = Connection;
        type Error = ();

        fn connect(&self) -> Result<Connection, ()> {
            Ok(Connection(0))
        }

        fn is_valid(&self, _: &mut Connection) -> Result<(), ()> {
            Ok(())
        }

        fn has_broken(&self, _: &mut Connection) -> bool {
            true
        }
    }

    struct Customizer;

    impl r2d2::CustomizeConnection<Connection, ()> for Customizer {
        fn on_acquire(&self, conn: &mut Connection) -> Result<(), ()> {
            if !DROPPED.load(Ordering::SeqCst) {
                Err(())
            } else {
                conn.0 = 1;
                Ok(())
            }
        }
    }

    let config = r2d2::Config::builder()
        .connection_customizer(Box::new(Customizer))
        .build();
    let pool = r2d2::Pool::new(config, Handler).unwrap();

    let conn = pool.get().unwrap();
    assert_eq!(1, conn.0);
    assert!(DROPPED.load(Ordering::SeqCst));
}
<commit_msg>Work around ZST bug in 1.3<commit_after>extern crate r2d2;

use std::default::Default;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::sync::mpsc::{self, SyncSender, Receiver};
use std::sync::{Mutex, Arc};
use std::time::Duration;
use std::thread;

mod config;

#[derive(Debug, PartialEq)]
struct FakeConnection(bool);

struct OkManager;

impl r2d2::ManageConnection for OkManager {
    type Connection = FakeConnection;
    type Error = ();

    fn connect(&self) -> Result<FakeConnection, ()> {
        Ok(FakeConnection(true))
    }

    fn is_valid(&self, _: &mut FakeConnection) -> Result<(), ()> {
        Ok(())
    }

    fn has_broken(&self, _: &mut FakeConnection) -> bool {
        false
    }
}

struct NthConnectFailManager {
    n: Mutex<u32>,
}

impl r2d2::ManageConnection for NthConnectFailManager {
    type Connection = FakeConnection;
    type Error = ();

    fn connect(&self) -> Result<FakeConnection, ()> {
        let mut n = self.n.lock().unwrap();
        if *n > 0 {
            *n -= 1;
            Ok(FakeConnection(true))
        } else {
            Err(())
        }
    }

    fn is_valid(&self, _: &mut FakeConnection) -> Result<(), ()> {
        Ok(())
    }

    fn has_broken(&self, _: &mut FakeConnection) -> bool {
        false
    }
}

#[test]
fn test_pool_size_ok() {
    let config = r2d2::Config::builder().pool_size(5).build();
    let manager = NthConnectFailManager { n: Mutex::new(5) };
    let pool = r2d2::Pool::new(config, manager).unwrap();
    let mut conns = vec![];
    for _ in 0..5 {
        conns.push(pool.get().ok().unwrap());
    }
}

#[test]
fn test_acquire_release() {
    let config = r2d2::Config::builder().pool_size(2).build();
    let pool = r2d2::Pool::new(config, OkManager).unwrap();

    let conn1 = pool.get().ok().unwrap();
    let conn2 = pool.get().ok().unwrap();
    drop(conn1);
    let conn3 = pool.get().ok().unwrap();
    drop(conn2);
    drop(conn3);
}

#[test]
fn test_is_send_sync() {
    fn is_send_sync<T: Send+Sync>() {}
    is_send_sync::<r2d2::Pool<OkManager>>();
}

#[test]
fn test_issue_2_unlocked_during_is_valid() {
    struct BlockingChecker {
        first: AtomicBool,
        s: Mutex<SyncSender<()>>,
        r: Mutex<Receiver<()>>,
    }

    impl r2d2::ManageConnection for BlockingChecker {
        type Connection = FakeConnection;
        type Error = ();

        fn connect(&self) -> Result<FakeConnection, ()> {
            Ok(FakeConnection(true))
        }

        fn is_valid(&self, _: &mut FakeConnection) -> Result<(), ()> {
            if self.first.compare_and_swap(true, false, Ordering::SeqCst) {
                self.s.lock().unwrap().send(()).unwrap();
                self.r.lock().unwrap().recv().unwrap();
            }
            Ok(())
        }

        fn has_broken(&self, _: &mut FakeConnection) -> bool {
            false
        }
    }

    let (s1, r1) = mpsc::sync_channel(0);
    let (s2, r2) = mpsc::sync_channel(0);

    let config = r2d2::Config::builder()
        .test_on_check_out(true)
        .pool_size(2)
        .build();
    let manager = BlockingChecker {
        first: AtomicBool::new(true),
        s: Mutex::new(s1),
        r: Mutex::new(r2),
    };
    let pool = Arc::new(r2d2::Pool::new(config, manager).unwrap());

    let p2 = pool.clone();
    let t = thread::spawn(move || {
        p2.get().ok().unwrap();
    });

    r1.recv().unwrap();
    // get call by other task has triggered the health check
    pool.get().ok().unwrap();
    s2.send(()).ok().unwrap();

    t.join().ok().unwrap();
}

#[test]
fn test_drop_on_broken() {
    static DROPPED: AtomicBool = ATOMIC_BOOL_INIT;
    DROPPED.store(false, Ordering::SeqCst);

    struct Connection;

    impl Drop for Connection {
        fn drop(&mut self) {
            DROPPED.store(true, Ordering::SeqCst);
        }
    }

    struct Handler;

    impl r2d2::ManageConnection for Handler {
        type Connection = Connection;
        type Error = ();

        fn connect(&self) -> Result<Connection, ()> {
            Ok(Connection)
        }

        fn is_valid(&self, _: &mut Connection) -> Result<(), ()> {
            Ok(())
        }

        fn has_broken(&self, _: &mut Connection) -> bool {
            true
        }
    }

    let pool = r2d2::Pool::new(Default::default(), Handler).unwrap();

    drop(pool.get().ok().unwrap());

    assert!(DROPPED.load(Ordering::SeqCst));
}

#[test]
fn test_initialization_failure() {
    let config = r2d2::Config::builder()
        .connection_timeout_ms(1000)
        .build();
    let manager = NthConnectFailManager {
        n: Mutex::new(0),
    };
    r2d2::Pool::new(config, manager).err().unwrap();
}

#[test]
fn test_get_timeout() {
    let config = r2d2::Config::builder()
        .pool_size(1)
        .connection_timeout(Duration::from_secs(1))
        .build();
    let pool = r2d2::Pool::new(config, OkManager).unwrap();
    let _c = pool.get().unwrap();
    pool.get().err().unwrap();
}

#[test]
fn test_connection_customizer() {
    static DROPPED: AtomicBool = ATOMIC_BOOL_INIT;
    DROPPED.store(false, Ordering::SeqCst);

    struct Connection(i32);

    impl Drop for Connection {
        fn drop(&mut self) {
            DROPPED.store(true, Ordering::SeqCst);
        }
    }

    struct Handler;

    impl r2d2::ManageConnection for Handler {
        type Connection = Connection;
        type Error = ();

        fn connect(&self) -> Result<Connection, ()> {
            Ok(Connection(0))
        }

        fn is_valid(&self, _: &mut Connection) -> Result<(), ()> {
            Ok(())
        }

        fn has_broken(&self, _: &mut Connection) -> bool {
            true
        }
    }

    struct Customizer;

    impl r2d2::CustomizeConnection<Connection, ()> for Customizer {
        fn on_acquire(&self, conn: &mut Connection) -> Result<(), ()> {
            if !DROPPED.load(Ordering::SeqCst) {
                Err(())
            } else {
                conn.0 = 1;
                Ok(())
            }
        }
    }

    let config = r2d2::Config::builder()
        .connection_customizer(Box::new(Customizer))
        .build();
    let pool = r2d2::Pool::new(config, Handler).unwrap();

    let conn = pool.get().unwrap();
    assert_eq!(1, conn.0);
    assert!(DROPPED.load(Ordering::SeqCst));
}
<|endoftext|>


<commit_before>use std::ops::{Deref, DerefMut};

trait Graph {
	fn graph_fn(&self) -> u32 ;
}
trait GraphMut: Graph {
	fn graph_mut(&mut self) -> &mut u32;
}
trait GraphMut2: Graph {
	fn graph_mut2(&mut self) -> &mut u32;
}

trait BaseConstraint: Sized {
	type Graph: Graph;
	fn get_graph(&self) -> &Self::Graph;
	fn constrain<G>(self) -> Result<G, ()>
		where G: Constraint<Base=Self>
	{
		G::constrain(self)
	}
}
trait BaseConstraintMut: BaseConstraint
{
	fn get_graph_mut(&mut self) -> &mut Self::Graph;
}
trait Constraint: Sized
{
	type Base:  BaseConstraint;
	type Constrained: Constraint<Base=Self::Base>;

	fn base_single(&self) -> &Self::Constrained;
	fn unconstrain_single(self) -> Self::Constrained;
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()>;

	fn unconstrain(self) -> Self::Base{
		self.unconstrain_single().unconstrain()
	}
	fn constrain(g: Self::Base) -> Result<Self, ()>{
		Self::constrain_single(Self::Constrained::constrain(g)?)
	}
	fn base(&self) -> &<Self::Base as BaseConstraint>::Graph {
		self.base_single().base()
	}

}
trait ConstraintMut: Constraint
{
	type BaseMut:  BaseConstraintMut;
	type ConstrainedMut: ConstraintMut<BaseMut=Self::BaseMut>;
	fn base_single_mut(&mut self) -> &mut Self::ConstrainedMut;
	fn base_mut(&mut self) -> &mut <Self::BaseMut as BaseConstraint>::Graph {
		self.base_single_mut().base_mut()
	}
}

impl<G: Graph, D: Deref<Target=G>> BaseConstraint for D
{
	type Graph = G;
	fn get_graph(&self) -> &Self::Graph {&**self}
}
impl<G: GraphMut, D: DerefMut<Target=G>> BaseConstraintMut for D
{
	fn get_graph_mut(&mut self) -> &mut Self::Graph {&mut **self}
}
impl<B: BaseConstraint> Constraint for B {
	type Base = Self;
	type Constrained = Self;

	fn base_single(&self) -> &Self::Constrained { &self }
	fn unconstrain_single(self) -> Self::Constrained { self }
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()> { Ok(g)}

	fn unconstrain(self) -> Self::Base { self }
	fn constrain(g: Self::Base) -> Result<Self, ()>{ Ok(g) }
	fn base(&self) -> &<Self::Base as BaseConstraint>::Graph { self.get_graph() }
}
impl<B: BaseConstraintMut> ConstraintMut for B {
	type BaseMut = Self;
	type ConstrainedMut = Self;
	fn base_single_mut(&mut self) -> &mut Self::Constrained { self }
	fn base_mut(&mut self) -> &mut <Self::BaseMut as BaseConstraint>::Graph {
		self.get_graph_mut()
	}
}

struct BaseGraph(u32);
impl BaseGraph {
	fn base_graph_fn(&self) -> u32
	{
		self.0
	}
}
impl Graph for BaseGraph{
	fn graph_fn(&self) -> u32 {
		self.0
	}
}
impl GraphMut for BaseGraph {
	fn graph_mut(&mut self) -> &mut u32 { &mut self.0 }
}
impl BaseConstraint for BaseGraph {
	type Graph = Self;
	fn get_graph(&self) -> &Self::Graph {self}
}
impl BaseConstraintMut for BaseGraph{
	fn get_graph_mut(&mut self) -> &mut Self::Graph {self}
}

struct Connected<C: Constraint>(C);
impl<C: Constraint> Connected<C>
{
	fn connected_fn(&self) -> u32
	{
		self.base().graph_fn()
	}
}
impl<C: Constraint> Graph for Connected<C>{
	fn graph_fn(&self) -> u32 {
		self.base().graph_fn()
	}
}
impl<C: ConstraintMut> GraphMut for Connected<C>
	where <C::BaseMut as BaseConstraint>::Graph: GraphMut
{
	fn graph_mut(&mut self) -> &mut u32 { self.0.base_mut().graph_mut() }
}
impl<C: ConstraintMut> GraphMut2 for Connected<C>
	where <C::BaseMut as BaseConstraint>::Graph: GraphMut2
{
	fn graph_mut2(&mut self) -> &mut u32 { self.0.base_mut().graph_mut2() }
}
impl<C: Constraint> Constraint for Connected<C>
{
	type Base = C::Base;
	type Constrained = C;

	fn base_single(&self) -> &Self::Constrained { &self.0 }
	fn unconstrain_single(self) -> Self::Constrained { self.0 }
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()> {
		if g.base().graph_fn() < 32 {
			Ok(Self(g))
		} else {
			Err(())
		}

	}
}
impl<C: ConstraintMut> ConstraintMut for Connected<C>
{
	type BaseMut = C::BaseMut;
	type ConstrainedMut = C;

	fn base_single_mut(&mut self) -> &mut Self::ConstrainedMut { &mut self.0 }
}

#[test]
fn constrainer_constraining_base(){
	type ConstrainedGraphRef<'a> =
	Connected<
		Connected<
			&'a BaseGraph
		>>;

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), 16);

	let c_ref = ConstrainedGraphRef::constrain(&g).unwrap();
	assert_eq!(c_ref.connected_fn(), 16);

	type ConstrainedGraphMut<'a> =
	Connected<
		Connected<
			&'a mut BaseGraph
		>>;

	let mut c_ref_mut = ConstrainedGraphMut::constrain(&mut g).unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), 30);

	type ConstrainedGraph<'a> =
	Connected<
		Connected<
			BaseGraph
		>>;

	let c_owned = ConstrainedGraph::constrain(g).unwrap();
	assert_eq!(c_owned.connected_fn(), 30);

}

#[test]
fn inline_constrainer_constraining_base(){

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), 16);

	let c_ref = <Connected<Connected<&BaseGraph>>>::constrain(&g).unwrap();
	assert_eq!(c_ref.connected_fn(), 16);

	let mut c_ref_mut = <Connected<Connected<&mut BaseGraph>>>::constrain(&mut g).unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), 30);

	let c_owned = <Connected<Connected<BaseGraph>>>::constrain(g).unwrap();
	assert_eq!(c_owned.connected_fn(), 30);

}

#[test]
fn base_constrains_self_by_constraint_inference(){
	type ConstrainedGraph<G> = Connected< Connected< Connected<G> > >;

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), 16);

	let c_ref: ConstrainedGraph<&BaseGraph> = (&g).constrain().unwrap();
	assert_eq!(c_ref.connected_fn(), 16);
	let c_ref_unc = c_ref.unconstrain_single();
	assert_eq!(c_ref_unc.connected_fn(), 16);

	let mut c_ref_mut: ConstrainedGraph<&mut BaseGraph> = (&mut g).constrain().unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), 30);
	let mut c_ref_mut_unc = c_ref_mut.unconstrain_single();
	assert_eq!(c_ref_mut_unc.connected_fn(), 30);
	*c_ref_mut_unc.graph_mut() = 31;
	assert_eq!(c_ref_mut_unc.connected_fn(), 31);

	let c_owned: ConstrainedGraph<BaseGraph> = g.constrain().unwrap();
	assert_eq!(c_owned.connected_fn(), 31);
	let c_owned_unc = c_owned.unconstrain_single();
	assert_eq!(c_owned_unc.connected_fn(), 31);
	let g2 = c_owned_unc.unconstrain();
	assert_eq!(g2.base_graph_fn(), 31);
}

#[test]
fn base_constrains_self_by_inline_constraint_inference(){

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), 16);

	let c_ref: Connected<Connected<Connected<&BaseGraph>>> = (&g).constrain().unwrap();
	assert_eq!(c_ref.connected_fn(), 16);
	let c_ref_unc = c_ref.unconstrain_single();
	assert_eq!(c_ref_unc.connected_fn(), 16);

	let mut c_ref_mut: Connected<Connected<Connected<&mut BaseGraph>>> = (&mut g).constrain().unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), 30);
	let mut c_ref_mut_unc = c_ref_mut.unconstrain_single();
	assert_eq!(c_ref_mut_unc.connected_fn(), 30);
	*c_ref_mut_unc.graph_mut() = 31;
	assert_eq!(c_ref_mut_unc.connected_fn(), 31);

	let c_owned: Connected<Connected<Connected<BaseGraph>>> = g.constrain().unwrap();
	assert_eq!(c_owned.connected_fn(), 31);
	let c_owned_unc = c_owned.unconstrain_single();
	assert_eq!(c_owned_unc.connected_fn(), 31);
	let g2 = c_owned_unc.unconstrain();
	assert_eq!(g2.base_graph_fn(), 31);
}<commit_msg>Tested second mutable trait.<commit_after>use std::ops::{Deref, DerefMut};

trait Graph {
	fn graph_fn(&self) -> u32 ;
}
trait GraphMut: Graph {
	fn graph_mut(&mut self) -> &mut u32;
}
trait GraphMut2: Graph {
	fn graph_mut2(&mut self) -> &mut u32;
}

trait BaseConstraint: Sized {
	type Graph: Graph;
	fn get_graph(&self) -> &Self::Graph;
	fn constrain<G>(self) -> Result<G, ()>
		where G: Constraint<Base=Self>
	{
		G::constrain(self)
	}
}
trait BaseConstraintMut: BaseConstraint
{
	fn get_graph_mut(&mut self) -> &mut Self::Graph;
}
trait Constraint: Sized
{
	type Base:  BaseConstraint;
	type Constrained: Constraint<Base=Self::Base>;

	fn base_single(&self) -> &Self::Constrained;
	fn unconstrain_single(self) -> Self::Constrained;
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()>;

	fn unconstrain(self) -> Self::Base{
		self.unconstrain_single().unconstrain()
	}
	fn constrain(g: Self::Base) -> Result<Self, ()>{
		Self::constrain_single(Self::Constrained::constrain(g)?)
	}
	fn base(&self) -> &<Self::Base as BaseConstraint>::Graph {
		self.base_single().base()
	}

}
trait ConstraintMut: Constraint
{
	type BaseMut:  BaseConstraintMut;
	type ConstrainedMut: ConstraintMut<BaseMut=Self::BaseMut>;
	fn base_single_mut(&mut self) -> &mut Self::ConstrainedMut;
	fn base_mut(&mut self) -> &mut <Self::BaseMut as BaseConstraint>::Graph {
		self.base_single_mut().base_mut()
	}
}

impl<G: Graph, D: Deref<Target=G>> BaseConstraint for D
{
	type Graph = G;
	fn get_graph(&self) -> &Self::Graph {&**self}
}
impl<G: GraphMut, D: DerefMut<Target=G>> BaseConstraintMut for D
{
	fn get_graph_mut(&mut self) -> &mut Self::Graph {&mut **self}
}
impl<B: BaseConstraint> Constraint for B {
	type Base = Self;
	type Constrained = Self;

	fn base_single(&self) -> &Self::Constrained { &self }
	fn unconstrain_single(self) -> Self::Constrained { self }
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()> { Ok(g)}

	fn unconstrain(self) -> Self::Base { self }
	fn constrain(g: Self::Base) -> Result<Self, ()>{ Ok(g) }
	fn base(&self) -> &<Self::Base as BaseConstraint>::Graph { self.get_graph() }
}
impl<B: BaseConstraintMut> ConstraintMut for B {
	type BaseMut = Self;
	type ConstrainedMut = Self;
	fn base_single_mut(&mut self) -> &mut Self::Constrained { self }
	fn base_mut(&mut self) -> &mut <Self::BaseMut as BaseConstraint>::Graph {
		self.get_graph_mut()
	}
}

struct BaseGraph(u32);
impl BaseGraph {
	fn base_graph_fn(&self) -> u32
	{
		self.0
	}
}
impl Graph for BaseGraph{
	fn graph_fn(&self) -> u32 {
		self.0
	}
}
impl GraphMut for BaseGraph {
	fn graph_mut(&mut self) -> &mut u32 { &mut self.0 }
}
impl GraphMut2 for BaseGraph {
	fn graph_mut2(&mut self) -> &mut u32 { &mut self.0 }
}
impl BaseConstraint for BaseGraph {
	type Graph = Self;
	fn get_graph(&self) -> &Self::Graph {self}
}
impl BaseConstraintMut for BaseGraph{
	fn get_graph_mut(&mut self) -> &mut Self::Graph {self}
}

struct Connected<C: Constraint>(C);
impl<C: Constraint> Connected<C>
{
	fn connected_fn(&self) -> u32
	{
		self.base().graph_fn()
	}
}
impl<C: Constraint> Graph for Connected<C>{
	fn graph_fn(&self) -> u32 {
		self.base().graph_fn()
	}
}
impl<C: ConstraintMut> GraphMut for Connected<C>
	where <C::BaseMut as BaseConstraint>::Graph: GraphMut
{
	fn graph_mut(&mut self) -> &mut u32 { self.0.base_mut().graph_mut() }
}
impl<C: ConstraintMut> GraphMut2 for Connected<C>
	where <C::BaseMut as BaseConstraint>::Graph: GraphMut2
{
	fn graph_mut2(&mut self) -> &mut u32 { self.0.base_mut().graph_mut2() }
}
impl<C: Constraint> Constraint for Connected<C>
{
	type Base = C::Base;
	type Constrained = C;

	fn base_single(&self) -> &Self::Constrained { &self.0 }
	fn unconstrain_single(self) -> Self::Constrained { self.0 }
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()> {
		if g.base().graph_fn() < 32 {
			Ok(Self(g))
		} else {
			Err(())
		}

	}
}
impl<C: ConstraintMut> ConstraintMut for Connected<C>
{
	type BaseMut = C::BaseMut;
	type ConstrainedMut = C;

	fn base_single_mut(&mut self) -> &mut Self::ConstrainedMut { &mut self.0 }
}

#[test]
fn constrainer_constraining_base(){
	type ConstrainedGraphRef<'a> =
	Connected<
		Connected<
			&'a BaseGraph
		>>;

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), 16);

	let c_ref = ConstrainedGraphRef::constrain(&g).unwrap();
	assert_eq!(c_ref.connected_fn(), 16);

	type ConstrainedGraphMut<'a> =
	Connected<
		Connected<
			&'a mut BaseGraph
		>>;

	let mut c_ref_mut = ConstrainedGraphMut::constrain(&mut g).unwrap();
	*c_ref_mut.graph_mut() = 30;
	*c_ref_mut.graph_mut2() = 30;
	assert_eq!(c_ref_mut.connected_fn(), 30);

	type ConstrainedGraph<'a> =
	Connected<
		Connected<
			BaseGraph
		>>;

	let c_owned = ConstrainedGraph::constrain(g).unwrap();
	assert_eq!(c_owned.connected_fn(), 30);

}

#[test]
fn inline_constrainer_constraining_base(){

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), 16);

	let c_ref = <Connected<Connected<&BaseGraph>>>::constrain(&g).unwrap();
	assert_eq!(c_ref.connected_fn(), 16);

	let mut c_ref_mut = <Connected<Connected<&mut BaseGraph>>>::constrain(&mut g).unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), 30);

	let c_owned = <Connected<Connected<BaseGraph>>>::constrain(g).unwrap();
	assert_eq!(c_owned.connected_fn(), 30);

}

#[test]
fn base_constrains_self_by_constraint_inference(){
	type ConstrainedGraph<G> = Connected< Connected< Connected<G> > >;

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), 16);

	let c_ref: ConstrainedGraph<&BaseGraph> = (&g).constrain().unwrap();
	assert_eq!(c_ref.connected_fn(), 16);
	let c_ref_unc = c_ref.unconstrain_single();
	assert_eq!(c_ref_unc.connected_fn(), 16);

	let mut c_ref_mut: ConstrainedGraph<&mut BaseGraph> = (&mut g).constrain().unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), 30);
	let mut c_ref_mut_unc = c_ref_mut.unconstrain_single();
	assert_eq!(c_ref_mut_unc.connected_fn(), 30);
	*c_ref_mut_unc.graph_mut() = 31;
	assert_eq!(c_ref_mut_unc.connected_fn(), 31);

	let c_owned: ConstrainedGraph<BaseGraph> = g.constrain().unwrap();
	assert_eq!(c_owned.connected_fn(), 31);
	let c_owned_unc = c_owned.unconstrain_single();
	assert_eq!(c_owned_unc.connected_fn(), 31);
	let g2 = c_owned_unc.unconstrain();
	assert_eq!(g2.base_graph_fn(), 31);
}

#[test]
fn base_constrains_self_by_inline_constraint_inference(){

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), 16);

	let c_ref: Connected<Connected<Connected<&BaseGraph>>> = (&g).constrain().unwrap();
	assert_eq!(c_ref.connected_fn(), 16);
	let c_ref_unc = c_ref.unconstrain_single();
	assert_eq!(c_ref_unc.connected_fn(), 16);

	let mut c_ref_mut: Connected<Connected<Connected<&mut BaseGraph>>> = (&mut g).constrain().unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), 30);
	let mut c_ref_mut_unc = c_ref_mut.unconstrain_single();
	assert_eq!(c_ref_mut_unc.connected_fn(), 30);
	*c_ref_mut_unc.graph_mut() = 31;
	assert_eq!(c_ref_mut_unc.connected_fn(), 31);

	let c_owned: Connected<Connected<Connected<BaseGraph>>> = g.constrain().unwrap();
	assert_eq!(c_owned.connected_fn(), 31);
	let c_owned_unc = c_owned.unconstrain_single();
	assert_eq!(c_owned_unc.connected_fn(), 31);
	let g2 = c_owned_unc.unconstrain();
	assert_eq!(g2.base_graph_fn(), 31);
}<|endoftext|>


<commit_before>use std::ops;
use std::ptr;
use std::slice;
use std::result;
use std::str;

use ffi;

use error::{Error, Result};
use rand::Level;

pub struct Buffer {
    buf: *mut u8,
    len: usize,
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            ffi::gcry_free(self.buf as *mut _);
        }
    }
}

impl Buffer {
    pub unsafe fn from_raw(buf: *mut u8, len: usize) -> Buffer {
        debug_assert!(!buf.is_null());
        Buffer {
            buf: buf,
            len: len,
        }
    }

    pub fn new(len: usize) -> Result<Buffer> {
        let _ = ::get_token();
        unsafe {
            ffi::gcry_malloc(len).as_mut().map(|x| {
                Buffer::from_raw(x as *mut _ as *mut _, len)
            }).ok_or_else(|| Error::last_os_error())
        }
    }

    pub fn new_secure(len: usize) -> Result<Buffer> {
        let _ = ::get_token();
        unsafe {
            ffi::gcry_malloc_secure(len).as_mut().map(|x| {
                Buffer::from_raw(x as *mut _ as *mut _, len)
            }).ok_or_else(|| Error::last_os_error())
        }
    }

    pub fn try_clone(&self) -> Result<Buffer> {
        let result = if self.is_secure() {
            try!(Buffer::new_secure(self.len))
        } else {
            try!(Buffer::new(self.len))
        };
        unsafe {
            ptr::copy_nonoverlapping(self.buf, result.buf, self.len);
        }
        Ok(result)
    }

    pub fn random(len: usize, level: Level) -> Result<Buffer> {
        let _ = ::get_token();
        unsafe {
            ffi::gcry_random_bytes(len, level.raw()).as_mut().map(|x| {
                Buffer::from_raw(x as *mut _ as *mut _, len)
            }).ok_or_else(|| Error::last_os_error())
        }
    }

    pub fn random_secure(len: usize, level: Level) -> Result<Buffer> {
        let _ = ::get_token();
        unsafe {
            ffi::gcry_random_bytes_secure(len, level.raw()).as_mut().map(|x| {
                Buffer::from_raw(x as *mut _ as *mut _, len)
            }).ok_or_else(|| Error::last_os_error())
        }
    }

    pub fn is_secure(&self) -> bool {
        unsafe { ffi::gcry_is_secure(self.buf as *const _) != 0 }
    }

    pub fn as_bytes(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(self.buf, self.len) }
    }

    pub fn as_mut_bytes(&mut self) -> &mut [u8] {
        unsafe { slice::from_raw_parts_mut(self.buf, self.len) }
    }

    pub fn to_str(&self) -> result::Result<&str, str::Utf8Error> {
        str::from_utf8(self.as_bytes())
    }
}

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

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

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

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

impl AsMut<[u8]> for Buffer {
    fn as_mut(&mut self) -> &mut [u8] {
        self.as_mut_bytes()
    }
}
<commit_msg>Fix clippy lints<commit_after>use std::ops;
use std::ptr;
use std::slice;
use std::result;
use std::str;

use ffi;

use error::{Error, Result};
use rand::Level;

pub struct Buffer {
    buf: *mut u8,
    len: usize,
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            ffi::gcry_free(self.buf as *mut _);
        }
    }
}

impl Buffer {
    pub unsafe fn from_raw(buf: *mut u8, len: usize) -> Buffer {
        debug_assert!(!buf.is_null());
        Buffer {
            buf: buf,
            len: len,
        }
    }

    pub fn new(len: usize) -> Result<Buffer> {
        let _ = ::get_token();
        unsafe {
            ffi::gcry_malloc(len).as_mut().map(|x| {
                Buffer::from_raw(x as *mut _ as *mut _, len)
            }).ok_or_else(Error::last_os_error)
        }
    }

    pub fn new_secure(len: usize) -> Result<Buffer> {
        let _ = ::get_token();
        unsafe {
            ffi::gcry_malloc_secure(len).as_mut().map(|x| {
                Buffer::from_raw(x as *mut _ as *mut _, len)
            }).ok_or_else(Error::last_os_error)
        }
    }

    pub fn try_clone(&self) -> Result<Buffer> {
        let result = if self.is_secure() {
            try!(Buffer::new_secure(self.len))
        } else {
            try!(Buffer::new(self.len))
        };
        unsafe {
            ptr::copy_nonoverlapping(self.buf, result.buf, self.len);
        }
        Ok(result)
    }

    pub fn random(len: usize, level: Level) -> Result<Buffer> {
        let _ = ::get_token();
        unsafe {
            ffi::gcry_random_bytes(len, level.raw()).as_mut().map(|x| {
                Buffer::from_raw(x as *mut _ as *mut _, len)
            }).ok_or_else(Error::last_os_error)
        }
    }

    pub fn random_secure(len: usize, level: Level) -> Result<Buffer> {
        let _ = ::get_token();
        unsafe {
            ffi::gcry_random_bytes_secure(len, level.raw()).as_mut().map(|x| {
                Buffer::from_raw(x as *mut _ as *mut _, len)
            }).ok_or_else(Error::last_os_error)
        }
    }

    pub fn is_secure(&self) -> bool {
        unsafe { ffi::gcry_is_secure(self.buf as *const _) != 0 }
    }

    pub fn as_bytes(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(self.buf, self.len) }
    }

    pub fn as_mut_bytes(&mut self) -> &mut [u8] {
        unsafe { slice::from_raw_parts_mut(self.buf, self.len) }
    }

    pub fn to_str(&self) -> result::Result<&str, str::Utf8Error> {
        str::from_utf8(self.as_bytes())
    }
}

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

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

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

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

impl AsMut<[u8]> for Buffer {
    fn as_mut(&mut self) -> &mut [u8] {
        self.as_mut_bytes()
    }
}
<|endoftext|>


<commit_before>use amq_protocol::frame::{BackToTheBuffer, GenError, GenResult, WriteContext};
use std::{cmp, io};

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Buffer {
    memory: Vec<u8>,
    capacity: usize,
    position: usize,
    end: usize,
}

pub(crate) struct Checkpoint(usize);

impl Buffer {
    pub(crate) fn with_capacity(capacity: usize) -> Buffer {
        Buffer {
            memory: vec![0; capacity],
            capacity,
            position: 0,
            end: 0,
        }
    }

    pub(crate) fn checkpoint(&self) -> Checkpoint {
        Checkpoint(self.end)
    }

    pub(crate) fn rollback(&mut self, checkpoint: Checkpoint) {
        self.end = checkpoint.0;
    }

    pub(crate) fn grow(&mut self, new_size: usize) -> bool {
        if self.capacity >= new_size {
            return false;
        }

        self.memory.resize(new_size, 0);
        self.capacity = new_size;
        true
    }

    pub(crate) fn available_data(&self) -> usize {
        self.end - self.position
    }

    pub(crate) fn available_space(&self) -> usize {
        self.capacity - self.end
    }

    pub(crate) fn consume(&mut self, count: usize) -> usize {
        let cnt = cmp::min(count, self.available_data());
        self.position += cnt;
        cnt
    }

    pub(crate) fn fill(&mut self, count: usize) -> usize {
        let cnt = cmp::min(count, self.available_space());
        self.end += cnt;
        cnt
    }

    pub(crate) fn data(&self) -> &[u8] {
        &self.memory[self.position..self.end]
    }

    pub(crate) fn space(&mut self) -> &mut [u8] {
        &mut self.memory[self.end..self.capacity]
    }

    pub(crate) fn shift(&mut self) {
        let length = self.end - self.position;
        if length > self.position {
            return;
        } else {
            let (start, end) = self.memory.split_at_mut(self.position);
            start[..length].copy_from_slice(&end[..length]);
        }
        self.position = 0;
        self.end = length;
    }

    pub(crate) fn shift_unless_available(&mut self, size: usize) {
        if self.available_space() < size {
            self.shift();
        }
    }
}

impl io::Write for &mut Buffer {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        let amt = self.space().write(data)?;
        self.fill(amt);
        Ok(amt)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl BackToTheBuffer for &mut Buffer {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        mut s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        if s.write.available_space() < reserved {
            return Err(GenError::BufferTooSmall(
                reserved - s.write.available_space(),
            ));
        }
        let start = s.write.end;
        s.write.end += reserved;
        gen(s).and_then(|(s, tmp)| {
            let end = s.write.end;
            s.write.end = start;
            before(s, tmp).and_then(|s| {
                s.write.end = end;
                Ok(s)
            })
        })
    }
}

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

    #[test]
    fn fill_and_consume() {
        let mut b = Buffer::with_capacity(10);
        assert_eq!(b.available_data(), 0);
        assert_eq!(b.available_space(), 10);
        let res = b.space().write(&b"abcd"[..]).map(|size| {
            b.fill(size);
            size
        });
        assert_eq!(res.ok(), Some(4));
        assert_eq!(b.available_data(), 4);
        assert_eq!(b.available_space(), 6);

        assert_eq!(b.data(), &b"abcd"[..]);

        b.consume(2);
        assert_eq!(b.available_data(), 2);
        assert_eq!(b.available_space(), 6);
        assert_eq!(b.data(), &b"cd"[..]);

        b.shift();
        assert_eq!(b.available_data(), 2);
        assert_eq!(b.available_space(), 8);
        assert_eq!(b.data(), &b"cd"[..]);

        assert_eq!(
            b.space()
                .write(&b"efghijklmnop"[..])
                .map(|size| {
                    b.fill(size);
                    size
                })
                .ok(),
            Some(8)
        );
        assert_eq!(b.available_data(), 10);
        assert_eq!(b.available_space(), 0);
        assert_eq!(b.data(), &b"cdefghijkl"[..]);
        b.shift();
        assert_eq!(b.available_data(), 10);
        assert_eq!(b.available_space(), 0);
        assert_eq!(b.data(), &b"cdefghijkl"[..]);
    }
}
<commit_msg>buffer: use api instead of fields<commit_after>use amq_protocol::frame::{BackToTheBuffer, GenError, GenResult, WriteContext};
use std::{cmp, io};

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Buffer {
    memory: Vec<u8>,
    capacity: usize,
    position: usize,
    end: usize,
}

pub(crate) struct Checkpoint(usize);

impl Buffer {
    pub(crate) fn with_capacity(capacity: usize) -> Buffer {
        Buffer {
            memory: vec![0; capacity],
            capacity,
            position: 0,
            end: 0,
        }
    }

    pub(crate) fn checkpoint(&self) -> Checkpoint {
        Checkpoint(self.end)
    }

    pub(crate) fn rollback(&mut self, checkpoint: Checkpoint) {
        self.end = checkpoint.0;
    }

    pub(crate) fn grow(&mut self, new_size: usize) -> bool {
        if self.capacity >= new_size {
            return false;
        }

        self.memory.resize(new_size, 0);
        self.capacity = new_size;
        true
    }

    pub(crate) fn available_data(&self) -> usize {
        self.end - self.position
    }

    pub(crate) fn available_space(&self) -> usize {
        self.capacity - self.end
    }

    pub(crate) fn consume(&mut self, count: usize) -> usize {
        let cnt = cmp::min(count, self.available_data());
        self.position += cnt;
        cnt
    }

    pub(crate) fn fill(&mut self, count: usize) -> usize {
        let cnt = cmp::min(count, self.available_space());
        self.end += cnt;
        cnt
    }

    pub(crate) fn data(&self) -> &[u8] {
        &self.memory[self.position..self.end]
    }

    pub(crate) fn space(&mut self) -> &mut [u8] {
        &mut self.memory[self.end..self.capacity]
    }

    pub(crate) fn shift(&mut self) {
        let length = self.end - self.position;
        if length > self.position {
            return;
        } else {
            let (start, end) = self.memory.split_at_mut(self.position);
            start[..length].copy_from_slice(&end[..length]);
        }
        self.position = 0;
        self.end = length;
    }

    pub(crate) fn shift_unless_available(&mut self, size: usize) {
        if self.available_space() < size {
            self.shift();
        }
    }
}

impl io::Write for &mut Buffer {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        let amt = self.space().write(data)?;
        self.fill(amt);
        Ok(amt)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl BackToTheBuffer for &mut Buffer {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        if s.write.available_space() < reserved {
            return Err(GenError::BufferTooSmall(
                reserved - s.write.available_space(),
            ));
        }
        let start = s.write.checkpoint();
        s.write.fill(reserved);
        gen(s).and_then(|(s, tmp)| {
            let end = s.write.checkpoint();
            s.write.rollback(start);
            before(s, tmp).and_then(|s| {
                s.write.rollback(end);
                Ok(s)
            })
        })
    }
}

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

    #[test]
    fn fill_and_consume() {
        let mut b = Buffer::with_capacity(10);
        assert_eq!(b.available_data(), 0);
        assert_eq!(b.available_space(), 10);
        let res = b.space().write(&b"abcd"[..]).map(|size| {
            b.fill(size);
            size
        });
        assert_eq!(res.ok(), Some(4));
        assert_eq!(b.available_data(), 4);
        assert_eq!(b.available_space(), 6);

        assert_eq!(b.data(), &b"abcd"[..]);

        b.consume(2);
        assert_eq!(b.available_data(), 2);
        assert_eq!(b.available_space(), 6);
        assert_eq!(b.data(), &b"cd"[..]);

        b.shift();
        assert_eq!(b.available_data(), 2);
        assert_eq!(b.available_space(), 8);
        assert_eq!(b.data(), &b"cd"[..]);

        assert_eq!(
            b.space()
                .write(&b"efghijklmnop"[..])
                .map(|size| {
                    b.fill(size);
                    size
                })
                .ok(),
            Some(8)
        );
        assert_eq!(b.available_data(), 10);
        assert_eq!(b.available_space(), 0);
        assert_eq!(b.data(), &b"cdefghijkl"[..]);
        b.shift();
        assert_eq!(b.available_data(), 10);
        assert_eq!(b.available_space(), 0);
        assert_eq!(b.data(), &b"cdefghijkl"[..]);
    }
}
<|endoftext|>


<commit_before>extern crate lambda_calculus as lambda;

use lambda::*;
use lambda::church::option::*;
use lambda::church::numerals::succ;

#[test]
fn church_none() {
    assert_eq!(beta(None.into_church(), HAP, 0), none());
}

#[test]
fn church_some() {
    assert_eq!(beta(app(some(), 3.into_church()), HAP, 0), Some(3.into_church()).into_church());
}

#[test]
fn church_is_some() {
    assert_eq!(beta(app(is_some(), None.into_church()), HAP, 0), false.into_church());
    assert_eq!(beta(app(is_some(), Some(3.into_church()).into_church()), HAP, 0), true.into_church());
}

#[test]
fn church_is_none() {
    assert_eq!(beta(app(is_none(), None.into_church()), HAP, 0), true.into_church());
    assert_eq!(beta(app(is_none(), Some(3.into_church()).into_church()), HAP, 0), false.into_church());
}

#[test]
fn church_map_or() {
    assert_eq!(beta(app!(map_or(), 5.into_church(), succ(), None.into_church()), HAP, 0), 5.into_church());
    assert_eq!(beta(app!(map_or(), 5.into_church(), succ(), Some(1.into_church()).into_church()), HAP, 0), 2.into_church());
}

#[test]
fn church_unwrap_or() {
    assert_eq!(beta(app!(unwrap_or(), 5.into(), None.into()), HAP, 0), 5.into());
    assert_eq!(beta(app!(unwrap_or(), 5.into(), Some(1.into()).into()), HAP, 0), 1.into());
}
<commit_msg>fix option tests in tests/ directory<commit_after>extern crate lambda_calculus as lambda;

use lambda::*;
use lambda::church::option::*;
use lambda::church::numerals::succ;

#[test]
fn church_none() {
    assert_eq!(beta(None.into_church(), HAP, 0), none());
}

#[test]
fn church_some() {
    assert_eq!(beta(app(some(), 3.into_church()), HAP, 0), Some(3.into_church()).into_church());
}

#[test]
fn church_is_some() {
    assert_eq!(beta(app(is_some(), None.into_church()), HAP, 0), false.into_church());
    assert_eq!(beta(app(is_some(), Some(3.into_church()).into_church()), HAP, 0), true.into_church());
}

#[test]
fn church_is_none() {
    assert_eq!(beta(app(is_none(), None.into_church()), HAP, 0), true.into_church());
    assert_eq!(beta(app(is_none(), Some(3.into_church()).into_church()), HAP, 0), false.into_church());
}

#[test]
fn church_map_or() {
    assert_eq!(beta(app!(map_or(), 5.into_church(), succ(), None.into_church()), HAP, 0), 5.into_church());
    assert_eq!(beta(app!(map_or(), 5.into_church(), succ(), Some(1.into_church()).into_church()), HAP, 0), 2.into_church());
}

#[test]
fn church_unwrap_or() {
    assert_eq!(beta(app!(unwrap_or(), 5.into_church(), None.into_church()), HAP, 0), 5.into_church());
    assert_eq!(beta(app!(unwrap_or(), 5.into_church(), Some(1.into_church()).into_church()), HAP, 0), 1.into_church());
}
<|endoftext|>


<commit_before>// #![allow(dead_code)]

use std::iter;
use linked_hash_map::LinkedHashMap;

use parser::*;
use scope::*;
use processing::*;

#[allow(dead_code)]
pub struct ObjectMemberIter<'a: 'b, 'b, I: IntoIterator<Item = &'b str>> {
    // ctx: &'a mut Context,
    expr: &'a ExprValue,
    cur: Option<&'a ExprValue>,
    key: Option<&'b str>,
    iter: <I as iter::IntoIterator>::IntoIter
}

impl<'a: 'b, 'b, I: IntoIterator<Item = &'b str>> ObjectMemberIter<'a, 'b, I>
{
    #[allow(dead_code)]
    pub fn new(expr: &'a ExprValue, iter: I) -> Self {
        ObjectMemberIter {
            // ctx: ctx,
            expr: expr,
            cur: Some(expr),
            key: None,
            iter: iter.into_iter()
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum ObjectMemberState<'a> {
    InterimResult(&'a ExprValue),
    FinalResult(&'a ExprValue)
}

impl<'a: 'b, 'b, I: IntoIterator<Item = &'b str>> Iterator for ObjectMemberIter<'a, 'b, I>
{
    type Item = ObjectMemberState<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        let mut res: Option<&'a ExprValue> = None;
        let mut next_cur: Option<&'a ExprValue> = None;
        let mut next_key: Option<&str> = None;

        // let cur_key = self.next_key.as_ref().map(|s| s.to_owned());

        // Handle first iteration
        if self.key.is_none() {
            if let Some(next_key) = self.iter.next() {
                self.key = Some(next_key);
            }
        }

        // Get the next part in the path which was cached on the last iteration
        if let Some(key) = self.key {

            // If the next value is an object expression
            if let Some(&ExprValue::LiteralObject(Some(ref props))) = self.cur {
                let mut member_ref = props.iter().filter(|p| p.0 == key).take(1);

                if let Some(member_ref) = member_ref.next() {
                    if let Some(ref expr) = member_ref.1 {
                        res = Some(expr);
                    }
                }
            }
        }

        let mut next_key: Option<&str> = None;

        // Prepare next iteration
        if let Some(res) = res {
            if let Some(key) = self.iter.next() {
                next_key = Some(key);
            }

            if next_key.is_none() {
                return Some(ObjectMemberState::FinalResult(res));
            }

            self.key = next_key;
            self.cur = Some(res);

            return Some(ObjectMemberState::InterimResult(res));
        }

        None
    }
}

pub struct MemberResolver<'a: 'b, 'b,  I: IntoIterator<Item = &'b str>> {
    member_iter: ObjectMemberIter<'a, 'b, I>
    // path_iter: I
}

impl<'a : 'b, 'b, I: IntoIterator<Item = &'b str>> MemberResolver<'a, 'b, I> {
    pub fn new_with_parts(expr: &'a ExprValue, parts: I) -> Self {
        let member_iter: ObjectMemberIter<'a, 'b, I> = ObjectMemberIter::new(expr, parts);

        MemberResolver {
            member_iter: member_iter
        }
    }

    pub fn resolve_member(self) -> Option<&'a ExprValue> {

        for res in self.member_iter {
            match res {
                ObjectMemberState::InterimResult(..) => { continue; }
                ObjectMemberState::FinalResult(expr) => { return Some(expr); }
            };
        }
        None
    }

    // pub fn resolve_member_in_expr(&self, ctx: &mut Context, expr: &'a ExprValue, path: &'b str) -> Option<&'a ExprValue> {
    //     resolve_member_in_expr_with_parts(ctx, expr, path.split("."))
    // }
}

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

    #[test]
    pub fn test_members_path1() {
        // let mut ctx = Context::default();

        let obj = ExprValue::LiteralObject(Some(vec![
            ("a".into(), Some(ExprValue::LiteralString("x1".into())))
        ]));

        let path: Vec<String> = vec!["a".into()];

        let mut iter = ObjectMemberIter::new(&obj, path.iter().map(|p| p.as_str()));

        assert_eq!(iter.next(), Some(ObjectMemberState::FinalResult(&ExprValue::LiteralString("x1".into()))));
    }

    #[test]
    pub fn test_members_path2() {
        // let mut ctx = Context::default();

        let obj = ExprValue::LiteralObject(Some(vec![
            ("a".into(), Some(ExprValue::LiteralObject(Some(vec![
                ("b".into(), Some(ExprValue::LiteralString("y1".into())))
            ]))))
        ]));

        let path: Vec<String> = vec!["a".into(), "b".into()];

        let mut iter = ObjectMemberIter::new(&obj, path.iter().map(|p| p.as_str()));

        assert_eq!(iter.next(), Some(ObjectMemberState::InterimResult(&ExprValue::LiteralObject(Some(vec![ ("b".into(), Some(ExprValue::LiteralString("y1".into()))) ])))));
        assert_eq!(iter.next(), Some(ObjectMemberState::FinalResult(&ExprValue::LiteralString("y1".into()))));
    }

    #[test]
    pub fn test_resolve_member_in_expr1() {
        // let mut ctx = Context::default();

        let obj = ExprValue::LiteralObject(Some(vec![
            ("a".into(), Some(ExprValue::LiteralObject(Some(vec![
                ("b".into(), Some(ExprValue::LiteralString("y1".into())))
            ]))))
        ]));

        let path = "a.b";

        let member_resolver = MemberResolver::new_with_parts(&obj, path.split("."));
        let res = member_resolver.resolve_member();
        // let res = resolve_member_in_expr(&mut ctx, &obj, path);
        assert_eq!(res, Some(&ExprValue::LiteralString("y1".into())));
    }

}<commit_msg>Add more test cases to `MemberResolver`, implement `resolve_member_in_expr` using `MemberResolver`.<commit_after>// #![allow(dead_code)]

use std::iter;
use linked_hash_map::LinkedHashMap;

use parser::*;
use scope::*;
use processing::*;

#[allow(dead_code)]
pub struct ObjectMemberIter<'a: 'b, 'b, I: IntoIterator<Item = &'b str>> {
    // ctx: &'a mut Context,
    expr: &'a ExprValue,
    cur: Option<&'a ExprValue>,
    key: Option<&'b str>,
    iter: <I as iter::IntoIterator>::IntoIter
}

impl<'a: 'b, 'b, I: IntoIterator<Item = &'b str>> ObjectMemberIter<'a, 'b, I>
{
    #[allow(dead_code)]
    pub fn new(expr: &'a ExprValue, iter: I) -> Self {
        ObjectMemberIter {
            // ctx: ctx,
            expr: expr,
            cur: Some(expr),
            key: None,
            iter: iter.into_iter()
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum ObjectMemberState<'a> {
    InterimResult(&'a ExprValue),
    FinalResult(&'a ExprValue)
}

impl<'a: 'b, 'b, I: IntoIterator<Item = &'b str>> Iterator for ObjectMemberIter<'a, 'b, I>
{
    type Item = ObjectMemberState<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        let mut res: Option<&'a ExprValue> = None;
        let mut next_cur: Option<&'a ExprValue> = None;
        let mut next_key: Option<&str> = None;

        // let cur_key = self.next_key.as_ref().map(|s| s.to_owned());

        // Handle first iteration
        if self.key.is_none() {
            if let Some(next_key) = self.iter.next() {
                self.key = Some(next_key);
            }
        }

        // Get the next part in the path which was cached on the last iteration
        if let Some(key) = self.key {

            // If the next value is an object expression
            if let Some(&ExprValue::LiteralObject(Some(ref props))) = self.cur {
                let mut member_ref = props.iter().filter(|p| p.0 == key).take(1);

                if let Some(member_ref) = member_ref.next() {
                    if let Some(ref expr) = member_ref.1 {
                        res = Some(expr);
                    }
                }
            }
        }

        let mut next_key: Option<&str> = None;

        // Prepare next iteration
        if let Some(res) = res {
            if let Some(key) = self.iter.next() {
                next_key = Some(key);
            }

            if next_key.is_none() {
                return Some(ObjectMemberState::FinalResult(res));
            }

            self.key = next_key;
            self.cur = Some(res);

            return Some(ObjectMemberState::InterimResult(res));
        }

        None
    }
}

pub struct MemberResolver<'a: 'b, 'b,  I: IntoIterator<Item = &'b str>> {
    member_iter: ObjectMemberIter<'a, 'b, I>
    // path_iter: I
}

impl<'a : 'b, 'b, I: IntoIterator<Item = &'b str>> MemberResolver<'a, 'b, I> {
    pub fn new_with_parts(expr: &'a ExprValue, parts: I) -> Self {
        let member_iter: ObjectMemberIter<'a, 'b, I> = ObjectMemberIter::new(expr, parts);

        MemberResolver {
            member_iter: member_iter
        }
    }

    pub fn resolve_member(self) -> Option<&'a ExprValue> {

        for res in self.member_iter {
            match res {
                ObjectMemberState::InterimResult(..) => { continue; }
                ObjectMemberState::FinalResult(expr) => { return Some(expr); }
            };
        }
        None
    }
}

pub fn resolve_member_in_expr<'a, 'b>(expr: &'a ExprValue, path: &'b str) -> Option<&'a ExprValue> {
        let member_resolver = MemberResolver::new_with_parts(expr, path.split("."));
        member_resolver.resolve_member()
}

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

    #[test]
    pub fn test_members_path1() {
        let obj = ExprValue::LiteralObject(Some(vec![
            ("a".into(), Some(ExprValue::LiteralString("x1".into())))
        ]));

        let path: Vec<String> = vec!["a".into()];

        let mut iter = ObjectMemberIter::new(&obj, path.iter().map(|p| p.as_str()));

        assert_eq!(iter.next(), Some(ObjectMemberState::FinalResult(&ExprValue::LiteralString("x1".into()))));
    }

    #[test]
    pub fn test_members_path2() {
        let obj = ExprValue::LiteralObject(Some(vec![
            ("a".into(), Some(ExprValue::LiteralObject(Some(vec![
                ("b".into(), Some(ExprValue::LiteralString("y1".into())))
            ]))))
        ]));

        let path: Vec<String> = vec!["a".into(), "b".into()];

        let mut iter = ObjectMemberIter::new(&obj, path.iter().map(|p| p.as_str()));

        assert_eq!(iter.next(), Some(ObjectMemberState::InterimResult(&ExprValue::LiteralObject(Some(vec![ ("b".into(), Some(ExprValue::LiteralString("y1".into()))) ])))));
        assert_eq!(iter.next(), Some(ObjectMemberState::FinalResult(&ExprValue::LiteralString("y1".into()))));
    }

    #[test]
    pub fn test_resolve_member_in_expr1() {
        let obj = ExprValue::LiteralObject(Some(vec![
            ("a".into(), Some(ExprValue::LiteralObject(Some(vec![
                ("b".into(), Some(ExprValue::LiteralString("y1".into())))
            ]))))
        ]));

        let path = "a.b";

        let member_resolver = MemberResolver::new_with_parts(&obj, path.split("."));
        let res = member_resolver.resolve_member();
        assert_eq!(res, Some(&ExprValue::LiteralString("y1".into())));
    }

    #[test]
    pub fn test_resolve_member_in_expr2() {
        let obj = ExprValue::LiteralObject(Some(vec![
            ("a".into(), Some(ExprValue::LiteralObject(Some(vec![
                ("b".into(), Some(ExprValue::LiteralString("y1".into())))
            ]))))
        ]));

        let path = "a.b";
        let res = resolve_member_in_expr(&obj, &path);
        assert_eq!(res, Some(&ExprValue::LiteralString("y1".into())));
    }

    #[test]
    pub fn test_resolve_member_in_expr3() {
        let obj = ExprValue::LiteralObject(Some(vec![
            ("a".into(), Some(ExprValue::LiteralObject(Some(vec![
                ("b".into(), Some(ExprValue::LiteralString("y1".into())))
            ]))))
        ]));

        let res = resolve_member_in_expr(&obj, "a.b");
        assert_eq!(res, Some(&ExprValue::LiteralString("y1".into())));
    }

}<|endoftext|>