<commit_before>use crate::rust::string::String;
use crate::io;
use super::{
	Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint32, VarUint1, Uint8,
	ValueType, TableElementType
};

const FLAG_HAS_MAX: u8 = 0x01;
#[cfg(feature="atomics")]
const FLAG_SHARED: u8 = 0x02;

/// Global definition struct
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct GlobalType {
	content_type: ValueType,
	is_mutable: bool,
}

impl GlobalType {
	/// New global type
	pub fn new(content_type: ValueType, is_mutable: bool) -> Self {
		GlobalType {
			content_type: content_type,
			is_mutable: is_mutable,
		}
	}

	/// Type of the global entry
	pub fn content_type(&self) -> ValueType { self.content_type }

	/// Is global entry is declared as mutable
	pub fn is_mutable(&self) -> bool { self.is_mutable }
}

impl Deserialize for GlobalType {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let content_type = ValueType::deserialize(reader)?;
		let is_mutable = VarUint1::deserialize(reader)?;
		Ok(GlobalType {
			content_type: content_type,
			is_mutable: is_mutable.into(),
		})
	}
}

impl Serialize for GlobalType {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		self.content_type.serialize(writer)?;
		VarUint1::from(self.is_mutable).serialize(writer)?;
		Ok(())
	}
}

/// Table entry
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct TableType {
	elem_type: TableElementType,
	limits: ResizableLimits,
}

impl TableType {
	/// New table definition
	pub fn new(min: u32, max: Option<u32>) -> Self {
		TableType {
			elem_type: TableElementType::AnyFunc,
			limits: ResizableLimits::new(min, max),
		}
	}

	/// Table memory specification
	pub fn limits(&self) -> &ResizableLimits { &self.limits }

	/// Table element type
	pub fn elem_type(&self) -> TableElementType { self.elem_type }
}

impl Deserialize for TableType {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let elem_type = TableElementType::deserialize(reader)?;
		let limits = ResizableLimits::deserialize(reader)?;
		Ok(TableType {
			elem_type: elem_type,
			limits: limits,
		})
	}
}

impl Serialize for TableType {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		self.elem_type.serialize(writer)?;
		self.limits.serialize(writer)
	}
}

/// Memory and table limits.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct ResizableLimits {
	initial: u32,
	maximum: Option<u32>,
	#[cfg(feature = "atomics")]
	shared: bool,
}

impl ResizableLimits {
	/// New memory limits definition.
	pub fn new(min: u32, max: Option<u32>) -> Self {
		ResizableLimits {
			initial: min,
			maximum: max,
			#[cfg(feature = "atomics")]
			shared: false,
		}
	}
	/// Initial size.
	pub fn initial(&self) -> u32 { self.initial }
	/// Maximum size.
	pub fn maximum(&self) -> Option<u32> { self.maximum }

	#[cfg(feature = "atomics")]
	/// Whether or not this is a shared array buffer.
	pub fn shared(&self) -> bool { self.shared }
}

impl Deserialize for ResizableLimits {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let flags: u8 = Uint8::deserialize(reader)?.into();
		match flags {
			// Default flags are always supported. This is simply: FLAG_HAS_MAX={true, false}.
			0x00 | 0x01 => {},

			// Atomics proposal introduce FLAG_SHARED (0x02). Shared memories can be used only
			// together with FLAG_HAS_MAX (0x01), hence 0x03.
			#[cfg(feature="atomics")]
			0x03 => {},

			_ => return Err(Error::InvalidLimitsFlags(flags)),
		}

		let initial = VarUint32::deserialize(reader)?;
		let maximum = if flags & FLAG_HAS_MAX != 0 {
			Some(VarUint32::deserialize(reader)?.into())
		} else {
			None
		};

		Ok(ResizableLimits {
			initial: initial.into(),
			maximum: maximum,

			#[cfg(feature="atomics")]
			shared: flags & FLAG_SHARED != 0,
		})
	}
}

impl Serialize for ResizableLimits {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		let mut flags: u8 = 0;
		if self.maximum.is_some() {
			flags |= FLAG_HAS_MAX;
		}

		#[cfg(feature="atomics")]
		{
			// If the atomics feature is enabled and if the shared flag is set, add logically
			// it to the flags.
			if self.shared {
				flags |= FLAG_SHARED;
			}
		}
		Uint8::from(flags).serialize(writer)?;
		VarUint32::from(self.initial).serialize(writer)?;
		if let Some(max) = self.maximum {
			VarUint32::from(max).serialize(writer)?;
		}
		Ok(())
	}
}

/// Memory entry.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct MemoryType(ResizableLimits);

impl MemoryType {
	/// New memory definition
	pub fn new(
		min: u32,
		max: Option<u32>,
	) -> Self {
		let r = ResizableLimits::new(min, max);
		MemoryType(r)
	}

	/// Set the `shared` flag that denotes a memory that can be shared between threads.
	///
	/// `false` by default. This is only available if the `atomics` feature is enabled.
	#[cfg(feature = "atomics")]
	pub fn set_shared(&mut self, shared: bool) {
		self.0.shared = shared;
	}

	/// Limits of the memory entry.
	pub fn limits(&self) -> &ResizableLimits {
		&self.0
	}
}

impl Deserialize for MemoryType {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		Ok(MemoryType(ResizableLimits::deserialize(reader)?))
	}
}

impl Serialize for MemoryType {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		self.0.serialize(writer)
	}
}

/// External to local binding.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum External {
	/// Binds to a function whose type is associated with the given index in the
	/// type section.
	Function(u32),
	/// Describes local table definition to be imported as.
	Table(TableType),
	/// Describes local memory definition to be imported as.
	Memory(MemoryType),
	/// Describes local global entry to be imported as.
	Global(GlobalType),
}

impl Deserialize for External {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let kind = VarUint7::deserialize(reader)?;
		match kind.into() {
			0x00 => Ok(External::Function(VarUint32::deserialize(reader)?.into())),
			0x01 => Ok(External::Table(TableType::deserialize(reader)?)),
			0x02 => Ok(External::Memory(MemoryType::deserialize(reader)?)),
			0x03 => Ok(External::Global(GlobalType::deserialize(reader)?)),
			_ => Err(Error::UnknownExternalKind(kind.into())),
		}
	}
}

impl Serialize for External {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		use self::External::*;

		match self {
			Function(index) => {
				VarUint7::from(0x00).serialize(writer)?;
				VarUint32::from(index).serialize(writer)?;
			},
			Table(tt) => {
				VarInt7::from(0x01).serialize(writer)?;
				tt.serialize(writer)?;
			},
			Memory(mt) => {
				VarInt7::from(0x02).serialize(writer)?;
				mt.serialize(writer)?;
			},
			Global(gt) => {
				VarInt7::from(0x03).serialize(writer)?;
				gt.serialize(writer)?;
			},
		}

		Ok(())
	}
}

/// Import entry.
#[derive(Debug, Clone, PartialEq)]
pub struct ImportEntry {
	module_str: String,
	field_str: String,
	external: External,
}

impl ImportEntry {
	/// New import entry.
	pub fn new(module_str: String, field_str: String, external: External) -> Self {
		ImportEntry {
			module_str: module_str,
			field_str: field_str,
			external: external,
		}
	}

	/// Module reference of the import entry.
	pub fn module(&self) -> &str { &self.module_str }

	/// Module reference of the import entry (mutable).
	pub fn module_mut(&mut self) -> &mut String {
		&mut self.module_str
	}

	/// Field reference of the import entry.
	pub fn field(&self) -> &str { &self.field_str }

	/// Field reference of the import entry (mutable)
	pub fn field_mut(&mut self) -> &mut String {
		&mut self.field_str
	}

	/// Local binidng of the import entry.
	pub fn external(&self) -> &External { &self.external }

	/// Local binidng of the import entry (mutable)
	pub fn external_mut(&mut self) -> &mut External { &mut self.external }
}

impl Deserialize for ImportEntry {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let module_str = String::deserialize(reader)?;
		let field_str = String::deserialize(reader)?;
		let external = External::deserialize(reader)?;

		Ok(ImportEntry {
			module_str: module_str,
			field_str: field_str,
			external: external,
		})
	}
}

impl Serialize for ImportEntry {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		self.module_str.serialize(writer)?;
		self.field_str.serialize(writer)?;
		self.external.serialize(writer)
	}
}
<commit_msg>Fix fmt.<commit_after>use crate::rust::string::String;
use crate::io;
use super::{
	Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint32, VarUint1, Uint8,
	ValueType, TableElementType
};

const FLAG_HAS_MAX: u8 = 0x01;
#[cfg(feature="atomics")]
const FLAG_SHARED: u8 = 0x02;

/// Global definition struct
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct GlobalType {
	content_type: ValueType,
	is_mutable: bool,
}

impl GlobalType {
	/// New global type
	pub fn new(content_type: ValueType, is_mutable: bool) -> Self {
		GlobalType {
			content_type: content_type,
			is_mutable: is_mutable,
		}
	}

	/// Type of the global entry
	pub fn content_type(&self) -> ValueType { self.content_type }

	/// Is global entry is declared as mutable
	pub fn is_mutable(&self) -> bool { self.is_mutable }
}

impl Deserialize for GlobalType {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let content_type = ValueType::deserialize(reader)?;
		let is_mutable = VarUint1::deserialize(reader)?;
		Ok(GlobalType {
			content_type: content_type,
			is_mutable: is_mutable.into(),
		})
	}
}

impl Serialize for GlobalType {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		self.content_type.serialize(writer)?;
		VarUint1::from(self.is_mutable).serialize(writer)?;
		Ok(())
	}
}

/// Table entry
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct TableType {
	elem_type: TableElementType,
	limits: ResizableLimits,
}

impl TableType {
	/// New table definition
	pub fn new(min: u32, max: Option<u32>) -> Self {
		TableType {
			elem_type: TableElementType::AnyFunc,
			limits: ResizableLimits::new(min, max),
		}
	}

	/// Table memory specification
	pub fn limits(&self) -> &ResizableLimits { &self.limits }

	/// Table element type
	pub fn elem_type(&self) -> TableElementType { self.elem_type }
}

impl Deserialize for TableType {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let elem_type = TableElementType::deserialize(reader)?;
		let limits = ResizableLimits::deserialize(reader)?;
		Ok(TableType {
			elem_type: elem_type,
			limits: limits,
		})
	}
}

