<commit_before>//! PUT /_matrix/client/r0/directory/room/:room_alias

#![allow(clippy::exhaustive_structs)]

use bytes::BufMut;
use http::{header::CONTENT_TYPE, method::Method};
use ruma_api::{
    error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, MatrixError, ServerError},
    AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest,
    OutgoingResponse, SendAccessToken,
};
use ruma_identifiers::{RoomAliasId, RoomId};
use ruma_serde::Outgoing;
use serde::{Deserialize, Serialize};

/// A request to create a new room alias.
#[derive(Debug)]
pub struct Request {
    pub room_id: Box<RoomId>,         // body
    pub room_alias: Box<RoomAliasId>, // path
}

impl Outgoing for Request {
    type Incoming = Self;
}

const METADATA: Metadata = Metadata {
    description: "Add an alias to a room.",
    method: Method::PUT,
    name: "create_alias",
    path: "/_matrix/client/r0/directory/room/:room_alias",
    rate_limited: false,
    authentication: AuthScheme::None,
};

impl OutgoingRequest for Request {
    type EndpointError = MatrixError;
    type IncomingResponse = Response;

    const METADATA: Metadata = METADATA;

    fn try_into_http_request<T: Default + BufMut>(
        self,
        base_url: &str,
        _access_token: SendAccessToken<'_>,
    ) -> Result<http::Request<T>, IntoHttpError> {
        let url = (base_url.to_owned() + METADATA.path)
            .replace(":room_alias", &self.room_alias.to_string());

        let request_body = RequestBody { room_id: self.room_id };

        let http_request = http::Request::builder()
            .method(METADATA.method)
            .uri(url)
            .body(ruma_serde::json_to_buf(&request_body)?)
            // this cannot fail because we don't give user-supplied data to any of the
            // builder methods
            .unwrap();

        Ok(http_request)
    }
}

impl IncomingRequest for Request {
    type EndpointError = MatrixError;
    type OutgoingResponse = Response;

    const METADATA: Metadata = METADATA;

    fn try_from_http_request<B, S>(
        request: http::Request<B>,
        path_args: &[S],
    ) -> Result<Self, FromHttpRequestError> where B: AsRef<[u8]>, S: AsRef<str> {
        let (room_alias,) = serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
            _,
            serde::de::value::Error,
        >::new(
            path_args.iter().map(::std::convert::AsRef::as_ref),
        ))?;

        let request_body: RequestBody = serde_json::from_slice(request.body().as_ref())?;

        Ok(Request { room_id: request_body.room_id, room_alias })
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct RequestBody {
    room_id: Box<RoomId>,
}

/// The response to a request to create a new room alias.
#[derive(Clone, Copy, Debug)]
pub struct Response;

impl Outgoing for Response {
    type Incoming = Self;
}

impl IncomingResponse for Response {
    type EndpointError = MatrixError;

    fn try_from_http_response<T: AsRef<[u8]>>(
        http_response: http::Response<T>,
    ) -> Result<Self, FromHttpResponseError<MatrixError>> {
        if http_response.status().as_u16() < 400 {
            Ok(Response)
        } else {
            Err(FromHttpResponseError::Http(ServerError::Known(
                <MatrixError as EndpointError>::try_from_http_response(http_response)?,
            )))
        }
    }
}

impl OutgoingResponse for Response {
    fn try_into_http_response<T: Default + BufMut>(
        self,
    ) -> Result<http::Response<T>, IntoHttpError> {
        let response = http::Response::builder()
            .header(CONTENT_TYPE, "application/json")
            .body(ruma_serde::slice_to_buf(b"{}"))
            .unwrap();

        Ok(response)
    }
}
<commit_msg>api: Fix inconsistent formatting<commit_after>//! PUT /_matrix/client/r0/directory/room/:room_alias

#![allow(clippy::exhaustive_structs)]

use bytes::BufMut;
use http::{header::CONTENT_TYPE, method::Method};
use ruma_api::{
    error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, MatrixError, ServerError},
    AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest,
    OutgoingResponse, SendAccessToken,
};
use ruma_identifiers::{RoomAliasId, RoomId};
use ruma_serde::Outgoing;
use serde::{Deserialize, Serialize};

/// A request to create a new room alias.
#[derive(Debug)]
pub struct Request {
    pub room_id: Box<RoomId>,         // body
    pub room_alias: Box<RoomAliasId>, // path
}

impl Outgoing for Request {
    type Incoming = Self;
}

const METADATA: Metadata = Metadata {
    description: "Add an alias to a room.",
    method: Method::PUT,
    name: "create_alias",
    path: "/_matrix/client/r0/directory/room/:room_alias",
    rate_limited: false,
    authentication: AuthScheme::None,
};

impl OutgoingRequest for Request {
    type EndpointError = MatrixError;
    type IncomingResponse = Response;

    const METADATA: Metadata = METADATA;

    fn try_into_http_request<T: Default + BufMut>(
        self,
        base_url: &str,
        _access_token: SendAccessToken<'_>,
    ) -> Result<http::Request<T>, IntoHttpError> {
        let url = (base_url.to_owned() + METADATA.path)
            .replace(":room_alias", &self.room_alias.to_string());

        let request_body = RequestBody { room_id: self.room_id };

        let http_request = http::Request::builder()
            .method(METADATA.method)
            .uri(url)
            .body(ruma_serde::json_to_buf(&request_body)?)
            // this cannot fail because we don't give user-supplied data to any of the
            // builder methods
            .unwrap();

        Ok(http_request)
    }
}

impl IncomingRequest for Request {
    type EndpointError = MatrixError;
    type OutgoingResponse = Response;

    const METADATA: Metadata = METADATA;

    fn try_from_http_request<B, S>(
        request: http::Request<B>,
        path_args: &[S],
    ) -> Result<Self, FromHttpRequestError>
    where
        B: AsRef<[u8]>,
        S: AsRef<str>,
    {
        let (room_alias,) = serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
            _,
            serde::de::value::Error,
        >::new(
            path_args.iter().map(::std::convert::AsRef::as_ref),
        ))?;

        let request_body: RequestBody = serde_json::from_slice(request.body().as_ref())?;

        Ok(Request { room_id: request_body.room_id, room_alias })
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct RequestBody {
    room_id: Box<RoomId>,
}

/// The response to a request to create a new room alias.
#[derive(Clone, Copy, Debug)]
pub struct Response;

impl Outgoing for Response {
    type Incoming = Self;
}

impl IncomingResponse for Response {
    type EndpointError = MatrixError;

    fn try_from_http_response<T: AsRef<[u8]>>(
        http_response: http::Response<T>,
    ) -> Result<Self, FromHttpResponseError<MatrixError>> {
        if http_response.status().as_u16() < 400 {
            Ok(Response)
        } else {
            Err(FromHttpResponseError::Http(ServerError::Known(
                <MatrixError as EndpointError>::try_from_http_response(http_response)?,
            )))
        }
    }
}

impl OutgoingResponse for Response {
    fn try_into_http_response<T: Default + BufMut>(
        self,
    ) -> Result<http::Response<T>, IntoHttpError> {
        let response = http::Response::builder()
            .header(CONTENT_TYPE, "application/json")
            .body(ruma_serde::slice_to_buf(b"{}"))
            .unwrap();

        Ok(response)
    }
}
<|endoftext|>


<commit_before>use cairo;
use gio;
use glib;
use librsvg;
use rsvg_internals;

use gio::MemoryInputStreamExt;
use glib::Cast;

use librsvg::{CairoRenderer, Loader, SvgHandle};

use std::fs::File;
use std::io::BufReader;
use std::path::Path;

use self::rsvg_internals::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};

mod compare_surfaces;

use crate::compare_surfaces::{compare_surfaces, BufferDiff};

fn load_svg(input: &'static [u8]) -> SvgHandle {
    let stream = gio::MemoryInputStream::new();
    stream.add_bytes(&glib::Bytes::from_static(input));

    Loader::new()
        .read_stream(&stream.upcast(), None, None)
        .unwrap()
}

#[test]
fn render_to_viewport_with_different_size() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
  <rect x="8" y="8" width="32" height="32" fill="blue"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 128, 128).unwrap();

    {
        let cr = cairo::Context::new(&output);
        renderer
            .render_element_to_viewport(
                &cr,
                None,
                &cairo::Rectangle {
                    x: 0.0,
                    y: 0.0,
                    width: 128.0,
                    height: 128.0,
                },
            )
            .unwrap();
    }

    let output_surf = SharedImageSurface::new(output, SurfaceType::SRgb).unwrap();

    let fixture_path = Path::new("tests/fixtures/rect-48x48-rendered-128x128.png");
    let mut fixture_file = BufReader::new(File::open(fixture_path).unwrap());

    let expected = cairo::ImageSurface::create_from_png(&mut fixture_file).unwrap();
    let expected_surf = SharedImageSurface::new(expected, SurfaceType::SRgb).unwrap();

    let diff = compare_surfaces(&output_surf, &expected_surf).unwrap();

    match diff {
        BufferDiff::DifferentSizes => unreachable!("surfaces should be of the same size"),

        BufferDiff::Diff(diff) => {
            assert_eq!(diff.num_pixels_changed, 0);
        }
    }
}

#[test]
fn render_to_offsetted_viewport() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
  <rect x="8" y="8" width="32" height="32" fill="blue"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();

    {
        let cr = cairo::Context::new(&output);
        renderer
            .render_element_to_viewport(
                &cr,
                None,
                &cairo::Rectangle {
                    x: 10.0,
                    y: 20.0,
                    width: 48.0,
                    height: 48.0,
                },
            )
            .unwrap();
    }

    let mut output_file = File::create(Path::new("output.png")).unwrap();
    output.write_to_png(&mut output_file).unwrap();

    let output_surf = SharedImageSurface::new(output, SurfaceType::SRgb).unwrap();

    let fixture_path = Path::new("tests/fixtures/rect-48x48-offsetted-100x100-10x20.png");
    let mut fixture_file = BufReader::new(File::open(fixture_path).unwrap());

    let expected = cairo::ImageSurface::create_from_png(&mut fixture_file).unwrap();
    let expected_surf = SharedImageSurface::new(expected, SurfaceType::SRgb).unwrap();

    let diff = compare_surfaces(&output_surf, &expected_surf).unwrap();

    match diff {
        BufferDiff::DifferentSizes => unreachable!("surfaces should be of the same size"),

        BufferDiff::Diff(diff) => {
            let surf = diff.surface.into_image_surface().unwrap();
            let mut output_file = File::create(Path::new("diff.png")).unwrap();
            surf.write_to_png(&mut output_file).unwrap();

            assert_eq!(diff.num_pixels_changed, 0);

        }
    }
}
<commit_msg>wip: test render_to_viewport_with_transform()<commit_after>use cairo;
use gio;
use glib;
use librsvg;
use rsvg_internals;

use gio::MemoryInputStreamExt;
use glib::Cast;

use librsvg::{CairoRenderer, Loader, SvgHandle};

use std::fs::File;
use std::io::BufReader;
use std::path::Path;

use self::rsvg_internals::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};

mod compare_surfaces;

use crate::compare_surfaces::{compare_surfaces, BufferDiff};

