<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The style bloom filter is used as an optimization when matching deep
//! descendant selectors.

use dom::{TNode, TElement, UnsafeNode};
use matching::MatchMethods;
use selectors::bloom::BloomFilter;

pub struct StyleBloom {
    /// The bloom filter per se.
    filter: Box<BloomFilter>,

    /// The stack of elements that this bloom filter contains. These unsafe
    /// nodes are guaranteed to be elements.
    ///
    /// Note that the use we do for them is safe, since the data we access from
    /// them is completely read-only during restyling.
    elements: Vec<UnsafeNode>,

    /// A monotonic counter incremented which each reflow in order to invalidate
    /// the bloom filter if appropriate.
    generation: u32,
}

impl StyleBloom {
    pub fn new(generation: u32) -> Self {
        StyleBloom {
            filter: Box::new(BloomFilter::new()),
            elements: vec![],
            generation: generation,
        }
    }

    pub fn filter(&self) -> &BloomFilter {
        &*self.filter
    }

    pub fn generation(&self) -> u32 {
        self.generation
    }

    pub fn maybe_pop<E>(&mut self, element: E)
        where E: TElement + MatchMethods
    {
        if self.elements.last() == Some(&element.as_node().to_unsafe()) {
            self.pop::<E>().unwrap();
        }
    }

    /// Push an element to the bloom filter, knowing that it's a child of the
    /// last element parent.
    pub fn push<E>(&mut self, element: E)
        where E: TElement + MatchMethods,
    {
        if cfg!(debug_assertions) {
            if self.elements.is_empty() {
                assert!(element.parent_element().is_none());
            }
        }
        element.insert_into_bloom_filter(&mut *self.filter);
        self.elements.push(element.as_node().to_unsafe());
    }

    /// Pop the last element in the bloom filter and return it.
    fn pop<E>(&mut self) -> Option<E>
        where E: TElement + MatchMethods,
    {
        let popped =
            self.elements.pop().map(|unsafe_node| {
                let parent = unsafe {
                    E::ConcreteNode::from_unsafe(&unsafe_node)
                };
                parent.as_element().unwrap()
            });
        if let Some(popped) = popped {
            popped.remove_from_bloom_filter(&mut self.filter);
        }

        popped
    }

    fn clear(&mut self) {
        self.filter.clear();
        self.elements.clear();
    }

    fn rebuild<E>(&mut self, mut element: E) -> usize
        where E: TElement + MatchMethods,
    {
        self.clear();

        while let Some(parent) = element.parent_element() {
            parent.insert_into_bloom_filter(&mut *self.filter);
            self.elements.push(parent.as_node().to_unsafe());
            element = parent;
        }

        // Put them in the order we expect, from root to `element`'s parent.
        self.elements.reverse();
        return self.elements.len();
    }

    /// In debug builds, asserts that all the parents of `element` are in the
    /// bloom filter.
    pub fn assert_complete<E>(&self, mut element: E)
        where E: TElement,
    {
        if cfg!(debug_assertions) {
            let mut checked = 0;
            while let Some(parent) = element.parent_element() {
                assert_eq!(parent.as_node().to_unsafe(),
                           self.elements[self.elements.len() - 1 - checked]);
                element = parent;
                checked += 1;
            }
            assert_eq!(checked, self.elements.len());
        }
    }

    /// Insert the parents of an element in the bloom filter, trying to recover
    /// the filter if the last element inserted doesn't match.
    ///
    /// Gets the element depth in the dom, to make it efficient, or if not
    /// provided always rebuilds the filter from scratch.
    ///
    /// Returns the new bloom filter depth.
    pub fn insert_parents_recovering<E>(&mut self,
                                        element: E,
                                        element_depth: Option<usize>,
                                        generation: u32)
                                        -> usize
        where E: TElement,
    {
        // Easy case, we're in a different restyle, or we're empty.
        if self.generation != generation || self.elements.is_empty() {
            self.generation = generation;
            return self.rebuild(element);
        }

        let parent_element = match element.parent_element() {
            Some(parent) => parent,
            None => {
                // Yay, another easy case.
                self.clear();
                return 0;
            }
        };

        let unsafe_parent = parent_element.as_node().to_unsafe();
        if self.elements.last() == Some(&unsafe_parent) {
            // Ta da, cache hit, we're all done.
            return self.elements.len();
        }

        let element_depth = match element_depth {
            Some(depth) => depth,
            // If we don't know the depth of `element`, we'd rather don't try
            // fixing up the bloom filter, since it's quadratic.
            None => {
                return self.rebuild(element);
            }
        };

        // We should've early exited above.
        debug_assert!(element_depth != 0,
                      "We should have already cleared the bloom filter");
        debug_assert!(!self.elements.is_empty(),
                      "How! We should've just rebuilt!");

        // Now the fun begins: We have the depth of the dom and the depth of the
        // last element inserted in the filter, let's try to find a common
        // parent.
        //
        // The current depth, that is, the depth of the last element inserted in
        // the bloom filter, is the number of elements _minus one_, that is: if
        // there's one element, it must be the root -> depth zero.
        let mut current_depth = self.elements.len() - 1;

        // If the filter represents an element too deep in the dom, we need to
        // pop ancestors.
        while current_depth >= element_depth - 1 {
            self.pop::<E>().expect("Emilio is bad at math");
            current_depth -= 1;
        }

        // Now let's try to find a common parent in the bloom filter chain,
        // starting with parent_element.
        let mut common_parent = parent_element;
        let mut common_parent_depth = element_depth - 1;

        // Let's collect the parents we are going to need to insert once we've
        // found the common one.
        let mut parents_to_insert = vec![];

        // If the bloom filter still doesn't have enough elements, the common
        // parent is up in the dom.
        while common_parent_depth > current_depth {
            // TODO(emilio): Seems like we could insert parents here, then
            // reverse the slice.
            parents_to_insert.push(common_parent);
            common_parent =
                common_parent.parent_element().expect("We were lied");
            common_parent_depth -= 1;
        }

        // Now the two depths are the same.
        debug_assert_eq!(common_parent_depth, current_depth);

        // Happy case: The parents match, we only need to push the ancestors
        // we've collected and we'll never enter in this loop.
        //
        // Not-so-happy case: Parent's don't match, so we need to keep going up
        // until we find a common ancestor.
        while *self.elements.last().unwrap() != common_parent.as_node().to_unsafe() {
            parents_to_insert.push(common_parent);
            common_parent =
                common_parent.parent_element().expect("We were lied again?");
            self.pop::<E>().unwrap();
        }

        // Now the parents match, so insert the stack of elements we have been
        // collecting so far.
        for parent in parents_to_insert.into_iter().rev() {
            self.push(parent);
        }

        debug_assert_eq!(self.elements.len(), element_depth);

        // We're done! Easy.
        return self.elements.len();
    }
}
<commit_msg>style: Don't pop too much in the bloom filter.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The style bloom filter is used as an optimization when matching deep
//! descendant selectors.

use dom::{TNode, TElement, UnsafeNode};
use matching::MatchMethods;
use selectors::bloom::BloomFilter;

pub struct StyleBloom {
    /// The bloom filter per se.
    filter: Box<BloomFilter>,

    /// The stack of elements that this bloom filter contains. These unsafe
    /// nodes are guaranteed to be elements.
    ///
    /// Note that the use we do for them is safe, since the data we access from
    /// them is completely read-only during restyling.
    elements: Vec<UnsafeNode>,

    /// A monotonic counter incremented which each reflow in order to invalidate
    /// the bloom filter if appropriate.
    generation: u32,
}

impl StyleBloom {
    pub fn new(generation: u32) -> Self {
        StyleBloom {
            filter: Box::new(BloomFilter::new()),
            elements: vec![],
            generation: generation,
        }
    }

    pub fn filter(&self) -> &BloomFilter {
        &*self.filter
    }

    pub fn generation(&self) -> u32 {
        self.generation
    }

    pub fn maybe_pop<E>(&mut self, element: E)
        where E: TElement + MatchMethods
    {
        if self.elements.last() == Some(&element.as_node().to_unsafe()) {
            self.pop::<E>().unwrap();
        }
    }

    /// Push an element to the bloom filter, knowing that it's a child of the
    /// last element parent.
    pub fn push<E>(&mut self, element: E)
        where E: TElement + MatchMethods,
    {
        if cfg!(debug_assertions) {
            if self.elements.is_empty() {
                assert!(element.parent_element().is_none());
            }
        }
        element.insert_into_bloom_filter(&mut *self.filter);
        self.elements.push(element.as_node().to_unsafe());
    }

    /// Pop the last element in the bloom filter and return it.
    fn pop<E>(&mut self) -> Option<E>
        where E: TElement + MatchMethods,
    {
        let popped =
            self.elements.pop().map(|unsafe_node| {
                let parent = unsafe {
                    E::ConcreteNode::from_unsafe(&unsafe_node)
                };
                parent.as_element().unwrap()
            });
        if let Some(popped) = popped {
            popped.remove_from_bloom_filter(&mut self.filter);
        }

        popped
    }

    fn clear(&mut self) {
        self.filter.clear();
        self.elements.clear();
    }

    fn rebuild<E>(&mut self, mut element: E) -> usize
        where E: TElement + MatchMethods,
    {
        self.clear();

        while let Some(parent) = element.parent_element() {
            parent.insert_into_bloom_filter(&mut *self.filter);
            self.elements.push(parent.as_node().to_unsafe());
            element = parent;
        }

        // Put them in the order we expect, from root to `element`'s parent.
        self.elements.reverse();
        return self.elements.len();
    }

    /// In debug builds, asserts that all the parents of `element` are in the
    /// bloom filter.
    pub fn assert_complete<E>(&self, mut element: E)
        where E: TElement,
    {
        if cfg!(debug_assertions) {
            let mut checked = 0;
            while let Some(parent) = element.parent_element() {
                assert_eq!(parent.as_node().to_unsafe(),
                           self.elements[self.elements.len() - 1 - checked]);
                element = parent;
                checked += 1;
            }
            assert_eq!(checked, self.elements.len());
        }
    }

