<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    jellyfish_merkle_node::JellyfishMerkleNodeSchema, metrics::PRUNER_LEAST_READABLE_VERSION,
    pruner::db_pruner::DBPruner, stale_node_index::StaleNodeIndexSchema, OTHER_TIMERS_SECONDS,
};
use aptos_infallible::Mutex;
use aptos_jellyfish_merkle::StaleNodeIndex;
use aptos_logger::{error, warn};
use aptos_types::transaction::{AtomicVersion, Version};
use schemadb::{ReadOptions, SchemaBatch, SchemaIterator, DB};
use std::{
    iter::Peekable,
    sync::{atomic::Ordering, Arc},
    time::{Duration, Instant},
};

#[cfg(test)]
mod test;

pub const STATE_STORE_PRUNER_NAME: &str = "state store pruner";

pub struct StateStorePruner {
    db: Arc<DB>,
    index_min_nonpurged_version: AtomicVersion,
    index_purged_at: Mutex<Instant>,
    /// Keeps track of the target version that the pruner needs to achieve.
    target_version: AtomicVersion,
    min_readable_version: AtomicVersion,
}

impl DBPruner for StateStorePruner {
    fn name(&self) -> &'static str {
        STATE_STORE_PRUNER_NAME
    }

    fn prune(
        &self,
        _ledger_db_batch: &mut SchemaBatch,
        max_versions: u64,
    ) -> anyhow::Result<Version> {
        if !self.is_pruning_pending() {
            return Ok(self.min_readable_version());
        }
        let min_readable_version = self.min_readable_version.load(Ordering::Relaxed);
        let target_version = self.target_version();
        return match prune_state_store(
            &self.db,
            min_readable_version,
            target_version,
            max_versions as usize,
        ) {
            Ok(new_min_readable_version) => {
                self.record_progress(new_min_readable_version);
                // Try to purge the log.
                if let Err(e) = self.maybe_purge_index() {
                    warn!(
                        error = ?e,
                        "Failed purging state node index, ignored.",
                    );
                }
                Ok(new_min_readable_version)
            }
            Err(e) => {
                error!(
                    error = ?e,
                    "Error pruning stale state nodes.",
                );
                Err(e)
                // On error, stop retrying vigorously by making next recv() blocking.
            }
        };
    }

    fn initialize_min_readable_version(&self) -> anyhow::Result<Version> {
        let mut iter = self
            .db
            .iter::<StaleNodeIndexSchema>(ReadOptions::default())?;
        iter.seek_to_first();
        Ok(iter.next().transpose()?.map_or(0, |(index, _)| {
            index
                .stale_since_version
                .checked_sub(1)
                .expect("Nothing is stale since version 0.")
        }))
    }

    fn min_readable_version(&self) -> Version {
        self.min_readable_version.load(Ordering::Relaxed)
    }

    fn set_target_version(&self, target_version: Version) {
        self.target_version.store(target_version, Ordering::Relaxed);
    }

    fn target_version(&self) -> Version {
        self.target_version.load(Ordering::Relaxed)
    }

    fn record_progress(&self, min_readable_version: Version) {
        self.min_readable_version
            .store(min_readable_version, Ordering::Relaxed);
        PRUNER_LEAST_READABLE_VERSION
            .with_label_values(&["state_store"])
            .set(min_readable_version as i64);
    }
}

impl StateStorePruner {
    pub fn new(
        db: Arc<DB>,
        index_min_nonpurged_version: Version,
        index_purged_at: Instant,
    ) -> Self {
        let pruner = StateStorePruner {
            db,
            index_min_nonpurged_version: AtomicVersion::new(index_min_nonpurged_version),
            index_purged_at: Mutex::new(index_purged_at),
            target_version: AtomicVersion::new(0),
            min_readable_version: AtomicVersion::new(0),
        };
        pruner.initialize();
        pruner
    }

    /// Purge the stale node index so that after restart not too much already pruned stuff is dealt
    /// with again (although no harm is done deleting those then non-existent things.)
    ///
    /// We issue (range) deletes on the index only periodically instead of after every pruning batch
    /// to avoid sending too many deletions to the DB, which takes disk space and slows it down.
    fn maybe_purge_index(&self) -> anyhow::Result<()> {
        const MIN_INTERVAL: Duration = Duration::from_secs(10);
        const MIN_VERSIONS: u64 = 60000;

        // A deletion is issued at most once in one minute and when the pruner has progressed by at
        // least 60000 versions (assuming the pruner deletes as slow as 1000 versions per second,
        // this imposes at most one minute of work in vain after restarting.)
        let now = Instant::now();
        if self.min_readable_version.load(Ordering::Relaxed) < self.index_min_nonpurged_version() {
            warn!("State pruner inconsistent, min_readable_version is {} and  index_min_non-purged_version is {}",
                self.min_readable_version.load(Ordering::Relaxed), self.index_min_nonpurged_version());
            return Ok(());
        }

        if now - *self.index_purged_at.lock() > MIN_INTERVAL
            && self.min_readable_version.load(Ordering::Relaxed)
                - self.index_min_nonpurged_version()
                + 1
                > MIN_VERSIONS
        {
            let new_min_non_purged_version = self.min_readable_version.load(Ordering::Relaxed) + 1;
            self.db.range_delete::<StaleNodeIndexSchema, Version>(
                &self.index_min_nonpurged_version(),
                &new_min_non_purged_version, // end is exclusive
            )?;
            self.index_min_nonpurged_version
                .store(new_min_non_purged_version, Ordering::Relaxed);
            *self.index_purged_at.lock() = now;
        }
        Ok(())
    }

    pub fn index_min_nonpurged_version(&self) -> Version {
        self.index_min_nonpurged_version.load(Ordering::Relaxed)
    }

    pub fn target_version(&self) -> Version {
        self.target_version.load(Ordering::Relaxed)
    }
}

pub fn prune_state_store(
    db: &DB,
    min_readable_version: Version,
    target_version: Version,
    max_versions: usize,
) -> anyhow::Result<Version> {
    let indices = StaleNodeIndicesByVersionIterator::new(db, min_readable_version, target_version)?
        .take(max_versions) // Iterator<Item = Result<Vec<StaleNodeIndex>>>
        .collect::<anyhow::Result<Vec<_>>>()? // now Vec<Vec<StaleNodeIndex>>
        .into_iter()
        .flatten()
        .collect::<Vec<_>>();

    if indices.is_empty() {
        Ok(min_readable_version)
    } else {
        let _timer = OTHER_TIMERS_SECONDS
            .with_label_values(&["pruner_commit"])
            .start_timer();
        let new_min_readable_version = indices.last().expect("Should exist.").stale_since_version;
        let mut batch = SchemaBatch::new();
        indices
            .into_iter()
            .try_for_each(|index| batch.delete::<JellyfishMerkleNodeSchema>(&index.node_key))?;
        db.write_schemas(batch)?;
        Ok(new_min_readable_version)
    }
}

struct StaleNodeIndicesByVersionIterator<'a> {
    inner: Peekable<SchemaIterator<'a, StaleNodeIndexSchema>>,
    target_min_readable_version: Version,
}

impl<'a> StaleNodeIndicesByVersionIterator<'a> {
    fn new(
        db: &'a DB,
        min_readable_version: Version,
        target_min_readable_version: Version,
    ) -> anyhow::Result<Self> {
        let mut iter = db.iter::<StaleNodeIndexSchema>(ReadOptions::default())?;
        iter.seek(&min_readable_version)?;

        Ok(Self {
            inner: iter.peekable(),
            target_min_readable_version,
        })
    }

    fn next_result(&mut self) -> anyhow::Result<Option<Vec<StaleNodeIndex>>> {
        match self.inner.next().transpose()? {
            None => Ok(None),
            Some((index, _)) => {
                let version = index.stale_since_version;
                if version > self.target_min_readable_version {
                    return Ok(None);
                }

                let mut indices = vec![index];
                while let Some(res) = self.inner.peek() {
                    if let Ok((index_ref, _)) = res {
                        if index_ref.stale_since_version != version {
                            break;
                        }
                    }

                    let (index, _) = self.inner.next().transpose()?.expect("Should be Some.");
                    indices.push(index);
                }

                Ok(Some(indices))
            }
        }
    }
}

impl<'a> Iterator for StaleNodeIndicesByVersionIterator<'a> {
    type Item = anyhow::Result<Vec<StaleNodeIndex>>;

    fn next(&mut self) -> Option<Self::Item> {
        self.next_result().transpose()
    }
}
<commit_msg>trivial: use anyhow::Result<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    jellyfish_merkle_node::JellyfishMerkleNodeSchema, metrics::PRUNER_LEAST_READABLE_VERSION,
    pruner::db_pruner::DBPruner, stale_node_index::StaleNodeIndexSchema, OTHER_TIMERS_SECONDS,
};
use anyhow::Result;
use aptos_infallible::Mutex;
use aptos_jellyfish_merkle::StaleNodeIndex;
use aptos_logger::{error, warn};
use aptos_types::transaction::{AtomicVersion, Version};
use schemadb::{ReadOptions, SchemaBatch, SchemaIterator, DB};
use std::{
    iter::Peekable,
    sync::{atomic::Ordering, Arc},
    time::{Duration, Instant},
};