fn load_svg(input: &'static [u8]) -> SvgHandle {
    let stream = gio::MemoryInputStream::new();
    stream.add_bytes(&glib::Bytes::from_static(input));

    Loader::new()
        .read_stream(&stream.upcast(), None, None)
        .unwrap()
}

#[test]
fn render_to_viewport_with_different_size() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
  <rect x="8" y="8" width="32" height="32" fill="blue"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 128, 128).unwrap();

    {
        let cr = cairo::Context::new(&output);
        renderer
            .render_element_to_viewport(
                &cr,
                None,
                &cairo::Rectangle {
                    x: 0.0,
                    y: 0.0,
                    width: 128.0,
                    height: 128.0,
                },
            )
            .unwrap();
    }

    let output_surf = SharedImageSurface::new(output, SurfaceType::SRgb).unwrap();

    let fixture_path = Path::new("tests/fixtures/rect-48x48-rendered-128x128.png");
    let mut fixture_file = BufReader::new(File::open(fixture_path).unwrap());

    let expected = cairo::ImageSurface::create_from_png(&mut fixture_file).unwrap();
    let expected_surf = SharedImageSurface::new(expected, SurfaceType::SRgb).unwrap();

    let diff = compare_surfaces(&output_surf, &expected_surf).unwrap();

    match diff {
        BufferDiff::DifferentSizes => unreachable!("surfaces should be of the same size"),

        BufferDiff::Diff(diff) => {
            assert_eq!(diff.num_pixels_changed, 0);
        }
    }
}

#[test]
fn render_to_offsetted_viewport() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
  <rect x="8" y="8" width="32" height="32" fill="blue"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();

    {
        let cr = cairo::Context::new(&output);
        renderer
            .render_element_to_viewport(
                &cr,
                None,
                &cairo::Rectangle {
                    x: 10.0,
                    y: 20.0,
                    width: 48.0,
                    height: 48.0,
                },
            )
            .unwrap();
    }

    let mut output_file = File::create(Path::new("output.png")).unwrap();
    output.write_to_png(&mut output_file).unwrap();

    let output_surf = SharedImageSurface::new(output, SurfaceType::SRgb).unwrap();

    let fixture_path = Path::new("tests/fixtures/rect-48x48-offsetted-100x100-10x20.png");
    let mut fixture_file = BufReader::new(File::open(fixture_path).unwrap());

    let expected = cairo::ImageSurface::create_from_png(&mut fixture_file).unwrap();
    let expected_surf = SharedImageSurface::new(expected, SurfaceType::SRgb).unwrap();

    let diff = compare_surfaces(&output_surf, &expected_surf).unwrap();

    match diff {
        BufferDiff::DifferentSizes => unreachable!("surfaces should be of the same size"),

        BufferDiff::Diff(diff) => {
            let surf = diff.surface.into_image_surface().unwrap();
            let mut output_file = File::create(Path::new("diff.png")).unwrap();
            surf.write_to_png(&mut output_file).unwrap();

            assert_eq!(diff.num_pixels_changed, 0);

        }
    }
}

#[test]
fn render_to_viewport_with_transform() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
  <g transform="translate(-10, -10)">
    <path fill="blue" d="M 18 18 l 32 0 l 0 32 l -32 0 z"/>
  </g>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();

    {
        let cr = cairo::Context::new(&output);
        cr.translate(10.0, 20.0);
        renderer
            .render_element_to_viewport(
                &cr,
                None,
                &cairo::Rectangle {
                    x: 0.0,
                    y: 0.0,
                    width: 48.0,
                    height: 48.0,
                },
            )
            .unwrap();
    }

    let mut output_file = File::create(Path::new("output.png")).unwrap();
    output.write_to_png(&mut output_file).unwrap();

    let output_surf = SharedImageSurface::new(output, SurfaceType::SRgb).unwrap();

    let fixture_path = Path::new("tests/fixtures/rect-48x48-offsetted-100x100-10x20.png");
    let mut fixture_file = BufReader::new(File::open(fixture_path).unwrap());

    let expected = cairo::ImageSurface::create_from_png(&mut fixture_file).unwrap();
    let expected_surf = SharedImageSurface::new(expected, SurfaceType::SRgb).unwrap();

    let diff = compare_surfaces(&output_surf, &expected_surf).unwrap();

    match diff {
        BufferDiff::DifferentSizes => unreachable!("surfaces should be of the same size"),

        BufferDiff::Diff(diff) => {
            let surf = diff.surface.into_image_surface().unwrap();
            let mut output_file = File::create(Path::new("diff.png")).unwrap();
            surf.write_to_png(&mut output_file).unwrap();

            assert_eq!(diff.num_pixels_changed, 0);

        }
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::cmp;
use std::iter;
pub use super::heap::Heap;

#[derive(Debug)]
pub struct BinomialHeap<T> {
	trees: Vec<Option<Link<T>>>,
}

type Link<T> = Arc<Node<T>>;

#[derive(Clone, Hash, Debug)]
struct Node<T> {
	elem: T,
	children: Vec<Link<T>>,
}

fn link<T: Ord + Clone>(a: &Link<T>, b: &Link<T>) -> Link<T> {
	let (smaller, bigger) = if a.elem < b.elem { (a, b) } else { (b, a) };
	let mut new_children = Vec::with_capacity(smaller.children.len() + 1);
	new_children.extend(smaller.children.iter().cloned());
	new_children.push(bigger.clone());
	Arc::new(Node { elem: smaller.elem.clone(), children: new_children })
}

impl <T: Ord + Clone> Heap<T> for BinomialHeap<T> {
	fn empty() -> Self {
		BinomialHeap { trees: Vec::new() }
	}

	fn is_empty(&self) -> bool {
		self.trees.is_empty()
	}

	fn insert(&self, item: T) -> Self {
		BinomialHeap { trees: vec![
			Some(Arc::new(Node { elem: item, children: Vec::new()}))
		]}.merge(self)
	}

	fn merge<'a>(&self, other: &Self) -> Self {
		let cap = cmp::max(self.trees.len(), other.trees.len()) + 1;
		let mut result: Vec<Option<Link<T>>> = Vec::with_capacity(cap);
		let mut c: Option<Link<T>> = None;

		// Create infinite interator of Option<&Link<T>>
		let iter_self = self.trees.iter().map(Option::as_ref).chain(iter::repeat(None));
		let iter_other = other.trees.iter().map(Option::as_ref).chain(iter::repeat(None));
		// Link trees of equal rank, carrying the added trees up a rank
		for ((a, b), _) in iter_self.zip(iter_other).zip(0..cap) {
			result.push( match (a, b, c.take()) {
				(None, None, None) => None,
				(Some(x), None, None) => Some(x.clone()),
				(None, Some(y), None) => Some(y.clone()),
				(None, None, Some(z)) => Some(z.clone()),
				(Some(x), Some(y), None) => { c = Some(link(x,y)); None }
				(Some(x), None, Some(z)) => { c = Some(link(x,&z)); None }
				(None, Some(y), Some(z)) => { c = Some(link(y,&z)); None }
				(Some(x), Some(y), Some(z)) => { c = Some(link(x,y)); Some(z) }
			});
		}
		if let Some(&None) = result.last() {
			result.pop();
		}
		BinomialHeap { trees: result }
	}

	fn find_min(&self) -> Option<T> {
		match min_index(&self.trees) {
			None => None,
			Some(index) => Some(self.trees[index].as_ref().unwrap().elem.clone())
		}
	}

	fn delete_min(&self) -> Self {
		match min_index(&self.trees) {
			None => Heap::empty(),
			Some(index) => {
				let mut old_trees = self.trees.clone();
				let taken = old_trees[index].take().unwrap();
				let old = BinomialHeap { trees: old_trees };
				old.merge(&BinomialHeap { trees: taken.children.iter().cloned().map(Some).collect() })
			}
		}
	}
}

// Utility function to find the smallest index in the heap
fn min_index<T: Ord>(vec: &Vec<Option<Link<T>>>) -> Option<usize> {
	let mut i = vec.iter()                                           // Iterator<&Option<Link<T>>>
	               .enumerate()                                      // Iterator<(usize, &Option<Link<T>>)
	               .map(|(i, x)| x.as_ref().map(|v| (i, &(v.elem)))) // Iterator<Option<(usize, &T)>>
	               .filter(Option::is_some).map(Option::unwrap);     // Iterator<(usize, &T)>

	// Grab first item if it exists
	let first = i.next();
	let (ix, init) = match first {
		None => return None,
		Some(x) => x,
	};

	// Compare all the values, find the smallest, and return its index
	Some(i.fold((ix, init), |(ai, a), (bi, b)| if &a < &b { (ai, a) } else { (bi, b) }).0)
}

#[cfg(test)]
mod test {
	use super::{ BinomialHeap, Heap };

	#[test]
	fn basics() {
		let heap: BinomialHeap<i32> = Heap::empty();
		assert_eq!(heap.find_min(), None);

		let heap = heap.insert(2).insert(1).insert(3);
		assert_eq!(heap.find_min(), Some(1));

		let heap = heap.delete_min();
		assert_eq!(heap.find_min(), Some(2));

		let heap = heap.delete_min();
		assert_eq!(heap.find_min(), Some(3));

		let heap = heap.delete_min();
		assert_eq!(heap.find_min(), None);

		let heap = heap.delete_min();
		assert_eq!(heap.find_min(), None);
	}

	#[test]
	fn thread_safety() {
		fn is_send<T: Send>(){}
		is_send::<BinomialHeap<i32>>();

		fn is_sync<T: Sync>(){}
		is_sync::<BinomialHeap<i32>>();

		assert!(true);
	}

	use super::super::heap::properties;

	#[test]
	fn heap_quickchecks() {
		properties::sorting::<i32, BinomialHeap<i32>>();
	}
}
<commit_msg>Fixed None for binomial heap<commit_after>use std::sync::Arc;
use std::cmp;
use std::iter;
pub use super::heap::Heap;

#[derive(Debug)]
pub struct BinomialHeap<T> {
	trees: Vec<Option<Link<T>>>,
}

type Link<T> = Arc<Node<T>>;

#[derive(Clone, Hash, Debug)]
struct Node<T> {
	elem: T,
	children: Vec<Link<T>>,
}

fn link<T: Ord + Clone>(a: &Link<T>, b: &Link<T>) -> Link<T> {
	let (smaller, bigger) = if a.elem < b.elem { (a, b) } else { (b, a) };
	let mut new_children = Vec::with_capacity(smaller.children.len() + 1);
	new_children.extend(smaller.children.iter().cloned());
	new_children.push(bigger.clone());
	Arc::new(Node { elem: smaller.elem.clone(), children: new_children })
}

impl <T: Ord + Clone> Heap<T> for BinomialHeap<T> {
	fn empty() -> Self {
		BinomialHeap { trees: Vec::new() }
	}

	fn is_empty(&self) -> bool {
		self.trees.is_empty()
	}

	fn insert(&self, item: T) -> Self {
		BinomialHeap { trees: vec![
			Some(Arc::new(Node { elem: item, children: Vec::new()}))
		]}.merge(self)
	}

