<commit_before>use std::io::{Read, Write};

use super::{CountedList, CountedListWriter, CountedWriter, Deserialize, Error, Serialize, VarInt32, VarUint32, VarUint7};

const FUNCTION_INDEX_LEB: u8 = 0;
const TABLE_INDEX_SLEB: u8 = 1;
const TABLE_INDEX_I32: u8 = 2;
const MEMORY_ADDR_LEB: u8 = 3;
const MEMORY_ADDR_SLEB: u8 = 4;
const MEMORY_ADDR_I32: u8 = 5;
const TYPE_INDEX_LEB: u8 = 6;
const GLOBAL_INDEX_LEB: u8 = 7;

/// Relocation information.
#[derive(Clone, Debug)]
pub struct RelocSection {
	/// Name of this section.
	name: String,

	/// ID of the section containing the relocations described in this section.
	section_id: u32,

	/// Name of the section containing the relocations described in this section. Only set if section_id is 0.
	relocation_section_name: Option<String>,

	/// Relocation entries.
	entries: Vec<RelocationEntry>,
}

impl RelocSection {
	/// Name of this section.
	pub fn name(&self) -> &str {
		&self.name
	}

	/// Name of this section (mutable).
	pub fn name_mut(&mut self) -> &mut String {
		&mut self.name
	}

	/// ID of the section containing the relocations described in this section.
	pub fn section_id(&self) -> u32 {
		self.section_id
	}

	/// ID of the section containing the relocations described in this section (mutable).
	pub fn section_id_mut(&mut self) -> &mut u32 {
		&mut self.section_id
	}

	/// Name of the section containing the relocations described in this section.
	pub fn relocation_section_name(&self) -> Option<&str> {
		self.relocation_section_name.as_ref().map(String::as_str)
	}

	/// Name of the section containing the relocations described in this section (mutable).
	pub fn relocation_section_name_mut(&mut self) -> &mut Option<String> {
		&mut self.relocation_section_name
	}

	/// List of relocation entries.
	pub fn entries(&self) -> &[RelocationEntry] {
		&self.entries
	}

	/// List of relocation entries (mutable).
	pub fn entries_mut(&mut self) -> &mut Vec<RelocationEntry> {
		&mut self.entries
	}
}

impl RelocSection {
	pub fn deserialize<R: Read>(
		name: String,
		rdr: &mut R,
	) -> Result<Self, Error> {
		let section_id = VarUint32::deserialize(rdr)?.into();

		let relocation_section_name =
			if section_id == 0 {
				Some(String::deserialize(rdr)?)
			}
			else {
				None
			};

		let entries = CountedList::deserialize(rdr)?.into_inner();

		Ok(RelocSection {
			name,
			section_id,
			relocation_section_name,
			entries,
		})
	}
}

impl Serialize for RelocSection {
	type Error = Error;

	fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
		let mut counted_writer = CountedWriter::new(wtr);

		self.name.serialize(&mut counted_writer)?;

		VarUint32::from(self.section_id).serialize(&mut counted_writer)?;

		if let Some(relocation_section_name) = self.relocation_section_name {
			relocation_section_name.serialize(&mut counted_writer)?;
		}

		let counted_list = CountedListWriter(self.entries.len(), self.entries.into_iter());
		counted_list.serialize(&mut counted_writer)?;

		counted_writer.done()?;

		Ok(())
	}
}

/// Relocation entry.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum RelocationEntry {
	/// Function index.
	FunctionIndexLeb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the function symbol in the symbol table.
		index: u32,
	},

	/// Function table index.
	TableIndexSleb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the function symbol in the symbol table.
		index: u32,
	},

	/// Function table index.
	TableIndexI32 {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the function symbol in the symbol table.
		index: u32,
	},

	/// Linear memory index.
	MemoryAddressLeb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the data symbol in the symbol table.
		index: u32,

		/// Addend to add to the address.
		addend: i32,
	},

	/// Linear memory index.
	MemoryAddressSleb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the data symbol in the symbol table.
		index: u32,

		/// Addend to add to the address.
		addend: i32,
	},

	/// Linear memory index.
	MemoryAddressI32 {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the data symbol in the symbol table.
		index: u32,

		/// Addend to add to the address.
		addend: i32,
	},

	/// Type table index.
	TypeIndexLeb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the type used.
		index: u32,
	},

	/// Global index.
	GlobalIndexLeb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the global symbol in the symbol table.
		index: u32,
	},
}

impl Deserialize for RelocationEntry {
	type Error = Error;

