dpp/voting/contender_structs/contender/
mod.rs1pub mod v0;
2
3use crate::data_contract::document_type::DocumentTypeRef;
4use crate::data_contract::DataContract;
5use crate::document::Document;
6#[cfg(feature = "json-conversion")]
7use crate::serialization::JsonConvertible;
8#[cfg(feature = "value-conversion")]
9use crate::serialization::ValueConvertible;
10use crate::serialization::{PlatformDeserializable, PlatformSerializable};
11use crate::voting::contender_structs::contender::v0::ContenderV0;
12use crate::voting::contender_structs::ContenderWithSerializedDocumentV0;
13use crate::ProtocolError;
14use bincode::{Decode, Encode};
15use derive_more::From;
16use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
17use platform_value::Identifier;
18use platform_version::version::PlatformVersion;
19
20#[derive(Debug, PartialEq, Clone, From)]
25pub enum Contender {
26 V0(ContenderV0),
28}
29
30#[cfg_attr(
36 all(feature = "json-conversion", feature = "serde-conversion"),
37 derive(JsonConvertible)
38)]
39#[derive(
40 Debug, PartialEq, Eq, Clone, From, Encode, Decode, PlatformSerialize, PlatformDeserialize,
41)]
42#[cfg_attr(
43 feature = "serde-conversion",
44 derive(serde::Serialize, serde::Deserialize),
45 serde(tag = "$formatVersion")
46)]
47#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
48#[platform_serialize(unversioned)]
49pub enum ContenderWithSerializedDocument {
50 #[cfg_attr(feature = "serde-conversion", serde(rename = "0"))]
52 V0(ContenderWithSerializedDocumentV0),
53}
54
55impl Contender {
56 pub fn identity_id(&self) -> Identifier {
57 match self {
58 Contender::V0(v0) => v0.identity_id,
59 }
60 }
61
62 pub fn identity_id_ref(&self) -> &Identifier {
63 match self {
64 Contender::V0(v0) => &v0.identity_id,
65 }
66 }
67
68 pub fn document(&self) -> &Option<Document> {
69 match self {
70 Contender::V0(v0) => &v0.document,
71 }
72 }
73
74 pub fn take_document(&mut self) -> Option<Document> {
75 match self {
76 Contender::V0(v0) => v0.document.take(),
77 }
78 }
79
80 pub fn vote_tally(&self) -> Option<u32> {
81 match self {
82 Contender::V0(v0) => v0.vote_tally,
83 }
84 }
85}
86
87impl ContenderWithSerializedDocument {
88 pub fn identity_id(&self) -> Identifier {
89 match self {
90 ContenderWithSerializedDocument::V0(v0) => v0.identity_id,
91 }
92 }
93
94 pub fn identity_id_ref(&self) -> &Identifier {
95 match self {
96 ContenderWithSerializedDocument::V0(v0) => &v0.identity_id,
97 }
98 }
99
100 pub fn serialized_document(&self) -> &Option<Vec<u8>> {
101 match self {
102 ContenderWithSerializedDocument::V0(v0) => &v0.serialized_document,
103 }
104 }
105
106 pub fn take_serialized_document(&mut self) -> Option<Vec<u8>> {
107 match self {
108 ContenderWithSerializedDocument::V0(v0) => v0.serialized_document.take(),
109 }
110 }
111
112 pub fn vote_tally(&self) -> Option<u32> {
113 match self {
114 ContenderWithSerializedDocument::V0(v0) => v0.vote_tally,
115 }
116 }
117}
118
119impl ContenderWithSerializedDocument {
120 pub fn try_into_contender(
121 self,
122 document_type_ref: DocumentTypeRef,
123 platform_version: &PlatformVersion,
124 ) -> Result<Contender, ProtocolError> {
125 match self {
126 ContenderWithSerializedDocument::V0(v0) => Ok(v0
127 .try_into_contender(document_type_ref, platform_version)?
128 .into()),
129 }
130 }
131
132 pub fn try_to_contender(
133 &self,
134 document_type_ref: DocumentTypeRef,
135 platform_version: &PlatformVersion,
136 ) -> Result<Contender, ProtocolError> {
137 match self {
138 ContenderWithSerializedDocument::V0(v0) => Ok(v0
139 .try_to_contender(document_type_ref, platform_version)?
140 .into()),
141 }
142 }
143}
144
145impl Contender {
146 pub fn try_into_contender_with_serialized_document(
147 self,
148 document_type_ref: DocumentTypeRef,
149 data_contract: &DataContract,
150 platform_version: &PlatformVersion,
151 ) -> Result<ContenderWithSerializedDocument, ProtocolError> {
152 match self {
153 Contender::V0(v0) => Ok(v0
154 .try_into_contender_with_serialized_document(
155 document_type_ref,
156 data_contract,
157 platform_version,
158 )?
159 .into()),
160 }
161 }
162
163 pub fn try_to_contender_with_serialized_document(
164 &self,
165 document_type_ref: DocumentTypeRef,
166 data_contract: &DataContract,
167 platform_version: &PlatformVersion,
168 ) -> Result<ContenderWithSerializedDocument, ProtocolError> {
169 match self {
170 Contender::V0(v0) => Ok(v0
171 .try_to_contender_with_serialized_document(
172 document_type_ref,
173 data_contract,
174 platform_version,
175 )?
176 .into()),
177 }
178 }
179
180 pub fn serialize(
181 &self,
182 document_type: DocumentTypeRef,
183 data_contract: &DataContract,
184 platform_version: &PlatformVersion,
185 ) -> Result<Vec<u8>, ProtocolError> {
186 self.try_to_contender_with_serialized_document(
187 document_type,
188 data_contract,
189 platform_version,
190 )?
191 .serialize_to_bytes()
192 }
193
194 pub fn serialize_consume(
195 self,
196 document_type: DocumentTypeRef,
197 data_contract: &DataContract,
198 platform_version: &PlatformVersion,
199 ) -> Result<Vec<u8>, ProtocolError> {
200 self.try_into_contender_with_serialized_document(
201 document_type,
202 data_contract,
203 platform_version,
204 )?
205 .serialize_to_bytes()
206 }
207
208 pub fn from_bytes(
209 serialized_contender: &[u8],
210 document_type: DocumentTypeRef,
211 platform_version: &PlatformVersion,
212 ) -> Result<Self, ProtocolError>
213 where
214 Self: Sized,
215 {
216 let serialized_contender =
217 ContenderWithSerializedDocument::deserialize_from_bytes(serialized_contender)?;
218 serialized_contender.try_into_contender(document_type, platform_version)
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225 use crate::voting::contender_structs::contender::v0::{
226 ContenderV0, ContenderWithSerializedDocumentV0,
227 };
228 use platform_value::Identifier;
229
230 mod contender_construction {
231 use super::*;
232
233 #[test]
234 fn contender_v0_default() {
235 let contender = ContenderV0::default();
236 assert_eq!(contender.identity_id, Identifier::default());
237 assert!(contender.document.is_none());
238 assert!(contender.vote_tally.is_none());
239 }
240
241 #[test]
242 fn contender_v0_with_fields() {
243 let id = Identifier::new([1u8; 32]);
244 let contender = ContenderV0 {
245 identity_id: id,
246 document: None,
247 vote_tally: Some(42),
248 };
249 assert_eq!(contender.identity_id, id);
250 assert!(contender.document.is_none());
251 assert_eq!(contender.vote_tally, Some(42));
252 }
253
254 #[test]
255 fn contender_from_v0() {
256 let id = Identifier::new([2u8; 32]);
257 let v0 = ContenderV0 {
258 identity_id: id,
259 document: None,
260 vote_tally: Some(100),
261 };
262 let contender: Contender = v0.into();
263 assert_eq!(contender.identity_id(), id);
264 assert_eq!(contender.vote_tally(), Some(100));
265 }
266 }
267
268 mod contender_accessors {
269 use super::*;
270
271 #[test]
272 fn identity_id_returns_correct_value() {
273 let id = Identifier::new([3u8; 32]);
274 let contender = Contender::V0(ContenderV0 {
275 identity_id: id,
276 document: None,
277 vote_tally: None,
278 });
279 assert_eq!(contender.identity_id(), id);
280 }
281
282 #[test]
283 fn identity_id_ref_returns_reference() {
284 let id = Identifier::new([4u8; 32]);
285 let contender = Contender::V0(ContenderV0 {
286 identity_id: id,
287 document: None,
288 vote_tally: None,
289 });
290 assert_eq!(*contender.identity_id_ref(), id);
291 }
292
293 #[test]
294 fn document_returns_none_when_empty() {
295 let contender = Contender::V0(ContenderV0::default());
296 assert!(contender.document().is_none());
297 }
298
299 #[test]
300 fn vote_tally_returns_none_when_not_set() {
301 let contender = Contender::V0(ContenderV0::default());
302 assert!(contender.vote_tally().is_none());
303 }
304
305 #[test]
306 fn vote_tally_returns_value_when_set() {
307 let contender = Contender::V0(ContenderV0 {
308 identity_id: Identifier::default(),
309 document: None,
310 vote_tally: Some(999),
311 });
312 assert_eq!(contender.vote_tally(), Some(999));
313 }
314
315 #[test]
316 fn take_document_returns_none_and_leaves_none() {
317 let mut contender = Contender::V0(ContenderV0::default());
318 let doc = contender.take_document();
319 assert!(doc.is_none());
320 assert!(contender.document().is_none());
321 }
322 }
323
324 mod contender_with_serialized_document {
325 use super::*;
326
327 #[test]
328 fn default_values() {
329 let csd = ContenderWithSerializedDocumentV0::default();
330 assert_eq!(csd.identity_id, Identifier::default());
331 assert!(csd.serialized_document.is_none());
332 assert!(csd.vote_tally.is_none());
333 }
334
335 #[test]
336 fn construction_with_data() {
337 let id = Identifier::new([5u8; 32]);
338 let doc_bytes = vec![1, 2, 3, 4, 5];
339 let csd = ContenderWithSerializedDocumentV0 {
340 identity_id: id,
341 serialized_document: Some(doc_bytes.clone()),
342 vote_tally: Some(50),
343 };
344 let wrapped = ContenderWithSerializedDocument::V0(csd);
345 assert_eq!(wrapped.identity_id(), id);
346 assert_eq!(*wrapped.identity_id_ref(), id);
347 assert_eq!(wrapped.serialized_document(), &Some(doc_bytes));
348 assert_eq!(wrapped.vote_tally(), Some(50));
349 }
350
351 #[test]
352 fn take_serialized_document() {
353 let doc_bytes = vec![10, 20, 30];
354 let csd = ContenderWithSerializedDocumentV0 {
355 identity_id: Identifier::default(),
356 serialized_document: Some(doc_bytes.clone()),
357 vote_tally: None,
358 };
359 let mut wrapped = ContenderWithSerializedDocument::V0(csd);
360 let taken = wrapped.take_serialized_document();
361 assert_eq!(taken, Some(doc_bytes));
362 assert!(wrapped.serialized_document().is_none());
363 }
364
365 #[test]
366 fn serialization_round_trip() {
367 let id = Identifier::new([6u8; 32]);
368 let csd = ContenderWithSerializedDocumentV0 {
369 identity_id: id,
370 serialized_document: Some(vec![0xAA, 0xBB, 0xCC]),
371 vote_tally: Some(77),
372 };
373 let wrapped = ContenderWithSerializedDocument::V0(csd);
374
375 let bytes = wrapped
377 .serialize_to_bytes()
378 .expect("should serialize to bytes");
379 assert!(!bytes.is_empty());
380
381 let restored = ContenderWithSerializedDocument::deserialize_from_bytes(&bytes)
383 .expect("should deserialize from bytes");
384
385 assert_eq!(wrapped, restored);
386 }
387
388 #[test]
389 fn serialization_round_trip_with_no_document() {
390 let id = Identifier::new([7u8; 32]);
391 let csd = ContenderWithSerializedDocumentV0 {
392 identity_id: id,
393 serialized_document: None,
394 vote_tally: None,
395 };
396 let wrapped = ContenderWithSerializedDocument::V0(csd);
397
398 let bytes = wrapped
399 .serialize_to_bytes()
400 .expect("should serialize to bytes");
401 let restored = ContenderWithSerializedDocument::deserialize_from_bytes(&bytes)
402 .expect("should deserialize from bytes");
403
404 assert_eq!(wrapped, restored);
405 }
406 }
407
408 mod equality {
409 use super::*;
410
411 #[test]
412 fn equal_contenders() {
413 let id = Identifier::new([8u8; 32]);
414 let a = Contender::V0(ContenderV0 {
415 identity_id: id,
416 document: None,
417 vote_tally: Some(10),
418 });
419 let b = Contender::V0(ContenderV0 {
420 identity_id: id,
421 document: None,
422 vote_tally: Some(10),
423 });
424 assert_eq!(a, b);
425 }
426
427 #[test]
428 fn different_vote_tallies_not_equal() {
429 let id = Identifier::new([9u8; 32]);
430 let a = Contender::V0(ContenderV0 {
431 identity_id: id,
432 document: None,
433 vote_tally: Some(10),
434 });
435 let b = Contender::V0(ContenderV0 {
436 identity_id: id,
437 document: None,
438 vote_tally: Some(20),
439 });
440 assert_ne!(a, b);
441 }
442
443 #[test]
444 fn different_identity_ids_not_equal() {
445 let a = Contender::V0(ContenderV0 {
446 identity_id: Identifier::new([1u8; 32]),
447 document: None,
448 vote_tally: None,
449 });
450 let b = Contender::V0(ContenderV0 {
451 identity_id: Identifier::new([2u8; 32]),
452 document: None,
453 vote_tally: None,
454 });
455 assert_ne!(a, b);
456 }
457 }
458}