<commit_before>/*!
  This moule contain XDR encoder and decoder
 */

use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

const PADDING : usize = 4;

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType,
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			Error::InvalidValue => write!(f, "Invalid value."),
			Error::InvalidType => write!(f, "Invalid type."),
			Error::Io(ref err) => err.fmt(f),
		}
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			Error::InvalidValue => "Invalid value.",
			Error::InvalidType => "Invalid type.",
			Error::Io(ref err) => error::Error::description(err),
		}
	}

	fn cause(&self) -> Option<&error::Error> {
		match *self {
			Error::InvalidValue => None,
			Error::InvalidType => None,
			Error::Io(ref err) => err.cause(),
		}
	}
}

pub struct XdrReader<'a> {
	reader : io::Cursor<&'a [u8]>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn into_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

	pub fn pack_array<T:XdrPrimitive>(&mut self, x:Vec<T>) {
		for t in x {
			XdrPrimitive::write_to_xdr(self,t);
		};
	}
	pub fn pack_opaque_var_len(&mut self, x:Vec<u8>) {
		XdrPrimitive::write_to_xdr(self,x.len() as u32);
		for t in x {
			let _ = self.writer.write_u8(t);
		}
	}
	pub fn pack_opaque_fixed_len(&mut self, x:Vec<u8>) {
		for t in x {
			let _ = self.writer.write_u8(t);
		}
	}
	pub fn pad(&mut self, len : usize) {
		for _ in 0..len {
			let _ = self.writer.write_u8(0);
		}
	}

}
impl<'a> XdrReader<'a> {
	pub fn new(x:&'a Vec<u8>) -> XdrReader<'a> {
		XdrReader{ reader : io::Cursor::new(&x) }
	}

	pub fn from_array(x: &'a [u8]) -> XdrReader<'a> {
		XdrReader{ reader: io::Cursor::new(x) }
	}

	pub fn unpack<T: XdrPrimitive>(&mut self) -> Result<T,Error> {
		T::read_from_xdr(self)
	}

	pub fn unpack_array<T:XdrPrimitive>(&mut self, n : usize) -> Result<Vec<T>,Error> {
		let mut result : Vec<T> = Vec::with_capacity(n);

		for _ in 0..n {
			let t =  T::read_from_xdr(self);
			match t {
				Ok(v) => result.push(v),
				Err(v) => return Err(v),
			}
		};
		Ok(result)
	}
	pub fn unpack_opaque_var_len(&mut self) -> Result<Vec<u8>, Error> {
		let len = match self.unpack::<u32>() {
			Ok(t) => t as usize,
			Err(t) => return Err(t),
		};
		let mut v : Vec<u8>= Vec::with_capacity(len);

		for _ in 0..len {
			match self.reader.read_u8() {
				Ok(t) => v.push(t),
				Err(t) => return Err(Error::Io(t))
			}
		}
		Ok(v)
	}
	pub fn unpack_opaque_fixed_len(&mut self, len : usize) -> Result<Vec<u8>, Error> {
		let mut v : Vec<u8>= Vec::with_capacity(len);

		for _ in 0..len {
			match self.reader.read_u8() {
				Ok(t) => v.push(t),
				Err(t) => return Err(Error::Io(t))
			}
		}
		Ok(v)
	}
}

pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl<T:XdrPrimitive> XdrPrimitive for Vec<T> {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>{
		let count = match x.unpack::<u32>() {
						Ok(t) => t as usize,
						Err(t) => return Err(t),
		};
		let mut result : Vec<T> = Vec::with_capacity(count);

		for _ in 0..count {
			match x.unpack::<T>() {
				Ok(t) => result.push(t),
				Err(t) => return Err(t),
			}
		};
		Ok(result)
	}
	fn write_to_xdr(x: &mut XdrWriter, v: Self) {
		x.pack( v.len() as u32 );
		for t in v {
			x.pack(t);
		};
	}
}

impl XdrPrimitive for String {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>{
		let len = match x.unpack::<u32>() {
					Ok(t) => t as usize,
					Err(t) => return Err(t),
		};
		let pad = PADDING - (len % PADDING);
		let bytes = match x.unpack_opaque_fixed_len(len) {
			Ok(t) => t,
			Err(t) => return Err(t),
		};

		if pad != 0 {
			let _ = x.unpack_opaque_fixed_len(pad);
		};
		match String::from_utf8(bytes) {
			Ok(s) => Ok(s),
			Err(_) => Err(Error::InvalidValue)
		}
	}

	fn write_to_xdr(x: &mut XdrWriter, v: Self) {
		let bytes = v.into_bytes();
		let bytes_len = bytes.len();
		let pad = PADDING - (bytes_len % PADDING);
		x.pack_opaque_var_len(bytes);

		x.pad(pad);
	}
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_u32::<byteorder::BigEndian>(v);
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_u32::<byteorder::BigEndian>(v as u32);
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_u32::<byteorder::BigEndian>(v as u32);
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_i32::<byteorder::BigEndian>(v as i32);
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_i32::<byteorder::BigEndian>(v as i32);
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_i32::<byteorder::BigEndian>(v);
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_i64::<byteorder::BigEndian>(v);
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_u64::<byteorder::BigEndian>(v);
	}
}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_f32::<byteorder::BigEndian>(v);
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_f64::<byteorder::BigEndian>(v);
	}
}

impl XdrPrimitive for bool {
	fn read_from_xdr(x: &mut XdrReader) -> Result<bool, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(0) => Ok(false),
			Ok(1) => Ok(true),
			Ok(_) => Err(Error::InvalidValue),
			Err(v) => Err(Error::Io(v))
		}
	}

	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = match v {
			true => x.writer.write_u32::<byteorder::BigEndian>(1),
			false => x.writer.write_u32::<byteorder::BigEndian>(0),
		};
	}
}
<commit_msg>Replace some matches with try!<commit_after>/*!
  This moule contain XDR encoder and decoder
 */

use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

const PADDING : usize = 4;

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType,
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			Error::InvalidValue => write!(f, "Invalid value."),
			Error::InvalidType => write!(f, "Invalid type."),
			Error::Io(ref err) => err.fmt(f),
		}
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			Error::InvalidValue => "Invalid value.",
			Error::InvalidType => "Invalid type.",
			Error::Io(ref err) => error::Error::description(err),
		}
	}

	fn cause(&self) -> Option<&error::Error> {
		match *self {
			Error::InvalidValue => None,
			Error::InvalidType => None,
			Error::Io(ref err) => err.cause(),
		}
	}
}

pub struct XdrReader<'a> {
	reader : io::Cursor<&'a [u8]>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn into_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

	pub fn pack_array<T:XdrPrimitive>(&mut self, x:Vec<T>) {
		for t in x {
			XdrPrimitive::write_to_xdr(self,t);
		};
	}
	pub fn pack_opaque_var_len(&mut self, x:Vec<u8>) {
		XdrPrimitive::write_to_xdr(self,x.len() as u32);
		for t in x {
			let _ = self.writer.write_u8(t);
		}
	}
	pub fn pack_opaque_fixed_len(&mut self, x:Vec<u8>) {
		for t in x {
			let _ = self.writer.write_u8(t);
		}
	}
	pub fn pad(&mut self, len : usize) {
		for _ in 0..len {
			let _ = self.writer.write_u8(0);
		}
	}

}
impl<'a> XdrReader<'a> {
	pub fn new(x:&'a Vec<u8>) -> XdrReader<'a> {
		XdrReader{ reader : io::Cursor::new(&x) }
	}

	pub fn from_array(x: &'a [u8]) -> XdrReader<'a> {
		XdrReader{ reader: io::Cursor::new(x) }
	}

	pub fn unpack<T: XdrPrimitive>(&mut self) -> Result<T,Error> {
		T::read_from_xdr(self)
	}

	pub fn unpack_array<T:XdrPrimitive>(&mut self, n : usize) -> Result<Vec<T>,Error> {
		let mut result : Vec<T> = Vec::with_capacity(n);

		for _ in 0..n {
			let t =  T::read_from_xdr(self);
			match t {
				Ok(v) => result.push(v),
				Err(v) => return Err(v),
			}
		};
		Ok(result)
	}
	pub fn unpack_opaque_var_len(&mut self) -> Result<Vec<u8>, Error> {
		let len = try!(self.unpack::<u32>()) as usize;
		let mut v : Vec<u8>= Vec::with_capacity(len);

		for _ in 0..len {
			match self.reader.read_u8() {
				Ok(t) => v.push(t),
				Err(t) => return Err(Error::Io(t))
			}
		}
		Ok(v)
	}
	pub fn unpack_opaque_fixed_len(&mut self, len : usize) -> Result<Vec<u8>, Error> {
		let mut v : Vec<u8>= Vec::with_capacity(len);

		for _ in 0..len {
			match self.reader.read_u8() {
				Ok(t) => v.push(t),
				Err(t) => return Err(Error::Io(t))
			}
		}
		Ok(v)
	}
}

pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl<T:XdrPrimitive> XdrPrimitive for Vec<T> {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>{
		let count = try!(x.unpack::<u32>()) as usize;
		let mut result : Vec<T> = Vec::with_capacity(count);

		for _ in 0..count {
			match x.unpack::<T>() {
				Ok(t) => result.push(t),
				Err(t) => return Err(t),
			}
		};
		Ok(result)
	}
	fn write_to_xdr(x: &mut XdrWriter, v: Self) {
		x.pack( v.len() as u32 );
		for t in v {
			x.pack(t);
		};
	}
}

impl XdrPrimitive for String {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>{
		let len = try!(x.unpack::<u32>()) as usize;
		let pad = PADDING - (len % PADDING);
		let bytes = try!(x.unpack_opaque_fixed_len(len));

		if pad != 0 {
			let _ = x.unpack_opaque_fixed_len(pad);
		};
		match String::from_utf8(bytes) {
			Ok(s) => Ok(s),
			Err(_) => Err(Error::InvalidValue)
		}
	}

	fn write_to_xdr(x: &mut XdrWriter, v: Self) {
		let bytes = v.into_bytes();
		let bytes_len = bytes.len();
		let pad = PADDING - (bytes_len % PADDING);
		x.pack_opaque_var_len(bytes);

		x.pad(pad);
	}
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_u32::<byteorder::BigEndian>(v);
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_u32::<byteorder::BigEndian>(v as u32);
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_u32::<byteorder::BigEndian>(v as u32);
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_i32::<byteorder::BigEndian>(v as i32);
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_i32::<byteorder::BigEndian>(v as i32);
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_i32::<byteorder::BigEndian>(v);
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_i64::<byteorder::BigEndian>(v);
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_u64::<byteorder::BigEndian>(v);
	}
}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_f32::<byteorder::BigEndian>(v);
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}
	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = x.writer.write_f64::<byteorder::BigEndian>(v);
	}
}

