<commit_before>use failure::Fail;
use log::warn;
use std::{collections::HashMap, convert::From, fmt, iter};
use uuid::Uuid;

#[derive(Debug, Fail, Clone)]
pub enum Error {
    #[fail(display = "UniqueViolation")]
    UniqueViolation,
    #[fail(display = "NoTestQuery")]
    NoTestQuery { cmd: String },
    #[fail(display = "NoTestExecute")]
    NoTestExecute { cmd: String },
    #[fail(display = "PostgresError")]
    PostgresError { query: String, cause: String },
    #[fail(display = "R2D2Error")]
    R2D2Error { cause: String },
    #[fail(display = "NoSuchTable")]
    NoSuchTable,
    #[fail(display = "Value was NULL")]
    NullValue,
}

#[derive(Debug)]
pub struct HexSlice(Vec<u8>);

impl HexSlice {
    pub fn new(data: Vec<u8>) -> HexSlice {
        HexSlice(data)
    }

    pub fn sql(&self) -> String {
        format!("decode('{}', 'hex')", self)
    }
}

impl fmt::Display for HexSlice {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for byte in self.0.iter() {
            write!(f, "{:02X}", byte)?;
        }
        Ok(())
    }
}

pub trait FromSql {}
impl<T: FromSql> FromSql for Option<T> {}
impl FromSql for u32 {}
impl FromSql for Uuid {}
impl FromSql for String {}
impl<'a> FromSql for &'a str {}
impl FromSql for Vec<u8> {}
impl FromSql for serde_json::Value {}

#[derive(Debug, Clone)]
pub enum SqlValue {
    Null,
    U32(u32),
    UUID(Uuid),
    String(String),
    U8Bytes(Vec<u8>),
    JSON(serde_json::Value),
}

impl From<u32> for SqlValue {
    fn from(i: u32) -> SqlValue {
        SqlValue::U32(i)
    }
}

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub enum ValueIndex {
    U32(u32),
    String(String),
}

impl<'a> From<&'a str> for ValueIndex {
    fn from(s: &str) -> ValueIndex {
        ValueIndex::String(String::from(s))
    }
}

pub trait RowIndex {
    fn val(&self) -> ValueIndex;
}
impl RowIndex for u32 {
    fn val(&self) -> ValueIndex {
        ValueIndex::U32(*self)
    }
}
impl RowIndex for String {
    fn val(&self) -> ValueIndex {
        ValueIndex::String(self.clone())
    }
}
impl<'a> RowIndex for &'a str {
    fn val(&self) -> ValueIndex {
        ValueIndex::String(String::from(*self))
    }
}

#[derive(Debug, Clone, Default)]
pub struct TestRow {
    data: HashMap<ValueIndex, SqlValue>,
}

pub trait GetRow<T> {
    fn get<R>(&self, id: R) -> T
    where
        T: FromSql,
        R: RowIndex + fmt::Display;
}

impl TestRow {
    pub fn new() -> TestRow {
        TestRow { data: HashMap::new() }
    }

    pub fn insert<K, V>(&mut self, k: K, v: V) -> Option<SqlValue>
    where
        K: Into<ValueIndex>,
        V: Into<SqlValue>,
    {
        self.data.insert(k.into(), v.into())
    }
}

macro_rules! get_row {
    ($type: ty, $kind: path) => {
        impl GetRow<$type> for TestRow {
            fn get<R>(&self, id: R) -> $type
            where
                R: RowIndex + fmt::Display,
            {
                if !self.data.contains_key(&id.val()) {
                    panic!(format!("Can't find key {} in row", id));
                }
                match self.data[&id.val()] {
                    $kind(ref val) => val.clone(),
                    _ => panic!(),
                }
            }
        }

        impl GetRow<Option<$type>> for TestRow {
            fn get<R>(&self, id: R) -> Option<$type>
            where
                R: RowIndex + fmt::Display,
            {
                if !self.data.contains_key(&id.val()) {
                    panic!(format!("Can't find key {} in row", id));
                }
                match self.data[&id.val()] {
                    $kind(ref val) => Some(val.clone()),
                    SqlValue::Null => None,
                    _ => panic!(),
                }
            }
        }
    };
}

get_row!(u32, SqlValue::U32);
get_row!(Uuid, SqlValue::UUID);
get_row!(String, SqlValue::String);
get_row!(serde_json::Value, SqlValue::JSON);
get_row!(Vec<u8>, SqlValue::U8Bytes);

#[derive(Debug)]
pub enum Row<'a> {
    Postgres(postgres::rows::Row<'a>),
    Test(&'a TestRow),
}
impl<'a> Row<'a> {
    pub fn get<T, R>(&self, id: R) -> T
    where
        T: FromSql + postgres::types::FromSql,
        R: RowIndex + postgres::rows::RowIndex + fmt::Display + fmt::Debug,
        TestRow: GetRow<T>,
    {
        match *self {
            Row::Postgres(ref rows) => rows.get(id),
            Row::Test(ref rows) => rows.get(id),
        }
    }

    pub fn get_opt<T, R>(&self, id: R) -> Option<Result<T, Error>>
    where
        T: FromSql + postgres::types::FromSql,
        R: RowIndex + postgres::rows::RowIndex + fmt::Display + fmt::Debug,
        TestRow: GetRow<T>,
    {
        match *self {
            Row::Postgres(ref rows) => match rows.get_opt(id) {
                None => None,
                Some(val) => Some(val.map_err(|e| convert_postgres_error(e, ""))),
            },
            Row::Test(ref rows) => Some(Ok(rows.get(id))),
        }
    }

    pub fn get_with_null<T>(&self, index: &str) -> Option<T>
    where
        T: FromSql + postgres::types::FromSql,
        TestRow: GetRow<T>,
    {
        match self.get_opt(index) {
            Some(val) => match val {
                Ok(val) => Some(val),
                Err(Error::NullValue) => None,
                Err(err) => panic!("{:?}", err),
            },
            None => None,
        }
    }
}

#[derive(Debug)]
pub struct TestRowIterator<'a> {
    rows: &'a [TestRow],
    location: usize,
}

impl<'a> TestRowIterator<'a> {
    fn new(r: &'a [TestRow]) -> TestRowIterator<'a> {
        TestRowIterator { rows: r, location: 0 }
    }

    fn next(&mut self) -> Option<&'a TestRow> {
        self.location += 1;
        if self.location < self.rows.len() {
            Some(&self.rows[self.location])
        } else {
            None
        }
    }
}

pub enum RowIterator<'a> {
    Postgres(postgres::rows::Iter<'a>),
    Test(TestRowIterator<'a>),
}

impl<'a> fmt::Debug for RowIterator<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            RowIterator::Postgres(_) => write!(f, "RowIterator(PostgresRows)"),
            RowIterator::Test(ref rows) => write!(f, "RowIterator({:?})", rows),
        }
    }
}

impl<'a> Iterator for RowIterator<'a> {
    type Item = Row<'a>;

    fn next(&mut self) -> Option<Row<'a>> {
        match *self {
            RowIterator::Postgres(ref mut rows) => rows.next().map(Row::Postgres),
            RowIterator::Test(ref mut rows) => rows.next().map(Row::Test),
        }
    }
}

#[derive(Debug)]
pub enum Rows {
    Postgres(postgres::rows::Rows),
    Test(Vec<TestRow>),
}

impl<'stmt> Rows {
    pub fn get(&self, id: usize) -> Row {
        match *self {
            Rows::Postgres(ref rows) => Row::Postgres(rows.get(id)),
            Rows::Test(ref rows) => Row::Test(&rows[id]),
        }
    }
    pub fn is_empty(&self) -> bool {
        match *self {
            Rows::Postgres(ref rows) => rows.is_empty(),
            Rows::Test(ref rows) => rows.is_empty(),
        }
    }
    pub fn len(&self) -> usize {
        match *self {
            Rows::Postgres(ref rows) => rows.len(),
            Rows::Test(ref rows) => rows.len(),
        }
    }
    pub fn iter(&self) -> RowIterator {
        match *self {
            Rows::Postgres(ref rows) => RowIterator::Postgres(rows.iter()),
            Rows::Test(ref rows) => RowIterator::Test(TestRowIterator::new(rows)),
        }
    }
}

impl<'a> iter::IntoIterator for &'a Rows {
    type Item = Row<'a>;
    type IntoIter = RowIterator<'a>;
    fn into_iter(self) -> RowIterator<'a> {
        self.iter()
    }
}

#[derive(Debug, Clone, Default)]
pub struct TestConnection {
    query_results: Vec<(regex::Regex, Result<Vec<TestRow>, Error>)>,
    execute_results: Vec<(regex::Regex, Result<u64, Error>)>,
}

impl TestConnection {
    pub fn new() -> TestConnection {
        TestConnection {
            query_results: Vec::new(),
            execute_results: Vec::new(),
        }
    }

    pub fn add_test_query(&mut self, cmd: &str, results: Vec<TestRow>) {
        self.query_results.push((regex::Regex::new(cmd).unwrap(), Ok(results)));
    }

    // pub fn add_failed_query(&mut self, cmd: &str, err: ErrorKind) {
    //     self.query_results
    //         .push((regex::Regex::new(cmd).unwrap(), Err(Error::from(err))));
    // }

    pub fn add_test_execute(&mut self, cmd: &str, results: u64) {
        self.execute_results
            .push((regex::Regex::new(cmd).unwrap(), Ok(results)));
    }

