efivar_fix/efi/
variable.rs1use std::fmt;
4use std::str::FromStr;
5
6use crate::Error;
7
8use super::variable_vendor::VariableVendor;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
41pub struct Variable {
42 name: String,
44 vendor: VariableVendor,
46}
47
48impl Variable {
49 pub fn new(name: &str) -> Self {
55 Self {
56 name: name.to_owned(),
57 vendor: VariableVendor::Efi,
58 }
59 }
60
61 pub fn new_with_vendor<V: Into<VariableVendor>>(name: &str, vendor: V) -> Self {
68 Self {
69 name: name.to_owned(),
70 vendor: vendor.into(),
71 }
72 }
73
74 pub fn name(&self) -> &str {
76 &self.name
77 }
78
79 pub fn vendor(&self) -> &VariableVendor {
81 &self.vendor
82 }
83
84 pub fn short_name(&self) -> String {
86 if self.vendor.is_efi() {
87 self.name.clone()
88 } else {
89 self.to_string()
90 }
91 }
92
93 pub fn boot_var_id(&self) -> Option<u16> {
95 if self.name.len() == 8 && &self.name[0..4] == "Boot" {
96 u16::from_str_radix(&self.name[4..8], 16).ok()
97 } else {
98 None
99 }
100 }
101}
102
103impl FromStr for Variable {
104 type Err = Error;
105
106 fn from_str(s: &str) -> Result<Self, Self::Err> {
107 let name_parts = s.splitn(2, '-').collect::<Vec<_>>();
108 if name_parts.len() != 2 {
109 return Err(Error::InvalidVarName { name: s.into() });
110 }
111
112 let vendor = uuid::Uuid::from_str(name_parts[1])
114 .map_err(|error| crate::Error::UuidError { error })?;
115
116 Ok(Self::new_with_vendor(name_parts[0], vendor))
117 }
118}
119
120impl fmt::Display for Variable {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 write!(f, "{}-{}", self.name, self.vendor)
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use uuid::Uuid;
129
130 use super::*;
131
132 #[test]
133 fn parse_valid_var() {
134 let var = Variable::from_str("BootOrder-c9c4c263-cb10-45ea-bdb6-cabdb201d0f5").unwrap();
135 assert_eq!(var.name(), "BootOrder");
136 assert_eq!(
137 var.vendor().to_string(),
138 "c9c4c263-cb10-45ea-bdb6-cabdb201d0f5"
139 );
140 }
141
142 #[test]
143 fn parse_invalid_var() {
144 assert!(Variable::from_str("BootOrder_Invalid").is_err());
145 }
146
147 #[test]
148 fn parse_invalid_var_2() {
149 assert!(Variable::from_str("BootOrder-Invalid").is_err());
150 }
151
152 #[test]
153 fn to_fullname_partial() {
154 assert_eq!(
155 Variable::new("BootOrder").to_string(),
156 "BootOrder-8be4df61-93ca-11d2-aa0d-00e098032b8c"
157 );
158 }
159
160 #[test]
161 fn short_name() {
162 assert_eq!(Variable::new("BootOrder").short_name(), "BootOrder");
163 assert_eq!(
164 Variable::new_with_vendor(
165 "BootOrder",
166 Uuid::from_str("32e3b3d6-a5e6-47a8-980d-d9d37a104c56").unwrap()
167 )
168 .short_name(),
169 "BootOrder-32e3b3d6-a5e6-47a8-980d-d9d37a104c56"
170 );
171 }
172
173 #[test]
174 fn boot_var_id() {
175 assert_eq!(Variable::new("Boot0001").boot_var_id(), Some(0x0001));
176 assert_eq!(Variable::new("Boot1000").boot_var_id(), Some(0x1000));
177
178 assert_eq!(Variable::new("BootOrder").boot_var_id(), None);
179
180 assert_eq!(Variable::new("Boot10000").boot_var_id(), None);
181 assert_eq!(Variable::new("Boot100").boot_var_id(), None);
182 }
183}