#[cfg(test)]
mod test;

pub const STATE_STORE_PRUNER_NAME: &str = "state store pruner";

pub struct StateStorePruner {
    db: Arc<DB>,
    index_min_nonpurged_version: AtomicVersion,
    index_purged_at: Mutex<Instant>,
    /// Keeps track of the target version that the pruner needs to achieve.
    target_version: AtomicVersion,
    min_readable_version: AtomicVersion,
}

impl DBPruner for StateStorePruner {
    fn name(&self) -> &'static str {
        STATE_STORE_PRUNER_NAME
    }

    fn prune(&self, _ledger_db_batch: &mut SchemaBatch, max_versions: u64) -> Result<Version> {
        if !self.is_pruning_pending() {
            return Ok(self.min_readable_version());
        }
        let min_readable_version = self.min_readable_version.load(Ordering::Relaxed);
        let target_version = self.target_version();
        return match prune_state_store(
            &self.db,
            min_readable_version,
            target_version,
            max_versions as usize,
        ) {
            Ok(new_min_readable_version) => {
                self.record_progress(new_min_readable_version);
                // Try to purge the log.
                if let Err(e) = self.maybe_purge_index() {
                    warn!(
                        error = ?e,
                        "Failed purging state node index, ignored.",
                    );
                }
                Ok(new_min_readable_version)
            }
            Err(e) => {
                error!(
                    error = ?e,
                    "Error pruning stale state nodes.",
                );
                Err(e)
                // On error, stop retrying vigorously by making next recv() blocking.
            }
        };
    }

    fn initialize_min_readable_version(&self) -> Result<Version> {
        let mut iter = self
            .db
            .iter::<StaleNodeIndexSchema>(ReadOptions::default())?;
        iter.seek_to_first();
        Ok(iter.next().transpose()?.map_or(0, |(index, _)| {
            index
                .stale_since_version
                .checked_sub(1)
                .expect("Nothing is stale since version 0.")
        }))
    }

    fn min_readable_version(&self) -> Version {
        self.min_readable_version.load(Ordering::Relaxed)
    }

    fn set_target_version(&self, target_version: Version) {
        self.target_version.store(target_version, Ordering::Relaxed);
    }

    fn target_version(&self) -> Version {
        self.target_version.load(Ordering::Relaxed)
    }

    fn record_progress(&self, min_readable_version: Version) {
        self.min_readable_version
            .store(min_readable_version, Ordering::Relaxed);
        PRUNER_LEAST_READABLE_VERSION
            .with_label_values(&["state_store"])
            .set(min_readable_version as i64);
    }
}

impl StateStorePruner {
    pub fn new(
        db: Arc<DB>,
        index_min_nonpurged_version: Version,
        index_purged_at: Instant,
    ) -> Self {
        let pruner = StateStorePruner {
            db,
            index_min_nonpurged_version: AtomicVersion::new(index_min_nonpurged_version),
            index_purged_at: Mutex::new(index_purged_at),
            target_version: AtomicVersion::new(0),
            min_readable_version: AtomicVersion::new(0),
        };
        pruner.initialize();
        pruner
    }

    /// Purge the stale node index so that after restart not too much already pruned stuff is dealt
    /// with again (although no harm is done deleting those then non-existent things.)
    ///
    /// We issue (range) deletes on the index only periodically instead of after every pruning batch
    /// to avoid sending too many deletions to the DB, which takes disk space and slows it down.
    fn maybe_purge_index(&self) -> Result<()> {
        const MIN_INTERVAL: Duration = Duration::from_secs(10);
        const MIN_VERSIONS: u64 = 60000;

        // A deletion is issued at most once in one minute and when the pruner has progressed by at
        // least 60000 versions (assuming the pruner deletes as slow as 1000 versions per second,
        // this imposes at most one minute of work in vain after restarting.)
        let now = Instant::now();
        if self.min_readable_version.load(Ordering::Relaxed) < self.index_min_nonpurged_version() {
            warn!("State pruner inconsistent, min_readable_version is {} and  index_min_non-purged_version is {}",
                self.min_readable_version.load(Ordering::Relaxed), self.index_min_nonpurged_version());
            return Ok(());
        }

        if now - *self.index_purged_at.lock() > MIN_INTERVAL
            && self.min_readable_version.load(Ordering::Relaxed)
                - self.index_min_nonpurged_version()
                + 1
                > MIN_VERSIONS
        {
            let new_min_non_purged_version = self.min_readable_version.load(Ordering::Relaxed) + 1;
            self.db.range_delete::<StaleNodeIndexSchema, Version>(
                &self.index_min_nonpurged_version(),
                &new_min_non_purged_version, // end is exclusive
            )?;
            self.index_min_nonpurged_version
                .store(new_min_non_purged_version, Ordering::Relaxed);
            *self.index_purged_at.lock() = now;
        }
        Ok(())
    }

    pub fn index_min_nonpurged_version(&self) -> Version {
        self.index_min_nonpurged_version.load(Ordering::Relaxed)
    }

    pub fn target_version(&self) -> Version {
        self.target_version.load(Ordering::Relaxed)
    }
}

pub fn prune_state_store(
    db: &DB,
    min_readable_version: Version,
    target_version: Version,
    max_versions: usize,
) -> Result<Version> {
    let indices = StaleNodeIndicesByVersionIterator::new(db, min_readable_version, target_version)?
        .take(max_versions) // Iterator<Item = Result<Vec<StaleNodeIndex>>>
        .collect::<Result<Vec<_>>>()? // now Vec<Vec<StaleNodeIndex>>
        .into_iter()
        .flatten()
        .collect::<Vec<_>>();

    if indices.is_empty() {
        Ok(min_readable_version)
    } else {
        let _timer = OTHER_TIMERS_SECONDS
            .with_label_values(&["pruner_commit"])
            .start_timer();
        let new_min_readable_version = indices.last().expect("Should exist.").stale_since_version;
        let mut batch = SchemaBatch::new();
        indices
            .into_iter()
            .try_for_each(|index| batch.delete::<JellyfishMerkleNodeSchema>(&index.node_key))?;
        db.write_schemas(batch)?;
        Ok(new_min_readable_version)
    }
}

struct StaleNodeIndicesByVersionIterator<'a> {
    inner: Peekable<SchemaIterator<'a, StaleNodeIndexSchema>>,
    target_min_readable_version: Version,
}

impl<'a> StaleNodeIndicesByVersionIterator<'a> {
    fn new(
        db: &'a DB,
        min_readable_version: Version,
        target_min_readable_version: Version,
    ) -> Result<Self> {
        let mut iter = db.iter::<StaleNodeIndexSchema>(ReadOptions::default())?;
        iter.seek(&min_readable_version)?;

        Ok(Self {
            inner: iter.peekable(),
            target_min_readable_version,
        })
    }

    fn next_result(&mut self) -> Result<Option<Vec<StaleNodeIndex>>> {
        match self.inner.next().transpose()? {
            None => Ok(None),
            Some((index, _)) => {
                let version = index.stale_since_version;
                if version > self.target_min_readable_version {
                    return Ok(None);
                }

                let mut indices = vec![index];
                while let Some(res) = self.inner.peek() {
                    if let Ok((index_ref, _)) = res {
                        if index_ref.stale_since_version != version {
                            break;
                        }
                    }

                    let (index, _) = self.inner.next().transpose()?.expect("Should be Some.");
                    indices.push(index);
                }

                Ok(Some(indices))
            }
        }
    }
}

impl<'a> Iterator for StaleNodeIndicesByVersionIterator<'a> {
    type Item = Result<Vec<StaleNodeIndex>>;

    fn next(&mut self) -> Option<Self::Item> {
        self.next_result().transpose()
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
#[macro_use]
extern crate rosrust;
#[macro_use]
extern crate rosrust_codegen;

rosmsg_include!();

fn main() {
    env_logger::init();

    // Initialize node
    rosrust::init("talker");

    // Create publisher
    let mut chatter_pub_latched = rosrust::publish("chatter").unwrap();
    let mut chatter_pub_unlatched = rosrust::publish("chatter").unwrap();
    chatter_pub_unlatched.set_latching(false);

    let mut msg = msg::std_msgs::String::default();
    msg.data = String::from("hello world latched");

    // Log event
    ros_info!("Publishing: {}", msg.data);

    // Send string message to topic via publisher
    chatter_pub_latched.send(msg.clone()).unwrap();

    msg.data = String::from("hello world unlatched");

    // Log event
    ros_info!("Publishing: {}", msg.data);

    // Send string message to topic via publisher, without latching it
    chatter_pub_unlatched.send(msg).unwrap();

    rosrust::spin();
}
<commit_msg>Fix latching example<commit_after>extern crate env_logger;
#[macro_use]
extern crate rosrust;
#[macro_use]
extern crate rosrust_codegen;

rosmsg_include!();

fn main() {
    env_logger::init();

    // Initialize node
    rosrust::init("talker");

    // Create publisher
    let mut chatter_pub_latched = rosrust::publish("chatter").unwrap();
    let mut chatter_pub_unlatched = rosrust::publish("chatter").unwrap();
    chatter_pub_latched.set_latching(true);

    let mut msg = msg::std_msgs::String::default();
    msg.data = String::from("hello world latched");

    // Log event
    ros_info!("Publishing: {}", msg.data);

    // Send string message to topic via publisher
    chatter_pub_latched.send(msg.clone()).unwrap();

    msg.data = String::from("hello world unlatched");

    // Log event
    ros_info!("Publishing: {}", msg.data);

    // Send string message to topic via publisher, without latching it
    chatter_pub_unlatched.send(msg).unwrap();

    rosrust::spin();
}
<|endoftext|>


<commit_before>use {Field, Matrix2d, Rectangle};
use {Transform2d};
use {Borrowed, Value};
use vecmath::{translate, multiply, rotate_radians, scale, shear};
use {AddColor};
use {EllipseColorContext};

/// An ellipse context.
pub struct EllipseContext<'a> {
    /// Base/origin transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle enclosing the ellipse.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for EllipseContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddColor<'a, EllipseColorContext<'a>> for EllipseContext<'a> {
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> EllipseColorContext<'a> {
        EllipseColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            color: Value([r, g, b, a]),
        }
    }
}

