<commit_before>macro_rules! skip_bytes (
  ($input: expr, $length: expr, $offset: expr) => (
    {
      match take!($input, $length) {
        $crate::nom::IResult::Done(i, bytes)   => {
          let head        = bytes[0] << $offset;
          let tail        = &bytes[1..];
          let is_all_zero = tail.iter().all(|byte| *byte == 0);

          if head == 0 && is_all_zero {
            $crate::nom::IResult::Done(i, bytes)
          } else {
            $crate::nom::IResult::Error($crate::nom::Err::Position(
              $crate::nom::ErrorCode::Digit as u32, $input))
          }
        }
        $crate::nom::IResult::Error(error)     =>
          $crate::nom::IResult::Error(error),
        $crate::nom::IResult::Incomplete(need) =>
          $crate::nom::IResult::Incomplete(need),
      }
    }
  );
);

macro_rules! count_slice (
  ($input: expr, $submac: ident!( $($args:tt)* ), $result: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;

      for result in $result {
        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            *result = o;

            input   = i;
            count  += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorCode::Count as u32, $input.0))
      } else if count == $result.len() {
        $crate::nom::IResult::Done(input, ())
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_slice!($i, call!($f), $count);
  );
);

macro_rules! count_bits (
  ($input: expr, $submac: ident!( $($args:tt)* ), $count: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;
      let mut result   = Vec::with_capacity($count);

      loop {
        if count == $count {
          break;
        }

        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            result.push(o);

            input  = i;
            count += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorCode::Count as u32, $input.0))
      } else if count == $count {
        $crate::nom::IResult::Done(input, result)
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_bits!($i, call!($f), $count);
  );
);

macro_rules! take_signed_bits (
  ($input: expr, $signed_type: ty, $count: expr) => (
    map!($input, take_bits!(u32, $count), |value| {
      let max_count = ::std::mem::size_of::<$signed_type>() * 8;

      if $count >= max_count || value < (1 << ($count - 1)) {
        value as $signed_type
      } else {
        (value as $signed_type).wrapping_sub(1 << $count)
      }
    });
  );
  ($input: expr, $count: expr) => (
    take_signed_bits!($input, i32, $count);
  );
);

#[cfg(test)]
mod tests {
  use super::*;
  use nom::{
    IResult,
    Err, ErrorCode
  };

  #[test]
  fn test_take_signed_bits() {
    let inputs      = [ (&[0b00100000][..], 2)
                      , (&[0b00011111][..], 2)
                      , (&[0b00001000, 0b00000000][..], 4)
                      , (&[0b00000111, 0b11111111][..], 4)
                      ];
    let results_i8  = [ IResult::Done((&[][..], 0), -32)
                      , IResult::Done((&[][..], 0), 31)
                      ];
    let results_i16 = [ IResult::Done((&[][..], 0), -2048)
                      , IResult::Done((&[][..], 0), 2047)
                      ];

    assert_eq!(take_signed_bits!(inputs[0], i8, 6), results_i8[0]);
    assert_eq!(take_signed_bits!(inputs[1], i8, 6), results_i8[1]);
    assert_eq!(take_signed_bits!(inputs[2], i16, 12), results_i16[0]);
    assert_eq!(take_signed_bits!(inputs[3], i16, 12), results_i16[1]);
  }
}
<commit_msg>Add tests for 32-bit signed integers<commit_after>macro_rules! skip_bytes (
  ($input: expr, $length: expr, $offset: expr) => (
    {
      match take!($input, $length) {
        $crate::nom::IResult::Done(i, bytes)   => {
          let head        = bytes[0] << $offset;
          let tail        = &bytes[1..];
          let is_all_zero = tail.iter().all(|byte| *byte == 0);

          if head == 0 && is_all_zero {
            $crate::nom::IResult::Done(i, bytes)
          } else {
            $crate::nom::IResult::Error($crate::nom::Err::Position(
              $crate::nom::ErrorCode::Digit as u32, $input))
          }
        }
        $crate::nom::IResult::Error(error)     =>
          $crate::nom::IResult::Error(error),
        $crate::nom::IResult::Incomplete(need) =>
          $crate::nom::IResult::Incomplete(need),
      }
    }
  );
);

macro_rules! count_slice (
  ($input: expr, $submac: ident!( $($args:tt)* ), $result: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;

      for result in $result {
        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            *result = o;

            input   = i;
            count  += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorCode::Count as u32, $input.0))
      } else if count == $result.len() {
        $crate::nom::IResult::Done(input, ())
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_slice!($i, call!($f), $count);
  );
);

macro_rules! count_bits (
  ($input: expr, $submac: ident!( $($args:tt)* ), $count: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;
      let mut result   = Vec::with_capacity($count);

      loop {
        if count == $count {
          break;
        }

        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            result.push(o);

            input  = i;
            count += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorCode::Count as u32, $input.0))
      } else if count == $count {
        $crate::nom::IResult::Done(input, result)
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_bits!($i, call!($f), $count);
  );
);

macro_rules! take_signed_bits (
  ($input: expr, $signed_type: ty, $count: expr) => (
    map!($input, take_bits!(u32, $count), |value| {
      let max_count = ::std::mem::size_of::<$signed_type>() * 8;

      if $count >= max_count || value < (1 << ($count - 1)) {
        value as $signed_type
      } else {
        (value as $signed_type).wrapping_sub(1 << $count)
      }
    });
  );
  ($input: expr, $count: expr) => (
    take_signed_bits!($input, i32, $count);
  );
);

#[cfg(test)]
mod tests {
  use super::*;
  use nom::{
    IResult,
    Err, ErrorCode
  };

  #[test]
  fn test_take_signed_bits() {
    let inputs      = [ (&[0b00100000][..], 2)
                      , (&[0b00011111][..], 2)
                      , (&[0b00001000, 0b00000000][..], 4)
                      , (&[0b00000111, 0b11111111][..], 4)
                      , (&[0b10000000, 0b00000000, 0b00000000][..], 0)
                      , (&[0b01111111, 0b11111111, 0b11111111][..], 0)
                      ];
    let results_i8  = [ IResult::Done((&[][..], 0), -32)
                      , IResult::Done((&[][..], 0), 31)
                      ];
    let results_i16 = [ IResult::Done((&[][..], 0), -2048)
                      , IResult::Done((&[][..], 0), 2047)
                      ];
    let results_i32 = [ IResult::Done((&[][..], 0), -8388608)
                      , IResult::Done((&[][..], 0), 8388607)
                      ];

    assert_eq!(take_signed_bits!(inputs[0], i8, 6), results_i8[0]);
    assert_eq!(take_signed_bits!(inputs[1], i8, 6), results_i8[1]);
    assert_eq!(take_signed_bits!(inputs[2], i16, 12), results_i16[0]);
    assert_eq!(take_signed_bits!(inputs[3], i16, 12), results_i16[1]);
    assert_eq!(take_signed_bits!(inputs[4], i32, 24), results_i32[0]);
    assert_eq!(take_signed_bits!(inputs[5], i32, 24), results_i32[1]);
  }
}
<|endoftext|>


<commit_before>use elements::{Module, ResizableLimits, MemoryType, TableType};

pub struct Error(pub String);

pub fn validate_module(module: &Module) -> Result<(), Error> {
	if let Some(mem_section) = module.memory_section() {
		mem_section
			.entries()
			.iter()
			.map(MemoryType::validate)
			.collect::<Result<_, _>>()?
	}

	if let Some(table_section) = module.table_section() {
		table_section
			.entries()
			.iter()
			.map(TableType::validate)
			.collect::<Result<_, _>>()?
	}

	Ok(())
}

impl ResizableLimits {
	fn validate(&self) -> Result<(), Error> {
		if let Some(maximum) = self.maximum() {
			if self.initial() > maximum {
				return Err(Error(format!(
					"maximum limit {} is lesser than minimum {}",
					maximum,
					self.initial()
				)));
			}
		}
		Ok(())
	}
}

impl MemoryType {
	fn validate(&self) -> Result<(), Error> {
		self.limits().validate()
	}
}

impl TableType {
	fn validate(&self) -> Result<(), Error> {
		self.limits().validate()
	}
}

#[cfg(test)]
mod tests {
	use super::validate_module;
	use builder::module;
	use elements::{BlockType, ExportEntry, External, FunctionType, GlobalEntry, GlobalType,
	               ImportEntry, InitExpr, Internal, MemoryType, Opcode, Opcodes, TableType,
	               ValueType};

	#[test]
	fn empty_is_valid() {
		let module = module().build();
		assert!(validate_module(&module).is_ok());
	}

	#[test]
	fn mem_limits() {
		// min > max
		let m = module()
			.memory()
				.with_min(10)
				.with_max(Some(9))
				.build()
			.build();
		assert!(validate_module(&m).is_err());

		// min = max
		let m = module()
			.memory()
				.with_min(10)
				.with_max(Some(10))
				.build()
			.build();
		assert!(validate_module(&m).is_ok());

		// mem is always valid without max.
		let m = module()
			.memory()
				.with_min(10)
				.build()
			.build();
		assert!(validate_module(&m).is_ok());
	}

	#[test]
	fn table_limits() {
		// min > max
		let m = module()
			.table()
				.with_min(10)
				.with_max(Some(9))
				.build()
			.build();
		assert!(validate_module(&m).is_err());

		// min = max
		let m = module()
			.table()
				.with_min(10)
				.with_max(Some(10))
				.build()
			.build();
		assert!(validate_module(&m).is_ok());

		// table is always valid without max.
		let m = module()
			.table()
				.with_min(10)
				.build()
			.build();
		assert!(validate_module(&m).is_ok());
	}
}
<commit_msg>Reorganize<commit_after>#![allow(unused, missing_docs)]

use elements::{Module, ResizableLimits, MemoryType, TableType};

pub struct Error(pub String);