    fn get_rows(&self, cmd: &str) -> Result<Vec<TestRow>, Error> {
        for &(ref patt, ref res) in self.query_results.iter() {
            if patt.is_match(cmd) {
                return res.clone();
            }
        }
        Err(Error::NoTestQuery { cmd: String::from(cmd) })
    }
    fn execute(&self, cmd: &str) -> Result<u64, Error> {
        for &(ref patt, ref res) in self.execute_results.iter() {
            if patt.is_match(cmd) {
                return res.clone();
            }
        }
        Err(Error::NoTestExecute { cmd: String::from(cmd) })
    }
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum Connection {
    Postgres(r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager>),
    Test(TestConnection),
}

fn convert_postgres_error(e: postgres_shared::error::Error, query: &str) -> Error {
    if let Some(dberror) = e.as_db() {
        if dberror.code == postgres_shared::error::UNIQUE_VIOLATION {
            return Error::UniqueViolation;
        }
    } else if let Some(converror) = e.as_conversion() {
        if converror.is::<postgres::types::WasNull>() {
            return Error::NullValue;
        }
    }
    warn!("Error: {:?}", &e);
    Error::PostgresError {
        query: query.to_string(),
        cause: e.to_string(),
    }
}

impl<'conn> Connection {
    pub fn query(&'conn self, query: &str) -> Result<Rows, Error> {
        match *self {
            Connection::Postgres(ref conn) => Ok(Rows::Postgres(
                conn.query(query, &[]).map_err(|e| convert_postgres_error(e, query))?,
            )),
            Connection::Test(ref conn) => Ok(Rows::Test(conn.get_rows(query)?)),
        }
    }
    pub fn execute(&self, equery: &str) -> Result<u64, Error> {
        match *self {
            Connection::Postgres(ref conn) => conn.execute(equery, &[]).map_err(|e| convert_postgres_error(e, equery)),
            Connection::Test(ref conn) => conn.execute(equery),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Pool {
    Postgres(r2d2::Pool<r2d2_postgres::PostgresConnectionManager>),
    TestPool(TestConnection),
}

impl Pool {
    pub fn get(&self) -> Result<Connection, Error> {
        match *self {
            Pool::Postgres(ref pool) => {
                let conn = pool.get().map_err(|e| Error::R2D2Error { cause: e.to_string() })?;
                Ok(Connection::Postgres(conn))
            }
            Pool::TestPool(ref conn) => Ok(Connection::Test(conn.clone())),
        }
    }

    pub fn wipe_db(&self) -> Result<(), Error> {
        let conn = self.get()?;
        conn.execute("DROP SCHEMA public CASCADE")?;
        conn.execute("CREATE SCHEMA public")?;
        Ok(())
    }
}
<commit_msg>Fix format use in panic<commit_after>use failure::Fail;
use log::warn;
use std::{collections::HashMap, convert::From, fmt, iter};
use uuid::Uuid;

#[derive(Debug, Fail, Clone)]
pub enum Error {
    #[fail(display = "UniqueViolation")]
    UniqueViolation,
    #[fail(display = "NoTestQuery")]
    NoTestQuery { cmd: String },
    #[fail(display = "NoTestExecute")]
    NoTestExecute { cmd: String },
    #[fail(display = "PostgresError")]
    PostgresError { query: String, cause: String },
    #[fail(display = "R2D2Error")]
    R2D2Error { cause: String },
    #[fail(display = "NoSuchTable")]
    NoSuchTable,
    #[fail(display = "Value was NULL")]
    NullValue,
}

#[derive(Debug)]
pub struct HexSlice(Vec<u8>);

impl HexSlice {
    pub fn new(data: Vec<u8>) -> HexSlice {
        HexSlice(data)
    }

    pub fn sql(&self) -> String {
        format!("decode('{}', 'hex')", self)
    }
}

impl fmt::Display for HexSlice {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for byte in self.0.iter() {
            write!(f, "{:02X}", byte)?;
        }
        Ok(())
    }
}

pub trait FromSql {}
impl<T: FromSql> FromSql for Option<T> {}
impl FromSql for u32 {}
impl FromSql for Uuid {}
impl FromSql for String {}
impl<'a> FromSql for &'a str {}
impl FromSql for Vec<u8> {}
impl FromSql for serde_json::Value {}

#[derive(Debug, Clone)]
pub enum SqlValue {
    Null,
    U32(u32),
    UUID(Uuid),
    String(String),
    U8Bytes(Vec<u8>),
    JSON(serde_json::Value),
}

impl From<u32> for SqlValue {
    fn from(i: u32) -> SqlValue {
        SqlValue::U32(i)
    }
}

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub enum ValueIndex {
    U32(u32),
    String(String),
}

impl<'a> From<&'a str> for ValueIndex {
    fn from(s: &str) -> ValueIndex {
        ValueIndex::String(String::from(s))
    }
}

pub trait RowIndex {
    fn val(&self) -> ValueIndex;
}
impl RowIndex for u32 {
    fn val(&self) -> ValueIndex {
        ValueIndex::U32(*self)
    }
}
impl RowIndex for String {
    fn val(&self) -> ValueIndex {
        ValueIndex::String(self.clone())
    }
}
impl<'a> RowIndex for &'a str {
    fn val(&self) -> ValueIndex {
        ValueIndex::String(String::from(*self))
    }
}

#[derive(Debug, Clone, Default)]
pub struct TestRow {
    data: HashMap<ValueIndex, SqlValue>,
}

pub trait GetRow<T> {
    fn get<R>(&self, id: R) -> T
    where
        T: FromSql,
        R: RowIndex + fmt::Display;
}

impl TestRow {
    pub fn new() -> TestRow {
        TestRow { data: HashMap::new() }
    }

    pub fn insert<K, V>(&mut self, k: K, v: V) -> Option<SqlValue>
    where
        K: Into<ValueIndex>,
        V: Into<SqlValue>,
    {
        self.data.insert(k.into(), v.into())
    }
}

macro_rules! get_row {
    ($type: ty, $kind: path) => {
        impl GetRow<$type> for TestRow {
            fn get<R>(&self, id: R) -> $type
            where
                R: RowIndex + fmt::Display,
            {
                if !self.data.contains_key(&id.val()) {
                    panic!("Can't find key {} in row", id);
                }
                match self.data[&id.val()] {
                    $kind(ref val) => val.clone(),
                    _ => panic!(),
                }
            }
        }

        impl GetRow<Option<$type>> for TestRow {
            fn get<R>(&self, id: R) -> Option<$type>
            where
                R: RowIndex + fmt::Display,
            {
                if !self.data.contains_key(&id.val()) {
                    panic!("Can't find key {} in row", id);
                }
                match self.data[&id.val()] {
                    $kind(ref val) => Some(val.clone()),
                    SqlValue::Null => None,
                    _ => panic!(),
                }
            }
        }
    };
}

get_row!(u32, SqlValue::U32);
get_row!(Uuid, SqlValue::UUID);
get_row!(String, SqlValue::String);
get_row!(serde_json::Value, SqlValue::JSON);
get_row!(Vec<u8>, SqlValue::U8Bytes);

#[derive(Debug)]
pub enum Row<'a> {
    Postgres(postgres::rows::Row<'a>),
    Test(&'a TestRow),
}
impl<'a> Row<'a> {
    pub fn get<T, R>(&self, id: R) -> T
    where
        T: FromSql + postgres::types::FromSql,
        R: RowIndex + postgres::rows::RowIndex + fmt::Display + fmt::Debug,
        TestRow: GetRow<T>,
    {
        match *self {
            Row::Postgres(ref rows) => rows.get(id),
            Row::Test(ref rows) => rows.get(id),
        }
    }

    pub fn get_opt<T, R>(&self, id: R) -> Option<Result<T, Error>>
    where
        T: FromSql + postgres::types::FromSql,
        R: RowIndex + postgres::rows::RowIndex + fmt::Display + fmt::Debug,
        TestRow: GetRow<T>,
    {
        match *self {
            Row::Postgres(ref rows) => match rows.get_opt(id) {
                None => None,
                Some(val) => Some(val.map_err(|e| convert_postgres_error(e, ""))),
            },
            Row::Test(ref rows) => Some(Ok(rows.get(id))),
        }
    }

    pub fn get_with_null<T>(&self, index: &str) -> Option<T>
    where
        T: FromSql + postgres::types::FromSql,
        TestRow: GetRow<T>,
    {
        match self.get_opt(index) {
            Some(val) => match val {
                Ok(val) => Some(val),
                Err(Error::NullValue) => None,
                Err(err) => panic!("{:?}", err),
            },
            None => None,
        }
    }
}

#[derive(Debug)]
pub struct TestRowIterator<'a> {
    rows: &'a [TestRow],
    location: usize,
}

impl<'a> TestRowIterator<'a> {
    fn new(r: &'a [TestRow]) -> TestRowIterator<'a> {
        TestRowIterator { rows: r, location: 0 }
    }

    fn next(&mut self) -> Option<&'a TestRow> {
        self.location += 1;
        if self.location < self.rows.len() {
            Some(&self.rows[self.location])
        } else {
            None
        }
    }
}

pub enum RowIterator<'a> {
    Postgres(postgres::rows::Iter<'a>),
    Test(TestRowIterator<'a>),
}

impl<'a> fmt::Debug for RowIterator<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            RowIterator::Postgres(_) => write!(f, "RowIterator(PostgresRows)"),
            RowIterator::Test(ref rows) => write!(f, "RowIterator({:?})", rows),
        }
    }
}

impl<'a> Iterator for RowIterator<'a> {
    type Item = Row<'a>;

    fn next(&mut self) -> Option<Row<'a>> {
        match *self {
            RowIterator::Postgres(ref mut rows) => rows.next().map(Row::Postgres),
            RowIterator::Test(ref mut rows) => rows.next().map(Row::Test),
        }
    }
}

#[derive(Debug)]
pub enum Rows {
    Postgres(postgres::rows::Rows),
    Test(Vec<TestRow>),
}

impl<'stmt> Rows {
    pub fn get(&self, id: usize) -> Row {
        match *self {
            Rows::Postgres(ref rows) => Row::Postgres(rows.get(id)),
            Rows::Test(ref rows) => Row::Test(&rows[id]),
        }
    }
    pub fn is_empty(&self) -> bool {
        match *self {
            Rows::Postgres(ref rows) => rows.is_empty(),
            Rows::Test(ref rows) => rows.is_empty(),
        }
    }
    pub fn len(&self) -> usize {
        match *self {
            Rows::Postgres(ref rows) => rows.len(),
            Rows::Test(ref rows) => rows.len(),
        }
    }
    pub fn iter(&self) -> RowIterator {
        match *self {
            Rows::Postgres(ref rows) => RowIterator::Postgres(rows.iter()),
            Rows::Test(ref rows) => RowIterator::Test(TestRowIterator::new(rows)),
        }
    }
}

