alpm_buildinfo/
schema.rs

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
use std::{
    collections::HashMap,
    fmt::{Display, Formatter},
    str::FromStr,
};

use alpm_parsers::custom_ini::parser::Item;
use alpm_types::SchemaVersion;

use crate::Error;

/// An enum describing all valid BUILDINFO schemas
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Schema {
    V1(SchemaVersion),
    V2(SchemaVersion),
}

impl Schema {
    /// Returns the schema version
    pub fn inner(&self) -> &SchemaVersion {
        match self {
            Schema::V1(v) => v,
            Schema::V2(v) => v,
        }
    }

    /// Determines the schema version from the contents of a BUILDINFO file
    ///
    /// # Errors
    ///
    /// Returns an error if the format field is missing
    pub fn from_contents(contents: &str) -> Result<Schema, Error> {
        // Deserialize the file into a simple map, so we can take a look at the `format` string
        // that determines the buildinfo version.
        let raw_buildinfo: HashMap<String, Item> = alpm_parsers::custom_ini::from_str(contents)?;
        if let Some(Item::Value(version)) = raw_buildinfo.get("format") {
            Self::from_str(version)
        } else {
            Err(Error::MissingFormatField)
        }
    }
}

impl Default for Schema {
    /// Returns the default schema version which is V1
    ///
    /// # Panics
    ///
    /// Panics if the default schema version cannot be created.
    /// This should not happen normally.
    fn default() -> Self {
        match SchemaVersion::from_str("1") {
            Ok(v) => Schema::V1(v),
            Err(e) => panic!("failed to create default schema: {e}"),
        }
    }
}

impl FromStr for Schema {
    type Err = Error;

    /// Uses the `SchemaVersion` to determine the schema
    fn from_str(s: &str) -> Result<Schema, Self::Err> {
        match SchemaVersion::from_str(s) {
            Ok(version) => Self::try_from(version),
            Err(_) => Err(Error::UnsupportedSchemaVersion(s.to_string())),
        }
    }
}

impl TryFrom<SchemaVersion> for Schema {
    type Error = Error;

    /// Converts the major version of the `SchemaVersion` to a `Schema`
    fn try_from(value: SchemaVersion) -> Result<Self, Self::Error> {
        match value.inner().major {
            1 => Ok(Schema::V1(value)),
            2 => Ok(Schema::V2(value)),
            _ => Err(Error::UnsupportedSchemaVersion(value.to_string())),
        }
    }
}

impl Display for Schema {
    /// Converts the `Schema` to a `String`
    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(
            fmt,
            "{}",
            match self {
                Schema::V1(_) => "1",
                Schema::V2(_) => "2",
            }
        )
    }
}