    /// Insert the parents of an element in the bloom filter, trying to recover
    /// the filter if the last element inserted doesn't match.
    ///
    /// Gets the element depth in the dom, to make it efficient, or if not
    /// provided always rebuilds the filter from scratch.
    ///
    /// Returns the new bloom filter depth.
    pub fn insert_parents_recovering<E>(&mut self,
                                        element: E,
                                        element_depth: Option<usize>,
                                        generation: u32)
                                        -> usize
        where E: TElement,
    {
        // Easy case, we're in a different restyle, or we're empty.
        if self.generation != generation || self.elements.is_empty() {
            self.generation = generation;
            return self.rebuild(element);
        }

        let parent_element = match element.parent_element() {
            Some(parent) => parent,
            None => {
                // Yay, another easy case.
                self.clear();
                return 0;
            }
        };

        let unsafe_parent = parent_element.as_node().to_unsafe();
        if self.elements.last() == Some(&unsafe_parent) {
            // Ta da, cache hit, we're all done.
            return self.elements.len();
        }

        let element_depth = match element_depth {
            Some(depth) => depth,
            // If we don't know the depth of `element`, we'd rather don't try
            // fixing up the bloom filter, since it's quadratic.
            None => {
                return self.rebuild(element);
            }
        };

        // We should've early exited above.
        debug_assert!(element_depth != 0,
                      "We should have already cleared the bloom filter");
        debug_assert!(!self.elements.is_empty(),
                      "How! We should've just rebuilt!");

        // Now the fun begins: We have the depth of the dom and the depth of the
        // last element inserted in the filter, let's try to find a common
        // parent.
        //
        // The current depth, that is, the depth of the last element inserted in
        // the bloom filter, is the number of elements _minus one_, that is: if
        // there's one element, it must be the root -> depth zero.
        let mut current_depth = self.elements.len() - 1;

        // If the filter represents an element too deep in the dom, we need to
        // pop ancestors.
        while current_depth > element_depth - 1 {
            self.pop::<E>().expect("Emilio is bad at math");
            current_depth -= 1;
        }

        // Now let's try to find a common parent in the bloom filter chain,
        // starting with parent_element.
        let mut common_parent = parent_element;
        let mut common_parent_depth = element_depth - 1;

        // Let's collect the parents we are going to need to insert once we've
        // found the common one.
        let mut parents_to_insert = vec![];

        // If the bloom filter still doesn't have enough elements, the common
        // parent is up in the dom.
        while common_parent_depth > current_depth {
            // TODO(emilio): Seems like we could insert parents here, then
            // reverse the slice.
            parents_to_insert.push(common_parent);
            common_parent =
                common_parent.parent_element().expect("We were lied");
            common_parent_depth -= 1;
        }

        // Now the two depths are the same.
        debug_assert_eq!(common_parent_depth, current_depth);

        // Happy case: The parents match, we only need to push the ancestors
        // we've collected and we'll never enter in this loop.
        //
        // Not-so-happy case: Parent's don't match, so we need to keep going up
        // until we find a common ancestor.
        while *self.elements.last().unwrap() != common_parent.as_node().to_unsafe() {
            parents_to_insert.push(common_parent);
            common_parent =
                common_parent.parent_element().expect("We were lied again?");
            self.pop::<E>().unwrap();
        }

        // Now the parents match, so insert the stack of elements we have been
        // collecting so far.
        for parent in parents_to_insert.into_iter().rev() {
            self.push(parent);
        }

        debug_assert_eq!(self.elements.len(), element_depth);

        // We're done! Easy.
        return self.elements.len();
    }
}
<|endoftext|>


<commit_before>use crate::code_pair_put_back::CodePairPutBack;

use crate::{CodePair, DxfError, DxfResult};

use std::io::Read;

const FILE_HEADER_LENGTH: usize = 14;
const FILE_LENGTH_OFFSET: usize = 2;
const IMAGE_DATA_OFFSET_OFFSET: usize = 10;

const BITMAP_HEADER_PALETTE_COUNT_OFFSET: usize = 32;

pub(crate) fn read_thumbnail<T>(
    iter: &mut CodePairPutBack<T>,
) -> DxfResult<Option<image::DynamicImage>>
where
    T: Read,
{
    match read_thumbnail_bytes_from_code_pairs(iter)? {
        Some(mut data) => {
            if update_thumbnail_data_offset_in_situ(&mut data)? {
                read_thumbnail_from_bytes(&data)
            } else {
                Ok(None)
            }
        }
        None => Ok(None),
    }
}

fn read_thumbnail_bytes_from_code_pairs<T>(
    iter: &mut CodePairPutBack<T>,
) -> DxfResult<Option<Vec<u8>>>
where
    T: Read,
{
    // get the length; we don't really care about this since we'll just read whatever's there
    let _length = match iter.next() {
        Some(Ok(pair @ CodePair { code: 0, .. })) => {
            // likely 0/ENDSEC
            iter.put_back(Ok(pair));
            return Ok(None);
        }
        Some(Ok(pair @ CodePair { code: 90, .. })) => pair.assert_i32()? as usize,
        Some(Ok(pair)) => {
            return Err(DxfError::UnexpectedCode(pair.code, pair.offset));
        }
        Some(Err(e)) => return Err(e),
        None => return Ok(None),
    };

    // prepend the BMP header that always seems to be missing from DXF files
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length (set below)
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // image data offset (calculated elsewhere)
    ];

    // read the hex data
    loop {
        match iter.next() {
            Some(Ok(pair @ CodePair { code: 0, .. })) => {
                // likely 0/ENDSEC
                iter.put_back(Ok(pair));
                break;
            }
            Some(Ok(pair @ CodePair { code: 310, .. })) => {
                let line_data = pair.assert_binary()?;
                for b in line_data {
                    data.push(b);
                }
            }
            Some(Ok(pair)) => {
                return Err(DxfError::UnexpectedCode(pair.code, pair.offset));
            }
            Some(Err(e)) => return Err(e),
            None => break,
        }
    }

    let file_length = data.len();
    set_i32(&mut data, FILE_LENGTH_OFFSET, file_length as i32)?;
    Ok(Some(data))
}

fn update_thumbnail_data_offset_in_situ(data: &mut Vec<u8>) -> DxfResult<bool> {
    // calculate the image data offset
    let dib_header_size = get_i32(&data, FILE_HEADER_LENGTH)? as usize;

    // calculate the palette size
    let palette_size = if dib_header_size >= BITMAP_HEADER_PALETTE_COUNT_OFFSET + 4 {
        let palette_color_count = get_u32(
            &data,
            FILE_HEADER_LENGTH + BITMAP_HEADER_PALETTE_COUNT_OFFSET,
        )? as usize;
        palette_color_count * 4 // always 4 bytes: BGRA
    } else {
        return Ok(false);
    };

    // set the image data offset
    let image_data_offset = FILE_HEADER_LENGTH + dib_header_size + palette_size;
    set_i32(data, IMAGE_DATA_OFFSET_OFFSET, image_data_offset as i32)?;

    Ok(true)
}

#[test]
fn set_thumbnail_offset_for_bitmapinfoheader_non_palette() {
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length; not needed for this test
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // the image data offset that will be filled in
        0x28, 0x00, 0x00, 0x00, // BITMAPINFOHEADER length
        0x00, 0x00, 0x00, 0x00, // width (not needed)
        0x00, 0x00, 0x00, 0x00, // height (not needed)
        0x00, 0x00, // color planes (not needed)
        0x00, 0x00, // bits per pixel (not needed)
        0x00, 0x00, 0x00, 0x00, // compression (not needed)
        0x00, 0x00, 0x00, 0x00, // image size (not needed)
        0x00, 0x00, 0x00, 0x00, // horizontal resolution (not needed)
        0x00, 0x00, 0x00, 0x00, // vertical resolution (not needed)
        0x00, 0x00, 0x00,
        0x00, // color palette count (0 means default of 2^n)
              // rest of struct not needed
    ];
    assert!(update_thumbnail_data_offset_in_situ(&mut data).unwrap());
    assert_eq!(0x36, get_i32(&data, IMAGE_DATA_OFFSET_OFFSET).unwrap());
}

#[test]
fn set_thumbnail_offset_for_bitmapinfoheader_palette_256() {
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length; not needed for this test
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // the image data offset that will be filled in
        0x28, 0x00, 0x00, 0x00, // BITMAPINFOHEADER length
        0x00, 0x00, 0x00, 0x00, // width (not needed)
        0x00, 0x00, 0x00, 0x00, // height (not needed)
        0x00, 0x00, // color planes (not needed)
        0x00, 0x00, // bits per pixel (not needed)
        0x00, 0x00, 0x00, 0x00, // compression (not needed)
        0x00, 0x00, 0x00, 0x00, // image size (not needed)
        0x00, 0x00, 0x00, 0x00, // horizontal resolution (not needed)
        0x00, 0x00, 0x00, 0x00, // vertical resolution (not needed)
        0xFF, 0x00, 0x00,
        0x00, // color palette count (0 means default of 2^n)
              // rest of struct not needed
    ];
    assert!(update_thumbnail_data_offset_in_situ(&mut data).unwrap());
    assert_eq!(0x0432, get_i32(&data, IMAGE_DATA_OFFSET_OFFSET).unwrap());
}

#[test]
fn set_thumbnail_offset_for_bitmapv4header_non_palette() {
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length; not needed for this test
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // the image data offset that will be filled in
        0x6C, 0x00, 0x00, 0x00, // BITMAPV4HEADER length
        0x00, 0x00, 0x00, 0x00, // width (not needed)
        0x00, 0x00, 0x00, 0x00, // height (not needed)
        0x00, 0x00, // color planes (not needed)
        0x00, 0x00, // bits per pixel (not needed)
        0x00, 0x00, 0x00, 0x00, // compression (not needed)
        0x00, 0x00, 0x00, 0x00, // image size (not needed)
        0x00, 0x00, 0x00, 0x00, // horizontal resolution (not needed)
        0x00, 0x00, 0x00, 0x00, // vertical resolution (not needed)
        0x00, 0x00, 0x00,
        0x00, // color palette count (0 means default of 2^n)
              // rest of struct not needed
    ];
    assert!(update_thumbnail_data_offset_in_situ(&mut data).unwrap());
    assert_eq!(0x7A, get_i32(&data, IMAGE_DATA_OFFSET_OFFSET).unwrap());
}