impl<'a> iter::IntoIterator for &'a Rows {
    type Item = Row<'a>;
    type IntoIter = RowIterator<'a>;
    fn into_iter(self) -> RowIterator<'a> {
        self.iter()
    }
}

#[derive(Debug, Clone, Default)]
pub struct TestConnection {
    query_results: Vec<(regex::Regex, Result<Vec<TestRow>, Error>)>,
    execute_results: Vec<(regex::Regex, Result<u64, Error>)>,
}

impl TestConnection {
    pub fn new() -> TestConnection {
        TestConnection {
            query_results: Vec::new(),
            execute_results: Vec::new(),
        }
    }

    pub fn add_test_query(&mut self, cmd: &str, results: Vec<TestRow>) {
        self.query_results.push((regex::Regex::new(cmd).unwrap(), Ok(results)));
    }

    // pub fn add_failed_query(&mut self, cmd: &str, err: ErrorKind) {
    //     self.query_results
    //         .push((regex::Regex::new(cmd).unwrap(), Err(Error::from(err))));
    // }

    pub fn add_test_execute(&mut self, cmd: &str, results: u64) {
        self.execute_results
            .push((regex::Regex::new(cmd).unwrap(), Ok(results)));
    }

    fn get_rows(&self, cmd: &str) -> Result<Vec<TestRow>, Error> {
        for &(ref patt, ref res) in self.query_results.iter() {
            if patt.is_match(cmd) {
                return res.clone();
            }
        }
        Err(Error::NoTestQuery { cmd: String::from(cmd) })
    }
    fn execute(&self, cmd: &str) -> Result<u64, Error> {
        for &(ref patt, ref res) in self.execute_results.iter() {
            if patt.is_match(cmd) {
                return res.clone();
            }
        }
        Err(Error::NoTestExecute { cmd: String::from(cmd) })
    }
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum Connection {
    Postgres(r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager>),
    Test(TestConnection),
}

fn convert_postgres_error(e: postgres_shared::error::Error, query: &str) -> Error {
    if let Some(dberror) = e.as_db() {
        if dberror.code == postgres_shared::error::UNIQUE_VIOLATION {
            return Error::UniqueViolation;
        }
    } else if let Some(converror) = e.as_conversion() {
        if converror.is::<postgres::types::WasNull>() {
            return Error::NullValue;
        }
    }
    warn!("Error: {:?}", &e);
    Error::PostgresError {
        query: query.to_string(),
        cause: e.to_string(),
    }
}

impl<'conn> Connection {
    pub fn query(&'conn self, query: &str) -> Result<Rows, Error> {
        match *self {
            Connection::Postgres(ref conn) => Ok(Rows::Postgres(
                conn.query(query, &[]).map_err(|e| convert_postgres_error(e, query))?,
            )),
            Connection::Test(ref conn) => Ok(Rows::Test(conn.get_rows(query)?)),
        }
    }
    pub fn execute(&self, equery: &str) -> Result<u64, Error> {
        match *self {
            Connection::Postgres(ref conn) => conn.execute(equery, &[]).map_err(|e| convert_postgres_error(e, equery)),
            Connection::Test(ref conn) => conn.execute(equery),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Pool {
    Postgres(r2d2::Pool<r2d2_postgres::PostgresConnectionManager>),
    TestPool(TestConnection),
}

impl Pool {
    pub fn get(&self) -> Result<Connection, Error> {
        match *self {
            Pool::Postgres(ref pool) => {
                let conn = pool.get().map_err(|e| Error::R2D2Error { cause: e.to_string() })?;
                Ok(Connection::Postgres(conn))
            }
            Pool::TestPool(ref conn) => Ok(Connection::Test(conn.clone())),
        }
    }

    pub fn wipe_db(&self) -> Result<(), Error> {
        let conn = self.get()?;
        conn.execute("DROP SCHEMA public CASCADE")?;
        conn.execute("CREATE SCHEMA public")?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>use XY;
use vec::Vec2;
use view::{SizeConstraint, View, ViewWrapper};

/// Wrapper around another view, with a controlled size.
///
/// Each axis can independently be set to:
///
/// * Keep a **fixed** size
/// * Use **all** available size
/// * Use **at most** a given size
/// * Use **at least** a given size
/// * Let the wrapped view decide.
///
/// # Examples
///
/// ```
/// # use cursive::views::{BoxView,TextView};
/// // Creates a 20x4 BoxView with a TextView content.
/// let view = BoxView::with_fixed_size((20,4), TextView::new("Hello!"));
/// ```
pub struct BoxView<T: View> {
    /// Constraint on each axis
    size: XY<SizeConstraint>,

    /// `true` if the view can be squished.
    ///
    /// This means if the required size is less than the computed size,
    /// consider returning a smaller size.
    /// For instance, try to return the child's desires size.
    squishable: bool,

    /// The actual view we're wrapping.
    view: T,
}

impl<T: View> BoxView<T> {
    /// Creates a new `BoxView` with the given width and height requirements.
    ///
    /// `None` values will use the wrapped view's preferences.
    pub fn new(width: SizeConstraint, height: SizeConstraint, view: T) -> Self {
        BoxView {
            size: (width, height).into(),
            squishable: false,
            view: view,
        }
    }

    /// Sets `self` to be squishable.
    ///
    /// A squishable `BoxView` will take a smaller size than it should when
    /// the available space is too small. In that case, it will allow the
    /// child view to contract, if it can.
    ///
    /// More specifically, if the available space is less than the size we
    /// would normally ask for, return the child size.
    pub fn squishable(mut self) -> Self {
        self.squishable = true;
        self
    }

    /// Wraps `view` in a new `BoxView` with the given size.
    pub fn with_fixed_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(SizeConstraint::Fixed(size.x),
                     SizeConstraint::Fixed(size.y),
                     view)
    }

    /// Wraps `view` in a new `BoxView` with fixed width.
    pub fn with_fixed_width(width: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Fixed(width), SizeConstraint::Free, view)
    }

    /// Wraps `view` in a new `BoxView` with fixed height.
    pub fn with_fixed_height(height: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Free, SizeConstraint::Fixed(height), view)
    }

    /// Wraps `view` in a `BoxView` which will take all available space.
    pub fn with_full_screen(view: T) -> Self {
        BoxView::new(SizeConstraint::Full, SizeConstraint::Full, view)
    }

    /// Wraps `view` in a `BoxView` which will take all available width.
    pub fn with_full_width(view: T) -> Self {
        BoxView::new(SizeConstraint::Full, SizeConstraint::Free, view)
    }

    /// Wraps `view` in a `BoxView` which will take all available height.
    pub fn with_full_height(view: T) -> Self {
        BoxView::new(SizeConstraint::Free, SizeConstraint::Full, view)
    }

    /// Wraps `view` in a `BoxView` which will never be bigger than `size`.
    pub fn with_max_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(SizeConstraint::AtMost(size.x),
                     SizeConstraint::AtMost(size.y),
                     view)
    }

    /// Wraps `view` in a `BoxView` which will enforce a maximum width.
    ///
    /// The resulting width will never be more than `max_width`.
    pub fn with_max_width(max_width: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::AtMost(max_width),
                     SizeConstraint::Free,
                     view)
    }

    /// Wraps `view` in a `BoxView` which will enforce a maximum height.
    ///
    /// The resulting height will never be more than `max_height`.
    pub fn with_max_height(max_height: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Free,
                     SizeConstraint::AtMost(max_height),
                     view)
    }

    /// Wraps `view` in a `BoxView` which will never be smaller than `size`.
    pub fn with_min_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(SizeConstraint::AtLeast(size.x),
                     SizeConstraint::AtLeast(size.y),
                     view)
    }

    /// Wraps `view` in a `BoxView` which will enforce a minimum width.
    ///
    /// The resulting width will never be less than `min_width`.
    pub fn with_min_width(min_width: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::AtLeast(min_width),
                     SizeConstraint::Free,
                     view)
    }

    /// Wraps `view` in a `BoxView` which will enforce a minimum height.
    ///
    /// The resulting height will never be less than `min_height`.
    pub fn with_min_height(min_height: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Free,
                     SizeConstraint::AtLeast(min_height),
                     view)
    }
}

impl<T: View> ViewWrapper for BoxView<T> {
    wrap_impl!(self.view: T);

    fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 {

        let req = self.size.zip_map(req, SizeConstraint::available);
        let child_size = self.view.get_min_size(req);
        let result = self.size
            .zip_map(child_size.zip(req), SizeConstraint::result);

        if self.squishable {
            // We respect the request if we're less or equal.
            let respect_req = result.zip_map(req, |res, req| res <= req);
            result.zip_map(respect_req.zip(child_size),
                           |res, (respect, child)| if respect {
                               // If we respect the request, keep the result
                               res
                           } else {
                               // Otherwise, take the child as squish attempt.
                               child
                           })
        } else {
            result
        }
    }
}
<commit_msg>Added some size tests to BoxView<commit_after>use XY;
use vec::Vec2;
use view::{SizeConstraint, View, ViewWrapper};

/// Wrapper around another view, with a controlled size.
///
/// Each axis can independently be set to:
///
/// * Keep a **fixed** size
/// * Use **all** available size
/// * Use **at most** a given size
/// * Use **at least** a given size
/// * Let the wrapped view decide.
///
/// # Examples
///
/// ```
/// # use cursive::views::{BoxView,TextView};
/// // Creates a 20x4 BoxView with a TextView content.
/// let view = BoxView::with_fixed_size((20,4), TextView::new("Hello!"));
/// ```
pub struct BoxView<T: View> {
    /// Constraint on each axis
    size: XY<SizeConstraint>,