impl Serialize for TableType {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		self.elem_type.serialize(writer)?;
		self.limits.serialize(writer)
	}
}

/// Memory and table limits.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct ResizableLimits {
	initial: u32,
	maximum: Option<u32>,
	#[cfg(feature = "atomics")]
	shared: bool,
}

impl ResizableLimits {
	/// New memory limits definition.
	pub fn new(min: u32, max: Option<u32>) -> Self {
		ResizableLimits {
			initial: min,
			maximum: max,
			#[cfg(feature = "atomics")]
			shared: false,
		}
	}
	/// Initial size.
	pub fn initial(&self) -> u32 { self.initial }
	/// Maximum size.
	pub fn maximum(&self) -> Option<u32> { self.maximum }

	#[cfg(feature = "atomics")]
	/// Whether or not this is a shared array buffer.
	pub fn shared(&self) -> bool { self.shared }
}

impl Deserialize for ResizableLimits {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let flags: u8 = Uint8::deserialize(reader)?.into();
		match flags {
			// Default flags are always supported. This is simply: FLAG_HAS_MAX={true, false}.
			0x00 | 0x01 => {},

			// Atomics proposal introduce FLAG_SHARED (0x02). Shared memories can be used only
			// together with FLAG_HAS_MAX (0x01), hence 0x03.
			#[cfg(feature="atomics")]
			0x03 => {},

			_ => return Err(Error::InvalidLimitsFlags(flags)),
		}

		let initial = VarUint32::deserialize(reader)?;
		let maximum = if flags & FLAG_HAS_MAX != 0 {
			Some(VarUint32::deserialize(reader)?.into())
		} else {
			None
		};

		Ok(ResizableLimits {
			initial: initial.into(),
			maximum: maximum,

			#[cfg(feature="atomics")]
			shared: flags & FLAG_SHARED != 0,
		})
	}
}

impl Serialize for ResizableLimits {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		let mut flags: u8 = 0;
		if self.maximum.is_some() {
			flags |= FLAG_HAS_MAX;
		}

		#[cfg(feature="atomics")]
		{
			// If the atomics feature is enabled and if the shared flag is set, add logically
			// it to the flags.
			if self.shared {
				flags |= FLAG_SHARED;
			}
		}
		Uint8::from(flags).serialize(writer)?;
		VarUint32::from(self.initial).serialize(writer)?;
		if let Some(max) = self.maximum {
			VarUint32::from(max).serialize(writer)?;
		}
		Ok(())
	}
}

/// Memory entry.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct MemoryType(ResizableLimits);

impl MemoryType {
	/// New memory definition
	pub fn new(min: u32, max: Option<u32>) -> Self {
		let r = ResizableLimits::new(min, max);
		MemoryType(r)
	}

	/// Set the `shared` flag that denotes a memory that can be shared between threads.
	///
	/// `false` by default. This is only available if the `atomics` feature is enabled.
	#[cfg(feature = "atomics")]
	pub fn set_shared(&mut self, shared: bool) {
		self.0.shared = shared;
	}

	/// Limits of the memory entry.
	pub fn limits(&self) -> &ResizableLimits {
		&self.0
	}
}

impl Deserialize for MemoryType {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		Ok(MemoryType(ResizableLimits::deserialize(reader)?))
	}
}

impl Serialize for MemoryType {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		self.0.serialize(writer)
	}
}

/// External to local binding.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum External {
	/// Binds to a function whose type is associated with the given index in the
	/// type section.
	Function(u32),
	/// Describes local table definition to be imported as.
	Table(TableType),
	/// Describes local memory definition to be imported as.
	Memory(MemoryType),
	/// Describes local global entry to be imported as.
	Global(GlobalType),
}

impl Deserialize for External {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let kind = VarUint7::deserialize(reader)?;
		match kind.into() {
			0x00 => Ok(External::Function(VarUint32::deserialize(reader)?.into())),
			0x01 => Ok(External::Table(TableType::deserialize(reader)?)),
			0x02 => Ok(External::Memory(MemoryType::deserialize(reader)?)),
			0x03 => Ok(External::Global(GlobalType::deserialize(reader)?)),
			_ => Err(Error::UnknownExternalKind(kind.into())),
		}
	}
}

impl Serialize for External {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		use self::External::*;

		match self {
			Function(index) => {
				VarUint7::from(0x00).serialize(writer)?;
				VarUint32::from(index).serialize(writer)?;
			},
			Table(tt) => {
				VarInt7::from(0x01).serialize(writer)?;
				tt.serialize(writer)?;
			},
			Memory(mt) => {
				VarInt7::from(0x02).serialize(writer)?;
				mt.serialize(writer)?;
			},
			Global(gt) => {
				VarInt7::from(0x03).serialize(writer)?;
				gt.serialize(writer)?;
			},
		}

		Ok(())
	}
}

/// Import entry.
#[derive(Debug, Clone, PartialEq)]
pub struct ImportEntry {
	module_str: String,
	field_str: String,
	external: External,
}

impl ImportEntry {
	/// New import entry.
	pub fn new(module_str: String, field_str: String, external: External) -> Self {
		ImportEntry {
			module_str: module_str,
			field_str: field_str,
			external: external,
		}
	}

	/// Module reference of the import entry.
	pub fn module(&self) -> &str { &self.module_str }

	/// Module reference of the import entry (mutable).
	pub fn module_mut(&mut self) -> &mut String {
		&mut self.module_str
	}

	/// Field reference of the import entry.
	pub fn field(&self) -> &str { &self.field_str }

	/// Field reference of the import entry (mutable)
	pub fn field_mut(&mut self) -> &mut String {
		&mut self.field_str
	}

	/// Local binidng of the import entry.
	pub fn external(&self) -> &External { &self.external }

	/// Local binidng of the import entry (mutable)
	pub fn external_mut(&mut self) -> &mut External { &mut self.external }
}

impl Deserialize for ImportEntry {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let module_str = String::deserialize(reader)?;
		let field_str = String::deserialize(reader)?;
		let external = External::deserialize(reader)?;

		Ok(ImportEntry {
			module_str: module_str,
			field_str: field_str,
			external: external,
		})
	}
}

impl Serialize for ImportEntry {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		self.module_str.serialize(writer)?;
		self.field_str.serialize(writer)?;
		self.external.serialize(writer)
	}
}
<|endoftext|>


<commit_before>use crate::geometry::path::PathGeometry;
use crate::enums::{FigureBegin, FigureEnd, FillMode, PathSegment};
use crate::error::D2DResult;

use math2d::{ArcSegment, BezierSegment, Point2f, QuadBezierSegment};
use winapi::shared::winerror::SUCCEEDED;
use winapi::um::d2d1::{ID2D1GeometrySink,  D2D1_FIGURE_END};
use wio::com::ComPtr;

/// Interface for building Path geometry
pub struct PathBuilder {
    pub(super) path: PathGeometry,
    pub(super) sink: ComPtr<ID2D1GeometrySink>,
}

impl PathBuilder {
    #[inline]
    pub fn fill_mode(self, fill_mode: FillMode) -> Self {
        unsafe { self.sink.SetFillMode(fill_mode as u32) };
        self
    }

    #[inline]
    pub fn set_segment_flags(self, flags: PathSegment) -> Self {
        unsafe { self.sink.SetSegmentFlags(flags as u32) };
        self
    }

    #[inline]
    pub fn begin_figure(
        self,
        start: impl Into<Point2f>,
        begin: FigureBegin,
        end: FigureEnd,
    ) -> FigureBuilder {
        unsafe {
            self.sink.BeginFigure(start.into().into(), begin as u32);
        }
        FigureBuilder {
            builder: self,
            end: (end as u32),
        }
    }

    #[inline]
    pub fn with_figure(
        self,
        start: impl Into<Point2f>,
        begin: FigureBegin,
        end: FigureEnd,
        f: impl FnOnce(FigureBuilder) -> FigureBuilder,
    ) -> Self {
        f(self.begin_figure(start, begin, end)).end()
    }

    #[inline]
    pub fn with_line_figure(self, begin: FigureBegin, end: FigureEnd, lines: &[Point2f]) -> Self {
        assert!(lines.len() > 1);
        self.with_figure(lines[0], begin, end, |figure| figure.add_lines(&lines[1..]))
    }

    #[inline]
    pub fn copy_from(self, path: &PathGeometry) -> D2DResult<Self> {
        unsafe {
            let hr = path.ptr.Stream(self.sink.as_raw());
            if SUCCEEDED(hr) {
                Ok(self)
            } else {
                Err(hr.into())
            }
        }
    }

    #[inline]
    pub fn finish(mut self) -> D2DResult<PathGeometry> {
        unsafe {
            let hr = self.sink.Close();

            // Move path out of self without invoking drop.
            let path = std::ptr::read(&self.path);
            std::ptr::drop_in_place(&mut self.sink);
            std::mem::forget(self);

            if SUCCEEDED(hr) {
                Ok(path)
            } else {
                Err(hr.into())
            }
        }
    }
}

impl Drop for PathBuilder {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            self.sink.Close();
        }
    }
}

pub struct FigureBuilder {
    builder: PathBuilder,
    end: D2D1_FIGURE_END,
}

impl FigureBuilder {
    #[inline]
    pub fn end(self) -> PathBuilder {
        unsafe {
            self.builder.sink.EndFigure(self.end);

            // Move builder out of self without invoking drop.
            let builder = std::ptr::read(&self.builder);
            std::mem::forget(self);
            builder
        }
    }

    #[inline]
    pub fn add_line<P: Into<Point2f>>(self, point: P) -> Self {
        unsafe { self.builder.sink.AddLine(point.into().into()) };
        self
    }

    #[inline]
    pub fn add_lines(self, points: &[Point2f]) -> Self {
        unsafe {
            self.builder
                .sink
                .AddLines(points.as_ptr() as *const _, points.len() as u32)
        };
        self
    }

    #[inline]
    pub fn add_bezier(self, bezier: &BezierSegment) -> Self {
        unsafe { self.builder.sink.AddBezier(bezier as *const _ as *const _) };
        self
    }

    #[inline]
    pub fn add_beziers(self, beziers: &[BezierSegment]) -> Self {
        unsafe {
            self.builder
                .sink
                .AddBeziers(beziers.as_ptr() as *const _, beziers.len() as u32)
        };
        self
    }