#[test]
fn set_thumbnail_offset_for_bitmapv4header_palette_256() {
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length; not needed for this test
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // the image data offset that will be filled in
        0x6C, 0x00, 0x00, 0x00, // BITMAPV4HEADER length
        0x00, 0x00, 0x00, 0x00, // width (not needed)
        0x00, 0x00, 0x00, 0x00, // height (not needed)
        0x00, 0x00, // color planes (not needed)
        0x00, 0x00, // bits per pixel (not needed)
        0x00, 0x00, 0x00, 0x00, // compression (not needed)
        0x00, 0x00, 0x00, 0x00, // image size (not needed)
        0x00, 0x00, 0x00, 0x00, // horizontal resolution (not needed)
        0x00, 0x00, 0x00, 0x00, // vertical resolution (not needed)
        0xFF, 0x00, 0x00,
        0x00, // color palette count (0 means default of 2^n)
              // rest of struct not needed
    ];
    assert!(update_thumbnail_data_offset_in_situ(&mut data).unwrap());
    assert_eq!(0x0476, get_i32(&data, IMAGE_DATA_OFFSET_OFFSET).unwrap());
}

fn read_thumbnail_from_bytes(data: &[u8]) -> DxfResult<Option<image::DynamicImage>> {
    let image = image::load_from_memory(&data)?;
    Ok(Some(image))
}

fn get_i32(data: &[u8], offset: usize) -> DxfResult<i32> {
    let expected_length = offset + 4;
    if data.len() < expected_length {
        return Err(DxfError::UnexpectedEndOfInput);
    }

    let value = data[offset] as i32
        + ((data[offset + 1] as i32) << 8)
        + ((data[offset + 2] as i32) << 16)
        + ((data[offset + 3] as i32) << 24);
    Ok(value)
}

#[test]
fn test_get_i32() {
    let data: Vec<u8> = vec![0x00, 0x78, 0x56, 0x34, 0x12, 0x00];
    let value = get_i32(&data, 1).unwrap();
    assert_eq!(0x12345678, value);
}

fn get_u32(data: &[u8], offset: usize) -> DxfResult<u32> {
    let expected_length = offset + 4;
    if data.len() < expected_length {
        return Err(DxfError::UnexpectedEndOfInput);
    }

    let value = data[offset] as u32
        + ((data[offset + 1] as u32) << 8)
        + ((data[offset + 2] as u32) << 16)
        + ((data[offset + 3] as u32) << 24);
    Ok(value)
}

#[test]
fn test_get_u32() {
    let data: Vec<u8> = vec![0x00, 0x78, 0x56, 0x34, 0x12, 0x00];
    let value = get_u32(&data, 1).unwrap();
    assert_eq!(0x12345678, value);
}

fn set_i32(data: &mut Vec<u8>, offset: usize, value: i32) -> DxfResult<()> {
    let expected_length = offset + 4;
    if data.len() < expected_length {
        return Err(DxfError::UnexpectedEndOfInput);
    }

    data[offset] = value as u8;
    data[offset + 1] = (value >> 8) as u8;
    data[offset + 2] = (value >> 16) as u8;
    data[offset + 3] = (value >> 24) as u8;
    Ok(())
}

#[test]
fn test_set_i32() {
    let mut data = vec![0x00u8; 6];
    set_i32(&mut data, 1, 0x12345678).unwrap();
    assert_eq!(vec![0x00, 0x78, 0x56, 0x34, 0x12, 0x00], data);
}
<commit_msg>test against 256 color palette<commit_after>use crate::code_pair_put_back::CodePairPutBack;

use crate::{CodePair, DxfError, DxfResult};

use std::io::Read;

const FILE_HEADER_LENGTH: usize = 14;
const FILE_LENGTH_OFFSET: usize = 2;
const IMAGE_DATA_OFFSET_OFFSET: usize = 10;

const BITMAP_HEADER_PALETTE_COUNT_OFFSET: usize = 32;

pub(crate) fn read_thumbnail<T>(
    iter: &mut CodePairPutBack<T>,
) -> DxfResult<Option<image::DynamicImage>>
where
    T: Read,
{
    match read_thumbnail_bytes_from_code_pairs(iter)? {
        Some(mut data) => {
            if update_thumbnail_data_offset_in_situ(&mut data)? {
                read_thumbnail_from_bytes(&data)
            } else {
                Ok(None)
            }
        }
        None => Ok(None),
    }
}

fn read_thumbnail_bytes_from_code_pairs<T>(
    iter: &mut CodePairPutBack<T>,
) -> DxfResult<Option<Vec<u8>>>
where
    T: Read,
{
    // get the length; we don't really care about this since we'll just read whatever's there
    let _length = match iter.next() {
        Some(Ok(pair @ CodePair { code: 0, .. })) => {
            // likely 0/ENDSEC
            iter.put_back(Ok(pair));
            return Ok(None);
        }
        Some(Ok(pair @ CodePair { code: 90, .. })) => pair.assert_i32()? as usize,
        Some(Ok(pair)) => {
            return Err(DxfError::UnexpectedCode(pair.code, pair.offset));
        }
        Some(Err(e)) => return Err(e),
        None => return Ok(None),
    };

    // prepend the BMP header that always seems to be missing from DXF files
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length (set below)
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // image data offset (calculated elsewhere)
    ];

    // read the hex data
    loop {
        match iter.next() {
            Some(Ok(pair @ CodePair { code: 0, .. })) => {
                // likely 0/ENDSEC
                iter.put_back(Ok(pair));
                break;
            }
            Some(Ok(pair @ CodePair { code: 310, .. })) => {
                let line_data = pair.assert_binary()?;
                for b in line_data {
                    data.push(b);
                }
            }
            Some(Ok(pair)) => {
                return Err(DxfError::UnexpectedCode(pair.code, pair.offset));
            }
            Some(Err(e)) => return Err(e),
            None => break,
        }
    }

    let file_length = data.len();
    set_i32(&mut data, FILE_LENGTH_OFFSET, file_length as i32)?;
    Ok(Some(data))
}

fn update_thumbnail_data_offset_in_situ(data: &mut Vec<u8>) -> DxfResult<bool> {
    // calculate the image data offset
    let dib_header_size = get_i32(&data, FILE_HEADER_LENGTH)? as usize;

    // calculate the palette size
    let palette_size = if dib_header_size >= BITMAP_HEADER_PALETTE_COUNT_OFFSET + 4 {
        let palette_color_count = get_u32(
            &data,
            FILE_HEADER_LENGTH + BITMAP_HEADER_PALETTE_COUNT_OFFSET,
        )? as usize;
        palette_color_count * 4 // always 4 bytes: BGRA
    } else {
        return Ok(false);
    };

    // set the image data offset
    let image_data_offset = FILE_HEADER_LENGTH + dib_header_size + palette_size;
    set_i32(data, IMAGE_DATA_OFFSET_OFFSET, image_data_offset as i32)?;

    Ok(true)
}

#[test]
fn set_thumbnail_offset_for_bitmapinfoheader_non_palette() {
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length; not needed for this test
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // the image data offset that will be filled in
        0x28, 0x00, 0x00, 0x00, // BITMAPINFOHEADER length
        0x00, 0x00, 0x00, 0x00, // width (not needed)
        0x00, 0x00, 0x00, 0x00, // height (not needed)
        0x00, 0x00, // color planes (not needed)
        0x00, 0x00, // bits per pixel (not needed)
        0x00, 0x00, 0x00, 0x00, // compression (not needed)
        0x00, 0x00, 0x00, 0x00, // image size (not needed)
        0x00, 0x00, 0x00, 0x00, // horizontal resolution (not needed)
        0x00, 0x00, 0x00, 0x00, // vertical resolution (not needed)
        0x00, 0x00, 0x00,
        0x00, // color palette count (0 means default of 2^n)
              // rest of struct not needed
    ];
    assert!(update_thumbnail_data_offset_in_situ(&mut data).unwrap());
    assert_eq!(0x36, get_i32(&data, IMAGE_DATA_OFFSET_OFFSET).unwrap());
}

#[test]
fn set_thumbnail_offset_for_bitmapinfoheader_palette_256() {
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length; not needed for this test
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // the image data offset that will be filled in
        0x28, 0x00, 0x00, 0x00, // BITMAPINFOHEADER length
        0x00, 0x00, 0x00, 0x00, // width (not needed)
        0x00, 0x00, 0x00, 0x00, // height (not needed)
        0x00, 0x00, // color planes (not needed)
        0x00, 0x00, // bits per pixel (not needed)
        0x00, 0x00, 0x00, 0x00, // compression (not needed)
        0x00, 0x00, 0x00, 0x00, // image size (not needed)
        0x00, 0x00, 0x00, 0x00, // horizontal resolution (not needed)
        0x00, 0x00, 0x00, 0x00, // vertical resolution (not needed)
        0x00, 0x01, 0x00,
        0x00, // color palette count (0 means default of 2^n)
              // rest of struct not needed
    ];
    assert!(update_thumbnail_data_offset_in_situ(&mut data).unwrap());
    assert_eq!(0x0436, get_i32(&data, IMAGE_DATA_OFFSET_OFFSET).unwrap());
}

#[test]
fn set_thumbnail_offset_for_bitmapv4header_non_palette() {
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length; not needed for this test
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // the image data offset that will be filled in
        0x6C, 0x00, 0x00, 0x00, // BITMAPV4HEADER length
        0x00, 0x00, 0x00, 0x00, // width (not needed)
        0x00, 0x00, 0x00, 0x00, // height (not needed)
        0x00, 0x00, // color planes (not needed)
        0x00, 0x00, // bits per pixel (not needed)
        0x00, 0x00, 0x00, 0x00, // compression (not needed)
        0x00, 0x00, 0x00, 0x00, // image size (not needed)
        0x00, 0x00, 0x00, 0x00, // horizontal resolution (not needed)
        0x00, 0x00, 0x00, 0x00, // vertical resolution (not needed)
        0x00, 0x00, 0x00,
        0x00, // color palette count (0 means default of 2^n)
              // rest of struct not needed
    ];
    assert!(update_thumbnail_data_offset_in_situ(&mut data).unwrap());
    assert_eq!(0x7A, get_i32(&data, IMAGE_DATA_OFFSET_OFFSET).unwrap());
}