impl XdrPrimitive for bool {
	fn read_from_xdr(x: &mut XdrReader) -> Result<bool, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(0) => Ok(false),
			Ok(1) => Ok(true),
			Ok(_) => Err(Error::InvalidValue),
			Err(v) => Err(Error::Io(v))
		}
	}

	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		let _ = match v {
			true => x.writer.write_u32::<byteorder::BigEndian>(1),
			false => x.writer.write_u32::<byteorder::BigEndian>(0),
		};
	}
}
<|endoftext|>


<commit_before>//! Decoding and Encoding of PNG Images
//!
//! PNG (Portable Network Graphics) is an image format that supports lossless compression.
//!
//! # Related Links
//! * <http://www.w3.org/TR/PNG/> - The PNG Specification
//!

extern crate png;

use self::png::HasParameters;

use std::io::{self, Cursor, Read, Write};

use color::ColorType;
use image::{ImageDecoder, ImageError, ImageResult};

/// PNG decoder
pub struct PNGDecoder<R: Read> {
    colortype: ColorType,
    reader: png::Reader<R>,
}

impl<R: Read> PNGDecoder<R> {
    /// Creates a new decoder that decodes from the stream ```r```
    pub fn new(r: R) -> ImageResult<PNGDecoder<R>> {
        let decoder = png::Decoder::new(r);
        let (_, mut reader) = decoder.read_info()?;
        let colortype = reader.output_color_type().into();

        Ok(PNGDecoder { colortype, reader })
    }
}

impl<R: Read> ImageDecoder for PNGDecoder<R> {
    type Reader = Cursor<Vec<u8>>;

    fn dimensions(&self) -> (u64, u64) {
        let (w, h) = self.reader.info().size();
        (w as u64, h as u64)
    }

    fn colortype(&self) -> ColorType {
        self.colortype
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(Cursor::new(self.read_image()?))
    }

    fn read_image(mut self) -> ImageResult<Vec<u8>> {
        let mut data = vec![0; self.reader.output_buffer_size()];
        self.reader.next_frame(&mut data)?;
        Ok(data)
    }
}

/// PNG encoder
pub struct PNGEncoder<W: Write> {
    w: W,
}

