<commit_before>#[macro_export]
macro_rules! simple_bitfield_field {
   ($name:ident, $t:ty,) => {};
   ($name:ident, $t:ty, _, $setter:ident: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       impl $name {
           pub fn $setter(&mut self, value: $t) {
               self.set_range_($msb, $lsb, value);
           }
       }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, _, $setter:ident: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
       impl $name {
           pub fn $setter(&mut self, index: usize, value: $t) {
               debug_assert!(index < $count);
               let width = $msb - $lsb + 1;
               let lsb = $lsb + index*width;
               let msb = lsb + width - 1;
               self.set_range_(msb, lsb, value);
           }
       }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, $getter:ident, _: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       impl $name {
           pub fn $getter(&self) -> $t {
               self.get_range_($msb, $lsb)
           }
       }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, $getter:ident, _: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
       impl $name {
           pub fn $getter(&self, index: usize) -> $t {
               debug_assert!(index < $count);
               let width = $msb - $lsb + 1;
               let lsb = $lsb + index*width;
               let msb = lsb + width - 1;
               self.get_range_(msb, lsb)
           }
       }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, $getter:ident, $setter:ident: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       simple_bitfield_field!{$name, $t, $getter, _: $msb, $lsb, }
       simple_bitfield_field!{$name, $t, _, $setter: $msb, $lsb, }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, $getter:ident, $setter:ident: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
         simple_bitfield_field!{$name, $t, $getter, _: $msb, $lsb; $count, }
         simple_bitfield_field!{$name, $t, _, $setter: $msb, $lsb; $count, }
         simple_bitfield_field!{$name, $t, $($rest)*}
   };
}

#[macro_export]
macro_rules! simple_bitfield {
    ($name:ident, $t:ty, $($rest:tt)*) => {
         pub struct $name(pub $t);
         impl $name {
             fn get_range_(&self, msb: usize, lsb: usize) -> $t {
                 let bit_len = mem::size_of::<$t>()*8;
                 (self.0 << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)
             }

             fn set_range_(&mut self, msb: usize, lsb: usize, value: $t) {
                 let bit_len = mem::size_of::<$t>()*8;
                 let mask: $t = !(0 as $t) << (bit_len - msb - 1) >> (bit_len - msb - 1 + lsb) << (lsb);
                 self.0 &= !mask;
                 self.0 |= (value << lsb) & mask;
             }
         }
         simple_bitfield_field!{$name, $t, $($rest)*}
    }
}
<commit_msg>Add derive/repr to the generated structs<commit_after>#[macro_export]
macro_rules! simple_bitfield_field {
   ($name:ident, $t:ty,) => {};
   ($name:ident, $t:ty, _, $setter:ident: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       impl $name {
           pub fn $setter(&mut self, value: $t) {
               self.set_range_($msb, $lsb, value);
           }
       }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, _, $setter:ident: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
       impl $name {
           pub fn $setter(&mut self, index: usize, value: $t) {
               debug_assert!(index < $count);
               let width = $msb - $lsb + 1;
               let lsb = $lsb + index*width;
               let msb = lsb + width - 1;
               self.set_range_(msb, lsb, value);
           }
       }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, $getter:ident, _: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       impl $name {
           pub fn $getter(&self) -> $t {
               self.get_range_($msb, $lsb)
           }
       }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, $getter:ident, _: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
       impl $name {
           pub fn $getter(&self, index: usize) -> $t {
               debug_assert!(index < $count);
               let width = $msb - $lsb + 1;
               let lsb = $lsb + index*width;
               let msb = lsb + width - 1;
               self.get_range_(msb, lsb)
           }
       }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, $getter:ident, $setter:ident: $msb:expr, $lsb:expr, $($rest:tt)*) => {
       simple_bitfield_field!{$name, $t, $getter, _: $msb, $lsb, }
       simple_bitfield_field!{$name, $t, _, $setter: $msb, $lsb, }
       simple_bitfield_field!{$name, $t, $($rest)*}
   };
   ($name:ident, $t:ty, $getter:ident, $setter:ident: $msb:expr, $lsb:expr; $count:expr, $($rest:tt)*) => {
         simple_bitfield_field!{$name, $t, $getter, _: $msb, $lsb; $count, }
         simple_bitfield_field!{$name, $t, _, $setter: $msb, $lsb; $count, }
         simple_bitfield_field!{$name, $t, $($rest)*}
   };
}

#[macro_export]
macro_rules! simple_bitfield {
    ($name:ident, $t:ty, $($rest:tt)*) => {
         #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
         #[repr(C)]
         pub struct $name(pub $t);
         impl $name {
             fn get_range_(&self, msb: usize, lsb: usize) -> $t {
                 let bit_len = mem::size_of::<$t>()*8;
                 (self.0 << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)
             }

             fn set_range_(&mut self, msb: usize, lsb: usize, value: $t) {
                 let bit_len = mem::size_of::<$t>()*8;
                 let mask: $t = !(0 as $t) << (bit_len - msb - 1) >> (bit_len - msb - 1 + lsb) << (lsb);
                 self.0 &= !mask;
                 self.0 |= (value << lsb) & mask;
             }
         }
         simple_bitfield_field!{$name, $t, $($rest)*}
    }
}
<|endoftext|>


<commit_before>//! The `ztext` module contains encoding functions to encode text in z-ascii characters.
//!

use super::zbytes::Bytes;

pub static ALPHABET: [char; 78] = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',

    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',

    ' ', '\n', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.',
    ',', '!', '?', '_', '#', '\'','"', '/', '\\','-', ':', '(', ')'];

/// encodes an string to z-characters
/// and returns the length of the used bytes
/// TODO: Only works with lower case letters
///
/// # Examples
///
/// ```ignore
/// let data = Bytes{bytes: Vec::new()};
/// let byteLength = data.encode("hello");
/// ```
pub fn encode(data: &mut Bytes, content: &str, unicode_table: &Vec<u16>) -> u16 {
    let zchars: Vec<u8> = string_to_zchar(content, unicode_table);

    let mut two_bytes: u16 = 0;
    let len = zchars.len();
    for i in 0..len {
        let zasci_id =zchars[i];

        two_bytes |= shift(zasci_id as u16, i as u8);

        if i % 3 == 2 {
            data.write_u16(two_bytes, pos_to_index(i));
            two_bytes = 0;
        }

        // end of string
        if i == len -1 {
            if i % 3 != 2 {
                for j in (i % 3) + 1..3 {
                    two_bytes |= shift(0x05 as u16, j as u8);
                }

                data.write_u16(two_bytes, pos_to_index(i));
            }

            // end bit is written to the first bit of the next to last byte
            let end_index: usize = data.bytes.len() - 2 as usize;
            let mut end_byte: u8 = data.bytes[end_index];

            end_byte |= 0x80;
            data.write_byte(end_byte, end_index as usize);
        }
    }

    data.bytes.len() as u16
}

/// reads the content and converts it to a zasci vector
fn string_to_zchar(content: &str, unicode_table: &Vec<u16>) -> Vec<u8> {
    //let string_bytes = content.to_string().into_bytes();
    let mut zchars: Vec<u8> = Vec::new();

    for character in content.chars() {

        let mut byte: u8 = character as u8;
        let alpha_index = pos_in_alpha(byte as u8);
        if character as u16 <= 126 && alpha_index != -1 {

            if byte == 0x0A {
                // newline
                zchars.push(0x05);
                zchars.push(7);
            } else if byte == 0x20 {
                // space
                zchars.push(0x00);
            } else {
                if alpha_index > 51 {
                    // in A2
                    zchars.push(0x05);
                    zchars.push(alpha_index as u8 % 26 + 6);
                } else if alpha_index < 26 {
                    // in A0
                    zchars.push(alpha_index as u8 % 26 + 6);
                } else {
                    // in A1
                    zchars.push(0x04);
                    zchars.push(alpha_index as u8 % 26 + 6);
                }
            }
        } else {
            // not in alphabet or unicode

            // to change alphabet
            zchars.push(0x05);

            // for special char (10 bit z-ascii)
            zchars.push(0x06);

            //let mut byte: u8;
            if character as u16 <= 126 {
                // not in alphabet, but still ascii
                byte = character as u8;
            } else {
                // unicode
                let unicode_index = pos_in_unicode(character as u16, unicode_table);
                byte = unicode_index as u8 + 155;
            }

            zchars.push(byte >> 5);
            zchars.push(byte & 0x1f);
        }
    }
    zchars
}

/// shifts the z-char in a 2 bytes-array to the right position
/// shift_length has 3 possibilities: 10, 5, 0
/// an z-char use 5 bytes
/// look into two bytes:
/// ____byte one____ ____byte two____
/// 1 2 3 4 5 6  7 8 1 2 3  4 5 6 7 8
///   ^          ^          1
///   1 2 3 4 5  1 2 3 4 5  1 2 3 4 5
///   1. zchar   2. zchar   3. zchar
///   10         5          0
fn shift(zchar: u16, position: u8) -> u16 {
    let shift_length = 10 - (position % 3) * 5;
    zchar << shift_length
}

/// Returns the location of the character of the specified index in the zcode character array
///
/// # Examples
///
/// ```ignore
/// assert_eq!(pos_in_alpha('c'), 2);
/// ```
fn pos_in_alpha(letter: u8) -> i8 {
    for i in 0..ALPHABET.len() {
        if ALPHABET[i] as u8 == letter {
            return i as i8
        }
    }

    return -1
}