    /// `true` if the view can be squished.
    ///
    /// This means if the required size is less than the computed size,
    /// consider returning a smaller size.
    /// For instance, try to return the child's desires size.
    squishable: bool,

    /// The actual view we're wrapping.
    view: T,
}

impl<T: View> BoxView<T> {
    /// Creates a new `BoxView` with the given width and height requirements.
    ///
    /// `None` values will use the wrapped view's preferences.
    pub fn new(width: SizeConstraint, height: SizeConstraint, view: T) -> Self {
        BoxView {
            size: (width, height).into(),
            squishable: false,
            view: view,
        }
    }

    /// Sets `self` to be squishable.
    ///
    /// A squishable `BoxView` will take a smaller size than it should when
    /// the available space is too small. In that case, it will allow the
    /// child view to contract, if it can.
    ///
    /// More specifically, if the available space is less than the size we
    /// would normally ask for, return the child size.
    pub fn squishable(mut self) -> Self {
        self.squishable = true;
        self
    }

    /// Wraps `view` in a new `BoxView` with the given size.
    pub fn with_fixed_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(SizeConstraint::Fixed(size.x),
                     SizeConstraint::Fixed(size.y),
                     view)
    }

    /// Wraps `view` in a new `BoxView` with fixed width.
    pub fn with_fixed_width(width: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Fixed(width), SizeConstraint::Free, view)
    }

    /// Wraps `view` in a new `BoxView` with fixed height.
    pub fn with_fixed_height(height: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Free, SizeConstraint::Fixed(height), view)
    }

    /// Wraps `view` in a `BoxView` which will take all available space.
    pub fn with_full_screen(view: T) -> Self {
        BoxView::new(SizeConstraint::Full, SizeConstraint::Full, view)
    }

    /// Wraps `view` in a `BoxView` which will take all available width.
    pub fn with_full_width(view: T) -> Self {
        BoxView::new(SizeConstraint::Full, SizeConstraint::Free, view)
    }

    /// Wraps `view` in a `BoxView` which will take all available height.
    pub fn with_full_height(view: T) -> Self {
        BoxView::new(SizeConstraint::Free, SizeConstraint::Full, view)
    }

    /// Wraps `view` in a `BoxView` which will never be bigger than `size`.
    pub fn with_max_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(SizeConstraint::AtMost(size.x),
                     SizeConstraint::AtMost(size.y),
                     view)
    }

    /// Wraps `view` in a `BoxView` which will enforce a maximum width.
    ///
    /// The resulting width will never be more than `max_width`.
    pub fn with_max_width(max_width: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::AtMost(max_width),
                     SizeConstraint::Free,
                     view)
    }

    /// Wraps `view` in a `BoxView` which will enforce a maximum height.
    ///
    /// The resulting height will never be more than `max_height`.
    pub fn with_max_height(max_height: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Free,
                     SizeConstraint::AtMost(max_height),
                     view)
    }

    /// Wraps `view` in a `BoxView` which will never be smaller than `size`.
    pub fn with_min_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(SizeConstraint::AtLeast(size.x),
                     SizeConstraint::AtLeast(size.y),
                     view)
    }

    /// Wraps `view` in a `BoxView` which will enforce a minimum width.
    ///
    /// The resulting width will never be less than `min_width`.
    pub fn with_min_width(min_width: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::AtLeast(min_width),
                     SizeConstraint::Free,
                     view)
    }

    /// Wraps `view` in a `BoxView` which will enforce a minimum height.
    ///
    /// The resulting height will never be less than `min_height`.
    pub fn with_min_height(min_height: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Free,
                     SizeConstraint::AtLeast(min_height),
                     view)
    }
}

impl<T: View> ViewWrapper for BoxView<T> {
    wrap_impl!(self.view: T);

    fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 {

        let req = self.size.zip_map(req, SizeConstraint::available);
        let child_size = self.view.get_min_size(req);
        let result = self.size
            .zip_map(child_size.zip(req), SizeConstraint::result);

        if self.squishable {
            // We respect the request if we're less or equal.
            let respect_req = result.zip_map(req, |res, req| res <= req);
            result.zip_map(respect_req.zip(child_size),
                           |res, (respect, child)| {
                if respect {
                    // If we respect the request, keep the result
                    res
                } else {
                    // Otherwise, take the child as squish attempt.
                    child
                }
            })
        } else {
            result
        }
    }
}

#[cfg(test)]
mod tests {

    use vec::Vec2;
    use view::{View, Boxable};
    use views::DummyView;

    // No need to test `draw()` method as it's directly forwarded.

    #[test]
    fn min_size() {
        let mut min_w = DummyView.full_screen().min_width(5);

        assert_eq!(Vec2::new(5, 1), min_w.get_min_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(5, 10), min_w.get_min_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), min_w.get_min_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_w.get_min_size(Vec2::new(10, 10)));

        let mut min_h = DummyView.full_screen().min_height(5);

        assert_eq!(Vec2::new(1, 5), min_h.get_min_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), min_h.get_min_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 5), min_h.get_min_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_h.get_min_size(Vec2::new(10, 10)));

        let mut min_s = DummyView.full_screen().min_size((5, 5));

        assert_eq!(Vec2::new(5, 5), min_s.get_min_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(5, 10), min_s.get_min_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 5), min_s.get_min_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_s.get_min_size(Vec2::new(10, 10)));
    }

    #[test]
    fn max_size() {
        let mut max_w = DummyView.full_screen().max_width(5);

        assert_eq!(Vec2::new(1, 1), max_w.get_min_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), max_w.get_min_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(5, 1), max_w.get_min_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(5, 10), max_w.get_min_size(Vec2::new(10, 10)));

        let mut max_h = DummyView.full_screen().max_height(5);

        assert_eq!(Vec2::new(1, 1), max_h.get_min_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 5), max_h.get_min_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), max_h.get_min_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 5), max_h.get_min_size(Vec2::new(10, 10)));

        let mut max_s = DummyView.full_screen().max_size((5, 5));

        assert_eq!(Vec2::new(1, 1), max_s.get_min_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 5), max_s.get_min_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(5, 1), max_s.get_min_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(5, 5), max_s.get_min_size(Vec2::new(10, 10)));
    }

    #[test]
    fn full_screen() {
        let mut full = DummyView.full_screen();

        assert_eq!(Vec2::new(1, 1), full.get_min_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), full.get_min_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), full.get_min_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), full.get_min_size(Vec2::new(10, 10)));
    }
}
<|endoftext|>


<commit_before>//! Grammar for the command-line arguments.
#![allow(unreachable_pub)]
use std::{path::PathBuf, str::FromStr};

use ide_ssr::{SsrPattern, SsrRule};

use crate::cli::Verbosity;

xflags::xflags! {
    src "./src/cli/flags.rs"

    /// LSP server for the Rust programming language.
    cmd rust-analyzer {
        /// Verbosity level, can be repeated multiple times.
        repeated -v, --verbose
        /// Verbosity level.
        optional -q, --quiet

        /// Log to the specified file instead of stderr.
        optional --log-file path: PathBuf
        /// Flush log records to the file immediately.
        optional --no-log-buffering

        /// Wait until a debugger is attached to (requires debug build).
        optional --wait-dbg

        default cmd lsp-server {
            /// Print version.
            optional --version
            /// Print help.
            optional -h, --help

            /// Dump a LSP config JSON schema.
            optional --print-config-schema
        }

        /// Parse stdin.
        cmd parse {
            /// Suppress printing.
            optional --no-dump
        }

        /// Parse stdin and print the list of symbols.
        cmd symbols {}

        /// Highlight stdin as html.
        cmd highlight {
            /// Enable rainbow highlighting of identifiers.
            optional --rainbow
        }

        /// Batch typecheck project and print summary statistics
        cmd analysis-stats
            /// Directory with Cargo.toml.
            required path: PathBuf
        {
            optional --output format: OutputFormat

            /// Randomize order in which crates, modules, and items are processed.
            optional --randomize
            /// Run type inference in parallel.
            optional --parallel
            /// Collect memory usage statistics.
            optional --memory-usage
            /// Print the total length of all source and macro files (whitespace is not counted).
            optional --source-stats

            /// Only analyze items matching this path.
            optional -o, --only path: String
            /// Also analyze all dependencies.
            optional --with-deps
            /// Don't load sysroot crates (`std`, `core` & friends).
            optional --no-sysroot

            /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
            optional --disable-build-scripts
            /// Don't use expand proc macros.
            optional --disable-proc-macros
            /// Only resolve names, don't run type inference.
            optional --skip-inference
        }

        cmd diagnostics
            /// Directory with Cargo.toml.
            required path: PathBuf
        {
            /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
            optional --disable-build-scripts
            /// Don't use expand proc macros.
            optional --disable-proc-macros
        }

        cmd ssr
            /// A structured search replace rule (`$a.foo($b) ==> bar($a, $b)`)
            repeated rule: SsrRule
        {}

        cmd search
            /// A structured search replace pattern (`$a.foo($b)`)
            repeated pattern: SsrPattern
        {
            /// Prints debug information for any nodes with source exactly equal to snippet.
            optional --debug snippet: String
        }

        cmd proc-macro {}

        cmd lsif
            required path: PathBuf
        {}
    }
}

// generated start
// The following code is generated by `xflags` macro.
// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
#[derive(Debug)]
pub struct RustAnalyzer {
    pub verbose: u32,
    pub quiet: bool,
    pub log_file: Option<PathBuf>,
    pub no_log_buffering: bool,
    pub wait_dbg: bool,
    pub subcommand: RustAnalyzerCmd,
}

#[derive(Debug)]
pub enum RustAnalyzerCmd {
    LspServer(LspServer),
    Parse(Parse),
    Symbols(Symbols),
    Highlight(Highlight),
    AnalysisStats(AnalysisStats),
    Diagnostics(Diagnostics),
    Ssr(Ssr),
    Search(Search),
    ProcMacro(ProcMacro),
    Lsif(Lsif),
}

#[derive(Debug)]
pub struct LspServer {
    pub version: bool,
    pub help: bool,
    pub print_config_schema: bool,
}

