box2d-rs 0.0.4

Port of Box2d to Rust
Documentation
use crate::b2_fixture::*;
use crate::b2_body::*;
use crate::b2rs_common::UserDataType;
use crate::b2_shape::*;
use crate::shapes::b2_chain_shape::*;
use crate::shapes::b2_circle_shape::*;
use crate::shapes::b2_edge_shape::*;
use crate::shapes::b2_polygon_shape::*;
use crate::shapes::b2rs_to_derived_shape::*;
use std::cell::RefCell;
use std::rc::{Rc};

use serde::de;
use serde::de::{DeserializeSeed, Deserializer, MapAccess, SeqAccess, Visitor};
use serde::{
	ser::{SerializeStruct},
	Deserialize, Serialize, Serializer,
};
use std::fmt;
use strum::VariantNames;
use strum_macros::EnumVariantNames;

impl<D: UserDataType> Serialize for B2fixture<D> {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let mut state = serializer.serialize_struct("B2fixture", 7)?;
		state.serialize_field("m_friction", &self.m_friction)?;
		state.serialize_field("m_restitution", &self.m_restitution)?;
		state.serialize_field("m_restitution_threshold", &self.m_restitution_threshold)?;
		state.serialize_field("m_density", &self.m_density)?;
		state.serialize_field("m_is_sensor", &self.m_is_sensor)?;
		state.serialize_field("m_filter", &self.m_filter)?;
		state.serialize_field("m_shape_type", &self.m_shape.as_ref().unwrap().get_type())?;
		match self.m_shape.as_ref().unwrap().as_derived() {
			ShapeAsDerived::AsCircle(ref shape) => {
				state.serialize_field("m_shape", &shape)?;
			}
			ShapeAsDerived::AsEdge(ref shape) => {
				state.serialize_field("m_shape", &shape)?;
			}
			ShapeAsDerived::AsPolygon(ref shape) => {
				state.serialize_field("m_shape", &shape)?;
			}
			ShapeAsDerived::AsChain(ref shape) => {
				state.serialize_field("m_shape", &shape)?;
			}
		}
		state.end()
	}
}

struct B2fixtureVisitorContext<D: UserDataType> {
	pub(crate) body: BodyWeakPtr<D>,
}

impl<'de, U: UserDataType> DeserializeSeed<'de> for B2fixtureVisitorContext<U> {
	type Value = ();

	fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
	where
		D: Deserializer<'de>,
	{
		#[derive(Deserialize)]
		#[serde(field_identifier, rename_all = "lowercase")]
		#[derive(EnumVariantNames)]
        #[allow(non_camel_case_types)]
		enum Field {
			m_friction,
			m_restitution,
			m_restitution_threshold,
			m_density,
			m_is_sensor,
			m_filter,
			m_shape_type,
			m_shape,
		}
		struct B2fixtureVisitor<D: UserDataType>(B2fixtureVisitorContext<D>);

		impl<'de, U: UserDataType> Visitor<'de> for B2fixtureVisitor<U> {
			type Value = ();

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

			fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
			where
				V: SeqAccess<'de>,
			{
				let body = self.0.body.upgrade().unwrap();
				let mut definition = B2fixtureDef::<U>::default();

				definition.friction = seq
					.next_element()?
					.ok_or_else(|| de::Error::invalid_length(0, &self))?;

				definition.restitution = seq
					.next_element()?
					.ok_or_else(|| de::Error::invalid_length(0, &self))?;

				definition.restitution_threshold = seq
					.next_element()?
					.ok_or_else(|| de::Error::invalid_length(0, &self))?;

				definition.density = seq
					.next_element()?
					.ok_or_else(|| de::Error::invalid_length(0, &self))?;

				definition.is_sensor = seq
					.next_element()?
					.ok_or_else(|| de::Error::invalid_length(0, &self))?;

				definition.filter = seq
					.next_element()?
					.ok_or_else(|| de::Error::invalid_length(0, &self))?;

				let shape_type = seq
					.next_element()?
					.ok_or_else(|| de::Error::invalid_length(0, &self))?;

				match shape_type {
					B2ShapeType::EChain => {
						let shape: B2chainShape = seq
							.next_element()?
							.ok_or_else(|| de::Error::invalid_length(0, &self))?;
						definition.shape = Some(Rc::new(RefCell::new(shape)));
					}
					B2ShapeType::ECircle => {
						let shape: B2circleShape = seq
							.next_element()?
							.ok_or_else(|| de::Error::invalid_length(0, &self))?;
						definition.shape = Some(Rc::new(RefCell::new(shape)));
					}
					B2ShapeType::EEdge => {
						let shape: B2edgeShape = seq
							.next_element()?
							.ok_or_else(|| de::Error::invalid_length(0, &self))?;
						definition.shape = Some(Rc::new(RefCell::new(shape)));
					}
					B2ShapeType::EPolygon => {
						let shape: B2polygonShape = seq
							.next_element()?
							.ok_or_else(|| de::Error::invalid_length(0, &self))?;
						definition.shape = Some(Rc::new(RefCell::new(shape)));
					}
					_ => panic!(),
				}
				B2body::create_fixture(body, &definition);
				Ok(())
			}

			fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
			where
				V: MapAccess<'de>,
			{
				let body = self.0.body.upgrade().unwrap();
				let mut definition = B2fixtureDef::<U>::default();
				let mut shape_type = B2ShapeType::EChain;
				while let Some(key) = map.next_key()? {
					match key {
						Field::m_friction => {
							definition.friction = map.next_value()?;
						}
						Field::m_restitution => {
							definition.restitution = map.next_value()?;
						}
						Field::m_restitution_threshold => {
							definition.restitution_threshold = map.next_value()?;
						}
						Field::m_density => {
							definition.density = map.next_value()?;
						}
						Field::m_is_sensor => {
							definition.is_sensor = map.next_value()?;
						}
						Field::m_filter => {
							definition.filter = map.next_value()?;
						}
						Field::m_shape_type => {
							shape_type = map.next_value()?;
						}
						Field::m_shape => match shape_type {
							B2ShapeType::EChain => {
								let shape: B2chainShape = map.next_value()?;
								definition.shape = Some(Rc::new(RefCell::new(shape)));
							}
							B2ShapeType::ECircle => {
								let shape: B2circleShape = map.next_value()?;
								definition.shape = Some(Rc::new(RefCell::new(shape)));
							}
							B2ShapeType::EEdge => {
								let shape: B2edgeShape = map.next_value()?;
								definition.shape = Some(Rc::new(RefCell::new(shape)));
							}
							B2ShapeType::EPolygon => {
								let shape: B2polygonShape = map.next_value()?;
								definition.shape = Some(Rc::new(RefCell::new(shape)));
							}
							_ => panic!(),
						},
					}
				}
				B2body::create_fixture(body, &definition);
				Ok(())
			}
		}
		deserializer.deserialize_struct("Duration", Field::VARIANTS, B2fixtureVisitor(self))
	}
}

pub(crate) struct B2fixtureListVisitorContext<D: UserDataType> {
	pub(crate) body: BodyWeakPtr<D>,
}

impl<'de, U: UserDataType> DeserializeSeed<'de> for B2fixtureListVisitorContext<U> {
	type Value = ();

	fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
	where
		D: Deserializer<'de>,
	{
		struct B2bodyVisitor<D: UserDataType>(B2fixtureListVisitorContext<D>);

		impl<'de, U: UserDataType> Visitor<'de> for B2bodyVisitor<U> {
			type Value = ();

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

			fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
			where
				V: SeqAccess<'de>,
			{
				while let Some(_elem) = seq.next_element_seed(B2fixtureVisitorContext {
					body: self.0.body.clone(),
				})? {}
				Ok(())
			}
		}
		deserializer.deserialize_seq(B2bodyVisitor(self))
	}
}