impl<W: Write> PNGEncoder<W> {
    /// Create a new encoder that writes its output to ```w```
    pub fn new(w: W) -> PNGEncoder<W> {
        PNGEncoder { w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```
    pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> io::Result<()> {
        let (ct, bits) = color.into();
        let mut encoder = png::Encoder::new(self.w, width, height);
        encoder.set(ct).set(bits);
        let mut writer = try!(encoder.write_header());
        writer.write_image_data(data).map_err(|e| e.into())
    }
}

impl From<(png::ColorType, png::BitDepth)> for ColorType {
    fn from((ct, bits): (png::ColorType, png::BitDepth)) -> ColorType {
        use self::png::ColorType::*;
        let bits = bits as u8;
        match ct {
            Grayscale => ColorType::Gray(bits),
            RGB => ColorType::RGB(bits),
            Indexed => ColorType::Palette(bits),
            GrayscaleAlpha => ColorType::GrayA(bits),
            RGBA => ColorType::RGBA(bits),
        }
    }
}

impl From<ColorType> for (png::ColorType, png::BitDepth) {
    fn from(ct: ColorType) -> (png::ColorType, png::BitDepth) {
        use self::png::ColorType::*;
        let (ct, bits) = match ct {
            ColorType::Gray(bits) => (Grayscale, bits),
            ColorType::RGB(bits) => (RGB, bits),
            ColorType::Palette(bits) => (Indexed, bits),
            ColorType::GrayA(bits) => (GrayscaleAlpha, bits),
            ColorType::RGBA(bits) => (RGBA, bits),
            ColorType::BGRA(bits) => (RGBA, bits),
            ColorType::BGR(bits) => (RGB, bits),
        };
        (ct, png::BitDepth::from_u8(bits).unwrap())
    }
}

impl From<png::DecodingError> for ImageError {
    fn from(err: png::DecodingError) -> ImageError {
        use self::png::DecodingError::*;
        match err {
            IoError(err) => ImageError::IoError(err),
            Format(desc) => ImageError::FormatError(desc.into_owned()),
            InvalidSignature => ImageError::FormatError("invalid signature".into()),
            CrcMismatch { .. } => ImageError::FormatError("CRC error".into()),
            Other(desc) => ImageError::FormatError(desc.into_owned()),
            CorruptFlateStream => {
                ImageError::FormatError("compressed data stream corrupted".into())
            }
        }
    }
}
<commit_msg>Update png limits<commit_after>//! Decoding and Encoding of PNG Images
//!
//! PNG (Portable Network Graphics) is an image format that supports lossless compression.
//!
//! # Related Links
//! * <http://www.w3.org/TR/PNG/> - The PNG Specification
//!

extern crate png;

use self::png::HasParameters;

use std;
use std::io::{self, Cursor, Read, Write};

use color::ColorType;
use image::{ImageDecoder, ImageError, ImageResult};

/// PNG decoder
pub struct PNGDecoder<R: Read> {
    colortype: ColorType,
    reader: png::Reader<R>,
}

impl<R: Read> PNGDecoder<R> {
    /// Creates a new decoder that decodes from the stream ```r```
    pub fn new(r: R) -> ImageResult<PNGDecoder<R>> {
        let limits = png::Limits {
            pixels: std::u64::MAX,
        };
        let decoder = png::Decoder::new_with_limits(r, limits);
        let (_, mut reader) = decoder.read_info()?;
        let colortype = reader.output_color_type().into();

        Ok(PNGDecoder { colortype, reader })
    }
}

impl<R: Read> ImageDecoder for PNGDecoder<R> {
    type Reader = Cursor<Vec<u8>>;

    fn dimensions(&self) -> (u64, u64) {
        let (w, h) = self.reader.info().size();
        (w as u64, h as u64)
    }

    fn colortype(&self) -> ColorType {
        self.colortype
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(Cursor::new(self.read_image()?))
    }

    fn read_image(mut self) -> ImageResult<Vec<u8>> {
        let mut data = vec![0; self.reader.output_buffer_size()];
        self.reader.next_frame(&mut data)?;
        Ok(data)
    }
}

/// PNG encoder
pub struct PNGEncoder<W: Write> {
    w: W,
}

impl<W: Write> PNGEncoder<W> {
    /// Create a new encoder that writes its output to ```w```
    pub fn new(w: W) -> PNGEncoder<W> {
        PNGEncoder { w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```
    pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> io::Result<()> {
        let (ct, bits) = color.into();
        let mut encoder = png::Encoder::new(self.w, width, height);
        encoder.set(ct).set(bits);
        let mut writer = try!(encoder.write_header());
        writer.write_image_data(data).map_err(|e| e.into())
    }
}

impl From<(png::ColorType, png::BitDepth)> for ColorType {
    fn from((ct, bits): (png::ColorType, png::BitDepth)) -> ColorType {
        use self::png::ColorType::*;
        let bits = bits as u8;
        match ct {
            Grayscale => ColorType::Gray(bits),
            RGB => ColorType::RGB(bits),
            Indexed => ColorType::Palette(bits),
            GrayscaleAlpha => ColorType::GrayA(bits),
            RGBA => ColorType::RGBA(bits),
        }
    }
}

impl From<ColorType> for (png::ColorType, png::BitDepth) {
    fn from(ct: ColorType) -> (png::ColorType, png::BitDepth) {
        use self::png::ColorType::*;
        let (ct, bits) = match ct {
            ColorType::Gray(bits) => (Grayscale, bits),
            ColorType::RGB(bits) => (RGB, bits),
            ColorType::Palette(bits) => (Indexed, bits),
            ColorType::GrayA(bits) => (GrayscaleAlpha, bits),
            ColorType::RGBA(bits) => (RGBA, bits),
            ColorType::BGRA(bits) => (RGBA, bits),
            ColorType::BGR(bits) => (RGB, bits),
        };
        (ct, png::BitDepth::from_u8(bits).unwrap())
    }
}

impl From<png::DecodingError> for ImageError {
    fn from(err: png::DecodingError) -> ImageError {
        use self::png::DecodingError::*;
        match err {
            IoError(err) => ImageError::IoError(err),
            Format(desc) => ImageError::FormatError(desc.into_owned()),
            InvalidSignature => ImageError::FormatError("invalid signature".into()),
            CrcMismatch { .. } => ImageError::FormatError("CRC error".into()),
            Other(desc) => ImageError::FormatError(desc.into_owned()),
            CorruptFlateStream => {
                ImageError::FormatError("compressed data stream corrupted".into())
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeSet;

/*
A multi-expression program represented using a series of operations that can reuse results of previous operations.
*/
pub struct Mep<Ins> {
    pub instructions: Vec<Ins>,
}

impl<Ins> Clone for Mep<Ins>
    where Ins: Clone {
    fn clone(&self) -> Self {
        Mep{instructions: self.instructions.clone()}
    }
}

impl<Ins> Mep<Ins> {
    //Generates a new Mep with a particular size and takes a closure to generate random instructions
    pub fn new<I>(random_instruction_iter: I) -> Mep<Ins>
        where I: Iterator<Item=Ins> {
        Mep{instructions: random_instruction_iter.collect()}
    }

    /*
    Performs a crossover that switches at random points in the genome.
    random_point_generator takes an argument that specifies the end of the range to generate and is exclusive.
    */
    pub fn crossover<F>(parent0: &Mep<Ins>, parent1: &Mep<Ins>, points: usize, mut random_point_generator: F) -> Mep<Ins>
        where F: FnMut(usize) -> usize, Ins: Clone {
        //Get the smallest of the two lengths

        let total_instructions = if parent0.instructions.len() < parent1.instructions.len() {
                parent0.instructions.len()
            } else {
                parent1.instructions.len()
            };
        Mep{instructions: (0..points)
            //Generate crossover points
            .map(|_| random_point_generator(total_instructions))
            .chain(Some(total_instructions))
            //Sort them by value into BTree and remove duplicate values
            .fold(BTreeSet::new(), |mut set, i| {set.insert(i); set})
            .iter()
            //Turn every copy of two, prepending a 0, into a range
            .scan(0, |prev, x| {let out = Some(*prev..*x); *prev = *x; out})
            //Enumerate by index to differentiate odd and even values
            .enumerate()
            //Map even pairs to ranges in parent 0 and odd ones to ranges in parent 1 and expand the ranges
            .flat_map(|(index, range)| {
                {if index % 2 == 0 {parent0} else {parent1}}.instructions[range].iter().cloned()
            })
            //Collect all the ranges
            .collect()
        }
    }
}
<commit_msg>small name correction<commit_after>use std::collections::BTreeSet;

/*
A multi-expression program represented using a series of operations that can reuse results of previous operations.
*/
pub struct Mep<Ins> {
    pub instructions: Vec<Ins>,
}

impl<Ins> Clone for Mep<Ins>
    where Ins: Clone {
    fn clone(&self) -> Self {
        Mep{instructions: self.instructions.clone()}
    }
}

impl<Ins> Mep<Ins> {
    //Generates a new Mep with a particular size and takes a closure to generate random instructions
    pub fn new<I>(instruction_iter: I) -> Mep<Ins>
        where I: Iterator<Item=Ins> {
        Mep{instructions: instruction_iter.collect()}
    }

    /*
    Performs a crossover that switches at random points in the genome.
    random_point_generator takes an argument that specifies the end of the range to generate and is exclusive.
    */
    pub fn crossover<F>(parent0: &Mep<Ins>, parent1: &Mep<Ins>, points: usize, mut random_point_generator: F) -> Mep<Ins>
        where F: FnMut(usize) -> usize, Ins: Clone {
        //Get the smallest of the two lengths

        let total_instructions = if parent0.instructions.len() < parent1.instructions.len() {
                parent0.instructions.len()
            } else {
                parent1.instructions.len()
            };
        Mep{instructions: (0..points)
            //Generate crossover points
            .map(|_| random_point_generator(total_instructions))
            .chain(Some(total_instructions))
            //Sort them by value into BTree and remove duplicate values
            .fold(BTreeSet::new(), |mut set, i| {set.insert(i); set})
            .iter()
            //Turn every copy of two, prepending a 0, into a range
            .scan(0, |prev, x| {let out = Some(*prev..*x); *prev = *x; out})
            //Enumerate by index to differentiate odd and even values
            .enumerate()
            //Map even pairs to ranges in parent 0 and odd ones to ranges in parent 1 and expand the ranges
            .flat_map(|(index, range)| {
                {if index % 2 == 0 {parent0} else {parent1}}.instructions[range].iter().cloned()
            })
            //Collect all the ranges
            .collect()
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Debug, Display};
use std::mem;

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor};
use serde::de::value::BorrowedStrDeserializer;

use error::Error;

/// Reference to a range of bytes encompassing a single valid JSON value in the
/// input data.
///
/// A `RawValue` can be used to defer parsing parts of a payload until later,
/// or to avoid parsing it at all in the case that part of the payload just
/// needs to be transferred verbatim into a different output object.
///
/// When serializing, a value of this type will retain its original formatting
/// and will not be minified or pretty-printed.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate serde_derive;
/// extern crate serde_json;
///
/// use serde_json::{Result, value::RawValue};
///
/// #[derive(Deserialize)]
/// struct Input<'a> {
///     code: u32,
///     #[serde(borrow)]
///     payload: &'a RawValue,
/// }
///
/// #[derive(Serialize)]
/// struct Output<'a> {
///     info: (u32, &'a RawValue),
/// }
///
/// // Efficiently rearrange JSON input containing separate "code" and "payload"
/// // keys into a single "info" key holding an array of code and payload.
/// //
/// // This could be done equivalently using serde_json::Value as the type for
/// // payload, but &RawValue will perform netter because it does not require
/// // memory allocation. The correct range of bytes is borrowed from the input
/// // data and pasted verbatim into the output.
/// fn rearrange(input: &str) -> Result<String> {
///     let input: Input = serde_json::from_str(input)?;
///
///     let output = Output {
///         info: (input.code, input.payload),
///     };
///
///     serde_json::to_string(&output)
/// }
///
/// fn main() -> Result<()> {
///     let out = rearrange(r#" {"code": 200, "payload": {}} "#)?;
///
///     assert_eq!(out, r#"{"info":[200,{}]}"#);
///
///     Ok(())
/// }
/// ```
///
/// # Ownership
///
/// The typical usage of `RawValue` will be in the borrowed form:
///
/// ```
/// # #[macro_use]
/// # extern crate serde_derive;
/// # extern crate serde_json;
/// #
/// # use serde_json::value::RawValue;
/// #
/// #[derive(Deserialize)]
/// struct SomeStruct<'a> {
///     #[serde(borrow)]
///     raw_value: &'a RawValue,
/// }
/// #
/// # fn main() {}
/// ```
///
/// The borrowed form is suitable when deserializing through
/// [`serde_json::from_str`] and [`serde_json::from_slice`] which support
/// borrowing from the input data without memory allocation.
///
/// When deserializing through [`serde_json::from_reader`] you will need to use
/// the boxed form of `RawValue` instead. This is almost as efficient but
/// involves buffering the raw value from the I/O stream into memory.
///
/// [`serde_json::from_str`]: ../fn.from_str.html
/// [`serde_json::from_slice`]: ../fn.from_slice.html
/// [`serde_json::from_reader`]: ../fn.from_reader.html
///
/// ```
/// # #[macro_use]
/// # extern crate serde_derive;
/// # extern crate serde_json;
/// #
/// # use serde_json::value::RawValue;
/// #
/// #[derive(Deserialize)]
/// struct SomeStruct {
///     raw_value: Box<RawValue>,
/// }
/// #
/// # fn main() {}
/// ```
///
/// # Note
///
/// `RawValue` is only available if serde\_json is built with the `"raw_value"`
/// feature.
///
/// ```toml
/// [dependencies]
/// serde_json = { version = "1.0", features = ["raw_value"] }
/// ```
#[repr(C)]
pub struct RawValue {
    json: str,
}

impl RawValue {
    fn from_borrowed(json: &str) -> &Self {
        unsafe { mem::transmute::<&str, &RawValue>(json) }
    }

    fn from_owned(json: Box<str>) -> Box<Self> {
        unsafe { mem::transmute::<Box<str>, Box<RawValue>>(json) }
    }
}

impl Clone for Box<RawValue> {
    fn clone(&self) -> Self {
        (**self).to_owned()
    }
}

impl ToOwned for RawValue {
    type Owned = Box<RawValue>;

    fn to_owned(&self) -> Self::Owned {
        RawValue::from_owned(self.json.to_owned().into_boxed_str())
    }
}

impl Debug for RawValue {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_tuple("RawValue")
            .field(&format_args!("{}", &self.json))
            .finish()
    }
}

impl Display for RawValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.json)
    }
}

impl RawValue {
    /// Access the JSON text underlying a raw value.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate serde_derive;
    /// extern crate serde_json;
    ///
    /// use serde_json::{Result, value::RawValue};
    ///
    /// #[derive(Deserialize)]
    /// struct Response<'a> {
    ///     code: u32,
    ///     #[serde(borrow)]
    ///     payload: &'a RawValue,
    /// }
    ///
    /// fn process(input: &str) -> Result<()> {
    ///     let response: Response = serde_json::from_str(input)?;
    ///
    ///     let payload = response.payload.get();
    ///     if payload.starts_with('{') {
    ///         // handle a payload which is a JSON map
    ///     } else {
    ///         // handle any other type
    ///     }
    ///
    ///     Ok(())
    /// }
    ///
    /// fn main() -> Result<()> {
    ///     process(r#" {"code": 200, "payload": {}} "#)?;
    ///     Ok(())
    /// }
    /// ```
    pub fn get(&self) -> &str {
        &self.json
    }
}

pub const TOKEN: &'static str = "$serde_json::private::RawValue";

impl Serialize for RawValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut s = serializer.serialize_struct(TOKEN, 1)?;
        s.serialize_field(TOKEN, &self.json)?;
        s.end()
    }
}

impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct ReferenceVisitor;

