Kaynağa Gözat

Avoid intermediate allocations in parse_cpu_ranges

Tamir Duberstein 5 ay önce
ebeveyn
işleme
0e867572ff
1 değiştirilmiş dosya ile 22 ekleme ve 19 silme
  1. 22 19
      aya/src/util.rs

+ 22 - 19
aya/src/util.rs

@@ -203,30 +203,33 @@ fn read_cpu_ranges(path: &'static str) -> Result<Vec<u32>, (&'static str, io::Er
     (|| {
         let data = fs::read_to_string(path)?;
         parse_cpu_ranges(data.trim())
-            .map_err(|range| io::Error::new(io::ErrorKind::InvalidData, range))
     })()
     .map_err(|error| (path, error))
 }
 
-fn parse_cpu_ranges(data: &str) -> Result<Vec<u32>, &str> {
-    let mut cpus = Vec::new();
-    for range in data.split(',') {
-        cpus.extend({
-            match range
-                .splitn(2, '-')
-                .map(u32::from_str)
-                .collect::<Result<Vec<_>, _>>()
-                .map_err(|ParseIntError { .. }| range)?
-                .as_slice()
-            {
-                &[] | &[_, _, _, ..] => return Err(range),
-                &[start] => start..=start,
-                &[start, end] => start..=end,
-            }
+fn parse_cpu_ranges(data: &str) -> Result<Vec<u32>, io::Error> {
+    data.split(',')
+        .map(|range| {
+            let mut iter = range
+                .split('-')
+                .map(|s| s.parse::<u32>().map_err(|ParseIntError { .. }| range));
+            let start = iter.next().unwrap()?; // str::split always returns at least one element.
+            let end = match iter.next() {
+                None => start,
+                Some(end) => {
+                    if iter.next().is_some() {
+                        return Err(range);
+                    }
+                    end?
+                }
+            };
+            Ok(start..=end)
+        })
+        .try_fold(Vec::new(), |mut cpus, range| {
+            let range = range.map_err(|range| io::Error::new(io::ErrorKind::InvalidData, range))?;
+            cpus.extend(range);
+            Ok(cpus)
         })
-    }
-
-    Ok(cpus)
 }
 
 /// Loads kernel symbols from `/proc/kallsyms`.