	fn merge<'a>(&self, other: &Self) -> Self {
		let cap = cmp::max(self.trees.len(), other.trees.len()) + 1;
		let mut result: Vec<Option<Link<T>>> = Vec::with_capacity(cap);
		let mut c: Option<Link<T>> = None;

		// Create infinite interator of Option<&Link<T>>
		let iter_self = self.trees.iter().map(Option::as_ref).chain(iter::repeat(None));
		let iter_other = other.trees.iter().map(Option::as_ref).chain(iter::repeat(None));
		// Link trees of equal rank, carrying the added trees up a rank
		for ((a, b), _) in iter_self.zip(iter_other).zip(0..cap) {
			result.push( match (a, b, c.take()) {
				(None, None, None) => None,
				(Some(x), None, None) => Some(x.clone()),
				(None, Some(y), None) => Some(y.clone()),
				(None, None, Some(z)) => Some(z.clone()),
				(Some(x), Some(y), None) => { c = Some(link(x,y)); None }
				(Some(x), None, Some(z)) => { c = Some(link(x,&z)); None }
				(None, Some(y), Some(z)) => { c = Some(link(y,&z)); None }
				(Some(x), Some(y), Some(z)) => { c = Some(link(x,y)); Some(z) }
			});
		}
		while let Some(&None) = result.last() {
			result.pop();
		}
		BinomialHeap { trees: result }
	}

	fn find_min(&self) -> Option<T> {
		match min_index(&self.trees) {
			None => None,
			Some(index) => Some(self.trees[index].as_ref().unwrap().elem.clone())
		}
	}

	fn delete_min(&self) -> Self {
		match min_index(&self.trees) {
			None => Heap::empty(),
			Some(index) => {
				let mut old_trees = self.trees.clone();
				let taken = old_trees[index].take().unwrap();
				let old = BinomialHeap { trees: old_trees };
				old.merge(&BinomialHeap { trees: taken.children.iter().cloned().map(Some).collect() })
			}
		}
	}
}

// Utility function to find the smallest index in the heap
fn min_index<T: Ord>(vec: &Vec<Option<Link<T>>>) -> Option<usize> {
	let mut i = vec.iter()                                           // Iterator<&Option<Link<T>>>
	               .enumerate()                                      // Iterator<(usize, &Option<Link<T>>)
	               .map(|(i, x)| x.as_ref().map(|v| (i, &(v.elem)))) // Iterator<Option<(usize, &T)>>
	               .filter(Option::is_some).map(Option::unwrap);     // Iterator<(usize, &T)>

	// Grab first item if it exists
	let first = i.next();
	let (ix, init) = match first {
		None => return None,
		Some(x) => x,
	};

	// Compare all the values, find the smallest, and return its index
	Some(i.fold((ix, init), |(ai, a), (bi, b)| if &a < &b { (ai, a) } else { (bi, b) }).0)
}

#[cfg(test)]
mod test {
	use super::{ BinomialHeap, Heap };

	#[test]
	fn basics() {
		let heap: BinomialHeap<i32> = Heap::empty();
		assert_eq!(heap.find_min(), None);

		let heap = heap.insert(2).insert(1).insert(3);
		assert_eq!(heap.find_min(), Some(1));

		let heap = heap.delete_min();
		assert_eq!(heap.find_min(), Some(2));

		let heap = heap.delete_min();
		assert_eq!(heap.find_min(), Some(3));

		let heap = heap.delete_min();
		assert_eq!(heap.find_min(), None);

		let heap = heap.delete_min();
		assert_eq!(heap.find_min(), None);
	}

	#[test]
	fn thread_safety() {
		fn is_send<T: Send>(){}
		is_send::<BinomialHeap<i32>>();

		fn is_sync<T: Sync>(){}
		is_sync::<BinomialHeap<i32>>();

		assert!(true);
	}

	use super::super::heap::properties;

	#[test]
	fn heap_quickchecks() {
		properties::sorting::<i32, BinomialHeap<i32>>();
	}
}
<|endoftext|>


<commit_before>use std::io::{File, Open, ReadWrite};
use std::io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    file: Option<File>,
}

pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, ReadWrite) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);

    // Create a new buffer using the loaded data, file, and other defaults.
    Ok(Buffer{ data: data, file: Some(file) })
}

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

    #[test]
    fn from_file_loads_file_into_buffer() {
        match from_file(&Path::new("tests/sample/file")) {
            Ok(buffer) => assert_eq!(buffer.data.to_string(), "it works!\n"),
            Err(error) => panic!(error),
        }
    }
}
<commit_msg>Update IO references to use old_io module.<commit_after>use std::old_io::{File, Open, ReadWrite};
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    file: Option<File>,
}

pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, ReadWrite) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);

    // Create a new buffer using the loaded data, file, and other defaults.
    Ok(Buffer{ data: data, file: Some(file) })
}

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

    #[test]
    fn from_file_loads_file_into_buffer() {
        match from_file(&Path::new("tests/sample/file")) {
            Ok(buffer) => assert_eq!(buffer.data.to_string(), "it works!\n"),
            Err(error) => panic!(error),
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add test: Test moving entry with writing to it before and after moving<commit_after><|endoftext|>


<commit_before>//! Implementation of transport-agnostic Core Event Loop.

extern crate tokio_core;

use std::thread;
use std::sync::{mpsc, Arc};

use futures::{self, Future};
pub use self::tokio_core::reactor::Remote;

use {MetaIoHandler, Metadata};

/// EventLoop for all request to `jsonrpc-core`.
/// NOTE: This is more-less temporary solution until we find a good way of integrating with event loops of particular
/// transports.
pub struct RpcEventLoop {
	remote: Remote,
	handle: RpcEventLoopHandle,
}

impl RpcEventLoop {
	/// Spawns a new thread with `EventLoop` with given handler.
	pub fn spawn() -> Self {
		let (stop, stopped) = futures::oneshot();
		let (tx, rx) = mpsc::channel();
		let handle = thread::spawn(move || {
			let mut el = tokio_core::reactor::Core::new().expect("Creating an event loop should not fail.");
			tx.send(el.remote()).expect("Rx is blocking upper thread.");
			let _ = el.run(futures::empty().select(stopped));
		});
		let remote = rx.recv().expect("tx is transfered to a newly spawned thread.");

		RpcEventLoop {
			remote: remote,
			handle: RpcEventLoopHandle {
				close: Some(stop),
				handle: Some(handle),
			},
		}
	}

	/// Returns an RPC handler to process requests.
	pub fn handler<M: Metadata>(&self, handler: Arc<MetaIoHandler<M>>) -> RpcHandler<M> {
		RpcHandler::new(handler, self.remote.clone())
	}

	/// Returns event loop remote.
	pub fn remote(&self) -> Remote {
		self.remote.clone()
	}
}

/// A handle to running event loop. Dropping the handle will cause event loop to finish.
pub struct RpcEventLoopHandle {
	close: Option<futures::Complete<()>>,
	handle: Option<thread::JoinHandle<()>>
}

impl From<RpcEventLoop> for RpcEventLoopHandle {
	fn from(el: RpcEventLoop) -> Self {
		el.handle
	}
}

impl Drop for RpcEventLoopHandle {
	fn drop(&mut self) {
		self.close.take().map(|v| v.complete(()));
	}
}

impl RpcEventLoopHandle {
	/// Blocks current thread and waits until the event loop is finished.
	pub fn wait(mut self) -> thread::Result<()> {
		self.handle.take().unwrap().join()
	}

	/// Finishes this event loop.
	pub fn close(mut self) {
		self.close.take().unwrap().complete(())
	}
}

/// RPC Core Event Loop Handler.
#[derive(Clone)]
pub struct RpcHandler<M: Metadata = ()> {
	/// RPC Handler
	handler: Arc<MetaIoHandler<M>>,
	/// Event Loop Remote
	remote: Remote,
}

impl<M: Metadata> RpcHandler<M> {
	/// Creates new `RpcHandler` for existing `EventLoop`
	pub fn new(handler: Arc<MetaIoHandler<M>>, remote: Remote) -> Self {
		RpcHandler {
			handler: handler,
			remote: remote,
		}
	}

	/// Handles the request and returns to a closure response when it's ready.
	pub fn handle_request<F>(&self, request: &str, metadata: M, on_response: F) where
		F: Fn(Option<String>) + Send + 'static
	{
		let future = self.handler.handle_request(request, metadata);
		self.remote.spawn(|_| future.map(on_response))
	}

	/// Handles the request synchronously (not recommended)
	pub fn handle_request_sync(&self, request: &str, metadata: M) -> Option<String> {
		let (tx, rx) = mpsc::channel();
		self.handle_request(request, metadata, move |res| {
			tx.send(res).unwrap();
		});
		rx.recv().unwrap()
	}
}

<commit_msg>Fixing reactor support for middlewares (#36)<commit_after>//! Implementation of transport-agnostic Core Event Loop.

extern crate tokio_core;

use std::thread;
use std::sync::{mpsc, Arc};

use futures::{self, Future};
pub use self::tokio_core::reactor::Remote;

use {MetaIoHandler, Metadata, Middleware, NoopMiddleware};

/// EventLoop for all request to `jsonrpc-core`.
/// NOTE: This is more-less temporary solution until we find a good way of integrating with event loops of particular
/// transports.
pub struct RpcEventLoop {
	remote: Remote,
	handle: RpcEventLoopHandle,
}

impl RpcEventLoop {
	/// Spawns a new thread with `EventLoop` with given handler.
	pub fn spawn() -> Self {
		let (stop, stopped) = futures::oneshot();
		let (tx, rx) = mpsc::channel();
		let handle = thread::spawn(move || {
			let mut el = tokio_core::reactor::Core::new().expect("Creating an event loop should not fail.");
			tx.send(el.remote()).expect("Rx is blocking upper thread.");
			let _ = el.run(futures::empty().select(stopped));
		});
		let remote = rx.recv().expect("tx is transfered to a newly spawned thread.");

		RpcEventLoop {
			remote: remote,
			handle: RpcEventLoopHandle {
				close: Some(stop),
				handle: Some(handle),
			},
		}
	}

	/// Returns an RPC handler to process requests.
	pub fn handler<M: Metadata, S: Middleware<M>>(&self, handler: Arc<MetaIoHandler<M, S>>) -> RpcHandler<M, S> {
		RpcHandler::new(handler, self.remote.clone())
	}

	/// Returns event loop remote.
	pub fn remote(&self) -> Remote {
		self.remote.clone()
	}
}

/// A handle to running event loop. Dropping the handle will cause event loop to finish.
pub struct RpcEventLoopHandle {
	close: Option<futures::Complete<()>>,
	handle: Option<thread::JoinHandle<()>>
}

impl From<RpcEventLoop> for RpcEventLoopHandle {
	fn from(el: RpcEventLoop) -> Self {
		el.handle
	}
}

impl Drop for RpcEventLoopHandle {
	fn drop(&mut self) {
		self.close.take().map(|v| v.complete(()));
	}
}

impl RpcEventLoopHandle {
	/// Blocks current thread and waits until the event loop is finished.
	pub fn wait(mut self) -> thread::Result<()> {
		self.handle.take().unwrap().join()
	}

	/// Finishes this event loop.
	pub fn close(mut self) {
		self.close.take().unwrap().complete(())
	}
}

/// RPC Core Event Loop Handler.
pub struct RpcHandler<M: Metadata = (), S: Middleware<M> = NoopMiddleware> {
	/// RPC Handler
	handler: Arc<MetaIoHandler<M, S>>,
	/// Event Loop Remote
	remote: Remote,
}

impl<M: Metadata, S: Middleware<M>> Clone for RpcHandler<M, S> {
	fn clone(&self) -> Self {
		RpcHandler {
			handler: self.handler.clone(),
			remote: self.remote.clone(),
		}
	}
}

impl<M: Metadata, S: Middleware<M>> RpcHandler<M, S> {
	/// Creates new `RpcHandler` for existing `EventLoop`
	pub fn new(handler: Arc<MetaIoHandler<M, S>>, remote: Remote) -> Self {
		RpcHandler {
			handler: handler,
			remote: remote,
		}
	}

	/// Handles the request and returns to a closure response when it's ready.
	pub fn handle_request<F>(&self, request: &str, metadata: M, on_response: F) where
		F: Fn(Option<String>) + Send + 'static
	{
		let future = self.handler.handle_request(request, metadata);
		self.remote.spawn(|_| future.map(on_response))
	}

	/// Handles the request synchronously (not recommended)
	pub fn handle_request_sync(&self, request: &str, metadata: M) -> Option<String> {
		let (tx, rx) = mpsc::channel();
		self.handle_request(request, metadata, move |res| {
			tx.send(res).unwrap();
		});
		rx.recv().unwrap()
	}
}

<|endoftext|>


<commit_before>import platform::osmain;
import geometry::*;
import comm::*;
import image::base::image;
import dl = layout::display_list;
import azure::*;
import azure::bindgen::*;
import libc::size_t;
import text::text_run::text_run;

enum Msg {
    RenderMsg(dl::display_list),
    ExitMsg(comm::chan<()>)
}

#[doc = "
The interface used to by the renderer to aquire draw targets for
each rendered frame and submit them to be drawn to the display
"]
iface sink {
    fn begin_drawing(next_dt: chan<AzDrawTargetRef>);
    fn draw(next_dt: chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef);
}

fn renderer<S: sink send copy>(sink: S) -> chan<Msg> {
    task::spawn_listener::<Msg> {|po|
        listen {
            |draw_target_ch|
            #debug("renderer: beginning rendering loop");
            sink.begin_drawing(draw_target_ch);

            loop {
                alt po.recv() {
                  RenderMsg(display_list) {
                    #debug("renderer: got render request");
                    let draw_target = draw_target_ch.recv();
                    #debug("renderer: rendering");
                    clear(draw_target);
                    draw_display_list(draw_target, display_list);
                    #debug("renderer: returning surface");
                    sink.draw(draw_target_ch, draw_target);
                  }
                  ExitMsg(response_ch) {
                    response_ch.send(());
                    break;
                  }
                }
            }
        }
    }
}

impl to_float for u8 {
    fn to_float() -> float {
        (self as float) / 255f
    }
}

fn draw_display_list(
    draw_target: AzDrawTargetRef,
    display_list: dl::display_list
) {
    for display_list.each {|item|
        #debug["drawing %?", item];

        alt item.item_type {
          dl::display_item_solid_color(r, g, b) {
            draw_solid_color(draw_target, item, r, g, b);
          }
          dl::display_item_image(image) {
            draw_image(draw_target, item, image);
          }
          dl::display_item_text(text_run) {
            draw_text(draw_target, item, text_run);
          }
          dl::padding(*) {
            fail "should never see padding";
          }
        }
    }
}

fn draw_solid_color(draw_target: AzDrawTargetRef, item: dl::display_item,
                    r: u8, g: u8, b: u8) {
    let bounds = copy (*item).bounds;

    let red_color = {
        r: r.to_float() as AzFloat,
        g: g.to_float() as AzFloat,
        b: b.to_float() as AzFloat,
        a: 1f as AzFloat
    };
    let red_pattern = AzCreateColorPattern(ptr::addr_of(red_color));

    let red_rect = {
        x: au_to_px(bounds.origin.x) as AzFloat,
        y: au_to_px(bounds.origin.y) as AzFloat,
        width: au_to_px(bounds.size.width) as AzFloat,
        height: au_to_px(bounds.size.height) as AzFloat
    };
    AzDrawTargetFillRect(
        draw_target,
        ptr::addr_of(red_rect),
        unsafe { unsafe::reinterpret_cast(red_pattern) }
    );

    AzReleaseColorPattern(red_pattern);
}

fn draw_image(draw_target: AzDrawTargetRef, item: dl::display_item,
              -image: ~image) {
    // FIXME: This is hideously inefficient.

    let bounds = copy (*item).bounds;

    if (image.depth < 3u) {
        #debug("TODO: can't draw images with depth less than 3 yet");
        ret;
    }

    let stride = image.width * image.depth;
    for uint::range(0u, image.height) {
        |y|
        for uint::range(0u, image.width) {
            |x|
            let color = {
                r: image.data[y * stride + x * image.depth].to_float()
                    as AzFloat,
                g: image.data[y * stride + x * image.depth + 1u].to_float()
                    as AzFloat,
                b: image.data[y * stride + x * image.depth + 2u].to_float()
                    as AzFloat,
                a: 1f as AzFloat
            };
            let pattern = AzCreateColorPattern(ptr::addr_of(color));

            let pixel_rect = {
                x: (au_to_px(bounds.origin.x) + (x as int)) as AzFloat,
                y: (au_to_px(bounds.origin.y) + (y as int)) as AzFloat,
                width: 1f as AzFloat,
                height: 1f as AzFloat
            };
            AzDrawTargetFillRect(
                draw_target,
                ptr::addr_of(pixel_rect),
                unsafe { unsafe::reinterpret_cast(pattern) }
            );

            AzReleaseColorPattern(pattern);
        }
    }
}

fn draw_text(draw_target: AzDrawTargetRef, item: dl::display_item, text_run: text_run) {

    import ptr::{addr_of, null};
    import vec::unsafe::to_ptr;
    import libc::types::common::c99::{uint16_t, uint32_t};
    import geom::point::Point2D;
    import text::font::{font, create_test_font};
    import azure::{AzNativeFont, AzFloat, AZ_NATIVE_FONT_CAIRO_FONT_FACE};
    import azure::bindgen::{AzCreateScaledFontWithCairo,
                            AzReleaseScaledFont,
                            AzCreateColorPattern,
                            AzReleaseColorPattern};

    let bounds = copy (*item).bounds;
    let font = create_test_font();

    let nfont: AzNativeFont = {
        mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE,
        mFont: null()
    };

    let azfont = AzCreateScaledFontWithCairo(addr_of(nfont), 1f as AzFloat, font.cairo_font);
    assert azfont.is_not_null();

    let color = {
        r: 0f as AzFloat,
        g: 0f as AzFloat,
        b: 0f as AzFloat,
        a: 1f as AzFloat
    };
    let pattern = AzCreateColorPattern(addr_of(color));
    assert pattern.is_not_null();

    let options: AzDrawOptions = {
        mAlpha: 1f as AzFloat,
        fields: 0 as uint16_t
    };

    let mut origin = Point2D(bounds.origin.x, bounds.origin.y.add(bounds.size.height));
    let azglyphs = text_run.glyphs.map { |glyph|
        let azglyph: AzGlyph = {
            mIndex: glyph.codepoint as uint32_t,
            mPosition: {
                x: au_to_px(origin.x.add(glyph.pos.offset.x)) as AzFloat,
                y: au_to_px(origin.y.add(glyph.pos.offset.y)) as AzFloat
            }
        };
        origin = Point2D(origin.x.add(glyph.pos.advance.x),
                         origin.y.add(glyph.pos.advance.y));
        azglyph
    };

    let glyphbuf: AzGlyphBuffer = unsafe {{
        mGlyphs: to_ptr(azglyphs),
        mNumGlyphs: azglyphs.len() as uint32_t
    }};

    AzDrawTargetFillGlyphs(draw_target, azfont, addr_of(glyphbuf),
                           pattern, addr_of(options), null());

    AzReleaseColorPattern(pattern);
    AzReleaseScaledFont(azfont);
}

#[cfg(target_os = "macos")]
mod cocoa {
    use cocoa;
    export cocoa;
}

#[cfg(target_os = "macos")]
fn draw_some_text(draw_target: AzDrawTargetRef) {

    import az = azure;
    import azbg = azure::bindgen;
    import ft = azure::freetype;
    import ftbg = azure::freetype::bindgen;
    import cairo = azure::cairo;
    import cairobg = azure::cairo::bindgen;
    //import cairoftbg = azure::cairo_ft::bindgen;
    import libc::types::common::c99::uint16_t;
    import libc::types::common::c99::uint32_t;
    import cocoa::cocoa;
    import cocoa::cg::CGDataProviderRef;
    import cocoa::cg::cg::{
        CGDataProviderCreateWithData,
        CGDataProviderRelease,
        CGFontCreateWithDataProvider
    };
    import cairoqbg = azure::cairo_quartz::bindgen;

    /*impl methods for ft::FT_Error {
        fn for_sure() { assert self == 0 as ft::FT_Error }
    }*/

    //let library: ft::FT_Library = ptr::null();
    //ftbg::FT_Init_FreeType(ptr::addr_of(library)).for_sure();

    let fontbin = text::font::test_font_bin();

    let fontprov = vec::as_buf(fontbin) {|buf|
        CGDataProviderCreateWithData(ptr::null(),
                                     unsafe { unsafe::reinterpret_cast(buf) },
                                     fontbin.len() as size_t,
                                     ptr::null())
    };

    let cgfont = CGFontCreateWithDataProvider(fontprov);

    /*let face: ft::FT_Face = ptr::null();
    vec::as_buf(fontbin) {|buf|
        ftbg::FT_New_Memory_Face(library, buf, fontbin.len() as ft::FT_Long,
                                 0, ptr::addr_of(face)).for_sure();
    }

    unsafe {
        #debug("num_glyphs %?", (*face).num_glyphs);
        #debug("family_name %?",
               str::unsafe::from_c_str((*face).family_name));
        #debug("style_name %?",
               str::unsafe::from_c_str((*face).style_name));
    }

    let cface = cairoftbg::cairo_ft_font_face_create_for_ft_face(
        face, 0 as libc::c_int);
    assert cface.is_not_null();
    */

    let cface = cairoqbg::cairo_quartz_font_face_create_for_cgfont(cgfont);

    let fontmatrix: cairo::cairo_matrix_t = {
        xx: 0 as libc::c_double,
        yx: 0 as libc::c_double,
        xy: 0 as libc::c_double,
        yy: 0 as libc::c_double,
        x0: 0 as libc::c_double,
        y0: 0 as libc::c_double
    };
    cairobg::cairo_matrix_init_identity(ptr::addr_of(fontmatrix));
    cairobg::cairo_matrix_scale(ptr::addr_of(fontmatrix), 300f as libc::c_double, 400f as libc::c_double);

    let idmatrix: cairo::cairo_matrix_t = {
        xx: 0 as libc::c_double,
        yx: 0 as libc::c_double,
        xy: 0 as libc::c_double,
        yy: 0 as libc::c_double,
        x0: 0 as libc::c_double,
        y0: 0 as libc::c_double
    };
    cairobg::cairo_matrix_init_identity(ptr::addr_of(idmatrix));

    let options = cairobg::cairo_font_options_create();

    let cfont = cairobg::cairo_scaled_font_create(
        cface, ptr::addr_of(fontmatrix), ptr::addr_of(idmatrix), options);
    assert cfont.is_not_null();
    assert cairobg::cairo_scaled_font_status(cfont) == 0 as cairo::cairo_status_t;
    cairobg::cairo_font_face_destroy(cface);
    cairobg::cairo_font_options_destroy(options);

    let nfont: az::AzNativeFont = {
        mType: az::AZ_NATIVE_FONT_CAIRO_FONT_FACE,
        mFont: ptr::null()
    };

    let azfont = azbg::AzCreateScaledFontWithCairo(
        ptr::addr_of(nfont),
        20f as az::AzFloat,
        cfont);
    assert azfont.is_not_null();
    cairobg::cairo_scaled_font_destroy(cfont);

    let color = {
        r: 1f as AzFloat,
        g: 0f as AzFloat,
        b: 0.5f as AzFloat,
        a: 1f as AzFloat
    };
    let pattern = AzCreateColorPattern(ptr::addr_of(color));
    assert pattern.is_not_null();

    let options: az::AzDrawOptions = {
        mAlpha: 1f as az::AzFloat,
        fields: 0 as uint16_t
    };

    let glyphidx = 40 as uint32_t;//ftbg::FT_Get_Char_Index(face, 'w' as ft::FT_ULong);

    #debug("glyph: %?", glyphidx);

    for int::range(0, 3) {|i|
        let glyphs: [az::AzGlyph] = [
            {
                mIndex: glyphidx,
                mPosition: {
                    x: (100 + 250 * i) as az::AzFloat,
                    y: 600 as az::AzFloat
                }
            }
        ];

        let glyphbuf: az::AzGlyphBuffer = unsafe {{
            mGlyphs: vec::unsafe::to_ptr(glyphs),
            mNumGlyphs: 1 as uint32_t
        }};

        AzDrawTargetFillGlyphs(draw_target,
                               azfont,
                               ptr::addr_of(glyphbuf),
                               pattern,
                               ptr::addr_of(options),
                               ptr::null());
    }

    azbg::AzReleaseColorPattern(pattern);
    azbg::AzReleaseScaledFont(azfont);
    //ftbg::FT_Done_Face(face).for_sure();
    //ftbg::FT_Done_FreeType(library).for_sure();
    CGDataProviderRelease(fontprov);
}

#[cfg(target_os = "linux")]
fn draw_some_text(draw_target: AzDrawTargetRef) {

    import az = azure;
    import azbg = azure::bindgen;
    import ft = azure::freetype;
    import ftbg = azure::freetype::bindgen;
    import cairo = azure::cairo;
    import cairobg = azure::cairo::bindgen;
    import cairoftbg = azure::cairo_ft::bindgen;
    import libc::types::common::c99::uint16_t;
    import libc::types::common::c99::uint32_t;
    import azure::freetype::FT_Long;

    impl methods for ft::FT_Error {
        fn for_sure() { assert self == 0 as ft::FT_Error }
    }

    let library: ft::FT_Library = ptr::null();
    ftbg::FT_Init_FreeType(ptr::addr_of(library)).for_sure();

    let fontbin = text::font::test_font_bin();

    let face: ft::FT_Face = ptr::null();
    vec::as_buf(fontbin) {|buf|
        ftbg::FT_New_Memory_Face(library, buf, fontbin.len() as ft::FT_Long,
                                 0 as FT_Long, ptr::addr_of(face)).for_sure();
    }

    unsafe {
        #debug("num_glyphs %?", (*face).num_glyphs);
        #debug("family_name %?",
               str::unsafe::from_c_str((*face).family_name));
        #debug("style_name %?",
               str::unsafe::from_c_str((*face).style_name));
    }

    let cface = cairoftbg::cairo_ft_font_face_create_for_ft_face(
        face, 0 as libc::c_int);
    assert cface.is_not_null();

    let fontmatrix: cairo::cairo_matrix_t = {
        xx: 0 as libc::c_double,
        yx: 0 as libc::c_double,
        xy: 0 as libc::c_double,
        yy: 0 as libc::c_double,
        x0: 0 as libc::c_double,
        y0: 0 as libc::c_double
    };
    cairobg::cairo_matrix_init_identity(ptr::addr_of(fontmatrix));
    cairobg::cairo_matrix_scale(ptr::addr_of(fontmatrix), 300f as libc::c_double, 400f as libc::c_double);

    let idmatrix: cairo::cairo_matrix_t = {
        xx: 0 as libc::c_double,
        yx: 0 as libc::c_double,
        xy: 0 as libc::c_double,
        yy: 0 as libc::c_double,
        x0: 0 as libc::c_double,
        y0: 0 as libc::c_double
    };
    cairobg::cairo_matrix_init_identity(ptr::addr_of(idmatrix));

    let options = cairobg::cairo_font_options_create();

    let cfont = cairobg::cairo_scaled_font_create(
        cface, ptr::addr_of(fontmatrix), ptr::addr_of(idmatrix), options);
    assert cfont.is_not_null();
    assert cairobg::cairo_scaled_font_status(cfont) == 0 as cairo::cairo_status_t;
    cairobg::cairo_font_face_destroy(cface);
    cairobg::cairo_font_options_destroy(options);

    let nfont: az::AzNativeFont = {
        mType: az::AZ_NATIVE_FONT_CAIRO_FONT_FACE,
        mFont: ptr::null()
    };

    let azfont = azbg::AzCreateScaledFontWithCairo(
        ptr::addr_of(nfont),
        20f as az::AzFloat,
        cfont);
    assert azfont.is_not_null();
    cairobg::cairo_scaled_font_destroy(cfont);

    let color = {
        r: 1f as AzFloat,
        g: 0f as AzFloat,
        b: 0.5f as AzFloat,
        a: 1f as AzFloat
    };
    let pattern = AzCreateColorPattern(ptr::addr_of(color));
    assert pattern.is_not_null();

    let options: az::AzDrawOptions = {
        mAlpha: 1f as az::AzFloat,
        fields: 0 as uint16_t
    };

    let glyphidx = ftbg::FT_Get_Char_Index(face, 'w' as ft::FT_ULong);

    #debug("glyph: %?", glyphidx);

    for int::range(0, 3) {|i|
        let glyphs: [az::AzGlyph] = [
            {
                mIndex: glyphidx,
                mPosition: {
                    x: (100 + 250 * i) as az::AzFloat,
                    y: 600 as az::AzFloat
                }
            }
        ];

        let glyphbuf: az::AzGlyphBuffer = unsafe {{
            mGlyphs: vec::unsafe::to_ptr(glyphs),
            mNumGlyphs: 1 as uint32_t
        }};

        AzDrawTargetFillGlyphs(draw_target,
                               azfont,
                               ptr::addr_of(glyphbuf),
                               pattern,
                               ptr::addr_of(options),
                               ptr::null());
    }

    azbg::AzReleaseColorPattern(pattern);
    azbg::AzReleaseScaledFont(azfont);
    ftbg::FT_Done_Face(face).for_sure();
    ftbg::FT_Done_FreeType(library).for_sure();
}

fn clear(draw_target: AzDrawTargetRef) {

    let black_color = {
        r: 0f as AzFloat,
        g: 0f as AzFloat,
        b: 0f as AzFloat,
        a: 1f as AzFloat
    };
    let black_pattern = AzCreateColorPattern(ptr::addr_of(black_color));

    let black_rect = {
        x: 0 as AzFloat,
        y: 0 as AzFloat,
        width: 800 as AzFloat,
        height: 600 as AzFloat,
    };

    AzDrawTargetFillRect(
        draw_target,
        ptr::addr_of(black_rect),
        unsafe { unsafe::reinterpret_cast(black_pattern) }
    );

    AzReleaseColorPattern(black_pattern);
}
<commit_msg>Remove old font test code<commit_after>import platform::osmain;
import geometry::*;
import comm::*;
import image::base::image;
import dl = layout::display_list;
import azure::*;
import azure::bindgen::*;
import libc::size_t;
import text::text_run::text_run;

enum Msg {
    RenderMsg(dl::display_list),
    ExitMsg(comm::chan<()>)
}

#[doc = "
The interface used to by the renderer to aquire draw targets for
each rendered frame and submit them to be drawn to the display
"]
iface sink {
    fn begin_drawing(next_dt: chan<AzDrawTargetRef>);
    fn draw(next_dt: chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef);
}

fn renderer<S: sink send copy>(sink: S) -> chan<Msg> {
    task::spawn_listener::<Msg> {|po|
        listen {
            |draw_target_ch|
            #debug("renderer: beginning rendering loop");
            sink.begin_drawing(draw_target_ch);

            loop {
                alt po.recv() {
                  RenderMsg(display_list) {
                    #debug("renderer: got render request");
                    let draw_target = draw_target_ch.recv();
                    #debug("renderer: rendering");
                    clear(draw_target);
                    draw_display_list(draw_target, display_list);
                    #debug("renderer: returning surface");
                    sink.draw(draw_target_ch, draw_target);
                  }
                  ExitMsg(response_ch) {
                    response_ch.send(());
                    break;
                  }
                }
            }
        }
    }
}

impl to_float for u8 {
    fn to_float() -> float {
        (self as float) / 255f
    }
}

fn draw_display_list(
    draw_target: AzDrawTargetRef,
    display_list: dl::display_list
) {
    for display_list.each {|item|
        #debug["drawing %?", item];

        alt item.item_type {
          dl::display_item_solid_color(r, g, b) {
            draw_solid_color(draw_target, item, r, g, b);
          }
          dl::display_item_image(image) {
            draw_image(draw_target, item, image);
          }
          dl::display_item_text(text_run) {
            draw_text(draw_target, item, text_run);
          }
          dl::padding(*) {
            fail "should never see padding";
          }
        }
    }
}

fn draw_solid_color(draw_target: AzDrawTargetRef, item: dl::display_item,
                    r: u8, g: u8, b: u8) {
    let bounds = copy (*item).bounds;

    let red_color = {
        r: r.to_float() as AzFloat,
        g: g.to_float() as AzFloat,
        b: b.to_float() as AzFloat,
        a: 1f as AzFloat
    };
    let red_pattern = AzCreateColorPattern(ptr::addr_of(red_color));

    let red_rect = {
        x: au_to_px(bounds.origin.x) as AzFloat,
        y: au_to_px(bounds.origin.y) as AzFloat,
        width: au_to_px(bounds.size.width) as AzFloat,
        height: au_to_px(bounds.size.height) as AzFloat
    };
    AzDrawTargetFillRect(
        draw_target,
        ptr::addr_of(red_rect),
        unsafe { unsafe::reinterpret_cast(red_pattern) }
    );

    AzReleaseColorPattern(red_pattern);
}

fn draw_image(draw_target: AzDrawTargetRef, item: dl::display_item,
              -image: ~image) {
    // FIXME: This is hideously inefficient.

    let bounds = copy (*item).bounds;

    if (image.depth < 3u) {
        #debug("TODO: can't draw images with depth less than 3 yet");
        ret;
    }

    let stride = image.width * image.depth;
    for uint::range(0u, image.height) {
        |y|
        for uint::range(0u, image.width) {
            |x|
            let color = {
                r: image.data[y * stride + x * image.depth].to_float()
                    as AzFloat,
                g: image.data[y * stride + x * image.depth + 1u].to_float()
                    as AzFloat,
                b: image.data[y * stride + x * image.depth + 2u].to_float()
                    as AzFloat,
                a: 1f as AzFloat
            };
            let pattern = AzCreateColorPattern(ptr::addr_of(color));

            let pixel_rect = {
                x: (au_to_px(bounds.origin.x) + (x as int)) as AzFloat,
                y: (au_to_px(bounds.origin.y) + (y as int)) as AzFloat,
                width: 1f as AzFloat,
                height: 1f as AzFloat
            };
            AzDrawTargetFillRect(
                draw_target,
                ptr::addr_of(pixel_rect),
                unsafe { unsafe::reinterpret_cast(pattern) }
            );

            AzReleaseColorPattern(pattern);
        }
    }
}

fn draw_text(draw_target: AzDrawTargetRef, item: dl::display_item, text_run: text_run) {

    import ptr::{addr_of, null};
    import vec::unsafe::to_ptr;
    import libc::types::common::c99::{uint16_t, uint32_t};
    import geom::point::Point2D;
    import text::font::{font, create_test_font};
    import azure::{AzNativeFont, AzFloat, AZ_NATIVE_FONT_CAIRO_FONT_FACE};
    import azure::bindgen::{AzCreateScaledFontWithCairo,
                            AzReleaseScaledFont,
                            AzCreateColorPattern,
                            AzReleaseColorPattern};

    let bounds = copy (*item).bounds;
    let font = create_test_font();

    let nfont: AzNativeFont = {
        mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE,
        mFont: null()
    };

    let azfont = AzCreateScaledFontWithCairo(addr_of(nfont), 1f as AzFloat, font.cairo_font);
    assert azfont.is_not_null();

    let color = {
        r: 0f as AzFloat,
        g: 0f as AzFloat,
        b: 0f as AzFloat,
        a: 1f as AzFloat
    };
    let pattern = AzCreateColorPattern(addr_of(color));
    assert pattern.is_not_null();

    let options: AzDrawOptions = {
        mAlpha: 1f as AzFloat,
        fields: 0 as uint16_t
    };

    let mut origin = Point2D(bounds.origin.x, bounds.origin.y.add(bounds.size.height));
    let azglyphs = text_run.glyphs.map { |glyph|
        let azglyph: AzGlyph = {
            mIndex: glyph.codepoint as uint32_t,
            mPosition: {
                x: au_to_px(origin.x.add(glyph.pos.offset.x)) as AzFloat,
                y: au_to_px(origin.y.add(glyph.pos.offset.y)) as AzFloat
            }
        };
        origin = Point2D(origin.x.add(glyph.pos.advance.x),
                         origin.y.add(glyph.pos.advance.y));
        azglyph
    };

    let glyphbuf: AzGlyphBuffer = unsafe {{
        mGlyphs: to_ptr(azglyphs),
        mNumGlyphs: azglyphs.len() as uint32_t
    }};

    AzDrawTargetFillGlyphs(draw_target, azfont, addr_of(glyphbuf),
                           pattern, addr_of(options), null());

    AzReleaseColorPattern(pattern);
    AzReleaseScaledFont(azfont);
}

fn clear(draw_target: AzDrawTargetRef) {

    let black_color = {
        r: 0f as AzFloat,
        g: 0f as AzFloat,
        b: 0f as AzFloat,
        a: 1f as AzFloat
    };
    let black_pattern = AzCreateColorPattern(ptr::addr_of(black_color));

    let black_rect = {
        x: 0 as AzFloat,
        y: 0 as AzFloat,
        width: 800 as AzFloat,
        height: 600 as AzFloat,
    };

    AzDrawTargetFillRect(
        draw_target,
        ptr::addr_of(black_rect),
        unsafe { unsafe::reinterpret_cast(black_pattern) }
    );

    AzReleaseColorPattern(black_pattern);
}
<|endoftext|>


<commit_before>extern crate gj;
extern crate gjio;
extern crate byteorder;
extern crate slab;

use gj::{EventLoop, Promise, PromiseFulfiller, TaskReaper, TaskSet};

fn accept_loop(listener: gjio::SocketListener,
               mut task_set: TaskSet<(), ::std::io::Error>)
               -> Promise<(), ::std::io::Error>
{
    unimplemented!()
//    listener.accept().then(move |stream| {
//        accept_loop(listener, task_set)
//    })
}

struct Reaper;

impl TaskReaper<(), ::std::io::Error> for Reaper {
    fn task_failed(&mut self, error: ::std::io::Error) {
        println!("Task failed: {}", error);
    }
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }

    EventLoop::top_level(move |wait_scope| -> Result<(), ::std::io::Error> {
        use std::net::ToSocketAddrs;
        let mut event_port = try!(gjio::EventPort::new());
        let network = event_port.get_network();
        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let mut address = network.get_tcp_address(addr);
        let listener = try!(address.listen());
        let reaper = Box::new(Reaper);
        accept_loop(listener, TaskSet::new(reaper)).wait(wait_scope, &mut event_port)
    }).expect("top level");

}
<commit_msg>publisher half<commit_after>extern crate gj;
extern crate gjio;
extern crate byteorder;
extern crate slab;

