Skip to content

Commit 42cad4a

Browse files
committed
uefi: Changing get_envs() to return an Iterator
1 parent f5d84a5 commit 42cad4a

File tree

2 files changed

+65
-41
lines changed

2 files changed

+65
-41
lines changed

uefi-test-runner/src/proto/shell.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@ pub fn test_env(shell: &ScopedProtocol<Shell>) {
1010
let mut test_buf = [0u16; 128];
1111

1212
/* Test retrieving list of environment variable names */
13-
let cur_env_vec = shell.get_envs();
13+
let mut cur_env_vec = shell.get_envs();
1414
assert_eq!(
15-
*cur_env_vec.first().unwrap(),
15+
cur_env_vec.next().unwrap(),
1616
CStr16::from_str_with_buf("path", &mut test_buf).unwrap()
1717
);
1818
assert_eq!(
19-
*cur_env_vec.get(1).unwrap(),
19+
cur_env_vec.next().unwrap(),
2020
CStr16::from_str_with_buf("nonesting", &mut test_buf).unwrap()
2121
);
22-
let default_len = cur_env_vec.len();
22+
let cur_env_vec = shell.get_envs();
23+
let default_len = cur_env_vec.count();
2324

2425
/* Test setting and getting a specific environment variable */
26+
let cur_env_vec = shell.get_envs();
2527
let mut test_env_buf = [0u16; 32];
2628
let test_var = CStr16::from_str_with_buf("test_var", &mut test_env_buf).unwrap();
2729
let mut test_val_buf = [0u16; 32];
@@ -34,10 +36,24 @@ pub fn test_env(shell: &ScopedProtocol<Shell>) {
3436
.expect("Could not get environment variable");
3537
assert_eq!(cur_env_str, test_val);
3638

37-
assert!(!cur_env_vec.contains(&test_var));
39+
let mut found_var = false;
40+
for env_var in cur_env_vec {
41+
if env_var == test_var {
42+
found_var = true;
43+
}
44+
}
45+
assert!(!found_var);
3846
let cur_env_vec = shell.get_envs();
39-
assert!(cur_env_vec.contains(&test_var));
40-
assert_eq!(cur_env_vec.len(), default_len + 1);
47+
let mut found_var = false;
48+
for env_var in cur_env_vec {
49+
if env_var == test_var {
50+
found_var = true;
51+
}
52+
}
53+
assert!(found_var);
54+
55+
let cur_env_vec = shell.get_envs();
56+
assert_eq!(cur_env_vec.count(), default_len + 1);
4157

4258
/* Test deleting environment variable */
4359
let test_val = CStr16::from_str_with_buf("", &mut test_val_buf).unwrap();
@@ -46,8 +62,15 @@ pub fn test_env(shell: &ScopedProtocol<Shell>) {
4662
assert!(shell.get_env(test_var).is_none());
4763

4864
let cur_env_vec = shell.get_envs();
49-
assert!(!cur_env_vec.contains(&test_var));
50-
assert_eq!(cur_env_vec.len(), default_len);
65+
let mut found_var = false;
66+
for env_var in cur_env_vec {
67+
if env_var == test_var {
68+
found_var = true;
69+
}
70+
}
71+
assert!(!found_var);
72+
let cur_env_vec = shell.get_envs();
73+
assert_eq!(cur_env_vec.count(), default_len);
5174
}
5275

5376
/// Test ``get_cur_dir()`` and ``set_cur_dir()``

uefi/src/proto/shell/mod.rs

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
//! EFI Shell Protocol v2.2
44
5-
#![cfg(feature = "alloc")]
6-
7-
use alloc::vec::Vec;
85
use uefi_macros::unsafe_protocol;
96
use uefi_raw::Status;
107

8+
use core::marker::PhantomData;
119
use core::ptr;
1210

1311
use uefi_raw::protocol::shell::ShellProtocol;
@@ -20,6 +18,33 @@ use crate::{CStr16, Char16};
2018
#[unsafe_protocol(ShellProtocol::GUID)]
2119
pub struct Shell(ShellProtocol);
2220

21+
/// Contains environment variables
22+
#[derive(Debug)]
23+
pub struct Vars<'a> {
24+
/// Char16 containing names of environment variables
25+
inner: *const Char16,
26+
/// Placeholder to attach a lifetime to `Vars`
27+
placeholder: PhantomData<&'a CStr16>,
28+
}
29+
30+
impl<'a> Iterator for Vars<'a> {
31+
type Item = &'a CStr16;
32+
fn next(&mut self) -> Option<Self::Item> {
33+
let cur_start = self.inner;
34+
let mut cur_len = 0;
35+
unsafe {
36+
if *(cur_start) == Char16::from_u16_unchecked(0) {
37+
return None;
38+
}
39+
while *(cur_start.add(cur_len)) != Char16::from_u16_unchecked(0) {
40+
cur_len += 1;
41+
}
42+
self.inner = self.inner.add(cur_len + 1);
43+
Some(CStr16::from_ptr(cur_start))
44+
}
45+
}
46+
}
47+
2348
impl Shell {
2449
/// Gets the value of the specified environment variable
2550
///
@@ -50,36 +75,12 @@ impl Shell {
5075
///
5176
/// * `Vec<env_names>` - Vector of environment variable names
5277
#[must_use]
53-
pub fn get_envs(&self) -> Vec<&CStr16> {
54-
let mut env_vec: Vec<&CStr16> = Vec::new();
55-
let cur_env_ptr = unsafe { (self.0.get_env)(ptr::null()) };
56-
57-
let mut cur_start = cur_env_ptr;
58-
let mut cur_len = 0;
59-
60-
let mut i = 0;
61-
let mut null_count = 0;
62-
unsafe {
63-
while null_count <= 1 {
64-
if (*(cur_env_ptr.add(i))) == Char16::from_u16_unchecked(0).into() {
65-
if cur_len > 0 {
66-
env_vec.push(CStr16::from_char16_with_nul(
67-
&(*ptr::slice_from_raw_parts(cur_start.cast(), cur_len + 1)),
68-
).unwrap());
69-
}
70-
cur_len = 0;
71-
null_count += 1;
72-
} else {
73-
if null_count > 0 {
74-
cur_start = cur_env_ptr.add(i);
75-
}
76-
null_count = 0;
77-
cur_len += 1;
78-
}
79-
i += 1;
80-
}
78+
pub fn get_envs(&self) -> Vars {
79+
let env_ptr = unsafe { (self.0.get_env)(ptr::null()) };
80+
Vars {
81+
inner: env_ptr.cast::<Char16>(),
82+
placeholder: PhantomData,
8183
}
82-
env_vec
8384
}
8485

8586
/// Sets the environment variable

0 commit comments

Comments
 (0)