pub fn validate_module(module: &Module) -> Result<(), Error> {
	// TODO: Functions

	if let Some(table_section) = module.table_section() {
		table_section
			.entries()
			.iter()
			.map(TableType::validate)
			.collect::<Result<_, _>>()?
	}

	if let Some(mem_section) = module.memory_section() {
		mem_section
			.entries()
			.iter()
			.map(MemoryType::validate)
			.collect::<Result<_, _>>()?
	}

	Ok(())
}

impl ResizableLimits {
	fn validate(&self) -> Result<(), Error> {
		if let Some(maximum) = self.maximum() {
			if self.initial() > maximum {
				return Err(Error(format!(
					"maximum limit {} is lesser than minimum {}",
					maximum,
					self.initial()
				)));
			}
		}
		Ok(())
	}
}

impl MemoryType {
	fn validate(&self) -> Result<(), Error> {
		self.limits().validate()
	}
}

impl TableType {
	fn validate(&self) -> Result<(), Error> {
		self.limits().validate()
	}
}

#[cfg(test)]
mod tests {
	use super::validate_module;
	use builder::module;
	use elements::{BlockType, ExportEntry, External, FunctionType, GlobalEntry, GlobalType,
	               ImportEntry, InitExpr, Internal, MemoryType, Opcode, Opcodes, TableType,
	               ValueType};

	#[test]
	fn empty_is_valid() {
		let module = module().build();
		assert!(validate_module(&module).is_ok());
	}

	#[test]
	fn mem_limits() {
		// min > max
		let m = module()
			.memory()
				.with_min(10)
				.with_max(Some(9))
				.build()
			.build();
		assert!(validate_module(&m).is_err());

		// min = max
		let m = module()
			.memory()
				.with_min(10)
				.with_max(Some(10))
				.build()
			.build();
		assert!(validate_module(&m).is_ok());

		// mem is always valid without max.
		let m = module()
			.memory()
				.with_min(10)
				.build()
			.build();
		assert!(validate_module(&m).is_ok());
	}

	#[test]
	fn table_limits() {
		// min > max
		let m = module()
			.table()
				.with_min(10)
				.with_max(Some(9))
				.build()
			.build();
		assert!(validate_module(&m).is_err());

		// min = max
		let m = module()
			.table()
				.with_min(10)
				.with_max(Some(10))
				.build()
			.build();
		assert!(validate_module(&m).is_ok());

		// table is always valid without max.
		let m = module()
			.table()
				.with_min(10)
				.build()
			.build();
		assert!(validate_module(&m).is_ok());
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Amos Onn.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
//
use std::collections::HashMap;
use std::sync::RwLock;

/// Table for storing objects for handlers, and issuing handlers for new objects, all available via
/// inner mutability.
pub struct HandlerTable<T> {
    inner: RwLock<(u64, HashMap<u64, T>)>,
}

impl HandlerTable<T> {
    /// Create a new, empty HandlerTable.
    pub fn new() -> HandlerTable<T> {
        HandlerTable{ inner: RwLock::new((0, HashMap::new())) }
    }

    /// Get the object associated with a file handler, if it exists.
    pub fn get(&self, fh: u64) -> Option<T> {
        self.inner.read().unwrap().1.get(fh)
    }

    /// Insert a new object, returning the file handler generated for it.
    pub fn insert(&self, obj: T) -> u64 {
        let (fh, map) = self.inner.write().unwrap();
        assert!(map.insert(fh, obj).is_none());
        fh += 1;
        fh - 1
    }

    /// Remove an object associated with a file handler, if it exists.
    pub fn remove(&self, fh: u64) -> Option<T> {
        self.inner.write().unwrap().1.remove(fh)
    }
}
<commit_msg>Syntax.<commit_after>// Copyright 2017 Amos Onn.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
//
use std::collections::HashMap;
use std::sync::RwLock;

/// Table for storing objects for handlers, and issuing handlers for new objects, all available via
/// inner mutability.
pub struct HandlerTable<T> {
    inner: RwLock<(u64, HashMap<u64, T>)>,
}

impl<T> HandlerTable<T> {
    /// Create a new, empty HandlerTable.
    pub fn new() -> HandlerTable<T> {
        HandlerTable{ inner: RwLock::new((0, HashMap::new())) }
    }

    /// Get the object associated with a file handler, if it exists.
    pub fn get(&self, fh: u64) -> Option<T> {
        self.inner.read().unwrap().1.get(fh)
    }

    /// Insert a new object, returning the file handler generated for it.
    pub fn insert(&self, obj: T) -> u64 {
        let (fh, map) = self.inner.write().unwrap();
        assert!(map.insert(fh, obj).is_none());
        fh += 1;
        fh - 1
    }

    /// Remove an object associated with a file handler, if it exists.
    pub fn remove(&self, fh: u64) -> Option<T> {
        self.inner.write().unwrap().1.remove(fh)
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Ben Ashford
 *
 * 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.
 */

//! Specific options for the Function option of various queries

use std::collections::HashMap;

use serde::{Serialize, Serializer};

use ::json::ShouldSkip;

use ::units::{Distance, Duration, JsonVal, Location};

/// Function
#[derive(Debug, Serialize)]
pub enum Function {
    #[serde(rename="script_score")]
    ScriptScore(ScriptScore),
    #[serde(rename="weight")]
    Weight(Weight),
    #[serde(rename="random_score")]
    RandomScore(RandomScore),
    #[serde(rename="field_value_factor")]
    FieldValueFactor(FieldValueFactor),
    #[serde(rename="linear")]
    Linear(Decay),
    #[serde(rename="exp")]
    Exp(Decay),
    #[serde(rename="gauss")]
    Gauss(Decay)
}

/// ScriptScore function
#[derive(Debug, Default, Serialize)]
pub struct ScriptScore {
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    lang: Option<String>,
    params: HashMap<String, JsonVal>,
    inline: String
}

impl Function {
    pub fn build_script_score<A>(script: A) -> ScriptScore
        where A: Into<String> {

        ScriptScore {
            inline: script.into(),
            ..Default::default()
        }
    }
}

impl ScriptScore {
    add_field!(with_lang, lang, String);

    pub fn with_params<A>(mut self, params: A) -> Self
        where A: IntoIterator<Item=(String, JsonVal)> {

        self.params.extend(params);
        self
    }

    pub fn add_param<A, B>(mut self, key: A, value: B) -> Self
        where A: Into<String>,
              B: Into<JsonVal> {
        self.params.insert(key.into(), value.into());
        self
    }

    pub fn build(self) -> Function {
        Function::ScriptScore(self)
    }
}

/// Weight function
#[derive(Debug, Default, Serialize)]
pub struct Weight(f64);

impl Function {
    pub fn build_weight<A>(weight: A) -> Weight
        where A: Into<f64> {

        Weight(weight.into())
    }
}

impl Weight {
    pub fn build(self) -> Function {
        Function::Weight(self)
    }
}

/// Random score function
#[derive(Debug, Default, Serialize)]
pub struct RandomScore(i64);

impl Function {
    pub fn build_random_score<A>(seed: A) -> RandomScore
        where A: Into<i64> {

        RandomScore(seed.into())
    }
}

impl RandomScore {
    pub fn build(self) -> Function {
        Function::RandomScore(self)
    }
}

/// Field value factor function
#[derive(Debug, Default, Serialize)]
pub struct FieldValueFactor {
    field: String,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    factor: Option<f64>,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    modifier: Option<Modifier>,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    missing: Option<JsonVal>
}

impl Function {
    pub fn build_field_value_factor<A>(field: A) -> FieldValueFactor
        where A: Into<String> {

        FieldValueFactor {
            field: field.into(),
            ..Default::default()
        }
    }
}

impl FieldValueFactor {
    add_field!(with_factor, factor, f64);
    add_field!(with_modifier, modifier, Modifier);
    add_field!(with_missing, missing, JsonVal);

    pub fn build(self) -> Function {
        Function::FieldValueFactor(self)
    }
}

/// Modifier for the FieldValueFactor function
#[derive(Debug)]
pub enum Modifier {
    None,
    Log,
    Log1p,
    Log2p,
    Ln,
    Ln1p,
    Ln2p,
    Square,
    Sqrt,
    Reciprocal,
}

impl Serialize for Modifier {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        match self {
            &Modifier::None => "none".serialize(serializer),
            &Modifier::Log => "log".serialize(serializer),
            &Modifier::Log1p => "log1p".serialize(serializer),
            &Modifier::Log2p => "log2p".serialize(serializer),
            &Modifier::Ln => "ln".serialize(serializer),
            &Modifier::Ln1p => "ln1p".serialize(serializer),
            &Modifier::Ln2p => "ln2p".serialize(serializer),
            &Modifier::Square => "square".serialize(serializer),
            &Modifier::Sqrt => "sqrt".serialize(serializer),
            &Modifier::Reciprocal => "reciprocal".serialize(serializer),
        }
    }
}

/// Decay functions
#[derive(Debug, Default, Serialize)]
pub struct Decay {
    field: String,
    origin: Origin,
    scale: Scale,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    offset: Option<Scale>,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    decay: Option<f64>,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    multi_value_mode: Option<MultiValueMode>
}

macro_rules! build_decay_fn {
    ($fn_name:ident, $dec_fn:expr) => (
        pub fn $fn_name<A, B, C>(field: A, origin: B, scale: C) -> Decay
            where A: Into<String>,
                  B: Into<Origin>,
                  C: Into<Scale> {
            Decay {
                decay_function: $dec_fn,
                field: field.into(),
                origin: origin.into(),
                scale: scale.into(),
                ..Default::default()
            }
        }
    )
}

impl Function {
    pub fn build_decay<A, B, C>(field: A, origin: B, scale: C) -> Decay
        where A: Into<String>,
              B: Into<Origin>,
              C: Into<Scale> {
        Decay {
            field: field.into(),
            origin: origin.into(),
            scale: scale.into(),
            ..Default::default()
        }
    }
}

impl Decay {
    add_field!(with_offset, offset, Scale);
    add_field!(with_decay, decay, f64);
    add_field!(with_multi_value_mode, multi_value_mode, MultiValueMode);

    pub fn build_linear(self) -> Function {
        Function::Linear(self)
    }

    pub fn build_exp(self) -> Function {
        Function::Exp(self)
    }

    pub fn build_gauss(self) -> Function {
        Function::Gauss(self)
    }
}

// options used by decay functions

/// Origin for decay function
#[derive(Debug)]
pub enum Origin {
    I64(i64),
    U64(u64),
    F64(f64),
    Location(Location),
    Date(String)
}

impl Default for Origin {
    fn default() -> Origin {
        Origin::I64(0)
    }
}

from!(i64, Origin, I64);
from!(u64, Origin, U64);
from!(f64, Origin, F64);
from!(Location, Origin, Location);
from!(String, Origin, Date);

impl Serialize for Origin {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {

        match self {
            &Origin::I64(orig)          => orig.serialize(serializer),
            &Origin::U64(orig)          => orig.serialize(serializer),
            &Origin::F64(orig)          => orig.serialize(serializer),
            &Origin::Location(ref orig) => orig.serialize(serializer),
            &Origin::Date(ref orig)     => orig.serialize(serializer)
        }
    }
}

/// Scale used by decay function
#[derive(Debug)]
pub enum Scale {
    I64(i64),
    U64(u64),
    F64(f64),
    Distance(Distance),
    Duration(Duration)
}

impl Default for Scale {
    fn default() -> Self {
        Scale::I64(0)
    }
}

from!(i64, Scale, I64);
from!(u64, Scale, U64);
from!(f64, Scale, F64);
from!(Distance, Scale, Distance);
from!(Duration, Scale, Duration);

impl Serialize for Scale {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {

        match self {
            &Scale::I64(s) => s.serialize(serializer),
            &Scale::U64(s) => s.serialize(serializer),
            &Scale::F64(s) => s.serialize(serializer),
            &Scale::Distance(ref s) => s.serialize(serializer),
            &Scale::Duration(ref s) => s.serialize(serializer)
        }
    }
}

/// Values for multi_value_mode
#[derive(Debug)]
pub enum MultiValueMode {
    Min,
    Max,
    Avg,
    Sum
}

impl Serialize for MultiValueMode {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        use self::MultiValueMode::*;
        match self {
            &Min => "min",
            &Max => "max",
            &Avg => "avg",
            &Sum => "sum"
        }.serialize(serializer)
    }
}
<commit_msg>fix decay function<commit_after>/*
 * Copyright 2016 Ben Ashford
 *
 * 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.
 */

//! Specific options for the Function option of various queries

use std::collections::HashMap;

use serde::{Serialize, Serializer};

use ::json::{ShouldSkip, FieldBased, NoOuter};

use ::units::{Distance, Duration, JsonVal, Location};

/// Function
#[derive(Debug, Serialize)]
pub enum Function {
    #[serde(rename="script_score")]
    ScriptScore(ScriptScore),
    #[serde(rename="weight")]
    Weight(Weight),
    #[serde(rename="random_score")]
    RandomScore(RandomScore),
    #[serde(rename="field_value_factor")]
    FieldValueFactor(FieldValueFactor),
    #[serde(rename="linear")]
    Linear(Decay),
    #[serde(rename="exp")]
    Exp(Decay),
    #[serde(rename="gauss")]
    Gauss(Decay)
}

/// ScriptScore function
#[derive(Debug, Default, Serialize)]
pub struct ScriptScore {
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    lang: Option<String>,
    params: HashMap<String, JsonVal>,
    inline: String
}

impl Function {
    pub fn build_script_score<A>(script: A) -> ScriptScore
        where A: Into<String> {

        ScriptScore {
            inline: script.into(),
            ..Default::default()
        }
    }
}

impl ScriptScore {
    add_field!(with_lang, lang, String);

    pub fn with_params<A>(mut self, params: A) -> Self
        where A: IntoIterator<Item=(String, JsonVal)> {

        self.params.extend(params);
        self
    }

    pub fn add_param<A, B>(mut self, key: A, value: B) -> Self
        where A: Into<String>,
              B: Into<JsonVal> {
        self.params.insert(key.into(), value.into());
        self
    }

    pub fn build(self) -> Function {
        Function::ScriptScore(self)
    }
}

/// Weight function
#[derive(Debug, Default, Serialize)]
pub struct Weight(f64);

impl Function {
    pub fn build_weight<A>(weight: A) -> Weight
        where A: Into<f64> {

        Weight(weight.into())
    }
}

impl Weight {
    pub fn build(self) -> Function {
        Function::Weight(self)
    }
}

/// Random score function
#[derive(Debug, Default, Serialize)]
pub struct RandomScore(i64);

impl Function {
    pub fn build_random_score<A>(seed: A) -> RandomScore
        where A: Into<i64> {

        RandomScore(seed.into())
    }
}

impl RandomScore {
    pub fn build(self) -> Function {
        Function::RandomScore(self)
    }
}

/// Field value factor function
#[derive(Debug, Default, Serialize)]
pub struct FieldValueFactor {
    field: String,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    factor: Option<f64>,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    modifier: Option<Modifier>,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    missing: Option<JsonVal>
}

impl Function {
    pub fn build_field_value_factor<A>(field: A) -> FieldValueFactor
        where A: Into<String> {

        FieldValueFactor {
            field: field.into(),
            ..Default::default()
        }
    }
}

impl FieldValueFactor {
    add_field!(with_factor, factor, f64);
    add_field!(with_modifier, modifier, Modifier);
    add_field!(with_missing, missing, JsonVal);

    pub fn build(self) -> Function {
        Function::FieldValueFactor(self)
    }
}

/// Modifier for the FieldValueFactor function
#[derive(Debug)]
pub enum Modifier {
    None,
    Log,
    Log1p,
    Log2p,
    Ln,
    Ln1p,
    Ln2p,
    Square,
    Sqrt,
    Reciprocal,
}

impl Serialize for Modifier {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        match self {
            &Modifier::None => "none".serialize(serializer),
            &Modifier::Log => "log".serialize(serializer),
            &Modifier::Log1p => "log1p".serialize(serializer),
            &Modifier::Log2p => "log2p".serialize(serializer),
            &Modifier::Ln => "ln".serialize(serializer),
            &Modifier::Ln1p => "ln1p".serialize(serializer),
            &Modifier::Ln2p => "ln2p".serialize(serializer),
            &Modifier::Square => "square".serialize(serializer),
            &Modifier::Sqrt => "sqrt".serialize(serializer),
            &Modifier::Reciprocal => "reciprocal".serialize(serializer),
        }
    }
}

#[derive(Debug, Default, Serialize)]
pub struct DecayOptions {
    origin: Origin,
    scale: Scale,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    offset: Option<Scale>,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    decay: Option<f64>,
    #[serde(skip_serializing_if="ShouldSkip::should_skip")]
    multi_value_mode: Option<MultiValueMode>
}

impl DecayOptions {
    add_field!(with_offset, offset, Scale);
    add_field!(with_decay, decay, f64);
    add_field!(with_multi_value_mode, multi_value_mode, MultiValueMode);
}

/// Decay functions
#[derive(Debug, Serialize)]
pub struct Decay(FieldBased<String, DecayOptions, NoOuter>);

impl Function {
    pub fn build_decay<A, B, C>(field: A, origin: B, scale: C) -> Decay
        where A: Into<String>,
              B: Into<Origin>,
              C: Into<Scale> {
      Decay(FieldBased::new(field.into(),
                            DecayOptions {
                                origin: origin.into(),
                                scale: scale.into(),
                                ..Default::default()
                            },
                            NoOuter))
    }
}

impl Decay {
    pub fn build_linear(self) -> Function {
        Function::Linear(self)
    }

