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
/*!
	Documentation and (de-)serialization support for LU's network protocol.
*/
#![feature(specialization)]
#![allow(incomplete_features)]

/**
	Creates an [`Amf3::Array`](crate::world::amf3::Amf3::Array) containing the arguments.

	Since AMF3 arrays are both vectors and maps at the same time, there are multiple forms of the macro, for map and for vector usage.

	### Map usage

	The syntax is `name: value`, where `name` is a string literal that will be converted to an [`Amf3String`](crate::world::amf3::Amf3String), and `value` is an expression that will be converted to an [`Amf3`] object.

	Example:

	```
	# #[macro_use] extern crate lu_packets;
	# use lu_packets::amf3;
	# fn main() {
	amf3! {
		"false": false,
		"true": true,
		"double1": 3.14f32,
		"double2": 3.14f64,
		"string": "string",
		"array": amf3! { "inner": "array"},
	};
	# }
	```

	### Vector usage

	The syntax is the exact same as with the [`vec!`] macro, except that the arguments will be converted to an [`Amf3`] object before being inserted.

	Example:

	```
	# #[macro_use] extern crate lu_packets;
	# use lu_packets::amf3;
	# fn main() {
	amf3! [true, false, true];
	amf3! [true; 4];
	# }
	```

	[`Amf3`]: crate::world::amf3::Amf3
*/
#[macro_export]
macro_rules! amf3 {
	{} => { $crate::world::amf3::Amf3::Array($crate::world::amf3::Amf3Array::new()) };
	($($name:literal:$value:expr),+ $(,)?) => {
		{
			let mut array = $crate::world::amf3::Amf3Array::new();
			$(array.map.insert(::std::convert::TryInto::try_into($name).unwrap(), ::std::convert::TryInto::try_into($value).unwrap());)*
			$crate::world::amf3::Amf3::Array(array)
		}
	};
	($value:expr; $n:expr) => {
		{
			let converted = ::std::convert::TryInto::try_into($value).unwrap();
			let mut array = $crate::world::amf3::Amf3Array {
				map: ::std::collections::HashMap::new(),
				vec: vec![converted; $n],
			};
			$crate::world::amf3::Amf3::Array(array)
		}
	};
	($($value:expr),+ $(,)?) => {
		{
			let mut array = $crate::world::amf3::Amf3Array::new();
			$(array.vec.push(::std::convert::TryInto::try_into($value).unwrap());)*
			$crate::world::amf3::Amf3::Array(array)
		}
	};
}

/**
	Creates a [`LuNameValue`] containing the arguments.

	The syntax is `name: value`, where `name` is a string literal that will be converted to a [`LuVarWString<u32>`], and `value` is an expression that will be converted to an [`LnvValue`].

	Example:

	```
	# #[macro_use] extern crate lu_packets;
	# use lu_packets::lnv;
	# fn main() {
	lnv! {
		"wstring": "string expression",
		"i32": 42i32,
		"f32": 3.14f32,
		"f64": 3.14f64,
		"u32": 42u32,
		"bool": true,
		"i64": i64::MAX,
		"u64": u64::MAX,
		"string": b"byte slice",
	};
	# }
	```

	Care should be taken with integer and float literals to suffix them with the correct type, as seen above. Rust assumes `i32` for integer and `f64` for float literals by default, which may not be what you want, and can lead to incorrect serialization.

	[`LuNameValue`]: crate::world::LuNameValue
	[`LuVarWString<u32>`]: crate::common::LuVarWString
	[`LnvValue`]: crate::world::LnvValue
*/
#[macro_export]
macro_rules! lnv {
	{} => { $crate::world::LuNameValue::new() };
	{$($name:literal:$value:expr,)*} => {
		{
			let mut lnv = $crate::world::LuNameValue::new();
			$(lnv.insert(::std::convert::TryInto::try_into($name).unwrap(), $value.into());)*
			lnv
		}
	}
}

/**
	Converts the argument to a LU string.

	This forwards to the [`TryInto`] implementation on the argument, which means the macro is flexible and works with both string and wstring types, and both fixed and variable types, depending on context. Generally, to convert to a string type, pass a byte slice, and for a wstring type, pass a `&str` or `String`.

	[`TryInto`]: std::convert::TryInto
*/
#[macro_export]
macro_rules! lu {
	($str_lit:expr) => {
		::std::convert::TryInto::try_into($str_lit).unwrap()
	};
}

pub mod raknet;
pub mod auth;
pub mod chat;
pub mod common;
pub mod general;
pub mod world;
pub mod unified;