        impl<'de> Visitor<'de> for ReferenceVisitor {
            type Value = &'de RawValue;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(ReferenceFromString)
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, ReferenceVisitor)
    }
}

impl<'de> Deserialize<'de> for Box<RawValue> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct BoxedVisitor;

        impl<'de> Visitor<'de> for BoxedVisitor {
            type Value = Box<RawValue>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(BoxedFromString)
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, BoxedVisitor)
    }
}

struct RawKey;

impl<'de> Deserialize<'de> for RawKey {
    fn deserialize<D>(deserializer: D) -> Result<RawKey, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct FieldVisitor;

        impl<'de> Visitor<'de> for FieldVisitor {
            type Value = ();

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("raw value")
            }

            fn visit_str<E>(self, s: &str) -> Result<(), E>
            where
                E: de::Error,
            {
                if s == TOKEN {
                    Ok(())
                } else {
                    Err(de::Error::custom("unexpected raw value"))
                }
            }
        }

        deserializer.deserialize_identifier(FieldVisitor)?;
        Ok(RawKey)
    }
}

pub struct ReferenceFromString;

impl<'de> DeserializeSeed<'de> for ReferenceFromString {
    type Value = &'de RawValue;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for ReferenceFromString {
    type Value = &'de RawValue;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue::from_borrowed(s))
    }
}

pub struct BoxedFromString;

impl<'de> DeserializeSeed<'de> for BoxedFromString {
    type Value = Box<RawValue>;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for BoxedFromString {
    type Value = Box<RawValue>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        self.visit_string(s.to_owned())
    }

    fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue::from_owned(s.into_boxed_str()))
    }
}

struct RawKeyDeserializer;

impl<'de> Deserializer<'de> for RawKeyDeserializer {
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_borrowed_str(TOKEN)
    }

    forward_to_deserialize_any! {
        bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq
        bytes byte_buf map struct option unit newtype_struct ignored_any
        unit_struct tuple_struct tuple enum identifier
    }
}

pub struct OwnedRawDeserializer {
    pub raw_value: Option<String>,
}

impl<'de> MapAccess<'de> for OwnedRawDeserializer {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(self.raw_value.take().unwrap().into_deserializer())
    }
}

pub struct BorrowedRawDeserializer<'de> {
    pub raw_value: Option<&'de str>,
}

impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap()))
    }
}
<commit_msg>Add a method to construct RawValue from String without allocation<commit_after>use std::fmt::{self, Debug, Display};
use std::mem;

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor};
use serde::de::value::BorrowedStrDeserializer;

use error::Error;

/// Reference to a range of bytes encompassing a single valid JSON value in the
/// input data.
///
/// A `RawValue` can be used to defer parsing parts of a payload until later,
/// or to avoid parsing it at all in the case that part of the payload just
/// needs to be transferred verbatim into a different output object.
///
/// When serializing, a value of this type will retain its original formatting
/// and will not be minified or pretty-printed.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate serde_derive;
/// extern crate serde_json;
///
/// use serde_json::{Result, value::RawValue};
///
/// #[derive(Deserialize)]
/// struct Input<'a> {
///     code: u32,
///     #[serde(borrow)]
///     payload: &'a RawValue,
/// }
///
/// #[derive(Serialize)]
/// struct Output<'a> {
///     info: (u32, &'a RawValue),
/// }
///
/// // Efficiently rearrange JSON input containing separate "code" and "payload"
/// // keys into a single "info" key holding an array of code and payload.
/// //
/// // This could be done equivalently using serde_json::Value as the type for
/// // payload, but &RawValue will perform netter because it does not require
/// // memory allocation. The correct range of bytes is borrowed from the input
/// // data and pasted verbatim into the output.
/// fn rearrange(input: &str) -> Result<String> {
///     let input: Input = serde_json::from_str(input)?;
///
///     let output = Output {
///         info: (input.code, input.payload),
///     };
///
///     serde_json::to_string(&output)
/// }
///
/// fn main() -> Result<()> {
///     let out = rearrange(r#" {"code": 200, "payload": {}} "#)?;
///
///     assert_eq!(out, r#"{"info":[200,{}]}"#);
///
///     Ok(())
/// }
/// ```
///
/// # Ownership
///
/// The typical usage of `RawValue` will be in the borrowed form:
///
/// ```
/// # #[macro_use]
/// # extern crate serde_derive;
/// # extern crate serde_json;
/// #
/// # use serde_json::value::RawValue;
/// #
/// #[derive(Deserialize)]
/// struct SomeStruct<'a> {
///     #[serde(borrow)]
///     raw_value: &'a RawValue,
/// }
/// #
/// # fn main() {}
/// ```
///
/// The borrowed form is suitable when deserializing through
/// [`serde_json::from_str`] and [`serde_json::from_slice`] which support
/// borrowing from the input data without memory allocation.
///
/// When deserializing through [`serde_json::from_reader`] you will need to use
/// the boxed form of `RawValue` instead. This is almost as efficient but
/// involves buffering the raw value from the I/O stream into memory.
///
/// [`serde_json::from_str`]: ../fn.from_str.html
/// [`serde_json::from_slice`]: ../fn.from_slice.html
/// [`serde_json::from_reader`]: ../fn.from_reader.html
///
/// ```
/// # #[macro_use]
/// # extern crate serde_derive;
/// # extern crate serde_json;
/// #
/// # use serde_json::value::RawValue;
/// #
/// #[derive(Deserialize)]
/// struct SomeStruct {
///     raw_value: Box<RawValue>,
/// }
/// #
/// # fn main() {}
/// ```
///
/// # Note
///
/// `RawValue` is only available if serde\_json is built with the `"raw_value"`
/// feature.
///
/// ```toml
/// [dependencies]
/// serde_json = { version = "1.0", features = ["raw_value"] }
/// ```
#[repr(C)]
pub struct RawValue {
    json: str,
}

impl RawValue {
    fn from_borrowed(json: &str) -> &Self {
        unsafe { mem::transmute::<&str, &RawValue>(json) }
    }

    fn from_owned(json: Box<str>) -> Box<Self> {
        unsafe { mem::transmute::<Box<str>, Box<RawValue>>(json) }
    }
}

impl Clone for Box<RawValue> {
    fn clone(&self) -> Self {
        (**self).to_owned()
    }
}

impl ToOwned for RawValue {
    type Owned = Box<RawValue>;

    fn to_owned(&self) -> Self::Owned {
        RawValue::from_owned(self.json.to_owned().into_boxed_str())
    }
}

impl Debug for RawValue {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_tuple("RawValue")
            .field(&format_args!("{}", &self.json))
            .finish()
    }
}

impl Display for RawValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.json)
    }
}

impl RawValue {
    /// Convert an owned `String` of JSON data to an owned `RawValue`.
    ///
    /// This function is equivalent to `serde_json::from_str::<Box<RawValue>>`
    /// except that we avoid an allocation and memcpy if both of the following
    /// are true:
    ///
    /// - the input has no leading or trailing whitespace, and
    /// - the input has capacity equal to its length.
    pub fn from_string(json: String) -> Result<Box<Self>, Error> {
        {
            let borrowed = ::from_str::<&Self>(&json)?;
            if borrowed.json.len() < json.len() {
                return Ok(borrowed.to_owned());
            }
        }
        Ok(Self::from_owned(json.into_boxed_str()))
    }