/// returns the position in the unicode-table
pub fn pos_in_unicode(letter: u16, unicode_table: &Vec<u16>) -> i8 {
    for (i, character) in unicode_table.iter().enumerate() {
        if *character == letter {
            return i as i8
        }
    }

    return -1
}

/// position in the vector from the position of an character in the string
/// every 3 zchars encode() writes 2 bytes
/// for example "helloworld"
/// "h": nothing
/// "e": nothing
/// "l": write 2 bytes to position 0   (2 * 2/3))
/// "l": nothing
/// "o": nothing
/// "w": write 2 bytes to position 2   (2 * 5/3))
/// ...
///
/// # Examples
///
/// ```ignore
/// assert_eq!(pos_to_index(5), 2);
/// ```
fn pos_to_index(position: usize) -> usize {
    2 * (position / 3)
}
<commit_msg>some tests for ztext<commit_after>//! The `ztext` module contains encoding functions to encode text in z-ascii characters.
//!

use super::zbytes::Bytes;

pub static ALPHABET: [char; 78] = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',

    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',

    ' ', '\n', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.',
    ',', '!', '?', '_', '#', '\'','"', '/', '\\','-', ':', '(', ')'];

/// encodes an string to z-characters
/// and returns the length of the used bytes
/// TODO: Only works with lower case letters
///
/// # Examples
///
/// ```ignore
/// let data = Bytes{bytes: Vec::new()};
/// let byteLength = data.encode("hello");
/// ```
pub fn encode(data: &mut Bytes, content: &str, unicode_table: &Vec<u16>) -> u16 {
    let zchars: Vec<u8> = string_to_zchar(content, unicode_table);

    let mut two_bytes: u16 = 0;
    let len = zchars.len();
    for i in 0..len {
        let zasci_id =zchars[i];

        two_bytes |= shift(zasci_id as u16, i as u8);

        if i % 3 == 2 {
            data.write_u16(two_bytes, pos_to_index(i));
            two_bytes = 0;
        }

        // end of string
        if i == len -1 {
            if i % 3 != 2 {
                for j in (i % 3) + 1..3 {
                    two_bytes |= shift(0x05 as u16, j as u8);
                }

                data.write_u16(two_bytes, pos_to_index(i));
            }

            // end bit is written to the first bit of the next to last byte
            let end_index: usize = data.bytes.len() - 2 as usize;
            let mut end_byte: u8 = data.bytes[end_index];

            end_byte |= 0x80;
            data.write_byte(end_byte, end_index as usize);
        }
    }

    data.bytes.len() as u16
}

/// reads the content and converts it to a zasci vector
fn string_to_zchar(content: &str, unicode_table: &Vec<u16>) -> Vec<u8> {
    //let string_bytes = content.to_string().into_bytes();
    let mut zchars: Vec<u8> = Vec::new();

    for character in content.chars() {

        let mut byte: u8 = character as u8;
        let alpha_index = pos_in_alpha(byte as u8);
        if character as u16 <= 126 && alpha_index != -1 {

            if byte == 0x0A {
                // newline
                zchars.push(0x05);
                zchars.push(7);
            } else if byte == 0x20 {
                // space
                zchars.push(0x00);
            } else {
                if alpha_index > 51 {
                    // in A2
                    zchars.push(0x05);
                    zchars.push(alpha_index as u8 % 26 + 6);
                } else if alpha_index < 26 {
                    // in A0
                    zchars.push(alpha_index as u8 % 26 + 6);
                } else {
                    // in A1
                    zchars.push(0x04);
                    zchars.push(alpha_index as u8 % 26 + 6);
                }
            }
        } else {
            // not in alphabet or unicode

            // to change alphabet
            zchars.push(0x05);

            // for special char (10 bit z-ascii)
            zchars.push(0x06);

            //let mut byte: u8;
            if character as u16 <= 126 {
                // not in alphabet, but still ascii
                byte = character as u8;
            } else {
                // unicode
                let unicode_index = pos_in_unicode(character as u16, unicode_table);
                byte = unicode_index as u8 + 155;
            }

            zchars.push(byte >> 5);
            zchars.push(byte & 0x1f);
        }
    }
    zchars
}

/// shifts the z-char in a 2 bytes-array to the right position
/// shift_length has 3 possibilities: 10, 5, 0
/// an z-char use 5 bytes
/// look into two bytes:
/// ____byte one____ ____byte two____
/// 1 2 3 4 5 6  7 8 1 2 3  4 5 6 7 8
///   ^          ^          1
///   1 2 3 4 5  1 2 3 4 5  1 2 3 4 5
///   1. zchar   2. zchar   3. zchar
///   10         5          0
fn shift(zchar: u16, position: u8) -> u16 {
    let shift_length = 10 - (position % 3) * 5;
    zchar << shift_length
}

/// Returns the location of the character of the specified index in the zcode character array
///
/// # Examples
///
fn pos_in_alpha(letter: u8) -> i8 {
    for i in 0..ALPHABET.len() {
        if ALPHABET[i] as u8 == letter {
            return i as i8
        }
    }

    return -1
}

/// returns the position in the unicode-table
pub fn pos_in_unicode(letter: u16, unicode_table: &Vec<u16>) -> i8 {
    for (i, character) in unicode_table.iter().enumerate() {
        if *character == letter {
            return i as i8
        }
    }

    return -1
}

/// position in the vector from the position of an character in the string
/// every 3 zchars encode() writes 2 bytes
/// for example "helloworld"
/// "h": nothing
/// "e": nothing
/// "l": write 2 bytes to position 0   (2 * 2/3))
/// "l": nothing
/// "o": nothing
/// "w": write 2 bytes to position 2   (2 * 5/3))
/// ...
///
/// # Examples
///
/// ```ignore
/// assert_eq!(pos_to_index(5), 2);
/// ```
fn pos_to_index(position: usize) -> usize {
    2 * (position / 3)
}

#[test]
fn test_pos_in_alpha() {
    assert_eq!(pos_in_alpha('a' as u8), 0);
    assert_eq!(pos_in_alpha('b' as u8), 1);
    assert_eq!(pos_in_alpha('c' as u8), 2);
    assert_eq!(pos_in_alpha('A' as u8), 26);
    assert_eq!(pos_in_alpha('B' as u8), 27);
    assert_eq!(pos_in_alpha('C' as u8), 28);
}

#[test]
fn test_pos_to_index() {
    assert_eq!(pos_to_index(5), 2);
}

#[test]
fn test_shift() {
    assert_eq!(shift(6,2), 6);
    assert_eq!(shift(26,5), 26);
}<|endoftext|>


<commit_before><commit_msg>Library update noise<commit_after><|endoftext|>


<commit_before>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Tests for async mode.. should be run with RUST_TEST_THREADS=1

pub mod common;

//mines for a bit on each available plugin, one after the other
#[test]
fn on_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("");
	for c in &caps {
		let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		common::mine_async_for_duration(plugin_path_vec, 30, None);
	}
}

//Same as above, but only for cuda
#[test]
fn on_cuda_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("cuda");
	for c in &caps {
	 let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		common::mine_async_for_duration(plugin_path_vec, 60, None);
	}
}

//mine cuda and matrix (mean) miner for a bit
#[test]
fn on_cuda_commit_mine_mean_cpu_and_lean_cuda_async() {
	let caps = common::get_plugin_vec("");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		if c.full_path.contains("lean_cuda_30") || c.full_path.contains("mean_cpu_30"){
			plugin_path_vec.push(&c.full_path);
		}
	}
	common::mine_async_for_duration(plugin_path_vec, 180, None);
}

//Mines for a bit on all available plugins at once
//(won't be efficient, but should stress-tes plugins nicely)
#[test]
fn on_commit_mine_plugins_async() {
	// Get a list of installed plugins and capabilities
	// only do cuckoo 30s
	let caps = common::get_plugin_vec("16");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		//Have to confine this for the time being to 2, due to travis CI memory constraints
		if c.full_path.contains("lean_cuda") || c.full_path.contains("mean_cpu"){
			plugin_path_vec.push(&c.full_path);
		}
	}
	common::mine_async_for_duration(plugin_path_vec, 120, None);
}
<commit_msg>travis memory limits<commit_after>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Tests for async mode.. should be run with RUST_TEST_THREADS=1

pub mod common;

//mines for a bit on each available plugin, one after the other
#[test]
fn on_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("16");
	for c in &caps {
		let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		common::mine_async_for_duration(plugin_path_vec, 30, None);
	}
}

//Same as above, but only for cuda
#[test]
fn on_cuda_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("cuda");
	for c in &caps {
	 let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		common::mine_async_for_duration(plugin_path_vec, 60, None);
	}
}

//mine cuda and matrix (mean) miner for a bit
#[test]
fn on_cuda_commit_mine_mean_cpu_and_lean_cuda_async() {
	let caps = common::get_plugin_vec("");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		if c.full_path.contains("lean_cuda_30") || c.full_path.contains("mean_cpu_30"){
			plugin_path_vec.push(&c.full_path);
		}
	}
	common::mine_async_for_duration(plugin_path_vec, 180, None);
}

//Mines for a bit on all available plugins at once
//(won't be efficient, but should stress-tes plugins nicely)
#[test]
fn on_commit_mine_plugins_async() {
	// Get a list of installed plugins and capabilities
	// only do cuckoo 30s
	let caps = common::get_plugin_vec("16");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		//Have to confine this for the time being to 2, due to travis CI memory constraints
		if c.full_path.contains("lean_cuda") || c.full_path.contains("mean_cpu"){
			plugin_path_vec.push(&c.full_path);
		}
	}
	common::mine_async_for_duration(plugin_path_vec, 120, None);
}
<|endoftext|>


