<commit_before>use super::BLOCKS_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use ssz::Decodable;
use std::sync::Arc;
use types::{readers::BeaconBlockReader, BeaconBlock, Hash256};

#[derive(Clone, Debug, PartialEq)]
pub enum BeaconBlockAtSlotError {
    UnknownBeaconBlock,
    InvalidBeaconBlock,
    DBError(String),
}

pub struct BeaconBlockStore<T>
where
    T: ClientDB,
{
    db: Arc<T>,
}

// Implements `put`, `get`, `exists` and `delete` for the store.
impl_crud_for_store!(BeaconBlockStore, DB_COLUMN);

impl<T: ClientDB> BeaconBlockStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self { db }
    }

    /// Retuns an object implementing `BeaconBlockReader`, or `None` (if hash not known).
    ///
    /// Note: Presently, this function fully deserializes a `BeaconBlock` and returns that. In the
    /// future, it would be ideal to return an object capable of reading directly from serialized
    /// SSZ bytes.
    pub fn get_reader(&self, hash: &Hash256) -> Result<Option<impl BeaconBlockReader>, DBError> {
        match self.get(&hash)? {
            None => Ok(None),
            Some(ssz) => {
                let (block, _) = BeaconBlock::ssz_decode(&ssz, 0).map_err(|_| DBError {
                    message: "Bad BeaconBlock SSZ.".to_string(),
                })?;
                Ok(Some(block))
            }
        }
    }

    /// Retrieve the block at a slot given a "head_hash" and a slot.
    ///
    /// A "head_hash" must be a block hash with a slot number greater than or equal to the desired
    /// slot.
    ///
    /// This function will read each block down the chain until it finds a block with the given
    /// slot number. If the slot is skipped, the function will return None.
    ///
    /// If a block is found, a tuple of (block_hash, serialized_block) is returned.
    ///
    /// Note: this function uses a loop instead of recursion as the compiler is over-strict when it
    /// comes to recursion and the `impl Trait` pattern. See:
    /// https://stackoverflow.com/questions/54032940/using-impl-trait-in-a-recursive-function
    pub fn block_at_slot(
        &self,
        head_hash: &Hash256,
        slot: u64,
    ) -> Result<Option<(Hash256, impl BeaconBlockReader)>, BeaconBlockAtSlotError> {
        let mut current_hash = *head_hash;

        loop {
            if let Some(block_reader) = self.get_reader(&current_hash)? {
                if block_reader.slot() == slot {
                    break Ok(Some((current_hash, block_reader)));
                } else if block_reader.slot() < slot {
                    break Ok(None);
                } else {
                    current_hash = block_reader.parent_root();
                }
            } else {
                break Err(BeaconBlockAtSlotError::UnknownBeaconBlock);
            }
        }
    }
}

impl From<DBError> for BeaconBlockAtSlotError {
    fn from(e: DBError) -> Self {
        BeaconBlockAtSlotError::DBError(e.message)
    }
}

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

    use std::sync::Arc;
    use std::thread;

    use ssz::ssz_encode;
    use types::test_utils::{SeedableRng, TestRandom, XorShiftRng};
    use types::BeaconBlock;
    use types::Hash256;

    test_crud_for_store!(BeaconBlockStore, DB_COLUMN);

    #[test]
    fn head_hash_slot_too_low() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));
        let mut rng = XorShiftRng::from_seed([42; 16]);

        let mut block = BeaconBlock::random_for_test(&mut rng);
        block.slot = 10;

        let block_root = block.canonical_root();
        bs.put(&block_root, &ssz_encode(&block)).unwrap();

        let result = bs.block_at_slot(&block_root, 11).unwrap();
        assert_eq!(result, None);
    }

    #[test]
    fn test_invalid_block_at_slot() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "definitly not a valid block".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes());

        db.put(DB_COLUMN, hash, ssz).unwrap();
        assert_eq!(
            store.block_at_slot(hash, 42),
            Err(BeaconBlockAtSlotError::DBError(
                "Bad BeaconBlock SSZ.".into()
            ))
        );
    }

    #[test]
    fn test_unknown_block_at_slot() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "some bytes".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes());
        let other_hash = &Hash256::from("another hash".as_bytes());

        db.put(DB_COLUMN, hash, ssz).unwrap();
        assert_eq!(
            store.block_at_slot(other_hash, 42),
            Err(BeaconBlockAtSlotError::UnknownBeaconBlock)
        );
    }

    #[test]
    fn test_block_store_on_memory_db() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));

        let thread_count = 10;
        let write_count = 10;

        // We're expecting the product of these numbers to fit in one byte.
        assert!(thread_count * write_count <= 255);

        let mut handles = vec![];
        for t in 0..thread_count {
            let wc = write_count;
            let bs = bs.clone();
            let handle = thread::spawn(move || {
                for w in 0..wc {
                    let key = (t * w) as u8;
                    let val = 42;
                    bs.put(&[key][..].into(), &vec![val]).unwrap();
                }
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.join().unwrap();
        }

        for t in 0..thread_count {
            for w in 0..write_count {
                let key = (t * w) as u8;
                assert!(bs.exists(&[key][..].into()).unwrap());
                let val = bs.get(&[key][..].into()).unwrap().unwrap();
                assert_eq!(vec![42], val);
            }
        }
    }

    #[test]
    fn test_block_at_slot() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));
        let mut rng = XorShiftRng::from_seed([42; 16]);

        // Specify test block parameters.
        let hashes = [
            Hash256::from(&[0; 32][..]),
            Hash256::from(&[1; 32][..]),
            Hash256::from(&[2; 32][..]),
            Hash256::from(&[3; 32][..]),
            Hash256::from(&[4; 32][..]),
        ];
        let parent_hashes = [
            Hash256::from(&[255; 32][..]), // Genesis block.
            Hash256::from(&[0; 32][..]),
            Hash256::from(&[1; 32][..]),
            Hash256::from(&[2; 32][..]),
            Hash256::from(&[3; 32][..]),
        ];
        let slots = [0, 1, 3, 4, 5];

        // Generate a vec of random blocks and store them in the DB.
        let block_count = 5;
        let mut blocks: Vec<BeaconBlock> = Vec::with_capacity(5);
        for i in 0..block_count {
            let mut block = BeaconBlock::random_for_test(&mut rng);

            block.parent_root = parent_hashes[i];
            block.slot = slots[i];

            let ssz = ssz_encode(&block);
            db.put(DB_COLUMN, &hashes[i], &ssz).unwrap();

            blocks.push(block);
        }

        // Test that certain slots can be reached from certain hashes.
        let test_cases = vec![(4, 4), (4, 3), (4, 2), (4, 1), (4, 0)];
        for (hashes_index, slot_index) in test_cases {
            let (matched_block_hash, reader) = bs
                .block_at_slot(&hashes[hashes_index], slots[slot_index])
                .unwrap()
                .unwrap();
            assert_eq!(matched_block_hash, hashes[slot_index]);
            assert_eq!(reader.slot(), slots[slot_index]);
        }

        let ssz = bs.block_at_slot(&hashes[4], 2).unwrap();
        assert_eq!(ssz, None);

        let ssz = bs.block_at_slot(&hashes[4], 6).unwrap();
        assert_eq!(ssz, None);

        let ssz = bs.block_at_slot(&Hash256::from("unknown".as_bytes()), 2);
        assert_eq!(ssz, Err(BeaconBlockAtSlotError::UnknownBeaconBlock));
    }
}
<commit_msg>Add Hash to beacon_block_store errors<commit_after>use super::BLOCKS_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use ssz::Decodable;
use std::sync::Arc;
use types::{readers::BeaconBlockReader, BeaconBlock, Hash256};

#[derive(Clone, Debug, PartialEq)]
pub enum BeaconBlockAtSlotError {
    UnknownBeaconBlock(Hash256),
    InvalidBeaconBlock(Hash256),
    DBError(String),
}

pub struct BeaconBlockStore<T>
where
    T: ClientDB,
{
    db: Arc<T>,
}

// Implements `put`, `get`, `exists` and `delete` for the store.
impl_crud_for_store!(BeaconBlockStore, DB_COLUMN);

impl<T: ClientDB> BeaconBlockStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self { db }
    }

    /// Retuns an object implementing `BeaconBlockReader`, or `None` (if hash not known).
    ///
    /// Note: Presently, this function fully deserializes a `BeaconBlock` and returns that. In the
    /// future, it would be ideal to return an object capable of reading directly from serialized
    /// SSZ bytes.
    pub fn get_reader(&self, hash: &Hash256) -> Result<Option<impl BeaconBlockReader>, DBError> {
        match self.get(&hash)? {
            None => Ok(None),
            Some(ssz) => {
                let (block, _) = BeaconBlock::ssz_decode(&ssz, 0).map_err(|_| DBError {
                    message: "Bad BeaconBlock SSZ.".to_string(),
                })?;
                Ok(Some(block))
            }
        }
    }

    /// Retrieve the block at a slot given a "head_hash" and a slot.
    ///
    /// A "head_hash" must be a block hash with a slot number greater than or equal to the desired
    /// slot.
    ///
    /// This function will read each block down the chain until it finds a block with the given
    /// slot number. If the slot is skipped, the function will return None.
    ///
    /// If a block is found, a tuple of (block_hash, serialized_block) is returned.
    ///
    /// Note: this function uses a loop instead of recursion as the compiler is over-strict when it
    /// comes to recursion and the `impl Trait` pattern. See:
    /// https://stackoverflow.com/questions/54032940/using-impl-trait-in-a-recursive-function
    pub fn block_at_slot(
        &self,
        head_hash: &Hash256,
        slot: u64,
    ) -> Result<Option<(Hash256, impl BeaconBlockReader)>, BeaconBlockAtSlotError> {
        let mut current_hash = *head_hash;

        loop {
            if let Some(block_reader) = self.get_reader(&current_hash)? {
                if block_reader.slot() == slot {
                    break Ok(Some((current_hash, block_reader)));
                } else if block_reader.slot() < slot {
                    break Ok(None);
                } else {
                    current_hash = block_reader.parent_root();
                }
            } else {
                break Err(BeaconBlockAtSlotError::UnknownBeaconBlock(current_hash));
            }
        }
    }
}