use std::io::{Error, ErrorKind};
use byteorder::{LittleEndian, ByteOrder};
use gj::{EventLoop, Promise, TaskReaper, TaskSet};
use gjio::{SocketStream, AsyncRead, AsyncWrite};

fn handle_publisher(mut stream: SocketStream, messages_received: u64) -> Promise<(), Error> {
    stream.try_read(vec![0], 1).then(move |(buf, n)| {
        if n == 0 {
            // EOF
            let mut word = vec![0u8; 8];
            <LittleEndian as ByteOrder>::write_u64(&mut word, messages_received);
            stream.write(word).map(|_| Ok(()))
        } else {
            let len = buf[0] as usize;
            let body = vec![0u8; len];
            stream.read(body, len).then(move |(buf, _)| {
                // TODO send buf to subscribers
                handle_publisher(stream, messages_received + 1)
            })
        }
    })
}

fn handle_connection(mut stream: SocketStream) -> Promise<(), Error> {
    stream.read(vec![0], 1).then(move |(buf, _)| {
        match buf[0] {
            0 => {
                // publisher
                handle_publisher(stream, 0)
            }
            1 => {
                // subscriber
                unimplemented!()
            }
            _ => {
                Promise::err(Error::new(ErrorKind::Other, "expected 0 or 1"))
            }
        }
    })
}

