<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2016 Skylor R. Schermer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//! Defines a structured Palette object for storing and generating colors.
use super::element::{ColorElement, Slot};
use super::metadata::Metadata;
use super::format::{PaletteFormat};
use color::{Color, lerp_rgb};
use address::Address;
use address;

use std::rc::Rc;
use std::collections::BTreeMap;
use std::collections::btree_map::{Iter, Keys};
use std::fmt;
use std::error;
use std::u8;
use std::mem;

/// The upper limit on the number of colors that can be in a single palette.
pub const MAX_PALETTE_SIZE: usize = (
	u8::MAX as usize * u8::MAX as usize * u8::MAX as usize
);

////////////////////////////////////////////////////////////////////////////////
// Palette
////////////////////////////////////////////////////////////////////////////////
/// Encapsulates a single palette.
#[derive(Debug)]
pub struct Palette {
	/// The PaletteFormat used to configure the palette.
	format_type: Option<&'static PaletteFormat>,
	/// The version of the PaletteFormat used to configure the palette.
	format_version: Option<(u8, u8, u8)>,
	/// A map assigning addresses to palette slots.
	data: BTreeMap<Address, Rc<Slot>>,
	/// Provided metadata for various parts of the palette.
	metadata: BTreeMap<address::Select, Metadata>,
	/// The internal address cursor that is used to track the next available
	/// address.
	address_cursor: address::Select,
	/// The number of pages in the palette.
	page_count: u8,
	/// The number of lines in each page.
	line_count: u8,
	/// The number of columns in each line.
	column_count: u8,
}

impl Palette {

	/// Constructs a new, empty Palette.
	#[inline]
	pub fn new() -> Palette {
		Default::default()
	}

	/// Returns the number of colors in the Palette.
	#[inline]
	pub fn len(&self) -> usize {
		self.data.len()
	}

	/// Returns an iterator over the (Address, Color) entries of the palette.
	#[inline]
	pub fn iter(&self) -> PaletteIterator {
		PaletteIterator::new(self)
	}

	/// Returns an iterator over the colors of the palette in address order.
	#[inline]
	pub fn colors(&self) -> ColorIterator {
		ColorIterator::new(self)
	}

	/// Returns and iterator over the addresses of the palette in order.
	#[inline]
	pub fn addresses(&self) -> AddressIterator {
		AddressIterator::new(self)
	}

	/// Returns the next available address after the cursor, and also advances
	/// the cursor to the next (wrapped) address. Returns an error and fails to
	/// advance the cursor if there are no free addresses.
	#[inline]
	fn next_free_address_advance_cursor(&mut self) -> Result<Address, Error> {
		let address = try!(self.next_free_address());
		// Update the cursor.
		self.address_cursor = address.wrapped_next(
			self.page_count,
			self.line_count,
			self.column_count
		).into();
		Ok(address)
	}

	/// Returns the next available address after the cursor. Returns an error if
	/// there are no free addresses.
	#[inline]
	fn next_free_address(&self) -> Result<Address, Error> {
		if self.space_remaining() == 0 {
			return Err(self.get_overflow_error());
		}

		let mut address = self.address_cursor.base_address();
		while self.data.get(&address).and_then(|s| s.get_color()).is_some() {
			address = address.wrapped_next(
				self.page_count,
				self.line_count,
				self.column_count
			);
		}
		Ok(address)
	}

	/// Returns whether the give address lies within the bounds defined by the
	/// wrapping and max page settings for the palette.
	#[inline]
	fn valid_address(&self, address: Address) -> bool {
		address.page <= self.page_count &&
		address.line < self.line_count &&
		address.column < self.column_count
	}

	/// Returns the upper bound on the number of slots storable in the palette.
	#[inline]
	fn size_bound(&self) -> usize {
		self.page_count as usize *
		self.line_count as usize *
		self.column_count as usize
	}

	/// Returns the amount of room left in the palette.
	#[inline]
	fn space_remaining(&self) -> usize {
		self.size_bound() - self.data.len()
	}

	/// Returns whether there are addresses that the palette considers invalid.
	#[inline]
	fn overflow_possible(&self) -> bool {
		self.column_count < u8::MAX ||
		self.line_count < u8::MAX ||
		self.page_count < u8::MAX
	}

	/// Returns the approprate error for an overflow condition.
	#[inline]
	fn get_overflow_error(&self) -> Error {
		if self.overflow_possible() {
			return Error::SetSlotLimitExceeded;
		} else {
			return Error::MaxSlotLimitExceeded;
		}
	}
}

impl fmt::Display for Palette {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		try!(write!(f, "Palette"));
		if let Some(data) = self.metadata.get(&address::Select::All) {
			try!(write!(f, " {}\n", data));
		}
		if let Some(format) = self.format_type {
			let version = format.get_version();
			try!(write!(f,
				"[{} {}.{}.{}]",
				format.get_name(),
				version.0,
				version.1,
				version.2));
		}
		try!(write!(f,
			" [{} pages] [wrap {}:{}] [cursor {}] \
			[{} slots free]",
			self.page_count,
			self.line_count,
			self.column_count,
			self.address_cursor,
			self.space_remaining()
		));

		try!(write!(f, "\n\tAddress   Color    Order  Name\n"));
		for (&address, ref slot) in self.data.iter() {
			try!(write!(f, "\t{:X}  {:X}  {:<5}  ",
				address,
				slot.borrow().get_color().unwrap_or(Color(0,0,0)),
				slot.borrow().get_order()
			));
			if let Some(data) = self.metadata.get(&address.clone().into()) {
				try!(write!(f, "{}\n", data));
			} else {
				try!(write!(f, "-\n"));
			}
		}
		Ok(())
	}
}