<commit_before>use jsrs_common::ast::BinOp::*;
use jsrs_common::ast::Exp::*;
use jsrs_common::ast::Stmt::*;
use std::f64::NAN;

macro_rules! format_exp {
    ($e1:expr, $o:expr, $e2:expr) => { &format!("{}", exp!($e1, $o, $e2)) }
}

macro_rules! format_assign {
    ($s:expr, $e:expr) => { &format!("{}", assign!($s, $e)) }
}

macro_rules! format_bare_exp {
    ($e:expr) => { &format!("{}", BareExp($e)) }
}

macro_rules! format_decl {
    ($s:expr, $e:expr) => { &format!("{}", decl!($s, $e)) }
}

macro_rules! format_seq {
    ($s1:expr, $s2:expr) => { &format!("{}", seq!($s1, $s2)) }
}

#[test]
fn constants() {
    // Floating point values specifically chosen so fractional part can be perfectly represented
    // by floating-point numbers.
    assert_eq!("12.25", format!("{}", Float(12.25)));
    assert_eq!("-3.5", format!("{}", Float(-3.5)));
    assert_eq!("NaN", format!("{}", Float(NAN)));
    assert_eq!("undefined", format!("{}", Undefined));
}

#[test]
fn vars() {
    assert_eq!("x", format!("{}", var!("x")));
    assert_eq!("X", format!("{}", var!("X")));
    assert_eq!("_x", format!("{}", var!("_x")));
    assert_eq!("_x2", format!("{}", var!("_x2")));
    assert_eq!("xX_", format!("{}", var!("xX_")));
    assert_eq!("X_x", format!("{}", var!("X_x")));
    assert_eq!("-x", format!("{}", neg_var!("x")));
    assert_eq!("+_2", format!("{}", pos_var!("_2")));
}

#[test]
fn single_binop_exprs() {
    assert_eq!("-14 * -num", format_exp!(Float(-14.0), Star, neg_var!("num")));
    assert_eq!("+z++ - -10", format_exp!(post_inc!(pos_var!("z")), Minus, Float(-10.0)));
    assert_eq!("12.25 + 72", format_exp!(Float(12.25), Plus, Float(72.0)));
    assert_eq!("-3 * 42.5", format_exp!(Float(-3.0), Star, Float(42.5)));
    assert_eq!("22 / x", format_exp!(Float(22.0), Slash, var!("x")));
    assert_eq!("3 - -----y", format_exp!(Float(3.0), Minus, pre_dec!(pre_dec!(neg_var!("y")))));
}

#[test]
fn multi_binop_exprs_no_grouping() {
    assert_eq!("x + 18.5 - 17",
        format_exp!(exp!(var!("x"), Plus, Float(18.5)), Minus, Float(17.0)));
    assert_eq!("-10 / +num - 17",
        format_exp!(exp!(Float(-10.0), Slash, pos_var!("num")), Minus, Float(17.0)));
    assert_eq!("-10 * 18.5 + -some_num",
        format_exp!(exp!(Float(-10.0), Star, Float(18.5)), Plus, neg_var!("some_num")));
    assert_eq!("anotherNumber - _x / 17",
        format_exp!(var!("anotherNumber"), Minus, exp!(var!("_x"), Slash, Float(17.0))));
    assert_eq!("_ - 18.5 + x2 * -3.25",
        format_exp!(exp!(var!("_"), Minus, Float(18.5)), Plus, exp!(var!("x2"), Star, Float(-3.25))));
    assert_eq!("NUMBER * 18.5 / 17 + ---N_4",
        format_exp!(exp!(exp!(var!("NUMBER"), Star, Float(18.5)), Slash, Float(17.0)), Plus, pre_dec!(neg_var!("N_4"))));
}

#[test]
fn multi_binop_exprs_with_grouping() {
    assert_eq!("_7 * (e_4_4 + OkDk)",
        format_exp!(var!("_7"), Star, exp!(var!("e_4_4"), Plus, var!("OkDk"))));
    assert_eq!("(-10 - 18.5) / 17",
        format_exp!(exp!(Float(-10.0), Minus, Float(18.5)), Slash, Float(17.0)));
    assert_eq!("-10 - (O_k + 17)",
        format_exp!(Float(-10.0), Minus, exp!(var!("O_k"), Plus, Float(17.0))));
    assert_eq!("-10 / (O_k * 17)",
        format_exp!(Float(-10.0), Slash, exp!(var!("O_k"), Star, Float(17.0))));
    assert_eq!("(_Ok - h2o) * 17 / -3.25",
        format_exp!(exp!(var!("_Ok"), Minus, var!("h2o")), Star, exp!(Float(17.0), Slash, Float(-3.25))));
    assert_eq!("(-10 + 18.5 - 17) * -3.25",
        format_exp!(exp!(exp!(Float(-10.0), Plus, Float(18.5)), Minus, Float(17.0)), Star, Float(-3.25)));
    assert_eq!("(-10 - (18.5 - 17)) / -3.25",
        format_exp!(exp!(Float(-10.0), Minus, exp!(Float(18.5), Minus, Float(17.0))), Slash, Float(-3.25)));
}

#[test]
fn assign_stmts() {
    assert_eq!("x = NaN;\n", format_assign!("x", Float(NAN)));
    assert_eq!("someThing = 8.25 - OTHER;\n",
        format_assign!("someThing", exp!(Float(8.25), Minus, var!("OTHER"))));
    assert_eq!("thing2 = r * -51 + 3.5;\n",
        format_assign!("thing2", exp!(exp!(var!("r"), Star, Float(-51.0)), Plus, Float(3.5))));
    assert_eq!("_2 = (-42.5 + undefined) / 7.125;\n",
        format_assign!("_2", exp!(exp!(Float(-42.5), Plus, Undefined), Slash, Float(7.125))));
}

#[test]
fn bare_exp_stmts() {
    assert_eq!("-3.5;\n", format_bare_exp!(Float(-3.5)));
    assert_eq!("NaN;\n", format_bare_exp!(Float(NAN)));
    assert_eq!("x - -10;\n", format_bare_exp!(exp!(var!("x"), Minus, Float(-10.0))));
    assert_eq!("-3 * 42.5;\n", format_bare_exp!(exp!(Float(-3.0), Star, Float(42.5))));
    assert_eq!("-10 / num - 17;\n",
        format_bare_exp!(exp!(exp!(Float(-10.0), Slash, var!("num")), Minus, Float(17.0))));
    assert_eq!("NUMBER * 18.5 / 17 + N_4;\n",
        format_bare_exp!(exp!(exp!(exp!(var!("NUMBER"), Star, Float(18.5)), Slash, Float(17.0)), Plus, var!("N_4"))));
    assert_eq!("-10 / (O_k * 17);\n",
        format_bare_exp!(exp!(Float(-10.0), Slash, exp!(var!("O_k"), Star, Float(17.0)))));
    assert_eq!("(-10 - (18.5 - 17)) / -3.25;\n",
        format_bare_exp!(exp!(exp!(Float(-10.0), Minus, exp!(Float(18.5), Minus, Float(17.0))), Slash, Float(-3.25))));
}

#[test]
fn decl_stmts() {
    assert_eq!("var _Nu4 = 2.25;\n", format_decl!("_Nu4", Float(2.25)));
    assert_eq!("var nU_M = x * -72;\n", format_decl!("nU_M", exp!(var!("x"), Star, Float(-72.0))));
    assert_eq!("var NUM = -34.5 / _l4 + 8;\n",
        format_decl!("NUM", exp!(exp!(Float(-34.5), Slash, var!("_l4")), Plus, Float(8.0))));
    assert_eq!("var eleven = (Y + 3) * -11;\n",
        format_decl!("eleven", exp!(exp!(var!("Y"), Plus, Float(3.0)), Star, Float(-11.0))));
}

#[test]
fn seq_stmts() {
    assert_eq!("someThing = 8.25 - OTHER;\n-3 * 42.5;\n",
        format_seq!(assign!("someThing", exp!(Float(8.25), Minus, var!("OTHER"))),
                    BareExp(exp!(Float(-3.0), Star, Float(42.5)))));
    assert_eq!("-10 / num - 17;\nvar NUM = -34.5 / _l4 + 8;\nthing2 = r * -51 + 3.5;\n", format_seq!(
        BareExp(exp!(exp!(Float(-10.0), Slash, var!("num")), Minus, Float(17.0))), seq!(
            decl!("NUM", exp!(exp!(Float(-34.5), Slash, var!("_l4")), Plus, Float(8.0))),
            assign!("thing2", exp!(exp!(var!("r"), Star, Float(-51.0)), Plus, Float(3.5))))));
}
<commit_msg>added format tests for boolean operations<commit_after>use jsrs_common::ast::BinOp::*;
use jsrs_common::ast::Exp::*;
use jsrs_common::ast::Stmt::*;
use std::f64::NAN;

macro_rules! format_exp {
    ($e1:expr, $o:expr, $e2:expr) => { &format!("{}", exp!($e1, $o, $e2)) }
}

macro_rules! format_assign {
    ($s:expr, $e:expr) => { &format!("{}", assign!($s, $e)) }
}

macro_rules! format_bare_exp {
    ($e:expr) => { &format!("{}", BareExp($e)) }
}

macro_rules! format_decl {
    ($s:expr, $e:expr) => { &format!("{}", decl!($s, $e)) }
}