<commit_msg>Implemented `RelativeRectangle` for `EllipseContext`<commit_after>use {Field, Matrix2d, Rectangle};
use {Transform2d};
use {Borrowed, Value};
use vecmath::{margin, translate, multiply, rotate_radians, scale, shear};
use {AddColor};
use {EllipseColorContext};
use {RelativeRectangle};

/// An ellipse context.
pub struct EllipseContext<'a> {
    /// Base/origin transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle enclosing the ellipse.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for EllipseContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddColor<'a, EllipseColorContext<'a>> for EllipseContext<'a> {
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> EllipseColorContext<'a> {
        EllipseColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            color: Value([r, g, b, a]),
        }
    }
}

impl<'a> RelativeRectangle<'a> for EllipseContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(margin(self.rect.get(), m)),
        }
    }
}

<|endoftext|>


<commit_before>// https://github.com/serde-rs/serde/issues/927

use std::collections::HashMap;
use std::collections::BTreeMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
#[macro_use] extern crate serde_json;
extern crate serde_yaml;
#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
    Array(Vec<ArgValue>),
    Hash(BTreeMap<String, ArgValue>),
}

impl ArgValue {
    fn to_json(&self, n: &str) -> String {
        match *self {
            ArgValue::None             =>   "".to_string(),
            ArgValue::Str(ref v)       =>   format!("\"{}\":{}", n, v ),
            ArgValue::Bool(ref v)      =>   format!("\"{}\":{}", n, v ),
            ArgValue::Byte(ref v)      =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int16(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int32(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int64(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt16(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt32(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt64(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::Double(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::Array(ref v)     =>   format!("\"{}\":{:?}", n, v ),
            ArgValue::Hash(ref v)      =>   format!("\"{}\":{:?}", n, v ),
        }
    }
}

trait FromVariant: Sized {
    fn from_variant(variant: &ArgValue) -> Option<Self>;
}

// String, Array, Hash differ, for all other variants use macros
impl FromVariant for String {
    fn from_variant(variant: &ArgValue) -> Option<Self> {
        match *variant {
            ArgValue::Str(ref v) => Some((*v).clone()),
            _ => None
        }
    }
}

impl<T> FromVariant for Vec<T> where T: FromVariant {
    fn from_variant(variant: &ArgValue) -> Option<Self> {
        match *variant {
            ArgValue::Array(ref v) => {
                let mut ret = Vec::<T>::new();
                for el in v {
                    let val: T = FromVariant::from_variant(&el).expect("type mismatch");
                    ret.push(val);
                }
                Some(ret)
            }
            _ => None
        }
    }
}

macro_rules! from_variant_inst {
    [$t: tt, $i: ident] => {
        impl FromVariant for $t {
            fn from_variant(variant: &ArgValue) -> Option<Self> {
                match *variant {
                    ArgValue::$i(v) => Some(v),
                    _ => None
                }
            }
        }
    };
}

from_variant_inst![bool, Bool];
from_variant_inst![u8,   Byte];
from_variant_inst![i16,  Int16];
from_variant_inst![i32,  Int32];
from_variant_inst![i64,  Int64];
from_variant_inst![u16,  UInt16];
from_variant_inst![u32,  UInt32];
from_variant_inst![u64,  UInt64];
from_variant_inst![f64,  Double];

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgsTag {
    Args,
    Rets,
}

#[derive(Serialize, Deserialize, Debug)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs = HashMap<String, ArgValue>;
type NamedArgs2 = HashMap<String, serde_json::value::Value>;

#[derive(Serialize, Deserialize)]
struct DbusMessage {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    args: NamedArgs,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting(String, String, String, Vec<DbusMessage>);

#[derive(Serialize, Deserialize)]
struct ConfYaml(Vec<DbusMessageRouting>);

#[derive(Serialize, Deserialize, Debug)]
struct ClientRequest {
    #[serde(rename = "type")]
    tp: DbusMessageType,
    name: String,
    args: Option<NamedArgs2>,
    rets: Option<NamedArgs2>,
}

impl ClientRequest {
    fn to_json(&self) -> String {
        fn serialize_args_or_rets(tag: &str, ar: &Option<NamedArgs2>) -> String {
            match ar {
                &Some(ref a) => {
                    let args_serialized: Vec<_> = a.iter().map( |ret| {
                        let (n, val) = ret;
                        //val.to_json(n)
                        format!("\"{}\":{}", n, val)
                        } ).collect();
                    format!("\"{}\": {{ {}", tag, args_serialized.join(","))
                },
                &None =>  "".to_string(),
            }
        }
        let json_reply_prefix = format!("{{\"type\":\"{:?}\",\"name\":\"{}\",", &self.tp, &self.name);
        let args_serialized = serialize_args_or_rets("args", &self.args);
        let rets_serialized = serialize_args_or_rets("rets", &self.rets);
        format!("{}{}{} }} }}",json_reply_prefix, args_serialized, rets_serialized).to_string()
    }
}

#[derive(Serialize, Deserialize)]
struct ClientRequestBody(DbusMessageType, NamedArgs);

type CRequest = HashMap<String, ClientRequestBody>;

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                    ("param2".to_string(), ArgValue::Bool(true)),
                                    ("param3".to_string(), ArgValue::Int64(17i64)),
                                    ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                    ("param5".to_string(), ArgValue::Array( vec![ArgValue::Double(1.1), ArgValue::Double(2.2), ArgValue::Double(3.3), ] )),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest { tp: DbusMessageType::Method, name: "api_name".to_string(),
                            args: Some([    ("param1".to_string(), json!("Hi")),
                                            ("param2".to_string(), json!(true)),
                                            ("param3".to_string(), json!(17i64)),
                                            ("param4".to_string(), json!(2.718281828f64)),
                                            ("param5".to_string(), json!( vec![ json!(1.1), json!(2.2), json!(3.3), ] )),
                                       ].iter().cloned().collect()),
                            rets: None,
                          };
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let d: ClientRequest = serde_json::from_str(&rs).expect("json deserialization error");
    println!("d: {:?}", d);

    let ds = serde_json::to_string(&d).unwrap();
    println!(" => ds: {}", ds);

    let data = "{\"type\":\"Method\",\"name\":\"utest_4p2r\",\"rets\":{\"parm1\":71,\"parm2\":12.12 } }";
    let d2: ClientRequest = serde_json::from_str(&data).expect("json deserialization error");
    println!("d2: {:?}", d2);
    println!("d2.to_json(): {}", d2.to_json());

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                        ("param2".to_string(), ArgValue::Bool(true)),
                                        ("param3".to_string(), ArgValue::Int64(17i64)),
                                        ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request: CRequest = HashMap::new();
    a_request.insert("api_name".to_string(), rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

    let de: CRequest = serde_json::from_str(&rsq).expect("json deserialization error");

    let rsq2 = serde_json::to_string(&de).expect("json serialization error");
    println!("rsq2 : {}", rsq2);

    for key in de.keys() {
        println!("key {}", key);
    }
    println!("key[0] : {}", de.keys().nth(0).unwrap());

    let arr = ArgValue:: Array( vec![ArgValue::Double(1.1), ArgValue::Double(2.2), ArgValue::Double(3.3),] );

    let from_arr_variant: Vec<f64> = FromVariant::from_variant(&arr).expect("array expected");

    println!("arr: {:?} from_arr_variant: {:?}", arr, from_arr_variant);

    let arr2 = ArgValue::Array( vec![ArgValue::Array(vec![ArgValue::Double(1.1), ArgValue::Double(2.2)]),
                                     ArgValue::Array(vec![ArgValue::Double(3.3), ArgValue::Double(4.4)]) ] );
    let from_arr2_variant: Vec<Vec<f64>> = FromVariant::from_variant(&arr2).expect("array of array expected");

    println!("arr2: {:?} from_arr2_variant: {:?}", arr2, from_arr2_variant);

    let bad_arr = ArgValue:: Array( vec![ArgValue::Double(1.1), ArgValue::Int32(2), ArgValue::Double(3.3),] );
    println!("bad_arr: {:?}", bad_arr);

    // expect here runtime error `thread 'main' panicked at 'type mismatch',`
    let from_bad_arr_variant: Vec<f64> = FromVariant::from_variant(&bad_arr).expect("array expected");
}
<commit_msg>`typeof` comment.<commit_after>// https://github.com/serde-rs/serde/issues/927

use std::collections::HashMap;
use std::collections::BTreeMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
#[macro_use] extern crate serde_json;
extern crate serde_yaml;
#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
    Array(Vec<ArgValue>),
    Hash(BTreeMap<String, ArgValue>),
}

impl ArgValue {
    fn to_json(&self, n: &str) -> String {
        match *self {
            ArgValue::None             =>   "".to_string(),
            ArgValue::Str(ref v)       =>   format!("\"{}\":{}", n, v ),
            ArgValue::Bool(ref v)      =>   format!("\"{}\":{}", n, v ),
            ArgValue::Byte(ref v)      =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int16(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int32(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int64(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt16(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt32(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt64(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::Double(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::Array(ref v)     =>   format!("\"{}\":{:?}", n, v ),
            ArgValue::Hash(ref v)      =>   format!("\"{}\":{:?}", n, v ),
        }
    }
}

trait FromVariant: Sized {
    fn from_variant(variant: &ArgValue) -> Option<Self>;
}

// String, Array, Hash differ, for all other variants use macros
impl FromVariant for String {
    fn from_variant(variant: &ArgValue) -> Option<Self> {
        match *variant {
            ArgValue::Str(ref v) => Some((*v).clone()),
            _ => None
        }
    }
}

impl<T> FromVariant for Vec<T> where T: FromVariant {
    fn from_variant(variant: &ArgValue) -> Option<Self> {
        match *variant {
            ArgValue::Array(ref v) => {
                let mut ret = Vec::<T>::new();
                for el in v {
                    let val: T = FromVariant::from_variant(&el).expect("type mismatch");
                    ret.push(val);
                }
                Some(ret)
            }
            _ => None
        }
    }
}

macro_rules! from_variant_inst {
    [$t: tt, $i: ident] => {
        impl FromVariant for $t {
            fn from_variant(variant: &ArgValue) -> Option<Self> {
                match *variant {
                    ArgValue::$i(v) => Some(v),
                    _ => None
                }
            }
        }
    };
}

from_variant_inst![bool, Bool];
from_variant_inst![u8,   Byte];
from_variant_inst![i16,  Int16];
from_variant_inst![i32,  Int32];
from_variant_inst![i64,  Int64];
from_variant_inst![u16,  UInt16];
from_variant_inst![u32,  UInt32];
from_variant_inst![u64,  UInt64];
from_variant_inst![f64,  Double];

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgsTag {
    Args,
    Rets,
}

#[derive(Serialize, Deserialize, Debug)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs = HashMap<String, ArgValue>;
type NamedArgs2 = HashMap<String, serde_json::value::Value>;

#[derive(Serialize, Deserialize)]
struct DbusMessage {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    args: NamedArgs,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting(String, String, String, Vec<DbusMessage>);

#[derive(Serialize, Deserialize)]
struct ConfYaml(Vec<DbusMessageRouting>);

#[derive(Serialize, Deserialize, Debug)]
struct ClientRequest {
    #[serde(rename = "type")]
    tp: DbusMessageType,
    name: String,
    args: Option<NamedArgs2>,
    rets: Option<NamedArgs2>,
}

impl ClientRequest {
    fn to_json(&self) -> String {
        fn serialize_args_or_rets(tag: &str, ar: &Option<NamedArgs2>) -> String {
            match ar {
                &Some(ref a) => {
                    let args_serialized: Vec<_> = a.iter().map( |ret| {
                        let (n, val) = ret;
                        //val.to_json(n)
                        format!("\"{}\":{}", n, val)
                        } ).collect();
                    format!("\"{}\": {{ {}", tag, args_serialized.join(","))
                },
                &None =>  "".to_string(),
            }
        }
        let json_reply_prefix = format!("{{\"type\":\"{:?}\",\"name\":\"{}\",", &self.tp, &self.name);
        let args_serialized = serialize_args_or_rets("args", &self.args);
        let rets_serialized = serialize_args_or_rets("rets", &self.rets);
        format!("{}{}{} }} }}",json_reply_prefix, args_serialized, rets_serialized).to_string()
    }
}

#[derive(Serialize, Deserialize)]
struct ClientRequestBody(DbusMessageType, NamedArgs);

type CRequest = HashMap<String, ClientRequestBody>;

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                    ("param2".to_string(), ArgValue::Bool(true)),
                                    ("param3".to_string(), ArgValue::Int64(17i64)),
                                    ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                    ("param5".to_string(), ArgValue::Array( vec![ArgValue::Double(1.1), ArgValue::Double(2.2), ArgValue::Double(3.3), ] )),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest { tp: DbusMessageType::Method, name: "api_name".to_string(),
                            args: Some([    ("param1".to_string(), json!("Hi")),
                                            ("param2".to_string(), json!(true)),
                                            ("param3".to_string(), json!(17i64)),
                                            ("param4".to_string(), json!(2.718281828f64)),
                                            ("param5".to_string(), json!( vec![ json!(1.1), json!(2.2), json!(3.3), ] )),
                                       ].iter().cloned().collect()),
                            rets: None,
                          };
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let d: ClientRequest = serde_json::from_str(&rs).expect("json deserialization error");
    println!("d: {:?}", d);

    let ds = serde_json::to_string(&d).unwrap();
    println!(" => ds: {}", ds);

    let data = "{\"type\":\"Method\",\"name\":\"utest_4p2r\",\"rets\":{\"parm1\":71,\"parm2\":12.12 } }";
    let d2: ClientRequest = serde_json::from_str(&data).expect("json deserialization error");
    println!("d2: {:?}", d2);
    println!("d2.to_json(): {}", d2.to_json());

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                        ("param2".to_string(), ArgValue::Bool(true)),
                                        ("param3".to_string(), ArgValue::Int64(17i64)),
                                        ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request: CRequest = HashMap::new();
    a_request.insert("api_name".to_string(), rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

    let de: CRequest = serde_json::from_str(&rsq).expect("json deserialization error");

    let rsq2 = serde_json::to_string(&de).expect("json serialization error");
    println!("rsq2 : {}", rsq2);

    for key in de.keys() {
        println!("key {}", key);
    }
    println!("key[0] : {}", de.keys().nth(0).unwrap());

    let arr = ArgValue:: Array( vec![ArgValue::Double(1.1), ArgValue::Double(2.2), ArgValue::Double(3.3),] );

    let from_arr_variant: Vec<f64> = FromVariant::from_variant(&arr).expect("array expected");

    println!("arr: {:?} from_arr_variant: {:?}", arr, from_arr_variant);

    let arr2 = ArgValue::Array( vec![ArgValue::Array(vec![ArgValue::Double(1.1), ArgValue::Double(2.2)]),
                                     ArgValue::Array(vec![ArgValue::Double(3.3), ArgValue::Double(4.4)]) ] );
    // typeof is reserved keyword but there is no support
    let mut from_arr2_variant = Vec::<Vec<f64>>::new();
    from_arr2_variant = FromVariant::from_variant(&arr2).expect("array of array expected");

    println!("arr2: {:?} from_arr2_variant: {:?}", arr2, from_arr2_variant);

    let bad_arr = ArgValue:: Array( vec![ArgValue::Double(1.1), ArgValue::Int32(2), ArgValue::Double(3.3),] );
    println!("bad_arr: {:?}", bad_arr);

    // expect here runtime error `thread 'main' panicked at 'type mismatch',`
    let from_bad_arr_variant: Vec<f64> = FromVariant::from_variant(&bad_arr).expect("array expected");
}
<|endoftext|>


<commit_before>use ast::with_error_checking_parse;
use core::{Match, MatchType, Session};
use typeinf::get_function_declaration;

use syntex_syntax::ast::ImplItemKind;

/// Returns completion snippets usable by some editors
///
/// Generates a snippet string given a `Match`. The provided snippet contains
/// substrings like "${1:name}" which some editors can use to quickly fill in
/// arguments.
///
/// # Examples
///
/// ```no_run
/// extern crate racer;
///
/// use std::path::Path;
///
/// let path = Path::new(".");
/// let cache = racer::FileCache::default();
/// let session = racer::Session::new(&cache);
///
/// let m = racer::complete_fully_qualified_name(
///     "std::fs::canonicalize",
///     &path,
///     &session
/// ).next().unwrap();
///
/// let snip = racer::snippet_for_match(&m, &session);
/// assert_eq!(snip, "canonicalize(${1:path})");
/// ```
pub fn snippet_for_match(m: &Match, session: &Session) -> String {
    if m.mtype == MatchType::Function {
        let method = get_function_declaration(m, session);
        if let Some(m) = MethodInfo::from_source_str(&method) {
            m.snippet()
        } else {
            "".into()
        }
    } else {
        m.matchstr.clone()
    }
}

struct MethodInfo {
    name: String,
    args: Vec<String>
}

impl MethodInfo {
    ///Parses method declaration as string and returns relevant data
    fn from_source_str(source: &str) -> Option<MethodInfo> {
        let trim: &[_] = &['\n', '\r', '{', ' '];
        let decorated = format!("{} {{}}()", source.trim_right_matches(trim));

        with_error_checking_parse(decorated, |p| {
            if let Ok(method) = p.parse_impl_item() {
                if let ImplItemKind::Method(ref msig, _) = method.node {
                        let decl = &msig.decl;
                        return Some(MethodInfo {
                            // ident.as_str calls Ident.name.as_str
                            name: method.ident.name.to_string(),
                            args: decl.inputs
                                      .iter()
                                      .map(|arg| {
                                          let codemap = &p.sess.codemap();
                                          match codemap.span_to_snippet(arg.pat.span) {
                                              Ok(name) => name,
                                              _ => "".into()
                                          }
                                      })
                                      .collect()
                        })
                }
            }
            debug!("Unable to parse method declaration. |{}|", source);
            None
        })
    }

    ///Returns completion snippets usable by some editors
    fn snippet(&self) -> String {
        format!("{}({})",
                self.name,
                &self.args
                     .iter()
                     .filter(|&s| !s.ends_with("self"))
                     .enumerate()
                     .fold(String::new(), |cur, (i, ref s)| {
                         let arg = format!("${{{}:{}}}", i + 1, s);
                         let delim = if i > 0 { ", " } else { "" };
                         cur + delim + &arg
                     }))
    }
}

#[test]
fn method_info_test() {
    let info = MethodInfo::from_source_str("pub fn new() -> Vec<T>").unwrap();
    assert_eq!(info.name, "new");
    assert_eq!(info.args.len(), 0);
    assert_eq!(info.snippet(), "new()");

    let info = MethodInfo::from_source_str("pub fn reserve(&mut self, additional: uint)").unwrap();
    assert_eq!(info.name, "reserve");
    assert_eq!(info.args.len(), 2);
    assert_eq!(info.args[0], "&mut self");
    assert_eq!(info.snippet(), "reserve(${1:additional})");
}
<commit_msg>Include the type name with snippets<commit_after>use ast::with_error_checking_parse;
use core::{Match, MatchType, Session};
use typeinf::get_function_declaration;

use syntex_syntax::ast::ImplItemKind;

/// Returns completion snippets usable by some editors
///
/// Generates a snippet string given a `Match`. The provided snippet contains
/// substrings like "${1:name}" which some editors can use to quickly fill in
/// arguments.
///
/// # Examples
///
/// ```no_run
/// extern crate racer;
///
/// use std::path::Path;
///
/// let path = Path::new(".");
/// let cache = racer::FileCache::default();
/// let session = racer::Session::new(&cache);
///
/// let m = racer::complete_fully_qualified_name(
///     "std::fs::canonicalize",
///     &path,
///     &session
/// ).next().unwrap();
///
/// let snip = racer::snippet_for_match(&m, &session);
/// assert_eq!(snip, "canonicalize(${1:path})");
/// ```
pub fn snippet_for_match(m: &Match, session: &Session) -> String {
    if m.mtype == MatchType::Function {
        let method = get_function_declaration(m, session);
        if let Some(m) = MethodInfo::from_source_str(&method) {
            m.snippet()
        } else {
            "".into()
        }
    } else {
        m.matchstr.clone()
    }
}

struct MethodInfo {
    name: String,
    args: Vec<String>
}

impl MethodInfo {
    ///Parses method declaration as string and returns relevant data
    fn from_source_str(source: &str) -> Option<MethodInfo> {
        let trim: &[_] = &['\n', '\r', '{', ' '];
        let decorated = format!("{} {{}}()", source.trim_right_matches(trim));

        with_error_checking_parse(decorated, |p| {
            if let Ok(method) = p.parse_impl_item() {
                if let ImplItemKind::Method(ref msig, _) = method.node {
                        let decl = &msig.decl;
                        return Some(MethodInfo {
                            // ident.as_str calls Ident.name.as_str
                            name: method.ident.name.to_string(),
                            args: decl.inputs
                                      .iter()
                                      .map(|arg| {
                                          let codemap = &p.sess.codemap();
                                          let var_name = match codemap.span_to_snippet(arg.pat.span) {
                                              Ok(name) => name,
                                              _ => "".into()
                                          };
                                          match codemap.span_to_snippet(arg.ty.span) {
                                              Ok(ref type_name) if !type_name.is_empty() => format!("{}: {}", var_name, type_name),
                                              _ => var_name
                                          }
                                      })
                                      .collect()
                        })
                }
            }
            debug!("Unable to parse method declaration. |{}|", source);
            None
        })
    }

    ///Returns completion snippets usable by some editors
    fn snippet(&self) -> String {
        format!("{}({})",
                self.name,
                &self.args
                     .iter()
                     .filter(|&s| !s.ends_with("self"))
                     .enumerate()
                     .fold(String::new(), |cur, (i, ref s)| {
                         let arg = format!("${{{}:{}}}", i + 1, s);
                         let delim = if i > 0 { ", " } else { "" };
                         cur + delim + &arg
                     }))
    }
}

#[test]
fn method_info_test() {
    let info = MethodInfo::from_source_str("pub fn new() -> Vec<T>").unwrap();
    assert_eq!(info.name, "new");
    assert_eq!(info.args.len(), 0);
    assert_eq!(info.snippet(), "new()");

    let info = MethodInfo::from_source_str("pub fn reserve(&mut self, additional: uint)").unwrap();
    assert_eq!(info.name, "reserve");
    assert_eq!(info.args.len(), 2);
    assert_eq!(info.args[0], "&mut self");
    assert_eq!(info.snippet(), "reserve(${1:additional: uint})");
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::boxed::Box;
use std::result;
use std::error;
use std::thread;
use std::convert;
use std::time::Duration;

use bytes::{Buf, ByteBuf};
use mio::{self, Token, NotifyError};

use util::codec;

mod conn;
mod server;
mod run;
mod handler;
mod bench;

pub type Result<T> = result::Result<T, Box<error::Error + Send + Sync>>;

const SERVER_TOKEN: Token = Token(1);
const FIRST_CUSTOM_TOKEN: Token = Token(1024);
const INVALID_TOKEN: Token = Token(0);
const DEFAULT_BASE_TICK_MS: u64 = 100;

#[derive(Clone, Debug)]
pub struct Config {
    pub addr: String,
}

pub struct ConnData {
    msg_id: u64,
    data: ByteBuf,
}

impl ConnData {
    pub fn encode_to_buf(&self) -> ByteBuf {
        let mut buf = ByteBuf::mut_with_capacity(codec::MSG_HEADER_LEN + self.data.bytes().len());

        // Must ok here
        codec::encode_data(&mut buf, self.msg_id, self.data.bytes()).unwrap();

        buf.flip()
    }

    // Notice: I meet a very strange problem in test, rust will
    // convert conn_data.data.bytes() to io::Bytes traits, I don't
    // know why so I supply this method instead temporally.
    // I may use vector instead of ByteBuf later.
    pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
        self.data.bytes()
    }
}

pub enum TimerMsg {
    // None is just for test, we will remove this later.
    None,
}

pub enum Msg {
    // Quit event loop.
    Quit,
    // Read data from connection.
    ReadData {
        token: Token,
        data: ConnData,
    },
    // Write data to connection.
    WriteData {
        token: Token,
        data: ConnData,
    },
    // Tick is for base internal tick message.
    Tick,
    // Timer is for custom timeout message.
    Timer {
        delay: u64,
        msg: TimerMsg,
    },
    // Send data to remote peer with address.
    SendPeer {
        addr: String,
        data: ConnData,
    },
}

#[derive(Debug)]
pub struct Sender {
    sender: mio::Sender<Msg>,
}

impl Clone for Sender {
    fn clone(&self) -> Sender {
        Sender { sender: self.sender.clone() }
    }
}

const MAX_SEND_RETRY_CNT: i32 = 20;

impl Sender {
    pub fn new(sender: mio::Sender<Msg>) -> Sender {
        Sender { sender: sender }
    }

    fn send(&self, msg: Msg) -> Result<()> {
        let mut value = msg;
        for _ in 0..MAX_SEND_RETRY_CNT {
            let r = self.sender.send(value);
            if r.is_ok() {
                return Ok(());
            }

            match r.unwrap_err() {
                NotifyError::Full(m) => {
                    warn!("notify queue is full, sleep and retry");
                    thread::sleep(Duration::from_millis(100));
                    value = m;
                    continue;
                }
                e@_ => {
                    return Err(convert::From::from(e));
                }
            }
        }

        Err(convert::From::from(NotifyError::Full(value)))
    }

    pub fn kill(&self) -> Result<()> {
        try!(self.send(Msg::Quit));
        Ok(())
    }

    pub fn write_data(&self, token: Token, data: ConnData) -> Result<()> {
        try!(self.send(Msg::WriteData {
            token: token,
            data: data,
        }));

        Ok(())
    }

    pub fn timeout_ms(&self, delay: u64, m: TimerMsg) -> Result<()> {
        try!(self.send(Msg::Timer {
            delay: delay,
            msg: m,
        }));

        Ok(())
    }

    pub fn send_peer(&self, addr: String, data: ConnData) -> Result<()> {
        try!(self.send(Msg::SendPeer {
            addr: addr,
            data: data,
        }));

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use std::thread;

    use mio::{EventLoop, Handler};

    use super::*;

    struct SenderHandler;

    impl Handler for SenderHandler {
        type Timeout = ();
        type Message = Msg;

        fn notify(&mut self, event_loop: &mut EventLoop<SenderHandler>, msg: Msg) {
            match msg {
                Msg::Quit => event_loop.shutdown(),
                _ => {}
            }
        }
    }

    #[test]
    fn test_sender() {
        let mut event_loop = EventLoop::new().unwrap();
        let sender = Sender::new(event_loop.channel());
        let h = thread::spawn(move || {
            event_loop.run(&mut SenderHandler).unwrap();
        });

        for _ in 1..10000 {
            sender.timeout_ms(100, TimerMsg::None).unwrap();
        }

        sender.kill().unwrap();

        h.join().unwrap();
    }
}
<commit_msg>raftserver: Address comment.<commit_after>#![allow(dead_code)]

use std::boxed::Box;
use std::result;
use std::error;
use std::thread;
use std::convert;
use std::time::Duration;

use bytes::{Buf, ByteBuf};
use mio::{self, Token, NotifyError};

use util::codec;

mod conn;
mod server;
mod run;
mod handler;
mod bench;

pub type Result<T> = result::Result<T, Box<error::Error + Send + Sync>>;

const SERVER_TOKEN: Token = Token(1);
const FIRST_CUSTOM_TOKEN: Token = Token(1024);
const INVALID_TOKEN: Token = Token(0);
const DEFAULT_BASE_TICK_MS: u64 = 100;

#[derive(Clone, Debug)]
pub struct Config {
    pub addr: String,
}

pub struct ConnData {
    msg_id: u64,
    data: ByteBuf,
}

impl ConnData {
    pub fn encode_to_buf(&self) -> ByteBuf {
        let mut buf = ByteBuf::mut_with_capacity(codec::MSG_HEADER_LEN + self.data.bytes().len());

        // Must ok here
        codec::encode_data(&mut buf, self.msg_id, self.data.bytes()).unwrap();

        buf.flip()
    }

    // Notice: I meet a very strange problem in test, rust will
    // convert conn_data.data.bytes() to io::Bytes traits, I don't
    // know why so I supply this method instead temporally.
    // I may use vector instead of ByteBuf later.
    pub fn as_bytes(&self) -> &[u8] {
        self.data.bytes()
    }
}

pub enum TimerMsg {
    // None is just for test, we will remove this later.
    None,
}

pub enum Msg {
    // Quit event loop.
    Quit,
    // Read data from connection.
    ReadData {
        token: Token,
        data: ConnData,
    },
    // Write data to connection.
    WriteData {
        token: Token,
        data: ConnData,
    },
    // Tick is for base internal tick message.
    Tick,
    // Timer is for custom timeout message.
    Timer {
        delay: u64,
        msg: TimerMsg,
    },
    // Send data to remote peer with address.
    SendPeer {
        addr: String,
        data: ConnData,
    },
}

#[derive(Debug)]
pub struct Sender {
    sender: mio::Sender<Msg>,
}

impl Clone for Sender {
    fn clone(&self) -> Sender {
        Sender { sender: self.sender.clone() }
    }
}

const MAX_SEND_RETRY_CNT: i32 = 20;

impl Sender {
    pub fn new(sender: mio::Sender<Msg>) -> Sender {
        Sender { sender: sender }
    }

    fn send(&self, msg: Msg) -> Result<()> {
        let mut value = msg;
        for _ in 0..MAX_SEND_RETRY_CNT {
            let r = self.sender.send(value);
            if r.is_ok() {
                return Ok(());
            }

            match r.unwrap_err() {
                NotifyError::Full(m) => {
                    warn!("notify queue is full, sleep and retry");
                    thread::sleep(Duration::from_millis(100));
                    value = m;
                    continue;
                }
                e@_ => {
                    return Err(convert::From::from(e));
                }
            }
        }

        Err(convert::From::from(NotifyError::Full(value)))
    }

    pub fn kill(&self) -> Result<()> {
        try!(self.send(Msg::Quit));
        Ok(())
    }

    pub fn write_data(&self, token: Token, data: ConnData) -> Result<()> {
        try!(self.send(Msg::WriteData {
            token: token,
            data: data,
        }));

        Ok(())
    }

    pub fn timeout_ms(&self, delay: u64, m: TimerMsg) -> Result<()> {
        try!(self.send(Msg::Timer {
            delay: delay,
            msg: m,
        }));

        Ok(())
    }

    pub fn send_peer(&self, addr: String, data: ConnData) -> Result<()> {
        try!(self.send(Msg::SendPeer {
            addr: addr,
            data: data,
        }));

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use std::thread;

    use mio::{EventLoop, Handler};

    use super::*;

    struct SenderHandler;

    impl Handler for SenderHandler {
        type Timeout = ();
        type Message = Msg;

        fn notify(&mut self, event_loop: &mut EventLoop<SenderHandler>, msg: Msg) {
            match msg {
                Msg::Quit => event_loop.shutdown(),
                _ => {}
            }
        }
    }

    #[test]
    fn test_sender() {
        let mut event_loop = EventLoop::new().unwrap();
        let sender = Sender::new(event_loop.channel());
        let h = thread::spawn(move || {
            event_loop.run(&mut SenderHandler).unwrap();
        });

        for _ in 1..10000 {
            sender.timeout_ms(100, TimerMsg::None).unwrap();
        }

        sender.kill().unwrap();

        h.join().unwrap();
    }
}
<|endoftext|>


<commit_before>use gfx::{self, CommandBuffer, Device, Encoder, Factory, PipelineState, Resources};
use gfx::handle::{DepthStencilView, RenderTargetView};
use gfx::traits::FactoryExt;
use gfx_device_gl;
use gfx_window_glutin;
use glutin::{ContextError, Window};
use std::error::{self, Error};
use std::fmt;

use math::FMatrix4;
use super::mesh::MeshBuffer;
use super::pipeline::{self, Data, Meta, Transform, Vertex};

type ColorFormat = gfx::format::Rgba8;
type DepthFormat = gfx::format::DepthStencil;

const CLEAR_COLOR: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

pub trait SwapBuffers {
    fn swap_buffers(&mut self) -> Result<(), RenderError>;
}

impl SwapBuffers for Window {
    fn swap_buffers(&mut self) -> Result<(), RenderError> {
        Window::swap_buffers(self).map_err(|error| {
            match error {
                ContextError::ContextLost => RenderError::ContextLost,
                _ => RenderError::Unknown,
            }
        })
    }
}

pub struct Context<W, R, F, B, D>
    where W: SwapBuffers,
          R: Resources,
          F: Factory<R>,
          B: CommandBuffer<R>,
          D: Device<Resources = R, CommandBuffer = B>
{
    pub window: W,
    factory: F,
    device: D,
    encoder: Encoder<R, B>,
    state: PipelineState<R, Meta>,
    data: Data<R>,
}

impl Context<Window,
             gfx_device_gl::Resources,
             gfx_device_gl::Factory,
             gfx_device_gl::CommandBuffer,
             gfx_device_gl::Device> {
    pub fn from_glutin_window(window: Window) -> Self {
        let (device, mut factory, color, depth) = gfx_window_glutin::init_existing(&window);
        let encoder = factory.create_command_buffer().into();
        Context::new(window, factory, device, encoder, color, depth)
    }
}

impl<W, R, F, B, D> Context<W, R, F, B, D>
    where W: SwapBuffers,
          R: Resources,
          F: Factory<R>,
          B: CommandBuffer<R>,
          D: Device<Resources = R, CommandBuffer = B>
{
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn new(window: W,
           mut factory: F,
           device: D,
           encoder: Encoder<R, B>,
           color: RenderTargetView<R, ColorFormat>,
           depth: DepthStencilView<R, DepthFormat>)
           -> Self {
        let state = factory.create_pipeline_simple(include_bytes!("../shader/cube.v.glsl"),
                                                   include_bytes!("../shader/cube.f.glsl"),
                                                   pipeline::new())
            .unwrap();
        let data = Data {
            // Using an empty slice here causes an error.
            buffer: factory.create_vertex_buffer(&[Vertex::default()]),
            transform: factory.create_constant_buffer(1),
            camera: [[0.0; 4]; 4],
            model: [[0.0; 4]; 4],
            color: color,
            depth: depth,
        };
        Context {
            window: window,
            factory: factory,
            device: device,
            encoder: encoder,
            state: state,
            data: data,
        }
    }

    pub fn set_transform(&mut self,
                         camera: &FMatrix4,
                         model: &FMatrix4)
                         -> Result<(), RenderError> {
        let transform = Transform::new(camera, model);
        self.data.camera = transform.camera;
        self.data.model = transform.model;
        self.encoder.update_buffer(&self.data.transform, &[transform], 0).map_err(|_| {
            // TODO: Coerce and expose the `UpdateError`.
            RenderError::Unknown
        })
    }

    pub fn draw_mesh_buffer(&mut self, buffer: &MeshBuffer) {
        let (buffer, slice) = self.factory
            .create_vertex_buffer_with_slice(buffer.vertices(), buffer.indices());
        self.data.buffer = buffer;
        self.encoder.draw(&slice, &self.state, &self.data);
    }

    pub fn clear(&mut self) {
        self.encoder.clear(&self.data.color, CLEAR_COLOR);
        self.encoder.clear_depth(&self.data.depth, 1.0);
    }

    pub fn flush(&mut self) -> Result<(), RenderError> {
        self.encoder.flush(&mut self.device);
        self.window.swap_buffers().and_then(|_| {
            self.device.cleanup();
            Ok(())
        })
    }
}

#[derive(Debug)]
pub enum RenderError {
    ContextLost,
    Unknown,
}

impl fmt::Display for RenderError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for RenderError {
    fn description(&self) -> &str {
        match *self {
            RenderError::ContextLost => "rendering context lost",
            _ => "unknown rendering error",
        }
    }
}
<commit_msg>Remove unneeded type definitions.<commit_after>use gfx::{self, CommandBuffer, Device, Encoder, Factory, PipelineState, Resources};
use gfx::format::{DepthStencil, Rgba8};
use gfx::handle::{DepthStencilView, RenderTargetView};
use gfx::traits::FactoryExt;
use gfx_device_gl;
use gfx_window_glutin;
use glutin::{ContextError, Window};
use std::error::{self, Error};
use std::fmt;

use math::FMatrix4;
use super::mesh::MeshBuffer;
use super::pipeline::{self, Data, Meta, Transform, Vertex};

const CLEAR_COLOR: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

pub trait SwapBuffers {
    fn swap_buffers(&mut self) -> Result<(), RenderError>;
}

impl SwapBuffers for Window {
    fn swap_buffers(&mut self) -> Result<(), RenderError> {
        Window::swap_buffers(self).map_err(|error| {
            match error {
                ContextError::ContextLost => RenderError::ContextLost,
                _ => RenderError::Unknown,
            }
        })
    }
}

pub struct Context<W, R, F, B, D>
    where W: SwapBuffers,
          R: Resources,
          F: Factory<R>,
          B: CommandBuffer<R>,
          D: Device<Resources = R, CommandBuffer = B>
{
    pub window: W,
    factory: F,
    device: D,
    encoder: Encoder<R, B>,
    state: PipelineState<R, Meta>,
    data: Data<R>,
}

impl Context<Window,
             gfx_device_gl::Resources,
             gfx_device_gl::Factory,
             gfx_device_gl::CommandBuffer,
             gfx_device_gl::Device> {
    pub fn from_glutin_window(window: Window) -> Self {
        let (device, mut factory, color, depth) = gfx_window_glutin::init_existing(&window);
        let encoder = factory.create_command_buffer().into();
        Context::new(window, factory, device, encoder, color, depth)
    }
}

impl<W, R, F, B, D> Context<W, R, F, B, D>
    where W: SwapBuffers,
          R: Resources,
          F: Factory<R>,
          B: CommandBuffer<R>,
          D: Device<Resources = R, CommandBuffer = B>
{
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn new(window: W,
           mut factory: F,
           device: D,
           encoder: Encoder<R, B>,
           color: RenderTargetView<R, Rgba8>,
           depth: DepthStencilView<R, DepthStencil>)
           -> Self {
        let state = factory.create_pipeline_simple(include_bytes!("../shader/cube.v.glsl"),
                                                   include_bytes!("../shader/cube.f.glsl"),
                                                   pipeline::new())
            .unwrap();
        let data = Data {
            // Using an empty slice here causes an error.
            buffer: factory.create_vertex_buffer(&[Vertex::default()]),
            transform: factory.create_constant_buffer(1),
            camera: [[0.0; 4]; 4],
            model: [[0.0; 4]; 4],
            color: color,
            depth: depth,
        };
        Context {
            window: window,
            factory: factory,
            device: device,
            encoder: encoder,
            state: state,
            data: data,
        }
    }

    pub fn set_transform(&mut self,
                         camera: &FMatrix4,
                         model: &FMatrix4)
                         -> Result<(), RenderError> {
        let transform = Transform::new(camera, model);
        self.data.camera = transform.camera;
        self.data.model = transform.model;
        self.encoder.update_buffer(&self.data.transform, &[transform], 0).map_err(|_| {
            // TODO: Coerce and expose the `UpdateError`.
            RenderError::Unknown
        })
    }

    pub fn draw_mesh_buffer(&mut self, buffer: &MeshBuffer) {
        let (buffer, slice) = self.factory
            .create_vertex_buffer_with_slice(buffer.vertices(), buffer.indices());
        self.data.buffer = buffer;
        self.encoder.draw(&slice, &self.state, &self.data);
    }

    pub fn clear(&mut self) {
        self.encoder.clear(&self.data.color, CLEAR_COLOR);
        self.encoder.clear_depth(&self.data.depth, 1.0);
    }

    pub fn flush(&mut self) -> Result<(), RenderError> {
        self.encoder.flush(&mut self.device);
        self.window.swap_buffers().and_then(|_| {
            self.device.cleanup();
            Ok(())
        })
    }
}

#[derive(Debug)]
pub enum RenderError {
    ContextLost,
    Unknown,
}

impl fmt::Display for RenderError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for RenderError {
    fn description(&self) -> &str {
        match *self {
            RenderError::ContextLost => "rendering context lost",
            _ => "unknown rendering error",
        }
    }
}
<|endoftext|>


<commit_before>use style::{StyledNode};
use glium::Display;

use resource::ResourceManager;
use layout::LayoutBuffer;
use markup;
use RenderBackbend;
use Viewport;
use style;

use super::RenderData;
use super::TextureRule;

pub struct View {
    dirty_flags: bool,
    layout_data: LayoutBuffer,
    render_data: Box<[RenderData]>,
    lookup_indices: Box<[usize]>,
}

impl View {

    pub fn new<R>(
        display: &Display,
        resource_manager: &R,
        view: &markup::View,
        stylesheet: &style::Stylesheet)
        -> View
        where R: ResourceManager
    {
        let stylenode = style::build_style_tree(view, stylesheet);
        let layout_buffer = LayoutBuffer::new(&stylenode);
        let (render_buffer, lookup_table) = create_render_buffer_and_lookup_table(
            display,
            resource_manager,
            &stylenode
        );
        View {
            dirty_flags: true,
            layout_data: layout_buffer,
            render_data: render_buffer,
            lookup_indices: lookup_table,
        }
    }

    pub fn update(&mut self, display: &Display, vp: Viewport) {
        if self.dirty_flags {
            self.layout_data.compute_layout(vp.width, vp.height);
            self.update_buffers(display);
            self.dirty_flags = false;
        }
    }

    pub fn render<R, B>(
        &self,
        backend: &B,
        resource_manager: &R,
        frame: &mut <B as RenderBackbend>::Frame)
        where B: RenderBackbend,
              R: ResourceManager
    {
        for data in self.render_data.iter() {
            backend.render_element(resource_manager, frame, data);
        }
    }

    fn update_buffers(&mut self, display: &Display) {
        let ref layout_data = self.layout_data;
        for (data, &i) in self.render_data.iter_mut().zip(self.lookup_indices.iter()) {
            // This part is always safe because the initialization step
            // ensure that:
            //       self.layout_data.len() >= self.render_data
            let boxi = unsafe { layout_data.get_unchecked(i) };
            data.update_coords(display, &boxi);
        }
    }

}

// ======================================== //
//                  HELPERS                 //
// ======================================== //

fn create_render_buffer_and_lookup_table<R>(
    display: &Display,
    resource_manager: &R,
    style_tree: &StyledNode) -> (Box<[RenderData]>, Box<[usize]>)
    where R: ResourceManager
{
    // Create buffer with the magic number.
    // TODO: Stop magic, use real life example.
    let mut buffer = Vec::with_capacity(10);
    let mut lookup_table = Vec::with_capacity(10);

    fill_buffer(
        display,
        resource_manager,
        &mut buffer,
        &mut lookup_table,
        &mut 0,
        style_tree
    );

    (buffer.into_boxed_slice(), lookup_table.into_boxed_slice())
}

fn fill_buffer<R>(
    display: &Display,
    resource_manager: &R,
    buffer: &mut Vec<RenderData>,
    lookup_table: &mut Vec<usize>,
    layout_box_ref: &mut usize,
    style_tree: &StyledNode)
    where R: ResourceManager
{
    if let Some(img) = style_tree.get_background_image() {

        let rule = style_tree.get_background_rule().unwrap_or(TextureRule::Fit);

        buffer.push(
            RenderData::new(
                display,
                resource_manager,
                img,
                rule
            )
        );

        lookup_table.push(
            *layout_box_ref
        );

    }
    *layout_box_ref += 1;

    for kid in &style_tree.kids {
        fill_buffer(display, resource_manager, buffer, lookup_table,
            layout_box_ref, kid);
    }
}

// ======================================== //
//                   TESTS                  //
// ======================================== //

#[cfg(test)]
mod test {

    use std::io::BufReader;
    use std::path::PathBuf;
    use glutin::WindowBuilder;
    use glium::DisplayBuild;
    use markup::{self, Node};
    use style::{self, StyledNode, Stylesheet};
    use deps::{Constructor, StyleDefinitions};
    use super::create_render_buffer_and_lookup_table;
    use report;
    use resource::{self, ResourceManager};

    fn stylesheet<R: ResourceManager>(st: &str, r: &mut R) -> Stylesheet {
        let reader = BufReader::new(st.as_bytes());
        let mut defs = StyleDefinitions::new();
        defs.insert("toto".to_string(),
            Constructor::Image(PathBuf::new(), None, None, None, None));
        style::parse(report::StdOutErrorReporter, reader, &defs, r)
    }

    fn markup_tree(mk: &str) -> markup::Node {
        let reader = BufReader::new(mk.as_bytes());
        let lib = markup::parse(report::StdOutErrorReporter, reader);
        let (_, root) = lib.views.into_iter().next().unwrap();
        root
    }

    #[test]
    fn lookup_table_should_contain_correct_indices() {

        let mut fake_resource_manager = resource::create_stateless();
        let stylesheet = stylesheet(
            ".btn { background-image: $toto; }",
            &mut fake_resource_manager);
        let root = markup_tree(
            "<view>\
                <button class=\"btn\"></button>\
                <button class=\"\"></button>\
                <button class=\"btn\"></button>\
            </view>
            ");
        let style_tree = style::build_style_tree(&root, &stylesheet);
        let fake_display = WindowBuilder::new()
            .with_dimensions(1, 1).with_visibility(false).build_glium().unwrap();
        let (_, lookup_table) = create_render_buffer_and_lookup_table(
            &fake_display,
            &fake_resource_manager,
            &style_tree
        );

        assert_eq!(lookup_table[0], 1);
        assert_eq!(lookup_table[1], 3);
    }
}
<commit_msg>Temporary fix for travis test.<commit_after>use style::{StyledNode};
use glium::Display;

use resource::ResourceManager;
use layout::LayoutBuffer;
use markup;
use RenderBackbend;
use Viewport;
use style;

use super::RenderData;
use super::TextureRule;

pub struct View {
    dirty_flags: bool,
    layout_data: LayoutBuffer,
    render_data: Box<[RenderData]>,
    lookup_indices: Box<[usize]>,
}

impl View {

    pub fn new<R>(
        display: &Display,
        resource_manager: &R,
        view: &markup::View,
        stylesheet: &style::Stylesheet)
        -> View
        where R: ResourceManager
    {
        let stylenode = style::build_style_tree(view, stylesheet);
        let layout_buffer = LayoutBuffer::new(&stylenode);
        let (render_buffer, lookup_table) = create_render_buffer_and_lookup_table(
            display,
            resource_manager,
            &stylenode
        );
        View {
            dirty_flags: true,
            layout_data: layout_buffer,
            render_data: render_buffer,
            lookup_indices: lookup_table,
        }
    }

    pub fn update(&mut self, display: &Display, vp: Viewport) {
        if self.dirty_flags {
            self.layout_data.compute_layout(vp.width, vp.height);
            self.update_buffers(display);
            self.dirty_flags = false;
        }
    }

    pub fn render<R, B>(
        &self,
        backend: &B,
        resource_manager: &R,
        frame: &mut <B as RenderBackbend>::Frame)
        where B: RenderBackbend,
              R: ResourceManager
    {
        for data in self.render_data.iter() {
            backend.render_element(resource_manager, frame, data);
        }
    }

    fn update_buffers(&mut self, display: &Display) {
        let ref layout_data = self.layout_data;
        for (data, &i) in self.render_data.iter_mut().zip(self.lookup_indices.iter()) {
            // This part is always safe because the initialization step
            // ensure that:
            //       self.layout_data.len() >= self.render_data
            let boxi = unsafe { layout_data.get_unchecked(i) };
            data.update_coords(display, &boxi);
        }
    }

}

// ======================================== //
//                  HELPERS                 //
// ======================================== //

fn create_render_buffer_and_lookup_table<R>(
    display: &Display,
    resource_manager: &R,
    style_tree: &StyledNode) -> (Box<[RenderData]>, Box<[usize]>)
    where R: ResourceManager
{
    // Create buffer with the magic number.
    // TODO: Stop magic, use real life example.
    let mut buffer = Vec::with_capacity(10);
    let mut lookup_table = Vec::with_capacity(10);

    fill_buffer(
        display,
        resource_manager,
        &mut buffer,
        &mut lookup_table,
        &mut 0,
        style_tree
    );

    (buffer.into_boxed_slice(), lookup_table.into_boxed_slice())
}

fn fill_buffer<R>(
    display: &Display,
    resource_manager: &R,
    buffer: &mut Vec<RenderData>,
    lookup_table: &mut Vec<usize>,
    layout_box_ref: &mut usize,
    style_tree: &StyledNode)
    where R: ResourceManager
{
    if let Some(img) = style_tree.get_background_image() {

        let rule = style_tree.get_background_rule().unwrap_or(TextureRule::Fit);

        buffer.push(
            RenderData::new(
                display,
                resource_manager,
                img,
                rule
            )
        );

        lookup_table.push(
            *layout_box_ref
        );

    }
    *layout_box_ref += 1;

    for kid in &style_tree.kids {
        fill_buffer(display, resource_manager, buffer, lookup_table,
            layout_box_ref, kid);
    }
}

// ======================================== //
//                   TESTS                  //
// ======================================== //

#[cfg(test)]
mod test {

    use std::io::BufReader;
    use std::path::PathBuf;
    use glutin::WindowBuilder;
    use glium::DisplayBuild;
    use markup::{self, Node};
    use style::{self, Stylesheet};
    use deps::{Constructor, StyleDefinitions};
    use super::create_render_buffer_and_lookup_table;
    use report;
    use resource::{self, ResourceManager};

    fn stylesheet<R: ResourceManager>(st: &str, r: &mut R) -> Stylesheet {
        let reader = BufReader::new(st.as_bytes());
        let mut defs = StyleDefinitions::new();
        defs.insert("toto".to_string(),
            Constructor::Image(PathBuf::new(), None, None, None, None));
        style::parse(report::StdOutErrorReporter, reader, &defs, r)
    }

    fn markup_tree(mk: &str) -> markup::Node {
        let reader = BufReader::new(mk.as_bytes());
        let lib = markup::parse(report::StdOutErrorReporter, reader);
        let (_, root) = lib.views.into_iter().next().unwrap();
        root
    }

    #[test]
    fn lookup_table_should_contain_correct_indices() {

        let mut fake_resource_manager = resource::create_stateless();
        let stylesheet = stylesheet(
            ".btn { background-image: $toto; }",
            &mut fake_resource_manager);
        let root = markup_tree(
            "<view>\
                <button class=\"btn\"></button>\
                <button class=\"\"></button>\
                <button class=\"btn\"></button>\
            </view>
            ");
        let style_tree = style::build_style_tree(&root, &stylesheet);

        // FIXME(This match is here to have the travis test pass)
        if let Some(fake_display) = WindowBuilder::new()
            .with_dimensions(1, 1).with_visibility(false).build_glium().ok()
        {

            let (_, lookup_table) = create_render_buffer_and_lookup_table(
                &fake_display,
                &fake_resource_manager,
                &style_tree
            );

            assert_eq!(lookup_table[0], 1);
            assert_eq!(lookup_table[1], 3);
        }
    }
}
<|endoftext|>


<commit_before>extern crate proc_macro2;
extern crate syn;

use std::str::FromStr;

use proc_macro2::TokenStream;
use syn::{Expr, ExprRange};

#[test]
fn test_expr_parse() {
    let code = "..100u32";
    let tt = TokenStream::from_str(code).unwrap();
    let ast1: Expr = syn::parse2(tt.clone()).unwrap();
    let ast2: ExprRange = syn::parse2(tt).unwrap();
    assert_eq!(ast1, Expr::Range(ast2));
}
<commit_msg>Avoid 'ast' since syntax tree is concrete<commit_after>extern crate proc_macro2;
extern crate syn;

use std::str::FromStr;

use proc_macro2::TokenStream;
use syn::{Expr, ExprRange};

#[test]
fn test_expr_parse() {
    let code = "..100u32";
    let tt = TokenStream::from_str(code).unwrap();
    let expr: Expr = syn::parse2(tt.clone()).unwrap();
    let expr_range: ExprRange = syn::parse2(tt).unwrap();
    assert_eq!(expr, Expr::Range(expr_range));
}
<|endoftext|>