#[derive(Debug)]
pub struct Parse {
    pub no_dump: bool,
}

#[derive(Debug)]
pub struct Symbols;

#[derive(Debug)]
pub struct Highlight {
    pub rainbow: bool,
}

#[derive(Debug)]
pub struct AnalysisStats {
    pub path: PathBuf,

    pub output: Option<OutputFormat>,
    pub randomize: bool,
    pub parallel: bool,
    pub memory_usage: bool,
    pub source_stats: bool,
    pub only: Option<String>,
    pub with_deps: bool,
    pub no_sysroot: bool,
    pub disable_build_scripts: bool,
    pub disable_proc_macros: bool,
    pub skip_inference: bool,
}

#[derive(Debug)]
pub struct Diagnostics {
    pub path: PathBuf,

    pub disable_build_scripts: bool,
    pub disable_proc_macros: bool,
}

#[derive(Debug)]
pub struct Ssr {
    pub rule: Vec<SsrRule>,
}

#[derive(Debug)]
pub struct Search {
    pub pattern: Vec<SsrPattern>,

    pub debug: Option<String>,
}

#[derive(Debug)]
pub struct ProcMacro;

#[derive(Debug)]
pub struct Lsif {
    pub path: PathBuf,
}

impl RustAnalyzer {
    pub const HELP: &'static str = Self::HELP_;

    #[allow(dead_code)]
    pub fn from_env() -> xflags::Result<Self> {
        Self::from_env_()
    }

    #[allow(dead_code)]
    pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
        Self::from_vec_(args)
    }
}
// generated end

#[derive(Debug, PartialEq, Eq)]
pub enum OutputFormat {
    Csv,
}

impl RustAnalyzer {
    pub fn verbosity(&self) -> Verbosity {
        if self.quiet {
            return Verbosity::Quiet;
        }
        match self.verbose {
            0 => Verbosity::Normal,
            1 => Verbosity::Verbose,
            _ => Verbosity::Spammy,
        }
    }
}

impl FromStr for OutputFormat {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "csv" => Ok(Self::Csv),
            _ => Err(format!("unknown output format `{}`", s)),
        }
    }
}
<commit_msg>Auto merge of #12951 - jonas-schievink:doc-cli-stability, r=Veykril<commit_after>//! Grammar for the command-line arguments.
#![allow(unreachable_pub)]
use std::{path::PathBuf, str::FromStr};

use ide_ssr::{SsrPattern, SsrRule};

use crate::cli::Verbosity;

xflags::xflags! {
    src "./src/cli/flags.rs"

    /// LSP server for the Rust programming language.
    ///
    /// Subcommands and their flags do not provide any stability guarantees and may be removed or
    /// changed without notice. Top-level flags that are not are marked as [Unstable] provide
    /// backwards-compatibility and may be relied on.
    cmd rust-analyzer {
        /// Verbosity level, can be repeated multiple times.
        repeated -v, --verbose
        /// Verbosity level.
        optional -q, --quiet

        /// Log to the specified file instead of stderr.
        optional --log-file path: PathBuf
        /// Flush log records to the file immediately.
        optional --no-log-buffering

        /// [Unstable] Wait until a debugger is attached to (requires debug build).
        optional --wait-dbg

        default cmd lsp-server {
            /// Print version.
            optional --version
            /// Print help.
            optional -h, --help

            /// Dump a LSP config JSON schema.
            optional --print-config-schema
        }

        /// Parse stdin.
        cmd parse {
            /// Suppress printing.
            optional --no-dump
        }

        /// Parse stdin and print the list of symbols.
        cmd symbols {}

        /// Highlight stdin as html.
        cmd highlight {
            /// Enable rainbow highlighting of identifiers.
            optional --rainbow
        }

        /// Batch typecheck project and print summary statistics
        cmd analysis-stats
            /// Directory with Cargo.toml.
            required path: PathBuf
        {
            optional --output format: OutputFormat

            /// Randomize order in which crates, modules, and items are processed.
            optional --randomize
            /// Run type inference in parallel.
            optional --parallel
            /// Collect memory usage statistics.
            optional --memory-usage
            /// Print the total length of all source and macro files (whitespace is not counted).
            optional --source-stats

            /// Only analyze items matching this path.
            optional -o, --only path: String
            /// Also analyze all dependencies.
            optional --with-deps
            /// Don't load sysroot crates (`std`, `core` & friends).
            optional --no-sysroot

            /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
            optional --disable-build-scripts
            /// Don't use expand proc macros.
            optional --disable-proc-macros
            /// Only resolve names, don't run type inference.
            optional --skip-inference
        }

        cmd diagnostics
            /// Directory with Cargo.toml.
            required path: PathBuf
        {
            /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
            optional --disable-build-scripts
            /// Don't use expand proc macros.
            optional --disable-proc-macros
        }

        cmd ssr
            /// A structured search replace rule (`$a.foo($b) ==> bar($a, $b)`)
            repeated rule: SsrRule
        {}

        cmd search
            /// A structured search replace pattern (`$a.foo($b)`)
            repeated pattern: SsrPattern
        {
            /// Prints debug information for any nodes with source exactly equal to snippet.
            optional --debug snippet: String
        }

        cmd proc-macro {}

        cmd lsif
            required path: PathBuf
        {}
    }
}

// generated start
// The following code is generated by `xflags` macro.
// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
#[derive(Debug)]
pub struct RustAnalyzer {
    pub verbose: u32,
    pub quiet: bool,
    pub log_file: Option<PathBuf>,
    pub no_log_buffering: bool,
    pub wait_dbg: bool,
    pub subcommand: RustAnalyzerCmd,
}

#[derive(Debug)]
pub enum RustAnalyzerCmd {
    LspServer(LspServer),
    Parse(Parse),
    Symbols(Symbols),
    Highlight(Highlight),
    AnalysisStats(AnalysisStats),
    Diagnostics(Diagnostics),
    Ssr(Ssr),
    Search(Search),
    ProcMacro(ProcMacro),
    Lsif(Lsif),
}

#[derive(Debug)]
pub struct LspServer {
    pub version: bool,
    pub help: bool,
    pub print_config_schema: bool,
}

#[derive(Debug)]
pub struct Parse {
    pub no_dump: bool,
}

#[derive(Debug)]
pub struct Symbols;

#[derive(Debug)]
pub struct Highlight {
    pub rainbow: bool,
}

#[derive(Debug)]
pub struct AnalysisStats {
    pub path: PathBuf,

    pub output: Option<OutputFormat>,
    pub randomize: bool,
    pub parallel: bool,
    pub memory_usage: bool,
    pub source_stats: bool,
    pub only: Option<String>,
    pub with_deps: bool,
    pub no_sysroot: bool,
    pub disable_build_scripts: bool,
    pub disable_proc_macros: bool,
    pub skip_inference: bool,
}

#[derive(Debug)]
pub struct Diagnostics {
    pub path: PathBuf,

    pub disable_build_scripts: bool,
    pub disable_proc_macros: bool,
}

#[derive(Debug)]
pub struct Ssr {
    pub rule: Vec<SsrRule>,
}

#[derive(Debug)]
pub struct Search {
    pub pattern: Vec<SsrPattern>,

    pub debug: Option<String>,
}

#[derive(Debug)]
pub struct ProcMacro;

#[derive(Debug)]
pub struct Lsif {
    pub path: PathBuf,
}

impl RustAnalyzer {
    pub const HELP: &'static str = Self::HELP_;

    #[allow(dead_code)]
    pub fn from_env() -> xflags::Result<Self> {
        Self::from_env_()
    }

    #[allow(dead_code)]
    pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
        Self::from_vec_(args)
    }
}
// generated end

#[derive(Debug, PartialEq, Eq)]
pub enum OutputFormat {
    Csv,
}

impl RustAnalyzer {
    pub fn verbosity(&self) -> Verbosity {
        if self.quiet {
            return Verbosity::Quiet;
        }
        match self.verbose {
            0 => Verbosity::Normal,
            1 => Verbosity::Verbose,
            _ => Verbosity::Spammy,
        }
    }
}

impl FromStr for OutputFormat {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "csv" => Ok(Self::Csv),
            _ => Err(format!("unknown output format `{}`", s)),
        }
    }
}
<|endoftext|>


<commit_before>use {Function,Global,Module,Value,Expression,Type};
use util::{Id,Identifiable};

pub enum Info
{
    Function {
        ty: ::types::Function,
    },
    Global {
        ty: Type,
    },
}

/// Something that may be resolved.
pub trait Resolvable : Identifiable
{
    fn name(&self) -> &str;
    fn give_to(self: Box<Self>, module: &mut Module);
    fn info(&self) -> Info;
}

impl Resolvable for Function {
    fn name(&self) -> &str { Function::name(self) }
    fn give_to(self: Box<Self>, module: &mut Module) {
        module.add_function(*self);
    }
    fn info(&self) -> Info {
        Info::Function {
            ty: ::types::Function::new(self.signature().clone()),
        }
    }
}

impl Resolvable for Global {
    fn name(&self) -> &str { Global::name(self) }
    fn give_to(self: Box<Self>, module: &mut Module) where Self: Sized {
        module.add_global(*self)
    }
    fn info(&self) -> Info {
        Info::Global {
            ty: self.ty()
        }
    }
}

pub struct Resolve
{
    items: Vec<ResolveItem>,
}

impl Resolve
{
    /// Creates a new resolver.
    pub fn new() -> Self {
        Resolve {
            items: Vec::new(),
        }
    }

    /// Gives back an `ID` which will be used to reference an item.
    pub fn reference(&mut self, name: String) -> Expression {
        if let Some(item) = self.lookup_name(&name) {
            return Expression::UnresolvedRef(item.id);
        }

        let id = Id::next();

        self.items.push(ResolveItem::unresolved(id, name));

        Expression::UnresolvedRef(id)
    }