#[test]
fn set_thumbnail_offset_for_bitmapv4header_palette_256() {
    let mut data: Vec<u8> = vec![
        b'B', b'M', // magic number
        0x00, 0x00, 0x00, 0x00, // file length; not needed for this test
        0x00, 0x00, // reserved
        0x00, 0x00, // reserved
        0x00, 0x00, 0x00, 0x00, // the image data offset that will be filled in
        0x6C, 0x00, 0x00, 0x00, // BITMAPV4HEADER length
        0x00, 0x00, 0x00, 0x00, // width (not needed)
        0x00, 0x00, 0x00, 0x00, // height (not needed)
        0x00, 0x00, // color planes (not needed)
        0x00, 0x00, // bits per pixel (not needed)
        0x00, 0x00, 0x00, 0x00, // compression (not needed)
        0x00, 0x00, 0x00, 0x00, // image size (not needed)
        0x00, 0x00, 0x00, 0x00, // horizontal resolution (not needed)
        0x00, 0x00, 0x00, 0x00, // vertical resolution (not needed)
        0x00, 0x01, 0x00,
        0x00, // color palette count (0 means default of 2^n)
              // rest of struct not needed
    ];
    assert!(update_thumbnail_data_offset_in_situ(&mut data).unwrap());
    assert_eq!(0x047A, get_i32(&data, IMAGE_DATA_OFFSET_OFFSET).unwrap());
}

fn read_thumbnail_from_bytes(data: &[u8]) -> DxfResult<Option<image::DynamicImage>> {
    let image = image::load_from_memory(&data)?;
    Ok(Some(image))
}

fn get_i32(data: &[u8], offset: usize) -> DxfResult<i32> {
    let expected_length = offset + 4;
    if data.len() < expected_length {
        return Err(DxfError::UnexpectedEndOfInput);
    }

    let value = data[offset] as i32
        + ((data[offset + 1] as i32) << 8)
        + ((data[offset + 2] as i32) << 16)
        + ((data[offset + 3] as i32) << 24);
    Ok(value)
}

#[test]
fn test_get_i32() {
    let data: Vec<u8> = vec![0x00, 0x78, 0x56, 0x34, 0x12, 0x00];
    let value = get_i32(&data, 1).unwrap();
    assert_eq!(0x12345678, value);
}

fn get_u32(data: &[u8], offset: usize) -> DxfResult<u32> {
    let expected_length = offset + 4;
    if data.len() < expected_length {
        return Err(DxfError::UnexpectedEndOfInput);
    }

    let value = data[offset] as u32
        + ((data[offset + 1] as u32) << 8)
        + ((data[offset + 2] as u32) << 16)
        + ((data[offset + 3] as u32) << 24);
    Ok(value)
}

#[test]
fn test_get_u32() {
    let data: Vec<u8> = vec![0x00, 0x78, 0x56, 0x34, 0x12, 0x00];
    let value = get_u32(&data, 1).unwrap();
    assert_eq!(0x12345678, value);
}

fn set_i32(data: &mut Vec<u8>, offset: usize, value: i32) -> DxfResult<()> {
    let expected_length = offset + 4;
    if data.len() < expected_length {
        return Err(DxfError::UnexpectedEndOfInput);
    }

    data[offset] = value as u8;
    data[offset + 1] = (value >> 8) as u8;
    data[offset + 2] = (value >> 16) as u8;
    data[offset + 3] = (value >> 24) as u8;
    Ok(())
}

#[test]
fn test_set_i32() {
    let mut data = vec![0x00u8; 6];
    set_i32(&mut data, 1, 0x12345678).unwrap();
    assert_eq!(vec![0x00, 0x78, 0x56, 0x34, 0x12, 0x00], data);
}
<|endoftext|>


<commit_before>/// The tokenizer for the query interpreter

use error::*;

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    unimplemented!()
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Rc::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Rc::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Rc::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    quickcheck! {
        fn test_array_index(i: i64) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<commit_msg>Add Token type<commit_after>/// The tokenizer for the query interpreter

use error::*;
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub enum Token {
    Identifier {
        ident: String,
        next: Option<Rc<Token>>
    },

    Index {
        idx: i64,
        next: Option<Rc<Token>>
    }
}

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    unimplemented!()
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Rc::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Rc::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Rc::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    quickcheck! {
        fn test_array_index(i: i64) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<|endoftext|>


<commit_before>//! The simplest possible implementation of the TimeSteward API.
//!
//! This implementation is unusably slow on large simulations. Its main use is to cross-check with other TimeSteward implementations to make sure they are implementing the API correctly.
//!
//!

use super::{DeterministicRandomId, SiphashIdGenerator, RowId, ColumnId, FieldId, PredictorId, Column, ExtendedTime, StewardRc,
             Basics, FieldRc, TimeSteward, FiatEventOperationError, ValidSince, PredictorFn, TimeStewardSettings, Accessor};
use std::collections::{HashMap, BTreeMap};
use std::hash::Hash;
// use std::collections::Bound::{Included, Excluded, Unbounded};
use std::any::Any;
use std::cmp::max;
use std::borrow::Borrow;
use std::rc::Rc;
use std::marker::PhantomData;

#[derive (Clone)]
pub struct Steward<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  Steward0,
  Steward1,
  PhantomData <B::Constants>
);
pub struct Snapshot<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  <Steward0 as TimeSteward <B>>::Snapshot,
  <Steward1 as TimeSteward <B>>::Snapshot,
);
pub struct Settings <B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  <Steward0 as TimeSteward <B>>::Settings,
  <Steward1 as TimeSteward <B>>::Settings,
);

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > super::Accessor<B> for Snapshot<B, Steward0, Steward1> {
  //macro_rules! forward_snapshot_method ($method: ident ($self, $($argument_name: ident: $argument_type:ty),*)->$return_type:ty
  // TODO: forward all the methods properly
  // and check equality by serialization
  fn generic_data_and_extended_last_change (&self, id: FieldId)->Option <(& FieldRc, & ExtendedTime <B>)> {
    match (
      self.0.generic_data_and_extended_last_change (id),
      self.1.generic_data_and_extended_last_change (id)
    ) {
      (None, None) => None,
      //we cannot actually check whether the values are the same, so just use one of them
      (Some (value_0), Some (value_1)) => Some (value_0),
      //however, we CAN tell the difference between something and nothing
      _=> panic! ("One snapshot returned a value and the other didn't; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types")
    }
  }
  fn constants(&self) -> &B::Constants {
    //constants methods are usually implemented trivially; we don't bother checking them.
    //Since the user only gives you one set of constants, it's hard to return a wrong value
    self.0.constants()
  }
  fn unsafe_now(&self) -> &B::Time {
    let result = (self.0.unsafe_now(), self.1.unsafe_now());
    assert! (result.0 == result.1, "Snapshots returned different times; this is an egregious bug!");
    result.0
  }
}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > super::MomentaryAccessor<B> for Snapshot<B, Steward0, Steward1> {}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > super::Snapshot<B> for Snapshot<B, Steward0, Steward1> {
  fn num_fields(&self) -> usize {
    assert_eq!(self.0.num_fields(), self.1.num_fields());
    self.0.num_fields()
  }
}/*
use std::collections::hash_set;
pub struct SnapshotIter <'a, B: Basics, Steward0: TimeSteward<B> + 'a, Steward1: TimeSteward<B> + 'a>
where & 'a Steward0::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>
{
  set: hash_set::HashSet <FieldId>,
  iter: hash_set::Iter <'a, FieldId>,
  snapshot: & 'a Snapshot <B, Steward0, Steward1>,
}
impl <'a, B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B>> Iterator for SnapshotIter<'a, B, Steward0, Steward1>
where & 'a Steward0::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>> {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  fn next (&mut self)->Option <Self::Item> {
    (self. iter).next().map (| id | (id.clone(), (self. snapshot).generic_data_and_extended_last_change (id.clone()).expect ("the snapshot thinks a FieldId exists when it doesn't")))
  }
  fn size_hint (&self)->(usize, Option <usize>) {self. iter.size_hint()}
}
impl <'a, B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B>> IntoIterator for & 'a Snapshot <B, Steward0, Steward1>
where & 'a Steward0::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>,

 {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  type IntoIter = SnapshotIter <'a, B, Steward0, Steward1>;
  fn into_iter (self)->Self::IntoIter {
    let mut field_ids = hash_set::HashSet::new();
    for entry in (& self.0) {
      field_ids.insert (entry.0.clone());
    }
    for entry in (& self.0) {
      let redundant =!field_ids.insert (entry.0.clone());
      assert!(redundant, "field existed in Steward1 snapshot but not Steward0 snapshot: {:?}", entry.0.clone());
    }
    unimplemented!()//SnapshotIter {set: field_ids, iter: field_ids.iter(), snapshot: self}
  }
}
*/
//TODO: implement snapshot iterating

/*
//TODO: should we just require PredictorFn to implement Clone?
#[derive (Serialize, Deserialize)]
struct ShareablePredictorFn <B: Basics, P: PredictorFn <B>> (StewardRc <P>, PhantomData <B>);
impl <B: Basics, P: PredictorFn <B>> PredictorFn <B> for ShareablePredictorFn <B, P> {
  fn call <PA: super::PredictorAccessor <B>> (&self, accessor: &mut PA, id: RowId) {
    self.0.call (accessor, id);
  }
}
// explicitly implement Clone to work around [a compiler weakness](https://github.com/rust-lang/rust/issues/26925).
impl<B: Basics> Clone for DynamicPredictor<B> {
  fn clone(&self) -> Self {
    DynamicPredictor {
      predictor_id: self.predictor_id,
      column_id: self.column_id,
      function: self.function.clone(),
      _marker: PhantomData,
    }
  }
}
*/

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > TimeStewardSettings <B> for Settings <B, Steward0, Steward1> {
  fn new()->Self {
    Settings (<Steward0::Settings as TimeStewardSettings <B>>::new(), <Steward1::Settings as TimeStewardSettings <B>>::new())
  }
  fn insert_predictor <P: PredictorFn <B>> (&mut self, predictor_id: PredictorId, column_id: ColumnId, function: P) {
    //let function = ShareablePredictorFn::<B, P> (StewardRc::new (function), PhantomData);
    self.0.insert_predictor (predictor_id, column_id, function.clone());
    self.1.insert_predictor (predictor_id, column_id, function);
  }
}