	fn deserialize<R: Read>(rdr: &mut R) -> Result<Self, Self::Error> {
		match VarUint7::deserialize(rdr)?.into() {
			FUNCTION_INDEX_LEB => Ok(RelocationEntry::FunctionIndexLeb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			TABLE_INDEX_SLEB => Ok(RelocationEntry::TableIndexSleb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			TABLE_INDEX_I32 => Ok(RelocationEntry::TableIndexI32 {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			MEMORY_ADDR_LEB => Ok(RelocationEntry::MemoryAddressLeb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
				addend: VarInt32::deserialize(rdr)?.into(),
			}),

			MEMORY_ADDR_SLEB => Ok(RelocationEntry::MemoryAddressSleb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
				addend: VarInt32::deserialize(rdr)?.into(),
			}),

			MEMORY_ADDR_I32 => Ok(RelocationEntry::MemoryAddressI32 {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
				addend: VarInt32::deserialize(rdr)?.into(),
			}),

			TYPE_INDEX_LEB => Ok(RelocationEntry::TypeIndexLeb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			GLOBAL_INDEX_LEB => Ok(RelocationEntry::GlobalIndexLeb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			entry_type => Err(Error::UnknownValueType(entry_type as i8)),
		}
	}
}

impl Serialize for RelocationEntry {
	type Error = Error;

	fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
		match self {
			RelocationEntry::FunctionIndexLeb { offset, index } => {
				VarUint7::from(FUNCTION_INDEX_LEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},

			RelocationEntry::TableIndexSleb { offset, index } => {
				VarUint7::from(TABLE_INDEX_SLEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},

			RelocationEntry::TableIndexI32 { offset, index } => {
				VarUint7::from(TABLE_INDEX_I32).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},

			RelocationEntry::MemoryAddressLeb { offset, index, addend } => {
				VarUint7::from(MEMORY_ADDR_LEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
				VarInt32::from(addend).serialize(wtr)?;
			},

			RelocationEntry::MemoryAddressSleb { offset, index, addend } => {
				VarUint7::from(MEMORY_ADDR_SLEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
				VarInt32::from(addend).serialize(wtr)?;
			},

			RelocationEntry::MemoryAddressI32 { offset, index, addend } => {
				VarUint7::from(MEMORY_ADDR_I32).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
				VarInt32::from(addend).serialize(wtr)?;
			},

			RelocationEntry::TypeIndexLeb { offset, index } => {
				VarUint7::from(TYPE_INDEX_LEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},

			RelocationEntry::GlobalIndexLeb { offset, index } => {
				VarUint7::from(GLOBAL_INDEX_LEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},
		}

		Ok(())
	}
}

#[cfg(test)]
mod tests {
	use super::super::{Section, deserialize_file};
	use super::RelocationEntry;

	#[test]
	fn reloc_section() {
		let module =
			deserialize_file("./res/cases/v1/relocatable.wasm").expect("Module should be deserialized")
			.parse_reloc().expect("Reloc section should be deserialized");
		let mut found = false;
		for section in module.sections() {
			match *section {
				Section::Reloc(ref reloc_section) => {
					assert_eq!(vec![
						RelocationEntry::MemoryAddressSleb { offset: 4, index: 0, addend: 0 },
						RelocationEntry::FunctionIndexLeb { offset: 12, index: 0 },
					], reloc_section.entries());
					found = true
				},
				_ => { }
			}
		}
		assert!(found, "There should be a reloc section in relocatable.wasm");
	}
}
<commit_msg>One last missing doc comment warning.<commit_after>use std::io::{Read, Write};

use super::{CountedList, CountedListWriter, CountedWriter, Deserialize, Error, Serialize, VarInt32, VarUint32, VarUint7};

const FUNCTION_INDEX_LEB: u8 = 0;
const TABLE_INDEX_SLEB: u8 = 1;
const TABLE_INDEX_I32: u8 = 2;
const MEMORY_ADDR_LEB: u8 = 3;
const MEMORY_ADDR_SLEB: u8 = 4;
const MEMORY_ADDR_I32: u8 = 5;
const TYPE_INDEX_LEB: u8 = 6;
const GLOBAL_INDEX_LEB: u8 = 7;

/// Relocation information.
#[derive(Clone, Debug)]
pub struct RelocSection {
	/// Name of this section.
	name: String,

	/// ID of the section containing the relocations described in this section.
	section_id: u32,

	/// Name of the section containing the relocations described in this section. Only set if section_id is 0.
	relocation_section_name: Option<String>,

	/// Relocation entries.
	entries: Vec<RelocationEntry>,
}

impl RelocSection {
	/// Name of this section.
	pub fn name(&self) -> &str {
		&self.name
	}

	/// Name of this section (mutable).
	pub fn name_mut(&mut self) -> &mut String {
		&mut self.name
	}

	/// ID of the section containing the relocations described in this section.
	pub fn section_id(&self) -> u32 {
		self.section_id
	}

	/// ID of the section containing the relocations described in this section (mutable).
	pub fn section_id_mut(&mut self) -> &mut u32 {
		&mut self.section_id
	}

	/// Name of the section containing the relocations described in this section.
	pub fn relocation_section_name(&self) -> Option<&str> {
		self.relocation_section_name.as_ref().map(String::as_str)
	}

	/// Name of the section containing the relocations described in this section (mutable).
	pub fn relocation_section_name_mut(&mut self) -> &mut Option<String> {
		&mut self.relocation_section_name
	}

	/// List of relocation entries.
	pub fn entries(&self) -> &[RelocationEntry] {
		&self.entries
	}

	/// List of relocation entries (mutable).
	pub fn entries_mut(&mut self) -> &mut Vec<RelocationEntry> {
		&mut self.entries
	}
}

impl RelocSection {
	/// Deserialize a reloc section.
	pub fn deserialize<R: Read>(
		name: String,
		rdr: &mut R,
	) -> Result<Self, Error> {
		let section_id = VarUint32::deserialize(rdr)?.into();

		let relocation_section_name =
			if section_id == 0 {
				Some(String::deserialize(rdr)?)
			}
			else {
				None
			};

		let entries = CountedList::deserialize(rdr)?.into_inner();

		Ok(RelocSection {
			name,
			section_id,
			relocation_section_name,
			entries,
		})
	}
}

impl Serialize for RelocSection {
	type Error = Error;

	fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
		let mut counted_writer = CountedWriter::new(wtr);

		self.name.serialize(&mut counted_writer)?;

		VarUint32::from(self.section_id).serialize(&mut counted_writer)?;

		if let Some(relocation_section_name) = self.relocation_section_name {
			relocation_section_name.serialize(&mut counted_writer)?;
		}

		let counted_list = CountedListWriter(self.entries.len(), self.entries.into_iter());
		counted_list.serialize(&mut counted_writer)?;

		counted_writer.done()?;

		Ok(())
	}
}

/// Relocation entry.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum RelocationEntry {
	/// Function index.
	FunctionIndexLeb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the function symbol in the symbol table.
		index: u32,
	},

	/// Function table index.
	TableIndexSleb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the function symbol in the symbol table.
		index: u32,
	},

	/// Function table index.
	TableIndexI32 {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the function symbol in the symbol table.
		index: u32,
	},

	/// Linear memory index.
	MemoryAddressLeb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the data symbol in the symbol table.
		index: u32,

		/// Addend to add to the address.
		addend: i32,
	},

	/// Linear memory index.
	MemoryAddressSleb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the data symbol in the symbol table.
		index: u32,

		/// Addend to add to the address.
		addend: i32,
	},

	/// Linear memory index.
	MemoryAddressI32 {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the data symbol in the symbol table.
		index: u32,

		/// Addend to add to the address.
		addend: i32,
	},

	/// Type table index.
	TypeIndexLeb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the type used.
		index: u32,
	},

	/// Global index.
	GlobalIndexLeb {
		/// Offset of the value to rewrite.
		offset: u32,

		/// Index of the global symbol in the symbol table.
		index: u32,
	},
}

impl Deserialize for RelocationEntry {
	type Error = Error;

	fn deserialize<R: Read>(rdr: &mut R) -> Result<Self, Self::Error> {
		match VarUint7::deserialize(rdr)?.into() {
			FUNCTION_INDEX_LEB => Ok(RelocationEntry::FunctionIndexLeb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			TABLE_INDEX_SLEB => Ok(RelocationEntry::TableIndexSleb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			TABLE_INDEX_I32 => Ok(RelocationEntry::TableIndexI32 {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			MEMORY_ADDR_LEB => Ok(RelocationEntry::MemoryAddressLeb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
				addend: VarInt32::deserialize(rdr)?.into(),
			}),

			MEMORY_ADDR_SLEB => Ok(RelocationEntry::MemoryAddressSleb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
				addend: VarInt32::deserialize(rdr)?.into(),
			}),

			MEMORY_ADDR_I32 => Ok(RelocationEntry::MemoryAddressI32 {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
				addend: VarInt32::deserialize(rdr)?.into(),
			}),

			TYPE_INDEX_LEB => Ok(RelocationEntry::TypeIndexLeb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			GLOBAL_INDEX_LEB => Ok(RelocationEntry::GlobalIndexLeb {
				offset: VarUint32::deserialize(rdr)?.into(),
				index: VarUint32::deserialize(rdr)?.into(),
			}),

			entry_type => Err(Error::UnknownValueType(entry_type as i8)),
		}
	}
}

impl Serialize for RelocationEntry {
	type Error = Error;

	fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
		match self {
			RelocationEntry::FunctionIndexLeb { offset, index } => {
				VarUint7::from(FUNCTION_INDEX_LEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},

			RelocationEntry::TableIndexSleb { offset, index } => {
				VarUint7::from(TABLE_INDEX_SLEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},

			RelocationEntry::TableIndexI32 { offset, index } => {
				VarUint7::from(TABLE_INDEX_I32).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},

			RelocationEntry::MemoryAddressLeb { offset, index, addend } => {
				VarUint7::from(MEMORY_ADDR_LEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
				VarInt32::from(addend).serialize(wtr)?;
			},

			RelocationEntry::MemoryAddressSleb { offset, index, addend } => {
				VarUint7::from(MEMORY_ADDR_SLEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
				VarInt32::from(addend).serialize(wtr)?;
			},

			RelocationEntry::MemoryAddressI32 { offset, index, addend } => {
				VarUint7::from(MEMORY_ADDR_I32).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
				VarInt32::from(addend).serialize(wtr)?;
			},

			RelocationEntry::TypeIndexLeb { offset, index } => {
				VarUint7::from(TYPE_INDEX_LEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},

			RelocationEntry::GlobalIndexLeb { offset, index } => {
				VarUint7::from(GLOBAL_INDEX_LEB).serialize(wtr)?;
				VarUint32::from(offset).serialize(wtr)?;
				VarUint32::from(index).serialize(wtr)?;
			},
		}

		Ok(())
	}
}

#[cfg(test)]
mod tests {
	use super::super::{Section, deserialize_file};
	use super::RelocationEntry;

	#[test]
	fn reloc_section() {
		let module =
			deserialize_file("./res/cases/v1/relocatable.wasm").expect("Module should be deserialized")
			.parse_reloc().expect("Reloc section should be deserialized");
		let mut found = false;
		for section in module.sections() {
			match *section {
				Section::Reloc(ref reloc_section) => {
					assert_eq!(vec![
						RelocationEntry::MemoryAddressSleb { offset: 4, index: 0, addend: 0 },
						RelocationEntry::FunctionIndexLeb { offset: 12, index: 0 },
					], reloc_section.entries());
					found = true
				},
				_ => { }
			}
		}
		assert!(found, "There should be a reloc section in relocatable.wasm");
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
    let id: &Mat2<float> = &Matrix::identity();
}

pub trait Index<Index,Result> { }
pub trait Dimensional<T>: Index<uint, T> { }

pub struct Mat2<T> { x: () }
pub struct Vec2<T> { x: () }

impl<T> Dimensional<Vec2<T>> for Mat2<T> { }
impl<T> Index<uint, Vec2<T>> for Mat2<T> { }

impl<T> Dimensional<T> for Vec2<T> { }
impl<T> Index<uint, T> for Vec2<T> { }

pub trait Matrix<T,V>: Dimensional<V> {
    fn identity() -> Self;
}

impl<T> Matrix<T, Vec2<T>> for Mat2<T> {
    fn identity() -> Mat2<T> { Mat2{ x: () } }
}
<commit_msg>testsuite: Make main fn public<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub fn main() {
    let id: &Mat2<float> = &Matrix::identity();
}

pub trait Index<Index,Result> { }
pub trait Dimensional<T>: Index<uint, T> { }

pub struct Mat2<T> { x: () }
pub struct Vec2<T> { x: () }

impl<T> Dimensional<Vec2<T>> for Mat2<T> { }
impl<T> Index<uint, Vec2<T>> for Mat2<T> { }

impl<T> Dimensional<T> for Vec2<T> { }
impl<T> Index<uint, T> for Vec2<T> { }

pub trait Matrix<T,V>: Dimensional<V> {
    fn identity() -> Self;
}

impl<T> Matrix<T, Vec2<T>> for Mat2<T> {
    fn identity() -> Mat2<T> { Mat2{ x: () } }
}
<|endoftext|>


<commit_before>//! An asynchronous RabbitMQ client for proxy engine
//!

use std::io;

use amq_protocol::uri::{AMQPUri};
use futures::{IntoFuture};
use futures::future::{Future};
use lapin_futures_rustls::{AMQPConnectionRustlsExt};
use lapin_futures_rustls::lapin::channel::{Channel, ConfirmSelectOptions};
use lapin_futures_rustls::lapin::client::{Client, ConnectionOptions};
use tokio::executor::{spawn};
use tokio_tcp::{TcpStream};

use super::super::cli::{CliOptions};
use super::super::error::{PathfinderError};

/// Alias for the lapin client with TLS.
pub type LapinClient = Client<TcpStream>;
/// Alias for the lapin channel.
pub type LapinChannel = Channel<TcpStream>;
/// Alias for generic future for pathfinder and RabbitMQ.
pub type RabbitMQFuture = Box<Future<Item=(), Error=PathfinderError> + 'static>;

/// A future-based asynchronous RabbitMQ client.
pub struct RabbitMQClient
{
    uri: AMQPUri,
    client: Option<Box<Future<Item=Client<TcpStream>, Error=io::Error> + Sync + Send + 'static>>,
}

impl RabbitMQClient {
    /// Returns a new instance of `RabbitMQClient`.
    pub fn new(cli: &CliOptions) -> RabbitMQClient {
        let schema = match cli.rabbitmq_secured {
            true => "amqps",
            false => "amqp",
        };

        let uri = format!(
            "{}://{}:{}@{}:{}/{}",
            schema.to_string(),
            cli.rabbitmq_username.clone(),
            cli.rabbitmq_password.clone(),
            cli.rabbitmq_host.clone(),
            cli.rabbitmq_port,
            cli.rabbitmq_virtual_host.clone()
        );

        RabbitMQClient {
            uri: uri.parse().unwrap(),
            client: None
        }
    }

    pub fn init(&mut self) {
        self.client = self.get_client();
    }

    pub fn get_channel(&self) -> Box<Future<Item=LapinChannel, Error=io::Error> + Sync + Send + 'static> {
        Box::new(
            self.client.unwrap().and_then(|client| {
                client.create_confirm_channel(ConfirmSelectOptions::default())
            })
        )
    }

    fn get_client(&mut self) -> Option<Box<Future<Item=LapinClient, Error=io::Error> + Sync + Send + 'static>> {
        match self.client {
            Some(client) => Some(client),
            None => {
                self.client = Some(Box::new(self.create_client()));
                self.client
            }
        }
    }

    fn create_client(&self) -> impl Future<Item=LapinClient, Error=io::Error> + Sync + Send + 'static {
        let address = self.get_address_to_rabbitmq().parse().unwrap();
        let uri = self.uri.clone();

        TcpStream::connect(&address).and_then(|stream| {
            Client::connect(stream, ConnectionOptions::from_uri(uri))
        })
        .and_then(|(client, heartbeat)| {
            spawn(heartbeat.map_err(|err| eprintln!("Heartbeat error: {:?}", err)))
                .into_future()
                .map(|_| client)
                .map_err(|_| io::Error::new(io::ErrorKind::Other, "Spawn error."))
        })
    }

    /// Generates a connection URL to RabbitMQ broker.
    fn get_address_to_rabbitmq(&self) -> String {
        format!("{}:{}", self.uri.authority.host, self.uri.authority.port)
    }
}
<commit_msg>Added Send and Sync markers for RabbitMQ future<commit_after>//! An asynchronous RabbitMQ client for proxy engine
//!

use std::io;

use amq_protocol::uri::{AMQPUri};
use futures::{IntoFuture};
use futures::future::{Future};
use lapin_futures_rustls::{AMQPConnectionRustlsExt};
use lapin_futures_rustls::lapin::channel::{Channel, ConfirmSelectOptions};
use lapin_futures_rustls::lapin::client::{Client, ConnectionOptions};
use tokio::executor::{spawn};
use tokio_tcp::{TcpStream};

use super::super::cli::{CliOptions};
use super::super::error::{PathfinderError};

/// Alias for the lapin client with TLS.
pub type LapinClient = Client<TcpStream>;
/// Alias for the lapin channel.
pub type LapinChannel = Channel<TcpStream>;
/// Alias for generic future for pathfinder and RabbitMQ.
pub type RabbitMQFuture = Box<Future<Item=(), Error=PathfinderError> + Send + Sync + 'static>;

/// A future-based asynchronous RabbitMQ client.
pub struct RabbitMQClient
{
    uri: AMQPUri,
    client: Option<Box<Future<Item=Client<TcpStream>, Error=io::Error> + Sync + Send + 'static>>,
}

impl RabbitMQClient {
    /// Returns a new instance of `RabbitMQClient`.
    pub fn new(cli: &CliOptions) -> RabbitMQClient {
        let schema = match cli.rabbitmq_secured {
            true => "amqps",
            false => "amqp",
        };

        let uri = format!(
            "{}://{}:{}@{}:{}/{}",
            schema.to_string(),
            cli.rabbitmq_username.clone(),
            cli.rabbitmq_password.clone(),
            cli.rabbitmq_host.clone(),
            cli.rabbitmq_port,
            cli.rabbitmq_virtual_host.clone()
        );

        RabbitMQClient {
            uri: uri.parse().unwrap(),
            client: None
        }
    }

    pub fn init(&mut self) {
        self.client = self.get_client();
    }

    pub fn get_channel(&self) -> Box<Future<Item=LapinChannel, Error=io::Error> + Sync + Send + 'static> {
        Box::new(
            self.client.unwrap().and_then(|client| {
                client.create_confirm_channel(ConfirmSelectOptions::default())
            })
        )
    }

    fn get_client(&mut self) -> Option<Box<Future<Item=LapinClient, Error=io::Error> + Sync + Send + 'static>> {
        match self.client {
            Some(client) => Some(client),
            None => {
                self.client = Some(Box::new(self.create_client()));
                self.client
            }
        }
    }

    fn create_client(&self) -> impl Future<Item=LapinClient, Error=io::Error> + Sync + Send + 'static {
        let address = self.get_address_to_rabbitmq().parse().unwrap();
        let uri = self.uri.clone();

        TcpStream::connect(&address).and_then(|stream| {
            Client::connect(stream, ConnectionOptions::from_uri(uri))
        })
        .and_then(|(client, heartbeat)| {
            spawn(heartbeat.map_err(|err| eprintln!("Heartbeat error: {:?}", err)))
                .into_future()
                .map(|_| client)
                .map_err(|_| io::Error::new(io::ErrorKind::Other, "Spawn error."))
        })
    }

    /// Generates a connection URL to RabbitMQ broker.
    fn get_address_to_rabbitmq(&self) -> String {
        format!("{}:{}", self.uri.authority.host, self.uri.authority.port)
    }
}
<|endoftext|>


<commit_before>extern crate structopt;

use crate::exceptions::IOError;
use std::path::PathBuf;
use std::process::{Command, ExitStatus};
use std::fs;
use structopt::StructOpt;

#[derive(Clone, Debug, StructOpt)]
#[structopt(name = "performance", about = "performance regression testing runner")]
enum Performance {
    #[structopt(name = "measure")]
    Measure {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        projects_dir: PathBuf,
        #[structopt(short)]
        branch_name: bool,
    },
    #[structopt(name = "compare")]
    Compare {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        results_dir: PathBuf,
    },
}

#[derive(Debug, Clone)]
struct Metric<'a> {
    name: &'a str,
    prepare: &'a str,
    cmd: &'a str,
}

impl Metric<'_> {
    fn outfile(&self, project: &str, branch: &str) -> String {
        [branch, "_", self.name, "_", project, ".json"].join("")
    }
}

// calls hyperfine via system command, and returns result of runs
pub fn measure(projects_directory: &PathBuf, dbt_branch: &str) -> Result<Vec<ExitStatus>, IOError> {
    // to add a new metric to the test suite, simply define it in this list:
    // TODO read from some config file?
    let metrics: Vec<Metric> = vec![
        Metric {
            name: "parse",
            prepare: "rm -rf target/",
            cmd: "dbt parse --no-version-check",
        },
    ];

    // run hyperfine on each target project in the directory
    fs::read_dir(projects_directory)
        .or_else(|e| Err(IOError::ReadErr(projects_directory.to_path_buf(), Some(e))))?
        .map(|entry| {
            metrics
                .clone()
                .into_iter()
                // for each entry-metric pair
                .map(|metric| {
                    let ent = entry
                        .as_ref()
                        .or_else(|e| Err(IOError::ReadErr(projects_directory.to_path_buf(), None)))?; // TODO change to Some(e)

                    let path: PathBuf = ent.path();
                    let project_name: &str = path
                        .file_name()
                        .ok_or_else(|| IOError::MissingFilenameErr(path.clone().to_path_buf()))
                        .and_then(|x| x.to_str().ok_or_else(|| IOError::FilenameNotUnicodeErr(path.clone().to_path_buf())))?;

                    Command::new("hyperfine")
                        .current_dir(&path)
                        // warms filesystem caches by running the command first without counting it.
                        // alternatively we could clear them before each run
                        .arg("--warmup")
                        .arg("1")
                        .arg("--prepare")
                        .arg(metric.prepare)
                        .arg([metric.cmd, " --profiles-dir ", "../../project_config/"].join(""))
                        .arg("--export-json")
                        .arg(
                            ["../../results/", &metric.outfile(&project_name, &dbt_branch)].join(""),
                        )
                        // this prevents capture dbt output. Noisy, but good for debugging when tests fail.
                        .arg("--show-output")
                        .status() // use spawn() here instead for more information
                        .or_else(|e| Err(IOError::CommandErr(Some(e))))
                })
                .collect::<Vec<Result<ExitStatus, IOError>>>()
        })
        .flatten()
        .collect()
}
<commit_msg>refactor for simpler flow<commit_after>extern crate structopt;

use crate::exceptions::IOError;
use std::path::PathBuf;
use std::process::{Command, ExitStatus};
use std::fs;
use structopt::StructOpt;

#[derive(Clone, Debug, StructOpt)]
#[structopt(name = "performance", about = "performance regression testing runner")]
enum Performance {
    #[structopt(name = "measure")]
    Measure {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        projects_dir: PathBuf,
        #[structopt(short)]
        branch_name: bool,
    },
    #[structopt(name = "compare")]
    Compare {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        results_dir: PathBuf,
    },
}

#[derive(Debug, Clone)]
struct Metric<'a> {
    name: &'a str,
    prepare: &'a str,
    cmd: &'a str,
}

impl Metric<'_> {
    fn outfile(&self, project: &str, branch: &str) -> String {
        [branch, "_", self.name, "_", project, ".json"].join("")
    }
}