    pub fn give<T>(&mut self, item: T)
        where T: Resolvable + 'static {
        if let Some(a) =  self.lookup_name_mut(item.name()) {
            a.resolve(item);
            return;
        }

        // otherwise create a new item
        self.items.push(ResolveItem::resolved(
            item.get_id(),
            item.name().to_owned(),
            item,
        ));
    }

    pub fn resolve(&mut self, mut module: Module)
        -> Module {
        // move the actual items (functions, globals)
        // into the module
        for item in self.items.iter_mut() {
            item.give_to(&mut module);
        }

        module.map_values(|v| self.resolve_value(v))
    }

    fn resolve_value(&mut self, value: Value) -> Value {
        let a = value.map_subvalues(|v| self.resolve_value(v));

        a.map_expression(|expr| match expr {
            Expression::UnresolvedRef(id) => self.resolve_reference(id),
            other => other,
        })
    }

    fn resolve_reference(&self, id: Id) -> Expression {
        match self.maybe_resolve_reference(id) {
            Some(expr) => expr,
            None => Expression::UnresolvedRef(id),
        }
    }

    fn maybe_resolve_reference(&self, id: Id) -> Option<Expression> {
        self.find_id(id).make_reference()
    }

    fn find_id(&self, id: Id) -> &ResolveItem {
        self.items.iter().find(|a| a.id == id)
            .expect("no item with that ID was found")
    }

    fn lookup_name(&self, name: &str)
        -> Option<&ResolveItem> {
        self.items.iter().find(|a| a.name == name)
    }

    fn lookup_name_mut(&mut self, name: &str)
        -> Option<&mut ResolveItem> {
        self.items.iter_mut().find(|a| a.name == name)
    }
}

struct ResolveItem
{
    id: Id,
    name: String,
    item: Option<Box<Resolvable>>,
    info: Option<Info>,
}

impl ResolveItem
{
    pub fn unresolved(id: Id,
                      name: String) -> Self {
        ResolveItem {
            id: id,
            name: name,
            item: None,
            info: None,
        }
    }

    pub fn resolved<T>(id: Id,
                       name: String,
                       item: T) -> Self
        where T: Resolvable + 'static {
        ResolveItem {
            id: id,
            name: name,
            info: Some(item.info()),
            item: Some(Box::new(item)),
        }
    }

    pub fn give_to(&mut self, module: &mut Module) {
        use std::mem;

        let item = mem::replace(&mut self.item, None);

        if let Some(i) = item { i.give_to(module) }
    }

    pub fn resolve<T>(&mut self, mut item: T)
        where T: Resolvable + 'static {
        // Make the item have the ID we have have been referring to it as.
        item.internal_set_id(self.id);

        self.info = Some(item.info());
        self.item = Some(Box::new(item));
    }

    pub fn make_reference(&self) -> Option<Expression> {
        use ::value::{FunctionRef,GlobalRef};

        let info = if let Some(ref i) = self.info { i } else { return None; };

        match *info {
            Info::Function { ref ty } => {
                Some(FunctionRef::new(
                    self.id,
                    self.name.clone(),
                    ty.clone()
                ).into())
            },
            Info::Global { ref ty } => {
                Some(GlobalRef::new(
                    self.id,
                    ty.clone(),
                ).into())
            },
        }
    }
}

<commit_msg>Rename ResolveItem to Item<commit_after>use {Function,Global,Module,Value,Expression,Type};
use util::{Id,Identifiable};

pub enum Info
{
    Function {
        ty: ::types::Function,
    },
    Global {
        ty: Type,
    },
}

/// Something that may be resolved.
pub trait Resolvable : Identifiable
{
    fn name(&self) -> &str;
    fn give_to(self: Box<Self>, module: &mut Module);
    fn info(&self) -> Info;
}

impl Resolvable for Function {
    fn name(&self) -> &str { Function::name(self) }
    fn give_to(self: Box<Self>, module: &mut Module) {
        module.add_function(*self);
    }
    fn info(&self) -> Info {
        Info::Function {
            ty: ::types::Function::new(self.signature().clone()),
        }
    }
}

impl Resolvable for Global {
    fn name(&self) -> &str { Global::name(self) }
    fn give_to(self: Box<Self>, module: &mut Module) where Self: Sized {
        module.add_global(*self)
    }
    fn info(&self) -> Info {
        Info::Global {
            ty: self.ty()
        }
    }
}

pub struct Resolve
{
    items: Vec<Item>,
}

impl Resolve
{
    /// Creates a new resolver.
    pub fn new() -> Self {
        Resolve {
            items: Vec::new(),
        }
    }

    /// Gives back an `ID` which will be used to reference an item.
    pub fn reference(&mut self, name: String) -> Expression {
        if let Some(item) = self.lookup_name(&name) {
            return Expression::UnresolvedRef(item.id);
        }

        let id = Id::next();

        self.items.push(Item::unresolved(id, name));

        Expression::UnresolvedRef(id)
    }

    pub fn give<T>(&mut self, item: T)
        where T: Resolvable + 'static {
        if let Some(a) =  self.lookup_name_mut(item.name()) {
            a.resolve(item);
            return;
        }

        // otherwise create a new item
        self.items.push(Item::resolved(
            item.get_id(),
            item.name().to_owned(),
            item,
        ));
    }

    pub fn resolve(&mut self, mut module: Module)
        -> Module {
        // move the actual items (functions, globals)
        // into the module
        for item in self.items.iter_mut() {
            item.give_to(&mut module);
        }

        module.map_values(|v| self.resolve_value(v))
    }

    fn resolve_value(&mut self, value: Value) -> Value {
        let a = value.map_subvalues(|v| self.resolve_value(v));

        a.map_expression(|expr| match expr {
            Expression::UnresolvedRef(id) => self.resolve_reference(id),
            other => other,
        })
    }

    fn resolve_reference(&self, id: Id) -> Expression {
        match self.maybe_resolve_reference(id) {
            Some(expr) => expr,
            None => Expression::UnresolvedRef(id),
        }
    }

    fn maybe_resolve_reference(&self, id: Id) -> Option<Expression> {
        self.find_id(id).make_reference()
    }

    fn find_id(&self, id: Id) -> &Item {
        self.items.iter().find(|a| a.id == id)
            .expect("no item with that ID was found")
    }

    fn lookup_name(&self, name: &str)
        -> Option<&Item> {
        self.items.iter().find(|a| a.name == name)
    }

    fn lookup_name_mut(&mut self, name: &str)
        -> Option<&mut Item> {
        self.items.iter_mut().find(|a| a.name == name)
    }
}

struct Item
{
    id: Id,
    name: String,
    item: Option<Box<Resolvable>>,
    info: Option<Info>,
}

impl Item
{
    pub fn unresolved(id: Id,
                      name: String) -> Self {
        Item {
            id: id,
            name: name,
            item: None,
            info: None,
        }
    }