impl<B: Basics, Steward0: TimeSteward<B> , Steward1: TimeSteward<B> > TimeSteward<B> for Steward<B, Steward0, Steward1> {
  type Snapshot = Snapshot<B, Steward0, Steward1>;
  type Settings = Settings<B, Steward0, Steward1>;

  fn valid_since(&self) -> ValidSince<B::Time> {
    max (self.0.valid_since(), self.1.valid_since())
  }
  fn new_empty(constants: B::Constants, settings: Self::Settings) -> Self {
    Steward (
      TimeSteward::new_empty (constants.clone(), settings.0),
      TimeSteward::new_empty (constants, settings.1),
      PhantomData,
    )
  }

  fn from_snapshot<'a, S: super::Snapshot<B>>(snapshot: & 'a S,
                                              settings: Self::Settings)
                                              -> Self
                                              where & 'a S: IntoIterator <Item = super::SnapshotEntry <'a, B>> {
    Steward (
      Steward0::from_snapshot (snapshot, settings.0),
      Steward1::from_snapshot (snapshot, settings.1),
      PhantomData,
    )
  }
  fn insert_fiat_event <E: super::EventFn <B>> (&mut self,
                       time: B::Time,
                       id: DeterministicRandomId,
                       event: E)
                       -> Result<(), FiatEventOperationError> {
    if self.valid_since() > time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match (
      self.0.insert_fiat_event (time.clone(), id, event.clone()),
      self.1.insert_fiat_event (time, id, event)
    ){
      (Ok (()), Ok (())) => Ok (()),
      (Err (FiatEventOperationError::InvalidTime),_) => panic!("Steward0 returned InvalidTime after its own ValidSince"),
      (_,Err (FiatEventOperationError::InvalidTime)) => panic!("Steward1 returned InvalidTime after its own ValidSince"),
      (Err (FiatEventOperationError::InvalidInput),Err (FiatEventOperationError::InvalidInput)) => Err (FiatEventOperationError::InvalidInput),
      _=> panic!("stewards returned different results for insert_fiat_event; I believe this is ALWAYS a bug in one of the stewards (that is, it cannot be caused by invalid input)"),
    }
  }
  fn erase_fiat_event(&mut self,
                      time: &B::Time,
                      id: DeterministicRandomId)
                      -> Result<(), FiatEventOperationError> {
    if self.valid_since() > *time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match (
      self.0.erase_fiat_event (time, id),
      self.1.erase_fiat_event (time, id)
    ){
      (Ok (()), Ok (())) => Ok (()),
      (Err (FiatEventOperationError::InvalidTime),_) => panic!("Steward0 returned InvalidTime after its own ValidSince"),
      (_,Err (FiatEventOperationError::InvalidTime)) => panic!("Steward1 returned InvalidTime after its own ValidSince"),
      (Err (FiatEventOperationError::InvalidInput),Err (FiatEventOperationError::InvalidInput)) => Err (FiatEventOperationError::InvalidInput),
      _=> panic!("stewards returned different results for insert_fiat_event; I believe this is ALWAYS a bug in one of the stewards (that is, it cannot be caused by invalid input)"),
    }
  }

  fn snapshot_before<'b>(&'b mut self, time: &'b B::Time) -> Option<Self::Snapshot> {
    if self.valid_since() > *time {
      return None;
    }
    match (
      self.0.snapshot_before (time),
      self.1.snapshot_before (time)
    ) {
      (Some (snapshot_0), Some (snapshot_1)) => Some (Snapshot (snapshot_0, snapshot_1)),
      (None, _) => panic! ("Steward0 failed to return a snapshot at a time it claims to be valid"),
      (_, None) => panic! ("Steward1 failed to return a snapshot at a time it claims to be valid"),
    }
  }
}

<commit_msg>Added another other check to cross verified time stewards<commit_after>//! The simplest possible implementation of the TimeSteward API.
//!
//! This implementation is unusably slow on large simulations. Its main use is to cross-check with other TimeSteward implementations to make sure they are implementing the API correctly.
//!
//!

use super::{DeterministicRandomId, SiphashIdGenerator, RowId, ColumnId, FieldId, PredictorId, Column, ExtendedTime, StewardRc,
             Basics, FieldRc, TimeSteward, FiatEventOperationError, ValidSince, PredictorFn, TimeStewardSettings, Accessor};
use std::collections::{HashMap, BTreeMap};
use std::hash::Hash;
// use std::collections::Bound::{Included, Excluded, Unbounded};
use std::any::Any;
use std::cmp::max;
use std::borrow::Borrow;
use std::rc::Rc;
use std::marker::PhantomData;

#[derive (Clone)]
pub struct Steward<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  Steward0,
  Steward1,
  PhantomData <B::Constants>
);
pub struct Snapshot<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  <Steward0 as TimeSteward <B>>::Snapshot,
  <Steward1 as TimeSteward <B>>::Snapshot,
);
pub struct Settings <B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  <Steward0 as TimeSteward <B>>::Settings,
  <Steward1 as TimeSteward <B>>::Settings,
);

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > super::Accessor<B> for Snapshot<B, Steward0, Steward1> {
  //macro_rules! forward_snapshot_method ($method: ident ($self, $($argument_name: ident: $argument_type:ty),*)->$return_type:ty
  // TODO: forward all the methods properly
  // and check equality by serialization
  fn generic_data_and_extended_last_change (&self, id: FieldId)->Option <(& FieldRc, & ExtendedTime <B>)> {
    match (
      self.0.generic_data_and_extended_last_change (id),
      self.1.generic_data_and_extended_last_change (id)
    ) {
      (None, None) => None,
      (Some (value_0), Some (value_1)) => {
        assert!(value_0.1 == value_1.1, "Snapshots returned different last change times for the same field; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types");
        //we cannot currently check whether the values are the same, so just use one of them
        Some (value_0)
      },
      //however, we CAN tell the difference between something and nothing
      _=> panic! ("One snapshot returned a value and the other didn't; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types")
    }
  }
  fn constants(&self) -> &B::Constants {
    //constants methods are usually implemented trivially; we don't bother checking them.
    //Since the user only gives you one set of constants, it's hard to return a wrong value
    self.0.constants()
  }
  fn unsafe_now(&self) -> &B::Time {
    let result = (self.0.unsafe_now(), self.1.unsafe_now());
    assert! (result.0 == result.1, "Snapshots returned different times; this is an egregious bug!");
    result.0
  }
}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > super::MomentaryAccessor<B> for Snapshot<B, Steward0, Steward1> {}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > super::Snapshot<B> for Snapshot<B, Steward0, Steward1> {
  fn num_fields(&self) -> usize {
    assert_eq!(self.0.num_fields(), self.1.num_fields());
    self.0.num_fields()
  }
}/*
use std::collections::hash_set;
pub struct SnapshotIter <'a, B: Basics, Steward0: TimeSteward<B> + 'a, Steward1: TimeSteward<B> + 'a>
where & 'a Steward0::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>
{
  set: hash_set::HashSet <FieldId>,
  iter: hash_set::Iter <'a, FieldId>,
  snapshot: & 'a Snapshot <B, Steward0, Steward1>,
}
impl <'a, B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B>> Iterator for SnapshotIter<'a, B, Steward0, Steward1>
where & 'a Steward0::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>> {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  fn next (&mut self)->Option <Self::Item> {
    (self. iter).next().map (| id | (id.clone(), (self. snapshot).generic_data_and_extended_last_change (id.clone()).expect ("the snapshot thinks a FieldId exists when it doesn't")))
  }
  fn size_hint (&self)->(usize, Option <usize>) {self. iter.size_hint()}
}
impl <'a, B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B>> IntoIterator for & 'a Snapshot <B, Steward0, Steward1>
where & 'a Steward0::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = super::SnapshotEntry <'a, B>>,

 {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  type IntoIter = SnapshotIter <'a, B, Steward0, Steward1>;
  fn into_iter (self)->Self::IntoIter {
    let mut field_ids = hash_set::HashSet::new();
    for entry in (& self.0) {
      field_ids.insert (entry.0.clone());
    }
    for entry in (& self.0) {
      let redundant =!field_ids.insert (entry.0.clone());
      assert!(redundant, "field existed in Steward1 snapshot but not Steward0 snapshot: {:?}", entry.0.clone());
    }
    unimplemented!()//SnapshotIter {set: field_ids, iter: field_ids.iter(), snapshot: self}
  }
}
*/
//TODO: implement snapshot iterating

/*
//TODO: should we just require PredictorFn to implement Clone?
#[derive (Serialize, Deserialize)]
struct ShareablePredictorFn <B: Basics, P: PredictorFn <B>> (StewardRc <P>, PhantomData <B>);
impl <B: Basics, P: PredictorFn <B>> PredictorFn <B> for ShareablePredictorFn <B, P> {
  fn call <PA: super::PredictorAccessor <B>> (&self, accessor: &mut PA, id: RowId) {
    self.0.call (accessor, id);
  }
}
// explicitly implement Clone to work around [a compiler weakness](https://github.com/rust-lang/rust/issues/26925).
impl<B: Basics> Clone for DynamicPredictor<B> {
  fn clone(&self) -> Self {
    DynamicPredictor {
      predictor_id: self.predictor_id,
      column_id: self.column_id,
      function: self.function.clone(),
      _marker: PhantomData,
    }
  }
}
*/

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > TimeStewardSettings <B> for Settings <B, Steward0, Steward1> {
  fn new()->Self {
    Settings (<Steward0::Settings as TimeStewardSettings <B>>::new(), <Steward1::Settings as TimeStewardSettings <B>>::new())
  }
  fn insert_predictor <P: PredictorFn <B>> (&mut self, predictor_id: PredictorId, column_id: ColumnId, function: P) {
    //let function = ShareablePredictorFn::<B, P> (StewardRc::new (function), PhantomData);
    self.0.insert_predictor (predictor_id, column_id, function.clone());
    self.1.insert_predictor (predictor_id, column_id, function);
  }
}