// calls hyperfine via system command, and returns result of runs
pub fn measure(projects_directory: &PathBuf, dbt_branch: &str) -> Result<Vec<ExitStatus>, IOError> {
    // to add a new metric to the test suite, simply define it in this list:
    // TODO read from some config file?
    let metrics: Vec<Metric> = vec![
        Metric {
            name: "parse",
            prepare: "rm -rf target/",
            cmd: "dbt parse --no-version-check",
        },
    ];

    fs::read_dir(projects_directory)
        .or_else(|e| Err(IOError::ReadErr(projects_directory.to_path_buf(), Some(e))))?
        .map(|entry| {
            let path = entry
                .or_else(|e| Err(IOError::ReadErr(projects_directory.to_path_buf(), Some(e))))?
                .path();

            let project_name: String = path
                .file_name()
                .ok_or_else(|| IOError::MissingFilenameErr(path.clone().to_path_buf()))
                .and_then(|x| x.to_str().ok_or_else(|| IOError::FilenameNotUnicodeErr(path.clone().to_path_buf())))?
                .to_owned();

            // each project-metric pair we will run
            let pairs = metrics
                .clone()
                .into_iter()
                .map(|metric| (path.clone(), project_name.clone(), metric))
                .collect::<Vec<(PathBuf, String, Metric)>>();

            Ok(pairs)
        })
        .collect::<Result<Vec<Vec<(PathBuf, String, Metric)>>, IOError>>()?
        .concat()
        .into_iter()
        // run hyperfine on each pairing
        .map(|(path, project_name, metric)| {
            Command::new("hyperfine")
                .current_dir(&path)
                // warms filesystem caches by running the command first without counting it.
                // alternatively we could clear them before each run
                .arg("--warmup")
                .arg("1")
                .arg("--prepare")
                .arg(metric.prepare)
                .arg([metric.cmd, " --profiles-dir ", "../../project_config/"].join(""))
                .arg("--export-json")
                .arg(
                    ["../../results/", &metric.outfile(&project_name, &dbt_branch)].join(""),
                )
                // this prevents capture dbt output. Noisy, but good for debugging when tests fail.
                .arg("--show-output")
                .status() // use spawn() here instead for more information
                .or_else(|e| Err(IOError::CommandErr(Some(e))))
        }
    )
    .collect()
}
<|endoftext|>