    pub fn build_exp(self) -> Function {
        Function::Exp(self)
    }

    pub fn build_gauss(self) -> Function {
        Function::Gauss(self)
    }
}

// options used by decay functions

/// Origin for decay function
#[derive(Debug)]
pub enum Origin {
    I64(i64),
    U64(u64),
    F64(f64),
    Location(Location),
    Date(String)
}

impl Default for Origin {
    fn default() -> Origin {
        Origin::I64(0)
    }
}

from!(i64, Origin, I64);
from!(u64, Origin, U64);
from!(f64, Origin, F64);
from!(Location, Origin, Location);
from!(String, Origin, Date);

impl Serialize for Origin {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {

        match self {
            &Origin::I64(orig)          => orig.serialize(serializer),
            &Origin::U64(orig)          => orig.serialize(serializer),
            &Origin::F64(orig)          => orig.serialize(serializer),
            &Origin::Location(ref orig) => orig.serialize(serializer),
            &Origin::Date(ref orig)     => orig.serialize(serializer)
        }
    }
}

/// Scale used by decay function
#[derive(Debug)]
pub enum Scale {
    I64(i64),
    U64(u64),
    F64(f64),
    Distance(Distance),
    Duration(Duration)
}

impl Default for Scale {
    fn default() -> Self {
        Scale::I64(0)
    }
}

from!(i64, Scale, I64);
from!(u64, Scale, U64);
from!(f64, Scale, F64);
from!(Distance, Scale, Distance);
from!(Duration, Scale, Duration);

impl Serialize for Scale {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {

        match self {
            &Scale::I64(s) => s.serialize(serializer),
            &Scale::U64(s) => s.serialize(serializer),
            &Scale::F64(s) => s.serialize(serializer),
            &Scale::Distance(ref s) => s.serialize(serializer),
            &Scale::Duration(ref s) => s.serialize(serializer)
        }
    }
}

/// Values for multi_value_mode
#[derive(Debug)]
pub enum MultiValueMode {
    Min,
    Max,
    Avg,
    Sum
}

impl Serialize for MultiValueMode {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        use self::MultiValueMode::*;
        match self {
            &Min => "min",
            &Max => "max",
            &Avg => "avg",
            &Sum => "sum"
        }.serialize(serializer)
    }
}