fn accept_loop(listener: gjio::SocketListener,
               mut task_set: TaskSet<(), ::std::io::Error>)
               -> Promise<(), ::std::io::Error>
{
     listener.accept().then(move |stream| {
         task_set.add(handle_connection(stream));
         accept_loop(listener, task_set)
    })
}

struct Reaper;

impl TaskReaper<(), ::std::io::Error> for Reaper {
    fn task_failed(&mut self, error: ::std::io::Error) {
        println!("Task failed: {}", error);
    }
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }

    EventLoop::top_level(move |wait_scope| -> Result<(), ::std::io::Error> {
        use std::net::ToSocketAddrs;
        let mut event_port = try!(gjio::EventPort::new());
        let network = event_port.get_network();
        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let mut address = network.get_tcp_address(addr);
        let listener = try!(address.listen());
        let reaper = Box::new(Reaper);
        accept_loop(listener, TaskSet::new(reaper)).wait(wait_scope, &mut event_port)
    }).expect("top level");

}
<|endoftext|>


<commit_before>use num::cast::{NumCast, cast};

pub trait Channel {
    static pure fn channel_max() -> self;

    static pure fn from_channel<T:Channel>(val: T) -> self;
    pure fn convert_channel<T:Channel>() -> T;

    pure fn to_channel_u8()    -> u8;
    pure fn to_channel_u16()   -> u16;
    pure fn to_channel_u32()   -> u32;
    pure fn to_channel_u64()   -> u64;
    pure fn to_channel_f32()   -> f32;
    pure fn to_channel_f64()   -> f64;
    pure fn to_channel_float() -> float;

    pure fn inverse() -> self;
}

pub pure fn convert_channel<T:Channel, U:Channel>(val: T) -> U { val.convert_channel() }

pub impl u8: Channel {
    #[inline(always)] static pure fn channel_max() -> u8 { 0xFF }  // 2^8

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> u8 { val.to_channel_u8() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { (self as u16 << 8) | self as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { (self.to_channel_u16() as u32 << 16) | self.to_channel_u16() as u32 }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { (self.to_channel_u32() as u64 << 32) | self.to_channel_u32() as u64 }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { (self as f32)   / (0xFF as f32)   }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { (self as f64)   / (0xFF as f64)   }
    #[inline(always)] pure fn to_channel_float() -> float { (self as float) / (0xFF as float) }

    #[inline(always)] pure fn inverse() -> u8 { !self }
}

pub impl u16: Channel {
    #[inline(always)] static pure fn channel_max() -> u16 { 0xFFFF }   // 2^16

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> u16 { val.to_channel_u16() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self / 0x100 as u8 }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { (self as u32 << 16) | self as u32 }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { (self.to_channel_u32() as u64 << 32) | self.to_channel_u32() as u64 }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self / 0xFFFF as f32   }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self / 0xFFFF as f64   }
    #[inline(always)] pure fn to_channel_float() -> float { self / 0xFFFF as float }

    #[inline(always)] pure fn inverse() -> u16 { !self }
}

pub impl u32: Channel {
    #[inline(always)] static pure fn channel_max() -> u32 { 0xFFFF_FFFF }   // 2^32

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> u32 { val.to_channel_u32() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self / 0x1_0000_00 as u8 }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self / 0x1_0000 as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { self }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { (self as u64 << 32) | self as u64 }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self / 0xFFFF_FFFF as f32   }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self / 0xFFFF_FFFF as f64   }
    #[inline(always)] pure fn to_channel_float() -> float { self / 0xFFFF_FFFF as float }

    #[inline(always)] pure fn inverse() -> u32 { !self }
}

pub impl u64: Channel {
    #[inline(always)] static pure fn channel_max() -> u64 { 0xFFFF_FFFF_FFFF_FFFF_u64 }   // 2^64

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> u64 { val.to_channel_u64() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self / 0x1_0000_0000_0000_00 as u8 }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self / 0x1_0000_0000_0000 as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { self / 0x1_0000_0000 as u32 }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { self }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self / 0xFFFF_FFFF_FFFF_FFFF_u64 as f32   }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self / 0xFFFF_FFFF_FFFF_FFFF_u64 as f64   }
    #[inline(always)] pure fn to_channel_float() -> float { self / 0xFFFF_FFFF_FFFF_FFFF_u64 as float }

    #[inline(always)] pure fn inverse() -> u64 { !self }
}