<commit_before>use byteorder::*;
use std::env;
use std::fs::*;
use std::io::{self, Read, Write, BufReader, BufWriter};
use std::path::*;
use ordermap::OrderMap;

use crusader::*;
use formation::Formation;
use super::Node;

pub struct Cache {
    directory: PathBuf,
}

impl Cache {
    pub fn new(key: u64) -> Self {
        let digest = format!("{:x}", key);
        Cache {
            directory: env::temp_dir().join("cotli_helper").join(&digest),
        }
    }

    pub(super) fn write_to_cache(&self, formation: &Formation, node: &Node) {
        let path = self.path_to_cache_file(formation);
        self.try_write_to_cache(&path, node).unwrap();
    }

    pub(super) fn load_from_cache<'a>(
        &self,
        formation: &Formation<'a>,
        crusaders: &'a [Crusader],
    ) -> Option<Node<'a>> {
        let file_path = self.path_to_cache_file(formation);
        if !file_path.join("search_data.toml").exists() {
            return None;
        }
        match self.try_load_from_cache(&file_path, crusaders) {
            Ok(x) => Some(x),
            Err(e) => {
                println!("Could not load from cache. Deleting directory. Error: {}", e);
                remove_dir_all(file_path).unwrap();
                None
            }
        }
    }

    fn path_to_cache_file(&self, formation: &Formation) -> PathBuf {
        formation.placements().fold(self.directory.clone(), |path, (idx, crusader)| {
            let as_dir = format!("{}{:?}", idx, crusader.name);
            path.join(&as_dir)
        })
    }

    fn try_write_to_cache(&self, path: &Path, node: &Node) -> io::Result<()> {
        create_dir_all(path)?;
        let mut file = BufWriter::new(File::create(path.join("search_data.toml"))?);
        file.write_u8(1)?;
        write_node(node, &mut file)?;
        Ok(())
    }

    fn try_load_from_cache<'a>(
        &self,
        path: &Path,
        crusaders: &'a [Crusader],
    ) -> io::Result<Node<'a>> {
        let mut file = BufReader::new(File::open(path.join("search_data.toml"))?);
        let v = file.read_u8()?;
        if v == 1 {
            read_node(crusaders, &mut file)
        } else {
            Err(io::Error::new(io::ErrorKind::Other, "Invalid cache version"))
        }
    }
}

fn write_node<W: Write>(node: &Node, out: &mut W) -> io::Result<()> {
    out.write_f64::<NativeEndian>(node.highest_score_seen.into())?;
    out.write_f64::<NativeEndian>(node.total_score_seen.into())?;
    out.write_u32::<NativeEndian>(node.times_checked)?;
    out.write_u64::<NativeEndian>(node.children.len() as u64)?;
    for (&(idx, crusader), child) in &node.children {
        out.write_u8(idx as u8)?;
        out.write_u8(crusader.name as u8)?;
        write_node(child, out)?;
    }
    Ok(())
}

fn read_node<'a, R: Read>(crusaders: &'a [Crusader], read: &mut R) -> io::Result<Node<'a>> {
    use std::mem::transmute;
    let highest_score_seen = read.read_f64::<NativeEndian>()?.into();
    let total_score_seen = read.read_f64::<NativeEndian>()?.into();
    let times_checked = read.read_u32::<NativeEndian>()?;
    let num_children = read.read_u64::<NativeEndian>()? as usize;
    let mut children = OrderMap::with_capacity(num_children);
    for _ in 0..num_children {
        let idx = read.read_u8()? as usize;
        let name = unsafe { transmute(read.read_u8()?) };
        let crusader = crusaders.iter().find(|c| c.name == name).unwrap();
        let node = read_node(crusaders, read)?;
        children.insert((idx, crusader), node);
    }
    Ok(Node {
        progress: Default::default(),
        highest_score_seen,
        total_score_seen,
        times_checked,
        children,
    })
}
<commit_msg>The cache does not use TOML<commit_after>use byteorder::*;
use std::env;
use std::fs::*;
use std::io::{self, Read, Write, BufReader, BufWriter};
use std::path::*;
use ordermap::OrderMap;

use crusader::*;
use formation::Formation;
use super::Node;

pub struct Cache {
    directory: PathBuf,
}

impl Cache {
    pub fn new(key: u64) -> Self {
        let digest = format!("{:x}", key);
        Cache {
            directory: env::temp_dir().join("cotli_helper").join(&digest),
        }
    }

    pub(super) fn write_to_cache(&self, formation: &Formation, node: &Node) {
        let path = self.path_to_cache_file(formation);
        self.try_write_to_cache(&path, node).unwrap();
    }