#[cfg(test)]
pub mod tests {
    use serde_json;

    #[test]
    fn test_decay_query() {
        use ::units::*;
        let gauss_decay_query = super::Function::build_decay("my_field",
                                   Location::LatLon(42., 24.),
                                   Distance::new(3., DistanceUnit::Kilometer))
                           .build_gauss();

        assert_eq!(r#"{"gauss":{"my_field":{"origin":{"lat":42,"lon":24},"scale":"3km"}}}"#,
                   serde_json::to_string(&gauss_decay_query).unwrap());
    }
}
<|endoftext|>


<commit_before>#![feature(alloc_system)]
#![allow(bad_style, unused_imports)]

extern crate alloc_system;
extern crate libc;
extern crate libc_test;

use std::any::{Any, TypeId};
use std::mem;

use libc::*;

trait Pretty {
    fn pretty(&self) -> String;
}

impl<T> Pretty for *const T {
    fn pretty(&self) -> String { format!("{:?}", self) }
}
impl<T> Pretty for *mut T {
    fn pretty(&self) -> String { format!("{:?}", self) }
}
macro_rules! p {
    ($($i:ident)*) => ($(
        impl Pretty for $i {
            fn pretty(&self) -> String { format!("{} ({:#x})", self, self) }
        }
    )*)
}
p! { i8 i16 i32 i64 u8 u16 u32 u64 usize isize }

fn same<T: Eq + Pretty>(rust: T, c: T, attr: &str) {
    if rust != c {
        panic!("bad {}: rust: {} != c {}", attr, rust.pretty(), c.pretty());
    }
}

#[allow(deprecated)]
fn align<T: Any>() -> u64 {
    // TODO: apparently these three types have less alignment in Rust on x86
    //       than they do in C this difference should.. probably be reconciled.
    //
    //       Perhaps #27195?
    if cfg!(target_pointer_width = "32") {
        if TypeId::of::<T>() == TypeId::of::<f64>() ||
           TypeId::of::<T>() == TypeId::of::<i64>() ||
           TypeId::of::<T>() == TypeId::of::<u64>() {
            return 8
        }
    }
    mem::min_align_of::<T>() as u64
}

macro_rules! offset_of {
    ($ty:ident, $field:ident) => (
        (&((*(0 as *const $ty)).$field)) as *const _ as u64
    )
}

#[cfg(test)]
include!(concat!(env!("OUT_DIR"), "/all.rs"));
<commit_msg>Revert alloc_system change<commit_after>#![allow(bad_style, unused_imports)]

extern crate libc;
extern crate libc_test;

use std::any::{Any, TypeId};
use std::mem;

use libc::*;

trait Pretty {
    fn pretty(&self) -> String;
}

impl<T> Pretty for *const T {
    fn pretty(&self) -> String { format!("{:?}", self) }
}
impl<T> Pretty for *mut T {
    fn pretty(&self) -> String { format!("{:?}", self) }
}
macro_rules! p {
    ($($i:ident)*) => ($(
        impl Pretty for $i {
            fn pretty(&self) -> String { format!("{} ({:#x})", self, self) }
        }
    )*)
}
p! { i8 i16 i32 i64 u8 u16 u32 u64 usize isize }

fn same<T: Eq + Pretty>(rust: T, c: T, attr: &str) {
    if rust != c {
        panic!("bad {}: rust: {} != c {}", attr, rust.pretty(), c.pretty());
    }
}

#[allow(deprecated)]
fn align<T: Any>() -> u64 {
    // TODO: apparently these three types have less alignment in Rust on x86
    //       than they do in C this difference should.. probably be reconciled.
    //
    //       Perhaps #27195?
    if cfg!(target_pointer_width = "32") {
        if TypeId::of::<T>() == TypeId::of::<f64>() ||
           TypeId::of::<T>() == TypeId::of::<i64>() ||
           TypeId::of::<T>() == TypeId::of::<u64>() {
            return 8
        }
    }
    mem::min_align_of::<T>() as u64
}

macro_rules! offset_of {
    ($ty:ident, $field:ident) => (
        (&((*(0 as *const $ty)).$field)) as *const _ as u64
    )
}

#[cfg(test)]
include!(concat!(env!("OUT_DIR"), "/all.rs"));
<|endoftext|>


<commit_before>#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.

use crate::intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
/// further optimizations.
///
/// # Safety
///
/// Reaching this function is completely *undefined behavior* (UB). In
/// particular, the compiler assumes that all UB must never happen, and
/// therefore will eliminate all branches that reach to a call to
/// `unreachable_unchecked()`.
///
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
/// `unreachable_unchecked()` call is actually reachable among all possible
/// control flow, the compiler will apply the wrong optimization strategy, and
/// may sometimes even corrupt seemingly unrelated code, causing
/// difficult-to-debug problems.
///
/// Use this function only when you can prove that the code will never call it.
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
/// [`unreachable!`]: unreachable
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` is always positive (not zero),
///     // hence `checked_div` will never return `None`.
///     // Therefore, the else branch is unreachable.
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
pub const unsafe fn unreachable_unchecked() -> ! {
    // SAFETY: the safety contract for `intrinsics::unreachable` must
    // be upheld by the caller.
    unsafe { intrinsics::unreachable() }
}

/// Emits a machine instruction hinting to the processor that it is running in busy-wait
/// spin-loop ("spin lock").
///
/// For a discussion of different locking strategies and their trade-offs, see
/// [`core::sync::atomic::spin_loop_hint`].
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
    {
        #[cfg(target_arch = "x86")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
            unsafe { crate::arch::x86::_mm_pause() };
        }

        #[cfg(target_arch = "x86_64")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
            unsafe { crate::arch::x86_64::_mm_pause() };
        }
    }

    #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
    {
        #[cfg(target_arch = "aarch64")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
            unsafe { crate::arch::aarch64::__yield() };
        }
        #[cfg(target_arch = "arm")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
            // with support for the v6 feature.
            unsafe { crate::arch::arm::__yield() };
        }
    }
}

/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
/// `black_box` could do.
///
/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
///
/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
/// use `x` in any possible valid way that Rust code is allowed to without introducing undefined
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
/// certain optimizations are not desired, such as benchmarks.
///
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
#[inline]
#[unstable(feature = "test", issue = "50297")]
#[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
pub fn black_box<T>(dummy: T) -> T {
    // We need to "use" the argument in some way LLVM can't introspect, and on
    // targets that support it we can typically leverage inline assembly to do
    // this. LLVM's interpretation of inline assembly is that it's, well, a black
    // box. This isn't the greatest implementation since it probably deoptimizes
    // more than we want, but it's so far good enough.

    #[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
    // SAFETY: the inline assembly is a no-op.
    unsafe {
        llvm_asm!("" : : "r"(&dummy));
    }

    dummy
}
<commit_msg>Remove intra-doc link as it resolves without reference link<commit_after>#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.

use crate::intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
/// further optimizations.
///
/// # Safety
///
/// Reaching this function is completely *undefined behavior* (UB). In
/// particular, the compiler assumes that all UB must never happen, and
/// therefore will eliminate all branches that reach to a call to
/// `unreachable_unchecked()`.
///
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
/// `unreachable_unchecked()` call is actually reachable among all possible
/// control flow, the compiler will apply the wrong optimization strategy, and
/// may sometimes even corrupt seemingly unrelated code, causing
/// difficult-to-debug problems.
///
/// Use this function only when you can prove that the code will never call it.
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` is always positive (not zero),
///     // hence `checked_div` will never return `None`.
///     // Therefore, the else branch is unreachable.
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
pub const unsafe fn unreachable_unchecked() -> ! {
    // SAFETY: the safety contract for `intrinsics::unreachable` must
    // be upheld by the caller.
    unsafe { intrinsics::unreachable() }
}

/// Emits a machine instruction hinting to the processor that it is running in busy-wait
/// spin-loop ("spin lock").
///
/// For a discussion of different locking strategies and their trade-offs, see
/// [`core::sync::atomic::spin_loop_hint`].
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
    {
        #[cfg(target_arch = "x86")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
            unsafe { crate::arch::x86::_mm_pause() };
        }

        #[cfg(target_arch = "x86_64")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
            unsafe { crate::arch::x86_64::_mm_pause() };
        }
    }

    #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
    {
        #[cfg(target_arch = "aarch64")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
            unsafe { crate::arch::aarch64::__yield() };
        }
        #[cfg(target_arch = "arm")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
            // with support for the v6 feature.
            unsafe { crate::arch::arm::__yield() };
        }
    }
}

/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
/// `black_box` could do.
///
/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
///
/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
/// use `x` in any possible valid way that Rust code is allowed to without introducing undefined
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
/// certain optimizations are not desired, such as benchmarks.
///
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
#[inline]
#[unstable(feature = "test", issue = "50297")]
#[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
pub fn black_box<T>(dummy: T) -> T {
    // We need to "use" the argument in some way LLVM can't introspect, and on
    // targets that support it we can typically leverage inline assembly to do
    // this. LLVM's interpretation of inline assembly is that it's, well, a black
    // box. This isn't the greatest implementation since it probably deoptimizes
    // more than we want, but it's so far good enough.

    #[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
    // SAFETY: the inline assembly is a no-op.
    unsafe {
        llvm_asm!("" : : "r"(&dummy));
    }

    dummy
}
<|endoftext|>


<commit_before>/// A wrapper for the output slice used when decompressing.
///
/// Using this rather than `Cursor` lets us implement the writing methods directly on
/// the buffer and lets us use a usize rather than u64 for the position which helps with
/// performance on 32-bit systems.
pub struct OutputBuffer<'a> {
    slice: &'a mut [u8],
    position: usize,
}