impl From<DBError> for BeaconBlockAtSlotError {
    fn from(e: DBError) -> Self {
        BeaconBlockAtSlotError::DBError(e.message)
    }
}

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

    use std::sync::Arc;
    use std::thread;

    use ssz::ssz_encode;
    use types::test_utils::{SeedableRng, TestRandom, XorShiftRng};
    use types::BeaconBlock;
    use types::Hash256;

    test_crud_for_store!(BeaconBlockStore, DB_COLUMN);

    #[test]
    fn head_hash_slot_too_low() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));
        let mut rng = XorShiftRng::from_seed([42; 16]);

        let mut block = BeaconBlock::random_for_test(&mut rng);
        block.slot = 10;

        let block_root = block.canonical_root();
        bs.put(&block_root, &ssz_encode(&block)).unwrap();

        let result = bs.block_at_slot(&block_root, 11).unwrap();
        assert_eq!(result, None);
    }

    #[test]
    fn test_invalid_block_at_slot() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "definitly not a valid block".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes());

        db.put(DB_COLUMN, hash, ssz).unwrap();
        assert_eq!(
            store.block_at_slot(hash, 42),
            Err(BeaconBlockAtSlotError::DBError(
                "Bad BeaconBlock SSZ.".into()
            ))
        );
    }

    #[test]
    fn test_unknown_block_at_slot() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "some bytes".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes());
        let other_hash = &Hash256::from("another hash".as_bytes());

        db.put(DB_COLUMN, hash, ssz).unwrap();
        assert_eq!(
            store.block_at_slot(other_hash, 42),
            Err(BeaconBlockAtSlotError::UnknownBeaconBlock(*other_hash))
        );
    }

    #[test]
    fn test_block_store_on_memory_db() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));

        let thread_count = 10;
        let write_count = 10;

        // We're expecting the product of these numbers to fit in one byte.
        assert!(thread_count * write_count <= 255);

        let mut handles = vec![];
        for t in 0..thread_count {
            let wc = write_count;
            let bs = bs.clone();
            let handle = thread::spawn(move || {
                for w in 0..wc {
                    let key = (t * w) as u8;
                    let val = 42;
                    bs.put(&[key][..].into(), &vec![val]).unwrap();
                }
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.join().unwrap();
        }

        for t in 0..thread_count {
            for w in 0..write_count {
                let key = (t * w) as u8;
                assert!(bs.exists(&[key][..].into()).unwrap());
                let val = bs.get(&[key][..].into()).unwrap().unwrap();
                assert_eq!(vec![42], val);
            }
        }
    }

    #[test]
    fn test_block_at_slot() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));
        let mut rng = XorShiftRng::from_seed([42; 16]);

        // Specify test block parameters.
        let hashes = [
            Hash256::from(&[0; 32][..]),
            Hash256::from(&[1; 32][..]),
            Hash256::from(&[2; 32][..]),
            Hash256::from(&[3; 32][..]),
            Hash256::from(&[4; 32][..]),
        ];
        let parent_hashes = [
            Hash256::from(&[255; 32][..]), // Genesis block.
            Hash256::from(&[0; 32][..]),
            Hash256::from(&[1; 32][..]),
            Hash256::from(&[2; 32][..]),
            Hash256::from(&[3; 32][..]),
        ];
        let slots = [0, 1, 3, 4, 5];

        // Generate a vec of random blocks and store them in the DB.
        let block_count = 5;
        let mut blocks: Vec<BeaconBlock> = Vec::with_capacity(5);
        for i in 0..block_count {
            let mut block = BeaconBlock::random_for_test(&mut rng);

            block.parent_root = parent_hashes[i];
            block.slot = slots[i];

            let ssz = ssz_encode(&block);
            db.put(DB_COLUMN, &hashes[i], &ssz).unwrap();

            blocks.push(block);
        }

        // Test that certain slots can be reached from certain hashes.
        let test_cases = vec![(4, 4), (4, 3), (4, 2), (4, 1), (4, 0)];
        for (hashes_index, slot_index) in test_cases {
            let (matched_block_hash, reader) = bs
                .block_at_slot(&hashes[hashes_index], slots[slot_index])
                .unwrap()
                .unwrap();
            assert_eq!(matched_block_hash, hashes[slot_index]);
            assert_eq!(reader.slot(), slots[slot_index]);
        }

        let ssz = bs.block_at_slot(&hashes[4], 2).unwrap();
        assert_eq!(ssz, None);

        let ssz = bs.block_at_slot(&hashes[4], 6).unwrap();
        assert_eq!(ssz, None);

        let bad_hash = &Hash256::from("unknown".as_bytes());
        let ssz = bs.block_at_slot(bad_hash, 2);
        assert_eq!(
            ssz,
            Err(BeaconBlockAtSlotError::UnknownBeaconBlock(*bad_hash))
        );
    }
}
<|endoftext|>


<commit_before>//! A `SpriteBatch` is a way to efficiently draw a large
//! number of copies of the same image, or part of the same image.  It's
//! useful for implementing tiled maps, spritesheets, particles, and
//! other such things.
//!
//! Essentially this uses a technique called "instancing" to queue up
//! a large amount of location/position data in a buffer, then feed it
//! to the graphics card all in one go.

use context::Context;
use graphics;
use error;
use gfx;
use gfx::Factory;
use GameResult;
use super::shader::BlendMode;

/// A `SpriteBatch` draws a number of copies of the same image, using a single draw call.
///
/// This is generally faster than drawing the same sprite with many invocations of `draw()`,
/// though it has a bit of overhead to set up the batch.  This makes it run very slowly
/// in Debug mode because it spends a lot of time on array bounds checking and
/// un-optimized math; you need to build with optimizations enabled to really get the
/// speed boost.
#[derive(Debug, Clone)]
pub struct SpriteBatch {
    image: graphics::Image,
    sprites: Vec<graphics::DrawParam>,
    blend_mode: Option<BlendMode>,
}

/// A drawable combination of a `SpriteBatch` and a specific `Image`.
/// It is not always convenient for a `SpriteBatch` to own the image
/// it is drawing, so this structure lets you override the image with
/// a borrowed one.
///
/// This is now deprecated; an `Image` is cheap to clone and
/// this was never terribly useful to begin with.
#[deprecated]
#[derive(Debug)]
pub struct BoundSpriteBatch<'a> {
    image: &'a graphics::Image,
    batch: &'a mut SpriteBatch,
}

/// An index of a particular sprite in a `SpriteBatch`.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SpriteIdx(usize);

impl SpriteBatch {
    /// Creates a new `SpriteBatch`, drawing with the given image.
    pub fn new(image: graphics::Image) -> Self {
        Self {
            image,
            sprites: vec![],
            blend_mode: None,
        }
    }

    /// Adds a new sprite to the sprite batch.
    ///
    /// Returns a handle with whictypeh to modify the sprite using `set()`
    pub fn add(&mut self, param: graphics::DrawParam) -> SpriteIdx {
        self.sprites.push(param);
        SpriteIdx(self.sprites.len() - 1)
    }

    /// Alters a sprite in the batch to use the given draw params
    pub fn set(&mut self, handle: SpriteIdx, param: graphics::DrawParam) -> GameResult<()> {
        if handle.0 < self.sprites.len() {
            self.sprites[handle.0] = param;
            Ok(())
        } else {
            Err(error::GameError::RenderError(String::from(
                "Provided index is out of bounds.",
            )))
        }
    }

    /// Immediately sends all data in the batch to the graphics card.
    ///
    /// Generally just calling `graphics::draw()` on the `SpriteBatch`
    /// will do this automaticassertally.
    fn flush(
        &self,
        ctx: &mut Context,
        image: &graphics::Image,
        draw_color: Option<graphics::Color>,
    ) -> GameResult<()> {
        // This is a little awkward but this is the right place
        // to do whatever transformations need to happen to DrawParam's.
        // We have a Context, and *everything* must pass through this
        // function to be drawn, so.
        // Though we do awkwardly have to allocate a new vector.
        assert!(draw_color.is_some());
        let new_sprites = self.sprites
            .iter()
            .map(|param| {
                // Copy old params
                let mut new_param = *param;
                let src_width = param.src.w;
                let src_height = param.src.h;
                let real_scale = graphics::Point2::new(
                    src_width * param.scale.x * image.width as f32,
                    src_height * param.scale.y * image.height as f32,
                );
                new_param.scale = real_scale;
                // If we have no color, our color is white.
                // This is fine because coloring the whole spritebatch is possible
                // with graphics::set_color(); this just inherits from that.
                new_param.color = new_param.color.or(draw_color);
                graphics::InstanceProperties::from(new_param)
            })
            .collect::<Vec<_>>();

        let gfx = &mut ctx.gfx_context;
        if gfx.data.rect_instance_properties.len() < self.sprites.len() {
            gfx.data.rect_instance_properties = gfx.factory.create_buffer(
                self.sprites.len(),
                gfx::buffer::Role::Vertex,
                gfx::memory::Usage::Dynamic,
                gfx::memory::Bind::TRANSFER_DST,
            )?;
        }
        gfx.encoder
            .update_buffer(&gfx.data.rect_instance_properties, &new_sprites[..], 0)?;
        Ok(())
    }

    /// Removes all data from the sprite batch.
    pub fn clear(&mut self) {
        self.sprites.clear();
    }

    /// Unwraps the contained `Image`
    pub fn into_inner(self) -> graphics::Image {
        self.image
    }

    /// Replaces the contained `Image`, returning the old one.
    pub fn set_image(&mut self, image: graphics::Image) -> graphics::Image {
        use std::mem;
        mem::replace(&mut self.image, image)
    }

    /// Create an object which draws the current sprite batch with a different image.
    #[deprecated]
    #[allow(deprecated)]
    pub fn with_image<'a>(&'a mut self, image: &'a graphics::Image) -> BoundSpriteBatch<'a> {
        BoundSpriteBatch {
            image,
            batch: self,
        }
    }
}

