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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//! MValue, stands for Multi Value, this is needed so you can tell alt:V
//! how to understand Rust types in more general way
//! to send or receive something from clients (players), or communicate with
//! [other alt:V resources](https://docs.altv.mp/articles/resources.html#types).
//!
//! If you want to know more about MValue in general, you can read more [here](https://docs.altv.mp/sdk/mvalues.html).
//!
//! Rust module uses [`serde`](https://serde.rs) for serializing and deserializing
//! data structures between Rust and alt:V (or other scripting languages, for example JavaScript).
//!
//! For example, alt:V has Dict MValue type, in Rust it can be created
//! (serialized) from `HashMap<String, &dyn Serialize>` or any struct which implements
//! [`Serialize`](https://docs.rs/serde/latest/serde/trait.Serialize.html)
//! ([see](#how-to-implement-serialize-and-deserialize-for-your-struct)).
//!
//! # Supported MValue <-> Rust types
//! [Full list of types](https://github.com/xxshady/altv-rust/blob/19b7454df79b077bcc7e8ffaff21324f23a37276/mvalue/src/helpers.rs#L111-L128)<br>
//! See also [`AnyMValue`](enum.AnyMValue.html).
//!
//! # Examples
//! > *Examples will use [`to_mvalue`](fn.to_mvalue.html) and [`from_mvalue`](fn.from_mvalue.html),
//! > these are used internally by events and meta in Rust module.*
//!
//! ### Numbers
//! ```rust
//! # fn test() -> altv::VoidResult {
//! use altv::mvalue::{from_mvalue, to_mvalue};
//!
//! let mvalue = to_mvalue(&123)?;
//! let value: i32 = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // 123
//!
//! let mvalue = to_mvalue(&256)?;
//! // Will return error and panic because 256 is greater than u8::MAX
//! let value: u8 = from_mvalue(&mvalue.into_const()).unwrap();
//! # Ok(()) }
//! ```
//!
//! ### String, &str, char
//! ```rust
//! # fn test() -> altv::VoidResult {
//! use altv::mvalue::{from_mvalue, to_mvalue};
//!
//! let mvalue = to_mvalue(&String::from("example"))?;
//! let value: String = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // "example"
//!
//! let mvalue = to_mvalue(&"example")?;
//! // &str can only be deserialized as String
//! let value: String = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // "example"
//!
//! let mvalue = to_mvalue(&'e')?;
//! let value: char = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // 'e'
//!
//! let mvalue = to_mvalue(&"eee")?;
//! // Will return error and panic
//! let value: char = from_mvalue(&mvalue.into_const()).unwrap();
//! # Ok(()) }
//! ```
//!
//! ### Option
//! ```rust
//! # fn test() -> altv::VoidResult {
//! use altv::mvalue::{from_mvalue, to_mvalue};
//!
//! let mvalue = to_mvalue(&Some(true))?;
//! let value: Option<bool> = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // Some(true)
//!
//! // Since there is no Option MValue type, all options containing the value
//! // are "unwrapped" and serialized as-is
//! let mvalue = to_mvalue(&Some(true))?;
//! let value: bool = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // true
//!
//! let mvalue = to_mvalue(&Option::<bool>::None)?;
//! let value: Option<bool> = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // None
//! # Ok(()) }
//! ```
//!
//! ### Tuple
//! ```rust
//! # fn test() -> altv::VoidResult {
//! use altv::mvalue::{from_mvalue, to_mvalue};
//!
//! let mvalue = to_mvalue(&(true, 123))?;
//! let value: (bool, i32) = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // (true, 123)
//!
//! // Tuples can be deserialized partially
//! // (in fact, it works the same for all sequences: arrays, vectors, etc.)
//! let mvalue = to_mvalue(&(true, 123))?;
//! let value: (bool,) = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // (true,)
//! # Ok(()) }
//! ```
//!
//! ### Byte Array (ByteBuf)
//! ```rust
//! # fn test() -> altv::VoidResult {
//! use altv::mvalue::{from_mvalue, to_mvalue};
//!
//! let mvalue = to_mvalue(&altv::ByteBuf::from([1, 2, 3]))?;
//! let value: altv::ByteBuf = from_mvalue(&mvalue.into_const())?;
//! dbg!(value); // [1, 2, 3]
//! # Ok(()) }
//! ```
//!
//! ### Enums
//! Default representation ([externally tagged](https://serde.rs/enum-representations.html#externally-tagged))
//! under the hood is serialized as List with two elements: `[variant_index (u32), variant_value (any)]`,
//! except if variant is unit variant its serialized as one u32,
//! but can also be deserialized as List with two elements (second element is ignored in that case but must still present).
//! ```rust
//! # fn test() -> altv::VoidResult {
//! use altv::{
//! serde::{Deserialize, Serialize},
//! mvalue::{from_mvalue, to_mvalue, AnyMValue},
//! };
//!
//! #[derive(Serialize, Deserialize, Debug)]
//! #[serde(crate = "altv::serde")]
//! enum TestEnum {
//! Unit,
//! Newtype(i32),
//! Tuple(i32, bool),
//! Struct { a: i32, b: bool },
//! }
//!
//! let mvalue = to_mvalue(&TestEnum::Newtype(123))?;
//!
//! // how it's serialized:
//! // "AnyMValue::List([AnyMValue::Int(1), AnyMValue::Int(123)])"
//! // dbg!(from_mvalue::<AnyMValue>(&mvalue.clone().into_const())?);
//!
//! let my_enum: TestEnum = from_mvalue(&mvalue.into_const())?;
//! dbg!(my_enum); // Newtype(123)
//! # Ok(()) }
//! ```
//!
//! [Untagged](https://serde.rs/enum-representations.html#untagged) representation is also supported.
//! Serialized as if we didn't use enums.
//! ```rust
//! # fn test() -> altv::VoidResult {
//! use altv::{
//! serde::{Deserialize, Serialize},
//! mvalue::{from_mvalue, to_mvalue, AnyMValue},
//! };
//!
//! #[derive(Serialize, Deserialize, Debug)]
//! #[serde(crate = "altv::serde")]
//! #[serde(untagged)]
//! enum TestEnum {
//! Unit,
//! Newtype(i32),
//! Tuple(i32, bool),
//! Struct { a: i32, b: bool },
//! }
//!
//! let mvalue = to_mvalue(&TestEnum::Newtype(123))?;
//!
//! // how it's serialized:
//! // "AnyMValue::Int(123)"
//! // dbg!(from_mvalue::<AnyMValue>(&mvalue.clone().into_const())?);
//!
//! let my_enum: TestEnum = from_mvalue(&mvalue.into_const())?;
//! dbg!(my_enum); // Newtype(123)
//! # Ok(()) }
//! ```
//!
//! # How to implement Serialize and Deserialize for your struct
//! ```rust
//! # fn test() -> altv::VoidResult {
//! use altv::{
//! serde::{Deserialize, Serialize},
//! mvalue::{from_mvalue, to_mvalue},
//! };
//!
//! #[derive(Serialize, Deserialize, Debug)]
//! #[serde(crate = "altv::serde")]
//! struct MyStruct {
//! a: i32,
//! }
//!
//! let mvalue = to_mvalue(&MyStruct { a: 123 })?;
//! let my_struct: MyStruct = from_mvalue(&mvalue.into_const())?;
//! dbg!(my_struct); // MyStruct { a: 123 }
//! # Ok(()) }
//! ```
pub use ;