macro_rules! format_seq {
    ($s1:expr, $s2:expr) => { &format!("{}", seq!($s1, $s2)) }
}

macro_rules! pos_float {
    ($e:expr) => { Pos(Box::new(Float($e))) }
}

#[test]
fn constants() {
    // Floating point values specifically chosen so fractional part can be perfectly represented
    // by floating-point numbers.
    assert_eq!("12.25", format!("{}", Float(12.25)));
    assert_eq!("-3.5", format!("{}", Float(-3.5)));
    assert_eq!("NaN", format!("{}", Float(NAN)));
    assert_eq!("undefined", format!("{}", Undefined));
    assert_eq!("false", format!("{}", Bool(false)));
    assert_eq!("true", format!("{}", Bool(true)));
}

#[test]
fn vars() {
    assert_eq!("x", format!("{}", var!("x")));
    assert_eq!("X", format!("{}", var!("X")));
    assert_eq!("_x", format!("{}", var!("_x")));
    assert_eq!("_x2", format!("{}", var!("_x2")));
    assert_eq!("xX_", format!("{}", var!("xX_")));
    assert_eq!("X_x", format!("{}", var!("X_x")));
    assert_eq!("-x", format!("{}", neg_var!("x")));
    assert_eq!("+_2", format!("{}", pos_var!("_2")));
}

#[test]
fn single_binop_exprs() {
    assert_eq!("-14 * -num", format_exp!(Float(-14.0), Star, neg_var!("num")));
    assert_eq!("+z++ - -10", format_exp!(post_inc!(pos_var!("z")), Minus, Float(-10.0)));
    assert_eq!("12.25 + 72", format_exp!(Float(12.25), Plus, Float(72.0)));
    assert_eq!("-3 * 42.5", format_exp!(Float(-3.0), Star, Float(42.5)));
    assert_eq!("22 / x", format_exp!(Float(22.0), Slash, var!("x")));
    assert_eq!("3 - -----y", format_exp!(Float(3.0), Minus, pre_dec!(pre_dec!(neg_var!("y")))));
    assert_eq!("_L2-- == -55.5", format_exp!(post_dec!(var!("_L2")), Eql, Float(-55.5)));
    assert_eq!("+22 != Z", format_exp!(pos_float!(22.0), Neq, var!("Z")));
    assert_eq!("-y > xX", format_exp!(neg_var!("y"), Gt, var!("xX")));
    assert_eq!("39 >= -76.25", format_exp!(Float(39.0), Ge, Float(-76.25)));
    assert_eq!("+++32 < -num--", format_exp!(pre_inc!(pos_float!(32.0)), Lt, post_dec!(neg_var!("num"))));
    assert_eq!("X_x <= 54.5", format_exp!(var!("X_x"), Le, Float(54.5)));
    assert_eq!("12++ && x_92", format_exp!(post_inc!(Float(12.0)), And, var!("x_92")));
    assert_eq!("99 || false", format_exp!(Float(99.0), Or, Bool(false)));
}

#[test]
fn multi_binop_exprs_no_grouping() {
    assert_eq!("x + 18.5 - 17",
        format_exp!(exp!(var!("x"), Plus, Float(18.5)), Minus, Float(17.0)));
    assert_eq!("-10 / +num - 17",
        format_exp!(exp!(Float(-10.0), Slash, pos_var!("num")), Minus, Float(17.0)));
    assert_eq!("-10 * 18.5 + -some_num",
        format_exp!(exp!(Float(-10.0), Star, Float(18.5)), Plus, neg_var!("some_num")));
    assert_eq!("anotherNumber - _x / 17",
        format_exp!(var!("anotherNumber"), Minus, exp!(var!("_x"), Slash, Float(17.0))));
    assert_eq!("x <= 32 && y++ == 88.5",
        format_exp!(exp!(var!("x"), Le, Float(32.0)), And, exp!(post_inc!(var!("y")), Eql, Float(88.5))));
    assert_eq!("17 < +NUMBER---- * -3 + w && false || some_bool",
        format_exp!(exp!(exp!(Float(17.0), Lt, exp!(exp!(post_dec!(post_dec!(pos_var!("NUMBER"))), Star, Float(-3.0)), Plus, var!("w"))),
            And, Bool(false)), Or, var!("some_bool")));
    assert_eq!("_ - 18.5 + x2 * -3.25",
        format_exp!(exp!(var!("_"), Minus, Float(18.5)), Plus, exp!(var!("x2"), Star, Float(-3.25))));
    assert_eq!("NUMBER * 18.5 / 17 + ---N_4",
        format_exp!(exp!(exp!(var!("NUMBER"), Star, Float(18.5)), Slash, Float(17.0)), Plus, pre_dec!(neg_var!("N_4"))));
}

#[test]
fn multi_binop_exprs_with_grouping() {
    assert_eq!("_7 * (e_4_4 + OkDk)",
        format_exp!(var!("_7"), Star, exp!(var!("e_4_4"), Plus, var!("OkDk"))));
    assert_eq!("(-10 - 18.5) / 17",
        format_exp!(exp!(Float(-10.0), Minus, Float(18.5)), Slash, Float(17.0)));
    assert_eq!("-10 - (O_k + 17)",
        format_exp!(Float(-10.0), Minus, exp!(var!("O_k"), Plus, Float(17.0))));
    assert_eq!("-10 / (O_k * 17)",
        format_exp!(Float(-10.0), Slash, exp!(var!("O_k"), Star, Float(17.0))));
    assert_eq!("+(++(((((a || b) && c) == d) + e) * f))",
        &format!("{}", Pos(Box::new(pre_inc!(
            exp!(exp!(exp!(exp!(exp!(var!("a"), Or, var!("b")), And, var!("c")), Eql, var!("d")), Plus, var!("e")), Star, var!("f")))))));
    assert_eq!("(_Ok - h2o) * 17 / -3.25",
        format_exp!(exp!(var!("_Ok"), Minus, var!("h2o")), Star, exp!(Float(17.0), Slash, Float(-3.25))));
    assert_eq!("(-10 + 18.5 - 17) * -3.25",
        format_exp!(exp!(exp!(Float(-10.0), Plus, Float(18.5)), Minus, Float(17.0)), Star, Float(-3.25)));
    assert_eq!("(-10 - (18.5 - 17)) / -3.25",
        format_exp!(exp!(Float(-10.0), Minus, exp!(Float(18.5), Minus, Float(17.0))), Slash, Float(-3.25)));
}

#[test]
fn assign_stmts() {
    assert_eq!("x = NaN;\n", format_assign!("x", Float(NAN)));
    assert_eq!("someThing = 8.25 - OTHER;\n",
        format_assign!("someThing", exp!(Float(8.25), Minus, var!("OTHER"))));
    assert_eq!("thing2 = r * -51 + 3.5;\n",
        format_assign!("thing2", exp!(exp!(var!("r"), Star, Float(-51.0)), Plus, Float(3.5))));
    assert_eq!("_2 = (-42.5 + undefined) / 7.125;\n",
        format_assign!("_2", exp!(exp!(Float(-42.5), Plus, Undefined), Slash, Float(7.125))));
}

#[test]
fn bare_exp_stmts() {
    assert_eq!("-3.5;\n", format_bare_exp!(Float(-3.5)));
    assert_eq!("NaN;\n", format_bare_exp!(Float(NAN)));
    assert_eq!("x - -10;\n", format_bare_exp!(exp!(var!("x"), Minus, Float(-10.0))));
    assert_eq!("-3 * 42.5;\n", format_bare_exp!(exp!(Float(-3.0), Star, Float(42.5))));
    assert_eq!("-10 / num - 17;\n",
        format_bare_exp!(exp!(exp!(Float(-10.0), Slash, var!("num")), Minus, Float(17.0))));
    assert_eq!("NUMBER * 18.5 / 17 + N_4;\n",
        format_bare_exp!(exp!(exp!(exp!(var!("NUMBER"), Star, Float(18.5)), Slash, Float(17.0)), Plus, var!("N_4"))));
    assert_eq!("-10 / (O_k * 17);\n",
        format_bare_exp!(exp!(Float(-10.0), Slash, exp!(var!("O_k"), Star, Float(17.0)))));
    assert_eq!("(-10 - (18.5 - 17)) / -3.25;\n",
        format_bare_exp!(exp!(exp!(Float(-10.0), Minus, exp!(Float(18.5), Minus, Float(17.0))), Slash, Float(-3.25))));
}

#[test]
fn decl_stmts() {
    assert_eq!("var _Nu4 = 2.25;\n", format_decl!("_Nu4", Float(2.25)));
    assert_eq!("var nU_M = x * -72;\n", format_decl!("nU_M", exp!(var!("x"), Star, Float(-72.0))));
    assert_eq!("var NUM = -34.5 / _l4 + 8;\n",
        format_decl!("NUM", exp!(exp!(Float(-34.5), Slash, var!("_l4")), Plus, Float(8.0))));
    assert_eq!("var eleven = (Y + 3) * -11;\n",
        format_decl!("eleven", exp!(exp!(var!("Y"), Plus, Float(3.0)), Star, Float(-11.0))));
}