impl Default for Palette {
	fn default() -> Self {
		Palette {
			format_type: None,
			format_version: None,
			data: BTreeMap::new(),
			metadata: BTreeMap::new(),
			address_cursor: address::Select::All,
			page_count: u8::MAX,
			line_count: u8::MAX,
			column_count: u8::MAX,
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// PaletteIterator
////////////////////////////////////////////////////////////////////////////////
/// An iterator over the (Address, Color) entries of a palette. The entries are
/// returned in address order.
pub struct PaletteIterator<'p> {
	inner: Iter<'p, Address, Rc<Slot>>
}

impl<'p> PaletteIterator<'p> {
	fn new(palette: &'p Palette) -> Self {
		PaletteIterator {
			inner: palette.data.iter()
		}
	}
}

impl<'p> Iterator for PaletteIterator<'p> {
	type Item = (Address, Color);

	fn next(&mut self) -> Option<Self::Item> {
		if let Some((&address, ref slot)) = self.inner.next() {
			Some((address,
				slot.get_color()
					.expect("iterator unwrapped valid slot")))
		} else {
			None
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// ColorIterator
////////////////////////////////////////////////////////////////////////////////
/// An iterator over the colors of a palette. The colors are returned in address
/// order.
pub struct ColorIterator<'p> {
	inner: PaletteIterator<'p>
}

impl<'p> ColorIterator<'p> {
	fn new(palette: &'p Palette) -> Self {
		ColorIterator {inner: palette.iter()}
	}
}

impl<'p> Iterator for ColorIterator<'p> {
	type Item = Color;

	fn next(&mut self) -> Option<Self::Item> {
		self.inner.next().map(|item| item.1)
	}
}

////////////////////////////////////////////////////////////////////////////////
// AddressIterator
////////////////////////////////////////////////////////////////////////////////
/// An iterator over the colors of a palette. The colors are returned in address
/// order.
pub struct AddressIterator<'p> {
	inner: Keys<'p, Address, Rc<Slot>>
}

impl<'p> AddressIterator<'p> {
	fn new(palette: &'p Palette) -> Self {
		AddressIterator {inner: palette.data.keys()}
	}
}

impl<'p> Iterator for AddressIterator<'p> {
	type Item = Address;

	fn next(&mut self) -> Option<Self::Item> {
		self.inner.next().map(|&address| address)
	}
}

////////////////////////////////////////////////////////////////////////////////
// PaletteBuilder
////////////////////////////////////////////////////////////////////////////////
/// Encapsulates the state of the palette during builder pattern construction.
pub struct PaletteBuilder {
	/// The PaletteFormat used to configure the palette.
	format_type: Option<&'static PaletteFormat>,
	/// The version of the PaletteFormat used to configure the palette.
	format_version: Option<(u8, u8, u8)>,
	/// The internal address cursor that is used to track the next available
	/// address.
	address_cursor: address::Select,
	/// The number of pages in the palette.
	page_count: u8,
	/// The number of lines in each page.
	line_count: u8,
	/// The number of columns in each line.
	column_count: u8,
	/// The name of the palette.
	palette_name: Option<String>,
}

impl PaletteBuilder {

	/// Starts building the palette with the default settings.
	pub fn new() -> PaletteBuilder {
		Default::default()
	}

	/// Allows the given palette format specification to set the palette's
	/// properties.
	pub fn using_format<T>(mut self, format: &'static T) -> PaletteBuilder
		where T: PaletteFormat
	{
		self.format_type = Some(format);
		self.format_version = Some(format.get_version());
		format.configure(self)
	}

	/// Sets the palette name.
	pub fn named<S>(mut self, palette_name: S) -> PaletteBuilder
		where S: Into<String>
	{
		self.palette_name = Some(palette_name.into());
		self
	}

	/// Sets the max page count.
	pub fn with_page_count(mut self, page_count: u8) -> PaletteBuilder {
		self.page_count = page_count;
		self
	}

	/// Sets the line wrap for new slots.
	pub fn with_line_count(mut self, line_count: u8) -> PaletteBuilder {
		self.line_count = line_count;
		self
	}

	/// Sets the max page count.
	pub fn with_column_count(mut self, column_count: u8) -> PaletteBuilder {
		self.column_count = column_count;
		self
	}

	/// Sets the starting address cursor.
	pub fn with_starting_address_cursor(
		mut self,
		address_cursor: address::Select)
		-> PaletteBuilder
	{
		self.address_cursor = address_cursor;
		self
	}

	/// Builds the palette and returns it.
	pub fn create(self) -> Palette {
		let mut pal = Palette {
			format_type: self.format_type,
			format_version: self.format_version,
			address_cursor: self.address_cursor,
			page_count: self.page_count,
			line_count: self.line_count,
			column_count: self.column_count,
			.. Default::default()
		};

		if let Some(name) = self.palette_name {
			pal.metadata.insert(address::Select::All, Metadata::Name(name));
		}
		pal
	}
}

impl Default for PaletteBuilder {
	fn default() -> Self {
		PaletteBuilder {
			format_type: None,
			format_version: None,
			address_cursor: address::Select::All,
			page_count: u8::MAX,
			line_count: u8::MAX,
			column_count: u8::MAX,
			palette_name: None,
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// Error
////////////////////////////////////////////////////////////////////////////////
/// Encapsulates errors associated with mutating palette operations.
#[derive(Debug)]
pub enum Error {
	/// Attempted to add a color to the palette, but the current wrapping
	/// settings prevent adding the color within the defined ranges. (Overflow
	/// is possible.)
	SetSlotLimitExceeded,
	/// Attempted to add a color to the palette, but the palette contains the
	/// maximum number of slots already. (Overflow not possible.)
	MaxSlotLimitExceeded,
	/// Attempted to set a color to a non-zeroth-order slot.
	CannotSetDerivedColor,
	/// An address was provided that lies outside of the range defined for the
	/// palette.
	InvalidAddress,
	/// An empty address was provided for an operation that requires a color.
	EmptyAddress(Address)
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		match *self {
			Error::EmptyAddress(address) => write!(f, "{}: {}",
				error::Error::description(self),
				address
			),

			_ => write!(f, "{}", error::Error::description(self))
		}
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			Error::SetSlotLimitExceeded
				=> "maximum number of color slots for wrapping settings \
					exceeded",
			Error::MaxSlotLimitExceeded
				=> "maximum number of color slots for palette exceeded",
			Error::CannotSetDerivedColor
				=> "cannot assign color to a location containing a derived \
				    color value",
			Error::InvalidAddress
				=> "address provided is outside allowed range for palette",
			Error::EmptyAddress(..)
				=> "empty address provided to an operation requiring a color"
		}
	}
}<commit_msg>REFACTOR: Removed reduntant palette error.<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016 Skylor R. Schermer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//! Defines a structured Palette object for storing and generating colors.
use super::element::{ColorElement, Slot};
use super::metadata::Metadata;
use super::format::{PaletteFormat};
use color::{Color, lerp_rgb};
use address::Address;
use address;

use std::rc::Rc;
use std::collections::BTreeMap;
use std::collections::btree_map::{Iter, Keys};
use std::fmt;
use std::error;
use std::u8;
use std::mem;

////////////////////////////////////////////////////////////////////////////////
// Palette
////////////////////////////////////////////////////////////////////////////////
/// Encapsulates a single palette.
#[derive(Debug)]
pub struct Palette {
	/// The PaletteFormat used to configure the palette.
	format_type: Option<&'static PaletteFormat>,
	/// The version of the PaletteFormat used to configure the palette.
	format_version: Option<(u8, u8, u8)>,
	/// A map assigning addresses to palette slots.
	data: BTreeMap<Address, Rc<Slot>>,
	/// Provided metadata for various parts of the palette.
	metadata: BTreeMap<address::Select, Metadata>,
	/// The internal address cursor that is used to track the next available
	/// address.
	address_cursor: address::Select,
	/// The number of pages in the palette.
	page_count: u8,
	/// The number of lines in each page.
	line_count: u8,
	/// The number of columns in each line.
	column_count: u8,
}

impl Palette {

	/// Constructs a new, empty Palette.
	#[inline]
	pub fn new() -> Palette {
		Default::default()
	}

	/// Returns the number of colors in the Palette.
	#[inline]
	pub fn len(&self) -> usize {
		self.data.len()
	}

	/// Returns an iterator over the (Address, Color) entries of the palette.
	#[inline]
	pub fn iter(&self) -> PaletteIterator {
		PaletteIterator::new(self)
	}

	/// Returns an iterator over the colors of the palette in address order.
	#[inline]
	pub fn colors(&self) -> ColorIterator {
		ColorIterator::new(self)
	}

	/// Returns and iterator over the addresses of the palette in order.
	#[inline]
	pub fn addresses(&self) -> AddressIterator {
		AddressIterator::new(self)
	}

	/// Returns the next available address after the cursor, and also advances
	/// the cursor to the next (wrapped) address. Returns an error and fails to
	/// advance the cursor if there are no free addresses.
	#[inline]
	fn next_free_address_advance_cursor(&mut self) -> Result<Address, Error> {
		let address = try!(self.next_free_address());
		// Update the cursor.
		self.address_cursor = address.wrapped_next(
			self.page_count,
			self.line_count,
			self.column_count
		).into();
		Ok(address)
	}

	/// Returns the next available address after the cursor. Returns an error if
	/// there are no free addresses.
	#[inline]
	fn next_free_address(&self) -> Result<Address, Error> {
		if self.space_remaining() == 0 {
			return Err(Error::MaxSlotLimitExceeded);
		}

		let mut address = self.address_cursor.base_address();
		while self.data.get(&address).and_then(|s| s.get_color()).is_some() {
			address = address.wrapped_next(
				self.page_count,
				self.line_count,
				self.column_count
			);
		}
		Ok(address)
	}

	/// Returns whether the give address lies within the bounds defined by the
	/// wrapping and max page settings for the palette.
	#[inline]
	fn valid_address(&self, address: Address) -> bool {
		address.page <= self.page_count &&
		address.line < self.line_count &&
		address.column < self.column_count
	}

	/// Returns the upper bound on the number of slots storable in the palette.
	#[inline]
	fn size_bound(&self) -> usize {
		self.page_count as usize *
		self.line_count as usize *
		self.column_count as usize
	}

	/// Returns the amount of room left in the palette.
	#[inline]
	fn space_remaining(&self) -> usize {
		self.size_bound() - self.data.len()
	}
}

impl fmt::Display for Palette {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		try!(write!(f, "Palette"));
		if let Some(data) = self.metadata.get(&address::Select::All) {
			try!(write!(f, " {}\n", data));
		}
		if let Some(format) = self.format_type {
			let version = format.get_version();
			try!(write!(f,
				"[{} {}.{}.{}]",
				format.get_name(),
				version.0,
				version.1,
				version.2));
		}
		try!(write!(f,
			" [{} pages] [wrap {}:{}] [cursor {}] \
			[{} slots free]",
			self.page_count,
			self.line_count,
			self.column_count,
			self.address_cursor,
			self.space_remaining()
		));

		try!(write!(f, "\n\tAddress   Color    Order  Name\n"));
		for (&address, ref slot) in self.data.iter() {
			try!(write!(f, "\t{:X}  {:X}  {:<5}  ",
				address,
				slot.borrow().get_color().unwrap_or(Color(0,0,0)),
				slot.borrow().get_order()
			));
			if let Some(data) = self.metadata.get(&address.clone().into()) {
				try!(write!(f, "{}\n", data));
			} else {
				try!(write!(f, "-\n"));
			}
		}
		Ok(())
	}
}

impl Default for Palette {
	fn default() -> Self {
		Palette {
			format_type: None,
			format_version: None,
			data: BTreeMap::new(),
			metadata: BTreeMap::new(),
			address_cursor: address::Select::All,
			page_count: u8::MAX,
			line_count: u8::MAX,
			column_count: u8::MAX,
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// PaletteIterator
////////////////////////////////////////////////////////////////////////////////
/// An iterator over the (Address, Color) entries of a palette. The entries are
/// returned in address order.
pub struct PaletteIterator<'p> {
	inner: Iter<'p, Address, Rc<Slot>>
}

impl<'p> PaletteIterator<'p> {
	fn new(palette: &'p Palette) -> Self {
		PaletteIterator {
			inner: palette.data.iter()
		}
	}
}

impl<'p> Iterator for PaletteIterator<'p> {
	type Item = (Address, Color);

	fn next(&mut self) -> Option<Self::Item> {
		if let Some((&address, ref slot)) = self.inner.next() {
			Some((address,
				slot.get_color()
					.expect("iterator unwrapped valid slot")))
		} else {
			None
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// ColorIterator
////////////////////////////////////////////////////////////////////////////////
/// An iterator over the colors of a palette. The colors are returned in address
/// order.
pub struct ColorIterator<'p> {
	inner: PaletteIterator<'p>
}

impl<'p> ColorIterator<'p> {
	fn new(palette: &'p Palette) -> Self {
		ColorIterator {inner: palette.iter()}
	}
}

impl<'p> Iterator for ColorIterator<'p> {
	type Item = Color;

	fn next(&mut self) -> Option<Self::Item> {
		self.inner.next().map(|item| item.1)
	}
}

////////////////////////////////////////////////////////////////////////////////
// AddressIterator
////////////////////////////////////////////////////////////////////////////////
/// An iterator over the colors of a palette. The colors are returned in address
/// order.
pub struct AddressIterator<'p> {
	inner: Keys<'p, Address, Rc<Slot>>
}

impl<'p> AddressIterator<'p> {
	fn new(palette: &'p Palette) -> Self {
		AddressIterator {inner: palette.data.keys()}
	}
}

impl<'p> Iterator for AddressIterator<'p> {
	type Item = Address;

	fn next(&mut self) -> Option<Self::Item> {
		self.inner.next().map(|&address| address)
	}
}

////////////////////////////////////////////////////////////////////////////////
// PaletteBuilder
////////////////////////////////////////////////////////////////////////////////
/// Encapsulates the state of the palette during builder pattern construction.
pub struct PaletteBuilder {
	/// The PaletteFormat used to configure the palette.
	format_type: Option<&'static PaletteFormat>,
	/// The version of the PaletteFormat used to configure the palette.
	format_version: Option<(u8, u8, u8)>,
	/// The internal address cursor that is used to track the next available
	/// address.
	address_cursor: address::Select,
	/// The number of pages in the palette.
	page_count: u8,
	/// The number of lines in each page.
	line_count: u8,
	/// The number of columns in each line.
	column_count: u8,
	/// The name of the palette.
	palette_name: Option<String>,
}

impl PaletteBuilder {

	/// Starts building the palette with the default settings.
	pub fn new() -> PaletteBuilder {
		Default::default()
	}

	/// Allows the given palette format specification to set the palette's
	/// properties.
	pub fn using_format<T>(mut self, format: &'static T) -> PaletteBuilder
		where T: PaletteFormat
	{
		self.format_type = Some(format);
		self.format_version = Some(format.get_version());
		format.configure(self)
	}

	/// Sets the palette name.
	pub fn named<S>(mut self, palette_name: S) -> PaletteBuilder
		where S: Into<String>
	{
		self.palette_name = Some(palette_name.into());
		self
	}

	/// Sets the max page count.
	pub fn with_page_count(mut self, page_count: u8) -> PaletteBuilder {
		self.page_count = page_count;
		self
	}

	/// Sets the line wrap for new slots.
	pub fn with_line_count(mut self, line_count: u8) -> PaletteBuilder {
		self.line_count = line_count;
		self
	}

	/// Sets the max page count.
	pub fn with_column_count(mut self, column_count: u8) -> PaletteBuilder {
		self.column_count = column_count;
		self
	}

	/// Sets the starting address cursor.
	pub fn with_starting_address_cursor(
		mut self,
		address_cursor: address::Select)
		-> PaletteBuilder
	{
		self.address_cursor = address_cursor;
		self
	}

	/// Builds the palette and returns it.
	pub fn create(self) -> Palette {
		let mut pal = Palette {
			format_type: self.format_type,
			format_version: self.format_version,
			address_cursor: self.address_cursor,
			page_count: self.page_count,
			line_count: self.line_count,
			column_count: self.column_count,
			.. Default::default()
		};

		if let Some(name) = self.palette_name {
			pal.metadata.insert(address::Select::All, Metadata::Name(name));
		}
		pal
	}
}

impl Default for PaletteBuilder {
	fn default() -> Self {
		PaletteBuilder {
			format_type: None,
			format_version: None,
			address_cursor: address::Select::All,
			page_count: u8::MAX,
			line_count: u8::MAX,
			column_count: u8::MAX,
			palette_name: None,
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// Error
////////////////////////////////////////////////////////////////////////////////
/// Encapsulates errors associated with mutating palette operations.
#[derive(Debug)]
pub enum Error {
	/// Attempted to add a color to the palette, but the palette contains the
	/// maximum number of slots already.
	MaxSlotLimitExceeded,
	/// Attempted to set a color to a non-zeroth-order slot.
	CannotSetDerivedColor,
	/// An address was provided that lies outside of the range defined for the
	/// palette.
	InvalidAddress,
	/// An empty address was provided for an operation that requires a color.
	EmptyAddress(Address)
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		match *self {
			Error::EmptyAddress(address) => write!(f, "{}: {}",
				error::Error::description(self),
				address
			),

			_ => write!(f, "{}", error::Error::description(self))
		}
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			Error::MaxSlotLimitExceeded
				=> "maximum number of color slots for palette exceeded",
			Error::CannotSetDerivedColor
				=> "cannot assign color to a location containing a derived \
				    color value",
			Error::InvalidAddress
				=> "address provided is outside allowed range for palette",
			Error::EmptyAddress(..)
				=> "empty address provided to an operation requiring a color"
		}
	}
}<|endoftext|>


<commit_before>/*
 * Copyright 2016-2018 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 crate::{
    json::{FieldBased, NoOuter, ShouldSkip},
    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: S) -> Result<S::Ok, 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);

    pub fn with_scale(mut self, val: Scale) -> Self {
        self.scale = val;
        self
    }

    pub fn with_origin(mut self, val: Origin) -> Self {
        self.origin = val;
        self
    }

    pub fn build<A: Into<String>>(self, field: A) -> Decay {
        Decay(FieldBased::new(
            field.into(),
            self,
            NoOuter,
        ))
    }
}

/// 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,
        ))
    }

    pub fn build_decay_from_options<A: Into<String>>(field: A, options: DecayOptions) -> Decay {
        options.build(field)
    }
}

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: S) -> Result<S::Ok, 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: S) -> Result<S::Ok, 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: S) -> Result<S::Ok, 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 crate::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.0,"lon":24.0},"scale":"3km"}}}"#,
            serde_json::to_string(&gauss_decay_query).unwrap()
        );
    }
}
<commit_msg>Add function to build DecayOptions<commit_after>/*
 * Copyright 2016-2018 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 crate::{
    json::{FieldBased, NoOuter, ShouldSkip},
    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: S) -> Result<S::Ok, 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 {
    pub fn new<A, B>(origin: A, scale: B) -> DecayOptions
    where
        A: Into<Origin>,
        B: Into<Scale>,
    {
        DecayOptions {
            origin: origin.into(),
            scale: scale.into(),
            offset: None,
            decay: None,
            multi_value_mode: None,
        }
    }

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

    pub fn with_scale(mut self, val: Scale) -> Self {
        self.scale = val;
        self
    }

    pub fn with_origin(mut self, val: Origin) -> Self {
        self.origin = val;
        self
    }

    pub fn build<A: Into<String>>(self, field: A) -> Decay {
        Decay(FieldBased::new(
            field.into(),
            self,
            NoOuter,
        ))
    }
}

/// 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,
        ))
    }

    pub fn build_decay_from_options<A: Into<String>>(field: A, options: DecayOptions) -> Decay {
        options.build(field)
    }
}

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: S) -> Result<S::Ok, 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: S) -> Result<S::Ok, 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: S) -> Result<S::Ok, 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 crate::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.0,"lon":24.0},"scale":"3km"}}}"#,
            serde_json::to_string(&gauss_decay_query).unwrap()
        );
    }
}
<|endoftext|>


<commit_before>#![feature(const_fn)]
#![feature(slice_patterns)]
#![cfg_attr(test, feature(test))]

pub mod color;
pub mod matrix;
pub mod orientation;
pub mod point;
pub mod quaternion;
pub mod vector;

#[cfg(test)]
mod test;

pub use point::Point;
pub use vector::{Vector2, Vector3};
pub use matrix::{Matrix3, Matrix4};
pub use color::Color;
pub use orientation::Orientation;

pub use std::f32::consts::PI;

pub const TAU: f32 = 2.0 * PI;

pub const EPSILON: f32 = 1e-6;

pub trait IsZero {
    fn is_zero(self) -> bool;
}

impl IsZero for f32 {
    fn is_zero(self) -> bool {
        self.abs() < EPSILON
    }
}

pub trait Clamp {
    fn clamp(self, min: Self, max: Self) -> Self;
}

impl Clamp for f32 {
    fn clamp(self, min: f32, max: f32) -> f32 {
        f32::min(f32::max(self, min), max)
    }
}

pub trait Dot<Other=Self> {
    type Output;

    fn dot(self, rhs: Other) -> Self::Output;
}

impl Dot for [f32; 3] {
    type Output = f32;

    fn dot(self, rhs: [f32; 3]) -> f32 {
        self[0] * rhs[0]
      + self[1] * rhs[1]
      + self[2] * rhs[2]
    }
}

// Doesn't cause ICE.
impl<'a, T> Dot<&'a T> for T where T: Dot<T> + Copy {
    type Output = T::Output;

    fn dot(self, rhs: &T) -> Self::Output {
        self.dot(*rhs)
    }
}

// // Causes ICE.
// impl<'a, T, U> Dot<&'a U> for T where T: Dot<U>, U: Copy {
//     type Output = T::Output;
//
//     fn dot(self, rhs: &U) -> Self::Output {
//         self.dot(*rhs)
//     }
// }

pub trait Lerp {
    fn lerp(t: f32, from: Self, to: Self) -> Self;
}

impl Lerp for f32 {
    fn lerp(t: f32, from: f32, to: f32) -> f32 {
        from + (to - from) * t
    }
}
<commit_msg>Add Modulo trait and default implementation for all Add + Rem types<commit_after>#![feature(const_fn)]
#![feature(slice_patterns)]
#![cfg_attr(test, feature(test))]

pub mod color;
pub mod matrix;
pub mod orientation;
pub mod point;
pub mod quaternion;
pub mod vector;

#[cfg(test)]
mod test;

pub use color::Color;
pub use matrix::{Matrix3, Matrix4};
pub use orientation::Orientation;
pub use point::Point;
pub use std::f32::consts::PI;
pub use vector::{Vector2, Vector3};

use std::ops::{Rem, Add};

pub const EPSILON: f32 = 1e-6;
pub const TAU: f32 = 2.0 * PI;

pub trait IsZero {
    fn is_zero(self) -> bool;
}

impl IsZero for f32 {
    fn is_zero(self) -> bool {
        self.abs() < EPSILON
    }
}

pub trait Clamp {
    fn clamp(self, min: Self, max: Self) -> Self;
}

impl Clamp for f32 {
    fn clamp(self, min: f32, max: f32) -> f32 {
        f32::min(f32::max(self, min), max)
    }
}

pub trait Dot<Other=Self> {
    type Output;

    fn dot(self, rhs: Other) -> Self::Output;
}

impl Dot for [f32; 3] {
    type Output = f32;

    fn dot(self, rhs: [f32; 3]) -> f32 {
        self[0] * rhs[0]
      + self[1] * rhs[1]
      + self[2] * rhs[2]
    }
}

// Doesn't cause ICE.
impl<'a, T> Dot<&'a T> for T where T: Dot<T> + Copy {
    type Output = T::Output;

    fn dot(self, rhs: &T) -> Self::Output {
        self.dot(*rhs)
    }
}

// // Causes ICE.
// impl<'a, T, U> Dot<&'a U> for T where T: Dot<U>, U: Copy {
//     type Output = T::Output;
//
//     fn dot(self, rhs: &U) -> Self::Output {
//         self.dot(*rhs)
//     }
// }

pub trait Lerp {
    fn lerp(t: f32, from: Self, to: Self) -> Self;
}

impl Lerp for f32 {
    fn lerp(t: f32, from: f32, to: f32) -> f32 {
        from + (to - from) * t
    }
}

pub trait Modulo<Rhs = Self> {
    type Output;

    fn modulo(self, divisor: Rhs) -> Self::Output;
}

impl<T> Modulo for T
    where
    T: Copy,
    T: Rem<Output=T>,
    T: Add<Output=T>,
{
    type Output = T;

    fn modulo(self, divisor: T) -> T {
        ((self % divisor) + divisor) % divisor
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use super::Error;
use super::types::SqlType;
use super::types::Column;
use std::io::{Write, Read, Seek, SeekFrom, Cursor};
use super::super::parse::ast::CompType;

#[derive(Debug)]
pub struct Rows <B: Write + Read + Seek> {
    data_src: B,
    columns: Vec<Column>,
    columns_size: u64,
    pub column_offsets: Vec<u64>,
    pos: u64,
}

/// Represents the lines read from file.
impl<B: Write + Read + Seek> Rows <B> {

    pub fn new(data_src: B, columns: &[Column]) -> Rows<B> {
        let mut column_offsets = Vec::<u64>::new();
        let mut offset: u64 = 0;
        for c in columns {
            column_offsets.push(offset);
            offset += c.get_size() as u64;
        }

        Rows {  data_src: data_src,
                columns: columns.to_vec(),
                columns_size: Self::get_columns_size(columns),
                column_offsets: column_offsets,
                pos: 0
            }
    }
    // returns the sum of the column sizes
    fn get_columns_size(columns: &[Column]) -> u64 {
        let mut size: u64 = 0;
        for c in columns {
            size += c.get_size() as u64;
        }
        size
    }

    /// reads the next row, which is not marked as deleted
    /// and writes the data into target_buf
    /// returns the bytes read or an Error otherwise.
    pub fn next_row<W: Write>(&mut self, mut target_buf: &mut W)
        -> Result<u64, Error>
    {
        let mut target_vec = Vec::<u8>::new();
        let columns_size = self.columns_size;
        info!("Reading Header");
        let mut row_header: RowHeader = try!(self.read_header());
        info!("Header Read");
        while row_header.is_deleted() {
            self.skip_row();
            row_header = try!(self.read_header());
        }

        info!("data read");
        try!(self.read_bytes(columns_size, &mut target_vec));
        try!(target_buf.write_all(&target_vec));
        info!("data read");
        Ok(target_vec.len() as u64)
    }

    /// sets pos to the beginning of the next row
    fn skip_row(&mut self) -> Result<u64, Error> {
        let columns_size = self.columns_size as i64;
        self.set_pos(SeekFrom::Current(columns_size))
    }

    /// sets pos to the beginning of the previous row
    fn prev_row(&mut self) -> Result<u64, Error> {
        let columns_size = self.columns_size as i64;
        self.set_pos(SeekFrom::Current(-(columns_size+(RowHeader::size()) as i64)))
    }

    /// sets position before the first line
    pub fn reset_pos(&mut self) -> Result<u64, Error> {
        self.set_pos(SeekFrom::Start(0))
    }

    /// sets position to offset
    fn set_pos(&mut self, seek_from: SeekFrom) -> Result<u64, Error> {
        match self.data_src.seek(seek_from) {
            Ok(n) => {
                self.pos = n;
                Ok(n)
            },
            Err(e) => return Err(Error::Io(e))
        }
    }

    /// reads the header of the current row
    /// moves the cursor past the header
    /// returns an error if no RowHeader exists
    fn read_header(&mut self) -> Result <RowHeader, Error> {
        let mut target_buf = Vec::<u8>::new();
        try!(self.read_bytes(RowHeader::size(), &mut target_buf));
        Ok(RowHeader::new(target_buf[0]))
    }

    /// writes a new row into buf, returns bytes written
    pub fn add_row(&mut self, data: &[u8]) -> Result<u64, Error> {
        info!("Adding Row");
        let new_row_header = RowHeader::new(0);
        try!(self.write_bytes(&new_row_header.to_raw_data()));
        Ok(try!(self.write_bytes(&data)))
    }

    /// set delete bit for one row
    pub fn delete_row(&mut self) -> Result<(), Error> {
        self.prev_row();
        let row_header = RowHeader::new(1);
        try!(self.write_bytes(&row_header.to_raw_data()));
        self.skip_row();
        info!("Row Deleted");
        Ok(())
    }

    /// returns the value of the column_index' column of the current row
    /// returns Error::InvalidState if no current row exists
    pub fn get_value(&self, row_data: &[u8], column_index: usize) -> Result<Vec<u8>, Error> {
        if row_data.len() == 0 {
            return Err(Error::InvalidState);
        }

        let s = self.column_offsets[column_index] as usize;
        let e = s + self.get_column(column_index).get_size() as usize;
        let d = row_data[s..e].to_vec();
        info!("get value: {:?}", d);
        Ok(d)
    }

    // returns the columns
    pub fn get_column(&self, index: usize) -> &Column {
        &self.columns[index]
    }

    /// reads the specified amount of bytes and writes them into target_buf
    /// returns bytes_read or error if bytes_read != bytes_to_read
    fn read_bytes(&mut self, bytes_to_read: u64, mut target_buf: &mut Vec<u8>)
        -> Result<u64, Error>
    {
        info!("Reading Bytes");
        let mut reader = (&mut self.data_src).take(bytes_to_read);
        let result = reader.read_to_end(&mut target_buf);
        let bytes_read = match result {
            Ok(n) => {
                if n == 0 {
                    return Err(Error::EndOfFile);
                };
                if n as u64 != bytes_to_read {
                    info!("bytes_read {:?} bytes_to_read {:?}", n, bytes_to_read);
                    return Err(Error::InterruptedRead);
                };
                n
            },
            Err(e) => {
                return Err(Error::Io(e));
            }
        };
        self.pos += bytes_read as u64;
        Ok(bytes_read as u64)
    }

    /// writes data to data_src
    /// returns bytes written
    fn write_bytes(&mut self, data: &[u8]) -> Result<u64, Error> {
            match self.data_src.write_all(data) {
            Ok(_) => {
                return Ok(data.len() as u64)
            },
            Err(e) => return Err(Error::Io(e))
        }
    }

    /// Inserts a new row with row_data.
    /// Returns the number of rows inserted.
    pub fn insert_row(&mut self, row_data: &[u8]) -> Result<u64, Error> {
        let mut pks: Vec<usize> = Vec::new();
        let mut count: usize = 0;
        //let mut value: Vec<Vec<u8>> = Vec::new();
        // get pks
        {
            let mut it = self.columns.iter();
            loop {
                match it.next() {
                    Some(x) => {
                        if x.is_primary_key {
                            pks.push(count);
                        }
                        count += 1;
                    },
                    None => break,
                };
            }
        }
        // do lookups
        {
            let mut it = pks.iter();
            let first = match it.next() {
                Some(x) => x,
                None => return Err(Error::FoundNoPrimaryKey),
            };

            let val = try!(self.get_value(row_data, *first));
            let mut look = try!(self.lookup(*first, &val, CompType::Equ));

            loop {
                match it.next() {
                    Some(x) => {
                        let value = try!(self.get_value(row_data, *x));
                        look = try!(look.lookup(*x, &value, CompType::Equ));
                        if try!(look.is_empty()) {
                            break;
                        }
                    },
                    None => break,
                };
            }
            if !try!(look.is_empty()) {
                return Err(Error::PrimaryKeyValueExists);
            }
        }
        self.set_pos(SeekFrom::End(0));
        Ok(try!(self.add_row(row_data)))
    }

    /// deletes rows which fulfills a constraint
    /// return rows deleted
    pub fn delete(&mut self, column_index: usize, value: &[u8], comp: CompType)
     -> Result<u64, Error>
    {
        let mut count = 0;
        while true {
            match self.get_next_row(column_index, value, comp) {
                Ok(_) => {
                    count += 1;
                    self.delete_row();
                }
                Err(e) => {
                    match e {
                        Error::EndOfFile => {
                            info!("reached end of file");
                            break;
                        },
                        _ => return Err(e)
                    }
                }
            }
        }

        Ok(count)

    }

    /// returns an new Rows object which fulfills a constraint
   pub fn lookup(&mut self, column_index: usize, value: &[u8], comp: CompType)
    -> Result<Rows<Cursor<Vec<u8>>>, Error>
    {
        let vec: Vec<u8> = Vec::new();
        let cursor = Cursor::new(vec);
        let mut rows = Rows::new(cursor, &self.columns);

        while true {
            let result = self.get_next_row(column_index, value, comp);
            match result {
                Ok(r) => {
                    println!{"Row: {:?}", r};
                    rows.add_row(&r);

                },
                Err(e) => {
                    match e {
                        Error::EndOfFile => {
                            info!("reached end of file");
                            break;
                        },
                        _ => return Err(e)
                    }
                }
            }
        }

        Ok(rows)
    }

    /// returns all rows which are not deleted
    pub fn full_scan(&mut self) -> Result<Rows<Cursor<Vec<u8>>>, Error> {
        let vec: Vec<u8> = Vec::new();
        let cursor = Cursor::new(vec);
        let mut rows = Rows::new(cursor, &self.columns);
        let mut buf: Vec<u8> = Vec::new();

        while true {
            match self.next_row(&mut buf) {
                Ok(_) => {
                        rows.add_row(& buf);
                },
                Err(e) => {
                    match e {
                        Error::EndOfFile => break,
                        _ => return Err(e)
                    }
                },
            }
        }
        Ok(rows)
    }

    /// returns true if data_src is empty
    pub fn is_empty(&mut self) -> Result <bool, Error> {
        //data_src.is_empty()
        let old_pos = self.pos;

        let result: Result<bool, Error> = match self.set_pos(SeekFrom::End(0)) {
            Ok(n) => {
                if n == 0 {
                    Ok(true)
                } else {
                    Ok(false)
                }
            },
            Err(e) => {
                Err(e)
            },
        };

        self.pos = old_pos;

        result
    }

    /// moves the cursor from the current position the row after the first row
    /// which fulfills the constraint.
    /// Returns the first row which fulfilly the condition.
    pub fn get_next_row(&mut self, column_index: usize, value: &[u8], comp: CompType)
    -> Result<Vec<u8>, Error>
    {
        let mut row = Vec::<u8>::new();
        let mut b = true;

        while b {
            b = match self.next_row(&mut row) {
                Ok(_) => {
                    let col = self.get_column(column_index);

                    let row_value: &Vec<u8> = &try!(self.get_value(&row, column_index));
                    let cmp_result = try!(col.sql_type.cmp(row_value, value, comp));

                    if cmp_result {
                        false
                    } else {
                        row.clear();
                        true
                    }
                },
                Err(e) => {
                    return Err(e)
                }
            }
        }

        Ok(row)
    }

}

pub struct RowHeader {
     pub data: u8,
}

impl RowHeader{

    pub fn new(deleted: u8) -> RowHeader {
        let data = 0 as u8;
        let mut h = RowHeader {
            data: data,
        };
        h.set_deleted(deleted);
        h
    }

    /// returns true if the current row is marked as deleted
    pub fn is_deleted(&self) -> bool {
        info!("check for delete bit");
        (self.data & 1 as u8) == 1
    }

    /// marks row as deleted
    pub fn set_deleted(&mut self, value: u8) {
        info!("set delete bit");
        if value == 1 {
            self.data |= 1 as u8
        }
        else {
            self.data &= 0xFE as u8
        }
    }
    /// returns size of RowHeader
    pub fn size() -> u64 {
        1
    }

    pub fn to_raw_data(&self) -> Vec<u8> {
        let mut raw_data = Vec::<u8>::new();
        raw_data.push(self.data);
        raw_data
    }
}
<commit_msg>add documentation and last touches<commit_after>use std::vec::Vec;
use super::Error;
use super::types::SqlType;
use super::types::Column;
use std::io::{Write, Read, Seek, SeekFrom, Cursor};
use super::super::parse::ast::CompType;

#[derive(Debug)]
pub struct Rows <B: Write + Read + Seek> {
    data_src: B,
    columns: Vec<Column>,
    columns_size: u64,
    pub column_offsets: Vec<u64>,
    pos: u64,
}

/// Represents the lines read from file.
impl<B: Write + Read + Seek> Rows <B> {

    pub fn new(data_src: B, columns: &[Column]) -> Rows<B> {
        let mut column_offsets = Vec::<u64>::new();
        let mut offset: u64 = 0;
        for c in columns {
            column_offsets.push(offset);
            offset += c.get_size() as u64;
        }

        Rows {  data_src: data_src,
                columns: columns.to_vec(),
                columns_size: Self::get_columns_size(columns),
                column_offsets: column_offsets,
                pos: 0
            }

    }
    // returns the sum of the column sizes
    fn get_columns_size(columns: &[Column]) -> u64 {
        let mut size: u64 = 0;
        for c in columns {
            size += c.get_size() as u64;
        }
        size
    }

    /// reads the next row, which is not marked as deleted
    /// and writes the data into target_buf
    /// returns the bytes read or an Error otherwise.
    pub fn next_row<W: Write>(&mut self, mut target_buf: &mut W)
        -> Result<u64, Error>
    {
        let mut target_vec = Vec::<u8>::new();
        let columns_size = self.columns_size;
        info!("Reading Header");
        let mut row_header: RowHeader = try!(self.read_header());
        info!("Header Read");
        while (row_header.is_deleted()) {
            self.skip_row();
            row_header = try!(self.read_header());
        }

        info!("data read");
        try!(self.read_bytes(columns_size, &mut target_vec));
        try!(target_buf.write_all(&target_vec));
        info!("data read");
        Ok(target_vec.len() as u64)
    }

    /// sets pos to the beginning of the next row
    fn skip_row(&mut self) -> Result<u64, Error> {
        let columns_size = self.columns_size as i64;
        self.set_pos(SeekFrom::Current(columns_size))
    }

    /// sets pos to the beginning of the previous row
    fn prev_row(&mut self) -> Result<u64, Error> {
        let columns_size = self.columns_size as i64;
        self.set_pos(SeekFrom::Current(-(columns_size+(RowHeader::size()) as i64)))
    }

    /// sets position before the first line
    pub fn reset_pos(&mut self) -> Result<u64, Error> {
        self.set_pos(SeekFrom::Start(0))
    }

    /// sets position to offset
    fn set_pos(&mut self, seek_from: SeekFrom) -> Result<u64, Error> {
        match self.data_src.seek(seek_from) {
            Ok(n) => {
                self.pos = n;
                Ok(n)
            },
            Err(e) => return Err(Error::Io(e))
        }
    }
/*
    fn last_not_deleted_row(&mut self) -> Result<u64, Error> {
        let old_pos = pos;
        let last_row_pos = try!(set_pos(
        SeekFrom::End(-(RowHeader::size() + self::get_columns_size(self.columns))
        ));
        loop {

            let header = self.read_header();
            if !header.is_deleted() {
                set_pos(SeekFrom::Start(old_pos));
                return last_row_pos;
            }

            if last_row_pos == old_pos {
                return last_row_pos;
            }

            if last_row_pos < old_pos {
                Err(Error::InvalidState);
            }

            last_row_pos = try!(set_pos(
            SeekFrom::Current(-(RowHeader::size() + self::get_columns_size(self.columns))
            ));
        }
    }

    fn get_next_deleted_row(&mut self) -> Result<u64, Error> {
        let old_pos = pos;
        let mut new_pos = 0;
        let mut target_vec = Vec::<u8>::new();
        loop {
            new_pos = pos;
            let header = try!(self.read_header());
            set_pos()
            try!(self.next_row(&target_vec, false));
            if header.is_deleted() {
                return Ok(new_pos);
            }
        }
    }*/
    /// reads the header of the current row
    /// moves the cursor past the header
    /// returns an error if no RowHeader exists
    fn read_header(&mut self) -> Result <RowHeader, Error> {
        let mut target_buf = Vec::<u8>::new();
        try!(self.read_bytes(RowHeader::size(), &mut target_buf));
        Ok(RowHeader::new(target_buf[0]))
    }

    /// writes a new row into buf, returns bytes written
    pub fn add_row(&mut self, data: &[u8]) -> Result<u64, Error> {
        info!("Adding Row");
        let new_row_header = RowHeader::new(0);
        try!(self.write_bytes(&new_row_header.to_raw_data()));
        Ok(try!(self.write_bytes(&data)))
    }

    /// set delete bit for one row
    pub fn delete_row(&mut self) -> Result<(), Error> {
        self.prev_row();
        let row_header = RowHeader::new(1);
        try!(self.write_bytes(&row_header.to_raw_data()));
        self.skip_row();
        info!("Row Deleted");
        Ok(())
    }

    /// returns the value of the column_index' column of the current row
    /// returns Error::InvalidState if no current row exists
    pub fn get_value(&self, row_data: &[u8], column_index: usize) -> Result<Vec<u8>, Error> {
        if row_data.len() == 0 {
            return Err(Error::InvalidState);
        }

        let s = self.column_offsets[column_index] as usize;
        let e = s + self.get_column(column_index).get_size() as usize;
        let d = row_data[s..e].to_vec();
        info!("get value: {:?}", d);
        Ok(d)
    }

    // returns the columns
    pub fn get_column(&self, index: usize) -> &Column {
        &self.columns[index]
    }

    /// reads the specified amount of bytes and writes them into target_buf
    /// returns bytes_read or error if bytes_read != bytes_to_read
    fn read_bytes(&mut self, bytes_to_read: u64, mut target_buf: &mut Vec<u8>)
        -> Result<u64, Error>
    {
        info!("Reading Bytes");
        let mut reader = (&mut self.data_src).take(bytes_to_read);
        let result = reader.read_to_end(&mut target_buf);
        let bytes_read = match result {
            Ok(n) => {
                if n == 0 {
                    return Err(Error::EndOfFile);
                };
                if n as u64 != bytes_to_read {
                    info!("bytes_read {:?} bytes_to_read {:?}", n, bytes_to_read);
                    return Err(Error::InterruptedRead);
                };
                n
            },
            Err(e) => {
                return Err(Error::Io(e));
            }
        };
        self.pos += bytes_read as u64;
        Ok(bytes_read as u64)
    }

    /// writes data to data_src
    /// returns bytes written
    fn write_bytes(&mut self, data: &[u8]) -> Result<u64, Error> {
            match self.data_src.write_all(data) {
            Ok(_) => {
                return Ok(data.len() as u64)
            },
            Err(e) => return Err(Error::Io(e))
        }
    }

    /// Inserts a new row with row_data.
    /// Returns the number of rows inserted.
    pub fn insert_row(&mut self, row_data: &[u8]) -> Result<u64, Error> {
        let mut pks: Vec<usize> = Vec::new();
        let mut count: usize = 0;
        // get pks
        info!("getting primary keys ....");
        {
            let mut it = self.columns.iter();
            loop {
                match it.next() {
                    Some(x) => {
                        if x.is_primary_key {
                            pks.push(count);
                        }
                        count += 1;
                    },
                    None => break,
                };
            }
        }
        // do lookups
        info!("doing lookups to search for matches ....");
        {
            let mut it = pks.iter();
            let first = match it.next() {
                Some(x) => x,
                None => return Err(Error::FoundNoPrimaryKey),
            };

            let val = try!(self.get_value(row_data, *first));
            let mut look = try!(self.lookup(*first, &val, CompType::Equ));

            loop {
                match it.next() {
                    Some(x) => {
                        let value = try!(self.get_value(row_data, *x));
                        look = try!(look.lookup(*x, &value, CompType::Equ));
                        if try!(look.is_empty()) {
                            break;
                        }
                    },
                    None => break,
                };
            }
            if !try!(look.is_empty()) {
                return Err(Error::PrimaryKeyValueExists);
            }
        }
        self.set_pos(SeekFrom::End(0));
        Ok(try!(self.add_row(row_data)))
    }

    /// deletes rows which fulfills a constraint
    /// return rows deleted
    pub fn delete(&mut self, column_index: usize, value: &[u8], comp: CompType)
     -> Result<u64, Error>
    {
        let mut count = 0;
        while true {
            match self.get_next_row(column_index, value, comp) {
                Ok(_) => {
                    count += 1;
                    self.delete_row();
                }
                Err(e) => {
                    match e {
                        Error::EndOfFile => {
                            info!("reached end of file");
                            break;
                        },
                        _ => return Err(e)
                    }
                }
            }
        }

        Ok(count)

    }
    /// looks for rows with the given primary key value and comparison
    /// returns an new Rows object which fulfills a constraint
    pub fn lookup(&mut self, column_index: usize, value: &[u8], comp: CompType)
        -> Result<Rows<Cursor<Vec<u8>>>, Error>
    {
        let vec: Vec<u8> = Vec::new();
        let cursor = Cursor::new(vec);
        let mut rows = Rows::new(cursor, &self.columns);
        info!("starting lookup for column {:?}", column_index);
        while true {
            let result = self.get_next_row(column_index, value, comp);
            match result {
                Ok(r) => {
                    println!{"Row: {:?}", r};
                    rows.add_row(&r);

                },
                Err(e) => {
                    match e {
                        Error::EndOfFile => {
                            info!("reached end of file");
                            break;
                        },
                        _ => return Err(e)
                    }
                }
            }
        }

        Ok(rows)
    }
    /// scans the entire file
    /// returns all rows which are not deleted
    pub fn full_scan(&mut self) -> Result<Rows<Cursor<Vec<u8>>>, Error> {
        let vec: Vec<u8> = Vec::new();
        let cursor = Cursor::new(vec);
        let mut rows = Rows::new(cursor, &self.columns);
        let mut buf: Vec<u8> = Vec::new();
        info!("starting full scan ....");
        while true {
            match self.next_row(&mut buf) {
                Ok(_) => {
                        rows.add_row(& buf);
                        info!(".");
                },
                Err(e) => {
                    match e {
                        Error::EndOfFile => break,
                        _ => return Err(e)
                    }
                },
            }
        }
        info!("finished full scan ....");
        Ok(rows)
    }
/*
    pub fn clean(&mut self) -> Result<u64, Error> {
        let mut buf: Vec<u8> = Vec::new();
        let mut copy_buf: Vec<u8> = Vec::new();
        loop {
            match self.next_row(&buf, false) {
                Ok(_) => ,
                Error::EndOfFile => break,
                Err(e) => return Err(e),
            }
            info!("Reading Header");
            try!(self.prev_row());
            let delete_pos = pos;
            let mut row_header: RowHeader = try!(self.read_header());
            info!("Header Read");
            if row_header.is_deleted() {
                let copy_row = try!(last_not_deleted_row());
                if copy_row != delete_pos {
                    try!(self.set_pos(SeekFrom::Start(copy_row)));
                    self.next_row(&copy_buf, false)
                    try!(self.set_pos(SeekFrom::Start(delete_pos)));
                    try!(self.add_row(copy_buf));
                    copy_buf.clear();

    /// returns true if data_src is empty
                }
            }
        }
    }
*/
    /// checks if object is containing rows
    /// returns bool on success else Error
    pub fn is_empty(&mut self) -> Result <bool, Error> {
        //data_src.is_empty()
        let old_pos = self.pos;

        let result: Result<bool, Error> = match self.set_pos(SeekFrom::End(0)) {
            Ok(n) => {
                if n == 0 {
                    Ok(true)
                } else {
                    Ok(false)
                }
            },
            Err(e) => {
                Err(e)
            },
        };

        self.pos = old_pos;

        result
    }

    /// moves the cursor from the current position the row after the first row
    /// which fulfills the constraint.
    /// Returns the first row which fulfilly the condition.
    pub fn get_next_row(&mut self, column_index: usize, value: &[u8], comp: CompType)
    -> Result<Vec<u8>, Error>
    {
        let mut row = Vec::<u8>::new();
        let mut b = true;

        while b {
            b = match self.next_row(&mut row) {
                Ok(_) => {
                    let col = self.get_column(column_index);

                    let row_value: &Vec<u8> = &try!(self.get_value(&row, column_index));
                    let cmp_result = try!(col.sql_type.cmp(row_value, value, comp));

                    if cmp_result {
                        false
                    } else {
                        row.clear();
                        true
                    }
                },
                Err(e) => {
                    return Err(e)
                }
            }
        }

        Ok(row)
    }

}

pub struct RowHeader {
     pub data: u8,
}

impl RowHeader{

    pub fn new(deleted: u8) -> RowHeader {
        let data = 0 as u8;
        let mut h = RowHeader {
            data: data,
        };
        h.set_deleted(deleted);
        h
    }

    /// returns true if the current row is marked as deleted
    pub fn is_deleted(&self) -> bool {
        info!("check for delete bit");
        (self.data & 1 as u8) == 1
    }

    /// marks row as deleted
    pub fn set_deleted(&mut self, value: u8) {
        info!("set delete bit");
        if value == 1 {
            self.data |= 1 as u8
        }
        else {
            self.data &= 0xFE as u8
        }
    }
    /// returns size of RowHeader
    pub fn size() -> u64 {
        1
    }

    pub fn to_raw_data(&self) -> Vec<u8> {
        let mut raw_data = Vec::<u8>::new();
        raw_data.push(self.data);
        raw_data
    }
}
<|endoftext|>


<commit_before>//! proc-macro tests

#[macro_use]
mod utils;
use utils::*;

use expect_test::expect;

#[test]
fn test_derive_empty() {
    assert_expand("DeriveEmpty", r#"struct S;"#, expect![[r#"SUBTREE $"#]]);
}

#[test]
fn test_derive_error() {
    assert_expand(
        "DeriveError",
        r#"struct S;"#,
        expect![[r##"
            SUBTREE $
              IDENT   compile_error 4294967295
              PUNCH   ! [joint] 4294967295
              SUBTREE () 4294967295
                LITERAL "#[derive(DeriveError)] struct S ;" 4294967295
              PUNCH   ; [alone] 4294967295"##]],
    );
}

#[test]
fn test_fn_like_macro_noop() {
    assert_expand(
        "fn_like_noop",
        r#"ident, 0, 1, []"#,
        expect![[r#"
            SUBTREE $
              IDENT   ident 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL 0 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL 1 4294967295
              PUNCH   , [alone] 4294967295
              SUBTREE [] 4294967295"#]],
    );
}

#[test]
fn test_fn_like_macro_clone_ident_subtree() {
    assert_expand(
        "fn_like_clone_tokens",
        r#"ident, []"#,
        expect![[r#"
            SUBTREE $
              IDENT   ident 4294967295
              PUNCH   , [alone] 4294967295
              SUBTREE [] 4294967295"#]],
    );
}

#[test]
fn test_fn_like_macro_clone_raw_ident() {
    assert_expand(
        "fn_like_clone_tokens",
        "r#async",
        expect![[r#"
            SUBTREE $
              IDENT   async 4294967295"#]],
    );
}

#[test]
fn test_fn_like_mk_literals() {
    assert_expand(
        "fn_like_mk_literals",
        r#""#,
        expect![[r#"
            SUBTREE $
              LITERAL b"byte_string" 4294967295
              LITERAL 'c' 4294967295
              LITERAL "string" 4294967295
              LITERAL 3.14f64 4294967295
              LITERAL 3.14 4294967295
              LITERAL 123i64 4294967295
              LITERAL 123 4294967295"#]],
    );
}

#[test]
fn test_fn_like_mk_idents() {
    // FIXME: this test is wrong: raw should be 'r#raw' but ABIs 1.64 and below
    // simply ignore `is_raw` when implementing the `Ident` interface.
    assert_expand(
        "fn_like_mk_idents",
        r#""#,
        expect![[r#"
            SUBTREE $
              IDENT   standard 4294967295
              IDENT   raw 4294967295"#]],
    );
}

#[test]
fn test_fn_like_macro_clone_literals() {
    assert_expand(
        "fn_like_clone_tokens",
        r#"1u16, 2_u32, -4i64, 3.14f32, "hello bridge""#,
        expect![[r#"
            SUBTREE $
              LITERAL 1u16 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL 2_u32 4294967295
              PUNCH   , [alone] 4294967295
              PUNCH   - [joint] 4294967295
              LITERAL 4i64 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL 3.14f32 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL "hello bridge" 4294967295"#]],
    );
}

#[test]
fn test_attr_macro() {
    // Corresponds to
    //    #[proc_macro_test::attr_error(some arguments)]
    //    mod m {}
    assert_expand_attr(
        "attr_error",
        r#"mod m {}"#,
        r#"some arguments"#,
        expect![[r##"
            SUBTREE $
              IDENT   compile_error 4294967295
              PUNCH   ! [joint] 4294967295
              SUBTREE () 4294967295
                LITERAL "#[attr_error(some arguments)] mod m {}" 4294967295
              PUNCH   ; [alone] 4294967295"##]],
    );
}

/// Tests that we find and classify all proc macros correctly.
#[test]
fn list_test_macros() {
    let res = list().join("\n");

    expect![[r#"
        fn_like_noop [FuncLike]
        fn_like_panic [FuncLike]
        fn_like_error [FuncLike]
        fn_like_clone_tokens [FuncLike]
        fn_like_mk_literals [FuncLike]
        fn_like_mk_idents [FuncLike]
        attr_noop [Attr]
        attr_panic [Attr]
        attr_error [Attr]
        DeriveEmpty [CustomDerive]
        DerivePanic [CustomDerive]
        DeriveError [CustomDerive]"#]]
    .assert_eq(&res);
}
<commit_msg>Update proc-macro-srv tests<commit_after>//! proc-macro tests

#[macro_use]
mod utils;
use utils::*;

use expect_test::expect;

#[test]
fn test_derive_empty() {
    assert_expand("DeriveEmpty", r#"struct S;"#, expect![[r#"SUBTREE $"#]]);
}

#[test]
fn test_derive_error() {
    assert_expand(
        "DeriveError",
        r#"struct S;"#,
        expect![[r##"
            SUBTREE $
              IDENT   compile_error 4294967295
              PUNCH   ! [alone] 4294967295
              SUBTREE () 4294967295
                LITERAL "#[derive(DeriveError)] struct S ;" 4294967295
              PUNCH   ; [alone] 4294967295"##]],
    );
}

#[test]
fn test_fn_like_macro_noop() {
    assert_expand(
        "fn_like_noop",
        r#"ident, 0, 1, []"#,
        expect![[r#"
            SUBTREE $
              IDENT   ident 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL 0 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL 1 4294967295
              PUNCH   , [alone] 4294967295
              SUBTREE [] 4294967295"#]],
    );
}

#[test]
fn test_fn_like_macro_clone_ident_subtree() {
    assert_expand(
        "fn_like_clone_tokens",
        r#"ident, []"#,
        expect![[r#"
            SUBTREE $
              IDENT   ident 4294967295
              PUNCH   , [alone] 4294967295
              SUBTREE [] 4294967295"#]],
    );
}

#[test]
fn test_fn_like_macro_clone_raw_ident() {
    assert_expand(
        "fn_like_clone_tokens",
        "r#async",
        expect![[r#"
            SUBTREE $
              IDENT   async 4294967295"#]],
    );
}

#[test]
fn test_fn_like_mk_literals() {
    assert_expand(
        "fn_like_mk_literals",
        r#""#,
        expect![[r#"
            SUBTREE $
              LITERAL b"byte_string" 4294967295
              LITERAL 'c' 4294967295
              LITERAL "string" 4294967295
              LITERAL 3.14f64 4294967295
              LITERAL 3.14 4294967295
              LITERAL 123i64 4294967295
              LITERAL 123 4294967295"#]],
    );
}

#[test]
fn test_fn_like_mk_idents() {
    // FIXME: this test is wrong: raw should be 'r#raw' but ABIs 1.64 and below
    // simply ignore `is_raw` when implementing the `Ident` interface.
    assert_expand(
        "fn_like_mk_idents",
        r#""#,
        expect![[r#"
            SUBTREE $
              IDENT   standard 4294967295
              IDENT   raw 4294967295"#]],
    );
}

#[test]
fn test_fn_like_macro_clone_literals() {
    assert_expand(
        "fn_like_clone_tokens",
        r#"1u16, 2_u32, -4i64, 3.14f32, "hello bridge""#,
        expect![[r#"
            SUBTREE $
              LITERAL 1u16 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL 2_u32 4294967295
              PUNCH   , [alone] 4294967295
              PUNCH   - [alone] 4294967295
              LITERAL 4i64 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL 3.14f32 4294967295
              PUNCH   , [alone] 4294967295
              LITERAL "hello bridge" 4294967295"#]],
    );
}

#[test]
fn test_attr_macro() {
    // Corresponds to
    //    #[proc_macro_test::attr_error(some arguments)]
    //    mod m {}
    assert_expand_attr(
        "attr_error",
        r#"mod m {}"#,
        r#"some arguments"#,
        expect![[r##"
            SUBTREE $
              IDENT   compile_error 4294967295
              PUNCH   ! [alone] 4294967295
              SUBTREE () 4294967295
                LITERAL "#[attr_error(some arguments)] mod m {}" 4294967295
              PUNCH   ; [alone] 4294967295"##]],
    );
}

/// Tests that we find and classify all proc macros correctly.
#[test]
fn list_test_macros() {
    let res = list().join("\n");

    expect![[r#"
        fn_like_noop [FuncLike]
        fn_like_panic [FuncLike]
        fn_like_error [FuncLike]
        fn_like_clone_tokens [FuncLike]
        fn_like_mk_literals [FuncLike]
        fn_like_mk_idents [FuncLike]
        attr_noop [Attr]
        attr_panic [Attr]
        attr_error [Attr]
        DeriveEmpty [CustomDerive]
        DerivePanic [CustomDerive]
        DeriveError [CustomDerive]"#]]
    .assert_eq(&res);
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

use config::functions::Function;
use config::parameter_matchable::ParameterMatchable;
use env::Env;
use library;
use nameutil;
use super::ref_mode::RefMode;

#[derive(Clone, Debug)]
pub struct Parameter {
    //from library::Parameter
    pub name: String,
    pub typ: library::TypeId,
    pub c_type: String,
    pub instance_parameter: bool,
    pub direction: library::ParameterDirection,
    pub transfer: library::Transfer,
    pub caller_allocates: bool,
    pub nullable: library::Nullable,
    pub allow_none: bool,
    pub is_error: bool,

    //analysis fields
    pub ref_mode: RefMode,
    //filled by functions
    //TODO: Find normal way to do it
    pub to_glib_extra: String,
}

pub fn analyze(env: &Env, par: &library::Parameter, configured_functions: &[&Function]) -> Parameter {
    let name = if par.instance_parameter {
        Cow::Borrowed(&*par.name)
    } else {
        nameutil::mangle_keywords(&*par.name)
    };

    let immutable = configured_functions.matched_parameters(&name)
        .iter().any(|p| p.constant);
    let ref_mode = RefMode::without_unneeded_mut(&env.library, par, immutable);

    let nullable_override = configured_functions.matched_parameters(&name).iter()
        .filter_map(|p| p.nullable)
        .next();
    let nullable = nullable_override.unwrap_or(par.nullable);

    Parameter {
        name: name.into_owned(),
        typ: par.typ,
        c_type: par.c_type.clone(),
        instance_parameter: par.instance_parameter,
        direction: par.direction,
        transfer: par.transfer,
        caller_allocates: par.caller_allocates,
        nullable: nullable,
        allow_none: par.allow_none,
        ref_mode: ref_mode,
        is_error: par.is_error,
        to_glib_extra: String::new(),
    }
}
<commit_msg>Fix generation out parameter with simply types<commit_after>use std::borrow::Cow;

use config::functions::Function;
use config::parameter_matchable::ParameterMatchable;
use env::Env;
use library;
use nameutil;
use super::conversion_type::ConversionType;
use super::ref_mode::RefMode;

#[derive(Clone, Debug)]
pub struct Parameter {
    //from library::Parameter
    pub name: String,
    pub typ: library::TypeId,
    pub c_type: String,
    pub instance_parameter: bool,
    pub direction: library::ParameterDirection,
    pub transfer: library::Transfer,
    pub caller_allocates: bool,
    pub nullable: library::Nullable,
    pub allow_none: bool,
    pub is_error: bool,

    //analysis fields
    pub ref_mode: RefMode,
    //filled by functions
    //TODO: Find normal way to do it
    pub to_glib_extra: String,
}

pub fn analyze(env: &Env, par: &library::Parameter, configured_functions: &[&Function]) -> Parameter {
    let name = if par.instance_parameter {
        Cow::Borrowed(&*par.name)
    } else {
        nameutil::mangle_keywords(&*par.name)
    };

    let immutable = configured_functions.matched_parameters(&name)
        .iter().any(|p| p.constant);
    let ref_mode = RefMode::without_unneeded_mut(&env.library, par, immutable);

    let nullable_override = configured_functions.matched_parameters(&name).iter()
        .filter_map(|p| p.nullable)
        .next();
    let nullable = nullable_override.unwrap_or(par.nullable);

    let mut caller_allocates  = par.caller_allocates;
    let mut transfer = par.transfer;
    let conversion = ConversionType::of(&env.library, par.typ);
    if conversion == ConversionType::Direct || conversion == ConversionType::Scalar {
        //For simply types no reason to have these flags
        caller_allocates = false;
        transfer = library::Transfer::None;
    }

    Parameter {
        name: name.into_owned(),
        typ: par.typ,
        c_type: par.c_type.clone(),
        instance_parameter: par.instance_parameter,
        direction: par.direction,
        transfer: transfer,
        caller_allocates: caller_allocates,
        nullable: nullable,
        allow_none: par.allow_none,
        ref_mode: ref_mode,
        is_error: par.is_error,
        to_glib_extra: String::new(),
    }
}
<|endoftext|>


<commit_before>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::UnscopedState;
use core::semantic::ast::*;
use core::position::*;

type ParseFn<'a, I, T> = fn (&LanguageEnv<'a, I>, State<I>)
                            -> ParseResult<T, I>;

type U = UnscopedState;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b LanguageEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

        /// Wrap a function into a MnParser with this environment
        fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                    -> MnParser<'a, 'b, I, T> {
            MnParser { env: self, parser: parser }
        }

        fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
            unimplemented!()
        }

        fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
            unimplemented!()
        }

        fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }
}
pub fn parse_module<N: ?Sized>(code: &str) -> Result<Vec<N>, ParseError<&str>>
where N: ASTNode + Sized {
    let alpha_ext = "+-*/<=>!?:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(|c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(|c| alpha_ext.contains(c)))
          , reserved: [ "and"               , "begin"
                      , "case"              , "cond"
                      , "data"              , "define"
                      , "defn"              , "delay"
                      , "do"                , "else"
                      , "if"                , "lambda"
                      , "let"               , "let*"
                      , "letrec"            , "or"
                      , "quasiquote"        , "quote"
                      , "set!"              , "unquote"
                      , "unquote-splicing"
                      ].iter().map(|x| (*x).into()).collect()
        }
      , op: Identifier {
            start: satisfy(|c| ops.contains(c))
          , rest:  satisfy(|c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|"].iter().map(|x| (*x).into())
                                                     .collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });

    env.white_space()
       .parse(code);

    unimplemented!()
}
<commit_msg>MnEnv happens<commit_after>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::UnscopedState;
use core::semantic::ast::*;
use core::position::*;

type ParseFn<'a, I, T> = fn (&LanguageEnv<'a, I>, State<I>)
                            -> ParseResult<T, I>;

type U = UnscopedState;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b LanguageEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

        /// Wrap a function into a MnParser with this environment
        fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                    -> MnParser<'a, 'b, I, T> {
            MnParser { env: self, parser: parser }
        }

        fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
            unimplemented!()
        }

        fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
            unimplemented!()
        }

        fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }

}
pub fn parse_module<N: ?Sized>(code: &str) -> Result<Vec<N>, ParseError<&str>>
where N: ASTNode + Sized {
    let alpha_ext = "+-*/<=>!?:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(|c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(|c| alpha_ext.contains(c)))
          , reserved: [ "and"               , "begin"
                      , "case"              , "cond"
                      , "data"              , "define"
                      , "defn"              , "delay"
                      , "do"                , "else"
                      , "if"                , "lambda"
                      , "let"               , "let*"
                      , "letrec"            , "or"
                      , "quasiquote"        , "quote"
                      , "set!"              , "unquote"
                      , "unquote-splicing"
                      ].iter().map(|x| (*x).into()).collect()
        }
      , op: Identifier {
            start: satisfy(|c| ops.contains(c))
          , rest:  satisfy(|c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|"].iter().map(|x| (*x).into())
                                                     .collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .parse(code);

    unimplemented!()
}
<|endoftext|>


<commit_before>// compile-flags: -O
#![crate_type="lib"]
#![feature(maybe_uninit)]

use std::mem::MaybeUninit;

// Boxing a `MaybeUninit` value should not copy junk from the stack
#[no_mangle]
pub fn box_uninitialized() -> Box<MaybeUninit<usize>> {
    // CHECK-LABEL: @box_uninitialized
    // CHECK-NOT: store
    Box::new(MaybeUninit::uninitialized())
}
<commit_msg>extend box-maybe-uninit test<commit_after>// compile-flags: -O
#![crate_type="lib"]
#![feature(maybe_uninit)]

use std::mem::MaybeUninit;

// Boxing a `MaybeUninit` value should not copy junk from the stack
#[no_mangle]
pub fn box_uninitialized() -> Box<MaybeUninit<usize>> {
    // CHECK-LABEL: @box_uninitialized
    // CHECK-NOT: store
    // CHECK-NOT: alloca
    // CHECK-NOT: memcpy
    // CHECK-NOT: memset
    Box::new(MaybeUninit::uninitialized())
}
<|endoftext|>