impl<'a> OutputBuffer<'a> {
    #[inline]
    pub fn from_slice_and_pos(slice: &'a mut [u8], position: usize) -> OutputBuffer<'a> {
        OutputBuffer { slice, position }
    }

    #[inline]
    pub const fn position(&self) -> usize {
        self.position
    }

    #[inline]
    pub fn set_position(&mut self, position: usize) {
        self.position = position;
    }

    /// Write a byte to the current position and increment
    ///
    /// Assumes that there is space.
    #[inline]
    pub fn write_byte(&mut self, byte: u8) {
        self.slice[self.position] = byte;
        self.position += 1;
    }

    /// Write a slice to the current position and increment
    ///
    /// Assumes that there is space.
    #[inline]
    pub fn write_slice(&mut self, data: &[u8]) {
        let len = data.len();
        self.slice[self.position..self.position + len].copy_from_slice(data);
        self.position += data.len();
    }

    #[inline]
    pub const fn bytes_left(&self) -> usize {
        self.slice.len() - self.position
    }

    #[inline]
    pub const fn get_ref(&self) -> &[u8] {
        self.slice
    }

    #[inline]
    pub fn get_mut(&mut self) -> &mut [u8] {
        self.slice
    }
}
<commit_msg>remove const that's not supported in 1.34<commit_after>/// A wrapper for the output slice used when decompressing.
///
/// Using this rather than `Cursor` lets us implement the writing methods directly on
/// the buffer and lets us use a usize rather than u64 for the position which helps with
/// performance on 32-bit systems.
pub struct OutputBuffer<'a> {
    slice: &'a mut [u8],
    position: usize,
}

impl<'a> OutputBuffer<'a> {
    #[inline]
    pub fn from_slice_and_pos(slice: &'a mut [u8], position: usize) -> OutputBuffer<'a> {
        OutputBuffer { slice, position }
    }

    #[inline]
    pub const fn position(&self) -> usize {
        self.position
    }

    #[inline]
    pub fn set_position(&mut self, position: usize) {
        self.position = position;
    }

    /// Write a byte to the current position and increment
    ///
    /// Assumes that there is space.
    #[inline]
    pub fn write_byte(&mut self, byte: u8) {
        self.slice[self.position] = byte;
        self.position += 1;
    }

    /// Write a slice to the current position and increment
    ///
    /// Assumes that there is space.
    #[inline]
    pub fn write_slice(&mut self, data: &[u8]) {
        let len = data.len();
        self.slice[self.position..self.position + len].copy_from_slice(data);
        self.position += data.len();
    }

    #[inline]
    pub fn bytes_left(&self) -> usize {
        self.slice.len() - self.position
    }

    #[inline]
    pub const fn get_ref(&self) -> &[u8] {
        self.slice
    }

    #[inline]
    pub fn get_mut(&mut self) -> &mut [u8] {
        self.slice
    }
}
<|endoftext|>


<commit_before>use io::regs;

use std::fmt;
use std::mem;

use openssl::hash::{Hasher, MessageDigest};

bfdesc!(RegCnt: u32, {
    busy: 0 => 0,
    final_round: 1 => 1,
    enable_irq0: 2 => 2,
    big_endian: 3 => 3,
    hash_mode: 4 => 5,
    clear_fifo: 8 => 8,
    enable_fifo: 9 => 9,
    enable_irq1: 10 => 10
});

#[derive(Default)]
pub struct ShaDeviceState {
    hasher: Option<Hasher>,
    hash: Vec<u8>
}

impl fmt::Debug for ShaDeviceState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ShaDeviceState {{ }}")
    }
}
unsafe impl Send for ShaDeviceState {} // TODO: Not good!

// TODO: The following implementation does not yet completely work, and still needs
// more hardware testing to determine the source of errors.

fn reg_cnt_update(dev: &mut ShaDevice) {
    let mut cnt = dev.cnt.get();
    trace!("Wrote 0x{:08X} to SHA CNT register!", cnt);

    if bf!(cnt @ RegCnt::final_round) == 1 && bf!(cnt @ RegCnt::busy) == 0 {
        info!("Reached end of final round!");
        if let Some(ref mut h) = dev._internal_state.hasher {
            dev._internal_state.hash = h.finish().unwrap();
        }
        bf!(cnt @ RegCnt::final_round = 0);
    }

    else if bf!(cnt @ RegCnt::clear_fifo) == 1 {
        dev._internal_state.hasher = None;
    }

    else if bf!(cnt @ RegCnt::busy) == 0 {
    }

    else if dev._internal_state.hasher.is_none() {
        // Create new hasher
        assert_eq!(bf!(cnt @ RegCnt::big_endian), 1);

        let mode = match bf!(cnt @ RegCnt::hash_mode) {
            0b00 => MessageDigest::sha256(),
            0b01 => MessageDigest::sha224(),
            _ => MessageDigest::sha1()
        };

        dev._internal_state.hasher = Some(Hasher::new(mode).unwrap());
    }

    bf!(cnt @ RegCnt::busy = 0);
    dev.cnt.set_unchecked(cnt);
}

fn reg_hash_read(dev: &mut ShaDevice, buf_pos: usize, dest: &mut [u8]) {
    println!("Reading {} bytes from SHA HASH at +0x{:X}", dest.len(), buf_pos);
    let src_slice = &dev._internal_state.hash[buf_pos .. buf_pos + dest.len()];
    dest.clone_from_slice(src_slice);
}

// TODO: Does a word written to any part of the hash just add on? What about
// writing to the fifo in reverse? How does this work?
fn reg_fifo_write(dev: &mut ShaDevice, buf_pos: usize, source: &[u8]) {
    println!("Writing {} bytes to SHA FIFO at +0x{:X}", source.len(), buf_pos);

    let cnt = dev.cnt.get();
    let hasher = match dev._internal_state.hasher {
        Some(ref mut h) => h,
        None => return
    };

    hasher.update(source).unwrap();
}

iodevice!(ShaDevice, {
    internal_state: ShaDeviceState;
    regs: {
        0x000 => cnt: u32 { write_effect = reg_cnt_update; }
        0x004 => blk_cnt: u32 { }
    }
    ranges: {
        0x040;0x20 => {
            read_effect = reg_hash_read;
            write_effect = |_, _, _| unimplemented!();
        }
        0x080;0x40 => {
            read_effect = |_, _, _| unimplemented!();
            write_effect = reg_fifo_write;
        }
    }
});<commit_msg>io/sha: Update from deprecated openssl hashing system<commit_after>use io::regs;

use std::fmt;
use std::mem;

use openssl::hash::{Hasher, MessageDigest, DigestBytes};

bfdesc!(RegCnt: u32, {
    busy: 0 => 0,
    final_round: 1 => 1,
    enable_irq0: 2 => 2,
    big_endian: 3 => 3,
    hash_mode: 4 => 5,
    clear_fifo: 8 => 8,
    enable_fifo: 9 => 9,
    enable_irq1: 10 => 10
});

#[derive(Default)]
pub struct ShaDeviceState {
    hasher: Option<Hasher>,
    hash: [u8; 32]
}

impl fmt::Debug for ShaDeviceState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ShaDeviceState {{ }}")
    }
}
unsafe impl Send for ShaDeviceState {} // TODO: Not good!

// TODO: The following implementation does not yet completely work, and still needs
// more hardware testing to determine the source of errors.

fn reg_cnt_update(dev: &mut ShaDevice) {
    let mut cnt = dev.cnt.get();
    trace!("Wrote 0x{:08X} to SHA CNT register!", cnt);

    if bf!(cnt @ RegCnt::final_round) == 1 && bf!(cnt @ RegCnt::busy) == 0 {
        info!("Reached end of final round!");
        if let Some(ref mut h) = dev._internal_state.hasher {
            let hash_slice = &*h.finish2().unwrap();
            dev._internal_state.hash = [0u8; 32];
            dev._internal_state.hash[0..hash_slice.len()].copy_from_slice(hash_slice);
        }
        bf!(cnt @ RegCnt::final_round = 0);
    }

    else if bf!(cnt @ RegCnt::clear_fifo) == 1 {
        dev._internal_state.hasher = None;
    }

    else if bf!(cnt @ RegCnt::busy) == 0 {
    }

    else if dev._internal_state.hasher.is_none() {
        // Create new hasher
        assert_eq!(bf!(cnt @ RegCnt::big_endian), 1);

        let mode = match bf!(cnt @ RegCnt::hash_mode) {
            0b00 => MessageDigest::sha256(),
            0b01 => MessageDigest::sha224(),
            _ => MessageDigest::sha1()
        };

        dev._internal_state.hasher = Some(Hasher::new(mode).unwrap());
    }

    bf!(cnt @ RegCnt::busy = 0);
    dev.cnt.set_unchecked(cnt);
}

fn reg_hash_read(dev: &mut ShaDevice, buf_pos: usize, dest: &mut [u8]) {
    println!("Reading {} bytes from SHA HASH at +0x{:X}", dest.len(), buf_pos);
    let src_slice = &dev._internal_state.hash[buf_pos .. buf_pos + dest.len()];
    dest.clone_from_slice(src_slice);
}

// TODO: Does a word written to any part of the hash just add on? What about
// writing to the fifo in reverse? How does this work?
fn reg_fifo_write(dev: &mut ShaDevice, buf_pos: usize, source: &[u8]) {
    println!("Writing {} bytes to SHA FIFO at +0x{:X}", source.len(), buf_pos);

    let cnt = dev.cnt.get();
    let hasher = match dev._internal_state.hasher {
        Some(ref mut h) => h,
        None => return
    };

    hasher.update(source).unwrap();
}

iodevice!(ShaDevice, {
    internal_state: ShaDeviceState;
    regs: {
        0x000 => cnt: u32 { write_effect = reg_cnt_update; }
        0x004 => blk_cnt: u32 { }
    }
    ranges: {
        0x040;0x20 => {
            read_effect = reg_hash_read;
            write_effect = |_, _, _| unimplemented!();
        }
        0x080;0x40 => {
            read_effect = |_, _, _| unimplemented!();
            write_effect = reg_fifo_write;
        }
    }
});<|endoftext|>


<commit_before>use quickcheck;
use quickcheck::{Arbitrary, Gen, TestResult};
use field::Pos;
use hash_table::{HashType, HashData};