impl<B: Basics, Steward0: TimeSteward<B> , Steward1: TimeSteward<B> > TimeSteward<B> for Steward<B, Steward0, Steward1> {
  type Snapshot = Snapshot<B, Steward0, Steward1>;
  type Settings = Settings<B, Steward0, Steward1>;

  fn valid_since(&self) -> ValidSince<B::Time> {
    max (self.0.valid_since(), self.1.valid_since())
  }
  fn new_empty(constants: B::Constants, settings: Self::Settings) -> Self {
    Steward (
      TimeSteward::new_empty (constants.clone(), settings.0),
      TimeSteward::new_empty (constants, settings.1),
      PhantomData,
    )
  }

  fn from_snapshot<'a, S: super::Snapshot<B>>(snapshot: & 'a S,
                                              settings: Self::Settings)
                                              -> Self
                                              where & 'a S: IntoIterator <Item = super::SnapshotEntry <'a, B>> {
    Steward (
      Steward0::from_snapshot (snapshot, settings.0),
      Steward1::from_snapshot (snapshot, settings.1),
      PhantomData,
    )
  }
  fn insert_fiat_event <E: super::EventFn <B>> (&mut self,
                       time: B::Time,
                       id: DeterministicRandomId,
                       event: E)
                       -> Result<(), FiatEventOperationError> {
    if self.valid_since() > time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match (
      self.0.insert_fiat_event (time.clone(), id, event.clone()),
      self.1.insert_fiat_event (time, id, event)
    ){
      (Ok (()), Ok (())) => Ok (()),
      (Err (FiatEventOperationError::InvalidTime),_) => panic!("Steward0 returned InvalidTime after its own ValidSince"),
      (_,Err (FiatEventOperationError::InvalidTime)) => panic!("Steward1 returned InvalidTime after its own ValidSince"),
      (Err (FiatEventOperationError::InvalidInput),Err (FiatEventOperationError::InvalidInput)) => Err (FiatEventOperationError::InvalidInput),
      _=> panic!("stewards returned different results for insert_fiat_event; I believe this is ALWAYS a bug in one of the stewards (that is, it cannot be caused by invalid input)"),
    }
  }
  fn erase_fiat_event(&mut self,
                      time: &B::Time,
                      id: DeterministicRandomId)
                      -> Result<(), FiatEventOperationError> {
    if self.valid_since() > *time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match (
      self.0.erase_fiat_event (time, id),
      self.1.erase_fiat_event (time, id)
    ){
      (Ok (()), Ok (())) => Ok (()),
      (Err (FiatEventOperationError::InvalidTime),_) => panic!("Steward0 returned InvalidTime after its own ValidSince"),
      (_,Err (FiatEventOperationError::InvalidTime)) => panic!("Steward1 returned InvalidTime after its own ValidSince"),
      (Err (FiatEventOperationError::InvalidInput),Err (FiatEventOperationError::InvalidInput)) => Err (FiatEventOperationError::InvalidInput),
      _=> panic!("stewards returned different results for insert_fiat_event; I believe this is ALWAYS a bug in one of the stewards (that is, it cannot be caused by invalid input)"),
    }
  }

  fn snapshot_before<'b>(&'b mut self, time: &'b B::Time) -> Option<Self::Snapshot> {
    if self.valid_since() > *time {
      return None;
    }
    match (
      self.0.snapshot_before (time),
      self.1.snapshot_before (time)
    ) {
      (Some (snapshot_0), Some (snapshot_1)) => Some (Snapshot (snapshot_0, snapshot_1)),
      (None, _) => panic! ("Steward0 failed to return a snapshot at a time it claims to be valid"),
      (_, None) => panic! ("Steward1 failed to return a snapshot at a time it claims to be valid"),
    }
  }
}

<|endoftext|>


<commit_before>use std::io;
use std::io::{Read, Write};
use std::net;
use std::net::TcpStream;
#[cfg(feature = "ssl")]
use openssl::ssl::{SslStream, SslConnector};

pub trait CDRSTransport: Sized + Read + Write + Send + Sync {
    fn try_clone(&self) -> io::Result<Self>;
    fn close(&mut self, close: net::Shutdown) -> io::Result<()>;
}

pub struct TransportTcp {
    tcp: TcpStream,
}

impl TransportTcp {
    /// Constructs a new `TransportTcp`.
    ///
    /// # Examples
    ///
    /// ```
    /// use cdrs::transport::TransportTcp;
    /// let addr = "127.0.0.1:9042";
    /// let tcp_transport = TransportTcp::new(addr).unwrap();
    /// ```
    pub fn new(addr: &str) -> io::Result<TransportTcp> {
        TcpStream::connect(addr).map(|socket| TransportTcp { tcp: socket })
    }
}

impl Read for TransportTcp {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.tcp.read(buf)
    }
}

impl Write for TransportTcp {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.tcp.write(buf)
    }

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

impl CDRSTransport for TransportTcp {
    fn try_clone(&self) -> io::Result<TransportTcp> {
        let addr = try!(self.tcp.peer_addr());
        println!("TRANSPORT ADDR: {:?}", addr);
        TcpStream::connect(addr).map(|socket| TransportTcp { tcp: socket })
    }

    fn close(&mut self, close: net::Shutdown) -> io::Result<()> {
        self.tcp.shutdown(close)
    }
}

/// **********************************
/** TLS**/
/// ***********************************
#[cfg(feature = "ssl")]
pub struct TransportTls {
    ssl: SslStream<TcpStream>,
    connector: SslConnector,
}
#[cfg(feature = "ssl")]
impl TransportTls {
    pub fn new(addr: &str, connector: &SslConnector) -> io::Result<TransportTls> {
        let a: Vec<&str> = addr.split(':').collect();
        let res = net::TcpStream::connect(addr).map(|socket| {
            connector.connect(a[0], socket)
                .map(|sslsocket| {
                    TransportTls {
                        ssl: sslsocket,
                        connector: connector.clone(),
                    }
                })
        });

        res.and_then(|res| {
            res.map(|n: TransportTls| n).map_err(|e| io::Error::new(io::ErrorKind::Other, e))

        })
    }
}
#[cfg(feature = "ssl")]
impl Read for TransportTls {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.ssl.read(buf)
    }
}
#[cfg(feature = "ssl")]
impl Write for TransportTls {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.ssl.write(buf)
    }

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

#[cfg(feature = "ssl")]
impl CDRSTransport for TransportTls {
    /// This method
    /// creates absolutely new connection - it gets an address
    /// of a peer from `TransportTls` and creates a new encrypted
    /// connection with a new TCP stream under hood.
    fn try_clone(&self) -> io::Result<TransportTls> {
        let addr = try!(self.ssl.get_ref().peer_addr());
        let ip_string = format!("{}", addr.ip());

        let res = net::TcpStream::connect(addr).map(|socket| {
            self.connector
                .connect(ip_string.as_str(), socket)
                .map(|sslsocket| {
                    TransportTls {
                        ssl: sslsocket,
                        connector: self.connector.clone(),
                    }
                })
        });

        res.and_then(|res| {
            res.map(|n: TransportTls| n).map_err(|e| io::Error::new(io::ErrorKind::Other, e))
        })
    }

    fn close(&mut self, _close: net::Shutdown) -> io::Result<()> {
        self.ssl
            .shutdown()
            .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
            .and_then(|_| Ok(()))
    }
}
<commit_msg>Rid of unnecessary println<commit_after>use std::io;
use std::io::{Read, Write};
use std::net;
use std::net::TcpStream;
#[cfg(feature = "ssl")]
use openssl::ssl::{SslStream, SslConnector};

pub trait CDRSTransport: Sized + Read + Write + Send + Sync {
    fn try_clone(&self) -> io::Result<Self>;
    fn close(&mut self, close: net::Shutdown) -> io::Result<()>;
}

pub struct TransportTcp {
    tcp: TcpStream,
}

impl TransportTcp {
    /// Constructs a new `TransportTcp`.
    ///
    /// # Examples
    ///
    /// ```
    /// use cdrs::transport::TransportTcp;
    /// let addr = "127.0.0.1:9042";
    /// let tcp_transport = TransportTcp::new(addr).unwrap();
    /// ```
    pub fn new(addr: &str) -> io::Result<TransportTcp> {
        TcpStream::connect(addr).map(|socket| TransportTcp { tcp: socket })
    }
}

impl Read for TransportTcp {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.tcp.read(buf)
    }
}

impl Write for TransportTcp {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.tcp.write(buf)
    }

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

impl CDRSTransport for TransportTcp {
    fn try_clone(&self) -> io::Result<TransportTcp> {
        let addr = try!(self.tcp.peer_addr());
        TcpStream::connect(addr).map(|socket| TransportTcp { tcp: socket })
    }

    fn close(&mut self, close: net::Shutdown) -> io::Result<()> {
        self.tcp.shutdown(close)
    }
}

/// **********************************
/** TLS**/
/// ***********************************
#[cfg(feature = "ssl")]
pub struct TransportTls {
    ssl: SslStream<TcpStream>,
    connector: SslConnector,
}
#[cfg(feature = "ssl")]
impl TransportTls {
    pub fn new(addr: &str, connector: &SslConnector) -> io::Result<TransportTls> {
        let a: Vec<&str> = addr.split(':').collect();
        let res = net::TcpStream::connect(addr).map(|socket| {
            connector.connect(a[0], socket)
                .map(|sslsocket| {
                    TransportTls {
                        ssl: sslsocket,
                        connector: connector.clone(),
                    }
                })
        });

        res.and_then(|res| {
            res.map(|n: TransportTls| n).map_err(|e| io::Error::new(io::ErrorKind::Other, e))

        })
    }
}
#[cfg(feature = "ssl")]
impl Read for TransportTls {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.ssl.read(buf)
    }
}
#[cfg(feature = "ssl")]
impl Write for TransportTls {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.ssl.write(buf)
    }

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