    /// Access the JSON text underlying a raw value.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate serde_derive;
    /// extern crate serde_json;
    ///
    /// use serde_json::{Result, value::RawValue};
    ///
    /// #[derive(Deserialize)]
    /// struct Response<'a> {
    ///     code: u32,
    ///     #[serde(borrow)]
    ///     payload: &'a RawValue,
    /// }
    ///
    /// fn process(input: &str) -> Result<()> {
    ///     let response: Response = serde_json::from_str(input)?;
    ///
    ///     let payload = response.payload.get();
    ///     if payload.starts_with('{') {
    ///         // handle a payload which is a JSON map
    ///     } else {
    ///         // handle any other type
    ///     }
    ///
    ///     Ok(())
    /// }
    ///
    /// fn main() -> Result<()> {
    ///     process(r#" {"code": 200, "payload": {}} "#)?;
    ///     Ok(())
    /// }
    /// ```
    pub fn get(&self) -> &str {
        &self.json
    }
}

pub const TOKEN: &'static str = "$serde_json::private::RawValue";

impl Serialize for RawValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut s = serializer.serialize_struct(TOKEN, 1)?;
        s.serialize_field(TOKEN, &self.json)?;
        s.end()
    }
}

impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct ReferenceVisitor;

        impl<'de> Visitor<'de> for ReferenceVisitor {
            type Value = &'de RawValue;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(ReferenceFromString)
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, ReferenceVisitor)
    }
}

impl<'de> Deserialize<'de> for Box<RawValue> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct BoxedVisitor;

        impl<'de> Visitor<'de> for BoxedVisitor {
            type Value = Box<RawValue>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(BoxedFromString)
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, BoxedVisitor)
    }
}

struct RawKey;

impl<'de> Deserialize<'de> for RawKey {
    fn deserialize<D>(deserializer: D) -> Result<RawKey, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct FieldVisitor;

        impl<'de> Visitor<'de> for FieldVisitor {
            type Value = ();

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("raw value")
            }

            fn visit_str<E>(self, s: &str) -> Result<(), E>
            where
                E: de::Error,
            {
                if s == TOKEN {
                    Ok(())
                } else {
                    Err(de::Error::custom("unexpected raw value"))
                }
            }
        }

        deserializer.deserialize_identifier(FieldVisitor)?;
        Ok(RawKey)
    }
}

pub struct ReferenceFromString;

impl<'de> DeserializeSeed<'de> for ReferenceFromString {
    type Value = &'de RawValue;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for ReferenceFromString {
    type Value = &'de RawValue;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue::from_borrowed(s))
    }
}

pub struct BoxedFromString;

impl<'de> DeserializeSeed<'de> for BoxedFromString {
    type Value = Box<RawValue>;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for BoxedFromString {
    type Value = Box<RawValue>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        self.visit_string(s.to_owned())
    }

    fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue::from_owned(s.into_boxed_str()))
    }
}

struct RawKeyDeserializer;

impl<'de> Deserializer<'de> for RawKeyDeserializer {
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_borrowed_str(TOKEN)
    }

    forward_to_deserialize_any! {
        bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq
        bytes byte_buf map struct option unit newtype_struct ignored_any
        unit_struct tuple_struct tuple enum identifier
    }
}

pub struct OwnedRawDeserializer {
    pub raw_value: Option<String>,
}

impl<'de> MapAccess<'de> for OwnedRawDeserializer {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(self.raw_value.take().unwrap().into_deserializer())
    }
}

pub struct BorrowedRawDeserializer<'de> {
    pub raw_value: Option<&'de str>,
}

impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap()))
    }
}
<|endoftext|>


<commit_before>//!
//! The API for communicating with devices.
//!
//! This API is provided as Traits to be implemented:
//!
//! - by the low-level layers of the FoxBox, including the adapters;
//! - by test suites and tools that need to simulate connected devices.
//!
//! In turn, this API is used to implement:
//!
//! - the public-facing REST and WebSocket API;
//! - the rules API (ThinkerBell).
//!
//!

use devices::*;
use requests::*;
use values::Value;

/// An error produced by one of the APIs in this module.
pub enum Error {
    /// There is no such node connected to the Foxbox, even indirectly.
    NoSuchNode(NodeId),

    /// There is no such service connected to the Foxbox, even indirectly.
    NoSuchService(ServiceId),

    /// Attempting to set a value with the wrong type
    TypeError,
}

/// An event during watching.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum WatchEvent {
    /// A new value is available.
    Value {
        /// The service that sent the value.
        from: ServiceId,

        /// The actual value.
        value: Value
    },

    /// The set of devices being watched has changed, typically either
    /// because a tag was edited or because a device was
    /// removed. Payload is the id of the device that was removed.
    InputRemoved(ServiceId),

    /// The set of devices being watched has changed, typically either
    /// because a tag was edited or because a device was
    /// added. Payload is the id of the device that was added.
    InputAdded(ServiceId),
}

/// The public API.
pub trait API {
    /// Get the metadata on nodes matching some conditions.
    ///
    /// A call to `API::get_nodes(vec![req1, req2, ...])` will return
    /// the metadata on all nodes matching _either_ `req1` or `req2`
    /// or ...
    ///
    /// # REST API
    ///
    /// `GET /api/v1/node/list`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to a `Vec<NodeRequest>`. See
    /// the implementation of `NodeRequest` for details.
    ///
    /// ### Example
    ///
    /// Request all doors in the entrance (tags `door`, `entrance`)
    /// that support output service `OpenClose`
    ///
    /// ```json
    /// [{
    ///   "tags": ["entrance", "door"],
    ///   "inputs": [
    ///     {
    ///       "kind": {
    ///         "Exactly": {
    ///           "OpenClose": []
    ///         }
    ///       }
    ///     }
    ///   ]
    /// }]
    /// ```
    ///
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing an array of `Node`. See the implementation
    /// of `Node` for details.
    ///
    /// ### Example
    ///
    /// ```json
    /// [{
    ///   "tags": ["entrance", "door", "somevendor"],
    ///   "id: "some-node-id",
    ///   "inputs": [],
    ///   "outputs": [
    ///     "tags": [...],
    ///     "id": "some-service-id",
    ///     "node": "some-node-id",
    ///     "last_seen": "some-date",
    ///     "mechanism": {
    ///       "Output":  {
    ///         "kind": {
    ///           "OnOff": []
    ///         },
    ///         "push": [5000],
    ///         "updated": "some-date",
    ///       }
    ///     }
    ///   ]
    /// }]
    /// ```
    fn get_nodes(&Vec<NodeRequest>) -> Vec<Node>;

    /// Label a set of nodes with a set of tags.
    ///
    /// A call to `API::put_node_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will label all the nodes matching _either_ `req1` or
    /// `req2` or ... with `tag1`, ... and return the number of nodes
    /// matching any of the requests.
    ///
    /// Some of the nodes may already be labelled with `tag1`, or
    /// `tag2`, ... They will not change state. They are counted in
    /// the resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if nodes
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/node/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<NodeRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn put_node_tag(set: &Vec<NodeRequest>, tags: &Vec<String>) -> usize;

    /// Remove a set of tags from a set of nodes.
    ///
    /// A call to `API::delete_node_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will remove from all the nodes matching _either_ `req1` or
    /// `req2` or ... all of the tags `tag1`, ... and return the number of nodes
    /// matching any of the requests.
    ///
    /// Some of the nodes may not be labelled with `tag1`, or `tag2`,
    /// ... They will not change state. They are counted in the
    /// resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if nodes
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/node/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<NodeRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn delete_node_tag(set: &Vec<NodeRequest>, tags: String) -> usize;

    /// Get a list of inputs matching some conditions
    ///
    /// # REST API
    ///
    /// `GET /api/v1/service/list`
    fn get_input_services(&Vec<InputRequest>) -> Vec<Service<Input>>;
    fn get_output_services(&Vec<OutputRequest>) -> Vec<Service<Output>>;

    /// Label a set of services with a set of tags.
    ///
    /// A call to `API::put_{input, output}_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will label all the services matching _either_ `req1` or
    /// `req2` or ... with `tag1`, ... and return the number of services
    /// matching any of the requests.
    ///
    /// Some of the services may already be labelled with `tag1`, or
    /// `tag2`, ... They will not change state. They are counted in
    /// the resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if services
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/service/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<InputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    /// or
    /// ```rust
    /// {
    ///   set: Vec<OutputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn put_input_tag(&Vec<InputRequest>, &Vec<String>) -> usize;
    fn put_output_tag(&Vec<OutputRequest>, &Vec<String>) -> usize;

    /// Remove a set of tags from a set of services.
    ///
    /// A call to `API::delete_{input, output}_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will remove from all the services matching _either_ `req1` or
    /// `req2` or ... all of the tags `tag1`, ... and return the number of services
    /// matching any of the requests.
    ///
    /// Some of the services may not be labelled with `tag1`, or `tag2`,
    /// ... They will not change state. They are counted in the
    /// resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if services
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/node/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<InputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    /// or
    /// ```rust
    /// {
    ///   set: Vec<OutputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn delete_input_tag(&Vec<InputRequest>, &Vec<String>) -> usize;
    fn delete_output_tag(&Vec<InputRequest>, &Vec<String>) -> usize;