    #[inline]
    pub fn add_quadratic_bezier(self, bezier: &QuadBezierSegment) -> Self {
        unsafe {
            self.builder
                .sink
                .AddQuadraticBezier(bezier as *const _ as *const _)
        };
        self
    }

    #[inline]
    pub fn add_quadratic_beziers(self, beziers: &[QuadBezierSegment]) -> Self {
        unsafe {
            self.builder
                .sink
                .AddQuadraticBeziers(beziers.as_ptr() as *const _, beziers.len() as u32)
        };
        self
    }

    #[inline]
    pub fn add_arc(self, arc: &ArcSegment) -> Self {
        unsafe { self.builder.sink.AddArc(arc as *const _ as *const _) };
        self
    }
}

impl Drop for FigureBuilder {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            self.builder.sink.EndFigure(self.end);
        }
    }
}
<commit_msg>Pass the figure end at the end<commit_after>use crate::enums::{FigureBegin, FigureEnd, FillMode, PathSegment};
use crate::error::D2DResult;
use crate::geometry::path::PathGeometry;

use math2d::{ArcSegment, BezierSegment, Point2f, QuadBezierSegment};
use winapi::shared::winerror::SUCCEEDED;
use winapi::um::d2d1::ID2D1GeometrySink;
use wio::com::ComPtr;

/// Interface for building Path geometry
pub struct PathBuilder {
    pub(super) path: PathGeometry,
    pub(super) sink: ComPtr<ID2D1GeometrySink>,
}

impl PathBuilder {
    #[inline]
    pub fn fill_mode(self, fill_mode: FillMode) -> Self {
        unsafe { self.sink.SetFillMode(fill_mode as u32) };
        self
    }

    #[inline]
    pub fn set_segment_flags(self, flags: PathSegment) -> Self {
        unsafe { self.sink.SetSegmentFlags(flags as u32) };
        self
    }

    #[inline]
    pub fn begin_figure(self, start: impl Into<Point2f>, begin: FigureBegin) -> FigureBuilder {
        unsafe {
            self.sink.BeginFigure(start.into().into(), begin as u32);
        }
        FigureBuilder { builder: self }
    }

    #[inline]
    pub fn with_figure(
        self,
        start: impl Into<Point2f>,
        begin: FigureBegin,
        end: FigureEnd,
        f: impl FnOnce(FigureBuilder) -> FigureBuilder,
    ) -> Self {
        f(self.begin_figure(start, begin)).end(end)
    }

    #[inline]
    pub fn with_line_figure(self, begin: FigureBegin, end: FigureEnd, lines: &[Point2f]) -> Self {
        assert!(lines.len() > 1);
        self.with_figure(lines[0], begin, end, |figure| figure.add_lines(&lines[1..]))
    }

    #[inline]
    pub fn copy_from(self, path: &PathGeometry) -> D2DResult<Self> {
        unsafe {
            let hr = path.ptr.Stream(self.sink.as_raw());
            if SUCCEEDED(hr) {
                Ok(self)
            } else {
                Err(hr.into())
            }
        }
    }

    #[inline]
    pub fn finish(mut self) -> D2DResult<PathGeometry> {
        unsafe {
            let hr = self.sink.Close();

            // Move path out of self without invoking drop.
            let path = std::ptr::read(&self.path);
            std::ptr::drop_in_place(&mut self.sink);
            std::mem::forget(self);

            if SUCCEEDED(hr) {
                Ok(path)
            } else {
                Err(hr.into())
            }
        }
    }
}

impl Drop for PathBuilder {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            self.sink.Close();
        }
    }
}

pub struct FigureBuilder {
    builder: PathBuilder,
}

impl FigureBuilder {
    #[inline]
    pub fn end(self, end: FigureEnd) -> PathBuilder {
        unsafe {
            self.builder.sink.EndFigure(end as u32);

            // Move builder out of self without invoking drop.
            let builder = std::ptr::read(&self.builder);
            std::mem::forget(self);
            builder
        }
    }

    #[inline]
    pub fn add_line<P: Into<Point2f>>(self, point: P) -> Self {
        unsafe { self.builder.sink.AddLine(point.into().into()) };
        self
    }

    #[inline]
    pub fn add_lines(self, points: &[Point2f]) -> Self {
        unsafe {
            self.builder
                .sink
                .AddLines(points.as_ptr() as *const _, points.len() as u32)
        };
        self
    }

    #[inline]
    pub fn add_bezier(self, bezier: &BezierSegment) -> Self {
        unsafe { self.builder.sink.AddBezier(bezier as *const _ as *const _) };
        self
    }

    #[inline]
    pub fn add_beziers(self, beziers: &[BezierSegment]) -> Self {
        unsafe {
            self.builder
                .sink
                .AddBeziers(beziers.as_ptr() as *const _, beziers.len() as u32)
        };
        self
    }

    #[inline]
    pub fn add_quadratic_bezier(self, bezier: &QuadBezierSegment) -> Self {
        unsafe {
            self.builder
                .sink
                .AddQuadraticBezier(bezier as *const _ as *const _)
        };
        self
    }

    #[inline]
    pub fn add_quadratic_beziers(self, beziers: &[QuadBezierSegment]) -> Self {
        unsafe {
            self.builder
                .sink
                .AddQuadraticBeziers(beziers.as_ptr() as *const _, beziers.len() as u32)
        };
        self
    }

    #[inline]
    pub fn add_arc(self, arc: &ArcSegment) -> Self {
        unsafe { self.builder.sink.AddArc(arc as *const _ as *const _) };
        self
    }
}

impl Drop for FigureBuilder {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            self.builder.sink.EndFigure(FigureEnd::Open as u32);
        }
    }
}
<|endoftext|>


<commit_before>use schema_capnp::*;

use codegen;

#[derive(Copy,Clone,PartialEq)]
pub enum Module { Reader, Builder, Owned }
impl ::std::fmt::Display for Module {
    fn fmt(&self, fmt:&mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        ::std::fmt::Display::fmt(match self {
            &Module::Reader => "Reader",
            &Module::Builder => "Builder",
            &Module::Owned => "Owned",
        }, fmt)
    }
}

// this is a collection of helpers acting on a "Node" (most of them are Type definitions)
pub trait RustNodeInfo {
    fn type_string(&self, gen:&codegen::GeneratorContext, brand:&::schema_capnp::brand::Reader,
        scope:Option<&Vec<String>>, module:Module, lifetime:&str) -> String;

    // in rust, we have only nestable modules, and parameterizable types...
    // so a logically child struct will be a physical sibling to its logical parent. so it must
    // keep track of all parameterization on its own
    // this function recursively parse a node definition to find out the parameters used and inherited by scoping
    // and add them to the explicit parameters
    // the result is the actual parameters for the type to be generated
    fn expand_parameters(&self, gen:&::codegen::GeneratorContext) -> Vec<String>;
}

// this is a collection of helpers acting on a "Type" (someplace where a Type is used, not defined)
pub trait RustTypeInfo {

    fn is_prim(&self) -> bool;
    fn is_parameterized(&self) -> bool;
    fn is_branded(&self) -> bool;
    fn type_string(&self, gen:&codegen::GeneratorContext,
        module:Module, lifetime:&str) -> String;
}

impl <'a> RustNodeInfo for node::Reader<'a> {

    fn expand_parameters(&self, gen:&::codegen::GeneratorContext) -> Vec<String> {
        let mut vec:Vec<String> = self.get_parameters().unwrap().iter().map(|p| p.get_name().unwrap().to_string()).collect();
        match self.which().unwrap() {
            ::schema_capnp::node::Struct(struct_reader) => {
                let fields = struct_reader.get_fields().unwrap();
                for field in fields.iter() {
                    match field.which().unwrap() {
                        ::schema_capnp::field::Slot(slot) => {
                            let typ = slot.get_type().unwrap().which().unwrap();
                            match typ {
                                ::schema_capnp::type_::Struct(st) => {
                                    let brand = st.get_brand().unwrap();
                                    let scopes = brand.get_scopes().unwrap();
                                    for scope in scopes.iter() {
                                        match scope.which().unwrap() {
                                            ::schema_capnp::brand::scope::Inherit(_) => {
                                                let parent_node = gen.node_map[&scope.get_scope_id()];
                                                for p in parent_node.get_parameters().unwrap().iter() {
                                                    let parameter_name = p.get_name().unwrap().to_string();
                                                    if !vec.contains(&parameter_name) {
                                                        vec.push(parameter_name);
                                                        }
                                                }
                                            },
                                            _ => {}
                                        }
                                    }
                                },
                                ::schema_capnp::type_::AnyPointer(any) => {
                                    match any.which().unwrap() {
                                        ::schema_capnp::type_::any_pointer::Parameter(def) => {
                                            let the_struct = &gen.node_map[&def.get_scope_id()];
                                            let parameters = the_struct.get_parameters().unwrap();
                                            let parameter = parameters.get(def.get_parameter_index() as u32);
                                            let parameter_name = parameter.get_name().unwrap().to_string();
                                            if !vec.contains(&parameter_name) {
                                                vec.push(parameter_name);
                                            }
                                        },
                                        _ => {}
                                    }
                                },
                                _ => {} // FIXME
                            }
                        },
                        _ => {} // FIXME
                    }
                }
            },
            _ => {} // FIXME
        }
        vec
    }