#[cfg(feature = "ssl")]
impl CDRSTransport for TransportTls {
    /// This method
    /// creates absolutely new connection - it gets an address
    /// of a peer from `TransportTls` and creates a new encrypted
    /// connection with a new TCP stream under hood.
    fn try_clone(&self) -> io::Result<TransportTls> {
        let addr = try!(self.ssl.get_ref().peer_addr());
        let ip_string = format!("{}", addr.ip());

        let res = net::TcpStream::connect(addr).map(|socket| {
            self.connector
                .connect(ip_string.as_str(), socket)
                .map(|sslsocket| {
                    TransportTls {
                        ssl: sslsocket,
                        connector: self.connector.clone(),
                    }
                })
        });

        res.and_then(|res| {
            res.map(|n: TransportTls| n).map_err(|e| io::Error::new(io::ErrorKind::Other, e))
        })
    }

    fn close(&mut self, _close: net::Shutdown) -> io::Result<()> {
        self.ssl
            .shutdown()
            .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
            .and_then(|_| Ok(()))
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::BindingDeclarations::ProgressEventBinding;
use dom::bindings::codegen::InheritTypes::ProgressEventDerived;
use dom::bindings::error::Fallible;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, ProgressEventTypeId};
use dom::window::Window;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct ProgressEvent {
    event: Event,
    length_computable: bool,
    loaded: u64,
    total: u64
}

impl ProgressEventDerived for Event {
    fn is_progressevent(&self) -> bool {
        self.type_id == ProgressEventTypeId
    }
}

impl ProgressEvent {
    pub fn new_inherited(length_computable: bool, loaded: u64, total: u64) -> ProgressEvent {
        ProgressEvent {
            event: Event::new_inherited(ProgressEventTypeId),
            length_computable: length_computable,
            loaded: loaded,
            total: total
        }
    }
    pub fn new(window: &JSRef<Window>, length_computable: bool,
                loaded: u64, total: u64) -> Temporary<ProgressEvent> {
        reflect_dom_object(~ProgressEvent::new_inherited(length_computable, loaded, total),
                           window,
                           ProgressEventBinding::Wrap)
    }
    pub fn Constructor(owner: &JSRef<Window>,
                       type_: DOMString,
                       init: &ProgressEventBinding::ProgressEventInit)
                       -> Fallible<Temporary<ProgressEvent>> {
        let ev = ProgressEvent::new(owner, init.lengthComputable, init.loaded, init.total);
        Ok(ev)
    }
}

pub trait ProgressEventMethods {
    fn LengthComputable(&self) -> bool;
    fn Loaded(&self) -> u64;
    fn Total(&self) -> u64;
}

impl<'a> ProgressEventMethods for JSRef<'a, ProgressEvent> {
    fn LengthComputable(&self) -> bool {
        self.length_computable
    }
    fn Loaded(&self) -> u64{
        self.loaded
    }
    fn Total(&self) -> u64 {
        self.total
    }
}

impl Reflectable for ProgressEvent {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.event.reflector()
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        self.event.mut_reflector()
    }
}<commit_msg>Rename an unused parameter to silence a warning.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::BindingDeclarations::ProgressEventBinding;
use dom::bindings::codegen::InheritTypes::ProgressEventDerived;
use dom::bindings::error::Fallible;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, ProgressEventTypeId};
use dom::window::Window;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct ProgressEvent {
    event: Event,
    length_computable: bool,
    loaded: u64,
    total: u64
}

impl ProgressEventDerived for Event {
    fn is_progressevent(&self) -> bool {
        self.type_id == ProgressEventTypeId
    }
}

impl ProgressEvent {
    pub fn new_inherited(length_computable: bool, loaded: u64, total: u64) -> ProgressEvent {
        ProgressEvent {
            event: Event::new_inherited(ProgressEventTypeId),
            length_computable: length_computable,
            loaded: loaded,
            total: total
        }
    }
    pub fn new(window: &JSRef<Window>, length_computable: bool,
                loaded: u64, total: u64) -> Temporary<ProgressEvent> {
        reflect_dom_object(~ProgressEvent::new_inherited(length_computable, loaded, total),
                           window,
                           ProgressEventBinding::Wrap)
    }
    pub fn Constructor(owner: &JSRef<Window>,
                       _type: DOMString,
                       init: &ProgressEventBinding::ProgressEventInit)
                       -> Fallible<Temporary<ProgressEvent>> {
        let ev = ProgressEvent::new(owner, init.lengthComputable, init.loaded, init.total);
        Ok(ev)
    }
}

pub trait ProgressEventMethods {
    fn LengthComputable(&self) -> bool;
    fn Loaded(&self) -> u64;
    fn Total(&self) -> u64;
}

impl<'a> ProgressEventMethods for JSRef<'a, ProgressEvent> {
    fn LengthComputable(&self) -> bool {
        self.length_computable
    }
    fn Loaded(&self) -> u64{
        self.loaded
    }
    fn Total(&self) -> u64 {
        self.total
    }
}

impl Reflectable for ProgressEvent {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.event.reflector()
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        self.event.mut_reflector()
    }
}<|endoftext|>


<commit_before>#[macro_use]
mod macros;
mod error;
mod expression;
mod statement;
mod function;

use error::Error;
use arena::Arena;
use module::Module;

use ast::{Loc, Ptr, Statement, List, ListBuilder, EmptyListBuilder};
use ast::{Parameter, ParameterKey, ParameterPtr, ParameterList, OperatorKind};
use ast::{Expression, ExpressionPtr, ExpressionList};
use lexer::{Lexer, Token, Asi};
use lexer::Token::*;

pub struct Parser<'ast> {
    arena: &'ast Arena,

    /// Lexer will produce tokens from the source
    lexer: Lexer<'ast>,

    /// Set to `Some` whenever peek is called
    token: Option<Token<'ast>>,

    /// Errors occurred during parsing
    errors: Vec<Error>,

    /// AST under construction
    body: List<'ast, Loc<Statement<'ast>>>,
}

impl<'ast> Parser<'ast> {
    pub fn new(source: &'ast str, arena: &'ast Arena) -> Self {
        Parser {
            arena,
            lexer: Lexer::new(source),
            token: None,
            errors: Vec::new(),
            body: List::empty(),
        }
    }

    /// Get the next token.
    #[inline]
    fn next(&mut self) -> Token<'ast> {
        match self.token {
            None => self.lexer.get_token(),

            Some(token) => {
                self.token = None;

                token
            }
        }
    }

    /// Peek on the next token.
    #[inline]
    fn peek(&mut self) -> Token<'ast> {
        match self.token {
            None => {
                let token = self.lexer.get_token();

                self.token = Some(token);

                token
            },

            Some(token) => token
        }
    }

    #[inline]
    fn asi(&mut self) -> Asi {
        self.peek();

        self.lexer.asi()
    }

    #[inline]
    fn consume(&mut self) {
        self.token = None;
    }

    #[inline]
    fn loc(&self) -> (u32, u32) {
        self.lexer.loc()
    }

    #[inline]
    fn in_loc<T>(&self, item: T) -> Loc<T> {
        let (start, end) = self.loc();

        Loc::new(start, end, item)
    }

    #[inline]
    fn alloc<T: Copy>(&mut self, val: T) -> Ptr<'ast, T> {
        Ptr::new(self.arena.alloc(val))
    }

    #[inline]
    fn alloc_in_loc<T: Copy>(&mut self, item: T) -> Ptr<'ast, Loc<T>> {
        let node = self.in_loc(item);
        self.alloc(node)
    }

    #[inline]
    fn parse(&mut self) {
        let statement = match self.next() {
            EndOfProgram => return,
            token        => self.statement(token)
        };

        let mut builder = ListBuilder::new(self.arena, statement);

        loop {
            let statement = match self.next() {
                EndOfProgram => break,
                token        => self.statement(token)
            };

            builder.push(statement);
        }

        self.body = builder.into_list()
    }

    #[inline]
    fn block_body_tail(&mut self) -> List<'ast, Loc<Statement<'ast>>> {
        let statement = match self.next() {
            BraceClose => return List::empty(),
            token      => self.statement(token),
        };

        let mut builder = ListBuilder::new(self.arena, statement);

        loop {
            let statement = match self.next() {
                BraceClose => break,
                token      => self.statement(token),
            };

            builder.push(statement);
        }

        builder.into_list()
    }

    #[inline]
    fn block_body(&mut self) -> List<'ast, Loc<Statement<'ast>>> {
        expect!(self, BraceOpen);
        self.block_body_tail()
    }

    #[inline]
    fn param_from_expression(&mut self, expression: ExpressionPtr<'ast>) -> ParameterPtr<'ast> {
        match expression.item {
            Expression::Identifier(ident) => {
                let param = Parameter {
                    key: ParameterKey::Identifier(ident),
                    value: None
                };

                self.alloc_in_loc(param)
            },
            Expression::Binary {
                operator: OperatorKind::Assign,
                left,
                right
            } => {
                let param = Parameter {
                    key: self.param_from_expression(left).key,
                    value: Some(right)
                };

                self.alloc_in_loc(param)
            },
            _ => unexpected_token!(self)
        }
    }

    #[inline]
    fn params_from_expressions(&mut self, expressions: ExpressionList<'ast>) -> ParameterList<'ast> {
        let mut expressions = expressions.ptr_iter();

        let mut builder = match expressions.next() {
            Some(expression) => {
                let param = self.param_from_expression(*expression);

                ListBuilder::new(self.arena, param)
            },
            None => return List::empty()
        };

        for expression in expressions {
            builder.push(self.param_from_expression(*expression));
        }

        builder.into_list()
    }

    #[inline]
    fn parameter_list(&mut self) -> ParameterList<'ast> {
        let mut builder = EmptyListBuilder::new(self.arena);

        loop {
            let key = parameter_key!(self);
            let token = self.next();

            if token == Operator(OperatorKind::Assign) {
                return self.parameter_list_with_defaults(key, builder);
            }

            let parameter = Parameter {
                key,
                value: None
            };

            builder.push(self.alloc_in_loc(parameter));

            match token {
                ParenClose => break,
                Comma      => {},
                _          => unexpected_token!(self),
            };
        }

        builder.into_list()
    }

    #[inline]
    fn parameter_list_with_defaults(
        &mut self,
        mut key: ParameterKey<'ast>,
        mut builder: EmptyListBuilder<'ast, Loc<Parameter<'ast>>>
    ) -> ParameterList<'ast> {
        loop {
            let value = self.expression(0);
            let parameter = Parameter {
                key,
                value: Some(value)
            };

            builder.push(self.alloc_in_loc(parameter));

            match self.next() {
                ParenClose => break,
                Comma      => {},
                _          => unexpected_token!(self),
            };

            key = parameter_key!(self);

            expect!(self, Operator(OperatorKind::Assign));
        }

        builder.into_list()
    }
}