#[deprecated]
#[allow(deprecated)]
impl<'a> graphics::Drawable for BoundSpriteBatch<'a> {
    fn draw_ex(&self, ctx: &mut Context, param: graphics::DrawParam) -> GameResult<()> {
        // Awkwardly we must update values on all sprites and such.
        // Also awkwardly we have this chain of colors with differing priorities.
        let fg = Some(ctx.gfx_context.foreground_color);
        let draw_color = param.color.or(fg);
        self.batch.flush(ctx, self.image, draw_color)?;
        let gfx = &mut ctx.gfx_context;
        let sampler = gfx.samplers
            .get_or_insert(self.image.sampler_info, gfx.factory.as_mut());
        gfx.data.vbuf = gfx.quad_vertex_buffer.clone();
        gfx.data.tex = (self.image.texture.clone(), sampler);
        let mut slice = gfx.quad_slice.clone();
        slice.instances = Some((self.batch.sprites.len() as u32, 0));
        let curr_transform = gfx.get_transform();
        gfx.push_transform(param.into_matrix() * curr_transform);
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        let previous_mode: Option<BlendMode> = if let Some(mode) = self.batch.blend_mode {
            let current_mode = gfx.get_blend_mode();
            if current_mode != mode {
                gfx.set_blend_mode(mode)?;
                Some(current_mode)
            } else {
                None
            }
        } else {
            None
        };
        gfx.draw(Some(&slice))?;
        if let Some(mode) = previous_mode {
            gfx.set_blend_mode(mode)?;
        }
        gfx.pop_transform();
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        Ok(())
    }

    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.batch.blend_mode = mode;
    }

    fn get_blend_mode(&self) -> Option<BlendMode> {
        self.batch.blend_mode
    }
}

impl graphics::Drawable for SpriteBatch {
    fn draw_ex(&self, ctx: &mut Context, param: graphics::DrawParam) -> GameResult<()> {
        // Awkwardly we must update values on all sprites and such.
        // Also awkwardly we have this chain of colors with differing priorities.
        let fg = Some(ctx.gfx_context.foreground_color);
        let draw_color = param.color.or(fg);
        self.flush(ctx, &self.image, draw_color)?;
        let gfx = &mut ctx.gfx_context;
        let sampler = gfx.samplers
            .get_or_insert(self.image.sampler_info, gfx.factory.as_mut());
        gfx.data.vbuf = gfx.quad_vertex_buffer.clone();
        gfx.data.tex = (self.image.texture.clone(), sampler);
        let mut slice = gfx.quad_slice.clone();
        slice.instances = Some((self.sprites.len() as u32, 0));
        let curr_transform = gfx.get_transform();
        gfx.push_transform(param.into_matrix() * curr_transform);
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        let previous_mode: Option<BlendMode> = if let Some(mode) = self.blend_mode {
            let current_mode = gfx.get_blend_mode();
            if current_mode != mode {
                gfx.set_blend_mode(mode)?;
                Some(current_mode)
            } else {
                None
            }
        } else {
            None
        };
        gfx.draw(Some(&slice))?;
        if let Some(mode) = previous_mode {
            gfx.set_blend_mode(mode)?;
        }
        gfx.pop_transform();
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        Ok(())
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.blend_mode = mode;
    }
    fn get_blend_mode(&self) -> Option<BlendMode> {
        self.blend_mode
    }
}
<commit_msg>Fix typo in graphics::spritebatch::SpriteBatch::add() docs<commit_after>//! A `SpriteBatch` is a way to efficiently draw a large
//! number of copies of the same image, or part of the same image.  It's
//! useful for implementing tiled maps, spritesheets, particles, and
//! other such things.
//!
//! Essentially this uses a technique called "instancing" to queue up
//! a large amount of location/position data in a buffer, then feed it
//! to the graphics card all in one go.

use context::Context;
use graphics;
use error;
use gfx;
use gfx::Factory;
use GameResult;
use super::shader::BlendMode;

/// A `SpriteBatch` draws a number of copies of the same image, using a single draw call.
///
/// This is generally faster than drawing the same sprite with many invocations of `draw()`,
/// though it has a bit of overhead to set up the batch.  This makes it run very slowly
/// in Debug mode because it spends a lot of time on array bounds checking and
/// un-optimized math; you need to build with optimizations enabled to really get the
/// speed boost.
#[derive(Debug, Clone)]
pub struct SpriteBatch {
    image: graphics::Image,
    sprites: Vec<graphics::DrawParam>,
    blend_mode: Option<BlendMode>,
}

/// A drawable combination of a `SpriteBatch` and a specific `Image`.
/// It is not always convenient for a `SpriteBatch` to own the image
/// it is drawing, so this structure lets you override the image with
/// a borrowed one.
///
/// This is now deprecated; an `Image` is cheap to clone and
/// this was never terribly useful to begin with.
#[deprecated]
#[derive(Debug)]
pub struct BoundSpriteBatch<'a> {
    image: &'a graphics::Image,
    batch: &'a mut SpriteBatch,
}

/// An index of a particular sprite in a `SpriteBatch`.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SpriteIdx(usize);

impl SpriteBatch {
    /// Creates a new `SpriteBatch`, drawing with the given image.
    pub fn new(image: graphics::Image) -> Self {
        Self {
            image,
            sprites: vec![],
            blend_mode: None,
        }
    }

    /// Adds a new sprite to the sprite batch.
    ///
    /// Returns a handle with which type to modify the sprite using `set()`
    pub fn add(&mut self, param: graphics::DrawParam) -> SpriteIdx {
        self.sprites.push(param);
        SpriteIdx(self.sprites.len() - 1)
    }

    /// Alters a sprite in the batch to use the given draw params
    pub fn set(&mut self, handle: SpriteIdx, param: graphics::DrawParam) -> GameResult<()> {
        if handle.0 < self.sprites.len() {
            self.sprites[handle.0] = param;
            Ok(())
        } else {
            Err(error::GameError::RenderError(String::from(
                "Provided index is out of bounds.",
            )))
        }
    }

    /// Immediately sends all data in the batch to the graphics card.
    ///
    /// Generally just calling `graphics::draw()` on the `SpriteBatch`
    /// will do this automaticassertally.
    fn flush(
        &self,
        ctx: &mut Context,
        image: &graphics::Image,
        draw_color: Option<graphics::Color>,
    ) -> GameResult<()> {
        // This is a little awkward but this is the right place
        // to do whatever transformations need to happen to DrawParam's.
        // We have a Context, and *everything* must pass through this
        // function to be drawn, so.
        // Though we do awkwardly have to allocate a new vector.
        assert!(draw_color.is_some());
        let new_sprites = self.sprites
            .iter()
            .map(|param| {
                // Copy old params
                let mut new_param = *param;
                let src_width = param.src.w;
                let src_height = param.src.h;
                let real_scale = graphics::Point2::new(
                    src_width * param.scale.x * image.width as f32,
                    src_height * param.scale.y * image.height as f32,
                );
                new_param.scale = real_scale;
                // If we have no color, our color is white.
                // This is fine because coloring the whole spritebatch is possible
                // with graphics::set_color(); this just inherits from that.
                new_param.color = new_param.color.or(draw_color);
                graphics::InstanceProperties::from(new_param)
            })
            .collect::<Vec<_>>();

        let gfx = &mut ctx.gfx_context;
        if gfx.data.rect_instance_properties.len() < self.sprites.len() {
            gfx.data.rect_instance_properties = gfx.factory.create_buffer(
                self.sprites.len(),
                gfx::buffer::Role::Vertex,
                gfx::memory::Usage::Dynamic,
                gfx::memory::Bind::TRANSFER_DST,
            )?;
        }
        gfx.encoder
            .update_buffer(&gfx.data.rect_instance_properties, &new_sprites[..], 0)?;
        Ok(())
    }

    /// Removes all data from the sprite batch.
    pub fn clear(&mut self) {
        self.sprites.clear();
    }

    /// Unwraps the contained `Image`
    pub fn into_inner(self) -> graphics::Image {
        self.image
    }

    /// Replaces the contained `Image`, returning the old one.
    pub fn set_image(&mut self, image: graphics::Image) -> graphics::Image {
        use std::mem;
        mem::replace(&mut self.image, image)
    }

    /// Create an object which draws the current sprite batch with a different image.
    #[deprecated]
    #[allow(deprecated)]
    pub fn with_image<'a>(&'a mut self, image: &'a graphics::Image) -> BoundSpriteBatch<'a> {
        BoundSpriteBatch {
            image,
            batch: self,
        }
    }
}

#[deprecated]
#[allow(deprecated)]
impl<'a> graphics::Drawable for BoundSpriteBatch<'a> {
    fn draw_ex(&self, ctx: &mut Context, param: graphics::DrawParam) -> GameResult<()> {
        // Awkwardly we must update values on all sprites and such.
        // Also awkwardly we have this chain of colors with differing priorities.
        let fg = Some(ctx.gfx_context.foreground_color);
        let draw_color = param.color.or(fg);
        self.batch.flush(ctx, self.image, draw_color)?;
        let gfx = &mut ctx.gfx_context;
        let sampler = gfx.samplers
            .get_or_insert(self.image.sampler_info, gfx.factory.as_mut());
        gfx.data.vbuf = gfx.quad_vertex_buffer.clone();
        gfx.data.tex = (self.image.texture.clone(), sampler);
        let mut slice = gfx.quad_slice.clone();
        slice.instances = Some((self.batch.sprites.len() as u32, 0));
        let curr_transform = gfx.get_transform();
        gfx.push_transform(param.into_matrix() * curr_transform);
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        let previous_mode: Option<BlendMode> = if let Some(mode) = self.batch.blend_mode {
            let current_mode = gfx.get_blend_mode();
            if current_mode != mode {
                gfx.set_blend_mode(mode)?;
                Some(current_mode)
            } else {
                None
            }
        } else {
            None
        };
        gfx.draw(Some(&slice))?;
        if let Some(mode) = previous_mode {
            gfx.set_blend_mode(mode)?;
        }
        gfx.pop_transform();
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        Ok(())
    }

    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.batch.blend_mode = mode;
    }

    fn get_blend_mode(&self) -> Option<BlendMode> {
        self.batch.blend_mode
    }
}