    /// Read the latest value from a set of services
    ///
    /// # REST API
    ///
    /// `GET /api/v1/service/value`
    fn get_service_value(&Vec<InputRequest>) -> Vec<(ServiceId, Result<Value, Error>)>;

    /// Send one value to a set of services
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/service/value`
    fn put_service_value(&Vec<OutputRequest>, Value) -> Vec<(ServiceId, Result<(), Error>)>;

    /// Watch for any change
    ///
    /// # WebSocket API
    ///
    /// `/api/v1/service/watch`
    fn register_service_watch<F>(WatchOptions, cb: F) -> Self::WatchGuard
        where F: FnMut(WatchEvent) + Send + Sync;

    /// A value that causes a disconnection once it is dropped.
    type WatchGuard;
}

/// Options for watching changes in one or more services.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WatchOptions {
    /// The set of inputs to watch. Note that the actual inputs in the
    /// set may change over time.
    source: InputRequest,

    /// If `true`, watch as new values become available.
    should_watch_values: bool,

    /// If `true`, watch as nodes are connected/disconnected.
    should_watch_topology: bool,
}

impl WatchOptions {
    pub fn new() -> Self {
        WatchOptions {
            source: InputRequest::new(),
            should_watch_values: false,
            should_watch_topology: false,
        }
    }

    /// Restrict to input services in a given set.
    ///
    /// Also note that the actual input services that are part of the
    /// set may change with time, for instance if devices are added
    /// ore removed.  The request _is live_, i.e. the service watch
    /// will continue watching any input services that match `req`.
    pub fn with_inputs(self, req: InputRequest) -> Self {
        WatchOptions {
            source: self.source.and(req),
            ..self
        }
    }

    pub fn with_watch_values(self, should: bool) -> Self {
        WatchOptions {
            should_watch_values: should,
            ..self
        }
    }

    pub fn with_watch_topology(self, should: bool) -> Self {
        WatchOptions {
            should_watch_topology: should,
            ..self
        }
    }
}
<commit_msg>register_service_watch now accepts a vector<commit_after>//!
//! The API for communicating with devices.
//!
//! This API is provided as Traits to be implemented:
//!
//! - by the low-level layers of the FoxBox, including the adapters;
//! - by test suites and tools that need to simulate connected devices.
//!
//! In turn, this API is used to implement:
//!
//! - the public-facing REST and WebSocket API;
//! - the rules API (ThinkerBell).
//!
//!

use devices::*;
use requests::*;
use values::Value;

/// An error produced by one of the APIs in this module.
pub enum Error {
    /// There is no such node connected to the Foxbox, even indirectly.
    NoSuchNode(NodeId),

    /// There is no such service connected to the Foxbox, even indirectly.
    NoSuchService(ServiceId),

    /// Attempting to set a value with the wrong type
    TypeError,
}

/// An event during watching.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum WatchEvent {
    /// A new value is available.
    Value {
        /// The service that sent the value.
        from: ServiceId,

        /// The actual value.
        value: Value
    },

    /// The set of devices being watched has changed, typically either
    /// because a tag was edited or because a device was
    /// removed. Payload is the id of the device that was removed.
    InputRemoved(ServiceId),

    /// The set of devices being watched has changed, typically either
    /// because a tag was edited or because a device was
    /// added. Payload is the id of the device that was added.
    InputAdded(ServiceId),
}

/// The public API.
pub trait API {
    /// Get the metadata on nodes matching some conditions.
    ///
    /// A call to `API::get_nodes(vec![req1, req2, ...])` will return
    /// the metadata on all nodes matching _either_ `req1` or `req2`
    /// or ...
    ///
    /// # REST API
    ///
    /// `GET /api/v1/node/list`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to a `Vec<NodeRequest>`. See
    /// the implementation of `NodeRequest` for details.
    ///
    /// ### Example
    ///
    /// Request all doors in the entrance (tags `door`, `entrance`)
    /// that support output service `OpenClose`
    ///
    /// ```json
    /// [{
    ///   "tags": ["entrance", "door"],
    ///   "inputs": [
    ///     {
    ///       "kind": {
    ///         "Exactly": {
    ///           "OpenClose": []
    ///         }
    ///       }
    ///     }
    ///   ]
    /// }]
    /// ```
    ///
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing an array of `Node`. See the implementation
    /// of `Node` for details.
    ///
    /// ### Example
    ///
    /// ```json
    /// [{
    ///   "tags": ["entrance", "door", "somevendor"],
    ///   "id: "some-node-id",
    ///   "inputs": [],
    ///   "outputs": [
    ///     "tags": [...],
    ///     "id": "some-service-id",
    ///     "node": "some-node-id",
    ///     "last_seen": "some-date",
    ///     "mechanism": {
    ///       "Output":  {
    ///         "kind": {
    ///           "OnOff": []
    ///         },
    ///         "push": [5000],
    ///         "updated": "some-date",
    ///       }
    ///     }
    ///   ]
    /// }]
    /// ```
    fn get_nodes(&Vec<NodeRequest>) -> Vec<Node>;

    /// Label a set of nodes with a set of tags.
    ///
    /// A call to `API::put_node_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will label all the nodes matching _either_ `req1` or
    /// `req2` or ... with `tag1`, ... and return the number of nodes
    /// matching any of the requests.
    ///
    /// Some of the nodes may already be labelled with `tag1`, or
    /// `tag2`, ... They will not change state. They are counted in
    /// the resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if nodes
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/node/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<NodeRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn put_node_tag(set: &Vec<NodeRequest>, tags: &Vec<String>) -> usize;

    /// Remove a set of tags from a set of nodes.
    ///
    /// A call to `API::delete_node_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will remove from all the nodes matching _either_ `req1` or
    /// `req2` or ... all of the tags `tag1`, ... and return the number of nodes
    /// matching any of the requests.
    ///
    /// Some of the nodes may not be labelled with `tag1`, or `tag2`,
    /// ... They will not change state. They are counted in the
    /// resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if nodes
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/node/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<NodeRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn delete_node_tag(set: &Vec<NodeRequest>, tags: String) -> usize;

    /// Get a list of inputs matching some conditions
    ///
    /// # REST API
    ///
    /// `GET /api/v1/service/list`
    fn get_input_services(&Vec<InputRequest>) -> Vec<Service<Input>>;
    fn get_output_services(&Vec<OutputRequest>) -> Vec<Service<Output>>;

    /// Label a set of services with a set of tags.
    ///
    /// A call to `API::put_{input, output}_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will label all the services matching _either_ `req1` or
    /// `req2` or ... with `tag1`, ... and return the number of services
    /// matching any of the requests.
    ///
    /// Some of the services may already be labelled with `tag1`, or
    /// `tag2`, ... They will not change state. They are counted in
    /// the resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if services
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/service/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<InputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    /// or
    /// ```rust
    /// {
    ///   set: Vec<OutputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn put_input_tag(&Vec<InputRequest>, &Vec<String>) -> usize;
    fn put_output_tag(&Vec<OutputRequest>, &Vec<String>) -> usize;

    /// Remove a set of tags from a set of services.
    ///
    /// A call to `API::delete_{input, output}_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will remove from all the services matching _either_ `req1` or
    /// `req2` or ... all of the tags `tag1`, ... and return the number of services
    /// matching any of the requests.
    ///
    /// Some of the services may not be labelled with `tag1`, or `tag2`,
    /// ... They will not change state. They are counted in the
    /// resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if services
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/node/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<InputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    /// or
    /// ```rust
    /// {
    ///   set: Vec<OutputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn delete_input_tag(&Vec<InputRequest>, &Vec<String>) -> usize;
    fn delete_output_tag(&Vec<InputRequest>, &Vec<String>) -> usize;

    /// Read the latest value from a set of services
    ///
    /// # REST API
    ///
    /// `GET /api/v1/service/value`
    fn get_service_value(&Vec<InputRequest>) -> Vec<(ServiceId, Result<Value, Error>)>;

    /// Send one value to a set of services
    ///
    /// # REST API
    ///
    /// `PUT /api/v1/service/value`
    fn put_service_value(&Vec<OutputRequest>, Value) -> Vec<(ServiceId, Result<(), Error>)>;

    /// Watch for any change
    ///
    /// # WebSocket API
    ///
    /// `/api/v1/service/watch`
    fn register_service_watch<F>(Vec<WatchOptions>, cb: F) -> Self::WatchGuard
        where F: FnMut(WatchEvent) + Send + Sync;

    /// A value that causes a disconnection once it is dropped.
    type WatchGuard;
}

/// Options for watching changes in one or more services.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WatchOptions {
    /// The set of inputs to watch. Note that the actual inputs in the
    /// set may change over time.
    source: InputRequest,

    /// If `true`, watch as new values become available.
    should_watch_values: bool,

    /// If `true`, watch as nodes are connected/disconnected.
    should_watch_topology: bool,
}

impl WatchOptions {
    pub fn new() -> Self {
        WatchOptions {
            source: InputRequest::new(),
            should_watch_values: false,
            should_watch_topology: false,
        }
    }