pub impl f32: Channel {
    #[inline(always)] static pure fn channel_max() -> f32 { 1f32 }

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> f32 { val.to_channel_f32() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self * (0xFFu8    as f32) as u8  }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self * (0xFFFFu16 as f32) as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { fail(~"to_channel_u32 not yet implemented for f32") }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { fail(~"to_channel_u64 not yet implemented for f32") }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self as f64 }
    #[inline(always)] pure fn to_channel_float() -> float { self as float }

    #[inline(always)] pure fn inverse() -> f32 { 1.0 - self }
}

pub impl f64: Channel {
    #[inline(always)] static pure fn channel_max() -> f64 { 1f64 }

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> f64 { val.to_channel_f64() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self * (0xFFu8    as f64) as u8  }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self * (0xFFFFu16 as f64) as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { fail(~"to_channel_u32 not yet implemented for f64") }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { fail(~"to_channel_u64 not yet implemented for f64") }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self as f32 }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self }
    #[inline(always)] pure fn to_channel_float() -> float { self as float }

    #[inline(always)] pure fn inverse() -> f64 { 1.0 - self }
}

pub impl float: Channel {
    #[inline(always)] static pure fn channel_max() -> float { 1f }

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> float { val.to_channel_float() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self * (0xFFu8    as float) as u8  }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self * (0xFFFFu16 as float) as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { fail(~"to_channel_u32 not yet implemented for float") }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { fail(~"to_channel_u64 not yet implemented for float") }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self as f32 }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self as f64 }
    #[inline(always)] pure fn to_channel_float() -> float { self }

    #[inline(always)] pure fn inverse() -> float { 1.0 - self }
}<commit_msg>Improve channel conversions<commit_after>use num::cast::{NumCast, cast};

pub trait Channel {
    static pure fn channel_max() -> self;

    static pure fn from_channel<T:Channel>(val: T) -> self;
    pure fn convert_channel<T:Channel>() -> T;

    pure fn to_channel_u8()    -> u8;
    pure fn to_channel_u16()   -> u16;
    pure fn to_channel_u32()   -> u32;
    pure fn to_channel_u64()   -> u64;
    pure fn to_channel_f32()   -> f32;
    pure fn to_channel_f64()   -> f64;
    pure fn to_channel_float() -> float;

    pure fn inverse() -> self;
}

pub pure fn convert_channel<T:Channel, U:Channel>(val: T) -> U { val.convert_channel() }

pub impl u8: Channel {
    #[inline(always)] static pure fn channel_max() -> u8 { 0xFF }  // 2^8

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> u8 { val.to_channel_u8() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { (self as u16 << 8) | self as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { (self.to_channel_u16() as u32 << 16) | self.to_channel_u16() as u32 }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { (self.to_channel_u32() as u64 << 32) | self.to_channel_u32() as u64 }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { (self as f32)   / (0xFF as f32)   }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { (self as f64)   / (0xFF as f64)   }
    #[inline(always)] pure fn to_channel_float() -> float { (self as float) / (0xFF as float) }

    #[inline(always)] pure fn inverse() -> u8 { !self }
}

pub impl u16: Channel {
    #[inline(always)] static pure fn channel_max() -> u16 { 0xFFFF }   // 2^16

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> u16 { val.to_channel_u16() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { (self >> 8) as u8 }    // this is the equivalent of `self/256`. Some folks prefer to do `self/257`
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { (self as u32 << 16) | self as u32 }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { (self.to_channel_u32() as u64 << 32) | self.to_channel_u32() as u64 }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self / 0xFFFF as f32   }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self / 0xFFFF as f64   }
    #[inline(always)] pure fn to_channel_float() -> float { self / 0xFFFF as float }

    #[inline(always)] pure fn inverse() -> u16 { !self }
}

pub impl u32: Channel {
    #[inline(always)] static pure fn channel_max() -> u32 { 0xFFFF_FFFF }   // 2^32

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> u32 { val.to_channel_u32() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { (self >> 24) as u8 }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { (self >> 16) as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { self }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { (self as u64 << 32) | self as u64 }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self / 0xFFFF_FFFF as f32   }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self / 0xFFFF_FFFF as f64   }
    #[inline(always)] pure fn to_channel_float() -> float { self / 0xFFFF_FFFF as float }

    #[inline(always)] pure fn inverse() -> u32 { !self }
}

pub impl u64: Channel {
    #[inline(always)] static pure fn channel_max() -> u64 { 0xFFFF_FFFF_FFFF_FFFF_u64 }   // 2^64

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> u64 { val.to_channel_u64() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { (self >> 56) as u8 }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { (self >> 48) as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { (self >> 32) as u32 }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { self }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self / 0xFFFF_FFFF_FFFF_FFFF_u64 as f32   }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self / 0xFFFF_FFFF_FFFF_FFFF_u64 as f64   }
    #[inline(always)] pure fn to_channel_float() -> float { self / 0xFFFF_FFFF_FFFF_FFFF_u64 as float }

    #[inline(always)] pure fn inverse() -> u64 { !self }
}

pub impl f32: Channel {
    #[inline(always)] static pure fn channel_max() -> f32 { 1f32 }

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> f32 { val.to_channel_f32() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self * (0xFF_u8         as f32) as u8  }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self * (0xFFFF_u16      as f32) as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { fail(~"to_channel_u32 not yet implemented for f32") }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { fail(~"to_channel_u64 not yet implemented for f32") }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self as f64 }
    #[inline(always)] pure fn to_channel_float() -> float { self as float }

    #[inline(always)] pure fn inverse() -> f32 { 1.0 - self }
}

pub impl f64: Channel {
    #[inline(always)] static pure fn channel_max() -> f64 { 1f64 }

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> f64 { val.to_channel_f64() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self * (0xFFu8    as f64) as u8  }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self * (0xFFFFu16 as f64) as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { fail(~"to_channel_u32 not yet implemented for f64") }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { fail(~"to_channel_u64 not yet implemented for f64") }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self as f32 }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self }
    #[inline(always)] pure fn to_channel_float() -> float { self as float }

    #[inline(always)] pure fn inverse() -> f64 { 1.0 - self }
}

pub impl float: Channel {
    #[inline(always)] static pure fn channel_max() -> float { 1f }

    #[inline(always)] static pure fn from_channel<T:Channel>(val: T) -> float { val.to_channel_float() }
    #[inline(always)] pure fn convert_channel<T:Channel>() -> T { from_channel(self) }

    #[inline(always)] pure fn to_channel_u8()    -> u8    { self * (0xFFu8    as float) as u8  }
    #[inline(always)] pure fn to_channel_u16()   -> u16   { self * (0xFFFFu16 as float) as u16 }
    #[inline(always)] pure fn to_channel_u32()   -> u32   { fail(~"to_channel_u32 not yet implemented for float") }
    #[inline(always)] pure fn to_channel_u64()   -> u64   { fail(~"to_channel_u64 not yet implemented for float") }
    #[inline(always)] pure fn to_channel_f32()   -> f32   { self as f32 }
    #[inline(always)] pure fn to_channel_f64()   -> f64   { self as f64 }
    #[inline(always)] pure fn to_channel_float() -> float { self }

    #[inline(always)] pure fn inverse() -> float { 1.0 - self }
}<|endoftext|>


<commit_before>use error::{CliError, Usage, UsageKind};
use super::Command;

use lib::setting::{Config, ConfigKey, Cron};

#[derive(Debug)]
pub struct Start;

impl Command for Start {
    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Start);
    }

    fn main(&self) -> Result<(), CliError> {
        let cron = try!(Cron::read());

        let pair_for_burn = ("0 0 * * *", "burn");

        let config        = try!(Config::read());
        let day_and_month = match try!(config.get(ConfigKey::SweepPeriod)).as_ref() {
            "daily"  => "* * *",
            "weekly" => "* * 0",
            _        => unreachable!("Mistake SweepPeriod's validation!!"),
        };
        let (hour, minute) = Config::to_hour_and_minute(try!(config.get(ConfigKey::SweepTime)));
        let when = format!("{} {} {}", minute, hour, day_and_month);
        let pair_for_sweep = (&when as &str, "sweep");

        cron
            .update(&[pair_for_burn, pair_for_sweep])
            .and_then(|new_cron| new_cron.set())
    }
}
<commit_msg>[Fix] Add option "indeed" to cron contents<commit_after>use error::{CliError, Usage, UsageKind};
use super::Command;

use lib::setting::{Config, ConfigKey, Cron};

#[derive(Debug)]
pub struct Start;

impl Command for Start {
    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Start);
    }

    fn main(&self) -> Result<(), CliError> {
        let cron = try!(Cron::read());

        let pair_for_burn = ("0 0 * * *", "burn indeed");

        let config        = try!(Config::read());
        let day_and_month = match try!(config.get(ConfigKey::SweepPeriod)).as_ref() {
            "daily"  => "* * *",
            "weekly" => "* * 0",
            _        => unreachable!("Mistake SweepPeriod's validation!!"),
        };
        let (hour, minute) = Config::to_hour_and_minute(try!(config.get(ConfigKey::SweepTime)));
        let when = format!("{} {} {}", minute, hour, day_and_month);
        let pair_for_sweep = (&when as &str, "sweep indeed");

        cron
            .update(&[pair_for_burn, pair_for_sweep])
            .and_then(|new_cron| new_cron.set())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::i32;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use itertools::Itertools;
use itertools::MinMaxResult;
use regex::Regex;

use common::Solution;

#[derive(Default)]
pub struct Day10 {
    points: Vec<i32>,
    speeds: Vec<i32>,
}

impl Day10 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_inputs(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        let matcher =
            Regex::new(r"position=<\s*(-?\d+),\s*(-?\d+)> velocity=<\s*(-?\d+),\s*(-?\d+)>")
                .unwrap();

        for line in reader.lines() {
            let line = line.unwrap();
            let groups = matcher.captures(&line).unwrap();

            self.points.push(groups[1].parse().unwrap());
            self.points.push(groups[2].parse().unwrap());
            self.speeds.push(groups[3].parse().unwrap());
            self.speeds.push(groups[4].parse().unwrap());
        }
    }

    fn print_state(&self) -> String {
        let points: HashSet<_> = self.points.iter().tuples().collect();
        let (xmin, xmax) = match points.iter().map(|&(x, _)| *x).minmax() {
            MinMaxResult::MinMax(x, y) => (x, y),
            _ => unreachable!(),
        };
        let (ymin, ymax) = match points.iter().map(|&(_, y)| *y).minmax() {
            MinMaxResult::MinMax(x, y) => (x, y),
            _ => unreachable!(),
        };

        let mut buffer = String::with_capacity(((xmax + 1 - xmin) * (ymax + 1 - ymin)) as usize);

        for y in ymin..=ymax {
            for x in xmin..=xmax {
                let c = if points.contains(&(&x, &y)) { '#' } else { '.' };
                buffer.push(c);
            }

            buffer.push('\n');
        }

        buffer
    }

    fn run(&mut self, time_step: i32) {
        for (x, dx) in self.points.iter_mut().zip(self.speeds.iter()) {
            *x += dx * time_step;
        }
    }

    fn height(&self) -> i32 {
        match self.points.iter().skip(1).step_by(2).minmax() {
            MinMaxResult::MinMax(x, y) => y - x + 1,
            _ => panic!("Input does not make sense."),
        }
    }

    fn underestimate_time(&self) -> i32 {
        let (lower, upper) = match self
            .points
            .iter()
            .enumerate()
            .skip(1)
            .step_by(2)
            .minmax_by_key(|&(_, y)| y)
        {
            MinMaxResult::MinMax((x, _), (y, _)) => (x, y),
            _ => panic!("Input does not make sense"),
        };

        // Letters are probably less than 100 in height
        let dist = self.points[upper] - self.points[lower] - 100;
        let speed = self.speeds[lower] - self.speeds[upper];

        dist.checked_div(speed).unwrap_or(1).max(1)
    }
}