impl graphics::Drawable for SpriteBatch {
    fn draw_ex(&self, ctx: &mut Context, param: graphics::DrawParam) -> GameResult<()> {
        // Awkwardly we must update values on all sprites and such.
        // Also awkwardly we have this chain of colors with differing priorities.
        let fg = Some(ctx.gfx_context.foreground_color);
        let draw_color = param.color.or(fg);
        self.flush(ctx, &self.image, draw_color)?;
        let gfx = &mut ctx.gfx_context;
        let sampler = gfx.samplers
            .get_or_insert(self.image.sampler_info, gfx.factory.as_mut());
        gfx.data.vbuf = gfx.quad_vertex_buffer.clone();
        gfx.data.tex = (self.image.texture.clone(), sampler);
        let mut slice = gfx.quad_slice.clone();
        slice.instances = Some((self.sprites.len() as u32, 0));
        let curr_transform = gfx.get_transform();
        gfx.push_transform(param.into_matrix() * curr_transform);
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        let previous_mode: Option<BlendMode> = if let Some(mode) = self.blend_mode {
            let current_mode = gfx.get_blend_mode();
            if current_mode != mode {
                gfx.set_blend_mode(mode)?;
                Some(current_mode)
            } else {
                None
            }
        } else {
            None
        };
        gfx.draw(Some(&slice))?;
        if let Some(mode) = previous_mode {
            gfx.set_blend_mode(mode)?;
        }
        gfx.pop_transform();
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        Ok(())
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.blend_mode = mode;
    }
    fn get_blend_mode(&self) -> Option<BlendMode> {
        self.blend_mode
    }
}
<|endoftext|>


<commit_before>//! JSON and serialization
//!
//! # What is JSON?
//!
//! JSON (JavaScript Object Notation) is a way to write data in JavaScript.  Like XML, it allows to
//! encode structured data in a text format that can be easily read by humans.  Its simple syntax
//! and native compatibility with JavaScript have made it a widely used format.
//!
//! Data types that can be encoded are JavaScript types (see the `serde_json:Value` enum for more
//! details):
//!
//! * `Boolean`: equivalent to rust's `bool`
//! * `I64`: equivalent to rust's `i64`
//! * `U64`: equivalent to rust's `u64`
//! * `F64`: equivalent to rust's `f64`
//! * `String`: equivalent to rust's `String`
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
//!    same array
//! * `Object`: equivalent to rust's `BTreeMap<String, serde_json::Value>`; set the
//!    `preserve_order` feature to use `LinkedHashMap<String, serde_json::Value>` instead
//! * `Null`
//!
//! An object is a series of string keys mapping to values, in `"key": value` format.  Arrays are
//! enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }).  A simple JSON
//! document encoding a person, his/her age, address and phone numbers could look like
//!
//! ```ignore
//! {
//!     "FirstName": "John",
//!     "LastName": "Doe",
//!     "Age": 43,
//!     "Address": {
//!         "Street": "Downing Street 10",
//!         "City": "London",
//!         "Country": "Great Britain"
//!     },
//!     "PhoneNumbers": [
//!         "+44 1234567",
//!         "+44 2345678"
//!     ]
//! }
//! ```
//!
//! If we assume that `FirstName` is optional and all other fields are mandatory, the above JSON could
//! correspond to the following Rust structs:
//!
//! ```ignore
//! #[derive(Serialize, Deserialize)]
//! struct Data {
//!     #[serde(rename="FirstName")] // to comply with Rust coding standards
//!     first_name: Option<String>,
//!     LastName: String,
//!     Age: u32,
//!     Address: Address,
//!     PhoneNumbers: Vec<String>
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! struct Address {
//!     Street: String,
//!     City: String,
//!     Country: String
//! }
//! ```
//!
//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from JSON via the serialization API.  To be able to serialize a piece of data, it must implement
//! the `serde::Serialize` trait.  To be able to deserialize a piece of data, it must implement the
//! `serde::Deserialize` trait.  Serde provides provides an annotation to automatically generate
//! the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! The JSON API also provides an enum `serde_json::Value` and a method `to_value` to serialize
//! objects.  A `serde_json::Value` value can be serialized as a string or buffer using the
//! functions described above.  You can also use the `json::Serializer` object, which implements the
//! `Serializer` trait.
//!
//! # Examples of use
//!
//! ## Parsing a `str` to `Value` and reading the result
//!
//! ```rust
//! //#![feature(custom_derive, plugin)]
//! //#![plugin(serde_macros)]
//!
//! extern crate serde_json;
//!
//! use serde_json::Value;
//!
//! fn main() {
//!     let data: Value = serde_json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
//!     println!("data: {:?}", data);
//!     // data: {"bar":"baz","foo":13}
//!     println!("object? {}", data.is_object());
//!     // object? true
//!
//!     let obj = data.as_object().unwrap();
//!     let foo = obj.get("foo").unwrap();
//!
//!     println!("array? {:?}", foo.as_array());
//!     // array? None
//!     println!("u64? {:?}", foo.as_u64());
//!     // u64? Some(13u64)
//!
//!     for (key, value) in obj.iter() {
//!         println!("{}: {}", key, match *value {
//!             Value::U64(v) => format!("{} (u64)", v),
//!             Value::String(ref v) => format!("{} (string)", v),
//!             _ => format!("other")
//!         });
//!     }
//!     // bar: baz (string)
//!     // foo: 13 (u64)
//! }
//! ```

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", deny(clippy, clippy_pedantic))]
// Because of "JavaScript"... fixed in Manishearth/rust-clippy#1071
#![cfg_attr(feature = "clippy", allow(doc_markdown))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "clippy", allow(
// integer and float ser/de requires these sorts of casts
    cast_possible_truncation,
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
// string ser/de uses indexing and slicing
    indexing_slicing,
// things are often more readable this way
    shadow_reuse,
    shadow_unrelated,
    single_match_else,
    stutter,
// not practical
    missing_docs_in_private_items,
))]

#![deny(missing_docs)]

extern crate num_traits;
extern crate core;
#[macro_use]
extern crate serde;
extern crate itoa;
extern crate dtoa;
#[cfg(feature = "preserve_order")]
extern crate linked_hash_map;

pub use self::de::{Deserializer, StreamDeserializer, from_iter, from_reader,
                   from_slice, from_str};
pub use self::error::{Error, ErrorCode, Result};
pub use self::ser::{Serializer, escape_str, to_string, to_string_pretty,
                    to_vec, to_vec_pretty, to_writer, to_writer_pretty};
pub use self::value::{Map, Value, from_value, to_value};

pub mod builder;
pub mod de;
pub mod error;
pub mod ser;
pub mod value;

mod read;
<commit_msg>Update docs for the deprecation of serde_macros.<commit_after>//! JSON and serialization
//!
//! # What is JSON?
//!
//! JSON (JavaScript Object Notation) is a way to write data in JavaScript.  Like XML, it allows to
//! encode structured data in a text format that can be easily read by humans.  Its simple syntax
//! and native compatibility with JavaScript have made it a widely used format.
//!
//! Data types that can be encoded are JavaScript types (see the `serde_json:Value` enum for more
//! details):
//!
//! * `Boolean`: equivalent to rust's `bool`
//! * `I64`: equivalent to rust's `i64`
//! * `U64`: equivalent to rust's `u64`
//! * `F64`: equivalent to rust's `f64`
//! * `String`: equivalent to rust's `String`
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
//!    same array
//! * `Object`: equivalent to rust's `BTreeMap<String, serde_json::Value>`; set the
//!    `preserve_order` feature to use `LinkedHashMap<String, serde_json::Value>` instead
//! * `Null`
//!
//! An object is a series of string keys mapping to values, in `"key": value` format.  Arrays are
//! enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }).  A simple JSON
//! document encoding a person, his/her age, address and phone numbers could look like
//!
//! ```ignore
//! {
//!     "FirstName": "John",
//!     "LastName": "Doe",
//!     "Age": 43,
//!     "Address": {
//!         "Street": "Downing Street 10",
//!         "City": "London",
//!         "Country": "Great Britain"
//!     },
//!     "PhoneNumbers": [
//!         "+44 1234567",
//!         "+44 2345678"
//!     ]
//! }
//! ```
//!
//! If we assume that `FirstName` is optional and all other fields are mandatory, the above JSON could
//! correspond to the following Rust structs:
//!
//! ```ignore
//! #[derive(Serialize, Deserialize)]
//! struct Data {
//!     #[serde(rename="FirstName")] // to comply with Rust coding standards
//!     first_name: Option<String>,
//!     LastName: String,
//!     Age: u32,
//!     Address: Address,
//!     PhoneNumbers: Vec<String>
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! struct Address {
//!     Street: String,
//!     City: String,
//!     Country: String
//! }
//! ```
//!
//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from JSON via the serialization API.  To be able to serialize a piece of data, it must implement
//! the `serde::Serialize` trait.  To be able to deserialize a piece of data, it must implement the
//! `serde::Deserialize` trait.  Serde provides provides an annotation to automatically generate
//! the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! The JSON API also provides an enum `serde_json::Value` and a method `to_value` to serialize
//! objects.  A `serde_json::Value` value can be serialized as a string or buffer using the
//! functions described above.  You can also use the `json::Serializer` object, which implements the
//! `Serializer` trait.
//!
//! # Examples of use
//!
//! ## Parsing a `str` to `Value` and reading the result
//!
//! ```rust
//! //#![feature(rustc_macro)]
//! //#[macro_use]
//!
//! extern crate serde_json;
//!
//! use serde_json::Value;
//!
//! fn main() {
//!     let data: Value = serde_json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
//!     println!("data: {:?}", data);
//!     // data: {"bar":"baz","foo":13}
//!     println!("object? {}", data.is_object());
//!     // object? true
//!
//!     let obj = data.as_object().unwrap();
//!     let foo = obj.get("foo").unwrap();
//!
//!     println!("array? {:?}", foo.as_array());
//!     // array? None
//!     println!("u64? {:?}", foo.as_u64());
//!     // u64? Some(13u64)
//!
//!     for (key, value) in obj.iter() {
//!         println!("{}: {}", key, match *value {
//!             Value::U64(v) => format!("{} (u64)", v),
//!             Value::String(ref v) => format!("{} (string)", v),
//!             _ => format!("other")
//!         });
//!     }
//!     // bar: baz (string)
//!     // foo: 13 (u64)
//! }
//! ```

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", deny(clippy, clippy_pedantic))]
// Because of "JavaScript"... fixed in Manishearth/rust-clippy#1071
#![cfg_attr(feature = "clippy", allow(doc_markdown))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "clippy", allow(
// integer and float ser/de requires these sorts of casts
    cast_possible_truncation,
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
// string ser/de uses indexing and slicing
    indexing_slicing,
// things are often more readable this way
    shadow_reuse,
    shadow_unrelated,
    single_match_else,
    stutter,
// not practical
    missing_docs_in_private_items,
))]