    fn type_string(&self, gen:&codegen::GeneratorContext, brand:&::schema_capnp::brand::Reader,
            scope:Option<&Vec<String>>, module:Module, lifetime:&str) -> String {
        let the_mod = scope.unwrap_or_else( || &gen.scope_map[&self.get_id()]).connect("::");
        let mut reader_bindings:Vec<String> = vec!();
        let mut builder_bindings:Vec<String> = vec!();
        let parameters_count = self.expand_parameters(gen).len();
        let scopes = brand.get_scopes().unwrap();
        for scope in scopes.iter() {
            println!("scope");
            match scope.which().unwrap() {
                brand::scope::Inherit(_) => {
                    let parent_node = gen.node_map[&scope.get_scope_id()];
                    reader_bindings.extend(parent_node.get_parameters().unwrap().iter().map(|p| p.get_name().unwrap().to_string()+"Reader"));
                    builder_bindings.extend(parent_node.get_parameters().unwrap().iter().map(|p| p.get_name().unwrap().to_string()+"Builder"));
                },
                brand::scope::Bind(b) => {
                    b.unwrap().iter().map(|binding|
                        match binding.which().unwrap() {
                            brand::binding::Type(Ok(t)) => {
                                reader_bindings.push(t.type_string(gen, Module::Reader, lifetime));
                                builder_bindings.push(t.type_string(gen, Module::Builder, lifetime));
                            }
                            _ => {}
                        }
                    ).count();
                },
            }
        };
        println!("generating {:?} params done", self.get_display_name());
        let bracketed_lifetime = if lifetime == "" { "".to_string() } else {
            format!("<{}>", lifetime)
        };
        let lifetime_coma = if lifetime == "" { "".to_string() } else {
            format!("{},", lifetime)
        };
        let module_with_var = format!("{}{}", module, bracketed_lifetime);
        if parameters_count == 0 {
            format!("{}::{}", the_mod, module_with_var)
        } else {
            if parameters_count != reader_bindings.len() {
                reader_bindings.clear();
                builder_bindings.clear();
                for _ in 0 .. parameters_count {
                    reader_bindings.push(format!("::capnp::any_pointer::Reader<{}>", lifetime));
                    builder_bindings.push(format!("::capnp::any_pointer::Builder<{}>", lifetime));
                }
            }
            format!("{}::{}<{}{},{}>", the_mod, module, lifetime_coma, reader_bindings.connect(","), builder_bindings.connect(","))
        }
    }
}

impl <'a> RustTypeInfo for type_::Reader<'a> {

    fn type_string(&self, gen:&codegen::GeneratorContext,
                   module:Module, lifetime:&str) -> String {
        use codegen_types::RustTypeInfo;

        let bracketed_lifetime = if lifetime == "" { "".to_string() } else {
            format!("<{}>", lifetime)
        };
        let lifetime_coma = if lifetime == "" { "".to_string() } else {
            format!("{},", lifetime)
        };
        let module_with_var = format!("{}{}", module, bracketed_lifetime);

        match self.which().unwrap() {
            type_::Void(()) => "()".to_string(),
            type_::Bool(()) => "bool".to_string(),
            type_::Int8(()) => "i8".to_string(),
            type_::Int16(()) => "i16".to_string(),
            type_::Int32(()) => "i32".to_string(),
            type_::Int64(()) => "i64".to_string(),
            type_::Uint8(()) => "u8".to_string(),
            type_::Uint16(()) => "u16".to_string(),
            type_::Uint32(()) => "u32".to_string(),
            type_::Uint64(()) => "u64".to_string(),
            type_::Float32(()) => "f32".to_string(),
            type_::Float64(()) => "f64".to_string(),
            type_::Text(()) => format!("text::{}", module_with_var),
            type_::Data(()) => format!("data::{}", module_with_var),
            type_::Struct(st) => {
                gen.node_map[&st.get_type_id()].type_string(gen, &st.get_brand().unwrap(), None, module, lifetime)
            },
            type_::List(ot1) => {
                match ot1.get_element_type().unwrap().which() {
                    Err(_) => { panic!("unsupported type") },
                    Ok(type_::Struct(_)) => {
                        let inner = ot1.get_element_type().unwrap().type_string(gen, Module::Owned, "");
                        format!("struct_list::{}<{}{}>", module, lifetime_coma, inner)
                    },
                    Ok(type_::Enum(_)) => {
                        let inner = ot1.get_element_type().unwrap().type_string(gen, Module::Owned, "");
                        format!("enum_list::{}<{}{}>",module, lifetime_coma, inner)
                    },
                    Ok(type_::List(_)) => {
                        let inner = ot1.get_element_type().unwrap().type_string(gen, Module::Owned, "");
                        format!("list_list::{}<{}{}>", module, lifetime_coma, inner)
                    },
                    Ok(type_::Text(())) => {
                        format!("text_list::{}", module_with_var)
                    },
                    Ok(type_::Data(())) => {
                        format!("data_list::{}", module_with_var)
                    },
                    Ok(type_::Interface(_)) => {panic!("unimplemented") },
                    Ok(type_::AnyPointer(_)) => {panic!("List(AnyPointer) is unsupported")},
                    Ok(_) => {
                        let inner = ot1.get_element_type().unwrap().type_string(gen, Module::Owned, "");
                        format!("primitive_list::{}<{}{}>", module, lifetime_coma, inner)
                    },
                }
            },
            type_::Enum(en) => {
                let scope = &gen.scope_map[&en.get_type_id()];
                scope.connect("::").to_string()
            },
            type_::Interface(interface) => {
                let the_mod = gen.scope_map[&interface.get_type_id()].connect("::");
                format!("{}::Client", the_mod)
            },
            type_::AnyPointer(pointer) => {
                match pointer.which().unwrap() {
                    type_::any_pointer::Parameter(def) => {
                        let the_struct = &gen.node_map[&def.get_scope_id()];
                        let parameters = the_struct.get_parameters().unwrap();
                        let parameter = parameters.get(def.get_parameter_index() as u32);
                        let parameter_name = parameter.get_name().unwrap();
                        format!("{}{}", parameter_name, module)
                    },
                    _ => {
                        format!("::capnp::any_pointer::{}{}", module, bracketed_lifetime)
                    }
                }
            }
        }
    }

    fn is_parameterized(&self) -> bool {
        match self.which().unwrap() {
            type_::AnyPointer(pointer) => {
                match pointer.which().unwrap() {
                    type_::any_pointer::Parameter(_) => true,
                    _ => false
                }
            }
            _ => false
        }
    }

    fn is_branded(&self) -> bool {
        match self.which().unwrap() {
            type_::Struct(st) => {
                let brand = st.get_brand().unwrap();
                let scopes = brand.get_scopes().unwrap();
                scopes.len() > 0
            }
            _ => false
        }
    }

    #[inline(always)]
    fn is_prim(&self) -> bool {
        match self.which().unwrap() {
            type_::Int8(()) | type_::Int16(()) | type_::Int32(()) | type_::Int64(()) |
            type_::Uint8(()) | type_::Uint16(()) | type_::Uint32(()) | type_::Uint64(()) |
            type_::Float32(()) | type_::Float64(()) | type_::Void(()) | type_::Bool(()) => true,
            _ => false
        }
    }
}

<commit_msg>println<commit_after>use schema_capnp::*;

use codegen;

#[derive(Copy,Clone,PartialEq)]
pub enum Module { Reader, Builder, Owned }
impl ::std::fmt::Display for Module {
    fn fmt(&self, fmt:&mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        ::std::fmt::Display::fmt(match self {
            &Module::Reader => "Reader",
            &Module::Builder => "Builder",
            &Module::Owned => "Owned",
        }, fmt)
    }
}

// this is a collection of helpers acting on a "Node" (most of them are Type definitions)
pub trait RustNodeInfo {
    fn type_string(&self, gen:&codegen::GeneratorContext, brand:&::schema_capnp::brand::Reader,
        scope:Option<&Vec<String>>, module:Module, lifetime:&str) -> String;

    // in rust, we have only nestable modules, and parameterizable types...
    // so a logically child struct will be a physical sibling to its logical parent. so it must
    // keep track of all parameterization on its own
    // this function recursively parse a node definition to find out the parameters used and inherited by scoping
    // and add them to the explicit parameters
    // the result is the actual parameters for the type to be generated
    fn expand_parameters(&self, gen:&::codegen::GeneratorContext) -> Vec<String>;
}

// this is a collection of helpers acting on a "Type" (someplace where a Type is used, not defined)
pub trait RustTypeInfo {

    fn is_prim(&self) -> bool;
    fn is_parameterized(&self) -> bool;
    fn is_branded(&self) -> bool;
    fn type_string(&self, gen:&codegen::GeneratorContext,
        module:Module, lifetime:&str) -> String;
}

impl <'a> RustNodeInfo for node::Reader<'a> {

    fn expand_parameters(&self, gen:&::codegen::GeneratorContext) -> Vec<String> {
        let mut vec:Vec<String> = self.get_parameters().unwrap().iter().map(|p| p.get_name().unwrap().to_string()).collect();
        match self.which().unwrap() {
            ::schema_capnp::node::Struct(struct_reader) => {
                let fields = struct_reader.get_fields().unwrap();
                for field in fields.iter() {
                    match field.which().unwrap() {
                        ::schema_capnp::field::Slot(slot) => {
                            let typ = slot.get_type().unwrap().which().unwrap();
                            match typ {
                                ::schema_capnp::type_::Struct(st) => {
                                    let brand = st.get_brand().unwrap();
                                    let scopes = brand.get_scopes().unwrap();
                                    for scope in scopes.iter() {
                                        match scope.which().unwrap() {
                                            ::schema_capnp::brand::scope::Inherit(_) => {
                                                let parent_node = gen.node_map[&scope.get_scope_id()];
                                                for p in parent_node.get_parameters().unwrap().iter() {
                                                    let parameter_name = p.get_name().unwrap().to_string();
                                                    if !vec.contains(&parameter_name) {
                                                        vec.push(parameter_name);
                                                        }
                                                }
                                            },
                                            _ => {}
                                        }
                                    }
                                },
                                ::schema_capnp::type_::AnyPointer(any) => {
                                    match any.which().unwrap() {
                                        ::schema_capnp::type_::any_pointer::Parameter(def) => {
                                            let the_struct = &gen.node_map[&def.get_scope_id()];
                                            let parameters = the_struct.get_parameters().unwrap();
                                            let parameter = parameters.get(def.get_parameter_index() as u32);
                                            let parameter_name = parameter.get_name().unwrap().to_string();
                                            if !vec.contains(&parameter_name) {
                                                vec.push(parameter_name);
                                            }
                                        },
                                        _ => {}
                                    }
                                },
                                _ => {} // FIXME
                            }
                        },
                        _ => {} // FIXME
                    }
                }
            },
            _ => {} // FIXME
        }
        vec
    }