    /// Restrict to input services in a given set.
    ///
    /// Also note that the actual input services that are part of the
    /// set may change with time, for instance if devices are added
    /// ore removed.  The request _is live_, i.e. the service watch
    /// will continue watching any input services that match `req`.
    pub fn with_inputs(self, req: InputRequest) -> Self {
        WatchOptions {
            source: self.source.and(req),
            ..self
        }
    }

    pub fn with_watch_values(self, should: bool) -> Self {
        WatchOptions {
            should_watch_values: should,
            ..self
        }
    }

    pub fn with_watch_topology(self, should: bool) -> Self {
        WatchOptions {
            should_watch_topology: should,
            ..self
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// 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
//
//    https://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.

use autocxx::include_cpp;
mod render_frame_host;
use autocxx::{c_int, PinMut};
use render_frame_host::RenderFrameHostForWebContents;
use render_frame_host::RenderFrameHostHandle;

include_cpp! {
    #include "fake-chromium-header.h"
    safety!(unsafe) // unsafety policy; see docs
    generate!("content::WebContents")
    generate!("content::RenderFrameHost")
    generate!("content::CreateParams")
    generate!("SimulateRendererShutdown")
    subclass!("content::WebContentsObserver",RenderFrameHostForWebContents)
}

use ffi::ToCppString;

fn main() {
    // Create some fake toy WebContents.
    let create_params = ffi::content::CreateParams::make_unique(&"silly-frame".into_cpp());
    let mut frame = ffi::content::WebContents::Create(&create_params);

    // This object is a memory-safe handle to a RenderFrameHost.
    // On creation, we pass it the WebContents, such that it can register
    // to be informed of the destruction of the RenderFrameHost.
    // It also happens to store a reference to that WebContents,
    // so the compiler will prove that this RenderFrameHostHandle
    // can't outlive the WebContents. That's nice. But currently
    // it stores an exclusive (a.k.a. mutable) reference, and we may
    // well want to relax that in future.
    // (If we are still using autocxx by then, this would be
    // https://github.com/google/autocxx/issues/622)
    let mut rfh_handle = RenderFrameHostHandle::from_id(c_int(3), c_int(0), frame.pin_mut());

    // We can directly call methods on the RFH.
    // (If this were a 'const' method, the `.pin_mut()` wouldn't be necessary).
    let frame_name = rfh_handle.pin_mut().GetFrameName();
    println!("Frame name is {}", frame_name.to_str().unwrap());

    {
        // We can also borrow the RFH and use Rust's borrow checker to ensure
        // no other code can do so. This also gives us a chance to explicitly
        // handle the case where the RFH was already destroyed, in case
        // we want to do something smarter than panicking.
        let mut rfh_borrowed = rfh_handle
            .try_borrow_mut()
            .expect("Oh! The RFH was already destroyed!");
        // Nobody else can borrow it during this time...
        //   let mut rfh_borrowed_again = rfh_handle.try_borrow_mut().unwrap();
        // Gives compile-time error "second mutable borrow occurs here..."
        let frame_name = rfh_borrowed.pin_mut().GetFrameName();
        println!("Frame name is {}", frame_name.to_str().unwrap());
        let frame_name = rfh_borrowed.pin_mut().GetFrameName();
        println!("Frame name is {}", frame_name.to_str().unwrap());

        // Supposing we end up calling some code deep in the Chrome C++
        // stack which destroys the RFH whilst it's still borrowed.
        // That will result in a runtime panic...
        //  ffi::SimulateRendererShutdown(c_int(0)); // would panic
    }

    // But let's assume we've now returned to the event loop.
    // None of the previous borrows still exist. It's perfectly OK to now
    // delete the RFH.
    ffi::SimulateRendererShutdown(c_int(0));
}
<commit_msg>Update main.rs<commit_after>// Copyright 2021 Google LLC
//
// 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
//
//    https://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.

use autocxx::include_cpp;
mod render_frame_host;
use autocxx::{c_int, PinMut};
use render_frame_host::RenderFrameHostForWebContents;
use render_frame_host::RenderFrameHostHandle;

include_cpp! {
    #include "fake-chromium-header.h"
    safety!(unsafe) // unsafety policy; see docs
    generate!("content::WebContents")
    generate!("content::RenderFrameHost")
    generate!("content::CreateParams")
    generate!("SimulateRendererShutdown")
    subclass!("content::WebContentsObserver",RenderFrameHostForWebContents)
}

use ffi::ToCppString;

fn main() {
    // Create some fake toy WebContents.
    let create_params = ffi::content::CreateParams::make_unique(&"silly-frame".into_cpp());
    let mut frame = ffi::content::WebContents::Create(&create_params);

    // This object is a memory-safe handle to a RenderFrameHost.
    // On creation, we pass it the WebContents, such that it can register
    // to be informed of the destruction of the RenderFrameHost.
    // It also happens to store a reference to that WebContents,
    // so the compiler will prove that this RenderFrameHostHandle
    // can't outlive the WebContents. That's nice. But currently
    // it stores an exclusive (a.k.a. mutable) reference, and we may
    // well want to relax that in future.
    // (This relates to https://github.com/google/autocxx/issues/622)
    let mut rfh_handle = RenderFrameHostHandle::from_id(c_int(3), c_int(0), frame.pin_mut());

    // We can directly call methods on the RFH.
    // (If this were a 'const' method, the `.pin_mut()` wouldn't be necessary).
    let frame_name = rfh_handle.pin_mut().GetFrameName();
    println!("Frame name is {}", frame_name.to_str().unwrap());

    {
        // We can also borrow the RFH and use Rust's borrow checker to ensure
        // no other code can do so. This also gives us a chance to explicitly
        // handle the case where the RFH was already destroyed, in case
        // we want to do something smarter than panicking.
        let mut rfh_borrowed = rfh_handle
            .try_borrow_mut()
            .expect("Oh! The RFH was already destroyed!");
        // Nobody else can borrow it during this time...
        //   let mut rfh_borrowed_again = rfh_handle.try_borrow_mut().unwrap();
        // Gives compile-time error "second mutable borrow occurs here..."
        let frame_name = rfh_borrowed.pin_mut().GetFrameName();
        println!("Frame name is {}", frame_name.to_str().unwrap());
        let frame_name = rfh_borrowed.pin_mut().GetFrameName();
        println!("Frame name is {}", frame_name.to_str().unwrap());

        // Supposing we end up calling some code deep in the Chrome C++
        // stack which destroys the RFH whilst it's still borrowed.
        // That will result in a runtime panic...
        //  ffi::SimulateRendererShutdown(c_int(0)); // would panic
    }

    // But let's assume we've now returned to the event loop.
    // None of the previous borrows still exist. It's perfectly OK to now
    // delete the RFH.
    ffi::SimulateRendererShutdown(c_int(0));
}
<|endoftext|>


<commit_before>use cocoa::base::id;
use std::convert::{From, Into};
use std::error::Error;
use std::fmt;
use std::mem;
use std::ops::{Deref, DerefMut};

/// A type which can be constructed from an Objective-C pointer.
pub trait FromRaw: Sized {
    /// Creates the object from the pointer. If there is a problem with the pointer,
    /// this function will return a FromRawError.
    fn from_raw(raw_pointer: id) -> Result<Self, FromRawError>;
}

/// A type which can be borrowed as an Objective-C pointer.
pub trait AsRaw {
    /// Get an immutable reference to the pointer.
    fn as_raw(&self) -> &id;

    /// Get a mutable reference to the pointer.
    fn as_raw_mut(&mut self) -> &mut id;
}

/// A type which can be converted into an Objective-C pointer.
pub trait IntoRaw {
    /// Get the underlying pointer to the object. Releases ownership.
    fn into_raw(self) -> id;
}

impl FromRaw for id {
    fn from_raw(ptr: id) -> Result<Self, FromRawError> {
        Ok(ptr)
    }
}

impl AsRaw for id {
    fn as_raw(&self) -> &id {
        self
    }

    fn as_raw_mut(&mut self) -> &mut id {
        self
    }
}

impl IntoRaw for id {
    fn into_raw(self) -> id {
        self
    }
}

/// An Objective-C pointer which sends the `release` message to its object on drop
#[derive(Eq, PartialEq)]
pub struct StrongPtr(id);

impl fmt::Debug for StrongPtr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "StrongPtr({:p})", self.0)
    }
}

impl fmt::Display for StrongPtr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Pointer::fmt(self, f)
    }
}

impl fmt::Pointer for StrongPtr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:p}", self.0)
    }
}

impl Deref for StrongPtr {
    type Target = id;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for StrongPtr {
    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
        &mut self.0
    }
}

impl FromRaw for StrongPtr {
    fn from_raw(ptr: id) -> Result<Self, FromRawError> {
        Ok(From::from(ptr))
    }
}

impl AsRaw for StrongPtr {
    fn as_raw(&self) -> &id {
        self.deref()
    }

    fn as_raw_mut(&mut self) -> &mut id {
        self.deref_mut()
    }
}

impl IntoRaw for StrongPtr {
    fn into_raw(self) -> id {
        self.into()
    }
}