#![deny(missing_docs)]

extern crate num_traits;
extern crate core;
#[macro_use]
extern crate serde;
extern crate itoa;
extern crate dtoa;
#[cfg(feature = "preserve_order")]
extern crate linked_hash_map;

pub use self::de::{Deserializer, StreamDeserializer, from_iter, from_reader,
                   from_slice, from_str};
pub use self::error::{Error, ErrorCode, Result};
pub use self::ser::{Serializer, escape_str, to_string, to_string_pretty,
                    to_vec, to_vec_pretty, to_writer, to_writer_pretty};
pub use self::value::{Map, Value, from_value, to_value};

pub mod builder;
pub mod de;
pub mod error;
pub mod ser;
pub mod value;

mod read;
<|endoftext|>


<commit_before>use std::io;
use rf_common::*;
use syntax::ast;
use rustc::middle::{ty,typeck};
use syntax::codemap::{BytePos, Pos};
use rsfind::ShowDefMode;

//use rustc::middle::typeck::*;-

use find_ast_node::{FNodeInfoMap, FNodeInfo, AstNode, NodeTreeLoc, find_node_tree_loc_at_byte_pos,
    build_node_def_node_table, build_node_info_map, get_node_source, astnode_expr,
    get_def_id, byte_pos_from_text_file_pos_str, ToJsonStr, ToJsonStrFc, AstNodeAccessors};
use rfindctx::{RFindCtx,get_source_loc};
use codemaput::ZTextFilePos;
use rf_ast_ut::{auto_deref_ty, find_named_struct_field};
use util::flatten_to_str_ng; //todo - why is qualifying manually not working?!
use timer::Timer;
//use super::rf_use_ast;

//todo - simple declartions of types shouldn't mean bringing in associated code modules ?
// a user that needs the type JumpToDefMap needn't necaserily need all its functions...

pub macro_rules! if_some {
    ($b:ident in $a:expr then $c:expr)=>(
        match $a {
            Some($b)=>$c,
            None=>{}
        }
    );
}

pub type JumpToDefMap = HashMap<ast::NodeId,ast::DefId> ;

pub fn lookup_def_node_of_node(dc:&RFindCtx,node:&AstNode, nodeinfomap:&FNodeInfoMap, _: &HashMap<ast::NodeId,ast::DefId>)->Option<ast::DefId> {

    match *node {
        astnode_expr(e)=>match e.node {
            // handle methods-calls
            ast::ExprMethodCall(call_ident, call_type_params, call_args)=>{
                // Currently unused
//              let rec_ty_node= astnode_expr(*receiver).ty_node_id();
//              let rec_ty_node1= dc.tycx.node_types.find(&(*id as uint));

                let method_map =dc.ca.maps.method_map;
				let method_call=typeck::MethodCall{expr_id:e.id,  autoderef:0}; // TODO is that e.id or call_ident...
				io::println(format!("e.id={:?} call_ident={:?}", e.id, call_ident.name));
                match method_map.borrow().get().get(&method_call).origin {
                    typeck::MethodStatic(def_id)=>
							return Some(def_id),
                    typeck::MethodObject(_)=>
                            return None,
                    typeck::MethodParam(mp)=>{
                        let trait_method_def_ids = dc.tycx_ref().trait_method_def_ids.borrow();
                        let trait_method_def_ids = trait_method_def_ids.get();
                        match trait_method_def_ids.find(&mp.trait_id) {
                            None=>{},
                            Some(method_def_ids)=>{
                                return Some(*method_def_ids.get(mp.method_num))
                            }
                        }
                    }
                }
            },
            // handle struct-fields? "object.field"
            ast::ExprField(ref object_expr, ref ident, _)=>{
                // we want the type of the object..
                let node_types = dc.tycx_ref().node_types.borrow();
                let node_types = node_types.get();
                let obj_ty=node_types.find(&(object_expr.id as uint));
                let tydef=/*rf_ast_ut::*/auto_deref_ty(ty::get(*obj_ty.unwrap()));
                match tydef.sty {
                    ty::ty_struct(def,_)=> {
                        let node_to_show=/*rf_ast_ut::*/find_named_struct_field(dc.tycx_ref(), def.node, ident).unwrap_or(def);
                        return Some(node_to_show);//mk_result(dc,m,node_spans,node_to_show,"(struct_field)");
                    },
                    _=>return None
                }
            }
            _=>{}
        },
        _=>{}

    }

    // handle everything else
    match node.ty_node_id() {
        Some(id) =>{
            let (def_id, _)= def_info_from_node_id(dc,nodeinfomap,id);
            return if def_id != ast::DefId{krate:0,node:id} {Some(def_id)} else {None}
/*          match opt_info {
                Some(info)=> {
                    return Some(def_id);
                },
                _=>{ println("can't find def for"+node.get_id().to_str()+".ty_node_id="+id.to_str()); //return None;
                    //let (def_id,opt_info)= def_info_from_node_id(dc,nodeinfomap,node.get_id().unwrap());
                    //match opt_info {
                    //  Some(info)=> {return Some(def_id);}
                    //  None=>{}
                    //}
                }
            }
*/
        },
        None=> {}
    };
    return None;
}

pub fn build_jump_to_def_map(dc:&RFindCtx, nim: &FNodeInfoMap,nd:&HashMap<ast::NodeId,ast::DefId>)->~JumpToDefMap{
// todo: NodeId->AStNode  .. lookup_def_ inner functionality extracted
    let mut jdm=~HashMap::new();
    for (k,node_info) in nim.iter() {
        match lookup_def_node_of_node(dc,&node_info.node, nim,nd) {
            None=>{},
            Some(def_node_id)=>{
//              if *k != def_node_id.node && def_node_id.crate==0 || (def_node_id.crate!=0)
                {
                    jdm.insert(*k,def_node_id);
                }
            }
        }
    }
    jdm
}

pub fn def_info_from_node_id<'a,'b>(dc:&'a RFindCtx, node_info:&'b FNodeInfoMap, id:ast::NodeId)->(ast::DefId,Option<&'b FNodeInfo>) {
    let crate_num=0;
    let def_map = dc.tycx_ref().def_map.borrow();
    let def_map = def_map.get();
    match def_map.find(&id) { // finds a def..
        Some(a)=>{
            match get_def_id(crate_num,*a){
                Some(b)=>
                    (b,node_info.find(&b.node)),
//              match b.crate {
//                  0=>(b.node,node_info.find(&b.node)),
//                  _ => (id as int, None)
//              },
                None=>(ast::DefId{krate:0,node:id},None)
            }
        },
        None=>(ast::DefId{krate:0,node:id},None)
    }
}

pub fn dump_json(dc:&RFindCtx) {
    // TODO: full/partial options - we currently wwrite out all the nodes we find.
    // need option to only write out nodes that map to definitons.
    io::println("{");
    io::println("\tcode_map:[");
//  for dc.sess.codemap.files.iter().advance |f| {
    let files = dc.codemap().files.borrow();
    let files = files.get();
    for f in files.iter() {
        let lines = f.lines.borrow();
        let lines = lines.get();
        print!("\t\t\\{ name:\"{}\"", f.name);
        print!("\tglobal_start_pos:{},", f.start_pos.to_uint().to_str());
        print!("\tlength:{},", (f.src.len()).to_str());
        print!("\tnum_lines:{},", lines.len().to_str());
        print!("\tlines:[\n{},", flatten_to_str_ng(lines, |&x|{(x-f.start_pos).to_uint()} ,","));
        print!("\n\t\t]\n\t\\},\n");
    }
    io::println("\t]");
    io::println("\tnode_spans:");
    let nim=build_node_info_map(dc.crate_);
    let node_def_node = build_node_def_node_table(dc);
    let jdm=build_jump_to_def_map(dc, &nim,node_def_node);
    io::println(nim.to_json_str(dc));
    io::println(",");
    io::println("\tnode_defs [\n");
    io::println(jdm.to_json_str());
    io::println("\t],\n");
    io::println("\tdef_ids:");
    io::println(node_def_node.to_json_str());
    io::println("}");
}

pub fn lookup_def_at_text_file_pos(dc:&RFindCtx, tfp:&ZTextFilePos, show_mode:ShowDefMode)->Option<~str> {
    match tfp.to_byte_pos(dc.tycx_ref()) {
        None=>None,
        Some(bp)=>lookup_def_at_byte_pos(dc,bp,show_mode)
    }
}

pub fn lookup_def_at_text_file_pos_str(dc:&RFindCtx,file_pos_str:&str, show_mode:ShowDefMode)->Option<~str> {
    match byte_pos_from_text_file_pos_str(dc,file_pos_str) {
        None=>None,
        Some(bp)=>lookup_def_at_byte_pos(dc,bp,show_mode),
    }
}

pub fn node_id_from_text_file_pos_str(dc:&RFindCtx, file_pos_str:&str)->Option<ast::NodeId> {
    match node_from_text_file_pos_str(dc, file_pos_str) {
        None=>None,
        Some(an)=>an.get_id()
    }
}
pub fn node_from_text_file_pos_str(dc:&RFindCtx, file_pos_str:&str)->Option<AstNode> {
    match byte_pos_from_text_file_pos_str(dc,file_pos_str) {
        Some(bp)=>{let ndt=find_node_tree_loc_at_byte_pos(dc.crate_,bp); Some(*ndt.last().get_ref().clone())},
        None=>None
    }
}

pub fn lookup_def_at_byte_pos(dc:&RFindCtx, bp:BytePos, m:ShowDefMode)->Option<~str> {
    let ndt=find_node_tree_loc_at_byte_pos(dc.crate_,bp);
    lookup_def_of_node_tree_loc(dc,&ndt,m)
}

pub fn lookup_def_of_node_tree_loc(dc:&RFindCtx,node_tree_loc:&NodeTreeLoc,m:ShowDefMode)->Option<~str> {
    lookup_def_of_node(dc,*node_tree_loc.last().get_ref(),m)
}