    fn type_string(&self, gen:&codegen::GeneratorContext, brand:&::schema_capnp::brand::Reader,
            scope:Option<&Vec<String>>, module:Module, lifetime:&str) -> String {
        let the_mod = scope.unwrap_or_else( || &gen.scope_map[&self.get_id()]).connect("::");
        let mut reader_bindings:Vec<String> = vec!();
        let mut builder_bindings:Vec<String> = vec!();
        let parameters_count = self.expand_parameters(gen).len();
        let scopes = brand.get_scopes().unwrap();
        for scope in scopes.iter() {
            match scope.which().unwrap() {
                brand::scope::Inherit(_) => {
                    let parent_node = gen.node_map[&scope.get_scope_id()];
                    reader_bindings.extend(parent_node.get_parameters().unwrap().iter().map(|p| p.get_name().unwrap().to_string()+"Reader"));
                    builder_bindings.extend(parent_node.get_parameters().unwrap().iter().map(|p| p.get_name().unwrap().to_string()+"Builder"));
                },
                brand::scope::Bind(b) => {
                    b.unwrap().iter().map(|binding|
                        match binding.which().unwrap() {
                            brand::binding::Type(Ok(t)) => {
                                reader_bindings.push(t.type_string(gen, Module::Reader, lifetime));
                                builder_bindings.push(t.type_string(gen, Module::Builder, lifetime));
                            }
                            _ => {}
                        }
                    ).count();
                },
            }
        };
        let bracketed_lifetime = if lifetime == "" { "".to_string() } else {
            format!("<{}>", lifetime)
        };
        let lifetime_coma = if lifetime == "" { "".to_string() } else {
            format!("{},", lifetime)
        };
        let module_with_var = format!("{}{}", module, bracketed_lifetime);
        if parameters_count == 0 {
            format!("{}::{}", the_mod, module_with_var)
        } else {
            if parameters_count != reader_bindings.len() {
                reader_bindings.clear();
                builder_bindings.clear();
                for _ in 0 .. parameters_count {
                    reader_bindings.push(format!("::capnp::any_pointer::Reader<{}>", lifetime));
                    builder_bindings.push(format!("::capnp::any_pointer::Builder<{}>", lifetime));
                }
            }
            format!("{}::{}<{}{},{}>", the_mod, module, lifetime_coma, reader_bindings.connect(","), builder_bindings.connect(","))
        }
    }
}

impl <'a> RustTypeInfo for type_::Reader<'a> {

    fn type_string(&self, gen:&codegen::GeneratorContext,
                   module:Module, lifetime:&str) -> String {
        use codegen_types::RustTypeInfo;

        let bracketed_lifetime = if lifetime == "" { "".to_string() } else {
            format!("<{}>", lifetime)
        };
        let lifetime_coma = if lifetime == "" { "".to_string() } else {
            format!("{},", lifetime)
        };
        let module_with_var = format!("{}{}", module, bracketed_lifetime);

        match self.which().unwrap() {
            type_::Void(()) => "()".to_string(),
            type_::Bool(()) => "bool".to_string(),
            type_::Int8(()) => "i8".to_string(),
            type_::Int16(()) => "i16".to_string(),
            type_::Int32(()) => "i32".to_string(),
            type_::Int64(()) => "i64".to_string(),
            type_::Uint8(()) => "u8".to_string(),
            type_::Uint16(()) => "u16".to_string(),
            type_::Uint32(()) => "u32".to_string(),
            type_::Uint64(()) => "u64".to_string(),
            type_::Float32(()) => "f32".to_string(),
            type_::Float64(()) => "f64".to_string(),
            type_::Text(()) => format!("text::{}", module_with_var),
            type_::Data(()) => format!("data::{}", module_with_var),
            type_::Struct(st) => {
                gen.node_map[&st.get_type_id()].type_string(gen, &st.get_brand().unwrap(), None, module, lifetime)
            },
            type_::List(ot1) => {
                match ot1.get_element_type().unwrap().which() {
                    Err(_) => { panic!("unsupported type") },
                    Ok(type_::Struct(_)) => {
                        let inner = ot1.get_element_type().unwrap().type_string(gen, Module::Owned, "");
                        format!("struct_list::{}<{}{}>", module, lifetime_coma, inner)
                    },
                    Ok(type_::Enum(_)) => {
                        let inner = ot1.get_element_type().unwrap().type_string(gen, Module::Owned, "");
                        format!("enum_list::{}<{}{}>",module, lifetime_coma, inner)
                    },
                    Ok(type_::List(_)) => {
                        let inner = ot1.get_element_type().unwrap().type_string(gen, Module::Owned, "");
                        format!("list_list::{}<{}{}>", module, lifetime_coma, inner)
                    },
                    Ok(type_::Text(())) => {
                        format!("text_list::{}", module_with_var)
                    },
                    Ok(type_::Data(())) => {
                        format!("data_list::{}", module_with_var)
                    },
                    Ok(type_::Interface(_)) => {panic!("unimplemented") },
                    Ok(type_::AnyPointer(_)) => {panic!("List(AnyPointer) is unsupported")},
                    Ok(_) => {
                        let inner = ot1.get_element_type().unwrap().type_string(gen, Module::Owned, "");
                        format!("primitive_list::{}<{}{}>", module, lifetime_coma, inner)
                    },
                }
            },
            type_::Enum(en) => {
                let scope = &gen.scope_map[&en.get_type_id()];
                scope.connect("::").to_string()
            },
            type_::Interface(interface) => {
                let the_mod = gen.scope_map[&interface.get_type_id()].connect("::");
                format!("{}::Client", the_mod)
            },
            type_::AnyPointer(pointer) => {
                match pointer.which().unwrap() {
                    type_::any_pointer::Parameter(def) => {
                        let the_struct = &gen.node_map[&def.get_scope_id()];
                        let parameters = the_struct.get_parameters().unwrap();
                        let parameter = parameters.get(def.get_parameter_index() as u32);
                        let parameter_name = parameter.get_name().unwrap();
                        format!("{}{}", parameter_name, module)
                    },
                    _ => {
                        format!("::capnp::any_pointer::{}{}", module, bracketed_lifetime)
                    }
                }
            }
        }
    }

    fn is_parameterized(&self) -> bool {
        match self.which().unwrap() {
            type_::AnyPointer(pointer) => {
                match pointer.which().unwrap() {
                    type_::any_pointer::Parameter(_) => true,
                    _ => false
                }
            }
            _ => false
        }
    }

    fn is_branded(&self) -> bool {
        match self.which().unwrap() {
            type_::Struct(st) => {
                let brand = st.get_brand().unwrap();
                let scopes = brand.get_scopes().unwrap();
                scopes.len() > 0
            }
            _ => false
        }
    }

    #[inline(always)]
    fn is_prim(&self) -> bool {
        match self.which().unwrap() {
            type_::Int8(()) | type_::Int16(()) | type_::Int32(()) | type_::Int64(()) |
            type_::Uint8(()) | type_::Uint16(()) | type_::Uint32(()) | type_::Uint64(()) |
            type_::Float32(()) | type_::Float64(()) | type_::Void(()) | type_::Bool(()) => true,
            _ => false
        }
    }
}

<|endoftext|>


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

use pest::prelude::*;

use super::*;