    pub fn resolved<T>(id: Id,
                       name: String,
                       item: T) -> Self
        where T: Resolvable + 'static {
        Item {
            id: id,
            name: name,
            info: Some(item.info()),
            item: Some(Box::new(item)),
        }
    }

    pub fn give_to(&mut self, module: &mut Module) {
        use std::mem;

        let item = mem::replace(&mut self.item, None);

        if let Some(i) = item { i.give_to(module) }
    }

    pub fn resolve<T>(&mut self, mut item: T)
        where T: Resolvable + 'static {
        // Make the item have the ID we have have been referring to it as.
        item.internal_set_id(self.id);

        self.info = Some(item.info());
        self.item = Some(Box::new(item));
    }

    pub fn make_reference(&self) -> Option<Expression> {
        use ::value::{FunctionRef,GlobalRef};

        let info = if let Some(ref i) = self.info { i } else { return None; };

        match *info {
            Info::Function { ref ty } => {
                Some(FunctionRef::new(
                    self.id,
                    self.name.clone(),
                    ty.clone()
                ).into())
            },
            Info::Global { ref ty } => {
                Some(GlobalRef::new(
                    self.id,
                    ty.clone(),
                ).into())
            },
        }
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use crate::{
    agent_error::ImlAgentError,
    daemon_plugins::{DaemonPlugin, Output},
};
use async_trait::async_trait;
use futures::{
    channel::oneshot, future, lock::Mutex, Future, FutureExt, Stream, StreamExt, TryFutureExt,
    TryStreamExt,
};
use std::{pin::Pin, sync::Arc};
use stream_cancel::{StreamExt as _, Trigger, Tripwire};
use tokio::{io::AsyncWriteExt, net::UnixStream};
use tokio_util::codec::{FramedRead, LinesCodec};

/// Opens a persistent stream to device scanner.
fn device_stream() -> impl Stream<Item = Result<String, ImlAgentError>> {
    UnixStream::connect("/var/run/device-scanner.sock")
        .err_into()
        .and_then(|mut conn| async {
            conn.write_all(b"\"Stream\"\n")
                .err_into::<ImlAgentError>()
                .await?;

            Ok(conn)
        })
        .map_ok(|c| FramedRead::new(c, LinesCodec::new()).err_into())
        .try_flatten_stream()
}

pub fn create() -> impl DaemonPlugin {
    Devices {
        trigger: None,
        state: Arc::new(Mutex::new((None, None))),
    }
}

#[derive(Debug)]
pub struct Devices {
    trigger: Option<Trigger>,
    state: Arc<Mutex<(Output, Output)>>,
}

#[async_trait]
impl DaemonPlugin for Devices {
    fn start_session(
        &mut self,
    ) -> Pin<Box<dyn Future<Output = Result<Output, ImlAgentError>> + Send>> {
        let (trigger, tripwire) = Tripwire::new();
        let (tx, rx) = oneshot::channel();

        self.trigger = Some(trigger);

        let state = Arc::clone(&self.state);

        tokio::spawn(
            device_stream()
                .boxed()
                .and_then(|x| future::ready(serde_json::from_str(&x).map_err(|e| e.into())))
                .into_future()
                .then(|(x, s)| {
                    let x = if let Some(x) = x {
                        x.map(move |y| {
                            let _ = tx.send(y);
                            s
                        })
                    } else {
                        Ok(s)
                    };

                    future::ready(x)
                })
                .try_flatten_stream()
                .take_until(tripwire)
                .try_for_each(move |x| {
                    let state = Arc::clone(&state);

                    async move {
                        let mut s = state.lock().await;

                        s.0 = s.1.take();
                        s.1 = x;

                        Ok(())
                    }
                })
                .map(|x| {
                    if let Err(e) = x {
                        tracing::error!("Error processing device output: {}", e);
                    }
                }),
        );

        Box::pin(rx.err_into())
    }
    fn update_session(
        &self,
    ) -> Pin<Box<dyn Future<Output = Result<Output, ImlAgentError>> + Send>> {
        let state = Arc::clone(&self.state);

        async move {
            let s = state.lock().await.clone();

            if s.0 != s.1 {
                Ok(s.1)
            } else {
                Ok(None)
            }
        }
        .boxed()
    }
    async fn teardown(&mut self) -> Result<(), ImlAgentError> {
        self.trigger.take();

        Ok(())
    }
}
<commit_msg>Fill device state (#1869)<commit_after>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use crate::{
    agent_error::ImlAgentError,
    daemon_plugins::{DaemonPlugin, Output},
};
use async_trait::async_trait;
use futures::{
    future, lock::Mutex, Future, FutureExt, Stream, StreamExt, TryFutureExt, TryStreamExt,
};
use std::{io, pin::Pin, sync::Arc};
use stream_cancel::{StreamExt as _, Trigger, Tripwire};
use tokio::{io::AsyncWriteExt, net::UnixStream};
use tokio_util::codec::{FramedRead, LinesCodec};

/// Opens a persistent stream to device scanner.
fn device_stream() -> impl Stream<Item = Result<String, ImlAgentError>> {
    UnixStream::connect("/var/run/device-scanner.sock")
        .err_into()
        .and_then(|mut conn| async {
            conn.write_all(b"\"Stream\"\n")
                .err_into::<ImlAgentError>()
                .await?;

            Ok(conn)
        })
        .map_ok(|c| FramedRead::new(c, LinesCodec::new()).err_into())
        .try_flatten_stream()
}

#[derive(Eq, PartialEq)]
enum State {
    Pending,
    Sent,
}

pub fn create() -> impl DaemonPlugin {
    Devices {
        trigger: None,
        state: Arc::new(Mutex::new((None, State::Sent))),
    }
}

#[derive(Debug)]
pub struct Devices {
    trigger: Option<Trigger>,
    state: Arc<Mutex<(Output, State)>>,
}

#[async_trait]
impl DaemonPlugin for Devices {
    fn start_session(
        &mut self,
    ) -> Pin<Box<dyn Future<Output = Result<Output, ImlAgentError>> + Send>> {
        let (trigger, tripwire) = Tripwire::new();

        self.trigger = Some(trigger);

        let fut = device_stream()
            .boxed()
            .and_then(|x| future::ready(serde_json::from_str(&x)).err_into())
            .into_future();

        let state = Arc::clone(&self.state);

        Box::pin(async move {
            let (x, s) = fut.await;

            let x: Output = match x {
                Some(x) => x,
                None => {
                    return Err(ImlAgentError::Io(io::Error::new(
                        io::ErrorKind::ConnectionAborted,
                        "Device scanner connection aborted before any data was sent",
                    )))
                }
            }?;

            {
                let mut lock = state.lock().await;

                lock.0 = x.clone();
            }

            tokio::spawn(
                s.take_until(tripwire)
                    .try_for_each(move |x| {
                        let state = Arc::clone(&state);

                        async move {
                            let mut lock = state.lock().await;

                            if lock.0 != x {
                                tracing::debug!("marking pending (is none: {}) ", x.is_none());

                                lock.0 = x;
                                lock.1 = State::Pending;
                            }

                            Ok(())
                        }
                    })
                    .map(|x| {
                        if let Err(e) = x {
                            tracing::error!("Error processing device output: {}", e);
                        }
                    }),
            );

            Ok(x)
        })
    }
    fn update_session(
        &self,
    ) -> Pin<Box<dyn Future<Output = Result<Output, ImlAgentError>> + Send>> {
        let state = Arc::clone(&self.state);

        async move {
            let mut lock = state.lock().await;

            if lock.1 == State::Pending {
                tracing::debug!("Sending new value");
                lock.1 = State::Sent;

                Ok(lock.0.clone())
            } else {
                Ok(None)
            }
        }
        .boxed()
    }
    async fn teardown(&mut self) -> Result<(), ImlAgentError> {
        self.trigger.take();

        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Common types used by multiple graph implementations.

use std::ops;
use std::fmt::Debug;
use std::default::Default;
use std::hash::{Hash};

use num_traits::{NumCast,ToPrimitive};

use super::interface::{self, Id, Graph};
use super::iter::Indices;

// ================================================================
// Indices: types used to identify nodes and edges.

/// Default integer type used to identify nodes and edges.
pub type DefaultIndexType = u32;

/// Any integer type used as the underlying type for node and edge indices.
pub trait IndexType: Copy + Eq + Hash + Ord + Debug + NumCast + ToPrimitive + 'static {}
impl<T> IndexType for T where T: Copy + Eq + Hash + Ord + Debug + NumCast + ToPrimitive + 'static {}

macro_rules! impl_index_wrapper_type {
    ($tp: ty, $n: ident, $T: ident) => {
        impl<$T: IndexType> Id for $tp {
            #[inline(always)]
            fn new(v: usize) -> Self { $n(NumCast::from(v).unwrap()) }
            #[inline(always)]
            fn index(&self) -> usize { NumCast::from(self.0).unwrap() }
        }

        impl<U: NumCast + ToPrimitive, $T: IndexType> From<U> for $tp {
            fn from(v: U) -> Self {
                Self::new(NumCast::from(v).unwrap())
            }
        }
    }
}

/// Type used to identify and index the edges of a graph.
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct EdgeIndex<T: IndexType>(T);
impl_index_wrapper_type!(EdgeIndex<T>,EdgeIndex,T);

/// Type used to identify and index the nodes of a graph.
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct NodeIndex<T: IndexType>(T);
impl_index_wrapper_type!(NodeIndex<T>,NodeIndex,T);

// --------------------------------

/// Implement `interface::Node` for a type with members `incoming_edges` and
/// `outgoing_edges` of types compatible with `Vec<$I>`.
macro_rules! impl_basic_node {
    ($I: ident) => {
        //type EdgeIter<'a> = std::slice::Iter<'a,$I>;

        #[inline(always)]
        fn incoming_edges(&self) -> std::slice::Iter<$I> {
            self.incoming_edges.iter()
        }

        fn incoming_edge_count(&self) -> usize {
            self.incoming_edges.len()
        }

        #[inline(always)]
        fn outgoing_edges(&self) -> std::slice::Iter<$I> {
            self.outgoing_edges.iter()
        }

        fn outgoing_edge_count(&self) -> usize {
            self.outgoing_edges.len()
        }
    }
}

macro_rules! impl_basic_node_mut {
    ($I: ident) => {
        #[inline(always)]
        fn add_incoming_edge(&mut self, e: $I) {
            self.incoming_edges.push(e);
        }

        #[inline(always)]
        fn add_outgoing_edge(&mut self, e: $I) {
            self.outgoing_edges.push(e);
        }

        fn rev(&mut self) {
            ::std::mem::swap(&mut self.incoming_edges, &mut self.outgoing_edges);
        }
    }
}

// --------------------------------
// AdjacencyList

/// Adjacency-list graph implementation.
#[derive(Clone,Debug)]
pub struct AdjacencyList<N, E> {
    nodes: Vec<N>,
    edges: Vec<E>
}

impl<N, E> AdjacencyList<N, E> {
    /// Create an empty AdjacencyList instance.
    pub fn new() -> Self {
        AdjacencyList{nodes: Vec::new(), edges: Vec::new()}
    }
}

impl<N, E> Default for AdjacencyList<N, E> {
    #[inline(always)]
    fn default() -> Self {
        AdjacencyList::new()
   }
}

impl<N, E> interface::Graph for AdjacencyList<N, E>
    where N: interface::Node,
          E: interface::Edge
{
    type NodeId = <E as interface::Edge>::NodeId;
    type EdgeId = <N as interface::Node>::EdgeId;
    type EdgeIdIterator = Indices<Self::EdgeId>;
    type NodeIdIterator = Indices<Self::NodeId>;

    #[inline(always)]
    fn contains_node(&self, n: Self::NodeId) -> bool {
        n.index() < self.nodes.len()
    }

    #[inline]
    fn node_ids(&self) -> Self::NodeIdIterator {
        Indices::new(0..self.nodes.len())
    }

    #[inline]
    fn node_count(&self) -> usize {
        self.nodes.len()
    }

    fn contains_edge(&self, e: Self::EdgeId) -> bool {
        e.index() < self.edges.len()
    }

    fn edge_ids(&self) -> Self::EdgeIdIterator {
        Indices::new(0..self.edges.len())
    }

    fn edge_count(&self) -> usize {
        self.edges.len()
    }

}

impl<N, E> interface::ConcreteGraph for AdjacencyList<N, E>
    where N: interface::DirectedNode,
          E: interface::DirectedEdge
{
    type Node = N;
    type Edge = E;

    #[inline(always)]
    fn node(&self, n: Self::NodeId) -> &Self::Node {
        &self.nodes[n.index()]
    }

    #[inline(always)]
    fn edge(&self, e: Self::EdgeId) -> &Self::Edge {
        &self.edges[e.index()]
    }
}

impl<N, E> interface::ConcreteGraphMut for AdjacencyList<N, E>
    where N: interface::DirectedNodeMut,
          E: interface::DirectedEdgeMut
{
    #[inline(always)]
    fn node_mut(&mut self, n: Self::NodeId) -> &mut Self::Node {
        &mut self.nodes[n.index()]
    }

    #[inline(always)]
    fn edge_mut(&mut self, e: Self::EdgeId) -> &mut Self::Edge {
        &mut self.edges[e.index()]
    }

    #[inline(always)]
    fn add_node<T: Into<Self::Node>>(&mut self, n: T) -> Self::NodeId {
        self.nodes.push(n.into());
        Self::NodeId::new(self.nodes.len() - 1)
    }

    fn add_edge<T: Into<Self::Edge>>(&mut self, e: T) -> Self::EdgeId {
        let edge = e.into();
        let (a, b) = edge.endpoints();
        let srcidx = a.index();
        let destidx = b.index();

        let node_count = self.node_count();
        panic_unless!(srcidx < node_count, "Invalid source node provided to `Graph::add_edge`: {:?}", a);
        panic_unless!(destidx < node_count, "Invalid target node provided to `Graph::add_edge`: {:?}", b);

        self.edges.push(edge);
        let index = Self::EdgeId::new(self.edges.len() - 1);

        // Update cross-referenced edge lists for the connected nodes.
        self.nodes[srcidx].add_outgoing_edge(index);
        self.nodes[destidx].add_incoming_edge(index);

        index
    }
}

// Implement node-data lookup via indexing.
macro_rules! graph_index_impl {
    ($tp: ty, $n: ident, $e: ident, $r: ident, $m: ident) => {
        impl<$n, $e, Ix> ops::Index<$tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            type Output = $r;
            fn index(&self, ix: $tp) -> &$r {
                &self.$m[ix.index()]
            }

        }
        impl<'a, $n, $e, Ix> ops::Index<&'a $tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            type Output = $r;
            fn index(&self, ix: &'a $tp) -> &$r {
                &self.$m[ix.index()]
            }

        }

        impl<$n, $e, Ix> ops::IndexMut<$tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            fn index_mut(&mut self, ix: $tp) -> &mut $r {
                &mut self.$m[ix.index()]
            }

        }
        impl<'a, $n, $e, Ix> ops::IndexMut<&'a $tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            fn index_mut(&mut self, ix: &'a $tp) -> &mut $r {
                &mut self.$m[ix.index()]
            }

        }

    }
}
graph_index_impl!(EdgeIndex<Ix>, N, E, E, edges);
graph_index_impl!(NodeIndex<Ix>, N, E, N, nodes);
<commit_msg>util/graph/common: relax bounds on AdjacencyList ConcreteGraph impl<commit_after>//! Common types used by multiple graph implementations.