pub fn lookup_def_of_node(dc: &RFindCtx, node: &AstNode, m: ShowDefMode)->Option<~str> {
    io::println("def of node:"+node.get_id().unwrap_or(0).to_str());
    let node_spans=build_node_info_map(dc.crate_);
    let node_def_node = build_node_def_node_table(dc);
    lookup_def_of_node_sub(dc,node,m,&node_spans,node_def_node)
}

pub fn lookup_def_of_node_sub(dc:&RFindCtx,node:&AstNode,m:ShowDefMode,nim:&FNodeInfoMap, node_def_node:&HashMap<ast::NodeId,ast::DefId>)->Option<~str> {
    // TODO - cache outside?

    fn mk_result(dc:&RFindCtx,  m:ShowDefMode, nim:&FNodeInfoMap, def_node_id:ast::DefId, _: &str)->Option<~str> {
        if def_node_id.krate != 0 {
            Some(~"{cross-crate-def not implemented, "+def_node_id.to_str()+"}")
        }
        else {
            match nim.find(&def_node_id.node) {
                None=>None,
                Some(def_info)=>{
                    let loc=get_source_loc(dc,def_info.span.lo);
                    let def_pos_str=
                        loc.file.name + ":"+loc.line.to_str()+": "+
                            match m { SDM_LineCol=>loc.col.to_uint().to_str()+": ", _ =>~"" }+"\n";
                    return  match m{
                        SDM_Source=>Some(def_pos_str+get_node_source(dc.tycx_ref(),nim, def_node_id)+"\n"),
                        SDM_GeditCmd=>Some("+"+loc.line.to_str()+" "+loc.file.name+" "),
                        _ => Some(def_pos_str)
                    };

                }
            }
        }
    }
    match lookup_def_node_of_node(dc, node, nim, node_def_node) {
        None=>None,
        Some(def_node_id)=>mk_result(dc,m, nim,def_node_id, "")
    }
}

pub fn make_jdm(dc:&RFindCtx)->( FNodeInfoMap, ~HashMap<ast::NodeId,ast::DefId>,~JumpToDefMap)
{
    let mut t = Timer::new();
    t.start();
    let nim=build_node_info_map(dc.crate_);
    t.end();
    println!("build_node_info_map: {}", t.get_time_string());
    t.start();
    let ndm=build_node_def_node_table(dc);
    t.end();
    println!("build_node_def_node_table: {}", t.get_time_string());
    t.start();
    let jdm=build_jump_to_def_map(dc, &nim,ndm);
    t.end();
    println!("build_jump_to_def_map: {}", t.get_time_string());
    (nim,ndm,jdm)
}
<commit_msg>works again<commit_after>use std::io;
use rf_common::*;
use syntax::ast;
use rustc::middle::{ty,typeck};
use syntax::codemap::{BytePos, Pos};
use rsfind::ShowDefMode;

//use rustc::middle::typeck::*;-

use find_ast_node::{FNodeInfoMap, FNodeInfo, AstNode, NodeTreeLoc, find_node_tree_loc_at_byte_pos,
    build_node_def_node_table, build_node_info_map, get_node_source, astnode_expr,
    get_def_id, byte_pos_from_text_file_pos_str, ToJsonStr, ToJsonStrFc, AstNodeAccessors};
use rfindctx::{RFindCtx,get_source_loc};
use codemaput::ZTextFilePos;
use rf_ast_ut::{auto_deref_ty, find_named_struct_field};
use util::flatten_to_str_ng; //todo - why is qualifying manually not working?!
use timer::Timer;
//use super::rf_use_ast;

//todo - simple declartions of types shouldn't mean bringing in associated code modules ?
// a user that needs the type JumpToDefMap needn't necaserily need all its functions...

pub macro_rules! if_some {
    ($b:ident in $a:expr then $c:expr)=>(
        match $a {
            Some($b)=>$c,
            None=>{}
        }
    );
}

pub type JumpToDefMap = HashMap<ast::NodeId,ast::DefId> ;

pub fn lookup_def_node_of_node(dc:&RFindCtx,node:&AstNode, nodeinfomap:&FNodeInfoMap, _: &HashMap<ast::NodeId,ast::DefId>)->Option<ast::DefId> {

    match *node {
        astnode_expr(e)=>match e.node {
            // handle methods-calls
            ast::ExprMethodCall(ref call_ident, ref call_type_params, ref call_args)=>{
                // Currently unused
//              let rec_ty_node= astnode_expr(*receiver).ty_node_id();
//              let rec_ty_node1= dc.tycx.node_types.find(&(*id as uint));

                let method_map =dc.ca.maps.method_map;
				let method_call=typeck::MethodCall{expr_id:e.id,  autoderef:0}; // TODO is that e.id or call_ident...
				io::println(format!("e.id={:?} call_ident={:?}", e.id, call_ident.name));
                match method_map.borrow().get().get(&method_call).origin {
                    typeck::MethodStatic(def_id)=>
							return Some(def_id),
                    typeck::MethodObject(_)=>
                            return None,
                    typeck::MethodParam(mp)=>{
                        let trait_method_def_ids = dc.tycx_ref().trait_method_def_ids.borrow();
                        let trait_method_def_ids = trait_method_def_ids.get();
                        match trait_method_def_ids.find(&mp.trait_id) {
                            None=>{},
                            Some(method_def_ids)=>{
                                return Some(*method_def_ids.get(mp.method_num))
                            }
                        }
                    }
                }
            },
            // handle struct-fields? "object.field"
            ast::ExprField(ref object_expr, ref ident, _)=>{
                // we want the type of the object..
                let node_types = dc.tycx_ref().node_types.borrow();
                let node_types = node_types.get();
                let obj_ty=node_types.find(&(object_expr.id as uint));
                let tydef=/*rf_ast_ut::*/auto_deref_ty(ty::get(*obj_ty.unwrap()));
                match tydef.sty {
                    ty::ty_struct(def,_)=> {
                        let node_to_show=/*rf_ast_ut::*/find_named_struct_field(dc.tycx_ref(), def.node, ident).unwrap_or(def);
                        return Some(node_to_show);//mk_result(dc,m,node_spans,node_to_show,"(struct_field)");
                    },
                    _=>return None
                }
            }
            _=>{}
        },
        _=>{}

    }

    // handle everything else
    match node.ty_node_id() {
        Some(id) =>{
            let (def_id, _)= def_info_from_node_id(dc,nodeinfomap,id);
            return if def_id != ast::DefId{krate:0,node:id} {Some(def_id)} else {None}
/*          match opt_info {
                Some(info)=> {
                    return Some(def_id);
                },
                _=>{ println("can't find def for"+node.get_id().to_str()+".ty_node_id="+id.to_str()); //return None;
                    //let (def_id,opt_info)= def_info_from_node_id(dc,nodeinfomap,node.get_id().unwrap());
                    //match opt_info {
                    //  Some(info)=> {return Some(def_id);}
                    //  None=>{}
                    //}
                }
            }
*/
        },
        None=> {}
    };
    return None;
}

pub fn build_jump_to_def_map(dc:&RFindCtx, nim: &FNodeInfoMap,nd:&HashMap<ast::NodeId,ast::DefId>)->~JumpToDefMap{
// todo: NodeId->AStNode  .. lookup_def_ inner functionality extracted
    let mut jdm=~HashMap::new();
    for (k,node_info) in nim.iter() {
        match lookup_def_node_of_node(dc,&node_info.node, nim,nd) {
            None=>{},
            Some(def_node_id)=>{
//              if *k != def_node_id.node && def_node_id.crate==0 || (def_node_id.crate!=0)
                {
                    jdm.insert(*k,def_node_id);
                }
            }
        }
    }
    jdm
}

pub fn def_info_from_node_id<'a,'b>(dc:&'a RFindCtx, node_info:&'b FNodeInfoMap, id:ast::NodeId)->(ast::DefId,Option<&'b FNodeInfo>) {
    let crate_num=0;
    let def_map = dc.tycx_ref().def_map.borrow();
    let def_map = def_map.get();
    match def_map.find(&id) { // finds a def..
        Some(a)=>{
            match get_def_id(crate_num,*a){
                Some(b)=>
                    (b,node_info.find(&b.node)),
//              match b.crate {
//                  0=>(b.node,node_info.find(&b.node)),
//                  _ => (id as int, None)
//              },
                None=>(ast::DefId{krate:0,node:id},None)
            }
        },
        None=>(ast::DefId{krate:0,node:id},None)
    }
}

pub fn dump_json(dc:&RFindCtx) {
    // TODO: full/partial options - we currently wwrite out all the nodes we find.
    // need option to only write out nodes that map to definitons.
    io::println("{");
    io::println("\tcode_map:[");
//  for dc.sess.codemap.files.iter().advance |f| {
    let files = dc.codemap().files.borrow();
    let files = files.get();
    for f in files.iter() {
        let lines = f.lines.borrow();
        let lines = lines.get();
        print!("\t\t\\{ name:\"{}\"", f.name);
        print!("\tglobal_start_pos:{},", f.start_pos.to_uint().to_str());
        print!("\tlength:{},", (f.src.len()).to_str());
        print!("\tnum_lines:{},", lines.len().to_str());
        print!("\tlines:[\n{},", flatten_to_str_ng(lines, |&x|{(x-f.start_pos).to_uint()} ,","));
        print!("\n\t\t]\n\t\\},\n");
    }
    io::println("\t]");
    io::println("\tnode_spans:");
    let nim=build_node_info_map(dc.crate_);
    let node_def_node = build_node_def_node_table(dc);
    let jdm=build_jump_to_def_map(dc, &nim,node_def_node);
    io::println(nim.to_json_str(dc));
    io::println(",");
    io::println("\tnode_defs [\n");
    io::println(jdm.to_json_str());
    io::println("\t],\n");
    io::println("\tdef_ids:");
    io::println(node_def_node.to_json_str());
    io::println("}");
}

pub fn lookup_def_at_text_file_pos(dc:&RFindCtx, tfp:&ZTextFilePos, show_mode:ShowDefMode)->Option<~str> {
    match tfp.to_byte_pos(dc.tycx_ref()) {
        None=>None,
        Some(bp)=>lookup_def_at_byte_pos(dc,bp,show_mode)
    }
}