#[derive(Clone, Copy, PartialEq, Debug)]
struct HashTypeArbitrary {
  hash_type: HashType
}

impl Arbitrary for HashTypeArbitrary {
  fn arbitrary<G: Gen>(gen: &mut G) -> HashTypeArbitrary {
    HashTypeArbitrary {
      hash_type: HashType::from((gen.next_u32() % 4) as usize)
    }
  }
}

#[test]
fn hash_data_check() {
  #[cfg_attr(feature="clippy", allow(needless_pass_by_value))]
  fn prop(depth: u32, hash_type_arbitrary: HashTypeArbitrary, pos: Pos, estimation: i32) -> TestResult {
    let hash_data = HashData::new(depth, hash_type_arbitrary.hash_type, pos, estimation);
    if hash_data.depth() != depth ||
      hash_data.hash_type() != hash_type_arbitrary.hash_type ||
      hash_data.pos() != pos ||
      hash_data.estimation() != estimation {
      TestResult::failed()
    } else {
      TestResult::passed()
    }
  }
  quickcheck::quickcheck(prop as fn(u32, HashTypeArbitrary, Pos, i32) -> TestResult);
}
<commit_msg>Simplify test.<commit_after>use quickcheck;
use quickcheck::{Arbitrary, Gen};
use field::Pos;
use hash_table::{HashType, HashData};

#[derive(Clone, Copy, PartialEq, Debug)]
struct HashTypeArbitrary {
  hash_type: HashType
}

impl Arbitrary for HashTypeArbitrary {
  fn arbitrary<G: Gen>(gen: &mut G) -> HashTypeArbitrary {
    HashTypeArbitrary {
      hash_type: HashType::from((gen.next_u32() % 4) as usize)
    }
  }
}

#[test]
fn hash_data_check() {
  #[cfg_attr(feature="clippy", allow(needless_pass_by_value))]
  fn prop(depth: u32, hash_type_arbitrary: HashTypeArbitrary, pos: Pos, estimation: i32) -> bool {
    let hash_data = HashData::new(depth, hash_type_arbitrary.hash_type, pos, estimation);
    hash_data.depth() == depth &&
      hash_data.hash_type() == hash_type_arbitrary.hash_type &&
      hash_data.pos() == pos &&
      hash_data.estimation() == estimation
  }
  quickcheck::quickcheck(prop as fn(u32, HashTypeArbitrary, Pos, i32) -> bool);
}
<|endoftext|>


<commit_before>extern crate websocket;

use futures::future::Future;
use futures::stream::Stream;
use self::websocket::{WebSocketError};

use std::rc::Rc;
use std::cell::RefCell;

use self::websocket::server::upgrade::async::IntoWs;

use super::{Peer, io_other_error, BoxedNewPeerFuture, box_up_err};
use super::ws_peer::{WsReadWrapper, WsWriteWrapper, PeerForWs};

pub fn ws_upgrade_peer(inner_peer : Peer) -> BoxedNewPeerFuture {
    let step1 = PeerForWs(inner_peer);
    let step2 : Box<Future<Item=self::websocket::server::upgrade::async::Upgrade<_>,Error=_>> = step1.into_ws();
    let step3 = step2
        .map_err(|(_,_,_,e)| WebSocketError::IoError(io_other_error(e)) )
        .and_then(|x| {
            x.accept().map(|(y,_)| {
                info!("Incoming websocket connection");
                let (sink, stream) = y.split();
                let mpsink = Rc::new(RefCell::new(sink));

                let ws_str = WsReadWrapper {
                    s: stream,
                    pingreply: mpsink.clone(),
                    debt: None,
                };
                let ws_sin = WsWriteWrapper(mpsink);

                let ws = Peer::new(ws_str, ws_sin);
                ws
            })
        });
    let step4 = step3.map_err(box_up_err);
    Box::new(step4) as BoxedNewPeerFuture
}

<commit_msg>Improve logging for websocket server<commit_after>extern crate websocket;

use futures::future::Future;
use futures::stream::Stream;
use self::websocket::{WebSocketError};

use std::rc::Rc;
use std::cell::RefCell;

use self::websocket::server::upgrade::async::IntoWs;

use super::{Peer, io_other_error, BoxedNewPeerFuture, box_up_err};
use super::ws_peer::{WsReadWrapper, WsWriteWrapper, PeerForWs};

pub fn ws_upgrade_peer(inner_peer : Peer) -> BoxedNewPeerFuture {
    let step1 = PeerForWs(inner_peer);
    let step2 : Box<Future<Item=self::websocket::server::upgrade::async::Upgrade<_>,Error=_>> = step1.into_ws();
    let step3 = step2
        .map_err(|(_,_,_,e)| WebSocketError::IoError(io_other_error(e)) )
        .and_then(|x| {
            info!("Incoming connection to websocket: {}",x.request.subject.1);
            debug!("{:?}", x.request);
            debug!("{:?}", x.headers);
            x.accept().map(|(y,headers)| {
                debug!("{:?}", headers);
                info!("Upgraded");
                let (sink, stream) = y.split();
                let mpsink = Rc::new(RefCell::new(sink));

                let ws_str = WsReadWrapper {
                    s: stream,
                    pingreply: mpsink.clone(),
                    debt: None,
                };
                let ws_sin = WsWriteWrapper(mpsink);

                let ws = Peer::new(ws_str, ws_sin);
                ws
            })
        });
    let step4 = step3.map_err(box_up_err);
    Box::new(step4) as BoxedNewPeerFuture
}

<|endoftext|>


<commit_before>#![allow(unused)]

