1use std::convert::TryInto;
9use std::fs::File;
10use std::io::{self, BufRead, BufReader, Error, ErrorKind};
11use std::path::Path;
12
13use rustc_serialize::hex::{FromHex, ToHex};
14use serde::{Deserialize, Serialize};
15
16use crate::{CpuSvn, EncPpid, PceId, PceIsvsvn, QeId};
17
18#[derive(Clone, Serialize, Deserialize, Debug, Default, Hash, PartialEq, Eq)]
19pub struct PckID {
20 pub enc_ppid: EncPpid,
21 pub pce_id: PceId,
22 pub cpu_svn: CpuSvn,
23 pub pce_isvsvn: PceIsvsvn,
24 pub qe_id: QeId,
25}
26
27impl ToString for PckID {
28 fn to_string(&self) -> String {
29 let enc_ppid = self.enc_ppid.as_slice();
30 let mut string = String::from("==[ PckId ]==\n");
31 string += format!(" Info:\n").as_str();
32 string += format!(
33 " Encr. PPID: {}..{}\n",
34 enc_ppid[..12].to_hex(),
35 enc_ppid[enc_ppid.len() - 3..].to_hex()
36 )
37 .as_str();
38 string += format!(" pce_id: {}\n", self.pce_id.to_le_bytes().to_hex()).as_str();
39 string += format!(" cpu svn: {}\n", self.cpu_svn.as_slice().to_hex()).as_str();
40 string += format!(" pce isvsvn: {}\n", self.pce_isvsvn.to_le_bytes().to_hex()).as_str();
41 string += format!(" qe_id: {}\n", self.qe_id.as_slice().to_hex()).as_str();
42 return string;
43 }
44}
45
46fn parse_hex_array<'a>(chunk: &'a str, expected_bytes: usize) -> io::Result<Vec<u8>> {
47 if chunk.len() != expected_bytes * 2 {
48 return Err(Error::new(ErrorKind::InvalidData, "Parse error, incorrect field length"));
49 }
50
51 chunk
52 .from_hex()
53 .map_err(|_| Error::new(ErrorKind::InvalidData, "Cannot parse as hexadecimal"))
54}
55
56struct ResultAdapter<I: Iterator, E, F: Fn() -> E>(I, F);
58
59impl<I: Iterator, E, F: Fn() -> E> ResultAdapter<I, E, F> {
60 fn next(&mut self) -> std::result::Result<I::Item, E> {
61 self.0.next().ok_or_else(|| self.1())
62 }
63}
64
65impl PckID {
66 pub fn parse_line(line: &str) -> io::Result<Self> {
67 let mut fields = ResultAdapter(line.split(","), || Error::new(ErrorKind::InvalidData, "Too few fields"));
68
69 let enc_ppid: EncPpid = parse_hex_array(fields.next()?, 384)?;
70 let pce_id: PceId = u16::from_str_radix(fields.next()?, 16)
71 .map_err(|_| Error::new(ErrorKind::InvalidData, "Cannot parse as hexadecimal"))?;
72 let cpu_svn: CpuSvn = parse_hex_array(fields.next()?, 16)?
73 .try_into()
74 .map_err(|_e| Error::new(ErrorKind::InvalidData, "Incorrect length cpu_svn"))?;
75 let pce_isvsvn: PceIsvsvn = u16::from_str_radix(fields.next()?, 16)
76 .map_err(|_| Error::new(ErrorKind::InvalidData, "Cannot parse as hexadecimal"))?;
77 let qe_id: QeId = parse_hex_array(fields.next()?, 16)?
78 .try_into()
79 .map_err(|_e| Error::new(ErrorKind::InvalidData, "Incorrect length qe_id"))?;
80
81 Ok(PckID {
82 enc_ppid,
83 pce_id,
84 cpu_svn,
85 pce_isvsvn,
86 qe_id,
87 })
88 }
89
90 pub fn parse_file(file: &Path) -> io::Result<Vec<Self>> {
91 let file = File::open(file)?;
92 let mut pck_ids = Vec::new();
93
94 for line_res in BufReader::new(file).lines() {
95 let line = line_res?;
96 let trimmed = line.trim();
97 if trimmed.is_empty() {
98 continue;
99 }
100 let pck_id = PckID::parse_line(trimmed)?;
101 pck_ids.push(pck_id);
102 }
103
104 Ok(pck_ids)
105 }
106}