pub fn lookup_def_at_text_file_pos_str(dc:&RFindCtx,file_pos_str:&str, show_mode:ShowDefMode)->Option<~str> {
    match byte_pos_from_text_file_pos_str(dc,file_pos_str) {
        None=>None,
        Some(bp)=>lookup_def_at_byte_pos(dc,bp,show_mode),
    }
}

pub fn node_id_from_text_file_pos_str(dc:&RFindCtx, file_pos_str:&str)->Option<ast::NodeId> {
    match node_from_text_file_pos_str(dc, file_pos_str) {
        None=>None,
        Some(an)=>an.get_id()
    }
}
pub fn node_from_text_file_pos_str(dc:&RFindCtx, file_pos_str:&str)->Option<AstNode> {
    match byte_pos_from_text_file_pos_str(dc,file_pos_str) {
        Some(bp)=>{let ndt=find_node_tree_loc_at_byte_pos(dc.crate_,bp); Some(*ndt.last().get_ref().clone())},
        None=>None
    }
}

pub fn lookup_def_at_byte_pos(dc:&RFindCtx, bp:BytePos, m:ShowDefMode)->Option<~str> {
    let ndt=find_node_tree_loc_at_byte_pos(dc.crate_,bp);
    lookup_def_of_node_tree_loc(dc,&ndt,m)
}

pub fn lookup_def_of_node_tree_loc(dc:&RFindCtx,node_tree_loc:&NodeTreeLoc,m:ShowDefMode)->Option<~str> {
    lookup_def_of_node(dc,*node_tree_loc.last().get_ref(),m)
}

pub fn lookup_def_of_node(dc: &RFindCtx, node: &AstNode, m: ShowDefMode)->Option<~str> {
    io::println("def of node:"+node.get_id().unwrap_or(0).to_str());
    let node_spans=build_node_info_map(dc.crate_);
    let node_def_node = build_node_def_node_table(dc);
    lookup_def_of_node_sub(dc,node,m,&node_spans,node_def_node)
}

pub fn lookup_def_of_node_sub(dc:&RFindCtx,node:&AstNode,m:ShowDefMode,nim:&FNodeInfoMap, node_def_node:&HashMap<ast::NodeId,ast::DefId>)->Option<~str> {
    // TODO - cache outside?

    fn mk_result(dc:&RFindCtx,  m:ShowDefMode, nim:&FNodeInfoMap, def_node_id:ast::DefId, _: &str)->Option<~str> {
        if def_node_id.krate != 0 {
            Some(~"{cross-crate-def not implemented, "+def_node_id.to_str()+"}")
        }
        else {
            match nim.find(&def_node_id.node) {
                None=>None,
                Some(def_info)=>{
                    let loc=get_source_loc(dc,def_info.span.lo);
                    let def_pos_str=
                        loc.file.name + ":"+loc.line.to_str()+": "+
                            match m { SDM_LineCol=>loc.col.to_uint().to_str()+": ", _ =>~"" }+"\n";
                    return  match m{
                        SDM_Source=>Some(def_pos_str+get_node_source(dc.tycx_ref(),nim, def_node_id)+"\n"),
                        SDM_GeditCmd=>Some("+"+loc.line.to_str()+" "+loc.file.name+" "),
                        _ => Some(def_pos_str)
                    };

                }
            }
        }
    }
    match lookup_def_node_of_node(dc, node, nim, node_def_node) {
        None=>None,
        Some(def_node_id)=>mk_result(dc,m, nim,def_node_id, "")
    }
}

pub fn make_jdm(dc:&RFindCtx)->( FNodeInfoMap, ~HashMap<ast::NodeId,ast::DefId>,~JumpToDefMap)
{
    let mut t = Timer::new();
    t.start();
    let nim=build_node_info_map(dc.crate_);
    t.end();
    println!("build_node_info_map: {}", t.get_time_string());
    t.start();
    let ndm=build_node_def_node_table(dc);
    t.end();
    println!("build_node_def_node_table: {}", t.get_time_string());
    t.start();
    let jdm=build_jump_to_def_map(dc, &nim,ndm);
    t.end();
    println!("build_jump_to_def_map: {}", t.get_time_string());
    (nim,ndm,jdm)
}
<|endoftext|>


<commit_before>use cmp::Ordering;
use fmt;
use mem;
use sys::c;
use time::Duration;
use convert::TryInto;
use core::hash::{Hash, Hasher};

const NANOS_PER_SEC: u64 = 1_000_000_000;
const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100;

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub struct Instant {
    t: u64,
}

#[derive(Copy, Clone)]
pub struct SystemTime {
    t: c::FILETIME,
}

const INTERVALS_TO_UNIX_EPOCH: u64 = 11_644_473_600 * INTERVALS_PER_SEC;

pub const UNIX_EPOCH: SystemTime = SystemTime {
    t: c::FILETIME {
        dwLowDateTime: INTERVALS_TO_UNIX_EPOCH as u32,
        dwHighDateTime: (INTERVALS_TO_UNIX_EPOCH >> 32) as u32,
    },
};

impl Instant {
    pub fn now() -> Instant {
        // High precision timing on windows operates in "Performance Counter"
        // units, as returned by the WINAPI QueryPerformanceCounter function.
        // These relate to seconds by a factor of QueryPerformanceFrequency.
        // In order to keep unit conversions out of normal interval math, we
        // measure in QPC units and immediately convert to nanoseconds.
        perf_counter::PerformanceCounterInstant::now().into()
    }

    pub fn actually_monotonic() -> bool {
        false
    }

    pub const fn zero() -> Instant {
        Instant { t: 0 }
    }

    pub fn sub_instant(&self, other: &Instant) -> Duration {
        // On windows there's a threshold below which we consider two timestamps
        // equivalent due to measurement error. For more details + doc link,
        // check the docs on epsilon_nanos.
        let epsilon_ns =
            perf_counter::PerformanceCounterInstant::epsilon_nanos() as u64;
        if other.t > self.t && other.t - self.t <= epsilon_ns {
            return Duration::new(0, 0)
        }
        let diff = (self.t).checked_sub(other.t)
                           .expect("specified instant was later than self");
        Duration::new(diff / NANOS_PER_SEC, (diff % NANOS_PER_SEC) as u32)
    }

    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
        let sum = other.as_secs()
            .checked_mul(NANOS_PER_SEC)?
            .checked_add(other.subsec_nanos() as u64)?
            .checked_add(self.t as u64)?;
        Some(Instant {
            t: sum,
        })
    }

    pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
        let other_ns = other.as_secs()
            .checked_mul(NANOS_PER_SEC)?
            .checked_add(other.subsec_nanos() as u64)?;
        let difference = self.t.checked_sub(other_ns)?;
        Some(Instant {
            t: difference,
        })
    }
}

impl SystemTime {
    pub fn now() -> SystemTime {
        unsafe {
            let mut t: SystemTime = mem::zeroed();
            c::GetSystemTimeAsFileTime(&mut t.t);
            return t
        }
    }

    fn from_intervals(intervals: i64) -> SystemTime {
        SystemTime {
            t: c::FILETIME {
                dwLowDateTime: intervals as c::DWORD,
                dwHighDateTime: (intervals >> 32) as c::DWORD,
            }
        }
    }

    fn intervals(&self) -> i64 {
        (self.t.dwLowDateTime as i64) | ((self.t.dwHighDateTime as i64) << 32)
    }

    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
        let me = self.intervals();
        let other = other.intervals();
        if me >= other {
            Ok(intervals2dur((me - other) as u64))
        } else {
            Err(intervals2dur((other - me) as u64))
        }
    }

    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
        let intervals = self.intervals().checked_add(checked_dur2intervals(other)?)?;
        Some(SystemTime::from_intervals(intervals))
    }

    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
        let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?;
        Some(SystemTime::from_intervals(intervals))
    }
}

impl PartialEq for SystemTime {
    fn eq(&self, other: &SystemTime) -> bool {
        self.intervals() == other.intervals()
    }
}

impl Eq for SystemTime {}

impl PartialOrd for SystemTime {
    fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for SystemTime {
    fn cmp(&self, other: &SystemTime) -> Ordering {
        self.intervals().cmp(&other.intervals())
    }
}

impl fmt::Debug for SystemTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("SystemTime")
         .field("intervals", &self.intervals())
         .finish()
    }
}

impl From<c::FILETIME> for SystemTime {
    fn from(t: c::FILETIME) -> SystemTime {
        SystemTime { t }
    }
}

impl Hash for SystemTime {
    fn hash<H : Hasher>(&self, state: &mut H) {
        self.intervals().hash(state)
    }
}

fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
    dur.as_secs()
        .checked_mul(INTERVALS_PER_SEC)?
        .checked_add(dur.subsec_nanos() as u64 / 100)?
        .try_into()
        .ok()
}

fn intervals2dur(intervals: u64) -> Duration {
    Duration::new(intervals / INTERVALS_PER_SEC,
                  ((intervals % INTERVALS_PER_SEC) * 100) as u32)
}

mod perf_counter {
    use super::{NANOS_PER_SEC};
    use sync::Once;
    use sys_common::mul_div_u64;
    use sys::c;
    use sys::cvt;

    pub struct PerformanceCounterInstant {
        ts: c::LARGE_INTEGER
    }
    impl PerformanceCounterInstant {
        pub fn now() -> Self {
            Self {
                ts: query()
            }
        }

        // Per microsoft docs, the margin of error for cross-thread time comparisons
        // using QueryPerformanceCounter is 1 "tick" -- defined as 1/frequency().
        // Reference: https://docs.microsoft.com/en-us/windows/desktop/SysInfo
        //                   /acquiring-high-resolution-time-stamps
        pub fn epsilon_nanos() -> u32 {
            let epsilon = NANOS_PER_SEC / (frequency() as u64);
            // As noted elsewhere, subsecond nanos always fit in a u32
            epsilon as u32
        }
    }
    impl From<PerformanceCounterInstant> for super::Instant {
        fn from(other: PerformanceCounterInstant) -> Self {
            let freq = frequency() as u64;
            Self {
                t: mul_div_u64(other.ts as u64, NANOS_PER_SEC, freq)
            }
        }
    }