    pub(super) fn load_from_cache<'a>(
        &self,
        formation: &Formation<'a>,
        crusaders: &'a [Crusader],
    ) -> Option<Node<'a>> {
        let file_path = self.path_to_cache_file(formation);
        if !file_path.join("search_data.dat").exists() {
            return None;
        }
        match self.try_load_from_cache(&file_path, crusaders) {
            Ok(x) => Some(x),
            Err(e) => {
                println!("Could not load from cache. Deleting directory. Error: {}", e);
                remove_dir_all(file_path).unwrap();
                None
            }
        }
    }

    fn path_to_cache_file(&self, formation: &Formation) -> PathBuf {
        formation.placements().fold(self.directory.clone(), |path, (idx, crusader)| {
            let as_dir = format!("{}{:?}", idx, crusader.name);
            path.join(&as_dir)
        })
    }

    fn try_write_to_cache(&self, path: &Path, node: &Node) -> io::Result<()> {
        create_dir_all(path)?;
        let mut file = BufWriter::new(File::create(path.join("search_data.dat"))?);
        file.write_u8(1)?;
        write_node(node, &mut file)?;
        Ok(())
    }

    fn try_load_from_cache<'a>(
        &self,
        path: &Path,
        crusaders: &'a [Crusader],
    ) -> io::Result<Node<'a>> {
        let mut file = BufReader::new(File::open(path.join("search_data.dat"))?);
        let v = file.read_u8()?;
        if v == 1 {
            read_node(crusaders, &mut file)
        } else {
            Err(io::Error::new(io::ErrorKind::Other, "Invalid cache version"))
        }
    }
}

fn write_node<W: Write>(node: &Node, out: &mut W) -> io::Result<()> {
    out.write_f64::<NativeEndian>(node.highest_score_seen.into())?;
    out.write_f64::<NativeEndian>(node.total_score_seen.into())?;
    out.write_u32::<NativeEndian>(node.times_checked)?;
    out.write_u64::<NativeEndian>(node.children.len() as u64)?;
    for (&(idx, crusader), child) in &node.children {
        out.write_u8(idx as u8)?;
        out.write_u8(crusader.name as u8)?;
        write_node(child, out)?;
    }
    Ok(())
}

fn read_node<'a, R: Read>(crusaders: &'a [Crusader], read: &mut R) -> io::Result<Node<'a>> {
    use std::mem::transmute;
    let highest_score_seen = read.read_f64::<NativeEndian>()?.into();
    let total_score_seen = read.read_f64::<NativeEndian>()?.into();
    let times_checked = read.read_u32::<NativeEndian>()?;
    let num_children = read.read_u64::<NativeEndian>()? as usize;
    let mut children = OrderMap::with_capacity(num_children);
    for _ in 0..num_children {
        let idx = read.read_u8()? as usize;
        let name = unsafe { transmute(read.read_u8()?) };
        let crusader = crusaders.iter().find(|c| c.name == name).unwrap();
        let node = read_node(crusaders, read)?;
        children.insert((idx, crusader), node);
    }
    Ok(Node {
        progress: Default::default(),
        highest_score_seen,
        total_score_seen,
        times_checked,
        children,
    })
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_private)]

#[macro_use] extern crate log;
extern crate rustc;
extern crate rustc_errors;
extern crate rustc_target;
extern crate syntax;
extern crate syntax_pos;

pub mod expand;

pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
    AllocatorMethod {
        name: "alloc",
        inputs: &[AllocatorTy::Layout],
        output: AllocatorTy::ResultPtr,
    },
    AllocatorMethod {
        name: "dealloc",
        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
        output: AllocatorTy::Unit,
    },
    AllocatorMethod {
        name: "realloc",
        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
        output: AllocatorTy::ResultPtr,
    },
    AllocatorMethod {
        name: "alloc_zeroed",
        inputs: &[AllocatorTy::Layout],
        output: AllocatorTy::ResultPtr,
    },
];

pub struct AllocatorMethod {
    pub name: &'static str,
    pub inputs: &'static [AllocatorTy],
    pub output: AllocatorTy,
}

pub enum AllocatorTy {
    Layout,
    Ptr,
    ResultPtr,
    Unit,
    Usize,
}
<commit_msg>[nll] librustc_allocator: enable feature(nll) for bootstrap<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(not(stage0), feature(nll))]
#![feature(rustc_private)]

#[macro_use] extern crate log;
extern crate rustc;
extern crate rustc_errors;
extern crate rustc_target;
extern crate syntax;
extern crate syntax_pos;

pub mod expand;

pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
    AllocatorMethod {
        name: "alloc",
        inputs: &[AllocatorTy::Layout],
        output: AllocatorTy::ResultPtr,
    },
    AllocatorMethod {
        name: "dealloc",
        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
        output: AllocatorTy::Unit,
    },
    AllocatorMethod {
        name: "realloc",
        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
        output: AllocatorTy::ResultPtr,
    },
    AllocatorMethod {
        name: "alloc_zeroed",
        inputs: &[AllocatorTy::Layout],
        output: AllocatorTy::ResultPtr,
    },
];

pub struct AllocatorMethod {
    pub name: &'static str,
    pub inputs: &'static [AllocatorTy],
    pub output: AllocatorTy,
}

pub enum AllocatorTy {
    Layout,
    Ptr,
    ResultPtr,
    Unit,
    Usize,
}
<|endoftext|>


<commit_before>//! Extension traits for `Stream` implementing various operators.
//!
//! A collection of functions taking typed `Stream` objects as input and producing new `Stream`
//! objects as output. Many of the operators provide simple, composable functionality. Some of the
//! operators are more complicated, for use with advanced timely dataflow features.
//!
//! The [`Unary`](./unary/index.html) and [`Binary`](./binary/index.html) operators provide general
//! operators whose behavior can be supplied using closures accepting input and output handles.
//! Most of the operators in this module are defined using these two general operators.

pub use self::enterleave::{Enter, EnterAt, Leave};
pub use self::unary::Unary;
pub use self::queue::*;
pub use self::input::Input;
pub use self::feedback::{LoopVariable, ConnectLoop};
pub use self::concat::{Concat, Concatenate};
pub use self::partition::Partition;
pub use self::map::Map;
pub use self::inspect::Inspect;
pub use self::filter::Filter;
pub use self::binary::Binary;
pub use self::delay::Delay;
pub use self::exchange::Exchange as ExchangeExtension;
pub use self::broadcast::Broadcast;
pub use self::probe::Probe;
pub use self::to_stream::ToStream;
pub use self::capture::Capture;

pub mod enterleave;
pub mod unary;
pub mod queue;
pub mod input;
pub mod feedback;
pub mod concat;
pub mod partition;
pub mod map;
pub mod inspect;
pub mod filter;
pub mod binary;
pub mod delay;
pub mod exchange;
pub mod broadcast;
pub mod probe;
pub mod to_stream;
pub mod capture;

pub mod aggregation;

// keep the handle constructors private
mod handles;
pub use self::handles::{InputHandle, OutputHandle};

mod notificator;
pub use self::notificator::Notificator;

// keep "mint" module-private
mod capability;
pub use self::capability::Capability;
<commit_msg>commented out queue.rs, because it is dumb<commit_after>//! Extension traits for `Stream` implementing various operators.
//!
//! A collection of functions taking typed `Stream` objects as input and producing new `Stream`
//! objects as output. Many of the operators provide simple, composable functionality. Some of the
//! operators are more complicated, for use with advanced timely dataflow features.
//!
//! The [`Unary`](./unary/index.html) and [`Binary`](./binary/index.html) operators provide general
//! operators whose behavior can be supplied using closures accepting input and output handles.
//! Most of the operators in this module are defined using these two general operators.

pub use self::enterleave::{Enter, EnterAt, Leave};
pub use self::unary::Unary;
// pub use self::queue::*;
pub use self::input::Input;
pub use self::feedback::{LoopVariable, ConnectLoop};
pub use self::concat::{Concat, Concatenate};
pub use self::partition::Partition;
pub use self::map::Map;
pub use self::inspect::Inspect;
pub use self::filter::Filter;
pub use self::binary::Binary;
pub use self::delay::Delay;
pub use self::exchange::Exchange as ExchangeExtension;
pub use self::broadcast::Broadcast;
pub use self::probe::Probe;
pub use self::to_stream::ToStream;
pub use self::capture::Capture;

pub mod enterleave;
pub mod unary;
// pub mod queue;
pub mod input;
pub mod feedback;
pub mod concat;
pub mod partition;
pub mod map;
pub mod inspect;
pub mod filter;
pub mod binary;
pub mod delay;
pub mod exchange;
pub mod broadcast;
pub mod probe;
pub mod to_stream;
pub mod capture;

pub mod aggregation;

// keep the handle constructors private
mod handles;
pub use self::handles::{InputHandle, OutputHandle};

mod notificator;
pub use self::notificator::Notificator;