use interpreter::tokenizer::*;

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Node {
    Noop,
    Ident(Ident),
    Bool(bool),
    Int(i64),
    Float(f64),
    Str(String),
    Op(Box<Operator>),
    For(Box<For>),
    While(Box<While>),
    Function(Box<Function>),
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Operator {
    Call(Ident, Vec<Expr>),
    Assign(Ident, Expr),
    Add(Expr, Expr),
    Sub(Expr, Expr),
    Mul(Expr, Expr),
    Div(Expr, Expr),
    Negate(Expr),
    Not(Expr),
    And(Expr, Expr),
    Or(Expr, Expr),
    Equals(Expr, Expr),
    NotEquals(Expr, Expr),
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct Function {
    name: Ident,
    args: Vec<Ident>,
    body: Vec<Expr>,
}

impl Function {
    pub fn new(name: Ident, args: Vec<Ident>, body: Vec<Expr>) -> Function {
        Function { name, args, body }
    }
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct For {
    loopvar: Ident,
    iterator: Expr,
    body: Vec<Expr>,
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct While {
    condition: Expr,
    body: Vec<Expr>,
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct Expr {
    node: Node,
    debug: DebugInfo,
}

impl Expr {
    pub fn new(node: Node, debug: DebugInfo) -> Expr {
        Expr { node, debug }
    }

    pub fn parse(buffer: &str) -> Result<Expr, String> {
        let tokenizer = &mut RushTokenizer::new(buffer);
        let body = parse_exprs(tokenizer, true)?;
        Ok(Expr {
            node: Node::Function(Box::new(Function::new(
                Ident(String::from("<anonymous>")),
                Vec::new(),
                body,
            ))),
            debug: DebugInfo::new(buffer, 0),
        })
    }
}

fn parse_exprs(mut tokenizer: &mut RushTokenizer, outermost: bool) -> Result<Vec<Expr>, String> {
    if !outermost {
        tokenizer
            .next()
            .ok_or("Expected '{', reached end of input instead!")?
            .expect_operator_specific("{")?;
    }

    let mut exprs = Vec::new();

    while let Some(token) = tokenizer.next() {
        if !outermost {
            if token.expect_operator_specific("}").is_ok() {
                return Ok(exprs);
            }
        }
        exprs.push(parse_expr(token, tokenizer)?)
    }

    if outermost {
        Ok(exprs)
    } else {
        Err("Expected '}', reached end of input instead!")?
    }
}

fn parse_expr(first_token: Token, tokenizer: &mut RushTokenizer) -> Result<Expr, String> {

    let first_expr = match first_token {
        Token::Operator(op, debug) => {
            if op == ";" {
                return Ok(Expr::new(Node::Noop, debug));
            }

            let expr = parse_unary_operator(op, debug, tokenizer)?;
            check_for_semicolon(tokenizer)?;
            return Ok(expr);
        }
        Token::Ident(id, debug) => Expr::new(Node::Ident(id), debug),
        _ => unimplemented!(),
    };

    if let Some(second_token) = tokenizer.next() {
        match second_token {
            Token::Operator(op, debug) => {
                if op == ";" {
                    Ok(first_expr)
                } else {
                    let expr = parse_binary_operator(first_expr, op, debug, tokenizer)?;
                    check_for_semicolon(tokenizer)?;
                    Ok(expr)
                }
            }
            _ => unimplemented!(),
        }
    } else {
        Ok(first_expr)
    }
}

fn parse_unary_operator(
    op: String,
    debug: DebugInfo,
    tokenizer: &mut RushTokenizer,
) -> Result<Expr, String> {

    if !(op == "!" || op == "-") {
        return Err(
            debug.to_string() + ", but there is no expression preceding it and '" + &op +
                "' is not a unary operator!",
        )?;
    }

    let next = tokenizer.next().ok_or(
        debug.to_string() + ", then encountered end of input! '" + &op +
            "' must be followed by an expression.",
    )?;

    let next_expr = parse_expr(next, tokenizer)?;

    let operator = match op.as_ref() {
        "!" => Operator::Not(next_expr),
        "-" => Operator::Negate(next_expr),
        _ => {
            return Err(
                debug.to_string() +
                    ", which caused Rust to experience an internal error! Please report this!",
            )?
        }
    };

    let expr = Expr::new(Node::Op(Box::new(operator)), debug);

    Ok(expr)
}

fn parse_binary_operator(
    first_expr: Expr,
    op: String,
    debug: DebugInfo,
    tokenizer: &mut RushTokenizer,
) -> Result<Expr, String> {

    if op == "!" {
        return Err(
            debug.to_string() + ", but there is an expression preceding it and '" + &op +
                "' is not a binary operator!",
        )?;
    }

    let next = tokenizer.next().ok_or(
        debug.to_string() + ", then encountered end of input! '" + &op +
            "' must be followed by an expression.",
    )?;

    let next_expr = parse_expr(next, tokenizer)?;

    let operator = match op.as_ref() {
        "+" => Operator::Add(first_expr, next_expr),
        "-" => Operator::Sub(first_expr, next_expr),
        "*" => Operator::Mul(first_expr, next_expr),
        "/" => Operator::Div(first_expr, next_expr),
        "&&" => Operator::And(first_expr, next_expr),
        "||" => Operator::Or(first_expr, next_expr),
        "==" => Operator::Equals(first_expr, next_expr),
        "!=" => Operator::NotEquals(first_expr, next_expr),
        _ => {
            return Err(
                debug.to_string() +
                    ", which caused Rust to experience an internal error! Please report this!",
            )?
        }
    };

    let expr = Expr::new(Node::Op(Box::new(operator)), debug);

    Ok(expr)
}

fn check_for_semicolon(tokenizer: &mut RushTokenizer) -> Result<(), String> {
    // ensure that there is a semicolon at the end of this expression
    // or, ensure that this is the final expression,
    // by providing a fake semicolon if no token is returned at all
    tokenizer
        .next()
        .or(Some(Token::Operator(
            ";".to_string(),
            DebugInfo::new(";".to_string(), 0),
        )))
        .unwrap()
        .expect_operator_specific(";")
}

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

    #[test]
    fn parse_negate() {
        let expr = Expr::parse("!$someBool");
        assert_eq!(
            expr,
            Ok(Expr {
                node: Node::Function(Box::new(Function::new(
                    Ident(String::from("<anonymous>")),
                    Vec::new(),
                    vec![
                        Expr {
                            node: Node::Op(Box::new(Operator::Not(Expr {
                                node: Node::Ident(Ident("$someBool".to_string())),
                                debug: DebugInfo::new("$someBool", 1),
                            }))),
                            debug: DebugInfo::new("!", 0),
                        },
                    ],
                ))),
                debug: DebugInfo::new("!$someBool", 0),
            })
        );
    }

    #[test]
    fn parse_add() {
        let expr = Expr::parse("$someInt + $otherInt");
        assert_eq!(
            expr,
            Ok(Expr {
                node: Node::Function(Box::new(Function::new(
                    Ident(String::from("<anonymous>")),
                    Vec::new(),
                    vec![
                        Expr {
                            node: Node::Op(Box::new(Operator::Add(
                                Expr {
                                    node: Node::Ident(Ident("$someInt".to_string())),
                                    debug: DebugInfo::new("$someInt", 0),
                                },
                                Expr {
                                    node: Node::Ident(Ident("$otherInt".to_string())),
                                    debug: DebugInfo::new("$otherInt", 11),
                                },
                            ))),
                            debug: DebugInfo::new("+", 9),
                        },
                    ],
                ))),
                debug: DebugInfo::new("$someInt + $otherInt", 0),
            })
        );
    }
}
<commit_msg>Minor progress<commit_after>#![allow(unused)]

use interpreter::tokenizer::*;

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Node {
    Noop,
    Ident(Ident),
    Bool(bool),
    Int(i64),
    Float(f64),
    Str(String),
    Op(Box<Operator>),
    For(Box<For>),
    While(Box<While>),
    Function(Box<Function>),
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Operator {
    Call(Ident, Vec<Expr>),
    Assign(Ident, Expr),
    Add(Expr, Expr),
    Sub(Expr, Expr),
    Mul(Expr, Expr),
    Div(Expr, Expr),
    Negate(Expr),
    Not(Expr),
    And(Expr, Expr),
    Or(Expr, Expr),
    Equals(Expr, Expr),
    NotEquals(Expr, Expr),
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct Function {
    name: Ident,
    args: Vec<Ident>,
    body: Vec<Expr>,
}

impl Function {
    pub fn new(name: Ident, args: Vec<Ident>, body: Vec<Expr>) -> Function {
        Function { name, args, body }
    }
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct For {
    loopvar: Ident,
    iterator: Expr,
    body: Vec<Expr>,
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct While {
    condition: Expr,
    body: Vec<Expr>,
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct Expr {
    node: Node,
    debug: DebugInfo,
}

impl Expr {
    pub fn new(node: Node, debug: DebugInfo) -> Expr {
        Expr { node, debug }
    }

    pub fn parse(buffer: &str) -> Result<Expr, String> {
        let tokenizer = &mut RushTokenizer::new(buffer);
        let body = parse_exprs(tokenizer, true)?;
        Ok(Expr {
            node: Node::Function(Box::new(Function::new(
                Ident(String::from("<anonymous>")),
                Vec::new(),
                body,
            ))),
            debug: DebugInfo::new(buffer, 0),
        })
    }
}

fn parse_exprs(mut tokenizer: &mut RushTokenizer, outermost: bool) -> Result<Vec<Expr>, String> {
    if !outermost {
        tokenizer
            .next()
            .ok_or("Expected '{', reached end of input instead!")?
            .expect_operator_specific("{")?;
    }

    let mut exprs = Vec::new();

    while let Some(token) = tokenizer.next() {
        if !outermost {
            if token.expect_operator_specific("}").is_ok() {
                return Ok(exprs);
            }
        }
        exprs.push(parse_expr(token, tokenizer)?)
    }

    if outermost {
        Ok(exprs)
    } else {
        Err("Expected '}', reached end of input instead!")?
    }
}

fn parse_expr(first_token: Token, tokenizer: &mut RushTokenizer) -> Result<Expr, String> {

    let first_expr = match first_token {
        Token::Operator(op, debug) => {
            if op == ";" {
                return Ok(Expr::new(Node::Noop, debug));
            }

            let expr = parse_unary_operator(op, debug, tokenizer)?;
            check_for_semicolon(tokenizer)?;
            return Ok(expr);
        }
        Token::Ident(id, debug) => Expr::new(Node::Ident(id), debug),
        _ => unimplemented!(),
    };

    if let Some(second_token) = tokenizer.next() {
        match second_token {
            Token::Operator(op, debug) => {
                if op == ";" {
                    Ok(first_expr)
                } else {
                    let expr = parse_binary_operator(first_expr, op, debug, tokenizer)?;
                    check_for_semicolon(tokenizer)?;
                    Ok(expr)
                }
            }
            _ => unimplemented!(),
        }
    } else {
        Ok(first_expr)
    }
}

fn parse_unary_operator(
    op: String,
    debug: DebugInfo,
    tokenizer: &mut RushTokenizer,
) -> Result<Expr, String> {

    if !(op == "!" || op == "-") {
        return Err(
            debug.to_string() + ", but there is no expression preceding it and '" + &op +
                "' is not a unary operator!",
        )?;
    }

    let next = tokenizer.next().ok_or(
        debug.to_string() + ", then encountered end of input! '" + &op +
            "' must be followed by an expression.",
    )?;

    let next_expr = parse_expr(next, tokenizer)?;

    let operator = match op.as_ref() {
        "!" => Operator::Not(next_expr),
        "-" => Operator::Negate(next_expr),
        _ => {
            return Err(
                debug.to_string() +
                    ", which caused Rust to experience an internal error! Please report this!",
            )?
        }
    };

    let expr = Expr::new(Node::Op(Box::new(operator)), debug);

    Ok(expr)
}

fn parse_binary_operator(
    first_expr: Expr,
    op: String,
    debug: DebugInfo,
    tokenizer: &mut RushTokenizer,
) -> Result<Expr, String> {

    if op == "!" {
        return Err(
            debug.to_string() + ", but there is an expression preceding it and '" + &op +
                "' is not a binary operator!",
        )?;
    }

    let next = tokenizer.next().ok_or(
        debug.to_string() + ", then encountered end of input! '" + &op +
            "' must be followed by an expression.",
    )?;

    let next_expr = parse_expr(next, tokenizer)?;

    let operator = match op.as_ref() {
        "+" => Operator::Add(first_expr, next_expr),
        "-" => Operator::Sub(first_expr, next_expr),
        "*" => Operator::Mul(first_expr, next_expr),
        "/" => Operator::Div(first_expr, next_expr),
        "&&" => Operator::And(first_expr, next_expr),
        "||" => Operator::Or(first_expr, next_expr),
        "==" => Operator::Equals(first_expr, next_expr),
        "!=" => Operator::NotEquals(first_expr, next_expr),
        _ => {
            return Err(
                debug.to_string() +
                    ", which caused Rust to experience an internal error! Please report this!",
            )?
        }
    };

    let expr = Expr::new(Node::Op(Box::new(operator)), debug);

    Ok(expr)
}

fn parse_parenthetic_expr(
    first_token: Token,
    tokenizer: &mut RushTokenizer,
) -> Result<Expr, String> {

    first_token.expect_operator_specific("(").map_err(
        |mut err| {
            err.push_str(", which has caused an internal error! Please report this!");
            err
        },
    )?;

    unimplemented!();
}

fn check_for_semicolon(tokenizer: &mut RushTokenizer) -> Result<(), String> {
    // ensure that there is a semicolon at the end of this expression
    // or, ensure that this is the final expression,
    // by providing a fake semicolon if no token is returned at all
    tokenizer
        .next()
        .or(Some(Token::Operator(
            ";".to_string(),
            DebugInfo::new(";".to_string(), 0),
        )))
        .unwrap()
        .expect_operator_specific(";")
}

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

    #[test]
    fn parse_negate() {
        let expr = Expr::parse("!$someBool");
        assert_eq!(
            expr,
            Ok(Expr {
                node: Node::Function(Box::new(Function::new(
                    Ident(String::from("<anonymous>")),
                    Vec::new(),
                    vec![
                        Expr {
                            node: Node::Op(Box::new(Operator::Not(Expr {
                                node: Node::Ident(Ident("$someBool".to_string())),
                                debug: DebugInfo::new("$someBool", 1),
                            }))),
                            debug: DebugInfo::new("!", 0),
                        },
                    ],
                ))),
                debug: DebugInfo::new("!$someBool", 0),
            })
        );
    }

    #[test]
    fn parse_add() {
        let expr = Expr::parse("$someInt + $otherInt");
        assert_eq!(
            expr,
            Ok(Expr {
                node: Node::Function(Box::new(Function::new(
                    Ident(String::from("<anonymous>")),
                    Vec::new(),
                    vec![
                        Expr {
                            node: Node::Op(Box::new(Operator::Add(
                                Expr {
                                    node: Node::Ident(Ident("$someInt".to_string())),
                                    debug: DebugInfo::new("$someInt", 0),
                                },
                                Expr {
                                    node: Node::Ident(Ident("$otherInt".to_string())),
                                    debug: DebugInfo::new("$otherInt", 11),
                                },
                            ))),
                            debug: DebugInfo::new("+", 9),
                        },
                    ],
                ))),
                debug: DebugInfo::new("$someInt + $otherInt", 0),
            })
        );
    }
}
<|endoftext|>


<commit_before>//! Emulate LLVM intrinsics

use crate::intrinsics::*;
use crate::prelude::*;

use rustc_middle::ty::subst::SubstsRef;

pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    intrinsic: &str,
    substs: SubstsRef<'tcx>,
    args: &[mir::Operand<'tcx>],
    destination: Option<(CPlace<'tcx>, BasicBlock)>,
) {
    let ret = destination.unwrap().0;

    intrinsic_match! {
        fx, intrinsic, substs, args,
        _ => {
            fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
            crate::trap::trap_unimplemented(fx, intrinsic);
        };

        // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
        "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd", (c a) {
            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
            let lane_ty = fx.clif_type(lane_ty).unwrap();
            assert!(lane_count <= 32);

            let mut res = fx.bcx.ins().iconst(types::I32, 0);

            for lane in (0..lane_count).rev() {
                let a_lane = a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx);

                // cast float to int
                let a_lane = match lane_ty {
                    types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
                    types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
                    _ => a_lane,
                };

                // extract sign bit of an int
                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));

                // shift sign bit into result
                let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
                res = fx.bcx.ins().ishl_imm(res, 1);
                res = fx.bcx.ins().bor(res, a_lane_sign);
            }

            let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
            ret.write_cvalue(fx, res);
        };
        "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd", (c x, c y, o kind) {
            let kind_const = crate::constant::mir_operand_get_const_val(fx, kind).expect("llvm.x86.sse2.cmp.* kind not const");
            let flt_cc = match kind_const.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) {
                0 => FloatCC::Equal,
                1 => FloatCC::LessThan,
                2 => FloatCC::LessThanOrEqual,
                7 => {
                    unimplemented!("Compares corresponding elements in `a` and `b` to see if neither is `NaN`.");
                }
                3 => {
                    unimplemented!("Compares corresponding elements in `a` and `b` to see if either is `NaN`.");
                }
                4 => FloatCC::NotEqual,
                5 => {
                    unimplemented!("not less than");
                }
                6 => {
                    unimplemented!("not less than or equal");
                }
                kind => unreachable!("kind {:?}", kind),
            };

            simd_pair_for_each_lane(fx, x, y, ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
                let res_lane = match lane_layout.ty.kind() {
                    ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
                    _ => unreachable!("{:?}", lane_layout.ty),
                };
                bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
            });
        };
        "llvm.x86.sse2.psrli.d", (c a, o imm8) {
            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
            simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| {
                let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
                    imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
                    _ => fx.bcx.ins().iconst(types::I32, 0),
                };
                CValue::by_val(res_lane, res_lane_layout)
            });
        };
        "llvm.x86.sse2.pslli.d", (c a, o imm8) {
            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
            simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| {
                let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
                    imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
                    _ => fx.bcx.ins().iconst(types::I32, 0),
                };
                CValue::by_val(res_lane, res_lane_layout)
            });
        };
        "llvm.x86.sse2.storeu.dq", (v mem_addr, c a) {
            // FIXME correctly handle the unalignment
            let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
            dest.write_cvalue(fx, a);
        };
    }

    if let Some((_, dest)) = destination {
        let ret_block = fx.get_block(dest);
        fx.bcx.ins().jump(ret_block, &[]);
    } else {
        trap_unreachable(fx, "[corruption] Diverging intrinsic returned.");
    }
}