impl Solution for Day10 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_inputs(input);
        let mut prev = self.height();
        let initial = self.underestimate_time();
        self.run(initial);
        let mut height = self.height();
        while height < prev {
            prev = height;
            self.run(1);
            height = self.height();
        }
        self.run(-1);
        self.print_state()
    }

    fn part2(&mut self, input: &mut Read) -> String {
        self.read_inputs(input);
        let mut prev = self.height();
        let mut steps = self.underestimate_time();
        self.run(steps);
        let mut height = self.height();

        while height < prev {
            steps += 1;
            prev = height;
            self.run(1);
            height = self.height();
        }
        (steps - 1).to_string()
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day10::Day10;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/10.txt");

    #[test]
    fn sample_part1() {
        let mut instance = Day10::new();
        let result = instance.part1(&mut SAMPLE_INPUT);
        let correct = include_str!("samples/10.out.txt");
        assert_eq!(correct, &result);
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day10::new();
        assert_eq!("3", instance.part2(&mut SAMPLE_INPUT));
    }
}
<commit_msg>Reduce code duplication.<commit_after>use std::collections::HashSet;
use std::i32;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use itertools::Itertools;
use itertools::MinMaxResult;
use regex::Regex;

use common::Solution;

#[derive(Default)]
pub struct Day10 {
    points: Vec<i32>,
    speeds: Vec<i32>,
}

impl Day10 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_inputs(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        let matcher =
            Regex::new(r"position=<\s*(-?\d+),\s*(-?\d+)> velocity=<\s*(-?\d+),\s*(-?\d+)>")
                .unwrap();

        for line in reader.lines() {
            let line = line.unwrap();
            let groups = matcher.captures(&line).unwrap();

            self.points.push(groups[1].parse().unwrap());
            self.points.push(groups[2].parse().unwrap());
            self.speeds.push(groups[3].parse().unwrap());
            self.speeds.push(groups[4].parse().unwrap());
        }
    }

    fn print_state(&self) -> String {
        let points: HashSet<_> = self.points.iter().tuples().collect();
        let (xmin, xmax) = match points.iter().map(|&(x, _)| *x).minmax() {
            MinMaxResult::MinMax(x, y) => (x, y),
            _ => unreachable!(),
        };
        let (ymin, ymax) = match points.iter().map(|&(_, y)| *y).minmax() {
            MinMaxResult::MinMax(x, y) => (x, y),
            _ => unreachable!(),
        };

        let mut buffer = String::with_capacity(((xmax + 1 - xmin) * (ymax + 1 - ymin)) as usize);

        for y in ymin..=ymax {
            for x in xmin..=xmax {
                let c = if points.contains(&(&x, &y)) { '#' } else { '.' };
                buffer.push(c);
            }

            buffer.push('\n');
        }

        buffer
    }

    fn run(&mut self, time_step: i32) {
        for (x, dx) in self.points.iter_mut().zip(self.speeds.iter()) {
            *x += dx * time_step;
        }
    }

    fn height(&self) -> i32 {
        match self.points.iter().skip(1).step_by(2).minmax() {
            MinMaxResult::MinMax(x, y) => y - x + 1,
            _ => panic!("Input does not make sense."),
        }
    }

    fn underestimate_time(&self) -> i32 {
        let (lower, upper) = match self
            .points
            .iter()
            .enumerate()
            .skip(1)
            .step_by(2)
            .minmax_by_key(|&(_, y)| y)
        {
            MinMaxResult::MinMax((x, _), (y, _)) => (x, y),
            _ => panic!("Input does not make sense"),
        };

        // Letters are probably less than 100 in height
        let dist = self.points[upper] - self.points[lower] - 100;
        let speed = self.speeds[lower] - self.speeds[upper];

        dist.checked_div(speed).unwrap_or(1).max(1)
    }

    fn simulate(&mut self, input: &mut Read) -> i32 {
        self.read_inputs(input);
        let mut prev = self.height();
        let mut steps = self.underestimate_time();
        self.run(steps);
        let mut height = self.height();

        while height < prev {
            steps += 1;
            prev = height;
            self.run(1);
            height = self.height();
        }
        self.run(-1);
        steps - 1
    }
}

impl Solution for Day10 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.simulate(input);
        self.print_state()
    }

    fn part2(&mut self, input: &mut Read) -> String {
        self.simulate(input).to_string()
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day10::Day10;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/10.txt");

    #[test]
    fn sample_part1() {
        let mut instance = Day10::new();
        let result = instance.part1(&mut SAMPLE_INPUT);
        let correct = include_str!("samples/10.out.txt");
        assert_eq!(correct, &result);
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day10::new();
        assert_eq!("3", instance.part2(&mut SAMPLE_INPUT));
    }
}
<|endoftext|>


<commit_before>extern mod allegro5;

use std::num::Zero;
use std::float::consts::pi;
use std::c_str::*;
use allegro5::*;

#[start]
fn start(argc: int, argv: **u8, crate_map: *u8) -> int
{
    allegro5::run(argc, argv, crate_map, main)
}

fn main()
{
	let disp = Display::new(800, 600).unwrap();
	disp.set_window_title(&"Rust example".to_c_str());

	let q = EventQueue::new().unwrap();
	q.register_event_source(disp.get_event_source());

	let bmp = Bitmap::new(256, 256).unwrap();

	let mut info = MonitorInfo::new();
	get_monitor_info(0, &mut info);
	println!("{} {} {} {}", info.x1, info.y1, info.x2, info.y2);

	disp.clear_to_color(Color::map_rgb_f(0.0, 0.0, 0.0));
	bmp.clear_to_color(Color::map_rgb_f(0.0, 0.0, 1.0));

	let sub_bmp = bmp.create_sub_bitmap(64, 64, 64, 64).unwrap();
	sub_bmp.clear_to_color(Color::map_rgb_f(0.0, 1.0, 1.0));

	disp.draw_rotated_bitmap(&bmp, 0.0, 0.0, disp.get_width() / 2.0, disp.get_height() / 2.0, pi / 4.0, Zero::zero());
	disp.flip();

	match q.wait_for_event()
	{
		DisplayClose(src, _) =>
		// DisplayClose{ source: src, _} => // Issue #5557
		{
			assert!(disp.get_event_source().get_event_source() == src)
			println!("Display close event...")
		},
		_ => println!("Some other event...")
	}
}
<commit_msg>Update example to correctly use the struct like event<commit_after>extern mod allegro5;

use std::num::Zero;
use std::float::consts::pi;
use std::c_str::*;
use allegro5::*;

#[start]
fn start(argc: int, argv: **u8, crate_map: *u8) -> int
{
    allegro5::run(argc, argv, crate_map, main)
}

fn main()
{
	let disp = Display::new(800, 600).unwrap();
	disp.set_window_title(&"Rust example".to_c_str());

	let q = EventQueue::new().unwrap();
	q.register_event_source(disp.get_event_source());

	let bmp = Bitmap::new(256, 256).unwrap();

	let mut info = MonitorInfo::new();
	get_monitor_info(0, &mut info);
	println!("{} {} {} {}", info.x1, info.y1, info.x2, info.y2);

	disp.clear_to_color(Color::map_rgb_f(0.0, 0.0, 0.0));
	bmp.clear_to_color(Color::map_rgb_f(0.0, 0.0, 1.0));

	let sub_bmp = bmp.create_sub_bitmap(64, 64, 64, 64).unwrap();
	sub_bmp.clear_to_color(Color::map_rgb_f(0.0, 1.0, 1.0));

	disp.draw_rotated_bitmap(&bmp, 0.0, 0.0, disp.get_width() / 2.0, disp.get_height() / 2.0, pi / 4.0, Zero::zero());
	disp.flip();

	match q.wait_for_event()
	{
		DisplayClose{ source: src, _} =>
		{
			assert!(disp.get_event_source().get_event_source() == src)
			println!("Display close event...")
		},
		_ => println!("Some other event...")
	}
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<%helpers:shorthand name="outline" sub_properties="outline-color outline-style outline-width">
    use properties::longhands::outline_width;
    use values::specified;

    let _unused = context;
    let mut color = None;
    let mut style = None;
    let mut width = None;
    let mut any = false;
    loop {
        if color.is_none() {
            if let Ok(value) = input.try(specified::CSSColor::parse) {
                color = Some(value);
                any = true;
                continue
            }
        }
        if style.is_none() {
            if let Ok(value) = input.try(specified::BorderStyle::parse) {
                style = Some(value);
                any = true;
                continue
            }
        }
        if width.is_none() {
            if let Ok(value) = input.try(|input| outline_width::parse(context, input)) {
                width = Some(value);
                any = true;
                continue
            }
        }
        break
    }
    if any {
        Ok(Longhands {
            outline_color: color,
            outline_style: style,
            outline_width: width,
        })
    } else {
        Err(())
    }
</%helpers:shorthand>
<commit_msg>Support -moz-outline-radius shorthand in geckolib.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<%helpers:shorthand name="outline" sub_properties="outline-color outline-style outline-width">
    use properties::longhands::outline_width;
    use values::specified;

    let _unused = context;
    let mut color = None;
    let mut style = None;
    let mut width = None;
    let mut any = false;
    loop {
        if color.is_none() {
            if let Ok(value) = input.try(specified::CSSColor::parse) {
                color = Some(value);
                any = true;
                continue
            }
        }
        if style.is_none() {
            if let Ok(value) = input.try(specified::BorderStyle::parse) {
                style = Some(value);
                any = true;
                continue
            }
        }
        if width.is_none() {
            if let Ok(value) = input.try(|input| outline_width::parse(context, input)) {
                width = Some(value);
                any = true;
                continue
            }
        }
        break
    }
    if any {
        Ok(Longhands {
            outline_color: color,
            outline_style: style,
            outline_width: width,
        })
    } else {
        Err(())
    }
</%helpers:shorthand>

// The -moz-outline-radius shorthand is non-standard and not on a standards track.
<%helpers:shorthand name="-moz-outline-radius" sub_properties="${' '.join(
    '-moz-outline-radius-%s' % corner
    for corner in ['topleft', 'topright', 'bottomright', 'bottomleft']
)}" products="gecko">
    use properties::shorthands;

    // Re-use border-radius parsing.
    shorthands::border_radius::parse_value(context, input).map(|longhands| {
        Longhands {
            % for corner in ["top_left", "top_right", "bottom_right", "bottom_left"]:
            _moz_outline_radius_${corner.replace("_", "")}: longhands.border_${corner}_radius,
            % endfor
        }
    })
</%helpers:shorthand>
<|endoftext|>