// keep "mint" module-private
mod capability;
pub use self::capability::Capability;
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn chegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_complex, lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_real, bp: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublereal, bp: CLPK_doublereal,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_complex, bp: CLPK_complex,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublecomplex,
            bp: CLPK_doublecomplex, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn ssbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_real,
            ldab: CLPK_integer, bb: CLPK_real, ldbb: CLPK_integer,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_doublereal,
            ldab: CLPK_integer, bb: CLPK_doublereal, ldbb: CLPK_integer,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_complex,
            ldab: CLPK_integer, bb: CLPK_complex, ldbb: CLPK_integer,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_doublecomplex,
            ldab: CLPK_integer, bb: CLPK_doublecomplex,
            ldbb: CLPK_integer, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<commit_msg>Add Ggev trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn chegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_complex, lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_real, bp: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublereal, bp: CLPK_doublereal,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_complex, bp: CLPK_complex,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublecomplex,
            bp: CLPK_doublecomplex, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn ssbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_real,
            ldab: CLPK_integer, bb: CLPK_real, ldbb: CLPK_integer,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_doublereal,
            ldab: CLPK_integer, bb: CLPK_doublereal, ldbb: CLPK_integer,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_complex,
            ldab: CLPK_integer, bb: CLPK_complex, ldbb: CLPK_integer,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_doublecomplex,
            ldab: CLPK_integer, bb: CLPK_doublecomplex,
            ldbb: CLPK_integer, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sggev_(jobvl: c_char, jobvr: c_char, n: *const CLPK_integer, a: *mut CLPK_real,
            lda: *const CLPK_integer, b: *mut CLPK_real, ldb: *const CLPK_integer,
            alphar: CLPK_real, alphai: CLPK_real, beta: *mut CLPK_real,
            vl: CLPK_real, ldvl: CLPK_integer, vr: CLPK_real,
            ldvr: CLPK_integer, work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dggev_(jobvl: c_char, jobvr: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublereal, lda: *const CLPK_integer, b: *mut CLPK_doublereal,
            ldb: *const CLPK_integer, alphar: CLPK_doublereal,
            alphai: CLPK_doublereal, beta: *mut CLPK_doublereal,
            vl: CLPK_doublereal, ldvl: CLPK_integer,
            vr: CLPK_doublereal, ldvr: CLPK_integer,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn cggev_(jobvl: c_char, jobvr: c_char, n: *const CLPK_integer,
            a: *mut CLPK_complex, lda: *const CLPK_integer, b: *mut CLPK_complex,
            ldb: *const CLPK_integer, alpha: *mut CLPK_complex, beta: *mut CLPK_complex,
            vl: CLPK_complex, ldvl: CLPK_integer, vr: CLPK_complex,
            ldvr: CLPK_integer, work: CLPK_complex, lwork: CLPK_integer,
            rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zggev_(jobvl: c_char, jobvr: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            alpha: *mut CLPK_doublecomplex, beta: *mut CLPK_doublecomplex,
            vl: CLPK_doublecomplex, ldvl: CLPK_integer,
            vr: CLPK_doublecomplex, ldvr: CLPK_integer,
            work: CLPK_doublecomplex, lwork: CLPK_integer,
            rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<|endoftext|>


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

//! cmake wrapper for build

extern crate cmake;
extern crate fs_extra;

use cmake::Config;
use std::env;
use std::path::{PathBuf};
use fs_extra::dir::*;

fn main() {
	let path_str = env::var("OUT_DIR").unwrap();
	let mut out_path = PathBuf::from(&path_str);
	out_path.pop();
	out_path.pop();
	out_path.pop();
	let mut plugin_path = PathBuf::from(&path_str);
	plugin_path.push("build");
	plugin_path.push("plugins");
	//Collect the files and directories we care about
	let dir_content = get_dir_content("plugins").unwrap();
	for d in dir_content.directories {
		let file_content = get_dir_content(d).unwrap();
		for f in file_content.files {
			println!("cargo:rerun-if-changed={}",f);
		}
	}
	for f in dir_content.files{
		println!("cargo:rerun-if-changed={}",f);
	}
	//panic!("marp");
	let dst = Config::new("plugins")
	                      //.define("FOO","BAR") //whatever flags go here
	                      //.cflag("-foo") //and here
	                      .build_target("")
	                      .build();

	println!("Plugin path: {:?}", plugin_path);
	println!("OUT PATH: {:?}", out_path);
	let mut options = CopyOptions::new();
	options.overwrite=true;
	if let Err(e) = copy(plugin_path, out_path, &options) {
		println!("{:?}", e);
	}

	println!("cargo:rustc-link-search=native={}", dst.display());

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

//! cmake wrapper for build

extern crate cmake;
extern crate fs_extra;

use cmake::Config;
use std::{env,fs};
use std::path::{PathBuf};
use fs_extra::dir::*;

/// Tests whether source cuckoo directory exists

pub fn fail_on_empty_directory(name: &str){
	if fs::read_dir(name).unwrap().count()==0 {
		println!("The `{}` directory is empty. Did you forget to pull the submodules?", name);
		println!("Try `git submodule update --init --recursive`");
		panic!();
	}
}

fn main() {
	fail_on_empty_directory("plugins/cuckoo");
	let path_str = env::var("OUT_DIR").unwrap();
	let mut out_path = PathBuf::from(&path_str);
	out_path.pop();
	out_path.pop();
	out_path.pop();
	let mut plugin_path = PathBuf::from(&path_str);
	plugin_path.push("build");
	plugin_path.push("plugins");
	//Collect the files and directories we care about
	let dir_content = get_dir_content("plugins").unwrap();
	for d in dir_content.directories {
		let file_content = get_dir_content(d).unwrap();
		for f in file_content.files {
			println!("cargo:rerun-if-changed={}",f);
		}
	}
	for f in dir_content.files{
		println!("cargo:rerun-if-changed={}",f);
	}
	//panic!("marp");
	let dst = Config::new("plugins")
	                      //.define("FOO","BAR") //whatever flags go here
	                      //.cflag("-foo") //and here
	                      .build_target("")
	                      .build();

	println!("Plugin path: {:?}", plugin_path);
	println!("OUT PATH: {:?}", out_path);
	let mut options = CopyOptions::new();
	options.overwrite=true;
	if let Err(e) = copy(plugin_path, out_path, &options) {
		println!("{:?}", e);
	}

	println!("cargo:rustc-link-search=native={}", dst.display());

}<|endoftext|>


<commit_before>//! Manager that is called when an output is created or destroyed.
//! Pass a struct that implements this trait to the `Compositor` during
//! initialization.

use libc;
use manager::{OutputHandler, UserOutput};
use types::OutputHandle;
use wlroots_sys::wlr_output;

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;

/// Used to ensure the output sets the mode before doing any other
/// operation on the Output.
pub struct OutputBuilder<'output> {
    output: &'output mut OutputHandle
}

/// Used to ensure that the builder is used to construct
/// the OutputHandler instance.
pub struct OutputBuilderResult<'output> {
    pub output: &'output mut OutputHandle,
    result: Box<OutputHandler>
}

/// Wrapper around Output destruction so that you can't call
/// unsafe methods (e.g anything like setting the mode).
pub struct OutputDestruction<'output>(&'output mut OutputHandle);

/// Handles output addition and removal.
pub trait OutputManagerHandler {
    /// Called whenever an output is added.
    fn output_added<'output>(&mut self,
                             _: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        None
    }

    /// Called whenever an output is removed.
    fn output_removed(&mut self, OutputDestruction) {
        // TODO
    }
    /// Called every time the output frame is updated.
    fn output_frame(&mut self, &mut OutputHandle) {}
    /// Called every time the output resolution is updated.
    fn output_resolution(&mut self, &mut OutputHandle) {}
}

impl<'output> OutputBuilder<'output> {
    pub fn build_best_mode<T: OutputHandler + 'static>(self,
                                                       data: T)
                                                       -> OutputBuilderResult<'output> {
        // NOTE Rationale for why this is safe:
        // * The builder is only constructed in output_added callback
        // * Can't be copied or otherwise escape (due to the lifetime constraints)
        // * Is only called once per output because this function consumes
        unsafe {
            self.output.choose_best_mode();
        }
        OutputBuilderResult {
            output: self.output,
            result: Box::new(data)
        }
    }
}

impl<'output> OutputDestruction<'output> {
    // TODO Functions which are safe to use
}

wayland_listener!(OutputManager, (Vec<Box<UserOutput>>, Box<OutputManagerHandler>), [
    add_listener => add_notify: |this: &mut OutputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut outputs, ref mut manager) = this.data;
        let data = data as *mut wlr_output;
        let mut output = OutputHandle::from_ptr(data as *mut wlr_output);
        let builder = OutputBuilder { output: &mut output };
        if let Some(OutputBuilderResult {result: output, ..}) = manager.output_added(builder) {
            let mut output = UserOutput::new((data, output));
            // Add the output frame event to this manager
            wl_signal_add(&mut (*data).events.frame as *mut _ as _,
                        output.frame_listener() as _);
            // Add the output resolution event to this manager
            wl_signal_add(&mut (*data).events.resolution as *mut _ as _,
                        output.resolution_listener() as _);
            // Store the user UserOutput, free later in remove listener
            outputs.push(output);
        }
    };
    remove_listener => remove_notify: |this: &mut OutputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut outputs, ref mut manager) = this.data;
        let data = data as *mut wlr_output;
        let mut output = OutputHandle::from_ptr(data);
        manager.output_removed(OutputDestruction(&mut output));
        if let Some(layout) = output.layout() {
            layout.borrow_mut().remove(&mut output);
        }
        // Remove user output data
        if let Some(index) = outputs.iter().position(|output| output.output_ptr() == data) {
            let mut removed_output = outputs.remove(index);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_output.frame_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_output.resolution_listener()).link as *mut _ as _);

        }
    };
]);
<commit_msg>Removed OutputManager::output_{frame,resolution}<commit_after>//! Manager that is called when an output is created or destroyed.
//! Pass a struct that implements this trait to the `Compositor` during
//! initialization.