#[test]
fn seq_stmts() {
    assert_eq!("someThing = 8.25 - OTHER;\n-3 * 42.5;\n",
        format_seq!(assign!("someThing", exp!(Float(8.25), Minus, var!("OTHER"))),
            BareExp(exp!(Float(-3.0), Star, Float(42.5)))));
    assert_eq!("-10 / num - 17;\nvar NUM = -34.5 / _l4 + 8;\nthing2 = r * -51 + 3.5;\n", format_seq!(
        BareExp(exp!(exp!(Float(-10.0), Slash, var!("num")), Minus, Float(17.0))), seq!(
            decl!("NUM", exp!(exp!(Float(-34.5), Slash, var!("_l4")), Plus, Float(8.0))),
            assign!("thing2", exp!(exp!(var!("r"), Star, Float(-51.0)), Plus, Float(3.5))))));
}
<|endoftext|>


<commit_before>use ecs::*;
use spatial_hash::*;
use util::LeakyReserver;
use math::Coord;

struct Env {
    sh: SpatialHashTable,
    ctx: EcsCtx,
    ids: LeakyReserver<EntityId>,
}

impl Env {
    fn new() -> Self {
        Env {
            sh: SpatialHashTable::new(),
            ctx: EcsCtx::new(),
            ids: LeakyReserver::new(),
        }
    }
}

#[test]
fn insert_remove() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let coord = Coord::new(1, 2);

    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(coord);
        entity.insert_solid();

        entity.id()
    };

    assert!(!env.sh.get(coord).solid());
    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action); // this resets the action so it can be reused
    assert!(env.sh.get(coord).solid());

    {
        let mut entity = action.entity_mut(id);
        entity.remove_solid();
    }

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);
    assert!(!env.sh.get(coord).solid());
}

#[test]
fn insert_move() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let start_coord = Coord::new(1, 2);
    let end_coord = Coord::new(1, 3);

    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(start_coord);
        entity.insert_solid();

        entity.id()
    };

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    {
        let mut entity = action.entity_mut(id);
        entity.insert_position(end_coord);
    }

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert!(!env.sh.get(start_coord).solid());
    assert!(env.sh.get(end_coord).solid());
}

#[test]
fn remove_position() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let start_coord = Coord::new(1, 2);

    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(start_coord);
        entity.insert_solid();

        entity.id()
    };

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    {
        let mut entity = action.entity_mut(id);
        entity.remove_position();
    }

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert!(!env.sh.get(start_coord).solid());
}

#[test]
fn insert_solid() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let start_coord = Coord::new(1, 2);

    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(start_coord);

        entity.id()
    };

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    {
        let mut entity = action.entity_mut(id);
        entity.insert_solid();
    }

    assert!(!env.sh.get(start_coord).solid());

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert!(env.sh.get(start_coord).solid());
}

#[test]
fn track_opacity() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let start_coord = Coord::new(1, 2);
    let end_coord = Coord::new(1, 3);

    // initialise with no opacity
    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(start_coord);

        entity.id()
    };

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert_eq!((env.sh.get(start_coord).opacity() * 10.0).round(), 0.0 * 10.0);

    // add an opacity of 0.5
    {
        let mut entity = action.entity_mut(id);
        entity.insert_opacity(0.5);
    }

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert_eq!((env.sh.get(start_coord).opacity() * 10.0).round(), 0.5 * 10.0);

    // decrease opacity to 0.2
    {
        let mut entity = action.entity_mut(id);
        entity.insert_opacity(0.2);
    }

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert_eq!((env.sh.get(start_coord).opacity() * 10.0).round(), 0.2 * 10.0);

    // move the entity
    {
        let mut entity = action.entity_mut(id);
        entity.insert_position(end_coord);
    }

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);
    assert_eq!((env.sh.get(start_coord).opacity() * 10.0).round(), 0.0 * 10.0);
    assert_eq!((env.sh.get(end_coord).opacity() * 10.0).round(), 0.2 * 10.0);
}
<commit_msg>Refactored spatial hash tests<commit_after>use ecs::*;
use spatial_hash::*;
use util::LeakyReserver;
use math::Coord;

struct Env {
    sh: SpatialHashTable,
    ctx: EcsCtx,
    ids: LeakyReserver<EntityId>,
}

impl Env {
    fn new() -> Self {
        Env {
            sh: SpatialHashTable::new(),
            ctx: EcsCtx::new(),
            ids: LeakyReserver::new(),
        }
    }
}

#[test]
fn insert_remove() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let coord = Coord::new(1, 2);

    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(coord);
        entity.insert_solid();

        entity.id()
    };

    assert!(!env.sh.get(coord).solid());
    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action); // this resets the action so it can be reused
    assert!(env.sh.get(coord).solid());

    action.entity_mut(id).remove_solid();

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);
    assert!(!env.sh.get(coord).solid());
}

#[test]
fn insert_move() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let start_coord = Coord::new(1, 2);
    let end_coord = Coord::new(1, 3);

    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(start_coord);
        entity.insert_solid();

        entity.id()
    };

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    action.entity_mut(id).insert_position(end_coord);

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert!(!env.sh.get(start_coord).solid());
    assert!(env.sh.get(end_coord).solid());
}

#[test]
fn remove_position() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let start_coord = Coord::new(1, 2);

    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(start_coord);
        entity.insert_solid();

        entity.id()
    };

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    action.entity_mut(id).remove_position();

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert!(!env.sh.get(start_coord).solid());
}

#[test]
fn insert_solid() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let start_coord = Coord::new(1, 2);

    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(start_coord);

        entity.id()
    };

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    action.entity_mut(id).insert_solid();

    assert!(!env.sh.get(start_coord).solid());

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert!(env.sh.get(start_coord).solid());
}

#[test]
fn track_opacity() {
    let mut env = Env::new();

    let mut action = EcsAction::new();
    let start_coord = Coord::new(1, 2);
    let end_coord = Coord::new(1, 3);

    // initialise with no opacity
    let id = {
        let mut entity = action.entity_mut(env.ids.reserve());
        entity.insert_position(start_coord);

        entity.id()
    };

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert_eq!((env.sh.get(start_coord).opacity() * 10.0).round(), 0.0 * 10.0);

    // add an opacity of 0.5
    action.entity_mut(id).insert_opacity(0.5);

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert_eq!((env.sh.get(start_coord).opacity() * 10.0).round(), 0.5 * 10.0);

    // decrease opacity to 0.2
    action.entity_mut(id).insert_opacity(0.2);

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);

    assert_eq!((env.sh.get(start_coord).opacity() * 10.0).round(), 0.2 * 10.0);

    // move the entity
    action.entity_mut(id).insert_position(end_coord);

    env.sh.update(&env.ctx, &action);
    env.ctx.commit(&mut action);
    assert_eq!((env.sh.get(start_coord).opacity() * 10.0).round(), 0.0 * 10.0);
    assert_eq!((env.sh.get(end_coord).opacity() * 10.0).round(), 0.2 * 10.0);
}
<|endoftext|>


<commit_before>use gfx;
use gfx_core;
use memmap::MmapViewSync;
use vec_map::VecMap;

use terrain::quadtree::{Node, NodeId};
use runtime_texture::{TextureArray, TextureFormat};

#[derive(Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Priority(f32);
impl Priority {
    pub fn cutoff() -> Self {
        Priority(1.0)
    }
    pub fn none() -> Self {
        Priority(-1.0)
    }
    pub fn from_f32(value: f32) -> Self {
        assert!(value.is_finite());
        Priority(value)
    }
}
impl Eq for Priority {}
impl Ord for Priority {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.partial_cmp(other).unwrap()
    }
}