pub fn parse(source: &str) -> Result<Module, Vec<Error>> {
    let arena = Arena::new();

    let (body, errors) = {
        let source = arena.alloc_str(source);
        let mut parser = Parser::new(source, &arena);

        parser.parse();

        (parser.body.into_raw(), parser.errors)
    };

    match errors.len() {
        0 => Ok(Module::new(body, arena)),
        _ => Err(errors)
    }
}

#[cfg(test)]
mod mock {
    use super::*;
    use ast::{Expression, Value};

    pub struct Mock {
        arena: Arena
    }

    impl Mock {
        pub fn new() -> Self {
            Mock {
                arena: Arena::new()
            }
        }

        pub fn ptr<'a, T: 'a + Copy>(&'a self, val: T) -> Ptr<'a, Loc<T>> {
            Ptr::new(self.arena.alloc(Loc::new(0, 0, val)))
        }

        pub fn ident<'a>(&'a self, ident: &'static str) -> Ptr<'a, Loc<Expression<'a>>> {
            self.ptr(Expression::Identifier(ident))
        }

        pub fn number<'a>(&'a self, number: &'static str) -> Ptr<'a, Loc<Expression<'a>>> {
            self.ptr(Expression::Value(Value::Number(number)))
        }

        pub fn list<'a, T, L>(&'a self, list: L) -> List<'a, Loc<T>> where
            T: 'a + Copy,
            L: AsRef<[T]>
        {
            List::from_iter(&self.arena, list.as_ref().iter().cloned().map(|i| Loc::new(0, 0, i)))
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use parser::mock::Mock;

    #[test]
    fn empty_parse() {
        let module = parse("").unwrap();

        assert_eq!(module.body(), List::empty());
    }

    #[test]
    fn empty_statements() {
        let module = parse(";;;").unwrap();
        let mock = Mock::new();

        let expected = mock.list([
            Statement::Empty,
            Statement::Empty,
            Statement::Empty
        ]);

        assert_eq!(module.body(), expected);
    }

}
<commit_msg>Avoid recursion, copy location for arrow params<commit_after>#[macro_use]
mod macros;
mod error;
mod expression;
mod statement;
mod function;

use error::Error;
use arena::Arena;
use module::Module;

use ast::{Loc, Ptr, Statement, List, ListBuilder, EmptyListBuilder};
use ast::{Parameter, ParameterKey, ParameterPtr, ParameterList, OperatorKind};
use ast::{Expression, ExpressionPtr, ExpressionList};
use lexer::{Lexer, Token, Asi};
use lexer::Token::*;

pub struct Parser<'ast> {
    arena: &'ast Arena,

    /// Lexer will produce tokens from the source
    lexer: Lexer<'ast>,

    /// Set to `Some` whenever peek is called
    token: Option<Token<'ast>>,

    /// Errors occurred during parsing
    errors: Vec<Error>,

    /// AST under construction
    body: List<'ast, Loc<Statement<'ast>>>,
}

impl<'ast> Parser<'ast> {
    pub fn new(source: &'ast str, arena: &'ast Arena) -> Self {
        Parser {
            arena,
            lexer: Lexer::new(source),
            token: None,
            errors: Vec::new(),
            body: List::empty(),
        }
    }

    /// Get the next token.
    #[inline]
    fn next(&mut self) -> Token<'ast> {
        match self.token {
            None => self.lexer.get_token(),

            Some(token) => {
                self.token = None;

                token
            }
        }
    }

    /// Peek on the next token.
    #[inline]
    fn peek(&mut self) -> Token<'ast> {
        match self.token {
            None => {
                let token = self.lexer.get_token();

                self.token = Some(token);

                token
            },

            Some(token) => token
        }
    }

    #[inline]
    fn asi(&mut self) -> Asi {
        self.peek();

        self.lexer.asi()
    }

    #[inline]
    fn consume(&mut self) {
        self.token = None;
    }

    #[inline]
    fn loc(&self) -> (u32, u32) {
        self.lexer.loc()
    }

    #[inline]
    fn in_loc<T>(&self, item: T) -> Loc<T> {
        let (start, end) = self.loc();

        Loc::new(start, end, item)
    }

    #[inline]
    fn alloc<T: Copy>(&mut self, val: T) -> Ptr<'ast, T> {
        Ptr::new(self.arena.alloc(val))
    }

    #[inline]
    fn alloc_in_loc<T: Copy>(&mut self, item: T) -> Ptr<'ast, Loc<T>> {
        let node = self.in_loc(item);
        self.alloc(node)
    }

    #[inline]
    fn parse(&mut self) {
        let statement = match self.next() {
            EndOfProgram => return,
            token        => self.statement(token)
        };

        let mut builder = ListBuilder::new(self.arena, statement);

        loop {
            let statement = match self.next() {
                EndOfProgram => break,
                token        => self.statement(token)
            };

            builder.push(statement);
        }

        self.body = builder.into_list()
    }

    #[inline]
    fn block_body_tail(&mut self) -> List<'ast, Loc<Statement<'ast>>> {
        let statement = match self.next() {
            BraceClose => return List::empty(),
            token      => self.statement(token),
        };

        let mut builder = ListBuilder::new(self.arena, statement);

        loop {
            let statement = match self.next() {
                BraceClose => break,
                token      => self.statement(token),
            };

            builder.push(statement);
        }

        builder.into_list()
    }

    #[inline]
    fn block_body(&mut self) -> List<'ast, Loc<Statement<'ast>>> {
        expect!(self, BraceOpen);
        self.block_body_tail()
    }

    #[inline]
    fn param_from_expression(&mut self, expression: ExpressionPtr<'ast>) -> ParameterPtr<'ast> {
        let (key, value) = match expression.item {
            Expression::Binary {
                operator: OperatorKind::Assign,
                left,
                right,
            } => (left, Some(right)),
            _ => (expression, None)
        };

        let key = match key.item {
            Expression::Identifier(ident) => ParameterKey::Identifier(ident),
            // TODO: ParameterKey::Pattern
            _ => unexpected_token!(self)
        };

        self.alloc(Loc::new(expression.start, expression.end, Parameter {
            key,
            value
        }))
    }

    #[inline]
    fn params_from_expressions(&mut self, expressions: ExpressionList<'ast>) -> ParameterList<'ast> {
        let mut expressions = expressions.ptr_iter();

        let mut builder = match expressions.next() {
            Some(&expression) => {
                let param = self.param_from_expression(expression);

                ListBuilder::new(self.arena, param)
            },
            None => return List::empty()
        };

        for &expression in expressions {
            builder.push(self.param_from_expression(expression));
        }

        builder.into_list()
    }

    #[inline]
    fn parameter_list(&mut self) -> ParameterList<'ast> {
        let mut builder = EmptyListBuilder::new(self.arena);

        loop {
            let key = parameter_key!(self);
            let token = self.next();

            if token == Operator(OperatorKind::Assign) {
                return self.parameter_list_with_defaults(key, builder);
            }

            let parameter = Parameter {
                key,
                value: None
            };

            builder.push(self.alloc_in_loc(parameter));

            match token {
                ParenClose => break,
                Comma      => {},
                _          => unexpected_token!(self),
            };
        }

        builder.into_list()
    }

    #[inline]
    fn parameter_list_with_defaults(
        &mut self,
        mut key: ParameterKey<'ast>,
        mut builder: EmptyListBuilder<'ast, Loc<Parameter<'ast>>>
    ) -> ParameterList<'ast> {
        loop {
            let value = self.expression(0);
            let parameter = Parameter {
                key,
                value: Some(value)
            };

            builder.push(self.alloc_in_loc(parameter));

            match self.next() {
                ParenClose => break,
                Comma      => {},
                _          => unexpected_token!(self),
            };

            key = parameter_key!(self);

            expect!(self, Operator(OperatorKind::Assign));
        }

        builder.into_list()
    }
}

pub fn parse(source: &str) -> Result<Module, Vec<Error>> {
    let arena = Arena::new();

    let (body, errors) = {
        let source = arena.alloc_str(source);
        let mut parser = Parser::new(source, &arena);

        parser.parse();

        (parser.body.into_raw(), parser.errors)
    };

    match errors.len() {
        0 => Ok(Module::new(body, arena)),
        _ => Err(errors)
    }
}

#[cfg(test)]
mod mock {
    use super::*;
    use ast::{Expression, Value};

    pub struct Mock {
        arena: Arena
    }

    impl Mock {
        pub fn new() -> Self {
            Mock {
                arena: Arena::new()
            }
        }

        pub fn ptr<'a, T: 'a + Copy>(&'a self, val: T) -> Ptr<'a, Loc<T>> {
            Ptr::new(self.arena.alloc(Loc::new(0, 0, val)))
        }

        pub fn ident<'a>(&'a self, ident: &'static str) -> Ptr<'a, Loc<Expression<'a>>> {
            self.ptr(Expression::Identifier(ident))
        }

        pub fn number<'a>(&'a self, number: &'static str) -> Ptr<'a, Loc<Expression<'a>>> {
            self.ptr(Expression::Value(Value::Number(number)))
        }

        pub fn list<'a, T, L>(&'a self, list: L) -> List<'a, Loc<T>> where
            T: 'a + Copy,
            L: AsRef<[T]>
        {
            List::from_iter(&self.arena, list.as_ref().iter().cloned().map(|i| Loc::new(0, 0, i)))
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use parser::mock::Mock;

    #[test]
    fn empty_parse() {
        let module = parse("").unwrap();

        assert_eq!(module.body(), List::empty());
    }

    #[test]
    fn empty_statements() {
        let module = parse(";;;").unwrap();
        let mock = Mock::new();

        let expected = mock.list([
            Statement::Empty,
            Statement::Empty,
            Statement::Empty
        ]);

        assert_eq!(module.body(), expected);
    }

}
<|endoftext|>