use libc;
use manager::{OutputHandler, UserOutput};
use types::OutputHandle;
use wlroots_sys::wlr_output;

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;

/// Used to ensure the output sets the mode before doing any other
/// operation on the Output.
pub struct OutputBuilder<'output> {
    output: &'output mut OutputHandle
}

/// Used to ensure that the builder is used to construct
/// the OutputHandler instance.
pub struct OutputBuilderResult<'output> {
    pub output: &'output mut OutputHandle,
    result: Box<OutputHandler>
}

/// Wrapper around Output destruction so that you can't call
/// unsafe methods (e.g anything like setting the mode).
pub struct OutputDestruction<'output>(&'output mut OutputHandle);

/// Handles output addition and removal.
pub trait OutputManagerHandler {
    /// Called whenever an output is added.
    fn output_added<'output>(&mut self,
                             _: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        None
    }

    /// Called whenever an output is removed.
    fn output_removed(&mut self, OutputDestruction) {
        // TODO
    }
}

impl<'output> OutputBuilder<'output> {
    pub fn build_best_mode<T: OutputHandler + 'static>(self,
                                                       data: T)
                                                       -> OutputBuilderResult<'output> {
        // NOTE Rationale for why this is safe:
        // * The builder is only constructed in output_added callback
        // * Can't be copied or otherwise escape (due to the lifetime constraints)
        // * Is only called once per output because this function consumes
        unsafe {
            self.output.choose_best_mode();
        }
        OutputBuilderResult {
            output: self.output,
            result: Box::new(data)
        }
    }
}

impl<'output> OutputDestruction<'output> {
    // TODO Functions which are safe to use
}

wayland_listener!(OutputManager, (Vec<Box<UserOutput>>, Box<OutputManagerHandler>), [
    add_listener => add_notify: |this: &mut OutputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut outputs, ref mut manager) = this.data;
        let data = data as *mut wlr_output;
        let mut output = OutputHandle::from_ptr(data as *mut wlr_output);
        let builder = OutputBuilder { output: &mut output };
        if let Some(OutputBuilderResult {result: output, ..}) = manager.output_added(builder) {
            let mut output = UserOutput::new((data, output));
            // Add the output frame event to this manager
            wl_signal_add(&mut (*data).events.frame as *mut _ as _,
                        output.frame_listener() as _);
            // Add the output resolution event to this manager
            wl_signal_add(&mut (*data).events.resolution as *mut _ as _,
                        output.resolution_listener() as _);
            // Store the user UserOutput, free later in remove listener
            outputs.push(output);
        }
    };
    remove_listener => remove_notify: |this: &mut OutputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut outputs, ref mut manager) = this.data;
        let data = data as *mut wlr_output;
        let mut output = OutputHandle::from_ptr(data);
        manager.output_removed(OutputDestruction(&mut output));
        if let Some(layout) = output.layout() {
            layout.borrow_mut().remove(&mut output);
        }
        // Remove user output data
        if let Some(index) = outputs.iter().position(|output| output.output_ptr() == data) {
            let mut removed_output = outputs.remove(index);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_output.frame_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_output.resolution_listener()).link as *mut _ as _);

        }
    };
]);
<|endoftext|>


<commit_before>use std::io::{self,ErrorKind,Read,Write};
use std::net::SocketAddr;
use mio::tcp::{TcpListener,TcpStream};
use rustls::{ServerSession, Session};
use net2::TcpBuilder;
use net2::unix::UnixTcpBuilderExt;
#[cfg(feature = "use-openssl")]
use openssl::ssl::{ErrorCode, SslStream};

#[derive(Debug,PartialEq,Copy,Clone)]
pub enum SocketResult {
  Continue,
  Closed,
  WouldBlock,
  Error
}

pub trait SocketHandler {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult);
  fn socket_write(&mut self, buf: &[u8])    -> (usize, SocketResult);
  fn socket_ref(&self) -> &TcpStream;
}

impl SocketHandler for TcpStream {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            return (size, SocketResult::Closed)
          },
          _ => {
            error!("SOCKET\tsocket_read error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            return (size, SocketResult::Closed)
          },
          _ => {
            //FIXME: timeout and other common errors should be sent up
            error!("SOCKET\tsocket_write error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self }
}

#[cfg(feature = "use-openssl")]
impl SocketHandler for SslStream<TcpStream> {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => {
          match e.code() {
            ErrorCode::WANT_READ  => return (size, SocketResult::WouldBlock),
            ErrorCode::WANT_WRITE => return (size, SocketResult::WouldBlock),
            ErrorCode::SSL        => {
              error!("SOCKET-TLS\treadable TLS socket SSL error: {:?}", e);
              return (size, SocketResult::Error)
            },
            ErrorCode::SYSCALL    => {
              return (size, SocketResult::Error)
            },
            ErrorCode::ZERO_RETURN => {
              return (size, SocketResult::Closed)
            },
            _ => {
              error!("SOCKET-TLS\treadable TLS socket error={:?}", e);
              return (size, SocketResult::Error)
            }
          }
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => {
          match e.code() {
            ErrorCode::WANT_READ  => return (size, SocketResult::WouldBlock),
            ErrorCode::WANT_WRITE => return (size, SocketResult::WouldBlock),
            ErrorCode::SSL        => {
              error!("SOCKET-TLS\twritable TLS socket SSL error: {:?}", e);
              return (size, SocketResult::Error)
            },
            ErrorCode::SYSCALL        => {
              error!("SOCKET-TLS\twritable TLS socket syscall error: {:?}", e);
              return (size, SocketResult::Error)
            },
            ErrorCode::ZERO_RETURN => {
              return (size, SocketResult::Closed)
            },
            _ => {
              error!("SOCKET-TLS\twritable TLS socket error={:?}", e);
              return (size, SocketResult::Error)
            }
          }
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self.get_ref() }
}

pub struct FrontRustls {
  pub stream:  TcpStream,
  pub session: ServerSession,
}

impl SocketHandler for FrontRustls {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size      = 0usize;
    let mut can_read  = true;
    let mut is_error  = false;
    let mut is_closed = false;

    loop {
      if size == buf.len() {
        break;
      }

      if !can_read | is_error | is_closed {
        break;
      }

      match self.session.read_tls(&mut self.stream) {
        Ok(0)  => {
          can_read  = false;
          is_closed = true;
        },
        Ok(sz) => {},
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            can_read = false;
          },
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            is_closed = true;
          },
          _ => {
            error!("could not read TLS stream from socket: {:?}", e);
            is_error = true;
            break;
           }
        }
      }

      if let Err(e) = self.session.process_new_packets() {
        error!("could not process read TLS packets: {:?}", e);
        is_error = true;
        break;
      }

      while !self.session.wants_read() {
        match self.session.read(&mut buf[size..]) {
          Ok(sz) => size += sz,
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => {
              break;
            },
            ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
              is_closed = true;
              break;
            },
            _ => {
              error!("could not read data from TLS stream: {:?}", e);
              is_error = true;
              break;
            }
          }
        }
      }
    }

    if is_error {
      (size, SocketResult::Error)
    } else if is_closed {
      (size, SocketResult::Closed)
    } else if !can_read {
      (size, SocketResult::WouldBlock)
    } else {
      (size, SocketResult::Continue)
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut buffered_size = 0usize;
    let mut sent_size     = 0usize;
    let mut can_write     = true;
    let mut is_error      = false;
    let mut is_closed     = false;

    loop {
      if buffered_size == buf.len() {
        break;
      }

      if !can_write | is_error | is_closed {
        break;
      }

      match self.session.write(&buf[buffered_size..]) {
        Ok(0)  => {
          break;
        },
        Ok(sz) => {
          buffered_size += sz;
        },
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            // we don't need to do anything, the session will return false in wants_write?
            //error!("rustls socket_write wouldblock");
          },
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            //FIXME: this should probably not happen here
            is_closed = true;
            break;
          },
          _ => {
            error!("could not write data to TLS stream: {:?}", e);
            is_error = true;
            break;
          }
        }
      }

      loop {
        match self.session.write_tls(&mut self.stream) {
          Ok(0)  => {
            //can_write = false;
            break;
          },
          Ok(sz) => {
            sent_size += sz;
          },
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => can_write = false,
            ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
              is_closed = true;
              break;
            },
            _ => {
              error!("could not write TLS stream to socket: {:?}", e);
              is_error = true;
              break;
            }
          }
        }
      }
    }

    if is_error {
      (buffered_size, SocketResult::Error)
    } else if is_closed {
      (buffered_size, SocketResult::Closed)
    } else if !can_write {
      (buffered_size, SocketResult::WouldBlock)
    } else {
      (buffered_size, SocketResult::Continue)
    }
  }

  fn socket_ref(&self) -> &TcpStream { &self.stream }
}