impl Drop for StrongPtr {
    fn drop(&mut self) {
        unsafe { msg_send![self.0, release] }
    }
}

impl From<id> for StrongPtr {
    fn from(ptr: id) -> Self {
        StrongPtr(ptr)
    }
}

impl Into<id> for StrongPtr {
    /// Get the underlying pointer from `Self`. The pointer will no longer be released on drop.
    fn into(self) -> id {
        let self_ptr = self.0;
        mem::forget(self);
        self_ptr
    }
}

/// Represents errors which may occur when constructing an object from a pointer.
#[derive(Clone, Debug)]
pub enum FromRawError {
    /// The pointer was nil.
    NilPointer,

    /// The pointer does not point to either:
    ///
    /// * an object of the correct type,
    /// * an object which does not have a certain base class,
    /// * an object which does not implement a particular protocol.
    WrongPointerType
}

macro_rules! impl_from_into_raw {
    ($wrapper_type:ident, of protocol $protocol:expr) => (
        impl $crate::FromRaw for $wrapper_type {
            fn from_raw(raw_pointer: id) -> Result<Self, $crate::FromRawError> {
                use $crate::internal::conforms_to_protocol;
                use cocoa::base::nil;
                if raw_pointer == nil {
                    Err($crate::FromRawError::NilPointer)
                } else if !conforms_to_protocol(raw_pointer, $protocol) {
                    Err($crate::FromRawError::WrongPointerType)
                } else {
                    Ok($wrapper_type(From::from(raw_pointer)))
                }
            }
        }

        impl $crate::AsRaw for $wrapper_type {
            fn as_raw(&self) -> &id {
                &self.0
            }

            fn as_raw_mut(&mut self) -> &mut id {
                &mut self.0
            }
        }

        impl $crate::IntoRaw for $wrapper_type {
            fn into_raw(self) -> id {
                self.0.into()
            }
        }
    );

    ($wrapper_type:ident, of class $class:expr) => (
        impl $crate::FromRaw for $wrapper_type {
            fn from_raw(raw_pointer: id) -> Result<Self, $crate::FromRawError> {
                use $crate::internal::is_kind_of_class;
                use cocoa::base::nil;
                if raw_pointer == nil {
                    Err($crate::FromRawError::NilPointer)
                } else if !is_kind_of_class(raw_pointer, $class) {
                    Err($crate::FromRawError::WrongPointerType)
                } else {
                    Ok($wrapper_type(From::from(raw_pointer)))
                }
            }
        }

        impl $crate::AsRaw for $wrapper_type {
            fn as_raw(&self) -> &id {
                &self.0
            }

            fn as_raw_mut(&mut self) -> &mut id {
                &mut self.0
            }
        }

        impl $crate::IntoRaw for $wrapper_type {
            fn into_raw(self) -> id {
                self.0.into()
            }
        }
    )
}

impl fmt::Display for FromRawError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let descr = match *self {
            FromRawError::NilPointer => "FromRawError::NilPointer",
            FromRawError::WrongPointerType => "FromRawError::WrongPointerType",
        };
        write!(f, "{}", descr)
    }
}

impl Error for FromRawError {
    fn description(&self) -> &str {
        match *self {
            FromRawError::NilPointer => "Attempted to create an object from nil",
            FromRawError::WrongPointerType => "The object pointer is not of the correct class",
        }
    }
}
<commit_msg>Impl clone for StrongPtr ; it lets you retain the underlying pointer<commit_after>use cocoa::base::id;
use std::convert::{From, Into};
use std::error::Error;
use std::fmt;
use std::mem;
use std::ops::{Deref, DerefMut};

/// A type which can be constructed from an Objective-C pointer.
pub trait FromRaw: Sized {
    /// Creates the object from the pointer. If there is a problem with the pointer,
    /// this function will return a FromRawError.
    fn from_raw(raw_pointer: id) -> Result<Self, FromRawError>;
}

/// A type which can be borrowed as an Objective-C pointer.
pub trait AsRaw {
    /// Get an immutable reference to the pointer.
    fn as_raw(&self) -> &id;

    /// Get a mutable reference to the pointer.
    fn as_raw_mut(&mut self) -> &mut id;
}

/// A type which can be converted into an Objective-C pointer.
pub trait IntoRaw {
    /// Get the underlying pointer to the object. Releases ownership.
    fn into_raw(self) -> id;
}

impl FromRaw for id {
    fn from_raw(ptr: id) -> Result<Self, FromRawError> {
        Ok(ptr)
    }
}

impl AsRaw for id {
    fn as_raw(&self) -> &id {
        self
    }

    fn as_raw_mut(&mut self) -> &mut id {
        self
    }
}

impl IntoRaw for id {
    fn into_raw(self) -> id {
        self
    }
}

/// An Objective-C pointer which sends the `release` message to its object on drop
#[derive(Eq, PartialEq)]
pub struct StrongPtr(id);

impl fmt::Debug for StrongPtr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "StrongPtr({:p})", self.0)
    }
}

impl fmt::Display for StrongPtr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Pointer::fmt(self, f)
    }
}

impl fmt::Pointer for StrongPtr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:p}", self.0)
    }
}

impl Deref for StrongPtr {
    type Target = id;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for StrongPtr {
    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
        &mut self.0
    }
}

impl FromRaw for StrongPtr {
    fn from_raw(ptr: id) -> Result<Self, FromRawError> {
        Ok(From::from(ptr))
    }
}

impl AsRaw for StrongPtr {
    fn as_raw(&self) -> &id {
        self.deref()
    }

    fn as_raw_mut(&mut self) -> &mut id {
        self.deref_mut()
    }
}

impl IntoRaw for StrongPtr {
    fn into_raw(self) -> id {
        self.into()
    }
}

impl Clone for StrongPtr {
    fn clone(&self) -> Self {
        let retained = unsafe { msg_send![self.0, retain] };
        StrongPtr(retained)
    }
}

impl Drop for StrongPtr {
    fn drop(&mut self) {
        unsafe { msg_send![self.0, release] }
    }
}

impl From<id> for StrongPtr {
    fn from(ptr: id) -> Self {
        StrongPtr(ptr)
    }
}

impl Into<id> for StrongPtr {
    /// Get the underlying pointer from `Self`. The pointer will no longer be released on drop.
    fn into(self) -> id {
        let self_ptr = self.0;
        mem::forget(self);
        self_ptr
    }
}

/// Represents errors which may occur when constructing an object from a pointer.
#[derive(Clone, Debug)]
pub enum FromRawError {
    /// The pointer was nil.
    NilPointer,

    /// The pointer does not point to either:
    ///
    /// * an object of the correct type,
    /// * an object which does not have a certain base class,
    /// * an object which does not implement a particular protocol.
    WrongPointerType
}

macro_rules! impl_from_into_raw {
    ($wrapper_type:ident, of protocol $protocol:expr) => (
        impl $crate::FromRaw for $wrapper_type {
            fn from_raw(raw_pointer: id) -> Result<Self, $crate::FromRawError> {
                use $crate::internal::conforms_to_protocol;
                use cocoa::base::nil;
                if raw_pointer == nil {
                    Err($crate::FromRawError::NilPointer)
                } else if !conforms_to_protocol(raw_pointer, $protocol) {
                    Err($crate::FromRawError::WrongPointerType)
                } else {
                    Ok($wrapper_type(From::from(raw_pointer)))
                }
            }
        }

        impl $crate::AsRaw for $wrapper_type {
            fn as_raw(&self) -> &id {
                &self.0
            }

            fn as_raw_mut(&mut self) -> &mut id {
                &mut self.0
            }
        }

        impl $crate::IntoRaw for $wrapper_type {
            fn into_raw(self) -> id {
                self.0.into()
            }
        }
    );

    ($wrapper_type:ident, of class $class:expr) => (
        impl $crate::FromRaw for $wrapper_type {
            fn from_raw(raw_pointer: id) -> Result<Self, $crate::FromRawError> {
                use $crate::internal::is_kind_of_class;
                use cocoa::base::nil;
                if raw_pointer == nil {
                    Err($crate::FromRawError::NilPointer)
                } else if !is_kind_of_class(raw_pointer, $class) {
                    Err($crate::FromRawError::WrongPointerType)
                } else {
                    Ok($wrapper_type(From::from(raw_pointer)))
                }
            }
        }

        impl $crate::AsRaw for $wrapper_type {
            fn as_raw(&self) -> &id {
                &self.0
            }

            fn as_raw_mut(&mut self) -> &mut id {
                &mut self.0
            }
        }

        impl $crate::IntoRaw for $wrapper_type {
            fn into_raw(self) -> id {
                self.0.into()
            }
        }
    )
}

impl fmt::Display for FromRawError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let descr = match *self {
            FromRawError::NilPointer => "FromRawError::NilPointer",
            FromRawError::WrongPointerType => "FromRawError::WrongPointerType",
        };
        write!(f, "{}", descr)
    }
}

impl Error for FromRawError {
    fn description(&self) -> &str {
        match *self {
            FromRawError::NilPointer => "Attempted to create an object from nil",
            FromRawError::WrongPointerType => "The object pointer is not of the correct class",
        }
    }
}
<|endoftext|>