pub const NUM_LAYERS: usize = 3;

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub(crate) enum LayerType {
    Heights = 0,
    Colors = 1,
    Normals = 2,
}
impl LayerType {
    pub fn cache_size(&self) -> u16 {
        match *self {
            LayerType::Heights => 1024,
            LayerType::Colors => 512,
            LayerType::Normals => 96,
        }
    }
    pub fn index(&self) -> usize {
        *self as usize
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct LayerParams {
    /// What kind of layer this is. There can be at most one of each layer type in a file.
    pub layer_type: LayerType,
    /// Byte offset from start of file.
    pub offset: usize,
    /// Number of tiles in layer.
    pub tile_count: usize,
    /// Number of samples in each dimension, per tile.
    pub tile_resolution: u32,
    /// Number of samples outside the tile on each side.
    pub border_size: u32,
    /// Format used by this layer.
    pub format: TextureFormat,
    /// Number of bytes per tile.
    pub tile_bytes: usize,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct NoiseParams {
    pub offset: usize,
    pub resolution: u32,
    pub format: TextureFormat,
    pub bytes: usize,
    pub wavelength: f32,
}

#[derive(Serialize, Deserialize)]
pub(crate) struct TileHeader {
    pub layers: Vec<LayerParams>,
    pub noise: NoiseParams,
    pub nodes: Vec<Node>,
}

pub(crate) struct TileCache<R: gfx::Resources> {
    /// Maximum number of slots in this `TileCache`.
    size: usize,
    /// Actually contents of the cache.
    slots: Vec<(Priority, NodeId)>,
    /// Which index each node is at in the cache (if any).
    reverse: VecMap<usize>,
    /// Nodes that should be added to the cache.
    missing: Vec<(Priority, NodeId)>,
    /// Smallest priority among all nodes in the cache.
    min_priority: Priority,

    /// Resolution of each tile in this cache.
    layer_params: LayerParams,

    texture: TextureArray<R>,

    /// Section of memory map that holds the data for this layer.
    data_file: MmapViewSync,
}
impl<R: gfx::Resources> TileCache<R> {
    pub fn new<F: gfx::Factory<R>>(
        params: LayerParams,
        data_file: MmapViewSync,
        factory: &mut F,
    ) -> Self {
        let cache_size = params.layer_type.cache_size();
        let texture = TextureArray::new(
            params.format,
            params.tile_resolution as u16,
            cache_size,
            factory,
        );

        Self {
            size: cache_size as usize,
            slots: Vec::new(),
            reverse: VecMap::new(),
            missing: Vec::new(),
            min_priority: Priority::none(),
            layer_params: params,
            data_file,
            texture,
        }
    }

    pub fn update_priorities(&mut self, nodes: &mut Vec<Node>) {
        for &mut (ref mut priority, id) in self.slots.iter_mut() {
            *priority = nodes[id].priority();
        }

        self.min_priority = self.slots.iter().map(|s| s.0).min().unwrap_or(
            Priority::none(),
        );
    }

    pub fn add_missing(&mut self, element: (Priority, NodeId)) {
        if element.0 > self.min_priority || self.slots.len() < self.size {
            self.missing.push(element);
        }
    }

    pub fn load_missing<C: gfx_core::command::Buffer<R>>(
        &mut self,
        nodes: &mut Vec<Node>,
        encoder: &mut gfx::Encoder<R, C>,
    ) {
        if self.slots.len() + self.missing.len() < self.size {
            while let Some(m) = self.missing.pop() {
                let index = self.slots.len();
                self.slots.push(m.clone());
                self.load(m.1, &mut nodes[m.1], index, encoder);
            }
        } else {
            let mut possible: Vec<_> = self.slots
                .iter()
                .cloned()
                .chain(self.missing.iter().cloned())
                .collect();
            possible.sort();

            // Anything >= to cutoff should be included.
            let cutoff = possible[possible.len() - self.size];

            let mut index = 0;
            while let Some(m) = self.missing.pop() {
                if cutoff >= m {
                    continue;
                }

                // Find the next element to evict.
                while self.slots[index] >= cutoff {
                    index += 1;
                }

                self.slots[index] = m.clone();
                self.load(m.1, &mut nodes[m.1], index, encoder);
                index += 1;
            }
        }
    }

    fn load<C: gfx_core::command::Buffer<R>>(
        &mut self,
        id: NodeId,
        node: &mut Node,
        slot: usize,
        encoder: &mut gfx::Encoder<R, C>,
    ) {
        if slot < self.slots.len() {
            self.reverse.remove(self.slots[slot].1.index());
        }
        self.reverse.insert(id.index(), slot);

        let tile = node.tile_indices[self.layer_params.layer_type.index()].unwrap() as usize;
        let len = self.layer_params.tile_bytes;
        let offset = self.layer_params.offset + tile * len;
        let data = unsafe { &self.data_file.as_slice()[offset..(offset + len)] };

        self.texture.update_layer(
            slot as u16,
            self.layer_params.tile_resolution as u16,
            gfx::memory::cast_slice(data),
            encoder,
        )
    }

    pub fn contains(&self, id: NodeId) -> bool {
        self.reverse.contains_key(id.index())
    }

    pub fn get_slot(&self, id: NodeId) -> Option<usize> {
        self.reverse.get(id.index()).cloned()
    }

    pub fn get_texture_view_f32(&self) -> Option<&gfx_core::handle::ShaderResourceView<R, f32>> {
        match self.texture {
            TextureArray::F32 { ref view, .. } => Some(view),
            _ => None,
        }
    }

    pub fn get_texture_view_rgba8(
        &self,
    ) -> Option<&gfx_core::handle::ShaderResourceView<R, [f32; 4]>> {
        match self.texture {
            TextureArray::RGBA8 { ref view, .. } => Some(view),
            _ => None,
        }
    }

    pub fn get_texture_view_srgba(
        &self,
    ) -> Option<&gfx_core::handle::ShaderResourceView<R, [f32; 4]>> {
        match self.texture {
            TextureArray::SRGBA { ref view, .. } => Some(view),
            _ => None,
        }
    }

    pub fn resolution(&self) -> u32 {
        self.layer_params.tile_resolution
    }

    pub fn border(&self) -> u32 {
        self.layer_params.border_size
    }
}
<commit_msg>Fix bug in tile cache<commit_after>use gfx;
use gfx_core;
use memmap::MmapViewSync;
use vec_map::VecMap;

use terrain::quadtree::{Node, NodeId};
use runtime_texture::{TextureArray, TextureFormat};

#[derive(Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Priority(f32);
impl Priority {
    pub fn cutoff() -> Self {
        Priority(1.0)
    }
    pub fn none() -> Self {
        Priority(-1.0)
    }
    pub fn from_f32(value: f32) -> Self {
        assert!(value.is_finite());
        Priority(value)
    }
}
impl Eq for Priority {}
impl Ord for Priority {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.partial_cmp(other).unwrap()
    }
}

pub const NUM_LAYERS: usize = 3;

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub(crate) enum LayerType {
    Heights = 0,
    Colors = 1,
    Normals = 2,
}
impl LayerType {
    pub fn cache_size(&self) -> u16 {
        match *self {
            LayerType::Heights => 1024,
            LayerType::Colors => 512,
            LayerType::Normals => 96,
        }
    }
    pub fn index(&self) -> usize {
        *self as usize
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct LayerParams {
    /// What kind of layer this is. There can be at most one of each layer type in a file.
    pub layer_type: LayerType,
    /// Byte offset from start of file.
    pub offset: usize,
    /// Number of tiles in layer.
    pub tile_count: usize,
    /// Number of samples in each dimension, per tile.
    pub tile_resolution: u32,
    /// Number of samples outside the tile on each side.
    pub border_size: u32,
    /// Format used by this layer.
    pub format: TextureFormat,
    /// Number of bytes per tile.
    pub tile_bytes: usize,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct NoiseParams {
    pub offset: usize,
    pub resolution: u32,
    pub format: TextureFormat,
    pub bytes: usize,
    pub wavelength: f32,
}

#[derive(Serialize, Deserialize)]
pub(crate) struct TileHeader {
    pub layers: Vec<LayerParams>,
    pub noise: NoiseParams,
    pub nodes: Vec<Node>,
}

pub(crate) struct TileCache<R: gfx::Resources> {
    /// Maximum number of slots in this `TileCache`.
    size: usize,
    /// Actually contents of the cache.
    slots: Vec<(Priority, NodeId)>,
    /// Which index each node is at in the cache (if any).
    reverse: VecMap<usize>,
    /// Nodes that should be added to the cache.
    missing: Vec<(Priority, NodeId)>,
    /// Smallest priority among all nodes in the cache.
    min_priority: Priority,

    /// Resolution of each tile in this cache.
    layer_params: LayerParams,

    texture: TextureArray<R>,

    /// Section of memory map that holds the data for this layer.
    data_file: MmapViewSync,
}
impl<R: gfx::Resources> TileCache<R> {
    pub fn new<F: gfx::Factory<R>>(
        params: LayerParams,
        data_file: MmapViewSync,
        factory: &mut F,
    ) -> Self {
        let cache_size = params.layer_type.cache_size();
        let texture = TextureArray::new(
            params.format,
            params.tile_resolution as u16,
            cache_size,
            factory,
        );

        Self {
            size: cache_size as usize,
            slots: Vec::new(),
            reverse: VecMap::new(),
            missing: Vec::new(),
            min_priority: Priority::none(),
            layer_params: params,
            data_file,
            texture,
        }
    }

    pub fn update_priorities(&mut self, nodes: &mut Vec<Node>) {
        for &mut (ref mut priority, id) in self.slots.iter_mut() {
            *priority = nodes[id].priority();
        }

        self.min_priority = self.slots.iter().map(|s| s.0).min().unwrap_or(
            Priority::none(),
        );
    }

    pub fn add_missing(&mut self, element: (Priority, NodeId)) {
        if element.0 > self.min_priority || self.slots.len() < self.size {
            self.missing.push(element);
        }
    }

    pub fn load_missing<C: gfx_core::command::Buffer<R>>(
        &mut self,
        nodes: &mut Vec<Node>,
        encoder: &mut gfx::Encoder<R, C>,
    ) {
        while !self.missing.is_empty() && self.slots.len() < self.size {
            let m = self.missing.pop().unwrap();
            let index = self.slots.len();
            self.slots.push(m.clone());
            self.load(m.1, &mut nodes[m.1], index, encoder);
        }

        if !self.missing.is_empty() {
            let mut possible: Vec<_> = self.slots
                .iter()
                .cloned()
                .chain(self.missing.iter().cloned())
                .collect();
            possible.sort();

            // Anything >= to cutoff should be included.
            let cutoff = possible[possible.len() - self.size];

            let mut index = 0;
            while let Some(m) = self.missing.pop() {
                if cutoff >= m {
                    continue;
                }

                // Find the next element to evict.
                while self.slots[index] >= cutoff {
                    index += 1;
                }

                self.slots[index] = m.clone();
                self.load(m.1, &mut nodes[m.1], index, encoder);
                index += 1;
            }
        }
    }

    fn load<C: gfx_core::command::Buffer<R>>(
        &mut self,
        id: NodeId,
        node: &mut Node,
        slot: usize,
        encoder: &mut gfx::Encoder<R, C>,
    ) {
        if slot < self.slots.len() {
            self.reverse.remove(self.slots[slot].1.index());
        }
        self.reverse.insert(id.index(), slot);

        let tile = node.tile_indices[self.layer_params.layer_type.index()].unwrap() as usize;
        let len = self.layer_params.tile_bytes;
        let offset = self.layer_params.offset + tile * len;
        let data = unsafe { &self.data_file.as_slice()[offset..(offset + len)] };

        self.texture.update_layer(
            slot as u16,
            self.layer_params.tile_resolution as u16,
            gfx::memory::cast_slice(data),
            encoder,
        )
    }

    pub fn contains(&self, id: NodeId) -> bool {
        self.reverse.contains_key(id.index())
    }

    pub fn get_slot(&self, id: NodeId) -> Option<usize> {
        self.reverse.get(id.index()).cloned()
    }

    pub fn get_texture_view_f32(&self) -> Option<&gfx_core::handle::ShaderResourceView<R, f32>> {
        match self.texture {
            TextureArray::F32 { ref view, .. } => Some(view),
            _ => None,
        }
    }

    pub fn get_texture_view_rgba8(
        &self,
    ) -> Option<&gfx_core::handle::ShaderResourceView<R, [f32; 4]>> {
        match self.texture {
            TextureArray::RGBA8 { ref view, .. } => Some(view),
            _ => None,
        }
    }

    pub fn get_texture_view_srgba(
        &self,
    ) -> Option<&gfx_core::handle::ShaderResourceView<R, [f32; 4]>> {
        match self.texture {
            TextureArray::SRGBA { ref view, .. } => Some(view),
            _ => None,
        }
    }

    pub fn resolution(&self) -> u32 {
        self.layer_params.tile_resolution
    }

    pub fn border(&self) -> u32 {
        self.layer_params.border_size
    }
}
<|endoftext|>


<commit_before>extern crate inquerest;

use inquerest::*;

#[test]
fn test_filters(){
    assert_eq!(
        	Ok(
                Params {
                    filters: vec![
                        Filter {
                            connector: None,
                            condition: Condition {
                                left: Operand::Column("age".to_owned()),
                                equality: Equality::LT,
                                right: Operand::Number(13)
                            },
                            subfilter: vec![
                                Filter {
                                    connector: Some(
                                        Connector::AND
                                    ),
                                    condition: Condition {
                                        left: Operand::Column("student".to_owned()),
                                        equality: Equality::EQ,
                                        right: Operand::Boolean(true)
                                    },
                                    subfilter: vec![
                                        Filter {
                                            connector: Some(
                                                Connector::OR
                                            ),
                                            condition: Condition {
                                                left: Operand::Column("gender".to_owned()),
                                                equality: Equality::EQ,
                                                right: Operand::Column("M".to_owned())
                                            },
                                            subfilter: vec![]
                                        }
                                    ]
                                },

                            ]
                        }
                    ],
                    equations: vec![]
                }
            )

        , params("age=lt.13&student=eq.true|gender=eq.M"));
}

#[test]
fn test_filters_equations(){
    assert_eq!(
        	Ok(
                Params {
                    filters: vec![
                        Filter {
                            connector: None,
                            condition: Condition {
                                left: Operand::Column("age".to_owned()),
                                equality: Equality::LT,
                                right: Operand::Number(13)
                            },
                            subfilter: vec![
                                Filter {
                                    connector: Some(
                                        Connector::AND
                                    ),
                                    condition: Condition {
                                        left: Operand::Column("student".to_owned()),
                                        equality: Equality::EQ,
                                        right: Operand::Boolean(true)
                                    },
                                    subfilter: vec![
                                        Filter {
                                            connector: Some(
                                                Connector::OR
                                            ),
                                            condition: Condition {
                                                left: Operand::Column("gender".to_owned()),
                                                equality: Equality::EQ,
                                                right: Operand::Column("M".to_owned())
                                            },
                                            subfilter: vec![]
                                        }
                                    ]
                                },

                            ]
                        }
                    ],
                    equations: vec![Equation { left: Operand::Column("x".to_owned()), right: Operand::Number(123) }]
                }
            )

        , params("age=lt.13&student=eq.true|gender=eq.M&x=123"));
}

#[test]
fn test_filters_equations2(){
    assert_eq!(
        	Ok(
                Params {
                    filters: vec![
                        Filter {
                            connector: None,
                            condition: Condition {
                                left: Operand::Column("age".to_owned()),
                                equality: Equality::LT,
                                right: Operand::Number(13)
                            },
                            subfilter: vec![
                                Filter {
                                    connector: Some(
                                        Connector::AND
                                    ),
                                    condition: Condition {
                                        left: Operand::Column("student".to_owned()),
                                        equality: Equality::EQ,
                                        right: Operand::Boolean(true)
                                    },
                                    subfilter: vec![
                                        Filter {
                                            connector: Some(
                                                Connector::OR
                                            ),
                                            condition: Condition {
                                                left: Operand::Column("gender".to_owned()),
                                                equality: Equality::EQ,
                                                right: Operand::Column("M".to_owned())
                                            },
                                            subfilter: vec![]
                                        }
                                    ]
                                },

                            ]
                        }
                    ],
                    equations: vec![
                        Equation { left: Operand::Column("x".to_owned()), right: Operand::Number(123) },
                        Equation { left: Operand::Column("title".to_owned()), right: Operand::Column("engr".to_owned()) }
                        ]
                }
            )

        , params("age=lt.13&student=eq.true|gender=eq.M&x=123&title=engr"));
}

#[test]
fn test_filters2_equations2(){
    println!("{:#?}", params("age=lt.13&student=eq.true|gender=eq.M&age=lt.13&student=eq.true|gender=eq.M&x=123&title=engr"));
    assert_eq!(
        	Ok(
                Params {
                    filters: vec![
                        Filter {
                            connector: None,
                            condition: Condition {
                                left: Operand::Column("age".to_owned()),
                                equality: Equality::LT,
                                right: Operand::Number(13)
                            },
                            subfilter: vec![
                                Filter {
                                    connector: Some(
                                        Connector::AND
                                    ),
                                    condition: Condition {
                                        left: Operand::Column("student".to_owned()),
                                        equality: Equality::EQ,
                                        right: Operand::Boolean(true)
                                    },
                                    subfilter: vec![
                                        Filter {
                                            connector: Some(
                                                Connector::OR
                                            ),
                                            condition: Condition {
                                                left: Operand::Column("gender".to_owned()),
                                                equality: Equality::EQ,
                                                right: Operand::Column("M".to_owned())
                                            },
                                            subfilter: vec![
                                                    Filter {
                                                        connector: Some(Connector::AND),
                                                        condition: Condition {
                                                            left: Operand::Column("age".to_owned()),
                                                            equality: Equality::LT,
                                                            right: Operand::Number(13)
                                                        },
                                                        subfilter: vec![
                                                            Filter {
                                                                connector: Some(
                                                                    Connector::AND
                                                                ),
                                                                condition: Condition {
                                                                    left: Operand::Column("student".to_owned()),
                                                                    equality: Equality::EQ,
                                                                    right: Operand::Boolean(true)
                                                                },
                                                                subfilter: vec![
                                                                    Filter {
                                                                        connector: Some(
                                                                            Connector::OR
                                                                        ),
                                                                        condition: Condition {
                                                                            left: Operand::Column("gender".to_owned()),
                                                                            equality: Equality::EQ,
                                                                            right: Operand::Column("M".to_owned())
                                                                        },
                                                                        subfilter: vec![]
                                                                    }
                                                                ]
                                                            },

                                                        ]
                                                    }
                                            ]
                                        }
                                    ]
                                },

                            ]
                        },
                    ],
                    equations: vec![
                        Equation { left: Operand::Column("x".to_owned()), right: Operand::Number(123) },
                        Equation { left: Operand::Column("title".to_owned()), right: Operand::Column("engr".to_owned()) }
                        ]
                }
            )

        , params("age=lt.13&student=eq.true|gender=eq.M&age=lt.13&student=eq.true|gender=eq.M&x=123&title=engr"));
}

<commit_msg>queries when parses as param<commit_after>extern crate inquerest;

use inquerest::*;

#[test]
fn test_filters(){
    assert_eq!(
        	Ok(
                Params {
                    filters: vec![
                        Filter {
                            connector: None,
                            condition: Condition {
                                left: Operand::Column("age".to_owned()),
                                equality: Equality::LT,
                                right: Operand::Number(13)
                            },
                            subfilter: vec![
                                Filter {
                                    connector: Some(
                                        Connector::AND
                                    ),
                                    condition: Condition {
                                        left: Operand::Column("student".to_owned()),
                                        equality: Equality::EQ,
                                        right: Operand::Boolean(true)
                                    },
                                    subfilter: vec![
                                        Filter {
                                            connector: Some(
                                                Connector::OR
                                            ),
                                            condition: Condition {
                                                left: Operand::Column("gender".to_owned()),
                                                equality: Equality::EQ,
                                                right: Operand::Column("M".to_owned())
                                            },
                                            subfilter: vec![]
                                        }
                                    ]
                                },

                            ]
                        }
                    ],
                    equations: vec![]
                }
            )

        , params("age=lt.13&student=eq.true|gender=eq.M"));
}

#[test]
fn test_filters_equations(){
    assert_eq!(
        	Ok(
                Params {
                    filters: vec![
                        Filter {
                            connector: None,
                            condition: Condition {
                                left: Operand::Column("age".to_owned()),
                                equality: Equality::LT,
                                right: Operand::Number(13)
                            },
                            subfilter: vec![
                                Filter {
                                    connector: Some(
                                        Connector::AND
                                    ),
                                    condition: Condition {
                                        left: Operand::Column("student".to_owned()),
                                        equality: Equality::EQ,
                                        right: Operand::Boolean(true)
                                    },
                                    subfilter: vec![
                                        Filter {
                                            connector: Some(
                                                Connector::OR
                                            ),
                                            condition: Condition {
                                                left: Operand::Column("gender".to_owned()),
                                                equality: Equality::EQ,
                                                right: Operand::Column("M".to_owned())
                                            },
                                            subfilter: vec![]
                                        }
                                    ]
                                },

                            ]
                        }
                    ],
                    equations: vec![Equation { left: Operand::Column("x".to_owned()), right: Operand::Number(123) }]
                }
            )

        , params("age=lt.13&student=eq.true|gender=eq.M&x=123"));
}

#[test]
fn test_filters_equations2(){
    assert_eq!(
        	Ok(
                Params {
                    filters: vec![
                        Filter {
                            connector: None,
                            condition: Condition {
                                left: Operand::Column("age".to_owned()),
                                equality: Equality::LT,
                                right: Operand::Number(13)
                            },
                            subfilter: vec![
                                Filter {
                                    connector: Some(
                                        Connector::AND
                                    ),
                                    condition: Condition {
                                        left: Operand::Column("student".to_owned()),
                                        equality: Equality::EQ,
                                        right: Operand::Boolean(true)
                                    },
                                    subfilter: vec![
                                        Filter {
                                            connector: Some(
                                                Connector::OR
                                            ),
                                            condition: Condition {
                                                left: Operand::Column("gender".to_owned()),
                                                equality: Equality::EQ,
                                                right: Operand::Column("M".to_owned())
                                            },
                                            subfilter: vec![]
                                        }
                                    ]
                                },

                            ]
                        }
                    ],
                    equations: vec![
                        Equation { left: Operand::Column("x".to_owned()), right: Operand::Number(123) },
                        Equation { left: Operand::Column("title".to_owned()), right: Operand::Column("engr".to_owned()) }
                        ]
                }
            )

        , params("age=lt.13&student=eq.true|gender=eq.M&x=123&title=engr"));
}

#[test]
fn test_filters2_equations2(){
    println!("{:#?}", params("age=lt.13&student=eq.true|gender=eq.M&age=lt.13&student=eq.true|gender=eq.M&x=123&title=engr"));
    assert_eq!(
        	Ok(
                Params {
                    filters: vec![
                        Filter {
                            connector: None,
                            condition: Condition {
                                left: Operand::Column("age".to_owned()),
                                equality: Equality::LT,
                                right: Operand::Number(13)
                            },
                            subfilter: vec![
                                Filter {
                                    connector: Some(
                                        Connector::AND
                                    ),
                                    condition: Condition {
                                        left: Operand::Column("student".to_owned()),
                                        equality: Equality::EQ,
                                        right: Operand::Boolean(true)
                                    },
                                    subfilter: vec![
                                        Filter {
                                            connector: Some(
                                                Connector::OR
                                            ),
                                            condition: Condition {
                                                left: Operand::Column("gender".to_owned()),
                                                equality: Equality::EQ,
                                                right: Operand::Column("M".to_owned())
                                            },
                                            subfilter: vec![
                                                    Filter {
                                                        connector: Some(Connector::AND),
                                                        condition: Condition {
                                                            left: Operand::Column("age".to_owned()),
                                                            equality: Equality::LT,
                                                            right: Operand::Number(13)
                                                        },
                                                        subfilter: vec![
                                                            Filter {
                                                                connector: Some(
                                                                    Connector::AND
                                                                ),
                                                                condition: Condition {
                                                                    left: Operand::Column("student".to_owned()),
                                                                    equality: Equality::EQ,
                                                                    right: Operand::Boolean(true)
                                                                },
                                                                subfilter: vec![
                                                                    Filter {
                                                                        connector: Some(
                                                                            Connector::OR
                                                                        ),
                                                                        condition: Condition {
                                                                            left: Operand::Column("gender".to_owned()),
                                                                            equality: Equality::EQ,
                                                                            right: Operand::Column("M".to_owned())
                                                                        },
                                                                        subfilter: vec![]
                                                                    }
                                                                ]
                                                            },

                                                        ]
                                                    }
                                            ]
                                        }
                                    ]
                                },

                            ]
                        },
                    ],
                    equations: vec![
                        Equation { left: Operand::Column("x".to_owned()), right: Operand::Number(123) },
                        Equation { left: Operand::Column("title".to_owned()), right: Operand::Column("engr".to_owned()) }
                        ]
                }
            )

        , params("age=lt.13&student=eq.true|gender=eq.M&age=lt.13&student=eq.true|gender=eq.M&x=123&title=engr"));
}

#[test]
fn test_equations_from_join_filter_groupby_having_orderby_limit_as_param(){
    println!("{:#?}", params("from=bazaar.person&left_join=person_student&on=student.id&age=lt.13&student=eq.true&gender=eq.M&group_by=sum(age)&order_by=desc&limit=100&offset=25&x=123&y=456"));
    assert_eq!(
        	Ok(
    Params {
        filters: vec![],
        equations: vec![
            Equation {
                left: Operand::Column(
                    "from".to_owned()
                ),
                right: Operand::Column(
                    "bazaar.person".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "left_join".to_owned()
                ),
                right: Operand::Column(
                    "person_student".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "on".to_owned()
                ),
                right: Operand::Column(
                    "student.id".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "age".to_owned()
                ),
                right: Operand::Column(
                    "lt.13".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "student".to_owned()
                ),
                right: Operand::Column(
                    "eq.true".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "gender".to_owned()
                ),
                right: Operand::Column(
                    "eq.M".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "group_by".to_owned()
                ),
                right: Operand::Function(
                    Function {
                        function: "sum".to_owned(),
                        params: vec![
                            Operand::Column(
                                "age".to_owned()
                            )
                        ]
                    }
                )
            },
            Equation {
                left: Operand::Column(
                    "order_by".to_owned()
                ),
                right: Operand::Column(
                    "desc".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "limit".to_owned()
                ),
                right: Operand::Number(
                    100
                )
            },
            Equation {
                left: Operand::Column(
                    "offset".to_owned()
                ),
                right: Operand::Number(
                    25
                )
            },
            Equation {
                left: Operand::Column(
                    "x".to_owned()
                ),
                right: Operand::Number(
                    123
                )
            },
            Equation {
                left: Operand::Column(
                    "y".to_owned()
                ),
                right: Operand::Number(
                    456
                )
            }
        ]
    }
)

        , params(
"from=bazaar.person&left_join=person_student&on=student.id&age=lt.13&student=eq.true&gender=eq.M&group_by=sum(age)&order_by=desc&limit=100&offset=25&x=123&y=456"));
}

#[test]
fn test_equations_from_join_filter_groupby_having_orderby_limit_as_param2(){
    println!("{:#?}", params(
"age=lt.13&student=eq.true|gender=eq.M&group_by=sum(age)&order_by=desc&limit=100&offset=25&x=123&y=456&from=bazaar.person&left_join=person_student&on=student.id"));

    assert_eq!(
        Ok(
Params {
        filters: vec![
            Filter {
                connector: None,
                condition: Condition {
                    left: Operand::Column(
                        "age".to_owned()
                    ),
                    equality: Equality::LT,
                    right: Operand::Number(
                        13
                    )
                },
                subfilter: vec![
                    Filter {
                        connector: Some(
                            Connector::AND
                        ),
                        condition: Condition {
                            left: Operand::Column(
                                "student".to_owned()
                            ),
                            equality: Equality::EQ,
                            right: Operand::Boolean(
                                true
                            )
                        },
                        subfilter: vec![
                            Filter {
                                connector: Some(
                                    Connector::OR
                                ),
                                condition: Condition {
                                    left: Operand::Column(
                                        "gender".to_owned()
                                    ),
                                    equality: Equality::EQ,
                                    right: Operand::Column(
                                        "M".to_owned()
                                    )
                                },
                                subfilter: vec![]
                            }
                        ]
                    }
                ]
            }
        ],
        equations: vec![
            Equation {
                left: Operand::Column(
                    "group_by".to_owned()
                ),
                right: Operand::Function(
                    Function {
                        function: "sum".to_owned(),
                        params: vec![
                            Operand::Column(
                                "age".to_owned()
                            )
                        ]
                    }
                )
            },
            Equation {
                left: Operand::Column(
                    "order_by".to_owned()
                ),
                right: Operand::Column(
                    "desc".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "limit".to_owned()
                ),
                right: Operand::Number(
                    100
                )
            },
            Equation {
                left: Operand::Column(
                    "offset".to_owned()
                ),
                right: Operand::Number(
                    25
                )
            },
            Equation {
                left: Operand::Column(
                    "x".to_owned()
                ),
                right: Operand::Number(
                    123
                )
            },
            Equation {
                left: Operand::Column(
                    "y".to_owned()
                ),
                right: Operand::Number(
                    456
                )
            },
            Equation {
                left: Operand::Column(
                    "from".to_owned()
                ),
                right: Operand::Column(
                    "bazaar.person".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "left_join".to_owned()
                ),
                right: Operand::Column(
                    "person_student".to_owned()
                )
            },
            Equation {
                left: Operand::Column(
                    "on".to_owned()
                ),
                right: Operand::Column(
                    "student.id".to_owned()
                )
            }
        ]
    }
)

        , params(
"age=lt.13&student=eq.true|gender=eq.M&group_by=sum(age)&order_by=desc&limit=100&offset=25&x=123&y=456&from=bazaar.person&left_join=person_student&on=student.id"));
}

<|endoftext|>