summaryrefslogtreecommitdiff
path: root/systems/sheet/src/index_source.rs
blob: b22f5a618f2093711cf6ba542e5aae8a4c4fa3ad (plain)
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
use serde::{Deserialize, Serialize};

/// IndexSource
/// Points to a unique resource address in Vault
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct IndexSource {
    /// The index ID of the resource
    id: u32,

    /// The index version of the resource
    ver: u16,
}

// Implement construction and querying for IndexSource

impl IndexSource {
    /// Create IndexSource
    pub fn new(id: u32, ver: u16) -> Self {
        IndexSource { id, ver }
    }

    /// Get index ID from IndexSource
    pub fn id(&self) -> u32 {
        self.id
    }

    /// Get index version from IndexSource
    pub fn version(&self) -> u16 {
        self.ver
    }
}

// Implement comparison for IndexSource

impl PartialEq for IndexSource {
    fn eq(&self, other: &Self) -> bool {
        &self.id == &other.id && &self.ver == &other.ver
    }
}

impl Eq for IndexSource {}

// Implement hashing for IndexSource and IndexSourceBuf

impl std::hash::Hash for IndexSource {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.id.hash(state);
        self.ver.hash(state);
    }
}

// Implement construction of IndexSource from strings

impl<'a> TryFrom<&'a str> for IndexSource {
    type Error = &'static str;

    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
        let parts: Vec<&str> = value.split('/').collect();
        if parts.len() != 2 {
            return Err("Invalid format: expected 'id/version'");
        }

        let id_str = parts[0].trim();
        let ver_str = parts[1].trim();

        if id_str.is_empty() || ver_str.is_empty() {
            return Err("ID or version cannot be empty");
        }

        let id = id_str
            .parse::<u32>()
            .map_err(|_| "ID must be a valid u32")?;
        let ver = ver_str
            .parse::<u16>()
            .map_err(|_| "Version must be a valid u16")?;

        // Check for overflow (though parsing already validates range)
        // Additional bounds checks can be added here if needed
        Ok(Self { id, ver })
    }
}

impl TryFrom<String> for IndexSource {
    type Error = &'static str;

    fn try_from(value: String) -> Result<Self, Self::Error> {
        Self::try_from(value.as_str())
    }
}

impl From<IndexSource> for (u32, u16) {
    fn from(src: IndexSource) -> Self {
        (src.id, src.ver)
    }
}

// Implement modifications for IndexSource
impl IndexSource {
    /// Set the index ID of IndexSource
    pub fn set_id(&mut self, index_id: u32) {
        self.id = index_id;
    }

    /// Set the index version of IndexSource
    pub fn set_version(&mut self, version: u16) {
        self.ver = version;
    }
}

// Implement Display for IndexSourceBuf and IndexSource

impl std::fmt::Display for IndexSource {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}/{}", self.id.to_string(), self.ver.to_string())
    }
}