// llvm.x86.avx2.vperm2i128
// llvm.x86.ssse3.pshuf.b.128
// llvm.x86.avx2.pshuf.b
// llvm.x86.avx2.psrli.w
// llvm.x86.sse2.psrli.w
<commit_msg>Implement llvm.x86.addcarry.64 and llvm.x86.subborrow.64 (#1178)<commit_after>//! Emulate LLVM intrinsics

use crate::intrinsics::*;
use crate::prelude::*;

use rustc_middle::ty::subst::SubstsRef;

pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    intrinsic: &str,
    substs: SubstsRef<'tcx>,
    args: &[mir::Operand<'tcx>],
    destination: Option<(CPlace<'tcx>, BasicBlock)>,
) {
    let ret = destination.unwrap().0;

    intrinsic_match! {
        fx, intrinsic, substs, args,
        _ => {
            fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
            crate::trap::trap_unimplemented(fx, intrinsic);
        };

        // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
        "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd", (c a) {
            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
            let lane_ty = fx.clif_type(lane_ty).unwrap();
            assert!(lane_count <= 32);

            let mut res = fx.bcx.ins().iconst(types::I32, 0);

            for lane in (0..lane_count).rev() {
                let a_lane = a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx);

                // cast float to int
                let a_lane = match lane_ty {
                    types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
                    types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
                    _ => a_lane,
                };

                // extract sign bit of an int
                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));

                // shift sign bit into result
                let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
                res = fx.bcx.ins().ishl_imm(res, 1);
                res = fx.bcx.ins().bor(res, a_lane_sign);
            }

            let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
            ret.write_cvalue(fx, res);
        };
        "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd", (c x, c y, o kind) {
            let kind_const = crate::constant::mir_operand_get_const_val(fx, kind).expect("llvm.x86.sse2.cmp.* kind not const");
            let flt_cc = match kind_const.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) {
                0 => FloatCC::Equal,
                1 => FloatCC::LessThan,
                2 => FloatCC::LessThanOrEqual,
                7 => {
                    unimplemented!("Compares corresponding elements in `a` and `b` to see if neither is `NaN`.");
                }
                3 => {
                    unimplemented!("Compares corresponding elements in `a` and `b` to see if either is `NaN`.");
                }
                4 => FloatCC::NotEqual,
                5 => {
                    unimplemented!("not less than");
                }
                6 => {
                    unimplemented!("not less than or equal");
                }
                kind => unreachable!("kind {:?}", kind),
            };

            simd_pair_for_each_lane(fx, x, y, ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
                let res_lane = match lane_layout.ty.kind() {
                    ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
                    _ => unreachable!("{:?}", lane_layout.ty),
                };
                bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
            });
        };
        "llvm.x86.sse2.psrli.d", (c a, o imm8) {
            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
            simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| {
                let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
                    imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
                    _ => fx.bcx.ins().iconst(types::I32, 0),
                };
                CValue::by_val(res_lane, res_lane_layout)
            });
        };
        "llvm.x86.sse2.pslli.d", (c a, o imm8) {
            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
            simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| {
                let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
                    imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
                    _ => fx.bcx.ins().iconst(types::I32, 0),
                };
                CValue::by_val(res_lane, res_lane_layout)
            });
        };
        "llvm.x86.sse2.storeu.dq", (v mem_addr, c a) {
            // FIXME correctly handle the unalignment
            let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
            dest.write_cvalue(fx, a);
        };
        "llvm.x86.addcarry.64", (v c_in, c a, c b) {
            llvm_add_sub(
                fx,
                BinOp::Add,
                ret,
                c_in,
                a,
                b
            );
        };
        "llvm.x86.subborrow.64", (v b_in, c a, c b) {
            llvm_add_sub(
                fx,
                BinOp::Sub,
                ret,
                b_in,
                a,
                b
            );
        };
    }

    if let Some((_, dest)) = destination {
        let ret_block = fx.get_block(dest);
        fx.bcx.ins().jump(ret_block, &[]);
    } else {
        trap_unreachable(fx, "[corruption] Diverging intrinsic returned.");
    }
}

// llvm.x86.avx2.vperm2i128
// llvm.x86.ssse3.pshuf.b.128
// llvm.x86.avx2.pshuf.b
// llvm.x86.avx2.psrli.w
// llvm.x86.sse2.psrli.w

fn llvm_add_sub<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    bin_op: BinOp,
    ret: CPlace<'tcx>,
    cb_in: Value,
    a: CValue<'tcx>,
    b: CValue<'tcx>
) {
    assert_eq!(a.layout().ty, fx.tcx.types.u64, "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64");
    assert_eq!(b.layout().ty, fx.tcx.types.u64, "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64");

    // c + carry -> c + first intermediate carry or borrow respectively
    let int0 = crate::num::codegen_checked_int_binop(
        fx,
        bin_op,
        a,
        b,
    );
    let c = int0.value_field(fx, mir::Field::new(0));
    let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);

    // c + carry -> c + second intermediate carry or borrow respectively
    let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
    let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
    let int1 = crate::num::codegen_checked_int_binop(
        fx,
        bin_op,
        c,
        cb_in_as_u64,
    );
    let (c, cb1) = int1.load_scalar_pair(fx);

    // carry0 | carry1 -> carry or borrow respectively
    let cb_out = fx.bcx.ins().bor(cb0, cb1);

    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
    let val = CValue::by_val_pair(cb_out, c, layout);
    ret.write_cvalue(fx, val);
}
<|endoftext|>