pub fn server_bind(addr: &SocketAddr) -> io::Result<TcpListener> {
  let sock = try!(match *addr {
    SocketAddr::V4(..) => TcpBuilder::new_v4(),
    SocketAddr::V6(..) => TcpBuilder::new_v6(),
  });

  // set so_reuseaddr, but only on unix (mirrors what libstd does)
  if cfg!(unix) {
    try!(sock.reuse_address(true));
  }

  try!(sock.reuse_port(true));

  // bind the socket
  try!(sock.bind(addr));

  // listen
  // FIXME: make the backlog configurable?
  let listener = try!(sock.listen(1024));
  TcpListener::from_std(listener)
}

<commit_msg>mark tls socket error messages as debug<commit_after>use std::io::{self,ErrorKind,Read,Write};
use std::net::SocketAddr;
use mio::tcp::{TcpListener,TcpStream};
use rustls::{ServerSession, Session};
use net2::TcpBuilder;
use net2::unix::UnixTcpBuilderExt;
#[cfg(feature = "use-openssl")]
use openssl::ssl::{ErrorCode, SslStream};

#[derive(Debug,PartialEq,Copy,Clone)]
pub enum SocketResult {
  Continue,
  Closed,
  WouldBlock,
  Error
}

pub trait SocketHandler {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult);
  fn socket_write(&mut self, buf: &[u8])    -> (usize, SocketResult);
  fn socket_ref(&self) -> &TcpStream;
}

impl SocketHandler for TcpStream {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            return (size, SocketResult::Closed)
          },
          _ => {
            error!("SOCKET\tsocket_read error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            return (size, SocketResult::Closed)
          },
          _ => {
            //FIXME: timeout and other common errors should be sent up
            error!("SOCKET\tsocket_write error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self }
}

#[cfg(feature = "use-openssl")]
impl SocketHandler for SslStream<TcpStream> {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => {
          match e.code() {
            ErrorCode::WANT_READ  => return (size, SocketResult::WouldBlock),
            ErrorCode::WANT_WRITE => return (size, SocketResult::WouldBlock),
            ErrorCode::SSL        => {
              debug!("SOCKET-TLS\treadable TLS socket SSL error: {:?}", e);
              return (size, SocketResult::Error)
            },
            ErrorCode::SYSCALL    => {
              return (size, SocketResult::Error)
            },
            ErrorCode::ZERO_RETURN => {
              return (size, SocketResult::Closed)
            },
            _ => {
              debug!("SOCKET-TLS\treadable TLS socket error={:?}", e);
              return (size, SocketResult::Error)
            }
          }
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => {
          match e.code() {
            ErrorCode::WANT_READ  => return (size, SocketResult::WouldBlock),
            ErrorCode::WANT_WRITE => return (size, SocketResult::WouldBlock),
            ErrorCode::SSL        => {
              debug!("SOCKET-TLS\twritable TLS socket SSL error: {:?}", e);
              return (size, SocketResult::Error)
            },
            ErrorCode::SYSCALL        => {
              debug!("SOCKET-TLS\twritable TLS socket syscall error: {:?}", e);
              return (size, SocketResult::Error)
            },
            ErrorCode::ZERO_RETURN => {
              return (size, SocketResult::Closed)
            },
            _ => {
              debug!("SOCKET-TLS\twritable TLS socket error={:?}", e);
              return (size, SocketResult::Error)
            }
          }
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self.get_ref() }
}

pub struct FrontRustls {
  pub stream:  TcpStream,
  pub session: ServerSession,
}

impl SocketHandler for FrontRustls {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size      = 0usize;
    let mut can_read  = true;
    let mut is_error  = false;
    let mut is_closed = false;

    loop {
      if size == buf.len() {
        break;
      }

      if !can_read | is_error | is_closed {
        break;
      }

      match self.session.read_tls(&mut self.stream) {
        Ok(0)  => {
          can_read  = false;
          is_closed = true;
        },
        Ok(sz) => {},
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            can_read = false;
          },
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            is_closed = true;
          },
          _ => {
            error!("could not read TLS stream from socket: {:?}", e);
            is_error = true;
            break;
           }
        }
      }

      if let Err(e) = self.session.process_new_packets() {
        error!("could not process read TLS packets: {:?}", e);
        is_error = true;
        break;
      }

      while !self.session.wants_read() {
        match self.session.read(&mut buf[size..]) {
          Ok(sz) => size += sz,
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => {
              break;
            },
            ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
              is_closed = true;
              break;
            },
            _ => {
              error!("could not read data from TLS stream: {:?}", e);
              is_error = true;
              break;
            }
          }
        }
      }
    }

    if is_error {
      (size, SocketResult::Error)
    } else if is_closed {
      (size, SocketResult::Closed)
    } else if !can_read {
      (size, SocketResult::WouldBlock)
    } else {
      (size, SocketResult::Continue)
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut buffered_size = 0usize;
    let mut sent_size     = 0usize;
    let mut can_write     = true;
    let mut is_error      = false;
    let mut is_closed     = false;

    loop {
      if buffered_size == buf.len() {
        break;
      }

      if !can_write | is_error | is_closed {
        break;
      }

      match self.session.write(&buf[buffered_size..]) {
        Ok(0)  => {
          break;
        },
        Ok(sz) => {
          buffered_size += sz;
        },
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            // we don't need to do anything, the session will return false in wants_write?
            //error!("rustls socket_write wouldblock");
          },
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            //FIXME: this should probably not happen here
            is_closed = true;
            break;
          },
          _ => {
            error!("could not write data to TLS stream: {:?}", e);
            is_error = true;
            break;
          }
        }
      }

      loop {
        match self.session.write_tls(&mut self.stream) {
          Ok(0)  => {
            //can_write = false;
            break;
          },
          Ok(sz) => {
            sent_size += sz;
          },
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => can_write = false,
            ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
              is_closed = true;
              break;
            },
            _ => {
              error!("could not write TLS stream to socket: {:?}", e);
              is_error = true;
              break;
            }
          }
        }
      }
    }

    if is_error {
      (buffered_size, SocketResult::Error)
    } else if is_closed {
      (buffered_size, SocketResult::Closed)
    } else if !can_write {
      (buffered_size, SocketResult::WouldBlock)
    } else {
      (buffered_size, SocketResult::Continue)
    }
  }

  fn socket_ref(&self) -> &TcpStream { &self.stream }
}

pub fn server_bind(addr: &SocketAddr) -> io::Result<TcpListener> {
  let sock = try!(match *addr {
    SocketAddr::V4(..) => TcpBuilder::new_v4(),
    SocketAddr::V6(..) => TcpBuilder::new_v6(),
  });

  // set so_reuseaddr, but only on unix (mirrors what libstd does)
  if cfg!(unix) {
    try!(sock.reuse_address(true));
  }

  try!(sock.reuse_port(true));

  // bind the socket
  try!(sock.bind(addr));

  // listen
  // FIXME: make the backlog configurable?
  let listener = try!(sock.listen(1024));
  TcpListener::from_std(listener)
}

<|endoftext|>


<commit_before>use self::private::Sealed;
use std::error::Error;
use std::panic::UnwindSafe;

pub trait AsDynError<'a>: Sealed {
    fn as_dyn_error(&self) -> &(dyn Error + 'a);
}

impl<'a, T: Error + 'a> AsDynError<'a> for T {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + Sync + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + Sync + UnwindSafe + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

mod private {
    use super::*;

    pub trait Sealed {}
    impl<'a, T: Error + 'a> Sealed for T {}
    impl<'a> Sealed for dyn Error + 'a {}
    impl<'a> Sealed for dyn Error + Send + 'a {}
    impl<'a> Sealed for dyn Error + Send + Sync + 'a {}
    impl<'a> Sealed for dyn Error + Send + Sync + UnwindSafe + 'a {}
}
<commit_msg>Sealed trait does not need its own module<commit_after>use std::error::Error;
use std::panic::UnwindSafe;

pub trait AsDynError<'a>: Sealed {
    fn as_dyn_error(&self) -> &(dyn Error + 'a);
}

impl<'a, T: Error + 'a> AsDynError<'a> for T {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + Sync + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

impl<'a> AsDynError<'a> for dyn Error + Send + Sync + UnwindSafe + 'a {
    #[inline]
    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
        self
    }
}

pub trait Sealed {}
impl<'a, T: Error + 'a> Sealed for T {}
impl<'a> Sealed for dyn Error + 'a {}
impl<'a> Sealed for dyn Error + Send + 'a {}
impl<'a> Sealed for dyn Error + Send + Sync + 'a {}
impl<'a> Sealed for dyn Error + Send + Sync + UnwindSafe + 'a {}
<|endoftext|>