Skip to main content

rez_next_package/package/
serialize.rs

1//! Serde serialization/deserialization for Package.
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6use super::types::Package;
7
8/// Number of fields serialized in the Package struct (excludes `config` and `commands_function`).
9const PACKAGE_SERIALIZED_FIELD_COUNT: usize = 35;
10
11impl Serialize for Package {
12    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
13    where
14        S: serde::Serializer,
15    {
16        use serde::ser::SerializeStruct;
17        let mut state = serializer.serialize_struct("Package", PACKAGE_SERIALIZED_FIELD_COUNT)?;
18        state.serialize_field("name", &self.name)?;
19        state.serialize_field("version", &self.version)?;
20        state.serialize_field("description", &self.description)?;
21        state.serialize_field("authors", &self.authors)?;
22        state.serialize_field("requires", &self.requires)?;
23        state.serialize_field("build_requires", &self.build_requires)?;
24        state.serialize_field("private_build_requires", &self.private_build_requires)?;
25        state.serialize_field("variants", &self.variants)?;
26        state.serialize_field("tools", &self.tools)?;
27        state.serialize_field("commands", &self.commands)?;
28        state.serialize_field("build_command", &self.build_command)?;
29        state.serialize_field("build_system", &self.build_system)?;
30        state.serialize_field("pre_commands", &self.pre_commands)?;
31        state.serialize_field("post_commands", &self.post_commands)?;
32        state.serialize_field("pre_test_commands", &self.pre_test_commands)?;
33        state.serialize_field("pre_build_commands", &self.pre_build_commands)?;
34        state.serialize_field("tests", &self.tests)?;
35        state.serialize_field("requires_rez_version", &self.requires_rez_version)?;
36        state.serialize_field("uuid", &self.uuid)?;
37        // config excluded from serialization for compatibility
38        state.serialize_field("help", &self.help)?;
39        state.serialize_field("relocatable", &self.relocatable)?;
40        state.serialize_field("cachable", &self.cachable)?;
41        state.serialize_field("timestamp", &self.timestamp)?;
42        state.serialize_field("revision", &self.revision)?;
43        state.serialize_field("changelog", &self.changelog)?;
44        state.serialize_field("release_message", &self.release_message)?;
45        state.serialize_field("previous_version", &self.previous_version)?;
46        state.serialize_field("previous_revision", &self.previous_revision)?;
47        state.serialize_field("vcs", &self.vcs)?;
48        state.serialize_field("format_version", &self.format_version)?;
49        state.serialize_field("base", &self.base)?;
50        state.serialize_field("has_plugins", &self.has_plugins)?;
51        state.serialize_field("plugin_for", &self.plugin_for)?;
52        state.serialize_field("hashed_variants", &self.hashed_variants)?;
53        state.serialize_field("preprocess", &self.preprocess)?;
54        state.end()
55    }
56}
57
58impl<'de> Deserialize<'de> for Package {
59    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60    where
61        D: serde::Deserializer<'de>,
62    {
63        use serde::de::{self, MapAccess, SeqAccess, Visitor};
64        use std::fmt;
65
66        #[derive(Deserialize)]
67        #[serde(field_identifier, rename_all = "snake_case")]
68        enum Field {
69            Name,
70            Version,
71            Description,
72            Authors,
73            Requires,
74            BuildRequires,
75            PrivateBuildRequires,
76            Variants,
77            Tools,
78            Commands,
79            BuildCommand,
80            BuildSystem,
81            PreCommands,
82            PostCommands,
83            PreTestCommands,
84            PreBuildCommands,
85            Tests,
86            RequiresRezVersion,
87            Uuid,
88            Help,
89            Relocatable,
90            Cachable,
91            Timestamp,
92            Revision,
93            Changelog,
94            ReleaseMessage,
95            PreviousVersion,
96            PreviousRevision,
97            Vcs,
98            FormatVersion,
99            Base,
100            HasPlugins,
101            PluginFor,
102            HashedVariants,
103            Preprocess,
104            IsDevPackage,
105        }
106
107        struct PackageVisitor;
108
109        impl<'de> Visitor<'de> for PackageVisitor {
110            type Value = Package;
111
112            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
113                formatter.write_str("struct Package")
114            }
115
116            fn visit_seq<V>(self, mut seq: V) -> Result<Package, V::Error>
117            where
118                V: SeqAccess<'de>,
119            {
120                let name = seq
121                    .next_element()?
122                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
123                let version = seq
124                    .next_element()?
125                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
126                let description = seq
127                    .next_element()?
128                    .ok_or_else(|| de::Error::invalid_length(2, &self))?;
129                let authors = seq
130                    .next_element()?
131                    .ok_or_else(|| de::Error::invalid_length(3, &self))?;
132                let requires = seq
133                    .next_element()?
134                    .ok_or_else(|| de::Error::invalid_length(4, &self))?;
135                let build_requires = seq
136                    .next_element()?
137                    .ok_or_else(|| de::Error::invalid_length(5, &self))?;
138                let private_build_requires = seq
139                    .next_element()?
140                    .ok_or_else(|| de::Error::invalid_length(6, &self))?;
141                let variants = seq
142                    .next_element()?
143                    .ok_or_else(|| de::Error::invalid_length(7, &self))?;
144                let tools = seq
145                    .next_element()?
146                    .ok_or_else(|| de::Error::invalid_length(8, &self))?;
147                let commands = seq
148                    .next_element()?
149                    .ok_or_else(|| de::Error::invalid_length(9, &self))?;
150                let build_command = seq
151                    .next_element()?
152                    .ok_or_else(|| de::Error::invalid_length(10, &self))?;
153                let build_system = seq
154                    .next_element()?
155                    .ok_or_else(|| de::Error::invalid_length(11, &self))?;
156                let pre_commands = seq
157                    .next_element()?
158                    .ok_or_else(|| de::Error::invalid_length(12, &self))?;
159                let post_commands = seq
160                    .next_element()?
161                    .ok_or_else(|| de::Error::invalid_length(13, &self))?;
162                let pre_test_commands = seq
163                    .next_element()?
164                    .ok_or_else(|| de::Error::invalid_length(14, &self))?;
165                let pre_build_commands = seq
166                    .next_element()?
167                    .ok_or_else(|| de::Error::invalid_length(15, &self))?;
168                let tests = seq
169                    .next_element()?
170                    .ok_or_else(|| de::Error::invalid_length(16, &self))?;
171                let requires_rez_version = seq
172                    .next_element()?
173                    .ok_or_else(|| de::Error::invalid_length(17, &self))?;
174                let uuid = seq
175                    .next_element()?
176                    .ok_or_else(|| de::Error::invalid_length(18, &self))?;
177                let help = seq
178                    .next_element()?
179                    .ok_or_else(|| de::Error::invalid_length(19, &self))?;
180                let relocatable = seq
181                    .next_element()?
182                    .ok_or_else(|| de::Error::invalid_length(20, &self))?;
183                let cachable = seq
184                    .next_element()?
185                    .ok_or_else(|| de::Error::invalid_length(21, &self))?;
186                let timestamp = seq
187                    .next_element()?
188                    .ok_or_else(|| de::Error::invalid_length(22, &self))?;
189                let revision = seq
190                    .next_element()?
191                    .ok_or_else(|| de::Error::invalid_length(23, &self))?;
192                let changelog = seq
193                    .next_element()?
194                    .ok_or_else(|| de::Error::invalid_length(24, &self))?;
195                let release_message = seq
196                    .next_element()?
197                    .ok_or_else(|| de::Error::invalid_length(25, &self))?;
198                let previous_version = seq
199                    .next_element()?
200                    .ok_or_else(|| de::Error::invalid_length(26, &self))?;
201                let previous_revision = seq
202                    .next_element()?
203                    .ok_or_else(|| de::Error::invalid_length(27, &self))?;
204                let vcs = seq
205                    .next_element()?
206                    .ok_or_else(|| de::Error::invalid_length(28, &self))?;
207                let format_version = seq
208                    .next_element()?
209                    .ok_or_else(|| de::Error::invalid_length(29, &self))?;
210                let base = seq
211                    .next_element()?
212                    .ok_or_else(|| de::Error::invalid_length(30, &self))?;
213                let has_plugins = seq
214                    .next_element()?
215                    .ok_or_else(|| de::Error::invalid_length(31, &self))?;
216                let plugin_for = seq
217                    .next_element()?
218                    .ok_or_else(|| de::Error::invalid_length(32, &self))?;
219                let hashed_variants = seq
220                    .next_element()?
221                    .ok_or_else(|| de::Error::invalid_length(33, &self))?;
222                let preprocess = seq
223                    .next_element()?
224                    .ok_or_else(|| de::Error::invalid_length(34, &self))?;
225                let is_dev_package = seq
226                    .next_element()?
227                    .ok_or_else(|| de::Error::invalid_length(35, &self))?;
228
229                Ok(Package {
230                    name,
231                    version,
232                    description,
233                    authors,
234                    requires,
235                    build_requires,
236                    private_build_requires,
237                    variants,
238                    tools,
239                    commands,
240                    commands_function: None,
241                    build_command,
242                    build_system,
243                    pre_commands,
244                    post_commands,
245                    pre_test_commands,
246                    pre_build_commands,
247                    tests,
248                    requires_rez_version,
249                    uuid,
250                    config: HashMap::new(),
251                    help,
252                    relocatable,
253                    cachable,
254                    timestamp,
255                    revision,
256                    changelog,
257                    release_message,
258                    previous_version,
259                    previous_revision,
260                    vcs,
261                    format_version,
262                    base,
263                    has_plugins,
264                    plugin_for,
265                    hashed_variants,
266                    preprocess,
267                    is_dev_package,
268                    filepath: None,
269                    includes: None,
270                })
271            }
272
273            fn visit_map<V>(self, mut map: V) -> Result<Package, V::Error>
274            where
275                V: MapAccess<'de>,
276            {
277                let mut name = None;
278                let mut version = None;
279                let mut description = None;
280                let mut authors = None;
281                let mut requires = None;
282                let mut build_requires = None;
283                let mut private_build_requires = None;
284                let mut variants = None;
285                let mut tools = None;
286                let mut commands = None;
287                let mut build_command = None;
288                let mut build_system = None;
289                let mut pre_commands = None;
290                let mut post_commands = None;
291                let mut pre_test_commands = None;
292                let mut pre_build_commands = None;
293                let mut tests = None;
294                let mut requires_rez_version = None;
295                let mut uuid = None;
296                let mut help = None;
297                let mut relocatable = None;
298                let mut cachable = None;
299                let mut timestamp = None;
300                let mut revision = None;
301                let mut changelog = None;
302                let mut release_message = None;
303                let mut previous_version = None;
304                let mut previous_revision = None;
305                let mut vcs = None;
306                let mut format_version = None;
307                let mut base = None;
308                let mut has_plugins = None;
309                let mut plugin_for = None;
310                let mut hashed_variants = None;
311                let mut preprocess = None;
312                let mut is_dev_package = None;
313
314                while let Some(key) = map.next_key()? {
315                    match key {
316                        Field::Name => {
317                            if name.is_some() {
318                                return Err(de::Error::duplicate_field("name"));
319                            }
320                            name = Some(map.next_value()?);
321                        }
322                        Field::Version => {
323                            if version.is_some() {
324                                return Err(de::Error::duplicate_field("version"));
325                            }
326                            version = Some(map.next_value()?);
327                        }
328                        Field::Description => {
329                            if description.is_some() {
330                                return Err(de::Error::duplicate_field("description"));
331                            }
332                            description = Some(map.next_value()?);
333                        }
334                        Field::Authors => {
335                            if authors.is_some() {
336                                return Err(de::Error::duplicate_field("authors"));
337                            }
338                            authors = Some(map.next_value()?);
339                        }
340                        Field::Requires => {
341                            if requires.is_some() {
342                                return Err(de::Error::duplicate_field("requires"));
343                            }
344                            requires = Some(map.next_value()?);
345                        }
346                        Field::BuildRequires => {
347                            if build_requires.is_some() {
348                                return Err(de::Error::duplicate_field("build_requires"));
349                            }
350                            build_requires = Some(map.next_value()?);
351                        }
352                        Field::PrivateBuildRequires => {
353                            if private_build_requires.is_some() {
354                                return Err(de::Error::duplicate_field("private_build_requires"));
355                            }
356                            private_build_requires = Some(map.next_value()?);
357                        }
358                        Field::Variants => {
359                            if variants.is_some() {
360                                return Err(de::Error::duplicate_field("variants"));
361                            }
362                            variants = Some(map.next_value()?);
363                        }
364                        Field::Tools => {
365                            if tools.is_some() {
366                                return Err(de::Error::duplicate_field("tools"));
367                            }
368                            tools = Some(map.next_value()?);
369                        }
370                        Field::Commands => {
371                            if commands.is_some() {
372                                return Err(de::Error::duplicate_field("commands"));
373                            }
374                            commands = Some(map.next_value()?);
375                        }
376                        Field::BuildCommand => {
377                            if build_command.is_some() {
378                                return Err(de::Error::duplicate_field("build_command"));
379                            }
380                            build_command = Some(map.next_value()?);
381                        }
382                        Field::BuildSystem => {
383                            if build_system.is_some() {
384                                return Err(de::Error::duplicate_field("build_system"));
385                            }
386                            build_system = Some(map.next_value()?);
387                        }
388                        Field::PreCommands => {
389                            if pre_commands.is_some() {
390                                return Err(de::Error::duplicate_field("pre_commands"));
391                            }
392                            pre_commands = Some(map.next_value()?);
393                        }
394                        Field::PostCommands => {
395                            if post_commands.is_some() {
396                                return Err(de::Error::duplicate_field("post_commands"));
397                            }
398                            post_commands = Some(map.next_value()?);
399                        }
400                        Field::PreTestCommands => {
401                            if pre_test_commands.is_some() {
402                                return Err(de::Error::duplicate_field("pre_test_commands"));
403                            }
404                            pre_test_commands = Some(map.next_value()?);
405                        }
406                        Field::PreBuildCommands => {
407                            if pre_build_commands.is_some() {
408                                return Err(de::Error::duplicate_field("pre_build_commands"));
409                            }
410                            pre_build_commands = Some(map.next_value()?);
411                        }
412                        Field::Tests => {
413                            if tests.is_some() {
414                                return Err(de::Error::duplicate_field("tests"));
415                            }
416                            tests = Some(map.next_value()?);
417                        }
418                        Field::RequiresRezVersion => {
419                            if requires_rez_version.is_some() {
420                                return Err(de::Error::duplicate_field("requires_rez_version"));
421                            }
422                            requires_rez_version = Some(map.next_value()?);
423                        }
424                        Field::Uuid => {
425                            if uuid.is_some() {
426                                return Err(de::Error::duplicate_field("uuid"));
427                            }
428                            uuid = Some(map.next_value()?);
429                        }
430                        Field::Help => {
431                            if help.is_some() {
432                                return Err(de::Error::duplicate_field("help"));
433                            }
434                            help = Some(map.next_value()?);
435                        }
436                        Field::Relocatable => {
437                            if relocatable.is_some() {
438                                return Err(de::Error::duplicate_field("relocatable"));
439                            }
440                            relocatable = Some(map.next_value()?);
441                        }
442                        Field::Cachable => {
443                            if cachable.is_some() {
444                                return Err(de::Error::duplicate_field("cachable"));
445                            }
446                            cachable = Some(map.next_value()?);
447                        }
448                        Field::Timestamp => {
449                            if timestamp.is_some() {
450                                return Err(de::Error::duplicate_field("timestamp"));
451                            }
452                            timestamp = Some(map.next_value()?);
453                        }
454                        Field::Revision => {
455                            if revision.is_some() {
456                                return Err(de::Error::duplicate_field("revision"));
457                            }
458                            revision = Some(map.next_value()?);
459                        }
460                        Field::Changelog => {
461                            if changelog.is_some() {
462                                return Err(de::Error::duplicate_field("changelog"));
463                            }
464                            changelog = Some(map.next_value()?);
465                        }
466                        Field::ReleaseMessage => {
467                            if release_message.is_some() {
468                                return Err(de::Error::duplicate_field("release_message"));
469                            }
470                            release_message = Some(map.next_value()?);
471                        }
472                        Field::PreviousVersion => {
473                            if previous_version.is_some() {
474                                return Err(de::Error::duplicate_field("previous_version"));
475                            }
476                            previous_version = Some(map.next_value()?);
477                        }
478                        Field::PreviousRevision => {
479                            if previous_revision.is_some() {
480                                return Err(de::Error::duplicate_field("previous_revision"));
481                            }
482                            previous_revision = Some(map.next_value()?);
483                        }
484                        Field::Vcs => {
485                            if vcs.is_some() {
486                                return Err(de::Error::duplicate_field("vcs"));
487                            }
488                            vcs = Some(map.next_value()?);
489                        }
490                        Field::FormatVersion => {
491                            if format_version.is_some() {
492                                return Err(de::Error::duplicate_field("format_version"));
493                            }
494                            format_version = Some(map.next_value()?);
495                        }
496                        Field::Base => {
497                            if base.is_some() {
498                                return Err(de::Error::duplicate_field("base"));
499                            }
500                            base = Some(map.next_value()?);
501                        }
502                        Field::HasPlugins => {
503                            if has_plugins.is_some() {
504                                return Err(de::Error::duplicate_field("has_plugins"));
505                            }
506                            has_plugins = Some(map.next_value()?);
507                        }
508                        Field::PluginFor => {
509                            if plugin_for.is_some() {
510                                return Err(de::Error::duplicate_field("plugin_for"));
511                            }
512                            plugin_for = Some(map.next_value()?);
513                        }
514                        Field::HashedVariants => {
515                            if hashed_variants.is_some() {
516                                return Err(de::Error::duplicate_field("hashed_variants"));
517                            }
518                            hashed_variants = Some(map.next_value()?);
519                        }
520                        Field::Preprocess => {
521                            if preprocess.is_some() {
522                                return Err(de::Error::duplicate_field("preprocess"));
523                            }
524                            preprocess = Some(map.next_value()?);
525                        }
526                        Field::IsDevPackage => {
527                            if is_dev_package.is_some() {
528                                return Err(de::Error::duplicate_field("is_dev_package"));
529                            }
530                            is_dev_package = Some(map.next_value()?);
531                        }
532                    }
533                }
534
535                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
536                Ok(Package {
537                    name,
538                    version: version.unwrap_or(None),
539                    description: description.unwrap_or(None),
540                    authors: authors.unwrap_or_default(),
541                    requires: requires.unwrap_or_default(),
542                    build_requires: build_requires.unwrap_or_default(),
543                    private_build_requires: private_build_requires.unwrap_or_default(),
544                    variants: variants.unwrap_or_default(),
545                    tools: tools.unwrap_or_default(),
546                    commands: commands.unwrap_or(None),
547                    commands_function: None,
548                    build_command: build_command.unwrap_or(None),
549                    build_system: build_system.unwrap_or(None),
550                    pre_commands: pre_commands.unwrap_or(None),
551                    post_commands: post_commands.unwrap_or(None),
552                    pre_test_commands: pre_test_commands.unwrap_or(None),
553                    pre_build_commands: pre_build_commands.unwrap_or(None),
554                    tests: tests.unwrap_or_default(),
555                    requires_rez_version: requires_rez_version.unwrap_or(None),
556                    uuid: uuid.unwrap_or(None),
557                    config: HashMap::new(),
558                    help: help.unwrap_or(None),
559                    relocatable: relocatable.unwrap_or(None),
560                    cachable: cachable.unwrap_or(None),
561                    timestamp: timestamp.unwrap_or(None),
562                    revision: revision.unwrap_or(None),
563                    changelog: changelog.unwrap_or(None),
564                    release_message: release_message.unwrap_or(None),
565                    previous_version: previous_version.unwrap_or(None),
566                    previous_revision: previous_revision.unwrap_or(None),
567                    vcs: vcs.unwrap_or(None),
568                    format_version: format_version.unwrap_or(None),
569                    base: base.unwrap_or(None),
570                    has_plugins: has_plugins.unwrap_or(None),
571                    plugin_for: plugin_for.unwrap_or_default(),
572                    hashed_variants: hashed_variants.unwrap_or(None),
573                    preprocess: preprocess.unwrap_or(None),
574                    is_dev_package: is_dev_package.unwrap_or(None),
575                    filepath: None,
576                    includes: None,
577                })
578            }
579        }
580
581        const FIELDS: &[&str] = &[
582            "name",
583            "version",
584            "description",
585            "authors",
586            "requires",
587            "build_requires",
588            "private_build_requires",
589            "variants",
590            "tools",
591            "commands",
592            "build_command",
593            "build_system",
594            "pre_commands",
595            "post_commands",
596            "pre_test_commands",
597            "pre_build_commands",
598            "tests",
599            "requires_rez_version",
600            "uuid",
601            "help",
602            "relocatable",
603            "cachable",
604            "timestamp",
605            "revision",
606            "changelog",
607            "release_message",
608            "previous_version",
609            "previous_revision",
610            "vcs",
611            "format_version",
612            "base",
613            "has_plugins",
614            "plugin_for",
615            "hashed_variants",
616            "preprocess",
617            "is_dev_package",
618        ];
619        deserializer.deserialize_struct("Package", FIELDS, PackageVisitor)
620    }
621}