impl_rdp! {
    grammar! {
        program = _{ statement* ~ eoi }

        statement = { declaration | assignment | while_loop | conditional | (expr ~ semi) | comment }

        comment = @{ block_comment | line_comment }
        line_comment = _{ ["//"] ~ (!(["\r"] | ["\n"]) ~ any)* ~ (["\n"] | ["\r\n"] | ["\r"] | eoi) }
        block_comment = _{ ["/*"] ~ ((!(["*/"]) ~ any) | block_comment)* ~ ["*/"] }

        assignment = { identifier ~ op_assign ~ expr ~ semi}
        declaration = { ["let"] ~ pattern ~ [":"] ~ type_def ~ (op_assign ~ expr)? ~ semi}
        op_assign = { ["="] }
        pattern = { identifier }

        type_def = _{ identifier | array_type }
        array_type = { ["["] ~ type_def ~ semi ~ array_size ~ ["]"] }
        array_size = _{ unspecified | expr }
        unspecified = { ["_"] }

        while_loop = { ["while"] ~ expr ~ block }

        expr = {
            { field_access | identifier | func_call | conditional | string_literal | number }

            // Ordered from lowest precedence to highest precedence
            bool_or = {< ["||"] }
            bool_and = {< ["&&"] }
            // NOTE: Order matters! { ["<"] | ["<="] } will never match "<="
            comparison = { ["=="] | ["!="] | [">="] | ["<="] | [">"] | ["<"] }
        }

        conditional = { ["if"] ~ expr ~ block ~ (["else"] ~ conditional)? ~ (["else"] ~ block)? }

        // This allows {} and {statement; statement; statement;} and {statement; expr} and {expr}
        block = _{ block_start ~ statement* ~ expr? ~ block_end }
        block_start = { ["{"] }
        block_end = { ["}"] }

        func_call = { identifier ~ func_args }
        field_access = { identifier ~ op_access ~ identifier ~ func_args? }
        op_access = { ["."] }

        // This allows () and (func_arg, func_arg) and (func_arg) and (func_arg,)
        func_args = _{ func_args_start ~ (func_arg ~ [","])* ~ func_arg? ~ func_args_end }
        func_args_start = { ["("] }
        func_args_end = { [")"] }
        func_arg = _{ expr }

        string_literal = @{ ["\""] ~ literal_char* ~ ["\""] }
        literal_char = _{ escape_sequence | (!["\""] ~ any) }
        escape_sequence = _{ ["\\\\"] | ["\\\""] | ["\\\'"] | ["\\n"] | ["\\r"] | ["\\t"] | ["\\0"] | ["\\f"] | ["\\v"] | ["\\e"] }

        identifier = @{ !keyword ~ (alpha | ["_"]) ~ (alphanumeric | ["_"])* }
        alpha = _{ ['a'..'z'] | ['A'..'Z'] }
        alphanumeric = _{ alpha | ['0'..'9'] }

        number = @{ ["0"] | (nonzero ~ digit*) }
        // Allow "_" in numbers for grouping: 1_000_000 == 1000000
        digit = _{ ["0"] | nonzero | ["_"] }
        nonzero = _{ ['1'..'9'] }

        whitespace = _{ [" "] | ["\t"] | ["\u{000C}"] | ["\r"] | ["\n"] }
        // NOTE: When changing this code, make sure you don't have a subset of a word before
        // another word. For example: { ["type"] | ["typeof"] } will never match "typeof"
        keyword = @{
            ["abstract"] | ["as"] | ["become"] | ["break"] | ["byte"] | ["class"] | ["clear"] |
            ["const"] | ["continue"] | ["do"] | ["else"] | ["enum"] | ["eval"] | ["export"] |
            ["extern"] | ["false"] | ["final"] | ["fn"] | ["for"] | ["if"] | ["impl"] | ["import"] |
            ["in"] | ["let"] | ["loop"] | ["match"] | ["mod"] | ["move"] | ["mut"] | ["of"] |
            ["out"] | ["pub"] | ["raw"] | ["ref"] | ["return"] | ["self"] | ["static"] |
            ["struct"] | ["super"] | ["trait"] | ["true"] | ["typeof"] | ["type"] | ["unsafe"] |
            ["use"] | ["where"] | ["while"] | ["yield"]
        }

        // These are separate rules because we can use the generated rules and tokens to provide
        // better error messages
        semi = { [";"] }
    }

    process! {
        parse_program(&self) -> Program {
            (list: _program()) => {
                Program::new(list.into_iter().collect())
            },
        }

        _program(&self) -> VecDeque<Statement> {
            (_: statement, head: _statement(), mut tail: _program()) => {
                tail.push_front(head);

                tail
            },
            (&text: comment, mut tail: _program()) => {
                tail.push_front(Statement::Comment(text.into()));

                tail
            },
            () => {
                VecDeque::new()
            },
        }

        _statement(&self) -> Statement {
            (&text: comment) => {
                Statement::Comment(text.into())
            },
            (_: declaration, pattern: _pattern(), type_def: _type_def(), _: op_assign, _: expr, expr: _expr(), _: semi) => {
                Statement::Declaration {pattern: pattern, type_def: type_def, expr: Some(expr)}
            },
            (_: declaration, pattern: _pattern(), type_def: _type_def(), _: semi) => {
                Statement::Declaration {pattern: pattern, type_def: type_def, expr: None}
            },
            (_: assignment, ident: _identifier(), _: op_assign, _: expr, expr: _expr(), _: semi) => {
                Statement::Assignment {lhs: ident, expr: expr}
            },
            (_: while_loop, _: expr, condition: _expr(), body: _block()) => {
                Statement::WhileLoop {condition: condition, body: body}
            },
            // This should always be last as it will catch pretty much any cases that weren't caught above
            (_: expr, expr: _expr(), _: semi) => {
                Statement::Expression {expr: expr}
            },
        }

        _pattern(&self) -> Pattern {
            (_: pattern, ident: _identifier()) => {
                Pattern::Identifier(ident)
            },
        }

        _type_def(&self) -> TypeDefinition {
            (ident: _identifier()) => {
                TypeDefinition::Name {name: ident}
            },
            (_: array_type, type_def: _type_def(), _: semi, size: _optional_expr()) => {
                TypeDefinition::Array {type_def: Box::new(type_def), size: size}
            },
        }

        _optional_expr(&self) -> Option<Expression> {
            (_: expr, e: _expr()) => Some(e),
            () => None,
        }

        _expr(&self) -> Expression {
            (_: func_call, method: _identifier(), args: _func_args()) => {
                Expression::Call {
                    method: Box::new(Expression::Identifier(method)),
                    args: args,
                }
            },
            (_: field_access, expr: _field_access()) => {
                expr
            },
            (&ident: identifier) => {
                Expression::Identifier(ident.into())
            },
            (&s: string_literal) => {
                // The first and last quotes need to be removed
                Expression::StringLiteral(s[1..s.len()-2].into())
            },
            (&s: number) => {
                // If our grammar is correct, we are guarenteed that this will work
                Expression::Number(s.parse().unwrap())
            },
        }

        _field_access(&self) -> Expression {
            (target: _identifier(), _: op_access, field: _identifier(), args: _func_args()) => {
                Expression::Call {
                    method: Box::new(Expression::Access {
                        target: Box::new(Expression::Identifier(target)),
                        field: Box::new(Expression::Identifier(field)),
                    }),
                    args: args,
                }
            },
            (target: _identifier(), _: op_access, field: _identifier()) => {
                Expression::Access {
                    target: Box::new(Expression::Identifier(target)),
                    field: Box::new(Expression::Identifier(field)),
                }
            },
        }

        _func_args(&self) -> FuncArgs {
            (_: func_args_start, deque: _expr_deque()) => {
                deque.into_iter().collect()
            },
        }

        _expr_deque(&self) -> VecDeque<Expression> {
            (_: func_args_end) => {
                VecDeque::new()
            },
            (_: expr, head: _expr(), mut tail: _expr_deque()) => {
                tail.push_front(head);

                tail
            },
        }

        _block(&self) -> Block {
            (_: block_start, deque: _block_deque()) => {
                deque.into_iter().collect()
            },
        }

        _block_deque(&self) -> VecDeque<Statement> {
            (_: statement, head: _statement(), mut tail: _block_deque()) => {
                tail.push_front(head);

                tail
            },
            (_: expr, head: _expr(), mut tail: _block_deque()) => {
                tail.push_front(Statement::Expression {expr: head});

                tail
            },
            (_: block_end) => {
                VecDeque::new()
            },
        }

        _identifier(&self) -> Identifier {
            (&ident: identifier) => {
                ident.into()
            },
        }
    }
}

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

    use pest::prelude::*;

    #[test]
    fn string_literal() {
        test_parse(r#""""#, |p| p.string_literal(), vec![
            Token::new(Rule::string_literal, 0, 2),
        ]);

        test_parse(r#""foo""#, |p| p.string_literal(), vec![
            Token::new(Rule::string_literal, 0, 5),
        ]);
    }

    #[test]
    fn number() {
        test_parse(r#"0"#, |p| p.number(), vec![
            Token::new(Rule::number, 0, 1),
        ]);

        test_parse(r#"100"#, |p| p.number(), vec![
            Token::new(Rule::number, 0, 3),
        ]);

        test_parse(r#"1_000_000"#, |p| p.number(), vec![
            Token::new(Rule::number, 0, 9),
        ]);
    }

    #[test]
    fn field_access() {
        test_parse(r#"foo.bar"#, |p| p.field_access(), vec![
            Token::new(Rule::field_access, 0, 7),
            Token::new(Rule::identifier, 0, 3),
            Token::new(Rule::op_access, 3, 4),
            Token::new(Rule::identifier, 4, 7),
        ]);
    }

    fn test_parse<F>(input: &'static str, parse: F, tokens: Vec<Token<Rule>>)
        where F: FnOnce(&mut Rdp<StringInput>) -> bool {

        let mut parser = parser_from(input);
        assert!(parse(&mut parser), "Parsing failed");
        assert!(parser.end(), "Parser did not reach eoi");

        assert_eq!(parser.queue(), &tokens);
    }

    fn test_fail<F>(input: &'static str, parse: F)
        where F: FnOnce(&mut Rdp<StringInput>) -> bool {

        let mut parser = parser_from(input);
        assert!(!parse(&mut parser), "Parsing passed when expected it to fail");
        assert!(!parser.end(), "Parser reached end when expected it to fail");

        assert!(parser.queue().is_empty(), "Queue was not empty despite expecting to fail");
    }

    fn parser_from(s: &'static str) -> Rdp<StringInput> {
        Rdp::new(StringInput::new(s))
    }
}
<commit_msg>Fixing bugs in type def matcher method<commit_after>use std::collections::VecDeque;

use pest::prelude::*;

use super::*;

impl_rdp! {
    grammar! {
        program = _{ statement* ~ eoi }

        statement = { declaration | assignment | while_loop | conditional | (expr ~ semi) | comment }

        comment = @{ block_comment | line_comment }
        line_comment = _{ ["//"] ~ (!(["\r"] | ["\n"]) ~ any)* ~ (["\n"] | ["\r\n"] | ["\r"] | eoi) }
        block_comment = _{ ["/*"] ~ ((!(["*/"]) ~ any) | block_comment)* ~ ["*/"] }

        assignment = { identifier ~ op_assign ~ expr ~ semi}
        declaration = { ["let"] ~ pattern ~ [":"] ~ type_def ~ (op_assign ~ expr)? ~ semi}
        op_assign = { ["="] }
        pattern = { identifier }

        type_def = _{ identifier | array_type }
        array_type = { ["["] ~ type_def ~ semi ~ array_size ~ ["]"] }
        array_size = _{ unspecified | expr }
        unspecified = { ["_"] }

        while_loop = { ["while"] ~ expr ~ block }

        expr = {
            { field_access | identifier | func_call | conditional | string_literal | number }

            // Ordered from lowest precedence to highest precedence
            bool_or = {< ["||"] }
            bool_and = {< ["&&"] }
            // NOTE: Order matters! { ["<"] | ["<="] } will never match "<="
            comparison = { ["=="] | ["!="] | [">="] | ["<="] | [">"] | ["<"] }
        }

        conditional = { ["if"] ~ expr ~ block ~ (["else"] ~ conditional)? ~ (["else"] ~ block)? }

        // This allows {} and {statement; statement; statement;} and {statement; expr} and {expr}
        block = _{ block_start ~ statement* ~ expr? ~ block_end }
        block_start = { ["{"] }
        block_end = { ["}"] }

        func_call = { identifier ~ func_args }
        field_access = { identifier ~ op_access ~ identifier ~ func_args? }
        op_access = { ["."] }

        // This allows () and (func_arg, func_arg) and (func_arg) and (func_arg,)
        func_args = _{ func_args_start ~ (func_arg ~ [","])* ~ func_arg? ~ func_args_end }
        func_args_start = { ["("] }
        func_args_end = { [")"] }
        func_arg = _{ expr }

        string_literal = @{ ["\""] ~ literal_char* ~ ["\""] }
        literal_char = _{ escape_sequence | (!["\""] ~ any) }
        escape_sequence = _{ ["\\\\"] | ["\\\""] | ["\\\'"] | ["\\n"] | ["\\r"] | ["\\t"] | ["\\0"] | ["\\f"] | ["\\v"] | ["\\e"] }

        identifier = @{ !keyword ~ (alpha | ["_"]) ~ (alphanumeric | ["_"])* }
        alpha = _{ ['a'..'z'] | ['A'..'Z'] }
        alphanumeric = _{ alpha | ['0'..'9'] }

        number = @{ ["0"] | (nonzero ~ digit*) }
        // Allow "_" in numbers for grouping: 1_000_000 == 1000000
        digit = _{ ["0"] | nonzero | ["_"] }
        nonzero = _{ ['1'..'9'] }

        whitespace = _{ [" "] | ["\t"] | ["\u{000C}"] | ["\r"] | ["\n"] }
        // NOTE: When changing this code, make sure you don't have a subset of a word before
        // another word. For example: { ["type"] | ["typeof"] } will never match "typeof"
        keyword = @{
            ["abstract"] | ["as"] | ["become"] | ["break"] | ["byte"] | ["class"] | ["clear"] |
            ["const"] | ["continue"] | ["do"] | ["else"] | ["enum"] | ["eval"] | ["export"] |
            ["extern"] | ["false"] | ["final"] | ["fn"] | ["for"] | ["if"] | ["impl"] | ["import"] |
            ["in"] | ["let"] | ["loop"] | ["match"] | ["mod"] | ["move"] | ["mut"] | ["of"] |
            ["out"] | ["pub"] | ["raw"] | ["ref"] | ["return"] | ["self"] | ["static"] |
            ["struct"] | ["super"] | ["trait"] | ["true"] | ["typeof"] | ["type"] | ["unsafe"] |
            ["use"] | ["where"] | ["while"] | ["yield"]
        }

        // These are separate rules because we can use the generated rules and tokens to provide
        // better error messages
        semi = { [";"] }
    }

    process! {
        parse_program(&self) -> Program {
            (list: _program()) => {
                Program::new(list.into_iter().collect())
            },
        }

        _program(&self) -> VecDeque<Statement> {
            (_: statement, head: _statement(), mut tail: _program()) => {
                tail.push_front(head);

                tail
            },
            (&text: comment, mut tail: _program()) => {
                tail.push_front(Statement::Comment(text.into()));

                tail
            },
            () => {
                VecDeque::new()
            },
        }

        _statement(&self) -> Statement {
            (&text: comment) => {
                Statement::Comment(text.into())
            },
            (_: declaration, pattern: _pattern(), type_def: _type_def(), _: op_assign, _: expr, expr: _expr(), _: semi) => {
                Statement::Declaration {pattern: pattern, type_def: type_def, expr: Some(expr)}
            },
            (_: declaration, pattern: _pattern(), type_def: _type_def(), _: semi) => {
                Statement::Declaration {pattern: pattern, type_def: type_def, expr: None}
            },
            (_: assignment, ident: _identifier(), _: op_assign, _: expr, expr: _expr(), _: semi) => {
                Statement::Assignment {lhs: ident, expr: expr}
            },
            (_: while_loop, _: expr, condition: _expr(), body: _block()) => {
                Statement::WhileLoop {condition: condition, body: body}
            },
            // This should always be last as it will catch pretty much any cases that weren't caught above
            (_: expr, expr: _expr(), _: semi) => {
                Statement::Expression {expr: expr}
            },
        }

        _pattern(&self) -> Pattern {
            (_: pattern, ident: _identifier()) => {
                Pattern::Identifier(ident)
            },
        }

        _type_def(&self) -> TypeDefinition {
            (_: array_type, type_def: _type_def(), _: semi, _: unspecified) => {
                TypeDefinition::Array {type_def: Box::new(type_def), size: None}
            },
            (_: array_type, type_def: _type_def(), _: semi, _: expr, size: _expr()) => {
                TypeDefinition::Array {type_def: Box::new(type_def), size: Some(size)}
            },
            (ident: _identifier()) => {
                TypeDefinition::Name {name: ident}
            },
        }

        _expr(&self) -> Expression {
            (_: func_call, method: _identifier(), args: _func_args()) => {
                Expression::Call {
                    method: Box::new(Expression::Identifier(method)),
                    args: args,
                }
            },
            (_: field_access, expr: _field_access()) => {
                expr
            },
            (&ident: identifier) => {
                Expression::Identifier(ident.into())
            },
            (&s: string_literal) => {
                // The first and last quotes need to be removed
                Expression::StringLiteral(s[1..s.len()-2].into())
            },
            (&s: number) => {
                // If our grammar is correct, we are guarenteed that this will work
                Expression::Number(s.parse().unwrap())
            },
        }

        _field_access(&self) -> Expression {
            (target: _identifier(), _: op_access, field: _identifier(), args: _func_args()) => {
                Expression::Call {
                    method: Box::new(Expression::Access {
                        target: Box::new(Expression::Identifier(target)),
                        field: Box::new(Expression::Identifier(field)),
                    }),
                    args: args,
                }
            },
            (target: _identifier(), _: op_access, field: _identifier()) => {
                Expression::Access {
                    target: Box::new(Expression::Identifier(target)),
                    field: Box::new(Expression::Identifier(field)),
                }
            },
        }

        _func_args(&self) -> FuncArgs {
            (_: func_args_start, deque: _expr_deque()) => {
                deque.into_iter().collect()
            },
        }

        _expr_deque(&self) -> VecDeque<Expression> {
            (_: func_args_end) => {
                VecDeque::new()
            },
            (_: expr, head: _expr(), mut tail: _expr_deque()) => {
                tail.push_front(head);

                tail
            },
        }

        _block(&self) -> Block {
            (_: block_start, deque: _block_deque()) => {
                deque.into_iter().collect()
            },
        }

        _block_deque(&self) -> VecDeque<Statement> {
            (_: statement, head: _statement(), mut tail: _block_deque()) => {
                tail.push_front(head);

                tail
            },
            (_: expr, head: _expr(), mut tail: _block_deque()) => {
                tail.push_front(Statement::Expression {expr: head});

                tail
            },
            (_: block_end) => {
                VecDeque::new()
            },
        }

        _identifier(&self) -> Identifier {
            (&ident: identifier) => {
                ident.into()
            },
        }
    }
}

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

    use pest::prelude::*;

    #[test]
    fn string_literal() {
        test_parse(r#""""#, |p| p.string_literal(), vec![
            Token::new(Rule::string_literal, 0, 2),
        ]);

        test_parse(r#""foo""#, |p| p.string_literal(), vec![
            Token::new(Rule::string_literal, 0, 5),
        ]);
    }

    #[test]
    fn number() {
        test_parse(r#"0"#, |p| p.number(), vec![
            Token::new(Rule::number, 0, 1),
        ]);

        test_parse(r#"100"#, |p| p.number(), vec![
            Token::new(Rule::number, 0, 3),
        ]);

        test_parse(r#"1_000_000"#, |p| p.number(), vec![
            Token::new(Rule::number, 0, 9),
        ]);
    }

    #[test]
    fn field_access() {
        test_parse(r#"foo.bar"#, |p| p.field_access(), vec![
            Token::new(Rule::field_access, 0, 7),
            Token::new(Rule::identifier, 0, 3),
            Token::new(Rule::op_access, 3, 4),
            Token::new(Rule::identifier, 4, 7),
        ]);
    }

    fn test_parse<F>(input: &'static str, parse: F, tokens: Vec<Token<Rule>>)
        where F: FnOnce(&mut Rdp<StringInput>) -> bool {

        let mut parser = parser_from(input);
        assert!(parse(&mut parser), "Parsing failed");
        assert!(parser.end(), "Parser did not reach eoi");

        assert_eq!(parser.queue(), &tokens);
    }

    fn test_fail<F>(input: &'static str, parse: F)
        where F: FnOnce(&mut Rdp<StringInput>) -> bool {

        let mut parser = parser_from(input);
        assert!(!parse(&mut parser), "Parsing passed when expected it to fail");
        assert!(!parser.end(), "Parser reached end when expected it to fail");

        assert!(parser.queue().is_empty(), "Queue was not empty despite expecting to fail");
    }

    fn parser_from(s: &'static str) -> Rdp<StringInput> {
        Rdp::new(StringInput::new(s))
    }
}
<|endoftext|>


<commit_before>macro_rules! try_opt {
    ($value:expr) => {{
        match $value {
            Some(v) => v,
            None    => return None,
        }
    }};
}

macro_rules! gen_struct_value {
    // Default with no display name
    ($parent:expr, self, default) => {{
        gen_struct_value!($parent, self, Default::default())
    }};

    // Default value
    ($parent:expr, $disp_name:expr, default) => {{
        gen_struct_value!($parent, $disp_name, Default::default())
    }};

    // Option
    ($parent:expr, $disp_name:expr, None) => {{
        ParseYaml::from(&$parent[$disp_name])
    }};

    // Option with minimum
    ($parent:expr, $disp_name:expr, [$min:expr, None]) => {{
        let result = gen_struct_value!($parent, $disp_name, None);
        result.map(|v| if v < $min { $min } else { v })
    }};

    // Value with minimum
    ($parent:expr, $disp_name:expr, [$min:expr, $default:expr]) => {{
        let result = gen_struct_value!($parent, $disp_name, $default);
        if result < $min { $min } else { result }
    }};

    // Value with no display name that exits early on failure
    ($parent:expr, self, fail) => {{
        try_opt!(ParseYaml::from(&$parent))
    }};

    // Value with no display name
    ($parent:expr, self, $default:expr) => {{
        ParseYaml::from(&$parent).unwrap_or($default)
    }};

    // Value that exits early on failure
    ($parent:expr, $disp_name:expr, fail) => {{
        try_opt!(ParseYaml::from(&$parent[$disp_name]))
    }};

    // Value
    ($parent:expr, $disp_name:expr, $default:expr) => {{
        ParseYaml::from(&$parent[$disp_name]).unwrap_or($default)
    }};
}

macro_rules! get_default {
    (default)                    => (Default::default());
    (fail)                       => (Default::default());
    ([$min:expr, $default:expr]) => ($default);
    ($default:expr)              => ($default);
}

#[macro_export]
macro_rules! create_config_struct {
    ($name:ident, $($field:ident: $field_t:ty => $disp_name:tt => $default:tt,)+) => {
        #[derive(Debug)]
        pub struct $name {
            $(pub $field: $field_t,)+
        }

        impl ParseYaml for $name {
            fn from(doc: &Yaml) -> Option<$name> {
                Some($name {
                    $($field: gen_struct_value!(doc, $disp_name, $default),)+
                })
            }
        }

        impl Default for $name {
            fn default() -> $name {
                $name {
                    $($field: get_default!($default),)+
                }
            }
        }
    };
}

#[macro_export]
macro_rules! create_config_enum {
    ($name:ident, $($field:ident($field_t:ty) => $disp_name:expr,)+) => {
        #[derive(Debug)]
        pub enum $name {
            $($field($field_t),)+
        }

        impl ParseYaml for $name {
            fn from(doc: &Yaml) -> Option<$name> {
                $(
                match ParseYaml::from(&doc[$disp_name]) {
                    Some(v) => return Some($name::$field(v)),
                    None    => (),
                }
                )+
                None
            }
        }

        impl Default for $name {
            fn default() -> $name {
                panic!("unable to get default for {} enum", stringify!($name));
            }
        }
    };

    ($name:ident, $($field:ident => $disp_name:expr,)+) => {
         #[derive(Debug)]
        pub enum $name {
            $($field,)+
        }

        impl ParseYaml for $name {
            fn from(doc: &Yaml) -> Option<$name> {
                let result: Option<String> = ParseYaml::from(&doc);

                result.and_then(|result| {
                    match result.as_str() {
                        $($disp_name => Some($name::$field),)+
                        _ => None,
                    }
                })
            }
        }

        impl Default for $name {
            fn default() -> $name {
                panic!("unable to get default for {} enum", stringify!($name));
            }
        }
    };
}<commit_msg>Fix my horrific indentation<commit_after>macro_rules! try_opt {
    ($value:expr) => {{
        match $value {
            Some(v) => v,
            None    => return None,
        }
    }};
}

macro_rules! gen_struct_value {
    // Default with no display name
    ($parent:expr, self, default) => {{
        gen_struct_value!($parent, self, Default::default())
    }};

    // Default value
    ($parent:expr, $disp_name:expr, default) => {{
        gen_struct_value!($parent, $disp_name, Default::default())
    }};

    // Option
    ($parent:expr, $disp_name:expr, None) => {{
        ParseYaml::from(&$parent[$disp_name])
    }};

    // Option with minimum
    ($parent:expr, $disp_name:expr, [$min:expr, None]) => {{
        let result = gen_struct_value!($parent, $disp_name, None);
        result.map(|v| if v < $min { $min } else { v })
    }};

    // Value with minimum
    ($parent:expr, $disp_name:expr, [$min:expr, $default:expr]) => {{
        let result = gen_struct_value!($parent, $disp_name, $default);
        if result < $min { $min } else { result }
    }};

    // Value with no display name that exits early on failure
    ($parent:expr, self, fail) => {{
        try_opt!(ParseYaml::from(&$parent))
    }};

    // Value with no display name
    ($parent:expr, self, $default:expr) => {{
        ParseYaml::from(&$parent).unwrap_or($default)
    }};

    // Value that exits early on failure
    ($parent:expr, $disp_name:expr, fail) => {{
        try_opt!(ParseYaml::from(&$parent[$disp_name]))
    }};

    // Value
    ($parent:expr, $disp_name:expr, $default:expr) => {{
        ParseYaml::from(&$parent[$disp_name]).unwrap_or($default)
    }};
}

macro_rules! get_default {
    (default)                    => (Default::default());
    (fail)                       => (Default::default());
    ([$min:expr, $default:expr]) => ($default);
    ($default:expr)              => ($default);
}

#[macro_export]
macro_rules! create_config_struct {
    ($name:ident, $($field:ident: $field_t:ty => $disp_name:tt => $default:tt,)+) => {
        #[derive(Debug)]
        pub struct $name {
            $(pub $field: $field_t,)+
        }

        impl ParseYaml for $name {
            fn from(doc: &Yaml) -> Option<$name> {
                Some($name {
                    $($field: gen_struct_value!(doc, $disp_name, $default),)+
                })
            }
        }

        impl Default for $name {
            fn default() -> $name {
                $name {
                    $($field: get_default!($default),)+
                }
            }
        }
    };
}

#[macro_export]
macro_rules! create_config_enum {
    ($name:ident, $($field:ident($field_t:ty) => $disp_name:expr,)+) => {
        #[derive(Debug)]
        pub enum $name {
            $($field($field_t),)+
        }

        impl ParseYaml for $name {
            fn from(doc: &Yaml) -> Option<$name> {
                $(
                match ParseYaml::from(&doc[$disp_name]) {
                    Some(v) => return Some($name::$field(v)),
                    None    => (),
                }
                )+
                None
            }
        }

        impl Default for $name {
            fn default() -> $name {
                panic!("unable to get default for {} enum", stringify!($name));
            }
        }
    };

    ($name:ident, $($field:ident => $disp_name:expr,)+) => {
        #[derive(Debug)]
        pub enum $name {
            $($field,)+
        }

        impl ParseYaml for $name {
            fn from(doc: &Yaml) -> Option<$name> {
                let result: Option<String> = ParseYaml::from(&doc);

                result.and_then(|result| {
                    match result.as_str() {
                        $($disp_name => Some($name::$field),)+
                        _ => None,
                    }
                })
            }
        }

        impl Default for $name {
            fn default() -> $name {
                panic!("unable to get default for {} enum", stringify!($name));
            }
        }
    };
}<|endoftext|>


<commit_before>extern crate yaml_rust;
use self::yaml_rust::{YamlLoader, Yaml};

pub fn from_yaml(yaml_file: String) -> Vec<String> {
    let docs = YamlLoader::load_from_str(&yaml_file).unwrap();
    let doc = &docs[0];

    let key = Yaml::from_str("default");
    let default_command_list = doc.as_hash().unwrap().get(&key).unwrap();
    let yaml_commands = default_command_list.as_vec().unwrap();

    let mut result_commands = Vec::new();

    for element in yaml_commands {
        result_commands.push(element.as_str().unwrap().to_string());
    }

    result_commands
}
<commit_msg>Use extend instead of custom interation<commit_after>extern crate yaml_rust;
use self::yaml_rust::{YamlLoader, Yaml};

pub fn from_yaml(yaml_file: String) -> Vec<String> {
    let docs = YamlLoader::load_from_str(&yaml_file).unwrap();
    let doc = &docs[0];

    let key = Yaml::from_str("default");
    let default_command_list = doc.as_hash().unwrap().get(&key).unwrap();
    let yaml_commands = default_command_list.as_vec().unwrap();

    let mut result_commands = Vec::new();
    result_commands.extend(
        yaml_commands.iter().map(|e| element.as_str().unwrap().to_string()
    )

    result_commands
}
<|endoftext|>


<commit_before>/*
    Flag Register:

    Bit  Name  Set Clr  Expl.
    7    zf    Z   NZ   Zero Flag
    6    n     -   -    Add/Sub-Flag (BCD)
    5    h     -   -    Half Carry Flag (BCD)
    4    cy    C   NC   Carry Flag
    3-0  -     -   -    Not used (always zero)
*/

pub struct Registers {
    pub a: u8,
    pub f: u8,
    pub b: u8,
    pub c: u8,
    pub d: u8,
    pub e: u8,
    pub h: u8,
    pub l: u8,
    pub sp: u16,    // Stack Pointer
    pub pc: u16     // Program Counter
}

#[derive(Debug)]
pub enum Reg8 {
    A, F, B, C, D, E, H, L
}

#[derive(Debug)]
pub enum Reg16 {
    AF, BC, DE, HL, SP, PC
}

impl Registers {
    pub fn new() -> Registers {
        Registers {
            a: 0,
            f: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            h: 0,
            l: 0,
            sp: 0,
            pc: 0
        }
    }
}
<commit_msg>Added methods to set/reset with flag bits<commit_after>/*
    Flag Register:

    Bit  Name  Set Clr  Expl.
    7    zf    Z   NZ   Zero Flag
    6    n     -   -    Add/Sub-Flag (BCD)
    5    h     -   -    Half Carry Flag (BCD)
    4    cy    C   NC   Carry Flag
    3-0  -     -   -    Not used (always zero)
*/

pub struct Registers {
    pub a: u8,
    pub f: u8,
    pub b: u8,
    pub c: u8,
    pub d: u8,
    pub e: u8,
    pub h: u8,
    pub l: u8,
    pub sp: u16,    // Stack Pointer
    pub pc: u16     // Program Counter
}

#[derive(Debug)]
pub enum Reg8 {
    A, F, B, C, D, E, H, L
}

#[derive(Debug)]
pub enum Reg16 {
    AF, BC, DE, HL, SP, PC
}

#[derive(Debug)]
pub enum Flag {
    Z, N, H, C
}

impl Registers {
    pub fn new() -> Registers {
        Registers {
            a: 0,
            f: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            h: 0,
            l: 0,
            sp: 0,
            pc: 0
        }
    }

    fn select_flag(f: Flag) -> u8 {
        match f {
            Flag::Z => 7,
            Flag::N => 6,
            Flag::H => 5,
            Flag::C => 4
        }
    }

    pub fn get_flag(&self, f: Flag) -> bool {
        ((self.f >> Registers::select_flag(f)) & 1) == 1
    }

    pub fn set_flag(&mut self, f: Flag) {
        self.f |= 1 << Registers::select_flag(f);
    }

    pub fn reset_flag(&mut self, f: Flag) {
        self.f &= !(1 << Registers::select_flag(f));
    }
}

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

    #[test]
    fn set_z_flag() {
        let mut r = Registers::new();
        r.set_flag(Flag::Z);
        assert_eq!(r.f, 0b10000000)
    }

    #[test]
    fn set_n_flag() {
        let mut r = Registers::new();
        r.set_flag(Flag::N);
        assert_eq!(r.f, 0b01000000)
    }

    #[test]
    fn set_h_flag() {
        let mut r = Registers::new();
        r.set_flag(Flag::H);
        assert_eq!(r.f, 0b00100000)
    }

    #[test]
    fn set_c_flag() {
        let mut r = Registers::new();
        r.set_flag(Flag::C);
        assert_eq!(r.f, 0b00010000)
    }

    #[test]
    fn reset_c_flag_only() {
        let mut r = Registers::new();
        r.f = 0b00010000;
        r.reset_flag(Flag::C);
        assert_eq!(r.f, 0b00000000)
    }

    #[test]
    fn reset_z_and_c_flag_with_all_set() {
        let mut r = Registers::new();
        r.f = 0b11010000;
        r.reset_flag(Flag::Z);
        r.reset_flag(Flag::C);
        assert_eq!(r.f, 0b01000000)
    }
}<|endoftext|>