iota_enum_compat_util/
lib.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::{io::Write, path::PathBuf};
6
7pub trait EnumOrderMap {
8    fn order_to_variant_map() -> std::collections::BTreeMap<u64, String>;
9}
10
11pub fn check_enum_compat_order<T: EnumOrderMap>(snapshot_file: PathBuf) {
12    let new_map = T::order_to_variant_map();
13
14    if let Err(err) = std::fs::read_to_string(snapshot_file.clone()) {
15        if err.kind() == std::io::ErrorKind::NotFound {
16            // Create the file if not exists
17            let mut file = std::fs::File::create(snapshot_file).unwrap();
18            let content: String = serde_yaml::to_string(&new_map).unwrap();
19
20            write!(file, "{}", content).unwrap();
21            return;
22        }
23        panic!("Error reading file: {:?}: err {:?}", snapshot_file, err);
24    }
25
26    let existing_map: std::collections::BTreeMap<u64, String> =
27        serde_yaml::from_str(&std::fs::read_to_string(snapshot_file.clone()).unwrap()).unwrap();
28
29    // Check that the new map includes the existing map in order
30    for (pos, val) in existing_map {
31        match new_map.get(&pos) {
32            None => {
33                panic!(
34                    "Enum variant {} has been removed. Not allowed: enum must be backward compatible.",
35                    val
36                );
37            }
38            Some(new_val) if new_val == &val => continue,
39            Some(new_val) => {
40                panic!(
41                    "Enum variant {val} has been swapped with {new_val} at position {pos}. Not allowed: enum must be backward compatible."
42                );
43            }
44        }
45    }
46
47    // Update the file
48    let mut file = std::fs::File::create(snapshot_file).unwrap();
49    let content: String = serde_yaml::to_string(&new_map).unwrap();
50
51    write!(file, "{}", content).unwrap();
52}