1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
use {ClientPacket, ServerPacket};

use std::error::Error;

type ServerPacketIterator = Box<Iterator<Item = Vec<u8>>>;

/// Interface to implement for all protocols.
pub trait Protocol: Sync + Send {
	/// Error for when a packet fails to serialize.
	///
	/// This should be broad enough to be able to deal
	/// with failures for both [`ClientPacket`][0] and
	/// [`ServerPacket`][1].
	///
	/// [0]: enum.ClientPacket.html
	/// [1]: enum.ServerPacket.html
	type SerializeError: Error;
	/// Error for when a packet fails to deserialize.
	///
	/// This should be broad enough to be able to deal
	/// with failures for both [`ClientPacket`][0] and
	/// [`ServerPacket`][1].
	///
	/// [0]: enum.ClientPacket.html
	/// [1]: enum.ServerPacket.html
	type DeserializeError: Error;

	/// Unique version number for the protocol.
	fn version(&self) -> u8;

	/// Serialize a client packet into some number of
	/// binary packet bodies.
	///
	/// For most packets this should be a 1-to-1 deserialization
	/// but the iterator return type is there to allow for
	/// polyfilling of the packets behind the scenes if a
	/// protocol backend doesn't support them directly.
	/// This can be used (for example) to send multiple packets
	/// for when more than 255 missiles are reflected with
	/// the same goliath deflect (which is not supported by
	/// protocol-v5).
	///
	/// For users of this interface it will most likely be
	/// more convienient to call
	/// [`ProtocolSerializationExt::serialize()`][2] with a
	/// [`ClientPacket`][1] instead, since it provides a
	/// unified interface to serializing a [`ClientPacket`][1]
	/// and a [`ServerPacket`][0].
	///
	/// # Panics
	/// This method should never panic (based on the input),
	/// instead it should return an appropriate error within
	/// the SerializeError type.
	///
	/// [0]: struct.ServerPacket.html
	/// [1]: struct.ClientPacket.html
	/// [2]: trait.ProtocolSerializationExt.html#ty.serialize
	fn serialize_client(
		&self,
		packet: &ClientPacket,
	) -> Result<ServerPacketIterator, Self::SerializeError>;

	/// Serialize a server packet into some number of
	/// binary packet bodies.
	///
	/// For most packets this should be a 1-to-1 deserialization
	/// but the iterator return type is there to allow for
	/// polyfilling of the packets behind the scenes if a
	/// protocol backend doesn't support them directly.
	/// This can be used (for example) to send multiple packets
	/// for when more than 255 missiles are reflected with
	/// the same goliath deflect (which is not supported by
	/// protocol-v5).
	///
	/// For users of this interface it will most likely be
	/// more convienient to call
	/// [`ProtocolSerializationExt::serialize()`][2] with a
	/// [`ServerPacket`][0] instead, since it provides a
	/// unified interface to serializing a [`ServerPacket`][0]
	/// and a [`ClientPacket`][1].
	///
	/// # Panics
	/// This method should never panic (based on the input),
	/// instead it should return an appropriate error within
	/// the SerializeError type.
	///
	/// [0]: struct.ServerPacket.html
	/// [1]: struct.ClientPacket.html
	/// [2]: trait.ProtocolSerializationExt.html#ty.serialize
	fn serialize_server(
		&self,
		packet: &ServerPacket,
	) -> Result<ServerPacketIterator, Self::SerializeError>;

	/// Deserialize a binary packet into a client packet.
	fn deserialize_client(&self, data: &[u8]) -> Result<ClientPacket, Self::DeserializeError>;

	/// Deserialize a binary packet into a server packet.
	fn deserialize_server(&self, data: &[u8]) -> Result<ServerPacket, Self::DeserializeError>;
}

/// Helper trait to make working with protocols easier.
///
/// This allows for [`ServerPacket`][0] and
/// [`ClientPacket`][1] to be serialized and deserialized
/// without using the `serialize_*` or `deserialize_*`
/// methods within the [`Protocol`] trait. Instead they
/// can use [`serialize`][2] and [`deserialize`][3] and
/// let type inference deduce the correct type.
///
/// **This trait should not be implemented by client code.**
///
/// [0]: enum.ServerPacket.html
/// [1]: enum.ClientPacket.html
/// [2]: #tymethod.serialize
/// [3]: #tymethod.deserialize
pub trait ProtocolSerializationExt<T>: Protocol {
	/// Serialize a packet. This can be either a
	/// [`ClientPacket`][1] or a [`ServerPacket`][0]
	/// depending on the instantiation of this trait.
	///
	/// [0]: enum.ServerPacket.html
	/// [1]: enum.ClientPacket.html
	fn serialize<U>(&self, packet: U) -> Result<ServerPacketIterator, Self::SerializeError>
	where
		U: Into<T>;

	/// Deserialize a packet. This can be either a
	/// [`ClientPacket`][1] or a [`ServerPacket`][0]
	/// depending on the instantiation of this trait.
	///
	/// [0]: enum.ServerPacket.html
	/// [1]: enum.ClientPacket.html
	fn deserialize(&self, data: &[u8]) -> Result<T, Self::DeserializeError>;
}

impl<T> ProtocolSerializationExt<ServerPacket> for T
where
	T: Protocol + Sync + Send,
{
	fn serialize<U>(&self, packet: U) -> Result<ServerPacketIterator, Self::SerializeError>
	where
		U: Into<ServerPacket>,
	{
		self.serialize_server(&packet.into())
	}

	fn deserialize(&self, data: &[u8]) -> Result<ServerPacket, Self::DeserializeError> {
		self.deserialize_server(data)
	}
}

impl<T> ProtocolSerializationExt<ClientPacket> for T
where
	T: Protocol + Sync + Send,
{
	fn serialize<U>(&self, packet: U) -> Result<ServerPacketIterator, Self::SerializeError>
	where
		U: Into<ClientPacket>,
	{
		self.serialize_client(&packet.into())
	}

	fn deserialize(&self, data: &[u8]) -> Result<ClientPacket, Self::DeserializeError> {
		self.deserialize_client(data)
	}
}