    fn frequency() -> c::LARGE_INTEGER {
        static mut FREQUENCY: c::LARGE_INTEGER = 0;
        static ONCE: Once = Once::new();

        unsafe {
            ONCE.call_once(|| {
                cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
            });
            FREQUENCY
        }
    }

    fn query() -> c::LARGE_INTEGER {
        let mut qpc_value: c::LARGE_INTEGER = 0;
        cvt(unsafe {
            c::QueryPerformanceCounter(&mut qpc_value)
        }).unwrap();
        qpc_value
    }
}
<commit_msg>Move Instant backing type to Duration<commit_after>use cmp::Ordering;
use fmt;
use mem;
use sys::c;
use time::Duration;
use convert::TryInto;
use core::hash::{Hash, Hasher};

const NANOS_PER_SEC: u64 = 1_000_000_000;
const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100;

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub struct Instant {
    t: Duration,
}

#[derive(Copy, Clone)]
pub struct SystemTime {
    t: c::FILETIME,
}

const INTERVALS_TO_UNIX_EPOCH: u64 = 11_644_473_600 * INTERVALS_PER_SEC;

pub const UNIX_EPOCH: SystemTime = SystemTime {
    t: c::FILETIME {
        dwLowDateTime: INTERVALS_TO_UNIX_EPOCH as u32,
        dwHighDateTime: (INTERVALS_TO_UNIX_EPOCH >> 32) as u32,
    },
};

impl Instant {
    pub fn now() -> Instant {
        // High precision timing on windows operates in "Performance Counter"
        // units, as returned by the WINAPI QueryPerformanceCounter function.
        // These relate to seconds by a factor of QueryPerformanceFrequency.
        // In order to keep unit conversions out of normal interval math, we
        // measure in QPC units and immediately convert to nanoseconds.
        perf_counter::PerformanceCounterInstant::now().into()
    }

    pub fn actually_monotonic() -> bool {
        false
    }

    pub const fn zero() -> Instant {
        Instant { t: 0 }
    }

    pub fn sub_instant(&self, other: &Instant) -> Duration {
        // On windows there's a threshold below which we consider two timestamps
        // equivalent due to measurement error. For more details + doc link,
        // check the docs on epsilon.
        let epsilon =
            perf_counter::PerformanceCounterInstant::epsilon();
        if other.t > self.t && other.t - self.t <= epsilon {
            return Duration::new(0, 0)
        }
        self.t.checked_sub(other.t)
              .expect("specified instant was later than self")
    }

    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
        Some(Instant {
            t: self.t.checked_add(*other)?
        })
    }

    pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
        Some(Instant {
            t: self.t.checked_sub(*other)?
        })
    }
}

impl SystemTime {
    pub fn now() -> SystemTime {
        unsafe {
            let mut t: SystemTime = mem::zeroed();
            c::GetSystemTimeAsFileTime(&mut t.t);
            return t
        }
    }

    fn from_intervals(intervals: i64) -> SystemTime {
        SystemTime {
            t: c::FILETIME {
                dwLowDateTime: intervals as c::DWORD,
                dwHighDateTime: (intervals >> 32) as c::DWORD,
            }
        }
    }

    fn intervals(&self) -> i64 {
        (self.t.dwLowDateTime as i64) | ((self.t.dwHighDateTime as i64) << 32)
    }

    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
        let me = self.intervals();
        let other = other.intervals();
        if me >= other {
            Ok(intervals2dur((me - other) as u64))
        } else {
            Err(intervals2dur((other - me) as u64))
        }
    }

    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
        let intervals = self.intervals().checked_add(checked_dur2intervals(other)?)?;
        Some(SystemTime::from_intervals(intervals))
    }

    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
        let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?;
        Some(SystemTime::from_intervals(intervals))
    }
}

impl PartialEq for SystemTime {
    fn eq(&self, other: &SystemTime) -> bool {
        self.intervals() == other.intervals()
    }
}

impl Eq for SystemTime {}

impl PartialOrd for SystemTime {
    fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for SystemTime {
    fn cmp(&self, other: &SystemTime) -> Ordering {
        self.intervals().cmp(&other.intervals())
    }
}

impl fmt::Debug for SystemTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("SystemTime")
         .field("intervals", &self.intervals())
         .finish()
    }
}

impl From<c::FILETIME> for SystemTime {
    fn from(t: c::FILETIME) -> SystemTime {
        SystemTime { t }
    }
}

impl Hash for SystemTime {
    fn hash<H : Hasher>(&self, state: &mut H) {
        self.intervals().hash(state)
    }
}

fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
    dur.as_secs()
        .checked_mul(INTERVALS_PER_SEC)?
        .checked_add(dur.subsec_nanos() as u64 / 100)?
        .try_into()
        .ok()
}

fn intervals2dur(intervals: u64) -> Duration {
    Duration::new(intervals / INTERVALS_PER_SEC,
                  ((intervals % INTERVALS_PER_SEC) * 100) as u32)
}

mod perf_counter {
    use super::{NANOS_PER_SEC};
    use sync::Once;
    use sys_common::mul_div_u64;
    use sys::c;
    use sys::cvt;
    use time::Duration;

    pub struct PerformanceCounterInstant {
        ts: c::LARGE_INTEGER
    }
    impl PerformanceCounterInstant {
        pub fn now() -> Self {
            Self {
                ts: query()
            }
        }

        // Per microsoft docs, the margin of error for cross-thread time comparisons
        // using QueryPerformanceCounter is 1 "tick" -- defined as 1/frequency().
        // Reference: https://docs.microsoft.com/en-us/windows/desktop/SysInfo
        //                   /acquiring-high-resolution-time-stamps
        pub fn epsilon() -> Duration {
            let epsilon = NANOS_PER_SEC / (frequency() as u64);
            Duration::from_nanos(epsilon)
        }
    }
    impl From<PerformanceCounterInstant> for super::Instant {
        fn from(other: PerformanceCounterInstant) -> Self {
            let freq = frequency() as u64;
            let instant_nsec = mul_div_u64(other.ts as u64, NANOS_PER_SEC, freq);
            Self {
                t: Duration::from_nanos(instant_nsec)
            }
        }
    }

    fn frequency() -> c::LARGE_INTEGER {
        static mut FREQUENCY: c::LARGE_INTEGER = 0;
        static ONCE: Once = Once::new();

        unsafe {
            ONCE.call_once(|| {
                cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
            });
            FREQUENCY
        }
    }

    fn query() -> c::LARGE_INTEGER {
        let mut qpc_value: c::LARGE_INTEGER = 0;
        cvt(unsafe {
            c::QueryPerformanceCounter(&mut qpc_value)
        }).unwrap();
        qpc_value
    }
}
<|endoftext|>


<commit_before>//! An [HDL](https://en.wikipedia.org/wiki/Hardware_description_language) embedded in [Rust](https://www.rust-lang.org/).
//!
//! kaze provides an API to describe [`Module`]s composed of [`Signal`]s, which can then be used to generate [Rust simulator code](sim/fn.generate.html) or [verilog modules](verilog/fn.generate.html).
//!
//! kaze's API is designed to be as minimal as possible while still being expressive.
//! It's designed to prevent the user from being able to describe buggy or incorrect hardware as much as possible.
//! This enables a user to hack on designs fearlessly, while the API and generators ensure that these designs are sound.
//!
//! # Usage
//!
//! ```toml
//! [dependencies]
//! kaze = "0.1"
//! ```
//!
//! # Examples
//!
//! ```rust
//! # fn main() -> std::io::Result<()> {
//! use kaze::*;
//!
//! // Create a context, which will contain our module(s)
//! let c = Context::new();
//!
//! // Create a module
//! let inverter = c.module("Inverter");
//! let i = inverter.input("i", 1); // 1-bit input
//! inverter.output("o", !i); // Output inverted input
//!
//! // Generate Rust simulator code
//! sim::generate(inverter, std::io::stdout())?;
//!
//! // Generate verilog code
//! verilog::generate(inverter, std::io::stdout())?;
//! # Ok(())
//! # }
//! ```
//!
//! [`Module`]: ./graph/struct.Module.html
//! [`Signal`]: ./graph/struct.Signal.html

// Must be kept up-to-date with version in Cargo.toml
#![doc(html_root_url = "https://docs.rs/kaze/0.1.3")]

mod code_writer;
mod graph;
pub mod sim;
pub mod verilog;

pub use graph::*;
<commit_msg>Fix Module/Signal links in top-level docs<commit_after>//! An [HDL](https://en.wikipedia.org/wiki/Hardware_description_language) embedded in [Rust](https://www.rust-lang.org/).
//!
//! kaze provides an API to describe [`Module`]s composed of [`Signal`]s, which can then be used to generate [Rust simulator code](sim/fn.generate.html) or [verilog modules](verilog/fn.generate.html).
//!
//! kaze's API is designed to be as minimal as possible while still being expressive.
//! It's designed to prevent the user from being able to describe buggy or incorrect hardware as much as possible.
//! This enables a user to hack on designs fearlessly, while the API and generators ensure that these designs are sound.
//!
//! # Usage
//!
//! ```toml
//! [dependencies]
//! kaze = "0.1"
//! ```
//!
//! # Examples
//!
//! ```rust
//! # fn main() -> std::io::Result<()> {
//! use kaze::*;
//!
//! // Create a context, which will contain our module(s)
//! let c = Context::new();
//!
//! // Create a module
//! let inverter = c.module("Inverter");
//! let i = inverter.input("i", 1); // 1-bit input
//! inverter.output("o", !i); // Output inverted input
//!
//! // Generate Rust simulator code
//! sim::generate(inverter, std::io::stdout())?;
//!
//! // Generate verilog code
//! verilog::generate(inverter, std::io::stdout())?;
//! # Ok(())
//! # }
//! ```
//!
//! [`Module`]: ./struct.Module.html
//! [`Signal`]: ./struct.Signal.html

// Must be kept up-to-date with version in Cargo.toml
#![doc(html_root_url = "https://docs.rs/kaze/0.1.3")]

mod code_writer;
mod graph;
pub mod sim;
pub mod verilog;

pub use graph::*;
<|endoftext|>