use std::ops;
use std::fmt::Debug;
use std::default::Default;
use std::hash::{Hash};

use num_traits::{NumCast,ToPrimitive};

use super::interface::{self, Id, Graph};
use super::iter::Indices;

// ================================================================
// Indices: types used to identify nodes and edges.

/// Default integer type used to identify nodes and edges.
pub type DefaultIndexType = u32;

/// Any integer type used as the underlying type for node and edge indices.
pub trait IndexType: Copy + Eq + Hash + Ord + Debug + NumCast + ToPrimitive + 'static {}
impl<T> IndexType for T where T: Copy + Eq + Hash + Ord + Debug + NumCast + ToPrimitive + 'static {}

macro_rules! impl_index_wrapper_type {
    ($tp: ty, $n: ident, $T: ident) => {
        impl<$T: IndexType> Id for $tp {
            #[inline(always)]
            fn new(v: usize) -> Self { $n(NumCast::from(v).unwrap()) }
            #[inline(always)]
            fn index(&self) -> usize { NumCast::from(self.0).unwrap() }
        }

        impl<U: NumCast + ToPrimitive, $T: IndexType> From<U> for $tp {
            fn from(v: U) -> Self {
                Self::new(NumCast::from(v).unwrap())
            }
        }
    }
}

/// Type used to identify and index the edges of a graph.
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct EdgeIndex<T: IndexType>(T);
impl_index_wrapper_type!(EdgeIndex<T>,EdgeIndex,T);

/// Type used to identify and index the nodes of a graph.
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct NodeIndex<T: IndexType>(T);
impl_index_wrapper_type!(NodeIndex<T>,NodeIndex,T);

// --------------------------------

/// Implement `interface::Node` for a type with members `incoming_edges` and
/// `outgoing_edges` of types compatible with `Vec<$I>`.
macro_rules! impl_basic_node {
    ($I: ident) => {
        //type EdgeIter<'a> = std::slice::Iter<'a,$I>;

        #[inline(always)]
        fn incoming_edges(&self) -> std::slice::Iter<$I> {
            self.incoming_edges.iter()
        }

        fn incoming_edge_count(&self) -> usize {
            self.incoming_edges.len()
        }

        #[inline(always)]
        fn outgoing_edges(&self) -> std::slice::Iter<$I> {
            self.outgoing_edges.iter()
        }

        fn outgoing_edge_count(&self) -> usize {
            self.outgoing_edges.len()
        }
    }
}

macro_rules! impl_basic_node_mut {
    ($I: ident) => {
        #[inline(always)]
        fn add_incoming_edge(&mut self, e: $I) {
            self.incoming_edges.push(e);
        }

        #[inline(always)]
        fn add_outgoing_edge(&mut self, e: $I) {
            self.outgoing_edges.push(e);
        }

        fn rev(&mut self) {
            ::std::mem::swap(&mut self.incoming_edges, &mut self.outgoing_edges);
        }
    }
}

// --------------------------------
// AdjacencyList

/// Adjacency-list graph implementation.
#[derive(Clone,Debug)]
pub struct AdjacencyList<N, E> {
    nodes: Vec<N>,
    edges: Vec<E>
}

impl<N, E> AdjacencyList<N, E> {
    /// Create an empty AdjacencyList instance.
    pub fn new() -> Self {
        AdjacencyList{nodes: Vec::new(), edges: Vec::new()}
    }
}

impl<N, E> Default for AdjacencyList<N, E> {
    #[inline(always)]
    fn default() -> Self {
        AdjacencyList::new()
   }
}

impl<N, E> interface::Graph for AdjacencyList<N, E>
    where N: interface::Node,
          E: interface::Edge
{
    type NodeId = <E as interface::Edge>::NodeId;
    type EdgeId = <N as interface::Node>::EdgeId;
    type EdgeIdIterator = Indices<Self::EdgeId>;
    type NodeIdIterator = Indices<Self::NodeId>;

    #[inline(always)]
    fn contains_node(&self, n: Self::NodeId) -> bool {
        n.index() < self.nodes.len()
    }

    #[inline]
    fn node_ids(&self) -> Self::NodeIdIterator {
        Indices::new(0..self.nodes.len())
    }

    #[inline]
    fn node_count(&self) -> usize {
        self.nodes.len()
    }

    fn contains_edge(&self, e: Self::EdgeId) -> bool {
        e.index() < self.edges.len()
    }

    fn edge_ids(&self) -> Self::EdgeIdIterator {
        Indices::new(0..self.edges.len())
    }

    fn edge_count(&self) -> usize {
        self.edges.len()
    }

}

impl<N, E> interface::ConcreteGraph for AdjacencyList<N, E>
    where N: interface::Node,
          E: interface::Edge
{
    type Node = N;
    type Edge = E;

    #[inline(always)]
    fn node(&self, n: Self::NodeId) -> &Self::Node {
        &self.nodes[n.index()]
    }

    #[inline(always)]
    fn edge(&self, e: Self::EdgeId) -> &Self::Edge {
        &self.edges[e.index()]
    }
}

impl<N, E> interface::ConcreteGraphMut for AdjacencyList<N, E>
    where N: interface::DirectedNodeMut,
          E: interface::DirectedEdgeMut
{
    #[inline(always)]
    fn node_mut(&mut self, n: Self::NodeId) -> &mut Self::Node {
        &mut self.nodes[n.index()]
    }

    #[inline(always)]
    fn edge_mut(&mut self, e: Self::EdgeId) -> &mut Self::Edge {
        &mut self.edges[e.index()]
    }

    #[inline(always)]
    fn add_node<T: Into<Self::Node>>(&mut self, n: T) -> Self::NodeId {
        self.nodes.push(n.into());
        Self::NodeId::new(self.nodes.len() - 1)
    }

    fn add_edge<T: Into<Self::Edge>>(&mut self, e: T) -> Self::EdgeId {
        let edge = e.into();
        let (a, b) = edge.endpoints();
        let srcidx = a.index();
        let destidx = b.index();

        let node_count = self.node_count();
        panic_unless!(srcidx < node_count, "Invalid source node provided to `Graph::add_edge`: {:?}", a);
        panic_unless!(destidx < node_count, "Invalid target node provided to `Graph::add_edge`: {:?}", b);

        self.edges.push(edge);
        let index = Self::EdgeId::new(self.edges.len() - 1);

        // Update cross-referenced edge lists for the connected nodes.
        self.nodes[srcidx].add_outgoing_edge(index);
        self.nodes[destidx].add_incoming_edge(index);

        index
    }
}

// Implement node-data lookup via indexing.
macro_rules! graph_index_impl {
    ($tp: ty, $n: ident, $e: ident, $r: ident, $m: ident) => {
        impl<$n, $e, Ix> ops::Index<$tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            type Output = $r;
            fn index(&self, ix: $tp) -> &$r {
                &self.$m[ix.index()]
            }

        }
        impl<'a, $n, $e, Ix> ops::Index<&'a $tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            type Output = $r;
            fn index(&self, ix: &'a $tp) -> &$r {
                &self.$m[ix.index()]
            }

        }

        impl<$n, $e, Ix> ops::IndexMut<$tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            fn index_mut(&mut self, ix: $tp) -> &mut $r {
                &mut self.$m[ix.index()]
            }

        }
        impl<'a, $n, $e, Ix> ops::IndexMut<&'a $tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            fn index_mut(&mut self, ix: &'a $tp) -> &mut $r {
                &mut self.$m[ix.index()]
            }

        }

    }
}
graph_index_impl!(EdgeIndex<Ix>, N, E, E, edges);
graph_index_impl!(NodeIndex<Ix>, N, E, N, nodes);
<|endoftext|>